# A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers. # by: Brandon Tilly # Source URL: https://gist.github.com/1027674 # Post http://brandontilley.com/2011/01/31/gist-tag-for-jekyll.html # # Example usage: {% gist 1027674 gist_tag.rb %} //embeds a gist for this plugin require 'cgi' require 'digest/md5' require 'net/https' require 'uri' module Jekyll class GistTag < Liquid::Tag def initialize(tag_name, text, token) super @text = text @cache_disabled = false @cache_folder = File.expand_path "../.gist-cache", File.dirname(__FILE__) FileUtils.mkdir_p @cache_folder end def render(context) if parts = @text.match(/([a-zA-Z\d]*) (.*)/) gist, file = parts[1].strip, parts[2].strip script_url = script_url_for gist, file code = get_cached_gist(gist, file) || get_gist_from_web(gist, file) html_output_for script_url, code else "" end end def html_output_for(script_url, code) code = CGI.escapeHTML code <<-HTML
HTML end def script_url_for(gist_id, filename) url = "https://gist.github.com/#{gist_id}.js" url = "#{url}?file=#{filename}" unless filename.nil? or filename.empty? url end def get_gist_url_for(gist, file) "https://gist.github.com/raw/#{gist}/#{file}" end def cache(gist, file, data) cache_file = get_cache_file_for gist, file File.open(cache_file, "w") do |io| io.write data end end def get_cached_gist(gist, file) return nil if @cache_disabled cache_file = get_cache_file_for gist, file File.read cache_file if File.exist? cache_file end def get_cache_file_for(gist, file) bad_chars = /[^a-zA-Z0-9\-_.]/ gist = gist.gsub bad_chars, '' file = file.gsub bad_chars, '' md5 = Digest::MD5.hexdigest "#{gist}-#{file}" File.join @cache_folder, "#{gist}-#{file}-#{md5}.cache" end def get_gist_from_web(gist, file) gist_url = get_gist_url_for(gist, file) data = get_web_content(gist_url) if data.code.to_i == 302 data = handle_gist_redirecting(data) end if data.code.to_i != 200 raise RuntimeError, "Gist replied with #{data.code} for #{gist_url}" end cache(gist, file, data.body) unless @cache_disabled data.body end def handle_gist_redirecting(data) redirected_url = data.header['Location'] get_web_content(redirected_url) end def get_web_content(url) raw_uri = URI.parse url proxy = ENV['http_proxy'] if proxy proxy_uri = URI.parse(proxy) https = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new raw_uri.host, raw_uri.port else https = Net::HTTP.new raw_uri.host, raw_uri.port end https.use_ssl = true https.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new raw_uri.request_uri data = https.request request end end class GistTagNoCache < GistTag def initialize(tag_name, text, token) super @cache_disabled = true end end end Liquid::Template.register_tag('gist', Jekyll::GistTag) Liquid::Template.register_tag('gistnocache', Jekyll::GistTagNoCache)