[英]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.