| require 'open-uri' |
| require 'uri' |
| require 'cgi' |
| require 'digest' |
| |
| module Jekyll |
| |
| class Snippet < Liquid::Tag |
| |
| def initialize(tag_name, markup, tokens) |
| parse_params(markup) |
| |
| unless @url.start_with?('http') |
| @url = absolute_url(@url) |
| end |
| |
| if @url =~ URI::regexp |
| @content = fetchContent(@url) |
| else |
| STDERR.puts "Invalid URL passed to Snippet: " + @url |
| end |
| |
| super |
| end |
| |
| def render(context) |
| if @content |
| snippet = @content |
| if @id |
| snippet = snippet[/#{Regexp.escape("START SNIPPET: " + @id)}[^\n]*\n(.*?)\n[^\n]*#{Regexp.escape("END SNIPPET: " + @id)}/m, 1] |
| unless snippet |
| snippet = "START SNIPPET: " + @id + " not found in " + @url |
| STDERR.puts snippet |
| end |
| end |
| if @javadoc |
| unless @javadoc.to_s.strip.casecmp("FALSE") == 0 |
| snippet = snippet.gsub /^\s*\*/, '' |
| snippet = CGI.unescapeHTML(snippet) |
| end |
| end |
| if @lang |
| snippet = "\r\n" + "```" + @lang + "\r\n" + snippet + "\r\n" + "```" + "\r\n" |
| else |
| snippet = "<p>" + escapeJekyll(snippet) + "</p>" |
| end |
| |
| return snippet |
| else |
| raise 'Something went wrong in Snippet' |
| end |
| end |
| |
| def fetchContent(url) |
| cacheKey = Digest::SHA1.hexdigest(url.strip) |
| cacheFile = "target/snippet_" + cacheKey + ".cache" |
| unless File.exist?(cacheFile) |
| File.open(cacheFile, 'w') { |file| file.write(Net::HTTP.get(URI.parse(URI.encode(url.strip)))) } |
| end |
| file = File.open(cacheFile, "rb") |
| content = file.read |
| file.close |
| return content |
| end |
| |
| def parse_params(markup) |
| markup_split = markup.split("|").reject { |s| s.empty? }.each { |param| parse_param(param) } |
| end |
| |
| def parse_param(param) |
| param_split = param.split("=", 2).reject { |s| s.empty? } |
| if param_split[0].casecmp("id")==0 |
| @id = param_split[1].strip |
| else |
| if param_split[0].casecmp("lang")==0 |
| @lang = param_split[1].strip |
| else |
| if param_split[0].casecmp("javadoc")==0 |
| @javadoc = param_split[1].strip |
| else |
| if param_split[0].casecmp("url")==0 |
| @url = param_split[1].strip |
| else |
| @url = param.strip |
| end |
| end |
| end |
| end |
| end |
| |
| def absolute_url(url) |
| p = 'struts' |
| f = '' |
| tail = '' |
| slashIndex = url.index('/') |
| unless slashIndex |
| url = url.strip.gsub!('.','/') |
| tail = '.java' |
| if url.start_with?('org/apache/struts2/dojo/') |
| p = 'struts-archive' |
| f = 'plugins/struts2-dojo-plugin/src/main/java/' |
| else |
| f = 'core/src/main/java/' |
| end |
| else |
| baseUrl = url[0..slashIndex] |
| url = url[slashIndex+1..-1] |
| if baseUrl.casecmp("struts2-tags/") == 0 |
| f = 'core/src/site/resources/tags/' |
| else |
| if url.start_with?('plugins/dojo/') |
| p = 'struts-archive' |
| f = 'plugins/struts2-dojo-plugin/' |
| url = url[13..-1] |
| end |
| end |
| end |
| url = 'https://gitbox.apache.org/repos/asf?p=' + p + '.git;a=blob_plain;f=' + f + url + tail + ';hb=HEAD' |
| end |
| |
| def escape_brackets(content) |
| content.gsub(/{/,'{').gsub(/}/, '}') |
| end |
| |
| def unescape_brackets(content) |
| content.gsub!(/&(amp;)?#x7b;/, '{') |
| content.gsub!(/&(amp;)?#x7d;/, '}') |
| content |
| end |
| |
| def escapeJekyll(content) |
| |
| # Escape markdown style code blocks |
| |
| # Escape four tab or space indented code blocks |
| content = content.gsub /^((\t| {4})[^\n].+?)\n($|\S)/m do |
| "#{escape_brackets $1}\n#{$3}" |
| end |
| |
| # Escape in-line code backticks |
| content = content.gsub /(`[^`\n]+?`)/ do |
| "#{escape_brackets $1}" |
| end |
| |
| # Escape in-line code double backticks |
| content = content.gsub /(``[^\n]+?``)/ do |
| escape_brackets $1 |
| end |
| |
| # Escape highlight and codeblock tag contents |
| content = content.gsub /^({%\s*(codeblock|highlight).+?%})(.+?){%\s*end(codeblock|highlight)\s*%}/m do |
| "#{$1}{% raw %}#{unescape_brackets $3}{% endraw %}{% end#{$4} %}" |
| end |
| |
| # Escape codefenced codeblocks |
| content = content.gsub /^(`{3}.+?`{3})/m do |
| |
| # Replace any raw/endraw tags inside of codefence block |
| # as some of the regex above may have escaped contents |
| # of the codefence block |
| # |
| code = unescape_brackets($1).gsub(/{% (end)?raw %}/, '') |
| |
| # Wrap codefence content in raw tags |
| "{% raw %}\n#{code}\n{% endraw %}" |
| end |
| |
| content |
| end |
| |
| end |
| end |
| |
| Liquid::Template.register_tag('snippet', Jekyll::Snippet) |