+ return patch(partial, a);
+ }
+
+ var NUMBERS = /(-?\d+(?:\.\d+)?)/g;
+
+ function areNumericTwins(a, b) {
+ /** Check if a and b differ only in numerals
+
+ A leading "-" counts as part of numbers; a leading "+"
+ does not. Numbers may contain a single ".", but no other
+ floating point syntax.
+ */
+ return a.replace(NUMBERS, "0") === b.replace(NUMBERS, "0");
+ }
+
+ function nlerp(a, b, p) {
+ return a + (b - a) * p;
+ }
+
+ function numericLerp(a, b, p) {
+ /** Interpolate numerically between two strings containing numbers
+
+ Numbers may have a leading "-" and a single "." to mark
+ the decimal point, but something must be after the ".".
+ If both of the numbers in a pair are integers, the result
+ is clamped to an integer.
+
+ For example, numericLerp("0.0", "100", 0.123) === "12.3"
+ because the "." in "0.0" is intepreted as a decimal point.
+ But numericLerp("0.", "100.", 0.123) === "12." because the
+ strings are interpreted as integers followed by a full
+ stop.
+
+ Calling this functions on strings that differ in more than
+ numerals gives undefined results.
+ */
+ var aParts = a.split(NUMBERS);
+ var bParts = b.split(NUMBERS);
+ for (var i = 1; i < aParts.length; i += 2) {
+ var part = nlerp(+aParts[i], +bParts[i], p);
+ if (aParts[i].indexOf(".") === -1 && bParts[i].indexOf(".") === -1)
+ part = Math.round(part);
+ aParts[i] = part.toString();
+ }
+ return aParts.join("");