【问题标题】:Is there a way to use nunjucks to transform a DOM structure into another?有没有办法使用 nunjucks 将 DOM 结构转换为另一个结构?
【发布时间】:2020-08-16 21:35:52
【问题描述】:

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

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

【问题讨论】:

    标签: javascript dom nunjucks templating-engine


    【解决方案1】:

    好的,我解决了!

    在 Nunjucks 中,可以将一些 html 包装在 {% 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 渲染的自动转义会更容易。

    【讨论】:

      猜你喜欢
      • 2011-01-10
      • 1970-01-01
      • 2011-04-08
      • 2023-03-16
      • 2011-01-17
      • 1970-01-01
      • 2020-08-03
      • 2021-05-21
      • 1970-01-01
      相关资源
      最近更新 更多