【问题标题】:Chrome Apps. jQuery.Templates analogsChrome 应用程序。 jQuery.Templates 类似物
【发布时间】:2012-08-02 06:42:13
【问题描述】:

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

所以unsafe-eval 不允许用于script-src 指令。

对于可以使用哪种 JavaScript 模板引擎有什么建议吗?

模板引擎需要什么:

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

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

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

【问题讨论】:

标签: templates google-chrome google-chrome-extension jquery-templates


【解决方案1】:

我只需要一个模板系统并寻找可以与清单版本 2 一起使用的东西并找到了这个....
http://code.google.com/p/json-template/wiki/Reference
...在其代码中没有使用 eval 的地方。不幸的是,我发现如何充分利用它有点困难,而且我自己才刚刚开始研究它,所以我的以下 cmets 可能并不完全正确。
我不使用 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 的。我不能告诉你如何在不修改 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}
      ]);

...我相信您也可以使用谓词来设置变量,但还没有尝试过。 无论如何,绝对值得一看。

【讨论】:

    【解决方案2】:

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

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

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

    如果你已经安装了 NodeJS,你可以使用npm install handlebars -g 尝试它的预编译引擎。 -g 允许您在 FS 的任何项目中使用 handlebars。您可能需要 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>
    

    ma​​in.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}} 循环和自定义助手。我认为非常强大。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 感谢您的回答,但我已经从 JQ 模板迁移到 Handlebars.js =)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-23
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      相关资源
      最近更新 更多