Sublime Text 2でHTML要素のクラス名やIDの選択を少しだけ楽にする設定

Sublime Text 2は、デフォルトの設定では「-」(ハイフン)が単語の区切り文字に設定されています。なので、HTML要素のクラス名やIDなどのハイフン区切りの識別子をCtrl-dの単語選択で選択しようとしても一部分しか選択できなくて残念な気持ちになります。

しかし、この振る舞いはもちろん簡単に修正することができます。Sublime Text 2の設定項目のうちのひとつ、word_separatorsの内容を変更するだけです。

word_separatorsはデフォルトでは次のような設定になっています。

"word_separators": "./\\()\"'-:,.;<>~!@#$%^&*|+=[]{}`~?",

見ての通りハイフンが単語の区切り文字リストに含まれています。これを取り除いてユーザー設定ファイルにコピペすればOKです。

備考

この設定はユーザー設定ファイルに直接書いておくだけでも良いですが、言語固有の設定ファイルに置いておくのもよさそうです。僕はとりあえずHTMLとCSSJavaScript系の設定ファイルに置いておくことにしました。(言語固有の設定ファイルは、設定したい言語のファイルを開いて、メニューのPreferences > Settings - More > Syntax Specific - User と辿っていけば簡単に見つかります)

他にも、

  • JavaScript:「$」も単語の区切り文字リストから外しておく
  • Ruby: 「!, ?」を(略)
  • Lisp系: 「-, !, ?, *, などいろいろ」を(略)

などを設定しておくとよさそうですね:)

CoffeeScriptを利用したPhantom.jsのevaluateで「ReferenceError: Can't find variable: __slice」となる問題

原因

Phantom.jsのpage.evaluateに渡す関数は外側のスコープの変数を利用できないのに、CoffeeScriptのコンパイラが外側のスコープの変数を利用する関数を生成してしまうため。

対策

次のような関数を利用することでpage.evaluateに渡す関数が変数を自身のスコープ内のみで解決できるようにする。

toBeExecutableInBrowser = (func) ->
  str = func.toString().replace /\n/, '\n    var __slice = [].slice;\n'
  eval "(#{str})"

あるいは次のようにしてpage.evaluateの動作を変更し、ブラウザ内に__sliceという変数を事前に定義するようにしておく。

do () ->
  evaluate = page.evaluate
  page.evaluate = (func) ->
    evaluate.call @, `function() {
      window.__slice = [ ].slice;
    }`
    evaluate.call @, func

経緯みたいなもの(蛇足)

例えば、はてなブックマークホッテントリのタイトル一覧を取得しようとした場合、次のようなコードを書けば上手くいきます。

page = require('webpage').create()
page.open 'http://b.hatena.ne.jp/hotentry', (status) ->
  result = page.evaluate () ->
    links = document.getElementsByClassName 'entry-link'
    links = [ ].slice.call links
    JSON.stringify(links.map (link) -> link.innerText)
  titles = JSON.parse result
  console.log titles.join('\n')
  phantom.exit()

ブラウザ内でJavaScriptを実行するところの

links = document.getElementsByClassName 'entry-link'
links = [ ].slice.call links

という部分でdocument.getElementsByClassNameで取得したリンク一覧(配列のようなオブジェクト)をきちんとした配列に変換しています。

この部分をCoffeeScriptの文法を利用して次のように書き直しました。

[links...] = document.getElementsByClassName 'entry-link'

...これがGood PracticeかBad Practiceかどうかはどうかはさておくとして、一応これでも動くと思ったんですが、実行してみると次のようなエラーになってしまいました。

ReferenceError: Can't find variable: __slice

  phantomjs://webpage.evaluate():3
  phantomjs://webpage.evaluate():7
  phantomjs://webpage.evaluate():7
TypeError: 'null' is not an object (evaluating 'titles.join')

  example.coffee:17

