UNPKG

@technobuddha/library

Version:
514 lines (513 loc) 18.1 kB
"use strict"; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatNumber = void 0; var defaultTo_1 = __importDefault(require("lodash/defaultTo")); var map_1 = __importDefault(require("lodash/map")); var constants_1 = require("../constants"); var padNumber_1 = __importDefault(require("../padNumber")); var splitChars_1 = __importDefault(require("../splitChars")); var build_1 = __importDefault(require("../build")); function parse(mask) { var scale = 1; var beforeDP = true; var before = []; var after = []; var group = false; var commas = 0; var zeroSeen = false; var exponent = 0; var signExponent = false; var precision = 0; var m = splitChars_1.default(mask); for (var i = 0; i < m.length; ++i) { var c = m[i]; switch (c) { case '"': //literal string case "'": { var s = '"'; for (++i; i < mask.length; ++i) { var k = mask.charAt(i); if (c === k) break; s += k; } (beforeDP ? before : after).push(s); break; } case '#': { if (beforeDP) { before.push(zeroSeen ? '0' : '#'); } else { precision++; after.push('#'); } break; } case '0': { if (beforeDP) { //If we see a 0 before the decimal point, all following #s are transformed into 0s before.push('0'); zeroSeen = true; } else { //if we see a 0 after the decimal point, the proceeding #s are transformed into 0s precision++; after = map_1.default(after, function (a) { return (a === '#' ? '0' : a); }); after.push('0'); } break; } case ',': { if (beforeDP) commas++; break; } case '.': { beforeDP = false; break; } case '%': { scale *= 100; (beforeDP ? before : after).push("\"" + c); break; } case '‰': { scale *= 1000; (beforeDP ? before : after).push("\"" + c); break; } case '‱': { scale *= 10000; (beforeDP ? before : after).push("\"" + c); break; } case 'e': case 'E': { var signSeen = false; var j = i + 1; var e = 0; if (mask.length > j && mask.charAt(j) === '+') { j++; signSeen = true; } else if (mask.length > j && mask.charAt(j) === '-') { j++; } while (mask.length > j && mask.charAt(j) === '0') { j++; e++; } if (e > 0) { i = j - 1; exponent = e; signExponent = signSeen; (beforeDP ? before : after).push(c); } else { (beforeDP ? before : after).push("\"" + c); } break; } case '\\': { if (i < mask.length - 1) (beforeDP ? before : after).push("\"" + mask.charAt(++i)); else (beforeDP ? before : after).push('"\\'); break; } default: { (beforeDP ? before : after).push("\"" + c); break; } } if (beforeDP && c !== ',') { if (commas > 0) group = true; commas = 0; } } scale = scale / Math.pow(1000, commas); return { aMask: after, aDigits: after.reduce(function (acc, val) { return ((val === '0' || val === '#') ? acc + 1 : acc); }, 0), bMask: before, bDigits: before.reduce(function (acc, val) { return ((val === '0' || val === '#') ? acc + 1 : acc); }, 0), scale: scale, group: group, exponent: exponent, signExponent: signExponent, precision: precision, }; } function format(input, _a) { var round = _a.round, precision = _a.precision, scale = _a.scale, _b = _a.lead, lead = _b === void 0 ? 1 : _b, _c = _a.trim, trim = _c === void 0 ? 'none' : _c; var sign = Math.sign(input); var _d = __read(Math.abs(input).toExponential(15).split('e'), 2), m = _d[0], e = _d[1]; var exponent = Number(e) + 1; // +1 because we store the number without the decimal point var mantissa = m.replace('.', constants_1.empty).split(constants_1.empty); while (mantissa.length > exponent && mantissa[mantissa.length - 1] === '0') --mantissa.length; var rounder = function (n) { if (mantissa.length < n) { while (mantissa.length < n) mantissa.push('0'); } else { var c = mantissa[n]; mantissa.length = n; if (c > '4') { for (;;) { if (n < 0) { mantissa.unshift('0'); ++exponent; n = 1; } var d = mantissa[--n]; if (d === '0') { mantissa[n] = '1'; break; } if (d === '1') { mantissa[n] = '2'; break; } if (d === '2') { mantissa[n] = '3'; break; } if (d === '3') { mantissa[n] = '4'; break; } if (d === '4') { mantissa[n] = '5'; break; } if (d === '5') { mantissa[n] = '6'; break; } if (d === '6') { mantissa[n] = '7'; break; } if (d === '7') { mantissa[n] = '8'; break; } if (d === '8') { mantissa[n] = '9'; break; } if (d === '9') { mantissa[n] = '0'; mantissa.unshift('1'); ++exponent; break; } process.stderr.write("\"" + d + "\"" + n + "\""); } } } }; if (scale !== undefined) exponent += scale; if (round !== undefined) rounder(exponent + round); if (precision !== undefined) rounder(precision); var length = Math.min(exponent, mantissa.length); while (length < lead) { mantissa.unshift('0'); ++exponent; ++length; } if (trim === 'front' || trim === 'all') { while (mantissa.length > 1 && mantissa[0] === '0') { mantissa.shift(); --exponent; } } if (trim === 'back' || trim === 'all') { while (mantissa.length > exponent && mantissa[mantissa.length - 1] === '0') --mantissa.length; } return new NumberFormatter(sign, mantissa, exponent); } var NumberFormatter = /** @class */ (function () { function NumberFormatter(sign, mantissa, exponent) { this.sign = sign; this.mantissa = mantissa; this.exponent = exponent; this.output = []; } NumberFormatter.prototype.minus = function (negative, positive) { if (positive === void 0) { positive = constants_1.empty; } this.output.push(this.sign < 0 ? negative : positive); return this; }; NumberFormatter.prototype.grouped = function () { var whole = this.mantissa.slice(0, this.exponent); this.output.push(whole.map(function (c, i) { return (i > 0 && (whole.length - i) % 3 === 0 ? "," + c : c); })); return this; }; NumberFormatter.prototype.whole = function () { var whole = this.mantissa.slice(0, this.exponent); while (whole.length < this.exponent) whole.push('0'); this.output.push(whole); return this; }; NumberFormatter.prototype.decimal = function () { if (this.exponent < this.mantissa.length) this.output.push('.'); return this; }; NumberFormatter.prototype.fraction = function () { this.output.push(this.mantissa.slice(this.exponent)); return this; }; NumberFormatter.prototype.text = function (str) { this.output.push(str); return this; }; NumberFormatter.prototype.scientific = function (e) { this.output.push(this.mantissa[0], '.', this.mantissa.slice(1), e, this.exponent > 0 ? '+' : constants_1.empty, padNumber_1.default(this.exponent - 1, 3)); return this; }; NumberFormatter.prototype.build = function () { return build_1.default.apply(void 0, __spreadArray([], __read(this.output))); }; return NumberFormatter; }()); //#endregion //#region formatNumber function formatNumber(input, mask) { var _a, e_1, _b; if (/^([CDEFGNPX][0-9]*)|R$/ui.test(mask)) { var f_1 = mask.charAt(0); var prec = Number.parseInt(mask.slice(1), 10); switch (f_1) { case 'C': case 'c': { prec = defaultTo_1.default(prec, 2); return format(input, { round: prec, lead: 1 }).minus('($', '$').grouped().decimal().fraction().minus(')').build(); } case 'D': case 'd': { prec = defaultTo_1.default(prec, 2); return format(input, { round: 0, lead: prec }).minus('-').whole().build(); } case 'E': case 'e': { prec = defaultTo_1.default(prec, 6); return format(input, { precision: prec + 1 }).minus('-').scientific(f_1).build(); } case 'F': case 'f': { prec = defaultTo_1.default(prec, 2); return format(input, { round: prec }).minus('-').whole().decimal().fraction().build(); } case 'G': case 'g': { prec = defaultTo_1.default(prec, 15); var sci = format(input, { precision: prec, trim: 'all' }).minus('-').scientific(f_1 === 'G' ? 'E' : 'e').build(); var fix = format(input, { precision: prec, trim: 'back' }).minus('-').whole().decimal().fraction().build(); return sci.length < fix.length ? sci : fix; } case 'N': case 'n': { prec = defaultTo_1.default(prec, 2); return format(input, { round: prec }).minus('-').grouped().decimal().fraction().build(); } case 'P': case 'p': { prec = defaultTo_1.default(prec, 2); return format(input, { scale: 2, round: prec }).minus('-').whole().decimal().fraction().text(' %').build(); } case 'R': case 'r': { for (var i = 1; i < 21; ++i) { var num = input.toPrecision(i); if (Number.parseFloat(num) === input) return num; } break; } // No default } prec = defaultTo_1.default(prec, 0); var hex = (input >>> 0).toString(16); hex = hex.padStart(prec, '0'); if (f_1 === 'X') hex = hex.toUpperCase(); return hex; } var formats = mask.toString().split(';'); var fmt = parse(formats[0]); if (Number.parseFloat((input * fmt.scale).toFixed(fmt.precision)) === 0) fmt = formats.length < 3 ? fmt : parse(formats[2]); else if (input < 0) fmt = formats.length < 2 ? parse("-" + formats[0]) : parse(formats[1]); var w; var f; var exp = 0; if (fmt.exponent > 0) { var _c = __read(Math.abs(input).toExponential(fmt.aDigits + fmt.bDigits - 1).split('e'), 2), m = _c[0], e = _c[1]; (_a = __read(m.split('.').map(function (x) { return x.split(constants_1.empty); }), 2), w = _a[0], f = _a[1]); exp = Number(e); while (w.length < fmt.bDigits) { w.push(f.shift()); exp--; } } else if (fmt.bDigits === 0) { w = (Math.abs(input * fmt.scale)).toFixed(0).split(constants_1.empty); f = []; } else { var scaled = Math.abs(input * fmt.scale); var rescale = 0; var str = void 0; var split = void 0; //toFixed for numbers greater than 1e21 return scientific notation... while (scaled > 1e21) { scaled /= 1e21; rescale += 21; } if (rescale > 0) { str = (scaled).toFixed(17); split = str.split('.'); w = split[0].split(constants_1.empty); f = split[1].split(constants_1.empty); while (rescale-- > 0) { w.push(f.shift()); f.push('0'); } } else { str = (scaled).toFixed(fmt.aDigits); split = str.split('.'); w = split[0].split(constants_1.empty); //whole part f = split.length > 1 ? split[1].split(constants_1.empty) : []; //fractional } } while (w.length > 0 && w[0] === '0') w.shift(); var o = constants_1.empty; var d = 0; var b = fmt.bDigits; for (var i = fmt.bMask.length - 1; i >= 0; --i) { var x = fmt.bMask[i]; if (x === '0' || x === '#') { if (fmt.group && d === 3 && w.length > 0) { o = "," + o; d = 0; } if (x === '0') { o = w.length > 0 ? w.pop() + o : "0" + o; d++; b--; } else if (w.length > 0) { o = w.pop() + o; d++; b--; } while (b <= 0 && w.length > 0) { if (fmt.group && d === 3) { o = "," + o; d = 0; } o = w.pop() + o; d++; b--; } } else if (x === 'e' || x === 'E') { o = x + "-" + padNumber_1.default(Math.abs(exp), fmt.exponent) + o; } else { o = x.slice(1) + o; } } if (fmt.aMask.length > 0) { var a = constants_1.empty; var digits = false; try { for (var _d = __values(fmt.aMask), _e = _d.next(); !_e.done; _e = _d.next()) { var x = _e.value; switch (x) { case '0': { a = a + f.shift(); digits = true; break; } case '#': { if (f.reduce(function (acc, val) { return val === '0' ? acc : true; }, false)) { a = a + f.shift(); digits = true; } break; } case 'e': case 'E': { a = a + x + ((fmt.signExponent || exp < 0) ? (exp < 0 ? '-' : '+') : constants_1.empty) + padNumber_1.default(Math.abs(exp), fmt.exponent); break; } default: { a = a + x.slice(1); } } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_e && !_e.done && (_b = _d.return)) _b.call(_d); } finally { if (e_1) throw e_1.error; } } o += digits ? "." + a : a; } return o; } exports.formatNumber = formatNumber; //#endregion exports.default = formatNumber;