Хорошо, я решил это!
В Nunjucks можно обернуть немного html в тег {% call someMacro() %}
. Таким образом, макрос someMacro()
вызывается с бонусом: упакованный контент можно использовать внутри макроса с помощью метода caller()
.
Но caller()
возвращает весь кусок HTML в виде строки и мне все еще нужен способ разобрать его и выбрать только те элементы, которые мне нужны. Для этого я использовал cheerio вместе с некоторыми пользовательскими глобальными значениями Nunjucks.
Поскольку в шаблонах Nunjucks невозможно запустить чистый javascript, в моей настройке gulp я определил псевдоним cheerio's 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.