diff --git a/package.json b/package.json index 0e6f3fd..f57edb5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "findandreplacedomtext", - "version": "0.4.5", + "version": "0.4.6", "main": "./src/findAndReplaceDOMText.js", "description": "findAndReplaceDOMText: DOM find/replace utility", "repository": { diff --git a/readme.md b/readme.md index 445fbf5..1c82391 100644 --- a/readme.md +++ b/readme.md @@ -262,6 +262,7 @@ exposed.PRESETS = { ### Changelog + * 0.4.6 (5 Dec 2017): Fix indexInMatch ([See #60](https://github.com/padolsey/findAndReplaceDOMText/issues/60)). Fix undefined being echoed in optional+empty capture groups ([See #70](https://github.com/padolsey/findAndReplaceDOMText/issues/70)). * 0.4.4 (4 May 2015): Remove duplicate key from `NON_CONTIGUOUS_PROSE_ELEMENTS`. Expose library via UMD ([See #32](https://github.com/padolsey/findAndReplaceDOMText/issues/32)). * 0.4.3 (28 Apr 2015): Add `preset:prose` and `forceContext` features. [See #29](https://github.com/padolsey/findAndReplaceDOMText/issues/29). * 0.4.2 (30 Mar 2014): Fix IE to avoid incorrectly-closed-tags issue ([see #20](https://github.com/padolsey/findAndReplaceDOMText/issues/20)). Thanks to [shauryamal](https://github.com/shauryamal)! diff --git a/src/findAndReplaceDOMText.js b/src/findAndReplaceDOMText.js index 556cc9a..f4c4cb9 100644 --- a/src/findAndReplaceDOMText.js +++ b/src/findAndReplaceDOMText.js @@ -1,5 +1,5 @@ /** - * findAndReplaceDOMText v 0.4.5 + * findAndReplaceDOMText v 0.4.6 * @author James Padolsey http://james.padolsey.com * @license http://unlicense.org/UNLICENSE * @@ -334,14 +334,18 @@ if (curNode.nodeType === Node.TEXT_NODE) { if (!endPortion && curNode.length + atIndex >= match.endIndex) { - // We've found the ending + // (Note that, in the case of a single portion, it'll be an + // endPortion, not a startPortion.) endPortion = { node: curNode, index: portionIndex++, text: curNode.data.substring(match.startIndex - atIndex, match.endIndex - atIndex), - indexInMatch: atIndex - match.startIndex, - indexInNode: match.startIndex - atIndex, // always zero for end-portions + + // If it's the first match (atIndex==0) we should just return 0 + indexInMatch: atIndex === 0 ? 0 : atIndex - match.startIndex, + + indexInNode: match.startIndex - atIndex, endIndexInNode: match.endIndex - atIndex, isEnd: true }; @@ -459,7 +463,7 @@ replacement = match.input.substring(match.endIndex); break; default: - replacement = match[+t]; + replacement = match[+t] || ''; } return replacement; }); diff --git a/test/test.js b/test/test.js index cf91132..0562d2f 100644 --- a/test/test.js +++ b/test/test.js @@ -328,6 +328,17 @@ test('Right (\')', function() { htmlEqual(d.innerHTML, 'this is [ test] test'); }); +test('Empty captured groups', function() { + var d = document.createElement('div'); + d.innerHTML = '111333'; + findAndReplaceDOMText(d, { + find: /(1+)(\s+)?(3+)/g, + replace: '$3$2$1' + }); + // $2 is empty, so should be replaced by nothing (empty string): + htmlEqual(d.innerHTML, '333111'); +}); + module('Filtering'); test('Element filtering', function() { @@ -480,3 +491,44 @@ test('prose', function() { '); }); + +module('indexInMatch'); + +test('Single portion', function() { + var d = document.createElement('div'); + d.innerHTML = '___AAAAA'; + // ^ 0 + findAndReplaceDOMText(d, { + find: /A+/g, + replace: function(portion) { + return portion.indexInMatch; + } + }); + htmlEqual(d.innerHTML, '___0'); +}); + +test('Two portions', function() { + var d = document.createElement('div'); + d.innerHTML = '___AAAAA'; + // ^ 0 ^ 3 + findAndReplaceDOMText(d, { + find: /A+/g, + replace: function(portion) { + return portion.indexInMatch; + } + }); + htmlEqual(d.innerHTML, '___03'); +}); + +test('>Two portions', function() { + var d = document.createElement('div'); + d.innerHTML = '___AAAAA'; + // ^ 0 ^ 2 ^ 3 ^ 4 + findAndReplaceDOMText(d, { + find: /A+/g, + replace: function(portion) { + return portion.indexInMatch; + } + }); + htmlEqual(d.innerHTML, '___0234'); +});