简体   繁体   English

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

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

I frequently build webpages from InDesign exported HTML files.我经常从 InDesign 导出的 HTML 文件构建网页。 And in InDesign I have some control over the elements class attribute, but it is rather difficult to change the DOM structure itself.在 InDesign 中,我对元素的class属性有一些控制,但是改变 DOM 结构本身是相当困难的。 And it is not always sufficient to go with the DOM it outputs so I need a way to transform the DOM. go 与它输出的 DOM 并不总是足够的,所以我需要一种方法来转换 DOM。

The approach I had was to run a set of jquery commands on a puppeteer instance to imperatively shape the DOM and save the output HTML to a file.我的方法是在 puppeteer 实例上运行一组 jquery 命令以强制塑造 DOM 并将 output HTML 保存到文件中。 It became quite unmaintainable and it's very hard to tell from the code what are the expected input and output.它变得非常难以维护,并且很难从代码中分辨出预期的输入和 output 是什么。

So I'm trying nunjucks as a template engine to generate the output.所以我正在尝试将 nunjucks 作为模板引擎来生成 output。 But AFAIK Nunjucks is good at printing previously defined variables, but doesn't provide any tools to retrieve its input from a HTML block但是 AFAIK Nunjucks 擅长打印先前定义的变量,但不提供任何工具来从 HTML 块检索其输入

I want to write a template/macro with selectors that find the content in the input, kinda like this:我想用在输入中找到内容的选择器编写一个模板/宏,有点像这样:

<section>
    <header>
        <h2>{% contentFrom(".section-header") %}</h2>
    </header>
    <main>
        {% contentFrom(".content") %}
    </main>
</section>

And then just wrap my input in a nunjucks tag, like this然后将我的输入包装在一个 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}

I imagine this could be possible with nunjucks custom filters or custom tags.我想这可以通过 nunjucks 自定义过滤器或自定义标签来实现。 But if there is a much better solution, I'll accept that as an answer as well!但是,如果有更好的解决方案,我也会接受它作为答案!

Ok, I solved it!好的,我解决了!

In Nunjucks, one can wrap some html in a {% call someMacro() %} tag.在 Nunjucks 中,可以将一些 html 包装在{% call someMacro() %}标签中。 This way, the someMacro() macro gets called with a bonus: The wrapped content can be used inside the macro through the caller() method.这样, someMacro()宏被调用时有一个好处:可以通过caller()方法在宏内部使用包装的内容。

But caller() returns the whole HTML chunk as a string, and I still need a way to parse it and pick only the elements I need.但是caller()将整个 HTML 块作为字符串返回,我仍然需要一种方法来解析它并只选择我需要的元素。 For that, I used cheerio along with some Nunjucks custom globals.为此,我使用了Cheerio和一些 Nunjucks 自定义全局变量。

Since one can't run pure javascript inside Nunjucks templates, in my gulp setup, I defined an alias to cheerio's load() method and passed it to my nunjucks environment via a global variable (conveniently called $ ):由于无法在 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

Then, in my template, I assign caller() to a variable, just to make it less verbose, and then I can use my function to select and modify the input DOM before it gets inserted into my template:然后,在我的模板中,我将caller()分配给一个变量,以使其不那么冗长,然后我可以使用我的 function 到 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 %}

Importante note: I don't know why, but Nunjucks always escaped the HTML returned from my $() method, even when I used the safe filter.重要提示:我不知道为什么,但 Nunjucks 总是逃避从我的$()方法返回的 HTML,即使我使用了safe过滤器。 Since I have a fully controlled environment, It was easier just to turn off auto escaping for the whole Nunjucks rendering.由于我有一个完全受控的环境,因此关闭自动 escaping 以进行整个 Nunjucks 渲染会更容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有一种方法可以将字符串从JSON转换为DOM结构? - Is there a way to transform a string from JSON into a DOM structure? 如何将json结构转换为另一个 - How to transform a json structure into another 在jQuery中更改此DOM结构的有效方法 - An efficient way to change this DOM structure in jQuery 是否有可能读取另一个网址的dom结构? - Is it possible to read another url's dom structure? 将一种数据结构转换为另一种数据结构JavaScript / TypeScript - Transform one data structure into another data structure JavaScript/TypeScript 转换/移动大量 DOM 元素的最高效方法 - Most performant way to transform/move large number of DOM elements Javascript函数-从一种数据结构转换为另一种数据结构 - Javascript function- transform from one data structure to another 有没有办法使用 Nunjucks 过滤器提取属性? - Is there a way to extract an attribute using a Nunjucks filter? 将具有特定结构的列表转换为对象列表的最佳方法 - Best way to transform a list with a specific structure into a list of objects 如何&#39;将对象解析并转换为具有不同“键/值”结构的另一个对象 - How to 'Parse and Transform an Object into another Object with different “key/value” structure'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM