Neo: Ju jitsu? I’m gonna learn Ju jitsu?
Forewords
In the last article we explored the internals of D3.js, the data visualization library.
In doing that we ended up with a number of files in a gist.
This morning I thought it’d be nice to put up the thing into one of those JavaScript fiddle sites, I looked up a bunch of them: CodePen, JSFiddle, JS Bin but none of them allowed for arbitrary extensions or loading a code from a Gist1.
I had to build my own.
The Plan
- load and run gists by visiting URLs in this form:
http://ju-jist.herokuapp.com/USER/GIST_ID/FILE_NAME
- eventually add a home page that will build the right url from the
GIST_ID
defaulting toindex.html
as file name
Section 1: Rack Proxy
The first thing I did is to preparing a simple proxy rack application that would extract the gist id and
file name from the URL:
parts = %r{^/(?<user>[^/]+)/?(?<gist_id>w+)/(?<file>.*)(?:$|?(?<query>.*$))}.match(env['PATH_INFO'])
gist_id = parts[:gist_id]
file = parts[:file]
user = parts[:user]
Note here how handy are actually named Regexp groups (introduced in Ruby 1.9).
Then let’s be ol’ school and use open-uri
to fetch urls:
contents = open("https://gist.githubusercontent.com/#{user}/#{gist_id}/raw/#{file}")
Pass it over to Rack:
[200, {}, [contents.read]]
And wrap everything in a rack app:
# config.ru
def call(env)
parts = %r{^/(?<user>[^/]+)/?(?<gist_id>w+)/(?<file>.*)(?:$|?(?<query>.*$))}.match(env['PATH_INFO'])
gist_id = parts[:gist_id]
file = parts[:file]
user = parts[:user]
contents = open("https://gist.githubusercontent.com/#{user}/#{gist_id}/raw/#{file}")
[200, {}, [contents.read]]
end
run self
Section 2: The URL builder
Next I prepared a simple form:
<!-- inside index.html -->
<form>
<input type="text" id="user_and_gist_id">
<input type="submit" value="open">
</form>
And then I used Opal and Native with some vanilla DOM to build the URL and
redirect the user.
# gist-runner.rb
$doc = $$[:document]
input = $doc.querySelector('input#user_and_gist_id')
form = $doc.querySelector('form')
form[:onsubmit] = -> submit {
Native(submit).preventDefault
user_and_gist_id = input[:value]
$$[:location][:href] = "/#{user_and_gist_id}/index.html"
}
And let Rack serve static files:
use Rack::Static, urls: %w[/gist-runner.rb /favicon.ico], index: 'index.html'
run self
Conclusion
Ju-Jist is up and running, you can see the code from the last article gist live on ju-jist.
The code is available on GitHub.
- Actually JSFiddle has some docs for loading Gists, but I wasn’t able to make it work. CodePen and others allow for external resources, but GitHub blocks the sourcing of raw contents from Gists. ↩
Leave a Reply