Skip to content

Commit

Permalink
Merge pull request #28 from jekyll/api
Browse files Browse the repository at this point in the history
Merge pull request 28
  • Loading branch information
parkr committed Dec 1, 2015
2 parents acc6063 + af85461 commit cecdefe
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 13 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ You may optionally specify a `filename` after the `gist_id`:

This will produce the correct URL to show just the specified file in your post rather than the entire Gist.

**Pro-tip**: If you provide a personal access token with Gist scope, as the environmental variable `JEKYLL_GITHUB_TOKEN`, Jekyll Gist will use the Gist API to speed up site generation.

## Disabling `noscript` support

By default, Jekyll Gist will make an HTTP call per Gist to retrieve the raw content of the Gist. This information is used to propagate `noscript` tags for search engines and browsers without Javascript support. If you'd like to disable this feature, for example, to speed up builds locally, simply add the following to your site's `_config.yml`:
Expand Down
1 change: 1 addition & 0 deletions jekyll-gist.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]

spec.add_dependency "octokit", "~> 4.2"
spec.add_development_dependency "bundler", "~> 1.6"
spec.add_development_dependency "rake"
spec.add_development_dependency "rspec"
Expand Down
54 changes: 42 additions & 12 deletions lib/jekyll-gist/gist_tag.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'cgi'
require 'net/http'
require 'octokit'

Net::OpenTimeout = Class.new(RuntimeError) unless Net.const_defined?(:OpenTimeout)
Net::ReadTimeout = Class.new(RuntimeError) unless Net.const_defined?(:ReadTimeout)
Expand Down Expand Up @@ -55,7 +56,13 @@ def gist_noscript_tag(gist_id, filename = nil)
code = fetch_raw_code(gist_id, filename)
if !code.nil?
code = code.force_encoding(@encoding)
"<noscript><pre>#{CGI.escapeHTML(code)}</pre></noscript>"
code = CGI.escapeHTML(code)

# CGI.escapeHTML behavior differs in Ruby < 2.0
# See https://github.com/jekyll/jekyll-gist/pull/28
code = code.gsub("'", "&#39;") if RUBY_VERSION < "2.0"

"<noscript><pre>#{code}</pre></noscript>"
else
Jekyll.logger.warn "Warning:", "The <noscript> tag for your gist #{gist_id} could not"
Jekyll.logger.warn "", "be generated. This will affect users who do not have"
Expand All @@ -64,20 +71,43 @@ def gist_noscript_tag(gist_id, filename = nil)
end

def fetch_raw_code(gist_id, filename = nil)
return code_from_api(gist_id, filename) if ENV["JEKYLL_GITHUB_TOKEN"]

url = "https://gist.githubusercontent.com/#{gist_id}/raw"
url = "#{url}/#{filename}" unless filename.empty?
begin
uri = URI(url)
Net::HTTP.start(uri.host, uri.port,
use_ssl: uri.scheme == 'https',
read_timeout: 3, open_timeout: 3) do |http|
request = Net::HTTP::Get.new uri.to_s
response = http.request(request)
response.body
end
rescue SocketError, Net::HTTPError, Net::OpenTimeout, Net::ReadTimeout, TimeoutError
nil
uri = URI(url)
Net::HTTP.start(uri.host, uri.port,
use_ssl: uri.scheme == 'https',
read_timeout: 3, open_timeout: 3) do |http|
request = Net::HTTP::Get.new uri.to_s
response = http.request(request)
response.body
end
rescue SocketError, Net::HTTPError, Net::OpenTimeout, Net::ReadTimeout, TimeoutError
nil
end

private

def code_from_api(gist_id, filename = nil)
gist = GistTag.client.gist gist_id

file = if filename.to_s.empty?
# No file specified, return the value of the first key/value pair
gist.files.first[1]
else
# .files is a hash of :"filename.extension" => data pairs
# Rather than using to_sym on arbitrary user input,
# Find our file by calling to_s on the keys
match = gist.files.find { |name, data| name.to_s == filename }
match[1] if match
end

file[:content] if file
end

