Create a gist now

Instantly share code, notes, and snippets.

A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers.
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(/([\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
"<script src='#{script_url}'></script><div><noscript><pre><code>#{code}</code></pre></noscript></div>"
end
def script_url_for(gist_id, filename)
"https://gist.github.com/#{gist_id}.js?file=#{filename}"
end
def get_gist_url_for(gist, file)
"https://raw.github.com/gist/#{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
raw_uri = URI.parse gist_url
https = Net::HTTP.new raw_uri.host, raw_uri.port
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new raw_uri.request_uri
data = https.request request
data = data.body
cache gist, file, data unless @cache_disabled
data
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)
@hickford
hickford commented May 7, 2012

Hi. Please could you share an example of how to use this plugin?

@imathis
Owner
imathis commented May 7, 2012

{% gist 1027674 %} will embed this gist.

@hickford
hickford commented May 7, 2012

Thanks. Using your code and example, I get the following error when I run jekyll

Configuration from C:/Users/Matt/Documents/matt-hickford.github.com/_config.yml
Building site: C:/Users/Matt/Documents/matt-hickford.github.com -> C:/Users/Matt/Documents/matt-hickford.github.com/_site

 ___________________________________________________________________________
| Maruku tells you:
+---------------------------------------------------------------------------
| Could you please format this better?
| I see that "<div><noscript><pre><code>require 'cgi'" is left after the raw HTML.
| At line 4
|       text     |Hello|
|      empty     ||
|   raw_html     |<script src='https://gist.github.com/1027674.js?file='></script><div><noscript><pre><code>require 'cgi'|
|       text --> |require 'digest/md5'|
|       text     |require 'net/https'|
|       text     |require 'uri'|
|      empty     ||
+---------------------------------------------------------------------------

If I run jekyll --server I can browse to the post. All my content from below the gist tag is lost, but the first half and the gist bit appears okay.

@imathis
Owner
imathis commented May 7, 2012

If you use RDiscount you shouldn't have that problem. Maruku seems to have a hard time with HTML mixed into markdown.

@esparkman

Anyway to port this over to a non jekyll based platform?

@imathis
Owner
imathis commented May 9, 2012

@esparkman I suppose that depends on the platform but theoretically yes, you should be able to build this feature for other platforms.

@johnnyfreeman

You can also embed private gists if you change line 17 to:

if parts = @text.match(/([\w]*) (.*)/)

This is because private Gist ID's not only contain digits but also alpha characters as well.

You could also do a pull against my fork (git://gist.github.com/3706958.git) if you have a local clone. :)

@jehoshua02

While playing around with embedding gists, I realized gists could be obtained in json format. The url is almost identical to the javascript url:

https://gist.github.com/jehoshua02/4681039.json?file=.gitignore

The html content is right there in the "div" property of the json string.

I've also been having problems with the gist tag in octopress. Even though I specify a file, all files in the gist are output. Very rarely do I want to embed every file from a gist, but would rather embed one file, explain it, embed another file, etc.

@ttscoff
ttscoff commented Apr 7, 2013
def get_gist_url_for(gist, filename)
  file = filename == '' ? '' : "/#{filename}"
  "https://raw.github.com/gist/#{gist}#{file}"
end

Without adding that second line, gist tags created with just an id and no filename don't work.

@michaelcox

Works great, thanks!

@porcoesphino

The gist URL has changed as noted here (or with the urls generated for a gist):

http://stackoverflow.com/a/18835385/588702

Line 33 and line 37 need altering to include a username.

@rriemann

Same problem here. Any ideas on how to fix this without changing all the posts again?

@creativepsyco

Here's the fix: https://gist.github.com/creativepsyco/6821946 Changed the plugin to read the config and adjust the url accordingly . This means you can embed your own gists only

you would need to add your github username to Jekyll Config file though.

In _config.yml set github_user to your github username

@gr4y
gr4y commented Dec 22, 2013

@imathis Is it possible for you to fork the jekyll-project and replace the built in gist tag with your version? I think that would be a great improvement for jekyll!

@mzlogin
mzlogin commented May 16, 2014

jekyll now has gist build-in support, but the usage is :

# Gist Liquid Tag
#
# Example:
#    {% gist username/1234567 %}
#    {% gist username/1234567 file.rb %}

see https://github.com/jekyll/jekyll/blob/master/lib/jekyll/tags/gist.rb

but……It's realy ugly!

@Sankame
Sankame commented May 18, 2014

@johnnyfreeman

Thanks for your comment.
I once deleted my gist and created a public gist to get a numeric ID.
But I couldn't get it.

So I modified the following code.

/usr/local/rvm/gems/ruby-2.1.1/gems/jekyll-1.0.2/lib/jekyll/tags/gist.rb
# diff  gist.rb.org  gist.rb
10c10
< if tag_contents = @markup.strip.match(/\A(\d+) ?(\S*)\Z/)

---
> if tag_contents = @markup.strip.match(/\A([0-9a-fA-F]+) ?(\S*)\Z/)

The following is my setup.

ruby 2.1.1p76
jekyll 1.0.2
@fusion809

Can you use this tag to embed files in GitHub repos (not gist files) into posts? If so, how would ya?

@johnmccabe

I've updated this to work as originally described, no need to include a github username, and works with current hex gist ids.

https://gist.github.com/johnmccabe/a5fd4756cea0cfd2afc5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment