Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

JavaScriptのAST変換

ASTとは腐れ縁にある気がするeller86です。専攻とかは全然関係ないんですが、大抵の仕事でその姿を見ているような……。

さてJavaScriptのAST変換を使ってenchant.jsのassetsを変換できないか試してみました。以前正規表現でなんとかしましたが、どうせやるならASTの方が残念なバグが少なく済むでしょう。使用するライブラリはburritoです。

Hello, world!

コード:

var burrito = require('burrito');
burrito('console.log("Hello, world!")', function (node) {
    console.log(node.name);
});

実行結果:

stat
call
string

すごく単純です。burritoえらい。PMDのVisitorを使ったAPIも好きですが、小粒な変換ならこれで充分ですね。

assetsの探し方を考える

コード:

var burrito = require('burrito');
burrito('var image = hoge.fuga.game.assets["bear.gif"]', function (node) {
    console.log(node.name);
    console.log(node.value);
});

実行結果:

var
[ [ [ 'image', [Object] ] ] ]
sub
[ [ 'dot', [ 'dot', [Object], 'game' ], 'assets' ],
[ { name: 'string', start: [Object], end: [Object] },
'bear.gif' ] ]
string
[ 'bear.gif' ]

node.value[0][0] === 'dot' && node.value[0][2] === 'assets'ならassets自身のノードであると言えそうです。

実際に置き換える

assetsを親に持つstringがファイルパスを表すと仮定し、ファイルデータをBase64で変換したものと置き換えます。
コード:

実行結果:

var image = hoge.fuga.game.assets["data:image/gif;base64,R0lGO...AAOw=="];

わりと単純に実装できました。Base64変換にライブラリが要らないのが地味に嬉しいですね。同期読み込みを使っているので、Nodeっぽくないのがちょいと残念ですが……。

JavaScriptで複数行文字列を扱うためにヒアドキュメントを使いたくなったら

泣くしかない


のですが、代替案としてこのような方法もあります。

  1. CoffeeScriptのウェブサイトを開く
  2. メニューバーのTRY COFFEESCRIPTをクリックし、コンソールを開く
  3. 左ペインに(ダブルクォーテーション3つ)(改行2個)(ダブルクォーテーション3つ)と入力する
  4. 中央の空行に文字列を貼り付ける
  5. 右ペインに文字列が生成されるのでこれをコピペ

例えばこれ↓が

"""
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>example</title>
  <link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
"""

これ↓になります。

"<!DOCTYPE html>\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\" />\n  <title>example</title>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n</head>\n<body>";

頻繁に手が入るテキストには不向きですが、わりと活躍の場はありそうな気がします。