CoffeeScriptのコンパイラが余計な気を利かして配列化の関数__slicepage.evaluateに渡す関数の外側で定義していたことが原因でした。page.evaluateは渡された関数の外側にある変数を利用できない(というかPhantom側からブラウザ側に関数を渡す過程でスコープチェーンを保持しておくことができない)ので、ブラウザ側で__sliceという変数の解決に失敗しているということです。

それで、なるべく関数のコードを変えないような形でこの問題を解決できないかといろいろ試したんですが、最終的に次のようにするのがベターかなと思いました。

toBeExecutableInBrowser = (func) ->
  str = func.toString().replace /\n/, '\n    var __slice = [ ].slice;\n'
  eval "(#{str})"

getTitles = () ->
  [links...] = document.getElementsByClassName 'entry-link'
  JSON.stringify(links.map (link) -> link.innerText)

browserGetTitles = toBeExecutableInBrowser getTitles

page = require('webpage').create()
page.open 'http://b.hatena.ne.jp/hotentry', (status) ->
  result = page.evaluate browserGetTitles
  titles = JSON.parse result
  console.log titles.join('\n')
  phantom.exit()

toBeExecutableInBrowserという関数を利用して、page.evaluateに渡したい関数の中身に無理やり__sliceの宣言を追加してしまうという感じです。

一応これで動くようになりました。まあ今回の場合はべつに[links...]という記法を使わずに[ ].slice.callを使ったり、そもそも[ ].map.callを使えばよかったわけですが、他にも色々と同じような問題が出てくるだろうということで書き残しておきました。CoffeeScriptの予約語リストを見るに'__hasProp', '__extends', '__slice', '__bind' '__indexOf'のあたりはまた同じような問題を起こしそうです。


もう一つのやり方として次のようなのも良い感じです。

browserGetTitles = () ->
  [links...] = document.getElementsByClassName 'entry-link'
  JSON.stringify(links.map (link) -> link.innerText)

page = require('webpage').create()

do () ->
  evaluate = page.evaluate
  page.evaluate = (func) ->
    evaluate.call @, `function() {
      window.__slice = [ ].slice;
    }`
    evaluate.call @, func

page.open 'http://b.hatena.ne.jp/hotentry', (status) ->
  result = page.evaluate browserGetTitles
  titles = JSON.parse result
  console.log titles.join('\n')
  phantom.exit()

page.evaluateの動作を変更して、先にグローバルに__sliceを定義するようにしています。CoffeeScriptでは__slice予約語になっているのでJavaScript埋め込み機能を利用しています。page.evaluateJavaScriptを使えばもう少し簡潔になるんですが、なぜか利用できないのでこういう形になりました。

あとはpage.includeJspage.injectJsなんかを利用しても解決できるかと思います。

ブラウザでBase64エンコードされた画像をデコードして閲覧する

(Chrome, Safari, Firefoxで確認)

ブラウザのアドレスバーにdata:image/jpeg;base64,{{Base64文字列}}みたいな感じで入力して移動すると表示できます。

とりあえずGooglefaviconで。下のリンクをクリックするか、テキストをトリプルクリックなんかでコピーしてアドレスバーに貼り付けて移動してみてください。画像が表示されるのが確認できると思います。

リンク形式

リンク

