Skip to content

Instantly share code, notes, and snippets.

@myaumyau
Last active December 15, 2015 10:09
Show Gist options
  • Save myaumyau/5243662 to your computer and use it in GitHub Desktop.
Save myaumyau/5243662 to your computer and use it in GitHub Desktop.
[js]JSでテンプレート
/*
仕様
テンプレートを読み込み下記の処理を行う
[% code %] :コードの実行
[%= context.**** ] :変数代入
<% %>
<%= %>
[% と %] を文字列として扱う場合は\でエスケープする。
ex) [\% と \%]
*/
var TemplateProcessor = TemplateProcessor || (function() {
var TP = function() {
this.initialize.apply(this, arguments);
};
TP.prototype.initialize = function(template) {
var ary = [];
this.template = template;
ary.push('var parsedTemplate = function(context) {');
ary.push(this.analyze());
ary.push('return __code.join("");');
ary.push('}(context);');
this.javascriptSource = ary.join('\r\n');
};
TP.prototype.parse = function(context) {
if (!context) context = {};
try {
eval(this.javascriptSource);
} catch(ex) {
alert('Parse Error\r\nType: ' + ex.Type + '\r\nMessage: ' + ex.Message);
}
return parsedTemplate; //evalの結果を返す。
};
TP.prototype.analyze = function() {
/*
try {
var __code = [], __cCnt = 0;
// テンプレートから作成したコード
} catch(ex) {
alert('Analyze Error\r\nType: ' + ex.Name + '\r\nMessage: ' + ex.Message);
}
*/
var codeline = [''], // evalで評価されるコード
lCnt = 1,
template = this.template,
isCode = false,
isVariable = false,
strVariable = '', // 代入式
i = 0,
iz = template.length,
s, s1, s2, s3;
codeline[lCnt++] = 'var __code = [], __cCnt = 0;';
codeline[lCnt++] = '__code[__cCnt++] = unescape("';
/*
テンプレート文字以外 __code[__cCnt++] = unescape("エンコードされた文字列"); として出力
テンプレート文字 __code[__cCnt++] = this.;
*/
for (; i < iz; i++) {
s1 = template.charAt(i); // 1文字目
s2 = (i + 1 < iz) ? s1 + template.charAt(i + 1) : ''; // 2文字目
s3 = (i + 2 < iz) ? s2 + template.charAt(i + 2) : ''; // 3文字目
// エスケープの場合
if (s3 == '[\\%' || s3 == '\\%]') {
// 現在のモードがコード・代入のどちらかの場合は、\\を空文字に置換
// 現在のモードがコード・代入のどちらでもない場合は、\\を空文字に置換してエスケープ
s = (isCode || isVariable) ? s3.replace('\\', '') : escape(s3.replace('\\', ''));
if (isVariable) { // 現在のモードが代入の場合はストック
strVariable += s;
} else { // 現在のモードが代入以外の場合
codeline[lCnt++] = s;
}
i += 2;
} else if(s2 == '[%' && s3 != '[%=') { // コード開始タグ
isCode = true;
codeline[lCnt++] = '");\r\n';
i += 1;
} else if(s3 == '[%=') { // 代入開始タグ
isVariable = true;
codeline[lCnt++] = '");\r\n' + '__code[__cCnt++] = ';
i += 2;
} else if(s2 == '%]') { // 終了タグ
if (isVariable) {
codeline[lCnt++] = this.format(strVariable) + ';';
strVariable = '';
isVariable = false;
}
isCode = false;
codeline[lCnt++] = '\r\n' + '__code[__cCnt++] = unescape("';
i += 1;
} else { // 開始・終了タグ以外
// 現在のモードがコード・代入のどちらかの場合
// 現在のモードがコード・代入のどちらでもない場合は、エスケープ
s = (isCode || isVariable) ? s1 : escape(s1);
if(isVariable) { // 現在のモードが代入の場合
strVariable += s;
} else {
codeline[lCnt++] = s;
}
}
}
return 'try {' + '\r\n'
+ codeline.join('') + '");' + '\r\n'
+ '} catch(ex) {'
+ 'alert("Analyze Error\\r\\nType: " + ex.Name + "\\r\\nMessage: " + ex.Message);'
+ '}';
};
/*
フォーマット指定によりeval可能な結果を返す。
現在は未実装。
*/
TP.prototype.format = function(format) {
return format;
};
return TP;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment