如何从DOM查询文本节点,查找markdown模式,将匹配项替换为HTML标记以及将原始文本节点替换为新内容? [英] How to query text-nodes from DOM, find markdown-patterns, replace matches with HTML-markup and replace the original text-node with the new content?

查看:57
本文介绍了如何从DOM查询文本节点,查找markdown模式,将匹配项替换为HTML标记以及将原始文本节点替换为新内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要使用Vanilla JavaScript:

Using Vanilla JavaScript I want to:

更改此:

<div>
   <p>
        Hello [world]{big round planet we live on}, how is it [going]{verb that means walking}? 
   </p>
   <p>
        It is [fine]{a word that expresses gratitude}.
   </p>
</div> 

对此:

<div>
    <p>
        Hello <mark data-toggle="tooltip" data-placement="top" title="big round planet we live on">world</mark>, how is it <mark data-toggle="tooltip" data-placement="top" title="verb means walking">world</mark>?
    </p>
    <p>
        It is fine <mark data-toggle="tooltip" data-placement="top" title="a word that expresses gratitude">thanks</mark>.
    </p>
</div> 

所以它看起来像这样:

在某种程度上类似于"markdown",编辑功能.

is somehow similar to "markdown" edit functionalities.

  1. 标记字符串以其他方式替换:

<p>It is fine *[thanks]{a word that expresses gratitude}*!</p>

  1. 启动Bootstrap和工具提示功能.
  2. 抓取所有段落

var p = document.getElementsByTagName('p')

  1. 应用正则表达式

tooltip = original.match(/(\{)(.*?)(\})/gi)[0].slice(1, -1);
hint = original.match(/(\[)(.*?)(\])/gi)[0].slice(1, -1);

  1. 更改其内部文字

replaced = original.replace(/(\*)(.*?)(\*)/gi, 
        `<mark data-toggle="tooltip" data-placement="top" title="${tooltip}">${hint}</mark>`);
elem.innerHTML = replaced;

  1. 全部集中在一个功能中:

[].forEach.call(p, elem => {
    let original = elem.innerHTML;
    let replaced, tooltip, hint
    tooltip = original.match(/(\{)(.*?)(\})/gi)[0].slice(1, -1);
    hint = original.match(/(\[)(.*?)(\])/gi)[0].slice(1, -1);
    replaced = original.replace(/(\*)(.*?)(\*)/gi, 
        `<mark data-toggle="tooltip" data-placement="top" title="${tooltip}">${hint}</mark>`);
      elem.innerHTML = replaced;
});

但我失败了

当有更多段落时,或者当我只想用2对方括号(而不是附加的星号)以简单的方式完成操作时,就很糟糕.如果innerTEXT具有更多应具有工具提示的短语/单词,也将失败.有任何想法吗?你有什么建议吗?现有的做法吗?图书馆?脚本?

but I fail

Miserable when there is more paragraphs or when I just want to do it in an easy way with 2 pair of brackets instead of additional asterix. Fails also hen the innerTEXT has more phrases / words that should have the tooltip. Any ideas? Do you have any suggestions? Existing ways of doing it? Libraries? Scripts?

推荐答案

一个很容易会发现如何用其他未知HTML内容替换文本节点的正确方法.

One very easily can stumble at coming up with the right approach of how to replace a text node with other unknown HTML content.

通用解决方案考虑了更复杂的HTML内容.

A generic solution takes into account a more complex HTML content.

因此,从源节点开始,逐步需要在目标文本节点之前插入其每个子节点(文本节点或元素节点).插入所有节点后,最后一个将目标文本节点删除.

Thus, starting from a source-node, one stepwise needs to insert each of its child-nodes (either text- or element-nodes) before the targeted text-node. Once all nodes got inserted, one finally removes the targeted text-node.

关于 regex和标记模板,可以在其中创建标记字符串来自单个正则表达式和单个正则表达式的单个 replace 调用模板字符串都使用捕获组 .

Regarding the regex and the markup template, one can create the markup-string within a single replace call from a single regex and a single template string both making use of Capturing Groups.

// text node detection helper
function isNonEmptyTextNode(node) {
  return (
       (node.nodeType === 3)
    && (node.nodeValue.trim() !== '')
    && (node.parentNode.tagName.toLowerCase() !== 'script')
  );
}

// text node reducer functionality
function collectNonEmptyTextNode(list, node) {
  if (isNonEmptyTextNode(node)) {
    list.push(node);
  }
  return list;
}
function collectTextNodeList(list, elmNode) {
  return Array.from(
    elmNode.childNodes
  ).reduce(
    collectNonEmptyTextNode,
    list
  );
}

// final dom render function
function replaceTargetNodeWithSourceNodeContent(targetNode, sourceNode) {
  const parentNode = targetNode.parentNode;

  Array.from(sourceNode.childNodes).forEach(function (node) {
    parentNode.insertBefore(node, targetNode);
  });
  parentNode.removeChild(targetNode);    
}

// template and dom fragment render function
function findMarkdownCreateMarkupAndReplaceTextNode(node) {
  const regX = (/\[([^\]]+)\]\{([^\}]+)\}/g);
  const text = node.nodeValue;

  if (regX.test(text)) {
    const template = '<mark data-toggle="tooltip" data-placement="top" title="$2">$1</mark>'

    const renderNode = document.createElement('div');
    renderNode.innerHTML = text.replace(regX, template);

    replaceTargetNodeWithSourceNodeContent(node, renderNode);
  }
}


const elementNodeList = Array.from(document.body.getElementsByTagName('*'));

const textNodeList = elementNodeList.reduce(collectTextNodeList, []);

textNodeList.forEach(findMarkdownCreateMarkupAndReplaceTextNode);

.as-console-wrapper { min-height: 100%!important; top: 0; }

<div>
  <p>
    <span>Hello [world]{big round planet we live on}, how is it [going]{verb that means walking}?</span>
    <span>Hello [world]{big round planet we live on}, how is it [going]{verb that means walking}?</span>
  </p>
  <p>
    <span>It is [fine]{a word that expresses gratitude}.</span>
    It is [fine]{a word that expresses gratitude}.
    <span>It is [fine]{a word that expresses gratitude}.</span>
  </p>
</div>
<!--

  // does get rerendered into:

  <div>
    <p>
      <span>
        Hello
        <mark data-toggle="tooltip" data-placement="top" title="big round planet we live on">
          world
        </mark>
        , how is it
        <mark data-toggle="tooltip" data-placement="top" title="verb that means walking">
          going
        </mark>
        ?
      </span>
      <span>
        Hello
        <mark data-toggle="tooltip" data-placement="top" title="big round planet we live on">
          world
        </mark>
        , how is it
        <mark data-toggle="tooltip" data-placement="top" title="verb that means walking">
          going
        </mark>
        ?
      </span>
    </p>
    <p>
      <span>
        It is
        <mark data-toggle="tooltip" data-placement="top" title="a word that expresses gratitude">
          fine
        </mark>
        .
      </span>
      It is
      <mark data-toggle="tooltip" data-placement="top" title="a word that expresses gratitude">
        fine
      </mark>
      .
      <span>
        It is
        <mark data-toggle="tooltip" data-placement="top" title="a word that expresses gratitude">
          fine
        </mark>
        .
      </span>
    </p>
  </div>

//-->

这篇关于如何从DOM查询文本节点,查找markdown模式,将匹配项替换为HTML标记以及将原始文本节点替换为新内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