Skip to content

Instantly share code, notes, and snippets.

@balpha
Last active August 29, 2015 14:06
Show Gist options
  • Save balpha/81a4fbf2d5f40d19e26c to your computer and use it in GitHub Desktop.
Save balpha/81a4fbf2d5f40d19e26c to your computer and use it in GitHub Desktop.
// replacer is a function that receives the full matched string
// as the first argument and the regex's groups as the following
// arguments (similar to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter,
// except "offset" and "string"). It can return either a simple string,
// or a full DOM node.
//
// node is the document node from which to start (i.e. descend from)
function replaceTextWithElement(node, regex, replacer, skipCode) {
var len,
i;
if (node.nodeType !== 3) {
if (skipCode && node.nodeName.toLowerCase() === "code")
return;
var childNodes = node.childNodes,
children = [];
len = childNodes.length;
// We're altering the dom, and childNodes is a live collection. Hence we have to make
// a copy at this point.
for (i = 0; i < len; i++)
children.push(childNodes[i]);
for (i = 0; i < len; i++) {
replaceTextWithElement(children[i], regex, replacer, skipCode);
}
return;
}
regex.lastIndex = 0;
var text = node.nodeValue,
match,
result = [],
start = 0,
first = true;
while (match = regex.exec(text)) {
first = start === 0;
if (match.index > start) {
result.push(text.substring(start, match.index))
first = true;
}
start = regex.lastIndex;
result.push(replacer.apply({isFirst: first}, match));
}
if (!result.length)
return;
if (start < text.length)
result.push(text.substring(start));
var parent = node.parentNode, val;
len = result.length;
for (i = 0; i < len; i++) {
val = result[i];
if (typeof val === "string") {
val = document.createTextNode(val);
}
parent.insertBefore(val, node);
}
parent.removeChild(node);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment