打印编译后的车把模板(不填写数据)

Print compiled handlebar template (without data filled in)

本文关键字:数据 编译 打印      更新时间:2023-09-26

我正在使用把手编译部分模板。目前,我有以下javascript:

var handlebars = require('handlebars'),
  fs = require('fs');
var data = {
  title: "Print handlebars tempalte",
  author: "Internet",
  body: "Hi, I am the body"
}
fs.readFile('partial.html', 'utf-8', function(error, source) {
  handlebars.registerPartial('example_partial', source);
});
fs.readFile('ignore-keywords.html', 'utf-8', function(error, source) {
  var template = handlebars.compile(source);
  var html = template(data);
  console.log(html)
});

部分如下

<div>
  <p>
    Hi, I am a partial!
  </p>
</div>

模板是

<div class="header">
    <h1>{{title}}</h1>
</div>
<div class="body">
    <p>{{body}}</p>
</div>
<div class="footer">
    <div>
      <p>
        Written by {{author}}
      </p>
    </div>
    {{> example_partial}}
</div>

正如您在脚本中看到的,我可以使用console.log打印最终生成的html。然而,我希望能够打印最终的模板没有填写的数据。像这样:

<div class="header">
    <h1>{{title}}</h1>
</div>
<div class="body">
    <p>{{body}}</p>
</div>
<div class="footer">
    <div>
      <p>
        Written by {{author}}
      </p>
    </div>
    <div>
      <p>
        Hi, I am a partial!
      </p>
    </div>
</div> 

我希望能够打印编译模板,我应该能够然后发送到使用此编译模板的其他来源,用数据填充它,然后生成各自的HTML。正是出于这个目的,我需要生成上面提到的模板。我该如何实现这个目标呢?

编译后的模板不能打印或共享,因为它们是函数。

当您调用handlebars.compile时,它将模板分解为字符串和替换令牌,然后在运行时构建一个函数,该函数将从传入数据中连接字符串和适当的令牌。循环({{#each}})也变成了真正的JS循环。

不幸的是,简单的JSON字符串算法和更健壮的结构化克隆算法都不能序列化函数对象。我不知道有什么可以,尽管一些浏览器确实支持.toString上的函数,将打印源代码。

我想你也许可以解决这个问题。我会尝试替换'ignore-keywords.html'模板中的{{令牌,这样它们就不会被车把评估,但会排除{{>令牌。对部分模板执行相同的操作,然后调用父模板。它应该在不替换任何变量的情况下求值并包含偏导。将转义的标记交换回{{,您就有了一个可以正常编译的模板,但是已经内联了部分。

因为Handlebars是JS,你需要为每个项目/站点/应用添加一个JS文件,这些项目/站点/应用具有全局可访问的函数,这些函数可以从静态位置(已知的web地址)检索模板,然后根据函数参数生成模板。或者使用Node.js之类的东西来基于ajax请求参数构建和返回这些模板。就我个人而言,我会坚持前者,因为它只需要在你想要的任何应用程序中嵌入一个JS文件。

基于@ ssubbe的回答,它给了我这个想法,这就是我如何去做的。

只包含下面的相关代码。我的用例是,我需要实际生成带有数据的模板来测试,并且生成带有完整标签的最终.hbs,以便我们的团队将其上传到单独的服务。我将每个部分都放在partials目录中,并将启动该进程的主文件称为tamplate.hbs

所以基本上使用逻辑@ ssubbe提到我们只是做一个简单的替换所有的{{与另一个字符(我选择了插入符号^)。当然,我们不想替换我们的导入,所以我们忽略了模式{{> .

然后我们在没有数据的情况下运行模板,它将所有模板拉到一起,然后我们返回并将^替换为{{。注意,为了方便起见,我们不需要替换结尾的}},因为Handlebars会忽略它们,如果它们没有起始块。

function compileTemplate() {
    // register partials
    const partials = fs.readdirSync('/partials');
    partials.forEach(partial => {
        const partialName = partial.split('.')[0];
        const partialOutput =  fs.readFileSync(`/partials/${partial}`, 'utf8');
        // Strip out the handlebar tags so we can give the templating service an export with template strings intact
        // However we still want to pull in our partials so we ignore {{>. We replace all other {{ with ^ for now.
        const partialTemp = partialOutput.replace(/{{(?!>)/g, '^');
        // Register our exported partial for use.
        Handlebars.registerPartial(`${partialName}`, partialTemp);
    });
    // create the template object
    const templateStr = fs.readFileSync('/template.hbs', 'utf8');
    const exportTemplate = Handlebars.compile(templateStr);
    let exportTemplateOutput = exportTemplate();
    // Now add the {{ back we removed earlier.
    exportTemplateOutput = exportTemplateOutput.replace(/'^/g, '{{');
    fs.writeFileSync('exported/export.hbs', exportTemplateOutput, err => {
        if(err) {
            console.err(err);
        }
    });
}