我想遍历cheerio实例并装饰过程中的特定文本元素。
例如,我有一个类似这样的html:
<html>
<p>
{{#default name "Customer"}}
</p>
</html>
我要替换为:
<html>
<p>
{{#default <span class="editor-var">name</span> "Customer"}}
</p>
</html>
我可以通过编写的自定义访问者实现此目标:
var contentVars = ['name', 'age'];
var BLOCK_EXPRESSION_REGEX = /[{][{]#(.*)[}][}]/gm;
var contentVarsRegex = new RegExp(_.join(_.map(myVars, _.escapeRegExp), '|'), 'g');
var decorator = function decorator(key) {
return `<span class="editor-var">${key}</span>`;
};
var visitText = function visitText(node) {
$(node).replaceWith(_.chain([node.data || '']).map(function (html) {
return html.replace(contentVarsRegex, decorator);
}).map(function (html) {
return !_.isEmpty(contentVars) ? html.replace(BLOCK_EXPRESSION_REGEX, function (full, _g1) {
return '{{#' + _g1.replace(contentVarsRegex, decorator) + '}}';
}) : html;
}).head().value());
};
var visit = function visit(node) {
if (node.type === 'text') visitText(node);
_.get(node, 'children', []).forEach(function (node, i) {
if (node.type === 'text') visitText(node);
visit(node);
});
};
visit($.root()[0]);
var result = $.html().toString();
上述解决方案的问题在于它无法处理我的内容中的更多表达式集。
因为当我的装饰器用span
元素替换任何节点时,在该特定节点附近又创建了两个节点。确切地说,我在子节点_.get(node, 'children', []).forEach
上进行迭代的地方,迭代没有考虑在过程中添加的新节点。因此,假设最初该节点中的子节点数为80,即使该节点中添加了更多的节点,遍历也会在80次迭代后停止。
因此,也许我在做一件简单的事情时需要做很多逻辑工作,但是我真的在Cheerio文档中找不到任何可以为我做的功能。 如果有人在这方面有经验,可以推荐一些更好的方法或帮助我解决这个问题,将不胜感激。谢谢!