我经常从InDesign导出的HTML文件构建网页。在InDesign中,我可以控制元素class
属性,但是更改DOM结构本身相当困难。而且它输出的DOM并不总是足够的,因此我需要一种转换DOM的方法。
我所采用的方法是在操纵up的实例上运行一组jquery命令,以强制性地调整DOM并将输出的HTML保存到文件中。它变得非常难以维护,很难从代码中分辨出预期的输入和输出。
因此,我正在尝试将nunjucks作为模板引擎来生成输出。但是AFAIK Nunjucks擅长打印以前定义的变量,但不提供任何工具来从HTML块中检索其输入]
我想编写一个带有选择器的模板/宏,这些选择器可以在输入中找到内容,有点像这样:
<section>
<header>
<h2>{% contentFrom(".section-header") %}</h2>
</header>
<main>
{% contentFrom(".content") %}
</main>
</section>
然后将我的输入包裹在一个nunjucks标记中,像这样
{% filter dont_know_yet_what_should_go_in_here }
<p class="section-header">My_header_here</p>
<p class="content">My_contents</p>
{% endfilter}
我想这可以通过nunjucks定制过滤器或定制标签来实现。但是,如果有更好的解决方案,我也将其作为答案!
{% call someMacro() %}
标签中。这样,someMacro()
宏将获得额外奖励:包装的内容可通过caller()
方法在宏内部使用。但是caller()
将整个HTML块作为字符串返回,我仍然需要一种方法来解析它并仅选择我需要的元素。为此,我使用了cheerio以及一些Nunjucks自定义全局变量。
由于无法在Nunjucks模板内运行纯JavaScript,因此在我的gulp设置中,我为cheerio的load()
方法定义了一个别名,并通过全局变量(通常称为$
)将其传递给我的nunjucks环境:
const cheerio = require('cheerio')
function cheer(html, selector) {
var a = cheerio.load(html.toString())
return a(selector)
}
var manageEnvironment = function(environment) {
environment.addGlobal('$', cheer);
} // then pass manageEnvironment to Nunjucks initializer function
然后,在我的模板中,将caller()
分配给一个变量,只是为了使其不那么冗长,然后我可以使用我的函数来选择和修改输入DOM,然后再将其插入到我的模板中:{% macro myComponent() %} {% set a = caller() %} {# Assigned caller to a shorter variable because it'll be repeated a few times #} <section> <header> <h1>{{ $(a, '.box-title').html() }}</h1> </header> <main> {{ $(a, '._obj_box *:not(.box-title)').html() }} </main> <footer style="border: 2px solid red;"> {{ $(a, ".see_more-title").html() | urlize | safe }} </footer> </section> {% endmacro %}
我不知道为什么,但是Nunjucks总是逃避了从$()
方法返回的HTML,即使我使用了safe
过滤器也是如此。由于我拥有完全受控的环境,因此关闭整个Nunjucks渲染的自动转义会更容易。