テキスト形式

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4ge4SUNDX1BST0ZJTEUAAQEAAAeoYXBwbAIgAABtbnRyUkdCIFhZWiAH2QACABkACwAaAAthY3NwQVBQTAAAAABhcHBsAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtkZXNjAAABCAAAAG9kc2NtAAABeAAABWxjcHJ0AAAG5AAAADh3dHB0AAAHHAAAABRyWFlaAAAHMAAAABRnWFlaAAAHRAAAABRiWFlaAAAHWAAAABRyVFJDAAAHbAAAAA5jaGFkAAAHfAAAACxiVFJDAAAHbAAAAA5nVFJDAAAHbAAAAA5kZXNjAAAAAAAAABRHZW5lcmljIFJHQiBQcm9maWxlAAAAAAAAAAAAAAAUR2VuZXJpYyBSR0IgUHJvZmlsZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbWx1YwAAAAAAAAAeAAAADHNrU0sAAAAoAAABeGhySFIAAAAoAAABoGNhRVMAAAAkAAAByHB0QlIAAAAmAAAB7HVrVUEAAAAqAAACEmZyRlUAAAAoAAACPHpoVFcAAAAWAAACZGl0SVQAAAAoAAACem5iTk8AAAAmAAAComtvS1IAAAAWAAACyGNzQ1oAAAAiAAAC3mhlSUwAAAAeAAADAGRlREUAAAAsAAADHmh1SFUAAAAoAAADSnN2U0UAAAAmAAAConpoQ04AAAAWAAADcmphSlAAAAAaAAADiHJvUk8AAAAkAAADomVsR1IAAAAiAAADxnB0UE8AAAAmAAAD6G5sTkwAAAAoAAAEDmVzRVMAAAAmAAAD6HRoVEgAAAAkAAAENnRyVFIAAAAiAAAEWmZpRkkAAAAoAAAEfHBsUEwAAAAsAAAEpHJ1UlUAAAAiAAAE0GFyRUcAAAAmAAAE8mVuVVMAAAAmAAAFGGRhREsAAAAuAAAFPgBWAWEAZQBvAGIAZQBjAG4A/QAgAFIARwBCACAAcAByAG8AZgBpAGwARwBlAG4AZQByAGkBDQBrAGkAIABSAEcAQgAgAHAAcgBvAGYAaQBsAFAAZQByAGYAaQBsACAAUgBHAEIAIABnAGUAbgDoAHIAaQBjAFAAZQByAGYAaQBsACAAUgBHAEIAIABHAGUAbgDpAHIAaQBjAG8EFwQwBDMEMAQ7BEwEPQQ4BDkAIAQ/BEAEPgREBDAEOQQ7ACAAUgBHAEIAUAByAG8AZgBpAGwAIABnAOkAbgDpAHIAaQBxAHUAZQAgAFIAVgBCkBp1KAAgAFIARwBCACCCcl9pY8+P8ABQAHIAbwBmAGkAbABvACAAUgBHAEIAIABnAGUAbgBlAHIAaQBjAG8ARwBlAG4AZQByAGkAcwBrACAAUgBHAEIALQBwAHIAbwBmAGkAbMd8vBgAIABSAEcAQgAg1QS4XNMMx3wATwBiAGUAYwBuAP0AIABSAEcAQgAgAHAAcgBvAGYAaQBsBeQF6AXVBeQF2QXcACAAUgBHAEIAIAXbBdwF3AXZAEEAbABsAGcAZQBtAGUAaQBuAGUAcwAgAFIARwBCAC0AUAByAG8AZgBpAGwAwQBsAHQAYQBsAOEAbgBvAHMAIABSAEcAQgAgAHAAcgBvAGYAaQBsZm6QGgAgAFIARwBCACBjz4/wZYdO9k4AgiwAIABSAEcAQgAgMNcw7TDVMKEwpDDrAFAAcgBvAGYAaQBsACAAUgBHAEIAIABnAGUAbgBlAHIAaQBjA5MDtQO9A7kDugPMACADwAPBA78DxgOvA7sAIABSAEcAQgBQAGUAcgBmAGkAbAAgAFIARwBCACAAZwBlAG4A6QByAGkAYwBvAEEAbABnAGUAbQBlAGUAbgAgAFIARwBCAC0AcAByAG8AZgBpAGUAbA5CDhsOIw5EDh8OJQ5MACAAUgBHAEIAIA4XDjEOSA4nDkQOGwBHAGUAbgBlAGwAIABSAEcAQgAgAFAAcgBvAGYAaQBsAGkAWQBsAGUAaQBuAGUAbgAgAFIARwBCAC0AcAByAG8AZgBpAGkAbABpAFUAbgBpAHcAZQByAHMAYQBsAG4AeQAgAHAAcgBvAGYAaQBsACAAUgBHAEIEHgQxBEkEOAQ5ACAEPwRABD4ERAQ4BDsETAAgAFIARwBCBkUGRAZBACAGKgY5BjEGSgZBACAAUgBHAEIAIAYnBkQGOQYnBkUARwBlAG4AZQByAGkAYwAgAFIARwBCACAAUAByAG8AZgBpAGwAZQBHAGUAbgBlAHIAZQBsACAAUgBHAEIALQBiAGUAcwBrAHIAaQB2AGUAbABz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

