UNPKG

1.76 kBJavaScriptView Raw
1import number from "./number";
2
3var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
4 reB = new RegExp(reA.source, "g");
5
6function zero(b) {
7 return function() {
8 return b;
9 };
10}
11
12function one(b) {
13 return function(t) {
14 return b(t) + "";
15 };
16}
17
18export default function(a, b) {
19 var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
20 am, // current match in a
21 bm, // current match in b
22 bs, // string preceding current number in b, if any
23 i = -1, // index in s
24 s = [], // string constants and placeholders
25 q = []; // number interpolators
26
27 // Coerce inputs to strings.
28 a = a + "", b = b + "";
29
30 // Interpolate pairs of numbers in a & b.
31 while ((am = reA.exec(a))
32 && (bm = reB.exec(b))) {
33 if ((bs = bm.index) > bi) { // a string precedes the next number in b
34 bs = b.slice(bi, bs);
35 if (s[i]) s[i] += bs; // coalesce with previous string
36 else s[++i] = bs;
37 }
38 if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
39 if (s[i]) s[i] += bm; // coalesce with previous string
40 else s[++i] = bm;
41 } else { // interpolate non-matching numbers
42 s[++i] = null;
43 q.push({i: i, x: number(am, bm)});
44 }
45 bi = reB.lastIndex;
46 }
47
48 // Add remains of b.
49 if (bi < b.length) {
50 bs = b.slice(bi);
51 if (s[i]) s[i] += bs; // coalesce with previous string
52 else s[++i] = bs;
53 }
54
55 // Special optimization for only a single match.
56 // Otherwise, interpolate each of the numbers and rejoin the string.
57 return s.length < 2 ? (q[0]
58 ? one(q[0].x)
59 : zero(b))
60 : (b = q.length, function(t) {
61 for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
62 return s.join("");
63 });
64}