Skip to content

Instantly share code, notes, and snippets.

@poochin
Created May 7, 2013 05:49
Show Gist options
  • Select an option

  • Save poochin/5530506 to your computer and use it in GitHub Desktop.

Select an option

Save poochin/5530506 to your computer and use it in GitHub Desktop.
代入とイテレートのみ実装したテンプレートエンジンです。 短い行数で欲しかったので書きました。
/**
* Name: tParser
* Desc: Lite template engine (only assign and array iterate)
* License: MIT
* Author: poochin
**/
/**
* 構文:
* {{ A }}: 変数の代入
* ex: {{ A }}, {{A.B}}
* {{ iter A@B }}: 配列 A に B という名前を付けてループ
* ex: {{ iter A@B }} {{ B }} {{ /iter }}
* {{ iter A.a@B }} ... {{/iter}}
*
* 自由度と制約:
* {{...}} で参照する際には、オブジェクトの階層を .(ドット) を用いて掘ることができます
* {{...}} の中括弧の直内は空白を自由に取って構いません
* {{ iter }} はネストできません
* {{ iter }} はインデックス番号を参照できません
*/
function tParser(src) {
var self = this;
var reg = /(?:{{\s*([A-Za-z0-9._]+)\s*}}|{{\s*iter\s+([A-Za-z0-9._]+)@([A-Za-z0-9_]+)\s*}}([\s\S]*){{\s*\/iter\s*}})/gm;
var last_index = 0;
var next_str = "";
var nodes = [];
/* ここでは置換ではなく字句解析目的で replace 関数を用いています */
src.replace(reg,
function(match_text, assign_key, iter_key, iter_as, iter_text, index, all_text){
if (index !== 0) {
nodes.push(self.tNode(all_text.slice(last_index, index), 'text'));
last_index = index;
}
if (assign_key !== undefined) {
nodes.push(self.tNode(assign_key, 'assign'));
last_index += match_text.length;
}
else {
nodes.push(self.tNode(iter_text, 'iter', {iter_key: iter_key, iter_as: iter_as}));
last_index += match_text.length;
}
next_str = all_text.slice(last_index);
}
);
if (next_str.length) {
nodes.push(self.tNode(next_str, 'text'));
}
this.nodes = nodes;
}
tParser.prototype = {
digDict: function digDict(dict, keys) {
if (keys.length === 1) {
return dict[keys[0]];
}
return ((dict[keys[0]] !== undefined)
? (this.digDict(dict[keys[0]], keys.slice(1)))
: (undefined));
},
textBuilder: function textBuilder(text, dict, iter_dict) {
var self = this;
var reg = /{{\s*([A-Za-z0-9._]+)\s*}}/gm;
function replacer(a,b,c,d) {
return self.digDict(iter_dict, b.split('.')) || self.digDict(dict, b.split('.')) || "";
}
return text.replace(reg, replacer);
},
tNode: function tNode(text, type, iter_options) {
return {
text: text,
type: type, /* text, iter, assign */
iter_options: iter_options, /* iter_key, iter_as */
}
},
assign: function(dict) {
var self = this;
return this.nodes.map(
function(tnode){
var iter_array;
var iter_results;
switch(tnode.type) {
case "iter":
iter_array = self.digDict(dict, tnode.iter_options.iter_key.split('.'));
iter_results = iter_array.map(function(src) {
var iter_dict = {};
iter_dict[tnode.iter_options.iter_as] = src;
return self.textBuilder(tnode.text, dict, iter_dict);
});
return iter_results.join('');
case "assign":
return self.digDict(dict, tnode.text.split('.')) || "";
}
return tnode.text;
}
).join('');
}
};
/* // Sample
var text = "Balls are{{ iter A.ITER@B }} {{ B }}{{ /iter }} and {{ C }}";
var dict = {A: {ITER: ["red", "blue"]}, C: "yellow"};
var t = new tParser(text);
var result = t.assign(dict); // get "Balls are red blue and yellow"
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment