通过可变的cheerio实例正确进行迭代

时间:2019-01-24 11:24:51

标签: javascript jquery node.js cheerio

我想遍历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文档中找不到任何可以为我做的功能。 如果有人在这方面有经验,可以推荐一些更好的方法或帮助我解决这个问题,将不胜感激。谢谢!

0 个答案:

没有答案