Titanium Alloy with StylusでFontを設定
Titanium™ Advent Calendar 2013の18日目です。
枠が開いているようだったので、僭越ながら2回目書かせていただきます。
私のAlloyでの開発スタイル
私が最近Titaniumに取り組むときは、@ryugoo_さんのこちらの記事を参考にさせていただきつつ、Alloy with Jade & Stylusで作っています。
この組み合わせだと、さらにCoffeeScriptを加えるというのが定番のようですが、私はJS歴が短いこともあり、まずは素のJSを理解せねばということで、まだ使っていません。
Alloy with Slylusの問題
さて、Jade & Stylusだけでも、UI周りのコーディングは非常にわかりやすくなるわけですが、1点だけ問題がありました。
それは、Stylusの中でFontの設定が書けない点です。
例えばLabelに対してfontSizeやfontWeightを設定したい場合、.tssであれば以下のように書くと思います。
"Label": { font: { fontSize: 20, fontWeight: "bold" } }
これを、Stylusを使うので、
Label font fontSize 20 fontWeight "bold"
のように書けば良いのかと思いきや、これをStylusに通すと、
"Label font": { fontSize: 20, fontWeight: "bold" }
のようになってしまいます。
それもそのはずで、そもそもCSSは階層構造になることがないので、意図したような解釈をしてくれないということのようです。
改良記法で対応
そこで若干強引ですが、alloy.jmk内にてfont指定部分を書き換える処理を加える事で、fontの指定もできるようにしてみました。
前提として、解析を簡単にするために、fontへは以下の形式に指定することにします。
font <key> <value>, <key> <value>, ...
例えば、LabelにfontSizeのみ指定する場合、
Label font fontSize 24
例えば、fontSizeとfontWeightを指定する場合、
Label font fontSize 24, fontWeight "bold"
要するに、fontというキーに対して、指定するキーとバリューの組み合わせをカンマ区切りの値として指定するという感じです。
上記2種類を書いた.stylを通すと、それぞれ以下の様に.tssに出力されます。
"Label": { font: { fontSize:24 } }
"Label": { font: { fontSize:24, fontWeight:"bold" } }
これで、font指定もStylusっぽく書けるようになります。
変更した部分は、Stylusのを解析してreturn tss
していた箇所で、さらに上記の改良記法を解析する処理を入れてみました。
var compileTSS = function(root, target) { var data = fs.readFileSync(path.join(root, target), "utf8"), tss; styl.render(data, function(err, css) { css = css.replace(/;/gi, ","); css = css.replace(/\}/gi, "},"); css = css.replace(/(.+?).?\{/gi, "\"$1\": {"); css = css.replace(/,\n\},/gi, "\n\}"); css = css.replace(/\}\n\"/gi, "\},\n\""); css = css.replace(/['"]expr(.+?)['"]/gi, "expr$1"); css = css.replace(/['"]Ti(.+?)['"]/gi, "Ti$1"); css = css.replace(/['"]Titanium(.+?)['"]/gi, "Titanium$1"); css = css.replace(/['"]Alloy(.+?)['"]/gi, "Alloy$1"); tss = css; }); // return tss; var tss2 = []; tss.split("\n").forEach(function(line) { if (line.match(/font:/)) { var fontObj = RegExp.rightContext.replace(/(^\s+)|(\s+$)/g, ""); var closeBrace = " }"; if (fontObj.match(/,$/)) { closeBrace = closeBrace + ","; fontObj = fontObj.replace(/,$/, ""); } tss2.push(" font: {"); var fontObjArray = fontObj.split(","); for (var i = 0; i < fontObjArray.length; i++) { var f = fontObjArray[i].replace(/(^\s+)|(\s+$)/g, "").replace(/ /, ":"); if (1 < fontObjArray.length && i < (fontObjArray.length - 1)) { f = f + ","; } tss2.push(" " + f); } tss2.push(closeBrace); } else { tss2.push(line); } }); return tss2.join("\n"); }
上記対応部分を抽出したalloy.jmkとしては、以下の様な感じになります。
Alloy with StylusでFontも設定(改良記法)できるようにしたもの
もっとスマートに書けそうな気もしますが、とりあえず意図通りに動いたので、ひとまずそのままです。
あまり実戦投入していないので、不具合があるケースがあるかもしれませんので、そのときはそっと教えてください。
一応、これを使ったプロジェクトのサンプルとして、Titanium™ Advent Calendar 2013の3日目に掲載したumi-uyura/TiAnimateStudyでも使っています。
TableViewを普通に使うと、iOSに比べてAndroidでは文字が小さ目になってしまうので、AndroidのみfontSizeを少し大きくする、という使い方をしています。
ということで、参考になれば幸いです。
明日は@dasa_101さんです。
よろしくお願いします!