Gistをブログなど外部ページで表示したい場合、
Embed用JavaScript("https://gist.github.com/<ユーザー名>/\.js")が提供されているけれど、
これは document.write() を呼んでHTMLを書き込んでいるため、
動的なページ読み込みとの相性が良くない。
(document.write()を一時的に上書きして出力内容を保存し、最後に任意の箇所にappendするなど)
別途JSONやJSONPで document.write()書き込み内容と同様のHTMLタグ文字列を返すAPIも存在しているようなので
それを使用して外部ページ埋め込みを行ってみることにする。
-
JSONを返す
"https://gist.github.com/<ユーザー名>/\.json" -
JSONPを返す
"https://gist.github.com/<ユーザー名>/\.json?calback=<コールバック関数名>"
JSではdocument.write()を二回呼び、一回目でCSSへのリンク用タグ, 二回目で内容自体を書き込んでいるが、
JSONでは stylesheet, div に加えて description , owner, created_at といった情報も返される。
JQuery + CoffeeScript でこの JSON を処理してみる。
<p>euler1.hs</p>
<div class="gist" data-user="zaneli" data-id="6131635" data-file="euler1.hs"></div>
<p>euler2-1.hs</p>
<div class="gist" data-user="zaneli" data-id="6131635" data-file="euler2-1.hs"></div>
<button id="readmorebtn" />readmore</button>
<div id="readmorearea"></div>
$ ->
appendGist = ->
host = "https://gist.github.com"
$(".gist").each (index) ->
$this = $(@)
id = $this.data "id"
return unless id?
user = $this.data "user"
file = $this.data "file"
url = (x for x in [host, user, "#{id}.json"] when x?).join "/"
param = ("#{k}=#{v}" for k, v of {callback : "callback#{index}",file: file} when v?).join "&"
$this.attr "class", "gist#{index}"
$.ajax
type: "GET",
url: "#{url}?#{param}",
dataType: "jsonp",
jsonpCallback: "callback#{index}",
success: (json) ->
$(".gist#{index}").append """<link rel="stylesheet" href="#{host}/#{json.stylesheet}" />"""
$(".gist#{index}").append json.div
$("#readmorebtn").click ->
$("#readmorearea").append("""
<p>euler2-2.hs</p>
<div class="gist" data-user="zaneli" data-id="6131635" data-file="euler2-2.hs"></div>
<p>all</p>
<div class="gist" data-user="zaneli" data-id="6131635"></div>""")
appendGist()
appendGist()
user が指定されていない場合
(#{host}/#{id}.json にリクエストを投げるとユーザー名を補ったURLにリダイレクトされる)、
ファイル名が指定されていない場合
(一つのGistに複数ファイルがある場合、指定するとそのファイルのみ、指定しないと全てのファイルが返される)
などを考慮して、
url と param を作るところでリスト内包表記的に処理してみたが、パッと見分かりづらくなったかもしれない…。
ユーザー名を指定しない前提でシンプルにやるなら
url = "#{host}/#{id}.json?callback=callback#{index}"
url += "&file=#{file}" if file?
とか
url = "#{host}/#{id}.json?callback=callback#{index}#{if file? then "&file=#{file}" else ""}"
でも十分なはず。
(無駄にリダイレクトが発生してしまうので、逆にユーザー名指定必須だったりユーザー名固定でもいいかも。)
無名関数ではなくappendGistという関数名をつけたのは、
ページ初期表示時と動的なページ読み込み時にそれぞれ呼ぶことを想定しているため。