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 +
    +
  1. 0
  2. +
+ ``` + +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\n

b

}, @rendered + end + + test 'contents' do + g = Gollum::Gitcode.new 'github/gollum/master/test/file_view/1_file.txt' + + assert_equal g.contents, %{
    +
  1. 0
  2. +
} + 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{
<p>a  b</p>\n
}, 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

<p>a\n!base</p>\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

<p>a\n!rel</p>\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