有没有办法使用 nunjucks 将 DOM 结构转换为另一个结构?

Is there a way to use nunjucks to transform a DOM structure into another?

我经常从 InDesign 导出的 HTML 文件构建网页。在 InDesign 中,我对元素的 class 属性有一些控制,但很难更改 DOM 结构本身。 而且它输出的 DOM 并不总是足够的,所以我需要一种方法来转换 DOM.

我采用的方法是 运行 一组 jquery 人偶实例上的命令来强制塑造 DOM 并将输出 HTML 保存到文件.它变得非常难以维护,很难从代码中判断出预期的输入和输出是什么。

所以我正在尝试将 nunjucks 作为模板引擎来生成输出。但是 AFAIK Nunjucks 擅长打印先前定义的变量,但不提供任何工具来从 HTML 块

中检索其输入

我想写一个 template/macro 带有选择器的选择器,可以在输入中找到内容,有点像这样:

<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 自定义过滤器或自定义标签实现。但如果有更好的解决方案,我也会接受它作为答案!

好的,我解决了!

在 Nunjucks 中,可以将一些 html 包裹在 {% call someMacro() %} 标签中。这样,调用 someMacro() 宏有一个好处:包装的内容可以通过 caller() 方法在宏内部使用。

但是 caller() returns 整个 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() 分配给一个变量,只是为了让它不那么冗长,然后我可以使用我的函数 select 并修改输入 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 渲染的自动转义。