May 19, 2009

PHPとかerbのようなテンプレートをJavaScriptで。

UxU 0.5.11に入れ損ねた。次版で標準のヘルパーメソッドに入れるけど、割といいかげんな実装で、たいした規模じゃないから、テストケースの中に直接書いて使ってもいいと思う。

function parseTemplate(aCode, aContext) {
  var __parseTemplate__codes = [];
  aCode.split('%>').forEach(function(aPart) {
    var strPart, codePart;
    [strPart, codePart] = aPart.split('<%');
    __parseTemplate__codes.push('__parseTemplate__results.push('+
                                strPart.toSource()+
                                ');');
    if (!codePart) return;
    if (codePart.charAt(0) == '=') {
      __parseTemplate__codes.push('__parseTemplate__results.push(('+
                                  codePart.substring(1)+
                                  ') || "");');
    }
    else {
      __parseTemplate__codes.push(codePart);
    }
  });
  var __parseTemplate__results = [];
  with(aContext|| {}) {
    eval('(function() { '+__parseTemplate__codes.join('\n')+' }).call(aContext|| {})');
  }
  return __parseTemplate__results.join('');
}

var source = <![CDATA[
      大切な事なので3回言います。
      <% for (var i = 0; i < 3; i++) { %>
        今日は<%= today %>です。
      <% } %>
      オーケー?
    ]]>.toString();
var params = {
      today : (new Date()).toString()
    };
var result = parseTemplate(source, params);

レガシーだけどクロスブラウザな書き方だったら、こうか。

function parseTemplate(aCode, aContext) {
  var __parseTemplate__codes = [];
  aCode = aCode.split('%>');
  var strPart, codePart;
  for (var i in aCode) {
    aCode[i] = aCode[i].split('<%');
    strPart = aCode[i][0];
    codePart = aCode[i].length == 1 ? null : aCode[i][1] ;
    __parseTemplate__codes.push('__parseTemplate__results.push(unescape("'+
                                escape(strPart)+
                                '"));');
    if (!codePart) continue;
    if (codePart.charAt(0) == '=') {
      __parseTemplate__codes.push('__parseTemplate__results.push(('+
                                  codePart.substring(1)+
                                  ') || "");');
    }
    else {
      __parseTemplate__codes.push(codePart);
    }
  }
  var __parseTemplate__results = [];
  with(aContext|| {}) {
    eval('(function() { '+__parseTemplate__codes.join('\n')+' }).call(aContext|| {})');
  }
  return __parseTemplate__results.join('');
}

var source = '大切な事なので3回言います。\n'+
             '<% for (var i = 0; i < 3; i++) { %>\n'+
             '  今日は<%= today %>です。\n'+
             '<% } %>\n'+
             'オーケー?';
var params = {
      today : (new Date()).toString()
    };
var result = parseTemplate(source, params);
エントリを編集します。

wikieditish message: Ready to edit this entry.











拡張機能