def self.client
@client ||= Octokit::Client.new :access_token => ENV["JEKYLL_GITHUB_TOKEN"]
end
end
end
Expand Down
111 changes: 111 additions & 0 deletions spec/fixtures/multiple-files.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{
"url": "https://api.github.com/gists/aa5a315d61ae9438b18d",
"forks_url": "https://api.github.com/gists/aa5a315d61ae9438b18d/forks",
"commits_url": "https://api.github.com/gists/aa5a315d61ae9438b18d/commits",
"id": "aa5a315d61ae9438b18d",
"description": "description of gist",
"public": true,
"owner": {
"login": "octocat",
"id": 1,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"user": null,
"files": {
"ring.erl": {
"size": 932,
"raw_url": "https://gist.githubusercontent.com/raw/365370/8c4d2d43d178df44f4c03a7f2ac0ff512853564e/ring.erl",
"type": "text/plain",
"language": "Erlang",
"truncated": false,
"content": "contents of gist"
},
"hello-world.rb": {
"size": 932,
"raw_url": "https://gist.githubusercontent.com/raw/365370/8c4d2d43d178df44f4c03a7f2ac0ff512853564e/ring.erl",
"type": "text/plain",
"language": "Ruby",
"truncated": false,
"content": "puts 'hello world'"
}
},
"comments": 0,
"comments_url": "https://api.github.com/gists/aa5a315d61ae9438b18d/comments/",
"html_url": "https://gist.github.com/aa5a315d61ae9438b18d",
"git_pull_url": "https://gist.github.com/aa5a315d61ae9438b18d.git",
"git_push_url": "https://gist.github.com/aa5a315d61ae9438b18d.git",
"created_at": "2010-04-14T02:15:15Z",
"updated_at": "2011-06-20T11:34:15Z",
"forks": [
{
"user": {
"login": "octocat",
"id": 1,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"url": "https://api.github.com/gists/dee9c42e4998ce2ea439",
"id": "dee9c42e4998ce2ea439",
"created_at": "2011-04-14T16:00:49Z",
"updated_at": "2011-04-14T16:00:49Z"
}
],
"history": [
{
"url": "https://api.github.com/gists/aa5a315d61ae9438b18d/57a7f021a713b1c5a6a199b54cc514735d2d462f",
"version": "57a7f021a713b1c5a6a199b54cc514735d2d462f",
"user": {
"login": "octocat",
"id": 1,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"change_status": {
"deletions": 0,
"additions": 180,
"total": 180
},
"committed_at": "2010-04-14T02:15:15Z"
}
]
}
103 changes: 103 additions & 0 deletions spec/fixtures/single-file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
"url": "https://api.github.com/gists/aa5a315d61ae9438b18d",
"forks_url": "https://api.github.com/gists/aa5a315d61ae9438b18d/forks",
"commits_url": "https://api.github.com/gists/aa5a315d61ae9438b18d/commits",
"id": "aa5a315d61ae9438b18d",
"description": "description of gist",
"public": true,
"owner": {
"login": "octocat",
"id": 1,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"user": null,
"files": {
"ring.erl": {
"size": 932,
"raw_url": "https://gist.githubusercontent.com/raw/365370/8c4d2d43d178df44f4c03a7f2ac0ff512853564e/ring.erl",
"type": "text/plain",
"language": "Erlang",
"truncated": false,
"content": "contents of gist"
}
},
"comments": 0,
"comments_url": "https://api.github.com/gists/aa5a315d61ae9438b18d/comments/",
"html_url": "https://gist.github.com/aa5a315d61ae9438b18d",
"git_pull_url": "https://gist.github.com/aa5a315d61ae9438b18d.git",
"git_push_url": "https://gist.github.com/aa5a315d61ae9438b18d.git",
"created_at": "2010-04-14T02:15:15Z",
"updated_at": "2011-06-20T11:34:15Z",
"forks": [
{
"user": {
"login": "octocat",
"id": 1,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"url": "https://api.github.com/gists/dee9c42e4998ce2ea439",
"id": "dee9c42e4998ce2ea439",
"created_at": "2011-04-14T16:00:49Z",
"updated_at": "2011-04-14T16:00:49Z"
}
],
"history": [
{
"url": "https://api.github.com/gists/aa5a315d61ae9438b18d/57a7f021a713b1c5a6a199b54cc514735d2d462f",
"version": "57a7f021a713b1c5a6a199b54cc514735d2d462f",
"user": {
"login": "octocat",
"id": 1,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},
"change_status": {
"deletions": 0,
"additions": 180,
"total": 180
},
"committed_at": "2010-04-14T02:15:15Z"
}
]
}
32 changes: 32 additions & 0 deletions spec/gist_tag_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
doc.output = Jekyll::Renderer.new(doc.site, doc).run
end

before(:each) { ENV["JEKYLL_GITHUB_TOKEN"] = nil }

context "valid gist" do
context "with user prefix" do
Expand Down Expand Up @@ -118,6 +119,37 @@

end

context "with token" do
before { ENV["JEKYLL_GITHUB_TOKEN"] = "1234" }
before {
stub_request(:get, "https://api.github.com/gists/1342013").
to_return(:status => 200, :body => fixture("single-file"), :headers => {"Content-Type" => "application/json"})
}
let(:gist_id) { "1342013" }
let(:gist) { "page.gist_id" }
let(:output) do
doc.data['gist_id'] = gist_id
doc.content = content
doc.output = Jekyll::Renderer.new(doc.site, doc).run
end

it "produces the noscript tag" do
expect(output).to match(/<noscript><pre>contents of gist<\/pre><\/noscript>/)
end

context "with a filename" do
before {
stub_request(:get, "https://api.github.com/gists/1342013").
to_return(:status => 200, :body => fixture("multiple-files"), :headers => {"Content-Type" => "application/json"})
}
let(:content) { "{% gist 1342013 hello-world.rb %}" }

it "produces the noscript tag" do
expect(output).to match(/<noscript><pre>puts &#39;hello world&#39;<\/pre><\/noscript>/)
end
end
end

context "with noscript disabled" do
let(:doc) { doc_with_content(content, { "gist" => { "noscript" => false } }) }
let(:output) do
Expand Down
6 changes: 5 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
require File.expand_path("../lib/jekyll-gist.rb", TEST_DIR)

Jekyll.logger.log_level = :error
STDERR.reopen(test(?e, '/dev/null') ? '/dev/null' : 'NUL:')

RSpec.configure do |config|
config.run_all_when_everything_filtered = true
Expand Down Expand Up @@ -42,4 +41,9 @@ def site(opts = {})
}))
Jekyll::Site.new(conf)
end

def fixture(name)
path = File.expand_path "./fixtures/#{name}.json", File.dirname(__FILE__)
File.open(path).read
end
end

0 comments on commit cecdefe

Please sign in to comment.