整个单词的正则表达式匹配和在JavaScript中创建超链接。

huangapple go评论72阅读模式
英文:

Whole word regex matching and hyperlinking in Javascript

问题

我需要一点正则表达式的帮助。

我正在使用JavaScript和JQuery来在HTML文档中创建超链接术语,为此我正在使用以下代码。我正在为大量文档中的多个术语执行此操作。

var searchterm = "Water";

jQuery('#content p').each(function() {
  
  var content = jQuery(this),
      txt = content.html(),
      found = content.find(searchterm).length,
      regex = new RegExp('(' + searchterm + ')(?![^(<a.*?>).*?</a>))','gi');

  if (found != -1) {
    //超链接搜索词
    txt = txt.replace(regex, '<a href="/somelink">$1</a>');
    content.html(txt);
  }
});

然而,有一些情况我不想匹配,由于时间限制和思维混乱,我寻求一些帮助。

编辑:我已根据@ggorlen提供的出色示例更新了下面的codepen链接,谢谢!

示例:https://codepen.io/julian-young/pen/KKwyZMr

英文:

I need a little help with Regular Expressions.

I'm using Javascript and JQuery to hyperlink terms within an HTML document, to do this I'm using the following code. I'm doing this for a number of terms in a massive document.

var searchterm = &quot;Water&quot;;

jQuery(&#39;#content p&#39;).each(function() {
  
  var content = jQuery(this),
      txt = content.html(),
      found = content.find(searchterm).length,
      regex = new RegExp(&#39;(&#39; + searchterm + &#39;)(?![^(&lt;a.*?&gt;).]*?&lt;\/a&gt;)&#39;,&#39;gi&#39;);

  if (found != -1) {
    //hyperlink the search term
    txt = txt.replace(regex, &#39;&lt;a href=&quot;/somelink&quot;&gt;$1&lt;/a&gt;&#39;);
    content.html(txt);
  }
});

There are however a number of instances I do not want to match and due to time constraints and brain melt, I'm reaching out for some assistance.


EDIT: I've updated the codepen below based on the excellent example provided by @ggorlen, thank you!

Example https://codepen.io/julian-young/pen/KKwyZMr

答案1

得分: 2

以下是您要翻译的内容:

将整个DOM转储为原始文本并使用正则表达式解析它,绕过了jQuery(以及JS)的主要目的,即将DOM视为节点的抽象树来遍历和操作。

文本节点具有 nodeType Node.TEXT_NODE,我们可以在遍历中使用它来识别您感兴趣的非链接节点。

获得文本节点后,可以适当地应用正则表达式(解析文本,而不是HTML)。我在演示中使用了 <mark>,但您可以将其更改为锚标签或您需要的任何内容。

jQuery 提供了 replaceWith 方法,可以在进行所需的正则表达式替换后替换节点的内容。

您可以在不使用jQuery的情况下应用于文档中的所有内容:

英文:

Dumping the entire DOM to raw text and parsing it with regex circumvents the primary purpose of jQuery (and JS, by extension), which is to traverse and manipulate the DOM as an abstract tree of nodes.

Text nodes have a nodeType Node.TEXT_NODE which we can use in a traversal to identify the non-link nodes you're interested in.

After obtaining a text node, regex can be applied appropriately (parsing text, not HTML). I used &lt;mark&gt; for demonstration purposes, but you can make this an anchor tag or whatever you need.

jQuery gives you a replaceWith method that replaces the content of a node after you've made the desired regex substitution.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

$(&#39;#content li&#39;).contents().each(function () {
  if (this.nodeType === Node.TEXT_NODE) {    
    var pattern = /(\b[Ww]aters?(?!-)\b)/g;
    var replacement = &#39;&lt;mark&gt;$1&lt;/mark&gt;&#39;;
    $(this).replaceWith(this.nodeValue.replace(pattern, replacement));
  }
});

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;h1&gt;Example Content&lt;/h1&gt;
&lt;div id=&quot;content&quot;&gt;
  &lt;ul&gt;
    &lt;li&gt;Water is a fascinating subject. - &lt;strong&gt;match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;We all love water. - &lt;strong&gt;match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;ice; water; steam - &lt;strong&gt;match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;The beautiful waters of the world - &lt;strong&gt;match&lt;/strong&gt; (including the s)&lt;/li&gt;
    &lt;li&gt;and all other water-related subjects - &lt;strong&gt;no match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;and this watery topic of - &lt;strong&gt;no match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;of WaterStewardship looks at how best - &lt;strong&gt;no match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;On the topic of &lt;a href=&quot;/governance&quot;&gt;water governance&lt;/a&gt; - &lt;strong&gt;no match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;and other &lt;a href=&quot;/water&quot;&gt;water&lt;/a&gt; related things - &lt;strong&gt;no match&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;the best of &lt;a href=&quot;/allthingswater&quot;&gt;all things water&lt;/a&gt; - &lt;strong&gt;no match&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

<!-- end snippet -->

You can do it without jQ and apply to everything in the document:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

for (const parent of document.querySelectorAll(&quot;body *:not(a)&quot;)) {
  for (const child of parent.childNodes) {
    if (child.nodeType === Node.TEXT_NODE) {
      const pattern = /(\b[Ww]aters?(?!-)\b)/g;
      const replacement = &quot;&lt;mark&gt;$1&lt;/mark&gt;&quot;;
      const subNode = document.createElement(&quot;span&quot;);
      subNode.innerHTML = child.textContent.replace(pattern, replacement);
      parent.insertBefore(subNode, child);
      parent.removeChild(child);
    }    
  }
}

<!-- language: lang-html -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;div&gt;
  hello water
  &lt;div&gt;
    &lt;div&gt;
      I love Water.
      &lt;a href=&quot;&quot;&gt;more water&lt;/a&gt;
    &lt;/div&gt;
    watership down
    &lt;h4&gt;watery water&lt;/h4&gt;
    &lt;p&gt;
      waters
    &lt;/p&gt;
    foobar &lt;a href=&quot;&quot;&gt;water&lt;/a&gt; water
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2020年1月3日 23:56:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/59581570.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定