読者です 読者をやめる 読者になる 読者になる

blogタイトルにgithubのgrass-graphを設定してみた

PCだけ対応してみました。
f:id:rochefort:20170322161656p:plain

最近、全然GitHub使ってなかったので自責の念も込めて作成。
Grass-Graph / Imaging your GitHub Contributions GraphGitHubのGrass-Grappを画像として取得できるWebサービスを運営してくれているので、これを使おうかと思ったのですが、透過PNGでないことと個人的には自前で用意した環境(もしくはHatena Fotolife)に置きたいなと思ったので、script作ってS3に画像を置くようにしてみました。
まずかったらやめます。
 

公開ファイルの置き場所について

S3は十分使えそうなのは知っていたので、他を少し検討。

Hatena Fotolife

当初、ここに置いちゃえばCDNに乗るので使いたかったのですが、ファイル名固定でuploadする方法が分からず断念しました。(CSSで指定する際に固定でないと困る。)

Dropbox

日々のGrass-Graphをここに突っ込もうと思ったので、ついでに公開用のファイルも確か置けたのを思い出して、やろうとしたのですが、現在はPublicにするサービスが終了していました。

結局

公開用はS3、日々の画像はDropboxでやってみることにしました。
(今思うと、Google Cloud Storage でもよかったかも。)

その他検討内容

SVGPNG

blogに貼り付けるならSVGでも良いのではと思ったのですが、以下の理由からPNGで保持するようにしました。

  • SVGの方がファイルサイズが大きい(SVG: 50KB、PNG:3KB)
  • S3に置いただけでは圧縮がかからない
    (CLOUDFRONT使えば圧縮できるんですが、そこまでやるのは面倒だと感じた)
  • SVGをHTMLのbackground-image で指定した場合、CSSの適用ができない?
    SVGの中にstyleを書いちゃえばできるのですが、それは嫌だったので画像にしました
     
    最後のCSSの話になると、欲しいのはブラウザで解釈したGitHub上のGrass-Graphなので、SVG取りにいかずにスクレイプで画像保存すればいいなぁとか思い始めてやりかけたのですが、それはそれでまずそうなのでやめておきました。

Script

rochefort/grass_graph
(あんまりちゃんと作っていないのでgem化もしていません。)

Scrape

nokogiriで取得し、一部整形。
xmlnsの追加と、svgにstyleが書かれており、ブラウザでは見えない値があったので、それらを削除しています。

      def scrape
        url = "https://github.com/#{config.github_id}"
        doc = Nokogiri::HTML.parse(open(url))
        svg = doc.css("svg.js-calendar-graph-svg")
        svg.first["xmlns"] = "http://www.w3.org/2000/svg"
        svg.css('[style="display: none;"]').each { |node| node.content = "" }
        svg
      end

Configuration

Railsっぽいconfiguration設定ができるようにしてみました。

GrassGraph.configure do |config|
  config.github_id = "rochefort"
  config.png_path = "grass-graph.png"

  ...

end

conigureメソッドでblock受け取って、configメソッドでConfigurationクラスのアクセッサを処理する。すごい簡単に書ける。

  class << self
    def configure
      yield config
    end

    def config
      @config ||= Configuration.new
    end

  class Configuration
    attr_accessor :github_id, :png_path, :dropbox, :s3

透過PNG

minimagickでbackground(“none”)するだけでした。

    def self.convert(from, to)
      MiniMagick::Tool::Convert.new do |convert|
        convert.background("none")
        convert.merge! ["-pointsize", "11"]
        convert << from
        convert << to
      end
    end

余談

S3に公開用のSVGをuploadするには Content-Type: image/svg+xml の設定が必要。 f:id:rochefort:20170320225933p:plain