如何基于Fragment Directive将高亮文本转换为HTML元素?
如何将Fragment Directive指定的高亮文本转换为HTML元素
核心思路
Fragment Directive的:~:text参数通过前后上下文锚点锁定目标文本,我们可以解析该参数,再用脚本遍历页面文本节点,将目标文本替换为带自定义类的HTML元素。
步骤实现
- 解析Fragment参数
从URL的hash部分提取:~:text的参数,解码后拆分出上下文前缀、目标文本和上下文后缀。比如示例中的directive%20is%20a-,mechanism%20for,-URLs%20to%20specify,解码拆分后得到:
- 前缀:
directive is a - 目标文本:
mechanism for - 后缀:
URLs to specify
- 编写替换脚本
用JavaScript遍历页面文本节点,匹配包含完整上下文+目标文本的内容,将目标文本包裹到<span class="custom_element">中:
// 解析Fragment Directive参数 function parseFragmentDirective() { const fragment = window.location.hash.slice(1); if (!fragment.startsWith(':~:text=')) return null; const textParam = decodeURIComponent(fragment.replace(':~:text=', '')); // 拆分前缀、目标文本、后缀 const parts = textParam.split(',-'); return { prefix: parts[0] || '', targetText: parts[1] || '', suffix: parts[2] || '' }; } // 转义正则特殊字符的辅助函数 function escapeRegExp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // 遍历节点并替换目标文本 function wrapTargetText() { const directive = parseFragmentDirective(); if (!directive || !directive.targetText) return; const { prefix, targetText, suffix } = directive; // 构建匹配正则(忽略大小写) const pattern = `${escapeRegExp(prefix)}(${escapeRegExp(targetText)})${escapeRegExp(suffix)}`; const regex = new RegExp(pattern, 'i'); // 递归遍历文本节点 function traverse(node) { if (node.nodeType === Node.TEXT_NODE) { const text = node.textContent; const match = text.match(regex); if (match) { // 创建span元素 const span = document.createElement('span'); span.className = 'custom_element'; span.textContent = match[1]; // 拆分原文本节点为前缀、目标、后缀三部分 const prefixText = text.slice(0, match.index + match[0].indexOf(match[1])); const suffixText = text.slice(match.index + match[0].indexOf(match[1]) + match[1].length); const prefixNode = document.createTextNode(prefixText); const suffixNode = document.createTextNode(suffixText); // 替换原节点 node.parentNode.replaceChild(suffixNode, node); node.parentNode.insertBefore(span, suffixNode); node.parentNode.insertBefore(prefixNode, span); } } else if (node.nodeType === Node.ELEMENT_NODE && !node.classList.contains('custom_element')) { // 跳过已处理的元素,避免重复操作 Array.from(node.childNodes).forEach(traverse); } } traverse(document.body); } // 执行替换操作 wrapTargetText();
使用方式
- 打开包含Fragment Directive的页面,打开Chrome DevTools的Console面板,粘贴上述代码并回车执行,目标文本就会被包裹成指定的span元素。
- 如果需要页面加载时自动执行,可以将代码嵌入页面脚本,或者用油猴脚本(Tampermonkey)挂载到目标页面。
注意事项
- 上下文锚点能有效避免替换到重复的文本内容,如果没有前后锚点(即
:~:text=mechanism%20for),脚本会匹配页面中所有该文本,需根据需求调整正则逻辑。 - 若页面存在动态加载内容,需在内容加载完成后再执行脚本(比如监听
DOMContentLoaded或load事件)。
内容的提问来源于stack exchange,提问作者Lerner Zhang
相关产品推荐
相关产品推荐