MIMEタイプのところを変えればPNGやGIFといった他の形式の画像や、テキストファイルなんかも表示できそうですね。下は「Base64テスト」と書かれたテキストファイルをBase64エンコードした例です(もし文字化けしていればブラウザのエンコード指定をUTF-8に変更すれば正しく表示されると思います)。

リンク

data:text/plain;base64,QmFzZTY044OG44K544OICg==

Google画像検索結果のimgのsrc属性に使われているのを見て知りました:)

追記

こういうのはData URI schemeというらしい。

GitHub Pages利用メモ

Git力がないからこういうことはすぐハマってしまう:(
いろいろなサイトを参考にさせてもらいながらなんとか解決。

GitHubにmasterブランチは登録せずにgh-pagesブランチだけを登録してそのままgh-pagesで開発していく、というようなことがしたかった。

参考サイト

コード

masterをgh-pagesに改名する版

git init
echo "hello world" >> index.html
git add .
git commit -m "first commit"
git branch -m gh-pages
git remote add origin git@github.com:username/repositoryname.git
git push -u origin gh-pages

ローカルのmasterをリモートのgh-pagesにpushする版

git init
echo "hello world" >> index.html
git add .
git commit -m "first commit"
git remote add origin git@github.com:username/repositoryname.git
git push -u origin master:gh-pages

GitHubでの検索

ちょっと前の話題だけど、GitHubの検索機能の改良があったそうなのでリンクのメモ。あと、検索のトップページにいろいろなフィルターが載っていたのでこちらもメモ。

追記(2013/01/24)

GitHubにコードの全文検索機能が追加されてトップページのデザインが一新されてた。

JavaScript関連いろいろ

備忘録的に。

Backbone.js in Practice: Part I – Preventing Memory Leaks

Backbone.jsにおけるメモリリーク対策の解説。Backbone.jsにおけるメモリリークはイベントバインディングとネストしたビューが鬼門なんだけど、それらに対するメモリリーク対策のパターンが分かりやすく解説されている。

いままでメモリリークのことを気にしたことなかったのでためになった。まあメモリリークを気にするほどの大きなBackbone.jsアプリ作ってないけど:)

Marionette.js – A scalable and composite application architecture for Backbone.js

Backbone.jsの拡張的なもの?GitHubでのStar数が1600を超えていてかなり人気っぽい。

GitHub上のREADMEをちょこっと読んだだけだから詳しくは分からないけど、メモリ管理の機能を用意してくれたりビューやイベントの管理が楽にできたりするらしい?早く詳しく調べたい。

novus / nvd3

チャートライブラリ。グラフ描画系のライブラリといえば少し前にMorris.jsが話題になっていたけど、このNVD3はD3.jsを利用したもの。

まだまだ開発途中・発展途上って感じだけどなかなか良さげ。なによりD3.jsを利用してるってところが(・∀・)イイ!!

最近ちょっとしたお家騒動みたいなことがあったらしく、公式サイト謝罪文的なものが貼られてるけど、まあ結果的にこれからもずっとオープンソースプロジェクトとしてやっていくことになったらしいから一安心。