0

我在我的 chrome 应用程序中使用 jQuery.Template,但几天前 Chrome 更新了 Chrome 浏览器和 Chrome 网上应用店,现在manifest_version:1如果我想在网上应用店中发布我的扩展程序,我无法使用。从桌面安装应用程序也已被禁用。所以我必须使用manifest_version:2,但是script-src 'unsafe-eval'在 jQuery.Templates 中使用了一些麻烦。

所以指令unsafe-eval是不允许的。script-src

关于可以使用哪个 JavaScript 模板引擎的任何建议?

我需要模板引擎:

  • 没有任何new Function()eval()使用。
  • 像 jQuery.Templates 中的简单数据访问:${my_variable}
  • 内联逻辑为:{{if a==b}} ... {{else b == c}} ... {{/if}}
  • 可能正在为变量设置值,但不一定:${my_variable = 123, ''}
  • 它必须像一个插件(不是框架,我不会重写我的应用程序)。

注意:不,我不会使用沙盒页面,我认为这是非常丑陋的解决方案。

更新:感谢您的回答。我选择 Handlebars.js 作为主模板引擎

4

3 回答 3

0

我只需要一个模板系统并寻找可以与清单版本 2 一起使用的东西并找到了这个....
http://code.google.com/p/json-template/wiki/Reference
...在其中没有代码是否使用 eval。不幸的是,我发现如何充分利用它有点困难,而且我自己才刚刚开始研究它,所以我下面的评论可能并不完全正确。
我不使用 JQuery 所以不能真正比较,但我认为它会做你想要的,主要是。
它不会使用 jquery 之类的脚本标签来执行内联代码,但这很容易做到。我写得很快,让我可以使用内联模板......

jsontemplate.inlineSCRIPT = function(source,templateoptions) {
    var templates = source.querySelectorAll('script[type="text/json-template"]');
    for (var i = 0; i < templates.length; i++) {

        var template = templates[i];

        var options = JSON.parse(template.getAttribute('options'));

        if (!options.object) continue;

        var sourceObjectBits = options.object.split('.');

        var sourceObject = window[sourceObjectBits[0]];

        for (var i = 1; i < sourceObjectBits.length; i++) {
            if (!sourceObject[sourceObjectBits[i]]) break;
            sourceObject = sourceObject[sourceObjectBits[i]];
        }

        if (i != sourceObjectBits.length) continue;

        var target;
        if (options.target) {
            options.target == 'self' ? target = template : target = document.querySelector(options.target);
        } else {
            target = template;
        }

        if (!target) continue;

        if (options.innerOuter) {
            options.innerOuter == 'inner' ? target.innerHTML = jsontemplate.expand(template.innerHTML, sourceObject,templateoptions) : target.outerHTML = jsontemplate.expand(template.innerHTML, sourceObject,templateoptions);
        } else {
            target.outerHTML = jsontemplate.expand(template.innerHTML, sourceObject,templateoptions);
        }
    }
}

....然后在我的html中我可以...

<script type='text/json-template' options='{"object":"a.b.details"}'>
    {# This is a comment and will be removed from the output.}
    {.section songs}
      {.repeated section @}
        {.if equals test title}
          test equaled title
        {.end}
      {.end}
    {.or}
    <p><em>(No page content matches)</em></p>
    {.end}
</script>

模板有一些条件,但它们非常基本,比如 if variable = true then do this。但是如果变量等于变量执行此操作,我找不到任何东西。您可以使用自定义谓词添加它们,但我还没有想出如何在不更改 jsontemplate 源的情况下添加一个带参数的谓词......我相信你可以,我只是还没想出如何去做。如果您确实添加了谓词,您应该能够满足您想要的条件,但模板中的语法看起来不太好。我添加了一个 if equals ,模板的源代码如下所示......

{.if equals test title}
  test equaled title
{.end}

...这意味着,如果变量 test 的值等于 title 的值,则执行此块,然后您可以将 or 块和更多 ifs 用于 else's。我不能告诉你如何在不修改 jsontemplate 源的情况下添加一个,但这里是如何做到这一点的方法......
在函数function _Pluralize(value, unused_context, args) {第 76 行之后添加另一个函数,比如......

// Are two variables equal, gotta add the error checking
function _Mine(value, context, args) {
  var s, p;
  switch (args.length) {
    case 0:
      s = value;
      break;
    case 1:
       s = context.get(args[0]);
      break;
    case 2:
      s = context.get(args[0])==context.get(args[1]);
      break;
    default:
      // Should have been checked at compile time
      throw {
        name: 'EvaluationError', message: 'pluralize got too many args'
      };
  }
  return s;
}

..然后在编译函数中function _Compile(template_str, options) {查找该行var default_predicates = PrefixRegistry([(就在函数声明下方)并添加您的行,例如....

  // default predicates with arguments
  var default_predicates = PrefixRegistry([
    {name: 'equals', func: _Mine},
    {name: 'test', func: _TestAttribute}
      ]);

...我确定您也可以使用谓词来设置变量,但还没有尝试过。总之,绝对值得一看。

于 2012-08-02T17:39:27.397 回答
0

非常感谢您的详细回答,但我为我找到了更优雅的解决方案:Handlebars.js。

它具有模板的预编译引擎,如果使用预编译的模板则不使用eval()。它有非常简单的内联逻辑(我只是可以检查该变量的真假),但速度非常快。=) 你应该试试比较。一瞬间:它使用 NodeJS 进行预编译。如果您不需要它,则只需使用Handlebars.compile().

注意:manifest_version: 2必须使用预编译。如果您尝试使用Handlebars.compile(),您将收到有关 CSP 违规的错误。

如果你已经安装了 NodeJS,你可以尝试使用它的预编译引擎npm install handlebars -g-g允许您handlebars在 FS 的任何项目中使用。您可能需要 sudo 此命令。接下来重新加载您的终端和 cd 到包含模板文件的文件夹。

您需要将它们迁移到 Handlebars.js 语法并.handlebars为每个文件添加扩展名。然后运行handlebars path/to/templates/*.handlebars -f js/templates.js

如果你在 Handlebars.js 之后加载这个 js 文件,你应该在这里找到已编译的模板:

Handlebars.templates[your_template_file_name]

例如:

my_template.handlebars

<div>{{testing_template}}</div>

main.js

// example with RequreJS
require(["handlebars", "templates"], function(){
    var template = Handlebars.templates.my_template,
        rendered = template({
            "testing_template" : "some text right here"
        });

    console.log(rendered);
});

在控制台中,您会看到:

> "<div>some text right here</div>"

Handlebars.js 支持简单{{#if}}{{#unless}}块以及{{#each}}循环和自定义助手。我认为非常强大。

于 2012-08-03T03:31:26.700 回答
0

我对此进行了一些研究,对我来说,最快的方法就是编写一些自定义函数来替换 jQuery 模板的功能。

于 2012-08-09T08:42:46.060 回答