8

是否有一个模板引擎可以解析ES6 模板文字(例如"string ${var}")样式的模板,而不会违反脚本评估的内容安全策略 (CSP) 限制?

CSP 对脚本评估的限制阻止eval限制、new Function和.setTimeout(string)setInterval(string)

有许多模板引擎可以提供或修改以提供类似 ES6 样式的模板文字,例如 John Resig 的MicroTemplates、 lodash _.template 和DoT.js。然而,所有似乎都违反了 CSP 使用new Function.

如果var可以是不受限制的 Javascript,在某些方面会很方便,但由于明显的原因,这可能是不可能的。但是,我需要能够修改引擎以根据需要格式化输出。

在这种情况下,性能不是问题,并且预编译模板不是一种选择。其他人有讨论了预编译

作为附加限制,内容是文本,而不是 HTML。因此,我认为 Knockout 或 PURE 等面向 DOM 的模板引擎不会有效地工作。

我的第一个想法是从mustache.js开始并从那里修改它(即更改mustache.tags = ['${', '}']DIY 解决方案,但我会很感激有关该主题的任何想法,因为似乎很少有关于 CSP 和模板的讨论.

4

2 回答 2

1

Micromustache库正是这样做的。版本 6 支持设置自定义打开和关闭标记(${and}而不是{{and }}),这使其更像是模板文字的直接替代品。

于 2019-03-06T17:19:25.833 回答
1

如果您只需要键值替换,您可以使用一个简单的函数,例如我在下面提供的 templateReplace。不涉及 eval,只有正则表达式。

如果您需要包含“不受限制的 javascript”,则具有类似的内容${[1,2,3].join(', ')},正如您所承认的,您显然需要一个违反您的 CSP 政策的解决方案。

var templateReplace = function(html, data, keyTemplate) {
  if (!keyTemplate || typeof keyTemplate !== 'string' || keyTemplate.indexOf('key') === -1) {
    keyTemplate = '{{key}}';
  }
  return (Object.keys(data) || []).reduce(function(html, key) {
    var val = (data[key] !== undefined) ? data[key] : '';
    return html.replace(new RegExp(keyTemplate.replace('key', key), 'gi'), val);
  }, html);
};

// demo 1, using {{key}} syntax
(function() {
  var li = [{ text: 'one' }, { text: 'two' }, { text: 'three' }].map(function(d) {
    return templateReplace( '<li>Item: {{text}}</li>', d);
  });
  document.querySelector('#result1').innerHTML = li.join('\n')
}())

// demo 2, using ${key} syntax
(function() {
  var helloWorld = templateReplace('${hello} ${world}', { hello: 'Hello', world: 'World!' }, '\\${key}');
  document.querySelector('#result2').innerHTML = helloWorld;
}())
demo 1 - {{key}} syntax
<div id="result1"></div>

demo 2 - ${key} syntax
<div id="result2"></div>

于 2015-08-18T14:02:10.203 回答