diff --git a/.gitignore b/.gitignore
index 033ec934..62e405fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ pkg
.bundle
Gemfile.lock
*.gem
+*.swp
diff --git a/README.md b/README.md
index 0bbb649c..063c853a 100644
--- a/README.md
+++ b/README.md
@@ -335,6 +335,27 @@ then that whitespace will be ignored (this makes the blocks easier to read in pl
The block must end with three backticks indented at the same level than the opening
backticks.
+### GITHUB SYNTAX HIGHLIGHTING
+
+As an extra feature, you can syntax highlight a file from your repository, allowing
+you keep some of your sample code in the main repository. The code-snippet is
+updated when the wiki is rebuilt. You include github code like this:
+
+ ```html:github/gollum/master/test/file_view/1_file.txt```
+
+This will make the builder look at the **github user**, in the **gollum project**,
+in the **master branch**, at path **test/file_view/1_file.txt**. It will be
+rewritten to:
+
+ ```html
+
+ - 0
+
+ ```
+
+Which will be parsed as HTML code during the Pygments run, and thereby coloured
+appropriately.
+
## MATHEMATICAL EQUATIONS
diff --git a/lib/gollum/frontend/app.rb b/lib/gollum/frontend/app.rb
index fee66f0f..31a22360 100644
--- a/lib/gollum/frontend/app.rb
+++ b/lib/gollum/frontend/app.rb
@@ -89,12 +89,6 @@ module Precious
redirect File.join(settings.wiki_options[:base_path].to_s, 'Home')
end
- # Removes all slashes from the start of string.
- def clean_url url
- return url if url.nil?
- url.gsub('%2F','/').gsub(/^\/+/,'')
- end
-
# path is set to name if path is nil.
# if path is 'a/b' and a and b are dirs, then
# path must have a trailing slash 'a/b/' or
diff --git a/lib/gollum/frontend/helpers.rb b/lib/gollum/frontend/helpers.rb
index 845a0c7a..b8ec4afb 100644
--- a/lib/gollum/frontend/helpers.rb
+++ b/lib/gollum/frontend/helpers.rb
@@ -17,5 +17,11 @@ module Precious
def sanitize_empty_params(param)
[nil,''].include?(param) ? nil : CGI.unescape(param)
end
+
+ # Remove all slashes from the start of string.
+ def clean_url url
+ return url if url.nil?
+ url.gsub('%2F','/').gsub(/^\/+/,'')
+ end
end
end
diff --git a/lib/gollum/gitcode.rb b/lib/gollum/gitcode.rb
new file mode 100644
index 00000000..a4a8c064
--- /dev/null
+++ b/lib/gollum/gitcode.rb
@@ -0,0 +1,47 @@
+require 'net/http'
+require 'net/https' # ruby 1.8.7 fix, remove at upgrade
+require 'uri'
+require 'open-uri'
+
+module Gollum
+ class Gitcode
+ def initialize path
+ raise(ArgumentError, 'path is nil or empty') if path.nil? or path.empty?
+
+ @uri = URI::HTTP.build({
+ :path => self.unchomp(path),
+ :host => 'raw.github.com',
+ :scheme => 'https',
+ :port => 443 })
+ end
+
+ def contents
+ @contents ||= self.req @uri
+ end
+
+ def unchomp p
+ return p if p.nil?
+ p[0] == '/' ? p : ('/' + p)
+ end
+
+ def req uri, cut = 1
+ return "Too many redirects or retries" if cut >= 10
+ http = Net::HTTP.new uri.host, uri.port
+ http.use_ssl = true
+ resp = http.get uri.path, {
+ 'Accept' => 'text/plain',
+ 'Cache-Control' => 'no-cache',
+ 'Connection' => 'keep-alive',
+ 'Host' => uri.host,
+ 'User-Agent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0'
+ }
+ code = resp.code.to_i
+ return resp.body if code == 200
+ return "Not Found" if code == 404
+ return "Unhandled Response Code #{code}" unless code == 304 or not resp.header['location'].nil?
+ loc = URI.parse resp.header['location']
+ uri2 = loc.relative?() ? (uri + loc) : loc # overloads (+)
+ return req uri2, (cut + 1)
+ end
+ end
+end
diff --git a/lib/gollum/markup.rb b/lib/gollum/markup.rb
index 63c25c45..d1fa9fa0 100644
--- a/lib/gollum/markup.rb
+++ b/lib/gollum/markup.rb
@@ -3,12 +3,17 @@ require 'cgi'
require 'pygments'
require 'base64'
+require File.expand_path '../frontend/helpers', __FILE__
+require File.expand_path '../gitcode', __FILE__
+
# initialize Pygments
Pygments.start
module Gollum
class Markup
+ include Precious::Helpers
+
attr_accessor :toc
attr_reader :metadata
@@ -50,6 +55,7 @@ module Gollum
data = @data.dup
data = extract_metadata(data)
+ data = extract_gitcode(data)
data = extract_code(data)
data = extract_tex(data)
data = extract_wsd(data)
@@ -459,6 +465,34 @@ module Gollum
end
end
+ #########################################################################
+ #
+ # Gitcode - fetch code from github search path and replace the contents
+ # to a code-block that gets run the next parse.
+ #
+ #########################################################################
+
+ def extract_gitcode data
+ data.gsub /^[ \t]*``` ?([^:\n\r]+):([^`\n\r]+)```/ do
+ contents = ''
+ # Use empty string if $2 is nil.
+ uri = $2 || ''
+ # Detect local file.
+ if uri[0..6] != 'github/'
+ if uri[0..0] != '/' # relative file
+ contents = @wiki.page(uri).formatted_data
+ else # use full path
+ contents = @wiki.paged( extract_name( clean_url( uri ) ),
+ '/' + clean_url( extract_path( uri ) ) ).formatted_data
+ end
+ else
+ contents = Gollum::Gitcode.new(uri).contents
+ end
+
+ "```#{$1}\n#{contents}\n```\n"
+ end
+ end
+
#########################################################################
#
# Code
diff --git a/templates/helper_wiki.rb b/templates/helper_wiki.rb
new file mode 100644
index 00000000..16c17cba
--- /dev/null
+++ b/templates/helper_wiki.rb
@@ -0,0 +1,9 @@
+class WikiFactory
+ def self.create p
+ path = testpath "examples/test.git"
+ Grit::Repo.init_bare(@path)
+ Gollum::Wiki.default_options = {:universal_toc => false}
+ cleanup = lambda { FileUtils.rm_r File.join(File.dirname(__FILE__), *%w[examples test.git]) }
+ Gollum::Wiki.new(@path), @path, cleanup
+ end
+end
diff --git a/test/test_gitcode.rb b/test/test_gitcode.rb
new file mode 100644
index 00000000..0a7890e9
--- /dev/null
+++ b/test/test_gitcode.rb
@@ -0,0 +1,42 @@
+# ~*~ encoding: utf-8 ~*~
+require File.expand_path( '../helper', __FILE__ )
+require File.expand_path( '../wiki_factory', __FILE__ )
+
+context "gitcode" do
+
+ def page_with_content c
+ index = @wiki.repo.index
+ index.add 'Sample-Html.md', c
+ index.commit 'adding file html sample'
+
+ page = @wiki.page 'Sample Html'
+ page
+ end
+
+ setup do
+ # context
+ @wiki, @path, @cleanup = WikiFactory.create 'examples/test.git'
+
+ # given
+ p = page_with_content "a\n\n```html:github/gollum/master/test/file_view/1_file.txt```\n\nb"
+
+ # when rendering the page
+ @rendered = Gollum::Markup.new(p).render
+ end
+
+ test 'that the rendered output is correctly fetched and rendered as html code' do
+ assert_equal %Q{a
\n\n<ol class=\"tree\">\n <li class=\"file\"><a href=\"0\">0</a></li>\n</ol>\n
\n\nb
}, @rendered
+ end
+
+ test 'contents' do
+ g = Gollum::Gitcode.new 'github/gollum/master/test/file_view/1_file.txt'
+
+ assert_equal g.contents, %{
+ - 0
+
}
+ end
+
+ teardown do
+ @cleanup.call
+ end
+end
diff --git a/test/test_markup.rb b/test/test_markup.rb
index 82906172..3424e92a 100644
--- a/test/test_markup.rb
+++ b/test/test_markup.rb
@@ -1,17 +1,14 @@
# ~*~ encoding: utf-8 ~*~
-require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
+require File.expand_path( "../helper", __FILE__ )
+require File.expand_path( "../wiki_factory", __FILE__ )
context "Markup" do
setup do
- @path = testpath("examples/test.git")
- FileUtils.rm_rf(@path)
- Grit::Repo.init_bare(@path)
- Gollum::Wiki.default_options = {:universal_toc => false}
- @wiki = Gollum::Wiki.new(@path)
+ @wiki, @path, @teardown = WikiFactory.create 'examples/test.git'
end
teardown do
- FileUtils.rm_r(File.join(File.dirname(__FILE__), *%w[examples test.git]))
+ @teardown.call
end
test "formats page from Wiki#pages" do
@@ -508,6 +505,35 @@ np.array([[2,2],[1,3]],np.float)
assert_match /\(\[\[/, rendered, "#{markup_class} parses out wiki links\n#{rendered}"
end
+ test "embed code is escaped" do
+ @wiki.write_page("script", :markdown, "a b", commit_details)
+ @wiki.write_page("page", :markdown, "```html:script```", commit_details)
+
+ output_script = @wiki.page("script").formatted_data
+ output_page = @wiki.page("page").formatted_data
+
+ assert_equal %Q{a b
}, output_script
+ assert_equal %Q{}, output_page
+ end
+
+ test "embed code page absolute link" do
+ @wiki.write_page("base", :markdown, "a\n!base\b", commit_details)
+ @wiki.write_page("a", :markdown, "a\n```html:/base```\b", commit_details)
+
+ page = @wiki.page("a")
+ output = page.formatted_data
+ assert_equal %Q{a\n
\n}, output
+ end
+
+ test "embed code page relative link" do
+ @wiki.write_page("base", :markdown, "a\n!rel\b", commit_details)
+ @wiki.write_page("a", :markdown, "a\n```html:base```\b", commit_details)
+
+ page = @wiki.page("a")
+ output = page.formatted_data
+ assert_equal %Q{a\n
\n}, output
+ end
+
#########################################################################
#
# Web Sequence Diagrams
diff --git a/test/wiki_factory.rb b/test/wiki_factory.rb
new file mode 100644
index 00000000..e6536f28
--- /dev/null
+++ b/test/wiki_factory.rb
@@ -0,0 +1,10 @@
+class WikiFactory
+ def self.create p
+ path = testpath "examples/test.git"
+ Grit::Repo.init_bare(path)
+ Gollum::Wiki.default_options = {:universal_toc => false}
+ cleanup = Proc.new { FileUtils.rm_r File.join(File.dirname(__FILE__), *%w[examples test.git]) }
+ wiki = Gollum::Wiki.new(path)
+ return wiki, path, cleanup
+ end
+end