UNPKG

@formatjs/intl-numberformat

Version:

Ponyfill for ES2020 Intl.NumberFormat

1,949 lines • 71.7 kB
import { Decimal as Decimal$1 } from "@formatjs/bigdecimal"; import { LookupSupportedLocales, ResolveLocale } from "@formatjs/intl-localematcher"; //#region packages/ecma262-abstract/OrdinaryHasInstance.js function IsCallable$1(fn) { return typeof fn === "function"; } /** * https://tc39.es/ecma262/#sec-ordinaryhasinstance */ function OrdinaryHasInstance(C, O, internalSlots) { if (!IsCallable$1(C)) return false; if (internalSlots?.boundTargetFunction) return O instanceof internalSlots?.boundTargetFunction; if (typeof O !== "object") return false; let P = C.prototype; if (typeof P !== "object") throw new TypeError("OrdinaryHasInstance called on an object with an invalid prototype property."); return Object.prototype.isPrototypeOf.call(P, O); } //#endregion //#region packages/ecma402-abstract/CanonicalizeLocaleList.js /** * http://ecma-international.org/ecma-402/7.0/index.html#sec-canonicalizelocalelist * @param locales */ function CanonicalizeLocaleList(locales) { return Intl.getCanonicalLocales(locales); } //#endregion //#region node_modules/.aspect_rules_js/@formatjs+fast-memoize@0.0.0/node_modules/@formatjs/fast-memoize/index.js function memoize(fn, options) { const cache = options && options.cache ? options.cache : cacheDefault; const serializer = options && options.serializer ? options.serializer : serializerDefault; return (options && options.strategy ? options.strategy : strategyDefault)(fn, { cache, serializer }); } function isPrimitive(value) { return value == null || typeof value === "number" || typeof value === "boolean"; } function monadic(fn, cache, serializer, arg) { const cacheKey = isPrimitive(arg) ? arg : serializer(arg); let computedValue = cache.get(cacheKey); if (typeof computedValue === "undefined") { computedValue = fn.call(this, arg); cache.set(cacheKey, computedValue); } return computedValue; } function variadic(fn, cache, serializer) { const args = Array.prototype.slice.call(arguments, 3); const cacheKey = serializer(args); let computedValue = cache.get(cacheKey); if (typeof computedValue === "undefined") { computedValue = fn.apply(this, args); cache.set(cacheKey, computedValue); } return computedValue; } function assemble(fn, context, strategy, cache, serialize) { return strategy.bind(context, fn, cache, serialize); } function strategyDefault(fn, options) { const strategy = fn.length === 1 ? monadic : variadic; return assemble(fn, this, strategy, options.cache.create(), options.serializer); } function strategyVariadic(fn, options) { return assemble(fn, this, variadic, options.cache.create(), options.serializer); } function strategyMonadic(fn, options) { return assemble(fn, this, monadic, options.cache.create(), options.serializer); } const serializerDefault = function() { return JSON.stringify(arguments); }; var ObjectWithoutPrototypeCache = class { constructor() { this.cache = Object.create(null); } get(key) { return this.cache[key]; } set(key, value) { this.cache[key] = value; } }; const cacheDefault = { create: function create() { return new ObjectWithoutPrototypeCache(); } }; const strategies = { variadic: strategyVariadic, monadic: strategyMonadic }; //#endregion //#region packages/ecma402-abstract/utils.js function repeat(s, times) { if (typeof s.repeat === "function") return s.repeat(times); const arr = Array.from({ length: times }); for (let i = 0; i < arr.length; i++) arr[i] = s; return arr.join(""); } function defineProperty(target, name, { value }) { Object.defineProperty(target, name, { configurable: true, enumerable: false, writable: true, value }); } function invariant$1(condition, message, Err = Error) { if (!condition) throw new Err(message); } memoize((...args) => new Intl.NumberFormat(...args), { strategy: strategies.variadic }); const createMemoizedPluralRules = memoize((...args) => new Intl.PluralRules(...args), { strategy: strategies.variadic }); memoize((...args) => new Intl.ListFormat(...args), { strategy: strategies.variadic }); //#endregion //#region packages/ecma402-abstract/NumberFormat/decimal-cache.js /** * Cached function to compute powers of 10 for Decimal.js operations. * This cache significantly reduces overhead in ComputeExponent and ToRawFixed * by memoizing expensive Decimal.pow(10, n) calculations. * * Common exponents (e.g., -20 to 20) are used repeatedly in number formatting, * so caching provides substantial performance benefits. * * @param exponent - Can be a number or Decimal. If Decimal, it will be converted to string for cache key. */ const getPowerOf10 = memoize((exponent) => { return Decimal$1.pow(10, exponent); }); //#endregion //#region packages/ecma402-abstract/NumberFormat/ComputeExponentForMagnitude.js /** * The abstract operation ComputeExponentForMagnitude computes an exponent by which to scale a * number of the given magnitude (power of ten of the most significant digit) according to the * locale and the desired notation (scientific, engineering, or compact). */ function ComputeExponentForMagnitude(internalSlots, magnitude) { const { notation, dataLocaleData, numberingSystem } = internalSlots; switch (notation) { case "standard": return 0; case "scientific": return magnitude.toNumber(); case "engineering": return magnitude.div(3).floor().times(3).toNumber(); default: { invariant$1(notation === "compact", "Invalid notation"); const { compactDisplay, style, currencyDisplay } = internalSlots; let thresholdMap; if (style === "currency" && currencyDisplay !== "name") thresholdMap = (dataLocaleData.numbers.currency[numberingSystem] || dataLocaleData.numbers.currency[dataLocaleData.numbers.nu[0]]).short; else { const decimal = dataLocaleData.numbers.decimal[numberingSystem] || dataLocaleData.numbers.decimal[dataLocaleData.numbers.nu[0]]; thresholdMap = compactDisplay === "long" ? decimal.long : decimal.short; } if (!thresholdMap) return 0; const num = getPowerOf10(magnitude).toString(); const thresholds = Object.keys(thresholdMap); if (num < thresholds[0]) return 0; if (num > thresholds[thresholds.length - 1]) { const magnitudeKey = thresholds[thresholds.length - 1]; if (thresholdMap[magnitudeKey].other === "0") return 0; return magnitudeKey.length - thresholdMap[magnitudeKey].other.match(/0+/)[0].length; } const i = thresholds.indexOf(num); if (i === -1) return 0; const magnitudeKey = thresholds[i]; if (thresholdMap[magnitudeKey].other === "0") return 0; return magnitudeKey.length - thresholdMap[magnitudeKey].other.match(/0+/)[0].length; } } } //#endregion //#region packages/ecma402-abstract/constants.js const ZERO = new Decimal$1(0); const NEGATIVE_ZERO = new Decimal$1(-0); //#endregion //#region packages/ecma402-abstract/NumberFormat/GetUnsignedRoundingMode.js const negativeMapping = { ceil: "zero", floor: "infinity", expand: "infinity", trunc: "zero", halfCeil: "half-zero", halfFloor: "half-infinity", halfExpand: "half-infinity", halfTrunc: "half-zero", halfEven: "half-even" }; const positiveMapping = { ceil: "infinity", floor: "zero", expand: "infinity", trunc: "zero", halfCeil: "half-infinity", halfFloor: "half-zero", halfExpand: "half-infinity", halfTrunc: "half-zero", halfEven: "half-even" }; function GetUnsignedRoundingMode(roundingMode, isNegative) { if (isNegative) return negativeMapping[roundingMode]; return positiveMapping[roundingMode]; } //#endregion //#region packages/ecma402-abstract/NumberFormat/ApplyUnsignedRoundingMode.js function ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode) { if (x.eq(r1) || r1.eq(r2)) return r1; if (x.eq(r2)) return r2; invariant$1(r1.lessThan(x) && x.lessThan(r2), `x should be between r1 and r2 but x=${x}, r1=${r1}, r2=${r2}`); if (unsignedRoundingMode === "zero") return r1; if (unsignedRoundingMode === "infinity") return r2; const d1 = x.minus(r1); const d2 = r2.minus(x); if (d1.lessThan(d2)) return r1; if (d2.lessThan(d1)) return r2; invariant$1(d1.eq(d2), "d1 should be equal to d2"); if (unsignedRoundingMode === "half-zero") return r1; if (unsignedRoundingMode === "half-infinity") return r2; invariant$1(unsignedRoundingMode === "half-even", "unsignedRoundingMode should be half-even"); if (r1.div(r2.minus(r1)).mod(2).isZero()) return r1; return r2; } //#endregion //#region packages/ecma402-abstract/NumberFormat/ToRawFixed.js function ToRawFixedFn(n, f) { return n.times(getPowerOf10(-f)); } function findN1R1(x, f, roundingIncrement) { const n1 = x.times(getPowerOf10(f)).floor().div(roundingIncrement).floor().times(roundingIncrement); return { n1, r1: ToRawFixedFn(n1, f) }; } function findN2R2(x, f, roundingIncrement) { const n2 = x.times(getPowerOf10(f)).ceil().div(roundingIncrement).ceil().times(roundingIncrement); return { n2, r2: ToRawFixedFn(n2, f) }; } /** * https://tc39.es/ecma402/#sec-torawfixed * @param x a finite non-negative Number or BigInt * @param minFraction an integer between 0 and 20 * @param maxFraction an integer between 0 and 20 */ function ToRawFixed(x, minFraction, maxFraction, roundingIncrement, unsignedRoundingMode) { const f = maxFraction; const { n1, r1 } = findN1R1(x, f, roundingIncrement); const { n2, r2 } = findN2R2(x, f, roundingIncrement); const r = ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode); let n, xFinal; let m; if (r.eq(r1)) { n = n1; xFinal = r1; } else { n = n2; xFinal = r2; } if (n.isZero()) m = "0"; else m = n.toString(); let int; if (f !== 0) { let k = m.length; if (k <= f) { m = repeat("0", f - k + 1) + m; k = f + 1; } const a = m.slice(0, k - f); const b = m.slice(m.length - f); m = a + "." + b; int = a.length; } else int = m.length; let cut = maxFraction - minFraction; while (cut > 0 && m[m.length - 1] === "0") { m = m.slice(0, m.length - 1); cut--; } if (m[m.length - 1] === ".") m = m.slice(0, m.length - 1); return { formattedString: m, roundedNumber: xFinal, integerDigitsCount: int, roundingMagnitude: -f }; } //#endregion //#region packages/ecma402-abstract/NumberFormat/ToRawPrecision.js function findN1E1R1(x, p) { const maxN1 = getPowerOf10(p); const minN1 = getPowerOf10(p - 1); let e1 = x.log(10).floor(); const divisor = getPowerOf10(e1.minus(p).plus(1)); let n1 = x.div(divisor).floor(); let r1 = n1.times(divisor); if (n1.greaterThanOrEqualTo(maxN1)) { e1 = e1.plus(1); const newDivisor = getPowerOf10(e1.minus(p).plus(1)); n1 = x.div(newDivisor).floor(); r1 = n1.times(newDivisor); } else if (n1.lessThan(minN1)) { e1 = e1.minus(1); const newDivisor = getPowerOf10(e1.minus(p).plus(1)); n1 = x.div(newDivisor).floor(); r1 = n1.times(newDivisor); } if (r1.lessThanOrEqualTo(x) && n1.lessThan(maxN1) && n1.greaterThanOrEqualTo(minN1)) return { n1, e1, r1 }; let currentE1 = x.div(minN1).log(10).plus(p).minus(1).ceil(); while (true) { const currentDivisor = getPowerOf10(currentE1.minus(p).plus(1)); let currentN1 = x.div(currentDivisor).floor(); if (currentN1.lessThan(maxN1) && currentN1.greaterThanOrEqualTo(minN1)) { const currentR1 = currentN1.times(currentDivisor); if (currentR1.lessThanOrEqualTo(x)) return { n1: currentN1, e1: currentE1, r1: currentR1 }; } currentE1 = currentE1.minus(1); } } function findN2E2R2(x, p) { const maxN2 = getPowerOf10(p); const minN2 = getPowerOf10(p - 1); let e2 = x.log(10).floor(); const divisor = getPowerOf10(e2.minus(p).plus(1)); let n2 = x.div(divisor).ceil(); let r2 = n2.times(divisor); if (n2.greaterThanOrEqualTo(maxN2)) { e2 = e2.plus(1); const newDivisor = getPowerOf10(e2.minus(p).plus(1)); n2 = x.div(newDivisor).ceil(); r2 = n2.times(newDivisor); } else if (n2.lessThan(minN2)) { e2 = e2.minus(1); const newDivisor = getPowerOf10(e2.minus(p).plus(1)); n2 = x.div(newDivisor).ceil(); r2 = n2.times(newDivisor); } if (r2.greaterThanOrEqualTo(x) && n2.lessThan(maxN2) && n2.greaterThanOrEqualTo(minN2)) return { n2, e2, r2 }; let currentE2 = x.div(maxN2).log(10).plus(p).minus(1).floor(); while (true) { const currentDivisor = getPowerOf10(currentE2.minus(p).plus(1)); let currentN2 = x.div(currentDivisor).ceil(); if (currentN2.lessThan(maxN2) && currentN2.greaterThanOrEqualTo(minN2)) { const currentR2 = currentN2.times(currentDivisor); if (currentR2.greaterThanOrEqualTo(x)) return { n2: currentN2, e2: currentE2, r2: currentR2 }; } currentE2 = currentE2.plus(1); } } /** * https://tc39.es/ecma402/#sec-torawprecision * @param x a finite non-negative Number or BigInt * @param minPrecision an integer between 1 and 21 * @param maxPrecision an integer between 1 and 21 */ function ToRawPrecision(x, minPrecision, maxPrecision, unsignedRoundingMode) { const p = maxPrecision; let m; let e; let xFinal; if (x.isZero()) { m = repeat("0", p); e = 0; xFinal = ZERO; } else { const { n1, e1, r1 } = findN1E1R1(x, p); const { n2, e2, r2 } = findN2E2R2(x, p); let r = ApplyUnsignedRoundingMode(x, r1, r2, unsignedRoundingMode); let n; if (r.eq(r1)) { n = n1; e = e1.toNumber(); xFinal = r1; } else { n = n2; e = e2.toNumber(); xFinal = r2; } m = n.toString(); } let int; if (e >= p - 1) { m = m + repeat("0", e - p + 1); int = e + 1; } else if (e >= 0) { m = m.slice(0, e + 1) + "." + m.slice(m.length - (p - (e + 1))); int = e + 1; } else { invariant$1(e < 0, "e should be less than 0"); m = "0." + repeat("0", -e - 1) + m; int = 1; } if (m.includes(".") && maxPrecision > minPrecision) { let cut = maxPrecision - minPrecision; while (cut > 0 && m[m.length - 1] === "0") { m = m.slice(0, m.length - 1); cut--; } if (m[m.length - 1] === ".") m = m.slice(0, m.length - 1); } return { formattedString: m, roundedNumber: xFinal, integerDigitsCount: int, roundingMagnitude: e }; } //#endregion //#region packages/ecma402-abstract/NumberFormat/FormatNumericToString.js /** * https://tc39.es/ecma402/#sec-formatnumberstring */ function FormatNumericToString(intlObject, _x) { let x = _x; let sign; if (x.isZero() && x.isNegative()) { sign = "negative"; x = ZERO; } else { invariant$1(x.isFinite(), "NumberFormatDigitInternalSlots value is not finite"); if (x.lessThan(0)) sign = "negative"; else sign = "positive"; if (sign === "negative") x = x.negated(); } let result; const roundingType = intlObject.roundingType; const unsignedRoundingMode = GetUnsignedRoundingMode(intlObject.roundingMode, sign === "negative"); switch (roundingType) { case "significantDigits": result = ToRawPrecision(x, intlObject.minimumSignificantDigits, intlObject.maximumSignificantDigits, unsignedRoundingMode); break; case "fractionDigits": result = ToRawFixed(x, intlObject.minimumFractionDigits, intlObject.maximumFractionDigits, intlObject.roundingIncrement, unsignedRoundingMode); break; default: let sResult = ToRawPrecision(x, intlObject.minimumSignificantDigits, intlObject.maximumSignificantDigits, unsignedRoundingMode); let fResult = ToRawFixed(x, intlObject.minimumFractionDigits, intlObject.maximumFractionDigits, intlObject.roundingIncrement, unsignedRoundingMode); if (intlObject.roundingType === "morePrecision") if (sResult.roundingMagnitude <= fResult.roundingMagnitude) result = sResult; else result = fResult; else { invariant$1(intlObject.roundingType === "lessPrecision", "Invalid roundingType"); if (sResult.roundingMagnitude <= fResult.roundingMagnitude) result = fResult; else result = sResult; } break; } x = result.roundedNumber; let string = result.formattedString; if (intlObject.trailingZeroDisplay === "stripIfInteger" && x.isInteger()) { let i = string.indexOf("."); if (i > -1) string = string.slice(0, i); } const int = result.integerDigitsCount; const minInteger = intlObject.minimumIntegerDigits; if (int < minInteger) string = repeat("0", minInteger - int) + string; if (sign === "negative") if (x.isZero()) x = NEGATIVE_ZERO; else x = x.negated(); return { roundedNumber: x, formattedString: string }; } //#endregion //#region packages/ecma402-abstract/NumberFormat/ComputeExponent.js /** * The abstract operation ComputeExponent computes an exponent (power of ten) by which to scale x * according to the number formatting settings. It handles cases such as 999 rounding up to 1000, * requiring a different exponent. * * NOT IN SPEC: it returns [exponent, magnitude]. */ function ComputeExponent(internalSlots, x) { if (x.isZero()) return [0, 0]; if (x.isNegative()) x = x.negated(); const xNum = x.toNumber(); let magnitude; if (Number.isFinite(xNum) && Number.isSafeInteger(xNum) && xNum > 0 && xNum <= 999999) magnitude = new Decimal$1(Math.floor(Math.log10(xNum))); else magnitude = x.log(10).floor(); const exponent = ComputeExponentForMagnitude(internalSlots, magnitude); x = x.times(getPowerOf10(-exponent)); const formatNumberResult = FormatNumericToString(internalSlots, x); if (formatNumberResult.roundedNumber.isZero()) return [exponent, magnitude.toNumber()]; const roundedNum = formatNumberResult.roundedNumber.toNumber(); let newMagnitude; if (Number.isFinite(roundedNum) && Number.isSafeInteger(roundedNum) && roundedNum > 0 && roundedNum <= 999999) newMagnitude = new Decimal$1(Math.floor(Math.log10(roundedNum))); else newMagnitude = formatNumberResult.roundedNumber.log(10).floor(); if (newMagnitude.eq(magnitude.minus(exponent))) return [exponent, magnitude.toNumber()]; return [ComputeExponentForMagnitude(internalSlots, magnitude.plus(1)), magnitude.plus(1).toNumber()]; } //#endregion //#region node_modules/.aspect_rules_js/@formatjs_generated+unicode@0.0.0/node_modules/@formatjs_generated/unicode/regex.js const S_UNICODE_REGEX = /[\$\+<->\^`\|~\xA2-\xA6\xA8\xA9\xAC\xAE-\xB1\xB4\xB8\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u03F6\u0482\u058D-\u058F\u0606-\u0608\u060B\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u07FE\u07FF\u0888\u09F2\u09F3\u09FA\u09FB\u0AF1\u0B70\u0BF3-\u0BFA\u0C7F\u0D4F\u0D79\u0E3F\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u166D\u17DB\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2044\u2052\u207A-\u207C\u208A-\u208C\u20A0-\u20C1\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F\u218A\u218B\u2190-\u2307\u230C-\u2328\u232B-\u2429\u2440-\u244A\u249C-\u24E9\u2500-\u2767\u2794-\u27C4\u27C7-\u27E5\u27F0-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2B73\u2B76-\u2BFF\u2CE5-\u2CEA\u2E50\u2E51\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFF\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u309B\u309C\u3190\u3191\u3196-\u319F\u31C0-\u31E5\u31EF\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA700-\uA716\uA720\uA721\uA789\uA78A\uA828-\uA82B\uA836-\uA839\uAA77-\uAA79\uAB5B\uAB6A\uAB6B\uFB29\uFBB2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDCF\uFDFC-\uFDFF\uFE62\uFE64-\uFE66\uFE69\uFF04\uFF0B\uFF1C-\uFF1E\uFF3E\uFF40\uFF5C\uFF5E\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFFC\uFFFD]|\uD800[\uDD37-\uDD3F\uDD79-\uDD89\uDD8C-\uDD8E\uDD90-\uDD9C\uDDA0\uDDD0-\uDDFC]|\uD802[\uDC77\uDC78\uDEC8]|\uD803[\uDD8E\uDD8F\uDED1-\uDED8]|\uD805\uDF3F|\uD807[\uDFD5-\uDFF1]|\uD81A[\uDF3C-\uDF3F\uDF45]|\uD82F\uDC9C|\uD833[\uDC00-\uDCEF\uDCFA-\uDCFC\uDD00-\uDEB3\uDEBA-\uDED0\uDEE0-\uDEF0\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD64\uDD6A-\uDD6C\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDE00-\uDE41\uDE45\uDF00-\uDF56]|\uD835[\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85\uDE86]|\uD838[\uDD4F\uDEFF]|\uD83B[\uDCAC\uDCB0\uDD2E\uDEF0\uDEF1]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD0D-\uDDAD\uDDE6-\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFF]|\uD83D[\uDC00-\uDED8\uDEDC-\uDEEC\uDEF0-\uDEFC\uDF00-\uDFD9\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0-\uDCBB\uDCC0\uDCC1\uDCD0-\uDCD8\uDD00-\uDE57\uDE60-\uDE6D\uDE70-\uDE7C\uDE80-\uDE8A\uDE8E-\uDEC6\uDEC8\uDECD-\uDEDC\uDEDF-\uDEEA\uDEEF-\uDEF8\uDF00-\uDF92\uDF94-\uDFEF\uDFFA]/; //#endregion //#region node_modules/.aspect_rules_js/@formatjs_generated+unicode@0.0.0/node_modules/@formatjs_generated/unicode/digit-mapping.js const digitMapping = { "adlm": [ "šž„", "šž„‘", "šž„’", "šž„“", "šž„”", "šž„•", "šž„–", "šž„—", "šž„˜", "šž„™" ], "ahom": [ "š‘œ°", "š‘œ±", "š‘œ²", "š‘œ³", "š‘œ“", "š‘œµ", "š‘œ¶", "š‘œ·", "š‘œø", "š‘œ¹" ], "arab": [ "Ł ", "Ł”", "Ł¢", "Ł£", "٤", "Ł„", "٦", "٧", "ŁØ", "Ł©" ], "arabext": [ "Ū°", "Ū±", "Ū²", "Ū³", "Ū“", "Ūµ", "Ū¶", "Ū·", "Ūø", "Ū¹" ], "bali": [ "᭐", "į­‘", "į­’", "į­“", "į­”", "į­•", "į­–", "į­—", "᭘", "į­™" ], "beng": [ "০", "ą§§", "ą§Ø", "ą§©", "ą§Ŗ", "ą§«", "৬", "ą§­", "ą§®", "ą§Æ" ], "bhks": [ "𑱐", "𑱑", "𑱒", "𑱓", "𑱔", "𑱕", "𑱖", "𑱗", "š‘±˜", "𑱙" ], "brah": [ "𑁦", "𑁧", "𑁨", "𑁩", "𑁪", "𑁫", "𑁬", "𑁭", "𑁮", "𑁯" ], "cakm": [ "š‘„¶", "š‘„·", "š‘„ø", "š‘„¹", "š‘„ŗ", "š‘„»", "š‘„¼", "š‘„½", "š‘„¾", "š‘„æ" ], "cham": [ "꩐", "ź©‘", "ź©’", "ź©“", "ź©”", "ź©•", "ź©–", "ź©—", "꩘", "ź©™" ], "deva": [ "ą„¦", "ą„§", "ą„Ø", "ą„©", "ą„Ŗ", "ą„«", "ą„¬", "ą„­", "ą„®", "ą„Æ" ], "diak": [ "𑄐", "š‘„‘", "š‘„’", "š‘„“", "š‘„”", "š‘„•", "š‘„–", "š‘„—", "š‘„˜", "š‘„™" ], "fullwide": [ "0", "1", "ļ¼’", "3", "ļ¼”", "5", "ļ¼–", "ļ¼—", "8", "ļ¼™" ], "gong": [ "š‘¶ ", "š‘¶”", "š‘¶¢", "š‘¶£", "𑶤", "š‘¶„", "𑶦", "š‘¶§", "š‘¶Ø", "š‘¶©" ], "gonm": [ "𑵐", "𑵑", "𑵒", "𑵓", "𑵔", "𑵕", "𑵖", "𑵗", "š‘µ˜", "𑵙" ], "gujr": [ "૦", "ą«§", "૨", "ą«©", "૪", "ą««", "૬", "ą«­", "ą«®", "૯" ], "guru": [ "੦", "ą©§", "੨", "ą©©", "੪", "ą©«", "੬", "ą©­", "ą©®", "੯" ], "hanidec": [ "怇", "äø€", "二", "äø‰", "四", "äŗ”", "六", "七", "八", "九" ], "hmng": [ "𖭐", "š–­‘", "š–­’", "š–­“", "š–­”", "š–­•", "š–­–", "š–­—", "š–­˜", "š–­™" ], "hmnp": [ "šž…€", "šž…", "šž…‚", "šž…ƒ", "šž…„", "šž……", "šž…†", "šž…‡", "šž…ˆ", "šž…‰" ], "java": [ "꧐", "ź§‘", "ź§’", "ź§“", "ź§”", "ź§•", "ź§–", "ź§—", "꧘", "ź§™" ], "kali": [ "꤀", "꤁", "꤂", "꤃", "꤄", "꤅", "꤆", "꤇", "꤈", "꤉" ], "khmr": [ "០", "។", "២", "៣", "៤", "ោ", "៦", "៧", "៨", "៩" ], "knda": [ "೦", "ą³§", "೨", "೩", "ą³Ŗ", "೫", "೬", "ą³­", "ą³®", "೯" ], "lana": [ "įŖ€", "᪁", "įŖ‚", "᪃", "įŖ„", "įŖ…", "įŖ†", "įŖ‡", "᪈", "įŖ‰" ], "lanatham": [ "᪐", "įŖ‘", "įŖ’", "įŖ“", "įŖ”", "įŖ•", "įŖ–", "įŖ—", "᪘", "įŖ™" ], "laoo": [ "໐", "໑", "ą»’", "໓", "ą»”", "໕", "ą»–", "ą»—", "໘", "ą»™" ], "lepc": [ "᪐", "įŖ‘", "įŖ’", "įŖ“", "įŖ”", "įŖ•", "įŖ–", "įŖ—", "᪘", "įŖ™" ], "limb": [ "ᄆ", "ᄇ", "ᄈ", "ᄉ", "ᄊ", "į„‹", "ᄌ", "į„", "į„Ž", "į„" ], "mathbold": [ "šŸŽ", "šŸ", "šŸ", "šŸ‘", "šŸ’", "šŸ“", "šŸ”", "šŸ•", "šŸ–", "šŸ—" ], "mathdbl": [ "šŸ˜", "šŸ™", "šŸš", "šŸ›", "šŸœ", "šŸ", "šŸž", "šŸŸ", "šŸ ", "šŸ”" ], "mathmono": [ "šŸ¶", "šŸ·", "šŸø", "šŸ¹", "šŸŗ", "šŸ»", "šŸ¼", "šŸ½", "šŸ¾", "šŸæ" ], "mathsanb": [ "šŸ¬", "šŸ­", "šŸ®", "šŸÆ", "šŸ°", "šŸ±", "šŸ²", "šŸ³", "šŸ“", "šŸµ" ], "mathsans": [ "šŸ¢", "šŸ£", "šŸ¤", "šŸ„", "šŸ¦", "šŸ§", "šŸØ", "šŸ©", "šŸŖ", "šŸ«" ], "mlym": [ "൦", "ąµ§", "൨", "൩", "ąµŖ", "൫", "൬", "ąµ­", "ąµ®", "൯" ], "modi": [ "𑙐", "š‘™‘", "š‘™’", "š‘™“", "š‘™”", "š‘™•", "š‘™–", "š‘™—", "š‘™˜", "š‘™™" ], "mong": [ "᠐", "į ‘", "į ’", "į “", "į ”", "į •", "į –", "į —", "᠘", "į ™" ], "mroo": [ "š–© ", "š–©”", "š–©¢", "š–©£", "𖩤", "š–©„", "𖩦", "š–©§", "š–©Ø", "š–©©" ], "mtei": [ "꯰", "꯱", "꯲", "꯳", "ꯓ", "꯵", "꯶", "꯷", "꯸", "꯹" ], "mymr": [ "၀", "၁", "၂", "၃", "၄", "၅", "၆", "၇", "၈", "၉" ], "mymrshan": [ "႐", "į‚‘", "į‚’", "į‚“", "į‚”", "į‚•", "į‚–", "į‚—", "į‚˜", "į‚™" ], "mymrtlng": [ "ź§°", "ź§±", "ź§²", "ź§³", "ź§“", "ź§µ", "ź§¶", "ź§·", "ź§ø", "ź§¹" ], "newa": [ "𑑐", "š‘‘‘", "š‘‘’", "š‘‘“", "š‘‘”", "š‘‘•", "š‘‘–", "š‘‘—", "š‘‘˜", "š‘‘™" ], "nkoo": [ "߀", "߁", "߂", "߃", "߄", "߅", "߆", "߇", "߈", "߉" ], "olck": [ "᱐", "᱑", "į±’", "᱓", "į±”", "᱕", "į±–", "į±—", "᱘", "į±™" ], "orya": [ "ą­¦", "ą­§", "ą­Ø", "ą­©", "ą­Ŗ", "ą­«", "ą­¬", "ą­­", "ą­®", "ą­Æ" ], "osma": [ "𐒠", "𐒔", "𐒢", "𐒣", "𐒤", "𐒄", "𐒦", "𐒧", "𐒨", "𐒩" ], "rohg": [ "𐓰", "𐓱", "𐓲", "𐓳", "𐓓", "𐓵", "𐓶", "𐓷", "𐓸", "𐓹" ], "saur": [ "꣐", "꣑", "꣒", "꣓", "꣔", "꣕", "꣖", "꣗", "꣘", "꣙" ], "segment": [ "🯰", "🯱", "🯲", "🯳", "🯓", "🯵", "🯶", "🯷", "🯸", "🯹" ], "shrd": [ "𑇐", "𑇑", "𑇒", "𑇓", "𑇔", "𑇕", "𑇖", "𑇗", "š‘‡˜", "𑇙" ], "sind": [ "š‘‹°", "š‘‹±", "š‘‹²", "š‘‹³", "š‘‹“", "š‘‹µ", "š‘‹¶", "š‘‹·", "š‘‹ø", "š‘‹¹" ], "sinh": [ "ą·¦", "ą·§", "ą·Ø", "ą·©", "ą·Ŗ", "ą·«", "ą·¬", "ą·­", "ą·®", "ą·Æ" ], "sora": [ "š‘ƒ°", "š‘ƒ±", "š‘ƒ²", "š‘ƒ³", "š‘ƒ“", "š‘ƒµ", "š‘ƒ¶", "š‘ƒ·", "š‘ƒø", "š‘ƒ¹" ], "sund": [ "į®°", "į®±", "᮲", "᮳", "ᮓ", "᮵", "į®¶", "į®·", "᮸", "᮹" ], "takr": [ "𑛀", "𑛁", "š‘›‚", "š‘›ƒ", "š‘›„", "š‘›…", "𑛆", "𑛇", "š‘›ˆ", "𑛉" ], "talu": [ "᧐", "į§‘", "į§’", "į§“", "į§”", "į§•", "į§–", "į§—", "᧘", "į§™" ], "tamldec": [ "௦", "௧", "௨", "௩", "௪", "௫", "௬", "௭", "௮", "௯" ], "telu": [ "౦", "ą±§", "౨", "౩", "ą±Ŗ", "౫", "౬", "ą±­", "ą±®", "౯" ], "thai": [ "๐", "๑", "ą¹’", "๓", "ą¹”", "๕", "ą¹–", "ą¹—", "๘", "ą¹™" ], "tibt": [ "ą¼ ", "ą¼”", "ą¼¢", "ą¼£", "༤", "༄", "༦", "ą¼§", "༨", "༩" ], "tirh": [ "𑓐", "š‘“‘", "š‘“’", "š‘““", "š‘“”", "š‘“•", "š‘“–", "š‘“—", "š‘“˜", "š‘“™" ], "vaii": [ "ᘠ", "ᘔ", "ᘢ", "ᘣ", "ᘤ", "ᘄ", "ᘦ", "ᘧ", "ᘨ", "ᘩ" ], "wara": [ "š‘£ ", "š‘£”", "š‘£¢", "š‘££", "𑣤", "𑣄", "𑣦", "š‘£§", "𑣨", "𑣩" ], "wcho": [ "šž‹°", "šž‹±", "šž‹²", "šž‹³", "šž‹“", "šž‹µ", "šž‹¶", "šž‹·", "šž‹ø", "šž‹¹" ] }; //#endregion //#region packages/ecma402-abstract/NumberFormat/format_to_parts.js const CARET_S_UNICODE_REGEX = new RegExp(`^${S_UNICODE_REGEX.source}`); const S_DOLLAR_UNICODE_REGEX = new RegExp(`${S_UNICODE_REGEX.source}$`); const CLDR_NUMBER_PATTERN = /[#0](?:[.,][#0]+)*/g; function formatToParts$1(numberResult, data, pl, options) { const { sign, exponent, magnitude } = numberResult; const { notation, style, numberingSystem } = options; const defaultNumberingSystem = data.numbers.nu[0]; let compactNumberPattern = null; if (notation === "compact" && magnitude) compactNumberPattern = getCompactDisplayPattern(numberResult, pl, data, style, options.compactDisplay, options.currencyDisplay, numberingSystem); let nonNameCurrencyPart; if (style === "currency" && options.currencyDisplay !== "name") { const byCurrencyDisplay = data.currencies[options.currency]; if (byCurrencyDisplay) switch (options.currencyDisplay) { case "code": nonNameCurrencyPart = options.currency; break; case "symbol": nonNameCurrencyPart = byCurrencyDisplay.symbol; break; default: nonNameCurrencyPart = byCurrencyDisplay.narrow; break; } else nonNameCurrencyPart = options.currency; } let numberPattern; if (!compactNumberPattern) if (style === "decimal" || style === "unit" || style === "currency" && options.currencyDisplay === "name") numberPattern = getPatternForSign((data.numbers.decimal[numberingSystem] || data.numbers.decimal[defaultNumberingSystem]).standard, sign); else if (style === "currency") numberPattern = getPatternForSign((data.numbers.currency[numberingSystem] || data.numbers.currency[defaultNumberingSystem])[options.currencySign], sign); else numberPattern = getPatternForSign(data.numbers.percent[numberingSystem] || data.numbers.percent[defaultNumberingSystem], sign); else numberPattern = compactNumberPattern; const decimalNumberPattern = CLDR_NUMBER_PATTERN.exec(numberPattern)[0]; numberPattern = numberPattern.replace(CLDR_NUMBER_PATTERN, "{0}").replace(/'(.)'/g, "$1"); if (style === "currency" && options.currencyDisplay !== "name") { const currencyData = data.numbers.currency[numberingSystem] || data.numbers.currency[defaultNumberingSystem]; const afterCurrency = currencyData.currencySpacing.afterInsertBetween; if (afterCurrency && !S_DOLLAR_UNICODE_REGEX.test(nonNameCurrencyPart)) numberPattern = numberPattern.replace("¤{0}", `¤${afterCurrency}{0}`); const beforeCurrency = currencyData.currencySpacing.beforeInsertBetween; if (beforeCurrency && !CARET_S_UNICODE_REGEX.test(nonNameCurrencyPart)) numberPattern = numberPattern.replace("{0}¤", `{0}${beforeCurrency}¤`); } const numberPatternParts = numberPattern.split(/({c:[^}]+}|\{0\}|[¤%\-+])/g); const numberParts = []; const symbols = data.numbers.symbols[numberingSystem] || data.numbers.symbols[defaultNumberingSystem]; for (const part of numberPatternParts) { if (!part) continue; switch (part) { case "{0}": numberParts.push(...partitionNumberIntoParts(symbols, numberResult, notation, exponent, numberingSystem, !compactNumberPattern && (options.useGrouping ?? true), decimalNumberPattern, style, options.roundingIncrement, GetUnsignedRoundingMode(options.roundingMode, sign === -1))); break; case "-": numberParts.push({ type: "minusSign", value: symbols.minusSign }); break; case "+": numberParts.push({ type: "plusSign", value: symbols.plusSign }); break; case "%": numberParts.push({ type: "percentSign", value: symbols.percentSign }); break; case "¤": numberParts.push({ type: "currency", value: nonNameCurrencyPart }); break; default: if (part.startsWith("{c:")) numberParts.push({ type: "compact", value: part.substring(3, part.length - 1) }); else numberParts.push({ type: "literal", value: part }); break; } } switch (style) { case "currency": if (options.currencyDisplay === "name") { const unitPattern = (data.numbers.currency[numberingSystem] || data.numbers.currency[defaultNumberingSystem]).unitPattern; let unitName; const currencyNameData = data.currencies[options.currency]; if (currencyNameData) unitName = selectPlural(pl, numberResult.roundedNumber.times(getPowerOf10(exponent)).toNumber(), currencyNameData.displayName); else unitName = options.currency; const unitPatternParts = unitPattern.split(/(\{[01]\})/g); const result = []; for (const part of unitPatternParts) switch (part) { case "{0}": result.push(...numberParts); break; case "{1}": result.push({ type: "currency", value: unitName }); break; default: if (part) result.push({ type: "literal", value: part }); break; } return result; } else return numberParts; case "unit": { const { unit, unitDisplay } = options; let unitData = data.units.simple[unit]; let unitPattern; if (unitData) unitPattern = selectPlural(pl, numberResult.roundedNumber.times(getPowerOf10(exponent)).toNumber(), data.units.simple[unit][unitDisplay]); else { const [numeratorUnit, denominatorUnit] = unit.split("-per-"); unitData = data.units.simple[numeratorUnit]; const numeratorUnitPattern = selectPlural(pl, numberResult.roundedNumber.times(getPowerOf10(exponent)).toNumber(), data.units.simple[numeratorUnit][unitDisplay]); const perUnitPattern = data.units.simple[denominatorUnit].perUnit[unitDisplay]; if (perUnitPattern) unitPattern = perUnitPattern.replace("{0}", numeratorUnitPattern); else { const perPattern = data.units.compound.per[unitDisplay]; const denominatorPattern = selectPlural(pl, 1, data.units.simple[denominatorUnit][unitDisplay]); unitPattern = unitPattern = perPattern.replace("{0}", numeratorUnitPattern).replace("{1}", denominatorPattern.replace("{0}", "")); } } const result = []; for (const part of unitPattern.split(/(\s*\{0\}\s*)/)) { const interpolateMatch = /^(\s*)\{0\}(\s*)$/.exec(part); if (interpolateMatch) { if (interpolateMatch[1]) result.push({ type: "literal", value: interpolateMatch[1] }); result.push(...numberParts); if (interpolateMatch[2]) result.push({ type: "literal", value: interpolateMatch[2] }); } else if (part) result.push({ type: "unit", value: part }); } return result; } default: return numberParts; } } function partitionNumberIntoParts(symbols, numberResult, notation, exponent, numberingSystem, useGrouping, decimalNumberPattern, style, roundingIncrement, unsignedRoundingMode) { const result = []; let { formattedString: n, roundedNumber: x } = numberResult; if (x.isNaN()) return [{ type: "nan", value: n }]; else if (!x.isFinite()) return [{ type: "infinity", value: n }]; const digitReplacementTable = digitMapping[numberingSystem]; if (digitReplacementTable) n = n.replace(/\d/g, (digit) => digitReplacementTable[+digit] || digit); const decimalSepIndex = n.indexOf("."); let integer; let fraction; if (decimalSepIndex > 0) { integer = n.slice(0, decimalSepIndex); fraction = n.slice(decimalSepIndex + 1); } else integer = n; let shouldUseGrouping = false; if (useGrouping === "always") shouldUseGrouping = true; else if (useGrouping === "min2") shouldUseGrouping = x.greaterThanOrEqualTo(1e4); else if (useGrouping === "auto" || useGrouping) shouldUseGrouping = notation !== "compact" || x.greaterThanOrEqualTo(1e4); if (shouldUseGrouping) { const groupSepSymbol = style === "currency" && symbols.currencyGroup != null ? symbols.currencyGroup : symbols.group; const groups = []; const patternGroups = decimalNumberPattern.split(".")[0].split(","); let primaryGroupingSize = 3; let secondaryGroupingSize = 3; if (patternGroups.length > 1) primaryGroupingSize = patternGroups[patternGroups.length - 1].length; if (patternGroups.length > 2) secondaryGroupingSize = patternGroups[patternGroups.length - 2].length; let i = integer.length - primaryGroupingSize; if (i > 0) { groups.push(integer.slice(i, i + primaryGroupingSize)); for (i -= secondaryGroupingSize; i > 0; i -= secondaryGroupingSize) groups.push(integer.slice(i, i + secondaryGroupingSize)); groups.push(integer.slice(0, i + secondaryGroupingSize)); } else groups.push(integer); while (groups.length > 0) { const integerGroup = groups.pop(); result.push({ type: "integer", value: integerGroup }); if (groups.length > 0) result.push({ type: "group", value: groupSepSymbol }); } } else result.push({ type: "integer", value: integer }); if (fraction !== void 0) { const decimalSepSymbol = style === "currency" && symbols.currencyDecimal != null ? symbols.currencyDecimal : symbols.decimal; result.push({ type: "decimal", value: decimalSepSymbol }, { type: "fraction", value: fraction }); } if ((notation === "scientific" || notation === "engineering") && x.isFinite()) { result.push({ type: "exponentSeparator", value: symbols.exponential }); if (exponent < 0) { result.push({ type: "exponentMinusSign", value: symbols.minusSign }); exponent = -exponent; } const exponentResult = ToRawFixed(new Decimal$1(exponent), 0, 0, roundingIncrement, unsignedRoundingMode); result.push({ type: "exponentInteger", value: exponentResult.formattedString }); } return result; } function getPatternForSign(pattern, sign) { if (pattern.indexOf(";") < 0) pattern = `${pattern};-${pattern}`; const [zeroPattern, negativePattern] = pattern.split(";"); switch (sign) { case 0: return zeroPattern; case -1: return negativePattern; default: return negativePattern.indexOf("-") >= 0 ? negativePattern.replace(/-/g, "+") : `+${zeroPattern}`; } } function getCompactDisplayPattern(numberResult, pl, data, style, compactDisplay, currencyDisplay, numberingSystem) { const { roundedNumber, sign, magnitude } = numberResult; let magnitudeKey = String(10 ** magnitude); const defaultNumberingSystem = data.numbers.nu[0]; let pattern; if (style === "currency" && currencyDisplay !== "name") { const byNumberingSystem = data.numbers.currency; const currencyData = byNumberingSystem[numberingSystem] || byNumberingSystem[defaultNumberingSystem]; let compactPluralRules = currencyData.short?.[magnitudeKey]; if (!compactPluralRules) { const thresholds = Object.keys(currencyData.short || {}); if (thresholds.length > 0 && magnitudeKey > thresholds[thresholds.length - 1]) { magnitudeKey = thresholds[thresholds.length - 1]; compactPluralRules = currencyData.short?.[magnitudeKey]; } } if (!compactPluralRules) return null; pattern = selectPlural(pl, roundedNumber.toNumber(), compactPluralRules); } else { const byNumberingSystem = data.numbers.decimal; const byCompactDisplay = byNumberingSystem[numberingSystem] || byNumberingSystem[defaultNumberingSystem]; let compactPlaralRule = byCompactDisplay[compactDisplay][magnitudeKey]; if (!compactPlaralRule) { const thresholds = Object.keys(byCompactDisplay[compactDisplay]); if (thresholds.length > 0 && magnitudeKey > thresholds[thresholds.length - 1]) { magnitudeKey = thresholds[thresholds.length - 1]; compactPlaralRule = byCompactDisplay[compactDisplay][magnitudeKey]; } } if (!compactPlaralRule) return null; pattern = selectPlural(pl, roundedNumber.toNumber(), compactPlaralRule); } if (pattern === "0") return null; pattern = getPatternForSign(pattern, sign).replace(/([^\s;\-+\d¤]+)/g, "{c:$1}").replace(/0+/, "0"); return pattern; } function selectPlural(pl, x, rules) { return rules[pl.select(x)] || rules.other; } //#endregion //#region packages/ecma402-abstract/NumberFormat/PartitionNumberPattern.js /** * https://tc39.es/ecma402/#sec-partitionnumberpattern */ function PartitionNumberPattern(internalSlots, _x) { let x = _x; let magnitude = 0; const { pl, dataLocaleData, numberingSystem } = internalSlots; const symbols = dataLocaleData.numbers.symbols[numberingSystem] || dataLocaleData.numbers.symbols[dataLocaleData.numbers.nu[0]]; let exponent = 0; let n; if (x.isNaN()) n = symbols.nan; else if (!x.isFinite()) n = symbols.infinity; else { if (!x.isZero()) { invariant$1(x.isFinite(), "Input must be a mathematical value"); if (internalSlots.style == "percent") x = x.times(100); [exponent, magnitude] = ComputeExponent(internalSlots, x); x = x.times(getPowerOf10(-exponent)); } const formatNumberResult = FormatNumericToString(internalSlots, x); n = formatNumberResult.formattedString; x = formatNumberResult.roundedNumber; } let sign; const signDisplay = internalSlots.signDisplay; switch (signDisplay) { case "never": sign = 0; break; case "auto": if (x.isPositive() || x.isNaN()) sign = 0; else sign = -1; break; case "always": if (x.isPositive() || x.isNaN()) sign = 1; else sign = -1; break; case "exceptZero": if (x.isZero()) sign = 0; else if (x.isNegative()) sign = -1; else sign = 1; break; default: invariant$1(signDisplay === "negative", "signDisplay must be \"negative\""); if (x.isNegative() && !x.isZero()) sign = -1; else sign = 0; break; } return formatToParts$1({ roundedNumber: x, formattedString: n, exponent, magnitude, sign }, internalSlots.dataLocaleData, pl, internalSlots); } //#endregion //#region packages/ecma402-abstract/NumberFormat/FormatNumeric.js function FormatNumeric(internalSlots, x) { return PartitionNumberPattern(internalSlots, x).map((p) => p.value).join(""); } //#endregion //#region packages/ecma402-abstract/NumberFormat/CollapseNumberRange.js const PART_TYPES_TO_COLLAPSE = new Set([ "unit", "exponentMinusSign", "minusSign", "plusSign", "percentSign", "exponentSeparator", "percent", "percentSign", "currency", "literal" ]); /** * https://tc39.es/ecma402/#sec-collapsenumberrange * LDML: https://unicode-org.github.io/cldr/ldml/tr35-numbers.html#collapsing-number-ranges */ function CollapseNumberRange(numberFormat, result, { getInternalSlots }) { const internalSlots = getInternalSlots(numberFormat); const symbols = internalSlots.dataLocaleData.numbers.symbols[internalSlots.numberingSystem]; const rangeSignRegex = new RegExp(`s?[${symbols.rangeSign}]s?`); const rangeSignIndex = result.findIndex((r) => r.type === "literal" && rangeSignRegex.test(r.value)); let prefixSignParts = []; for (let i = rangeSignIndex - 1; i >= 0; i--) { if (!PART_TYPES_TO_COLLAPSE.has(result[i].type)) break; prefixSignParts.unshift(result[i]); } if (Array.from(prefixSignParts.map((p) => p.value).join("")).length > 1) { const newResult = Array.from(result); newResult.splice(rangeSignIndex - prefixSignParts.length, prefixSignParts.length); return newResult; } let suffixSignParts = []; for (let i = rangeSignIndex + 1; i < result.length; i++) { if (!PART_TYPES_TO_COLLAPSE.has(result[i].type)) break; suffixSignParts.push(result[i]); } if (Array.from(suffixSignParts.map((p) => p.value).join("")).length > 1) { const newResult = Array.from(result); newResult.splice(rangeSignIndex + 1, suffixSignParts.length); return newResult; } return result; } //#endregion //#region packages/ecma402-abstract/NumberFormat/FormatApproximately.js /** * https://tc39.es/ecma402/#sec-formatapproximately */ function FormatApproximately(internalSlots, result) { const approximatelySign = internalSlots.dataLocaleData.numbers.symbols[internalSlots.numberingSystem].approximatelySign; result.push({ type: "approximatelySign", value: approximatelySign }); return result; } //#endregion //#region packages/ecma402-abstract/NumberFormat/PartitionNumberRangePattern.js /** * https://tc39.es/ecma402/#sec-partitionnumberrangepattern */ function PartitionNumberRangePattern(numberFormat, x, y, { getInternalSlots }) { invariant$1(!x.isNaN() && !y.isNaN(), "Input must be a number", RangeError); const internalSlots = getInternalSlots(numberFormat); const xResult = PartitionNumberPattern(internalSlots, x); const yResult = PartitionNumberPattern(internalSlots, y); if (FormatNumeric(internalSlots, x) === FormatNumeric(internalSlots, y)) { const appxResult = FormatApproximately(internalSlots, xResult); appxResult.forEach((el) => { el.source = "shared"; }); return appxResult; } let result = []; xResult.forEach((el) => { el.source = "startRange"; result.push(el); }); const rangeSeparator = internalSlots.dataLocaleData.numbers.symbols[internalSlots.numberingSystem].rangeSign; result.push({ type: "literal", value: rangeSeparator, source: "shared" }); yResult.forEach((el) => { el.source = "endRange"; result.push(el); }); return CollapseNumberRange(numberFormat, result, { getInternalSlots }); } //#endregion //#region packages/ecma402-abstract/NumberFormat/FormatNumericRange.js /** * https://tc39.es/ecma402/#sec-formatnumericrange */ function FormatNumericRange(numberFormat, x, y, { getInternalSlots }) { return PartitionNumberRangePattern(numberFormat, x, y, { getInternalSlots }).map((part) => part.value).join(""); } //#endregion //#region packages/ecma402-abstract/NumberFormat/FormatNumericRangeToParts.js /** * https://tc39.es/ecma402/#sec-formatnumericrangetoparts */ function FormatNumericRangeToParts(numberFormat, x, y, { getInternalSlots }) { return PartitionNumberRangePattern(numberFormat, x, y, { getInternalSlots }).map((part, index) => ({ type: part.type, value: part.value, source: part.source, result: index.toString() })); } //#endregion //#region packages/ecma262-abstract/ArrayCreate.js /** * https://www.ecma-international.org/ecma-262/11.0/index.html#sec-arraycreate */ function ArrayCreate(len) { return Array.from({ length: len }); } //#endregion //#region packages/ecma402-abstract/NumberFormat/FormatNumericToParts.js function FormatNumericToParts(nf, x, implDetails) { const parts = PartitionNumberPattern(implDetails.getInternalSlots(nf), x); const result = ArrayCreate(0); for (const part of parts) result.push({ type: part.type, value: part.value }); return result; } //#endregion //#region packages/ecma262-abstract/ToObject.js /** * https://tc39.es/ecma262/#sec-toobject */ function ToObject(arg) { if (arg == null) throw new TypeError("undefined/null cannot be converted to object"); return Object(arg); } //#endregion //#region packages/ecma402-abstract/CoerceOptionsToObject.js /** * https://tc39.es/ecma402/#sec-coerceoptionstoobject * @param options * @returns */ function CoerceOptionsToObject(options) { if (typeof options === "undefined") return Object.create(null); return ToObject(options); } //#endregion //#region packages/ecma262-abstract/ToString.js /** * https://tc39.es/ecma262/#sec-tostring */ function ToString(o) { if (typeof o === "symbol") throw TypeError("Cannot convert a Symbol value to a string"); return String(o); } //#endregion //#region packages/ecma402-abstract/GetOption.js /** * https://tc39.es/ecma402/#sec-getoption * @param opts * @param prop * @param type * @param values * @param fallback */ function GetOption(opts, prop, type, values, fallback) { if (typeof opts !== "object") throw new TypeError("Options must be an object"); let value = opts[prop]; if (value !== void 0) { if (type !== "boolean" && type !== "string") throw new TypeError("invalid type"); if (type === "boolean") value = Boolean(value); if (type === "string") value = ToString(value); if (values !== void 0 && !values.filter((val) => val == value).length) throw new RangeError(`${value} is not within ${values.join(", ")}`); return value; } return fallback; } //#endregion //#region packages/ecma402-abstract/GetStringOrBooleanOption.js /** * https://tc39.es/ecma402/#sec-getstringorbooleanoption * @param opts * @param prop * @param values * @param trueValue * @param falsyValue * @param fallback */ function GetStringOrBooleanOption(opts, prop, values, trueValue, falsyValue, fallback) { let value = opts[prop]; if (value === void 0) return fallback; if (value === true) return trueValue; if (Boolean(value) === false) return falsyValue; value = ToString(value); if (value === "true" || value === "false") return fallback; if ((values || []).indexOf(value) === -1) throw new RangeError(`Invalid value ${value}`); return value; } //#endregion //#region packages/ecma262-abstract/HasOwnProperty.js /** * https://www.ecma-international.org/ecma-262/11.0/index.html#sec-hasownproperty */ function HasOwnProperty(o, prop) { return Object.prototype.hasOwnProperty.call(o, prop); } //#endregion //#region packages/ecma402-abstract/NumberFormat/CurrencyDigits.js /** * https://tc39.es/ecma402/#sec-currencydigits */ function CurrencyDigits(c, { currencyDigitsData }) { return HasOwnProperty(currencyDigitsData, c) ? currencyDigitsData[c] : 2; } //#endregion //#region packages/ecma402-abstract/DefaultNumberOption.js /** * https://tc39.es/ecma402/#sec-defaultnumberoption * @param val * @param min * @param max * @param fallback */ function DefaultNumberOption(inputVal, min, max, fallback) { if (inputVal === void 0) return fallback; const val = Number(inputVal); if (isNaN(val) || val < min || val > max) throw new RangeError(`${val} is outside of range [${min}, ${max}]`); return Math.floor(val); } //#endregion //#region packages/ecma402-abstract/GetNumberOption.js /** * https://tc39.es/ecma402/#sec-getnumberoption * @param options * @param property * @param min * @param max * @param fallback */ function GetNumberOption(options, property, minimum, maximum, fallback) { const val = options[property]; return DefaultNumberOption(val, minimum, maximum, fallback); } //#endregion //#region packages/ecma402-abstract/NumberFormat/SetNumberFormatDigitOptions.js const VALID_ROUNDING_INCREMENTS = new Set([ 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1e3, 2e3, 2500, 5e3 ]); /** * https://tc39.es/ecma402/#sec-setnfdigitoptions */ function SetNumberFormatDigitOptions(internalSlots, opts, mnfdDefault, mxfdDefault, notation) { const mnid = GetNumberOption(opts, "minimumIntegerDigits", 1, 21, 1); let mnfd = opts.minimumFractionDigits; let mxfd = opts.maximumFractionDigits; let mnsd = opts.minimumSignificantDigits; let mxsd = opts.maximumSignificantDigits; internalSlots.minimumIntegerDigits = mnid; const roundingIncrement = GetNumberOption(opts, "roundingIncrement", 1, 5e3, 1); invariant$1(VALID_ROUNDING_INCREMENTS.has(roundingIncrement), `Invalid rounding increment value: ${roundingIncrement}. Valid values are ${Array.from(VALID_ROUNDING_INCREMENTS).join(", ")}.`); const roundingMode = GetOption(opts, "roundingMode", "string", [ "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" ], "halfExpand"); const roundingPriority = GetOption(opts, "roundingPriority", "string", [ "auto", "morePrecision", "lessPrecision" ], "auto"); const trailingZeroDisplay = GetOption(opts, "trailingZeroDisplay", "string", ["auto", "stripIfInteger"], "auto"); if (roundingIncrement !== 1) mxfdDefault = mnfdDefault; internalSlots.roundingIncrement = roundingIncrement; internalSlots.roundingMode = roundingMode; internalSlots.trailingZeroDisplay = trailingZeroDisplay; const hasSd = mnsd !== void 0 || mxsd !== void 0; const hasFd = mnfd !== void 0 || mxfd !== void 0; let needSd = true; let needFd = true; if (roundingPriority === "auto") { needSd = hasSd; if (hasSd || !hasFd && notation === "compact") needFd = false; } if (needSd) i