forked from imathis/octopress
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgist_tag.rb
130 lines (112 loc) · 3.89 KB
/
gist_tag.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# 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
else
gist, file = @text.strip, ""
end
if gist.empty?
""
else
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
end
end
def html_output_for(script_url, code)
code = CGI.escapeHTML code
<<-HTML
<div><script src='#{script_url}'></script>
<noscript><pre><code>#{code}</code></pre></noscript></div>
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.githubusercontent.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)
locations = Array.new
while (data.code.to_i == 301 || data.code.to_i == 302)
data = handle_gist_redirecting(data)
break if locations.include? data.header['Location']
locations << data.header['Location']
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']
if redirected_url.nil? || redirected_url.empty?
raise ArgumentError, "GitHub replied with a 302 but didn't provide a location in the response headers."
end
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)