Skip to content

Instantly share code, notes, and snippets.

@kobachi
Last active May 1, 2024 01:25
Show Gist options
  • Save kobachi/ef303a38e4f55473c3ab711c7378022a to your computer and use it in GitHub Desktop.
Save kobachi/ef303a38e4f55473c3ab711c7378022a to your computer and use it in GitHub Desktop.
Text Highlighting
/**
1. Find TextNode contains specified text using XPath
2. Collect TextNode from XPath snapshot result into array
3. Edit TextNode with 3 steps below, eg. ```<p>ABCあいうXYZ</p>``` (highlight: ```あいう```)
1. Split prefix from ```ABCあいうXYZ```[1], and replace [1] to prefix ```ABC```[2]. (Temporally result: ```<p>ABC</p>```)
2. Append suffix ```XYZ```[3] after [2]. (Temporally result: ```<p>ABC``` ```XYZ</p>```)
3. Insert highlight node ```<span class="highlight">あいう</span>``` before suffix [3].
4. Final result: ```<p>ABC<span class="highlight">あいう</span>XYZ</p>```
*/
const highlight = (text) => {
const textNodes = [];
const evaluateResult = document.evaluate('//text()[contains(., "' + text + '")]', document.body, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < evaluateResult.snapshotLength; i++) {
textNodes.push(evaluateResult.snapshotItem(i));
}
textNodes.forEach((textNode) => {
const fullText = textNode.textContent;
const textPosition = fullText.indexOf(fullText);
const prefix = document.createTextNode(fullText.substring(0, textPosition));
textNode.parentNode.replaceChild(prefix, textNode);
if (textPosition + text.length <= fullText.length) {
const suffix = document.createTextNode(fullText.substring(textPosition + text.length));
prefix.parentNode.insertBefore(suffix, prefix.nextSibling);
}
const highlighted = document.createElement("span");
highlighted.setAttribute("class", "highlight");
highlighted.textContent = text;
prefix.parentNode.insertBefore(highlighted, prefix.nextSibling);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment