Skip to content

Commit a79cd88

Browse files
committed
First commit
0 parents  commit a79cd88

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed

.gitignore

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
6+
# Runtime data
7+
pids
8+
*.pid
9+
*.seed
10+
*.pid.lock
11+
12+
# Directory for instrumented libs generated by jscoverage/JSCover
13+
lib-cov
14+
15+
# Coverage directory used by tools like istanbul
16+
coverage
17+
18+
# nyc test coverage
19+
.nyc_output
20+
21+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
22+
.grunt
23+
24+
# node-waf configuration
25+
.lock-wscript
26+
27+
# Compiled binary addons (http://nodejs.org/api/addons.html)
28+
build/Release
29+
30+
# Dependency directories
31+
node_modules
32+
jspm_packages
33+
34+
# Optional npm cache directory
35+
.npm
36+
37+
# Optional eslint cache
38+
.eslintcache
39+
40+
# Optional REPL history
41+
.node_repl_history
42+
43+
# Output of 'npm pack'
44+
*.tgz
45+
46+
# Yarn Integrity file
47+
.yarn-integrity
48+

lib/index.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
var interpolateReplacement = function (matches, replacement) {
2+
var interpolated = replacement;
3+
var max = matches.length;
4+
5+
interpolated = interpolated.replace(
6+
/(\\)([1-9]\d*|[0nrtv\W]|([uUx])(?:\{([0-9a-fA-F]+)\}|([0-9a-fA-F]{2,4})))|(\$)([1-9]\d*|[$])/g, // todo: $&, $', $`
7+
function (
8+
wholeMatch,
9+
slash, slashEscapee, codePointPrefix, bracedCodePoint, unbracedCodePoint,
10+
dollar, dollarEscapee
11+
) {
12+
var args = Array.prototype.slice.call(arguments);
13+
var escapee = dollarEscapee || slashEscapee;
14+
var escapables = { '0' : '\0', n : '\n', r : '\r', t : '\t', v : '\v' };
15+
var codePoint = unbracedCodePoint || bracedCodePoint;
16+
17+
if (escapables.hasOwnProperty(escapee)) {
18+
return escapables[escapee];
19+
} else if (escapee.match(/^\d+$/)) {
20+
// let both \1 and $1 mean the same thing
21+
return ( matches.hasOwnProperty(escapee) ? matches [escapee] : '' );
22+
} else if (dollar && '$' == escapee) {
23+
return dollar;
24+
} else if (codePoint) {
25+
if (unbracedCodePoint) {
26+
if ('x' == codePointPrefix && 4 == codePoint.length) {
27+
return String.fromCodePoint(parseInt(codePoint.substr(0,2), 16)) + codePoint.substr(2,4);
28+
} else if ('u' == codePointPrefix && 2 == codePoint.length) {
29+
return '\\u' + codePoint;
30+
}
31+
}
32+
return String.fromCodePoint(parseInt(codePoint, 16));
33+
} else {
34+
return escapee;
35+
}
36+
}
37+
);
38+
return interpolated;
39+
};
40+
41+
module.exports = {
42+
interpolateReplacement: interpolateReplacement
43+
};

package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "regexp-capture-interpolation",
3+
"version": "0.1.0",
4+
"description": "Interpolate a regular expression match into a replacement string",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "tape test/**/*.js"
8+
},
9+
"keywords": [
10+
"regexp",
11+
"regex",
12+
"interpolation",
13+
"interpolate",
14+
"capture",
15+
"match",
16+
"replacement",
17+
"substitution",
18+
"$&",
19+
"$`",
20+
"$'",
21+
"$1",
22+
"$2"
23+
],
24+
"author": "Daniel Perrett",
25+
"license": "BSD-3-Clause",
26+
"devDependencies": {
27+
"tape": "^4.6.3"
28+
}
29+
}

test/test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
var test = require ('tape');
2+
var Interpolator = require('../lib/index.js');
3+
4+
var suite = [
5+
{
6+
"why" : "Empty string replacement produces empty string",
7+
"matchObject" : [],
8+
"replacement" : "",
9+
"expected" : ""
10+
},
11+
{
12+
"why" : "Can interpolate $1, $2",
13+
"matchObject" : ["foo, bar", "foo", "bar"],
14+
"replacement" : "$2$1",
15+
"expected" : "barfoo"
16+
},
17+
{
18+
"why" : "Can interpolate \\1, \\2",
19+
"matchObject" : ["foo, bar", "foo", "bar"],
20+
"replacement" : "\\2\\1",
21+
"expected" : "barfoo"
22+
},
23+
{
24+
"why" : "Can escape $",
25+
"matchObject" : ["foo, bar", "foo", "bar"],
26+
"replacement" : "\\$2$1",
27+
"expected" : "$2foo"
28+
},
29+
{
30+
"why" : "escaped \\ before $ does not escape",
31+
"matchObject" : ["foo, bar", "foo", "bar"],
32+
"replacement" : "\\\\$2\\\\\\$1",
33+
"expected" : "\\bar\\$1"
34+
},
35+
{
36+
"replacement" : "\\u{a0}",
37+
"expected" : "\xa0"
38+
},
39+
{
40+
"why" : "\\xhh only uses two characters",
41+
"replacement" : "\\xa0a0",
42+
"expected" : "\u{a0}a0"
43+
},
44+
{
45+
"replacement" : "\\ua0a0",
46+
"expected" : "\u{a0a0}"
47+
},
48+
{
49+
"why" : "Allow \\x{hhhh} to escape any number of characters",
50+
"replacement" : "\\x{a0a0}",
51+
"expected" : "\u{a0a0}"
52+
}
53+
];
54+
55+
for (var i = 0; i < suite.length; i++) {
56+
var c = suite[i];
57+
test (c.why || c.replacement, function (t) {
58+
var interp = Interpolator;
59+
t.is(interp.interpolateReplacement(c.matchObject || [], c.replacement), c.expected);
60+
t.end();
61+
});
62+
}

0 commit comments

Comments
 (0)