javascript - 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) {
//hyperlink the search term
txt = txt.replace(regex, '<a href="/somelink">$1</a>');
content.html(txt);
}
});
然而,有一些我不想匹配的实例,由于时间限制和大脑融化,我正在寻求一些帮助。
编辑:我已经根据@ggorlen 提供的优秀示例更新了下面的代码笔,谢谢!
解决方案
将整个 DOM 转储为原始文本并使用正则表达式对其进行解析绕过了 jQuery(以及扩展为 JS)的主要目的,即将 DOM 作为节点的抽象树进行遍历和操作。
文本节点有一个,我们可以在遍历中使用它来识别您感兴趣的非链接节点。nodeType
Node.TEXT_NODE
获得文本节点后,可以适当地应用正则表达式(解析文本,而不是 HTML)。我用于<mark>
演示目的,但您可以将其设为锚标记或任何您需要的标记。
jQuery 为您提供了replaceWith
一种在您进行所需的正则表达式替换后替换节点内容的方法。
$('#content li').contents().each(function () {
if (this.nodeType === Node.TEXT_NODE) {
var pattern = /(\b[Ww]aters?(?!-)\b)/g;
var replacement = '<mark>$1</mark>';
$(this).replaceWith(this.nodeValue.replace(pattern, replacement));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Example Content</h1>
<div id="content">
<ul>
<li>Water is a fascinating subject. - <strong>match</strong></li>
<li>We all love water. - <strong>match</strong></li>
<li>ice; water; steam - <strong>match</strong></li>
<li>The beautiful waters of the world - <strong>match</strong> (including the s)</li>
<li>and all other water-related subjects - <strong>no match</strong></li>
<li>and this watery topic of - <strong>no match</strong></li>
<li>of WaterStewardship looks at how best - <strong>no match</strong></li>
<li>On the topic of <a href="/governance">water governance</a> - <strong>no match</strong></li>
<li>and other <a href="/water">water</a> related things - <strong>no match</strong></li>
<li>the best of <a href="/allthingswater">all things water</a> - <strong>no match</strong></li>
</ul>
</div>
您可以在没有 jQ 的情况下执行此操作并应用于文档中的所有内容:
for (const parent of document.querySelectorAll("body *:not(a)")) {
for (const child of parent.childNodes) {
if (child.nodeType === Node.TEXT_NODE) {
const pattern = /(\b[Ww]aters?(?!-)\b)/g;
const replacement = "<mark>$1</mark>";
const subNode = document.createElement("span");
subNode.innerHTML = child.textContent.replace(pattern, replacement);
parent.insertBefore(subNode, child);
parent.removeChild(child);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
hello water
<div>
<div>
I love Water.
<a href="">more water</a>
</div>
watership down
<h4>watery water</h4>
<p>
waters
</p>
foobar <a href="">water</a> water
</div>
</div>
推荐阅读
- javascript - 父状态更改后反应子不更新
- python - 找不到通过 requests.py 获取 Twitch API 信息的方法
- java-8 - Java jackson反序列化json - 获取符号“=”而不是“:”
- python - 为什么我无法安装 discord.py?
- laravel - New Tenancy 1.x Laravel 创建数据库后如何插入数据
- celery - 只有当所有子任务都成功完成后才能使任务发布成功?
- r - 如何在 .rmd 文件中获取部分名称?
- java - 如何比较 3 个字符串,然后按字母顺序排列?(爪哇)
- android - 选择器可绘制仅在 not_night 模式下显示角半径,但在夜间模式下显示边框
- sql - 在 Oracle SQL 中,是否有可能有一个有效的日期查询也显示日期之间出现的行?