2

JavaScriptオブジェクトからHTMLコードを生成するprototype.jsテンプレートがある場合、HTMLが壊れないように、JavaScriptオブジェクトのデータ内のHTMLエンティティを自動的にエスケープするにはどうすればよいですか?

サンプルJavaScriptコード:

var data = {
    name: 'Josh',
    url: 'http://josh.gitlin.name/',
    statement: 'I\'m a JavaScript and PHP developer. Find me on Stack Overflow and say "hi"!'
}

var template = new Template(
    '<div><label>Name: <input name=\"name\" value=\"#{name}\"></label></div>'+
    '<div><label>URL: <input name=\"url\" value=\"#{url}\"></label></div>'+
    '<div><label>Personal Statement: <input name=\"statement\" value=\"#{statement}\"></label></div>'
);

$('test').update(template.evaluate(data));

上記のJSFiddleコード

上記のコードでは、引用符が含まれている<input>ため、不正な形式のタグが生成されます。オブジェクトを変更したり、オブジェクトのクローンを作成したりせずに、上記の例でHTMLエンティティを自動的にエスケープするにはどうすればよいですか?</ p> data.statement"Templatedatadata

4

2 に答える 2

1

これを行うには、次の 2 つのことを行う必要があります。

  1. クラスのescapeメソッドは、TemplateHTML エンティティをエスケープすることを知っている必要があります
  2. escapeHTMLPrototype.js がStringオブジェクトに追加するメソッドは、引用符を&quot;エンティティにエンコードするように拡張する必要があります。(そしておそらくもっと。は単純すぎる...)

これら 2 つの両方は、次のコードで実現できます。

String.prototype.escapeHTML = String.prototype.escapeHTML.wrap(function(proceed){
    return proceed().replace(/"/g,'&quot;');
});

Template.addMethods({
    evaluateEscapeHTML: function(object) {
        if (object && Object.isFunction(object.toTemplateReplacements))
          object = object.toTemplateReplacements();

        return this.template.gsub(this.pattern, function(match) {
          if (object == null) return (match[1] + '');

          var before = match[1] || '';
          if (before == '\\') return match[2];

          var ctx = object, expr = match[3],
              pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;

          match = pattern.exec(expr);
          if (match == null) return before;

          while (match != null) {
            var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
            ctx = ctx[comp];
            if (null == ctx || '' == match[3]) break;
            expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
            match = pattern.exec(expr);
          }

          return before + String.interpret(ctx).escapeHTML();
        });
    }
});

evaluateEscapeHTMLこのコードは Prototype.js を拡張し、新しいメソッドを Templatesに追加するため、このコードは1 回実行する必要があり、それ以降はすべてTemplate新しいevaluateEscapeHTMLメソッドになります。

var template = new Template(
    '<div><label>Name: <input name=\"name\" value=\"#{name}\"></label></div>'+
    '<div><label>URL: <input name=\"url\" value=\"#{url}\"></label></div>'+
    '<div><label>Personal Statement: <input name=\"statement\" value=\"#{statement}\"></label></div>'
);

$('test').update(template.evaluate(data));

これをテストする JSFiddle

ここでは、prototype.js バージョン 1.7 のクラスからメソッド全体を複製する必要があったことに注意してください。これには、メソッドの将来のバージョンが改善された場合、私のコードも改善する必要があるという大きな欠点があります。しかし、これを行うためのより良い方法を見つけることができませんでした。 evaluateTemplateevaluate

evaluate私が行ったメソッドへの特定の変更は、この行を変更することでした:

return before + String.interpret(ctx);

に:

return before + String.interpret(ctx).escapeHTML();

extendそれがすべてです。そのため、コードの残りの部分を何とかできなかったのはとても残念wrapです...

于 2012-07-19T19:57:01.110 に答える
1

ソース コードを読むと、HTML をエスケープするテンプレートには何もありません。さらに、String#escapeHTML正規表現 (wtf2) でタグ (wtf) を削除しようとし、引用符もエスケープしないため、提供されたものはかなりひどいものです。

これで文字列を手動でエスケープできます:

function escapeHTML(text) {
    var map = {
        "&" : "amp",
        "'": "#39",
        '"': "quot",
        "<": "lt",
        ">": "gt"

    };

    return text.replace( /[&'"<>]/g, function(m) {
        return "&" + map[m] + ";";
    });
}
于 2012-07-19T19:58:06.250 に答える