Skip to content

Commit

Permalink
Added support for capture groups; added capture group and word bounda…
Browse files Browse the repository at this point in the history
…ry tests
  • Loading branch information
badsyntax committed Oct 25, 2012
1 parent 8c72eef commit 983349e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 8 deletions.
35 changes: 27 additions & 8 deletions src/findAndReplaceDOMText.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,51 @@ window.findAndReplaceDOMText = (function() {
* @param {String|Element|Function} replacementNode A NodeName,
* Node to clone, or a function which returns a node to use
* as the replacement node.
* @param {Number} captureGroup A number specifiying which capture
* group to use in the match. (optional)
*/
function findAndReplaceDOMText(regex, node, replacementNode) {
function findAndReplaceDOMText(regex, node, replacementNode, captureGroup) {

var m, index, matches = [], text = _getText(node);
var m, matches = [], text = _getText(node);
var replaceFn = _genReplacer(replacementNode);

if (!text) { return; }

if (regex.global) {
while (m = regex.exec(text)) {
if (!m[0]) throw 'findAndReplaceDOMText cannot handle zero-length matches';
matches.push([regex.lastIndex - m[0].length, regex.lastIndex, m]);
matches.push(_getMatchIndexes(m, captureGroup));
}
} else {
m = text.match(regex);
index = text.indexOf(m[0]);
if (!m[0]) throw 'findAndReplaceDOMText cannot handle zero-length matches';
matches.push([index, index + m[0].length, m]);
matches.push(_getMatchIndexes(m, captureGroup));
}

if (matches.length) {
_stepThroughMatches(node, matches, replaceFn);
}

}

/**
* Gets the start and end indexes of a match
*/
function _getMatchIndexes(m, captureGroup) {

captureGroup = captureGroup || 0;

if (!m[0]) throw 'findAndReplaceDOMText cannot handle zero-length matches';

var index = m.index;

if (captureGroup > 0) {
var cg = m[captureGroup];
if (!cg) throw 'Invalid capture group';
index += m[0].indexOf(cg);
m[0] = cg;
}

return [ index, index + m[0].length, [ m[0] ] ];
};

/**
* Gets aggregate text of a node without resorting
* to broken innerText/textContent
Expand Down
32 changes: 32 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,36 @@ test('Custom replacement function - correct ordering', function() {
return document.createTextNode(fill);
});
equal(nCalled, 3);
});

test('Capture groups', function() {

var text = 'TEST TESThello TESThello TESThello';
var d = document.createElement('div');

d.innerHTML = text;
findAndReplaceDOMText(/(TEST)hello/, d, 'x', 1);
htmlEqual(d.innerHTML, 'TEST <x>TEST</x>hello TESThello TESTHello');

d.innerHTML = text;
findAndReplaceDOMText(/(TEST)hello/g, d, 'x', 1);
htmlEqual(d.innerHTML, 'TEST <x>TEST</x>hello <x>TEST</x>hello <x>TEST</x>hello');

d.innerHTML = text;
findAndReplaceDOMText(/\s(TEST)(hello)/g, d, 'x', 2);
htmlEqual(d.innerHTML, 'TEST TEST<x>hello</x> TEST<x>hello</x> TEST<x>hello</x>');
});

test('Word boundaries', function() {

var text = 'a go matching at test wordat at';
var d = document.createElement('div');

d.innerHTML = text;
findAndReplaceDOMText(/\bat\b/, d, 'x');
htmlEqual(d.innerHTML, 'a go matching <x>at</x> test wordat at');

d.innerHTML = text;
findAndReplaceDOMText(/\bat\b/g, d, 'x');
htmlEqual(d.innerHTML, 'a go matching <x>at</x> test wordat <x>at</x>');
});

0 comments on commit 983349e

Please sign in to comment.