Last active
December 15, 2015 10:09
-
-
Save myaumyau/5243662 to your computer and use it in GitHub Desktop.
[js]JSでテンプレート
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
仕様 | |
テンプレートを読み込み下記の処理を行う | |
[% 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