import number from "./number.js"; | |
var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, | |
reB = new RegExp(reA.source, "g"); | |
function zero(b) { | |
return function() { | |
return b; | |
}; | |
} | |
function one(b) { | |
return function(t) { | |
return b(t) + ""; | |
}; | |
} | |
export default function(a, b) { | |
var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b | |
am, // current match in a | |
bm, // current match in b | |
bs, // string preceding current number in b, if any | |
i = -1, // index in s | |
s = [], // string constants and placeholders | |
q = []; // number interpolators | |
// Coerce inputs to strings. | |
a = a + "", b = b + ""; | |
// Interpolate pairs of numbers in a & b. | |
while ((am = reA.exec(a)) | |
&& (bm = reB.exec(b))) { | |
if ((bs = bm.index) > bi) { // a string precedes the next number in b | |
bs = b.slice(bi, bs); | |
if (s[i]) s[i] += bs; // coalesce with previous string | |
else s[++i] = bs; | |
} | |
if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match | |
if (s[i]) s[i] += bm; // coalesce with previous string | |
else s[++i] = bm; | |
} else { // interpolate non-matching numbers | |
s[++i] = null; | |
q.push({i: i, x: number(am, bm)}); | |
} | |
bi = reB.lastIndex; | |
} | |
// Add remains of b. | |
if (bi < b.length) { | |
bs = b.slice(bi); | |
if (s[i]) s[i] += bs; // coalesce with previous string | |
else s[++i] = bs; | |
} | |
// Special optimization for only a single match. | |
// Otherwise, interpolate each of the numbers and rejoin the string. | |
return s.length < 2 ? (q[0] | |
? one(q[0].x) | |
: zero(b)) | |
: (b = q.length, function(t) { | |
for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); | |
return s.join(""); | |
}); | |
} | |