高亮文本
const inputs = [
"这是一个普通文本,包含关键字测试。",
'<p style="font-size: 10px">这是一个<span>GVM</span> <strong>测试</strong>内容。</p>',
];
const keywords = ["测试", "GVM"];
function highlightKeyword(inputContent, keyword) {
if (!keyword) return inputContent; // 如果没有关键字,直接返回原始内容
// 转义用户输入的关键字,避免正则表达式特殊字符冲突
const escapeRegExp = (str) =>
str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
// 创建匹配关键字的正则表达式
const keywordRegex = new RegExp(`(${escapeRegExp(keyword)})`, "gi");
// 判断是否为普通文本(没有 HTML 标签)
const isPlainText = !/<[^>]+>/.test(inputContent);
if (isPlainText) {
// 普通文本处理
return inputContent.replace(
keywordRegex,
'<span class="highlight">$1</span>'
);
}
// HTML 内容处理
const parser = new DOMParser();
const doc = parser.parseFromString(inputContent, "text/html");
// 遍历节点,处理文本高亮
function traverseNodes(node) {
if (node.nodeType === Node.TEXT_NODE) {
// 替换关键字为高亮的内容
const parent = node.parentNode;
const highlightedHTML = node.textContent.replace(
keywordRegex,
'<span class="highlight">$1</span>'
);
// 用安全的 HTML 替换
if (highlightedHTML !== node.textContent) {
const temp = document.createElement("div");
temp.innerHTML = highlightedHTML;
while (temp.firstChild) {
parent.insertBefore(temp.firstChild, node);
}
parent.removeChild(node);
}
} else if (node.nodeType === Node.ELEMENT_NODE) {
// 递归处理子节点
Array.from(node.childNodes).forEach(traverseNodes);
}
}
traverseNodes(doc.body);
// 返回处理后的 HTML
return doc.body.innerHTML;
}
跨标签命中
function highlightKeyword(inputContent, keyword) {
if (!keyword) return inputContent; // 如果没有关键字,直接返回原始内容
// 转义用户输入的关键字,避免正则表达式特殊字符冲突
const escapeRegExp = (str) =>
str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
// 创建匹配关键字的正则表达式
const keywordRegex = new RegExp(`(${escapeRegExp(keyword)})`, "gi");
// 使用 DOMParser 解析 HTML
const parser = new DOMParser();
const doc = parser.parseFromString(inputContent, "text/html");
// 提取纯文本和对应节点
const textNodes = [];
function extractTextNodes(node) {
if (node.nodeType === Node.TEXT_NODE) {
textNodes.push({ node, text: node.textContent });
} else if (node.nodeType === Node.ELEMENT_NODE) {
Array.from(node.childNodes).forEach(extractTextNodes);
}
}
extractTextNodes(doc.body);
// 合并纯文本
const combinedText = textNodes.map((item) => item.text).join("");
// 查找关键字在纯文本中的位置
const matches = [];
let match;
while ((match = keywordRegex.exec(combinedText)) !== null) {
matches.push({ start: match.index, end: match.index + match[0].length });
}
// 在原始文本节点中插入高亮
let currentIndex = 0;
matches.forEach(({ start, end }) => {
textNodes.forEach(({ node, text }) => {
const nodeEnd = currentIndex + text.length;
if (start < nodeEnd && end > currentIndex) {
const localStart = Math.max(start - currentIndex, 0);
const localEnd = Math.min(end - currentIndex, text.length);
const highlightedText =
text.slice(0, localStart) +
`<span class="highlight">${text.slice(localStart, localEnd)}</span>` +
text.slice(localEnd);
const temp = document.createElement("div");
temp.innerHTML = highlightedText;
// 替换节点
const parent = node.parentNode;
while (temp.firstChild) {
parent.insertBefore(temp.firstChild, node);
}
parent.removeChild(node);
// 更新当前文本
node.textContent = text;
}
currentIndex += text.length;
});
});
// 返回处理后的 HTML
return doc.body.innerHTML;
}
关键字忽略大小写
function highlightKeyword(inputContent, keyword) {
if (!keyword) return inputContent; // 关键字为空直接返回
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
// 统一大小写匹配
const keywordLower = keyword.toLowerCase();
const regex = new RegExp(`(${escapeRegExp(keywordLower)})`, "gi"); // 🔥【提前正则表达式】
// 判断是否是普通文本
const isPlainText = !/<[a-z][\s\S]*>/i.test(inputContent);
if (isPlainText) {
return inputContent.replace(regex, `<span class="highlight">$1</span>`);
}
// 解析 HTML
const parser = new DOMParser();
const doc = parser.parseFromString(inputContent, "text/html");
const textNodes = [];
function extractTextNodes(node) {
if (node.nodeType === Node.TEXT_NODE) {
textNodes.push({ node, text: node.textContent });
} else if (node.nodeType === Node.ELEMENT_NODE) {
Array.from(node.childNodes).forEach(extractTextNodes);
}
}
extractTextNodes(doc.body);
// 合并所有文本(保持原顺序)
let combinedText = textNodes.map((item) => item.text).join("");
// 在合并后的文本中查找匹配位置(忽略大小写)
const matches = [];
let match;
while ((match = regex.exec(combinedText)) !== null) {
matches.push({ start: match.index, end: match.index + match[0].length });
}
// 在原始 HTML 结构中插入高亮标签
let currentIndex = 0;
matches.forEach(({ start, end }) => {
textNodes.forEach(({ node, text }) => {
const textLower = text.toLowerCase();
const nodeEnd = currentIndex + text.length;
if (start < nodeEnd && end > currentIndex) {
const localStart = Math.max(start - currentIndex, 0);
const localEnd = Math.min(end - currentIndex, text.length);
// 保留原始大小写的文本进行替换
const highlightedText =
text.slice(0, localStart) +
`<span class="highlight">${text.slice(localStart, localEnd)}</span>` +
text.slice(localEnd);
const temp = document.createElement("div");
temp.innerHTML = highlightedText;
const parent = node.parentNode;
while (temp.firstChild) {
parent.insertBefore(temp.firstChild, node);
}
parent.removeChild(node);
}
currentIndex += text.length;
});
});
return doc.body.innerHTML;
}
619

被折叠的 条评论
为什么被折叠?



