UNPKG

@formatjs/intl-relativetimeformat

Version:

Formats JavaScript dates to relative time strings.

422 lines (421 loc) 15.5 kB
import { LookupSupportedLocales, ResolveLocale } from "@formatjs/intl-localematcher"; //#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/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 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/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/SupportedLocales.js /** * https://tc39.es/ecma402/#sec-supportedlocales * @param availableLocales * @param requestedLocales * @param options */ function SupportedLocales(availableLocales, requestedLocales, options) { let matcher = "best fit"; if (options !== void 0) { options = ToObject(options); matcher = GetOption(options, "localeMatcher", "string", ["lookup", "best fit"], "best fit"); } if (matcher === "best fit") return LookupSupportedLocales(Array.from(availableLocales), requestedLocales); return LookupSupportedLocales(Array.from(availableLocales), requestedLocales); } //#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 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 invariant(condition, message, Err = Error) { if (!condition) throw new Err(message); } const createMemoizedNumberFormat = memoize((...args) => new Intl.NumberFormat(...args), { strategy: strategies.variadic }); const createMemoizedPluralRules = memoize((...args) => new Intl.PluralRules(...args), { strategy: strategies.variadic }); memoize((...args) => new Intl.Locale(...args), { strategy: strategies.variadic }); memoize((...args) => new Intl.ListFormat(...args), { strategy: strategies.variadic }); //#endregion //#region packages/ecma402-abstract/RelativeTimeFormat/InitializeRelativeTimeFormat.js const NUMBERING_SYSTEM_REGEX = /^[a-z0-9]{3,8}(-[a-z0-9]{3,8})*$/i; function InitializeRelativeTimeFormat(rtf, locales, options, { getInternalSlots, availableLocales, relevantExtensionKeys, localeData, getDefaultLocale }) { const internalSlots = getInternalSlots(rtf); internalSlots.initializedRelativeTimeFormat = true; const requestedLocales = CanonicalizeLocaleList(locales); const opt = Object.create(null); const opts = CoerceOptionsToObject(options); opt.localeMatcher = GetOption(opts, "localeMatcher", "string", ["best fit", "lookup"], "best fit"); const numberingSystem = GetOption(opts, "numberingSystem", "string", void 0, void 0); if (numberingSystem !== void 0) { if (!NUMBERING_SYSTEM_REGEX.test(numberingSystem)) throw new RangeError(`Invalid numbering system ${numberingSystem}`); } opt.nu = numberingSystem; const r = ResolveLocale(availableLocales, requestedLocales, opt, relevantExtensionKeys, localeData, getDefaultLocale); const { locale, nu } = r; internalSlots.locale = locale; internalSlots.style = GetOption(opts, "style", "string", [ "long", "narrow", "short" ], "long"); internalSlots.numeric = GetOption(opts, "numeric", "string", ["always", "auto"], "always"); const fields = localeData[r.dataLocale]; invariant(!!fields, `Missing locale data for ${r.dataLocale}`); internalSlots.fields = fields; internalSlots.numberFormat = createMemoizedNumberFormat(locales); internalSlots.pluralRules = createMemoizedPluralRules(locales); internalSlots.numberingSystem = nu; return rtf; } //#endregion //#region packages/ecma262-abstract/SameValue.js /** * https://www.ecma-international.org/ecma-262/11.0/index.html#sec-samevalue */ function SameValue(x, y) { if (Object.is) return Object.is(x, y); if (x === y) return x !== 0 || 1 / x === 1 / y; return x !== x && y !== y; } //#endregion //#region packages/ecma262-abstract/Type.js /** * https://www.ecma-international.org/ecma-262/11.0/index.html#sec-type */ function Type(x) { if (x === null) return "Null"; if (typeof x === "undefined") return "Undefined"; if (typeof x === "function" || typeof x === "object") return "Object"; if (typeof x === "number") return "Number"; if (typeof x === "boolean") return "Boolean"; if (typeof x === "string") return "String"; if (typeof x === "symbol") return "Symbol"; if (typeof x === "bigint") return "BigInt"; } //#endregion //#region packages/ecma402-abstract/RelativeTimeFormat/SingularRelativeTimeUnit.js /** * https://tc39.es/proposal-intl-relative-time/#sec-singularrelativetimeunit * @param unit */ function SingularRelativeTimeUnit(unit) { invariant(Type(unit) === "String", "unit must be a string"); if (unit === "seconds") return "second"; if (unit === "minutes") return "minute"; if (unit === "hours") return "hour"; if (unit === "days") return "day"; if (unit === "weeks") return "week"; if (unit === "months") return "month"; if (unit === "quarters") return "quarter"; if (unit === "years") return "year"; if (unit !== "second" && unit !== "minute" && unit !== "hour" && unit !== "day" && unit !== "week" && unit !== "month" && unit !== "quarter" && unit !== "year") throw new RangeError("invalid unit"); return unit; } //#endregion //#region packages/ecma402-abstract/PartitionPattern.js /** * Partition a pattern into a list of literals and placeholders * https://tc39.es/ecma402/#sec-partitionpattern * @param pattern */ function PartitionPattern(pattern) { const result = []; let beginIndex = pattern.indexOf("{"); let endIndex = 0; let nextIndex = 0; const length = pattern.length; while (beginIndex < pattern.length && beginIndex > -1) { endIndex = pattern.indexOf("}", beginIndex); invariant(endIndex > beginIndex, `Invalid pattern ${pattern}`); if (beginIndex > nextIndex) result.push({ type: "literal", value: pattern.substring(nextIndex, beginIndex) }); result.push({ type: pattern.substring(beginIndex + 1, endIndex), value: void 0 }); nextIndex = endIndex + 1; beginIndex = pattern.indexOf("{", nextIndex); } if (nextIndex < length) result.push({ type: "literal", value: pattern.substring(nextIndex, length) }); return result; } //#endregion //#region packages/ecma402-abstract/RelativeTimeFormat/MakePartsList.js function MakePartsList(pattern, unit, parts) { const patternParts = PartitionPattern(pattern); const result = []; for (const patternPart of patternParts) if (patternPart.type === "literal") result.push({ type: "literal", value: patternPart.value }); else { invariant(patternPart.type === "0", `Malformed pattern ${pattern}`); for (const part of parts) result.push({ type: part.type, value: part.value, unit }); } return result; } //#endregion //#region packages/ecma402-abstract/RelativeTimeFormat/PartitionRelativeTimePattern.js function PartitionRelativeTimePattern(rtf, value, unit, { getInternalSlots }) { invariant(Type(value) === "Number", `value must be number, instead got ${typeof value}`, TypeError); invariant(Type(unit) === "String", `unit must be number, instead got ${typeof value}`, TypeError); if (isNaN(value) || !isFinite(value)) throw new RangeError(`Invalid value ${value}`); const resolvedUnit = SingularRelativeTimeUnit(unit); const { fields, style, numeric, pluralRules, numberFormat } = getInternalSlots(rtf); let entry = resolvedUnit; if (style === "short") entry = `${resolvedUnit}-short`; else if (style === "narrow") entry = `${resolvedUnit}-narrow`; if (!(entry in fields)) entry = resolvedUnit; const patterns = fields[entry]; if (numeric === "auto") { if (ToString(value) in patterns) return [{ type: "literal", value: patterns[ToString(value)] }]; } let tl = "future"; if (SameValue(value, -0) || value < 0) tl = "past"; const po = patterns[tl]; const fv = typeof numberFormat.formatToParts === "function" ? numberFormat.formatToParts(Math.abs(value)) : [{ type: "literal", value: numberFormat.format(Math.abs(value)), unit }]; const pattern = po[pluralRules.select(value)]; return MakePartsList(pattern, resolvedUnit, fv); } //#endregion //#region packages/intl-relativetimeformat/get_internal_slots.ts const internalSlotMap = /* @__PURE__ */ new WeakMap(); function getInternalSlots(x) { let internalSlots = internalSlotMap.get(x); if (!internalSlots) { internalSlots = Object.create(null); internalSlotMap.set(x, internalSlots); } return internalSlots; } //#endregion //#region packages/intl-relativetimeformat/index.ts var RelativeTimeFormat = class RelativeTimeFormat { constructor(locales, options) { if (!(this && this instanceof RelativeTimeFormat ? this.constructor : void 0)) throw new TypeError("Intl.RelativeTimeFormat must be called with 'new'"); return InitializeRelativeTimeFormat(this, locales, options, { getInternalSlots, availableLocales: RelativeTimeFormat.availableLocales, relevantExtensionKeys: RelativeTimeFormat.relevantExtensionKeys, localeData: RelativeTimeFormat.localeData, getDefaultLocale: RelativeTimeFormat.getDefaultLocale }); } format(value, unit) { if (typeof this !== "object") throw new TypeError("format was called on a non-object"); if (!getInternalSlots(this).initializedRelativeTimeFormat) throw new TypeError("format was called on a invalid context"); return PartitionRelativeTimePattern(this, Number(value), ToString(unit), { getInternalSlots }).map((el) => el.value).join(""); } formatToParts(value, unit) { if (typeof this !== "object") throw new TypeError("formatToParts was called on a non-object"); if (!getInternalSlots(this).initializedRelativeTimeFormat) throw new TypeError("formatToParts was called on a invalid context"); return PartitionRelativeTimePattern(this, Number(value), ToString(unit), { getInternalSlots }); } resolvedOptions() { if (typeof this !== "object") throw new TypeError("resolvedOptions was called on a non-object"); const internalSlots = getInternalSlots(this); if (!internalSlots.initializedRelativeTimeFormat) throw new TypeError("resolvedOptions was called on a invalid context"); return { locale: internalSlots.locale, style: internalSlots.style, numeric: internalSlots.numeric, numberingSystem: internalSlots.numberingSystem }; } static supportedLocalesOf(locales, options) { return SupportedLocales(RelativeTimeFormat.availableLocales, CanonicalizeLocaleList(locales), options); } static __addLocaleData(...data) { for (const { data: d, locale } of data) { const minimizedLocale = new Intl.Locale(locale).minimize().toString(); RelativeTimeFormat.localeData[locale] = RelativeTimeFormat.localeData[minimizedLocale] = d; RelativeTimeFormat.availableLocales.add(minimizedLocale); RelativeTimeFormat.availableLocales.add(locale); if (!RelativeTimeFormat.__defaultLocale) RelativeTimeFormat.__defaultLocale = minimizedLocale; } } static { this.localeData = {}; } static { this.availableLocales = /* @__PURE__ */ new Set(); } static { this.__defaultLocale = ""; } static getDefaultLocale() { return RelativeTimeFormat.__defaultLocale; } static { this.relevantExtensionKeys = ["nu"]; } static { this.polyfilled = true; } }; try { if (typeof Symbol !== "undefined") Object.defineProperty(RelativeTimeFormat.prototype, Symbol.toStringTag, { value: "Intl.RelativeTimeFormat", writable: false, enumerable: false, configurable: true }); Object.defineProperty(RelativeTimeFormat.prototype.constructor, "length", { value: 0, writable: false, enumerable: false, configurable: true }); Object.defineProperty(RelativeTimeFormat.supportedLocalesOf, "length", { value: 1, writable: false, enumerable: false, configurable: true }); } catch {} //#endregion //#region packages/intl-relativetimeformat/polyfill-force.ts Object.defineProperty(Intl, "RelativeTimeFormat", { value: RelativeTimeFormat, writable: true, enumerable: false, configurable: true }); const buf = globalThis.__FORMATJS_RELATIVETIMEFORMAT_DATA__; if (buf) { for (const d of buf) RelativeTimeFormat.__addLocaleData(d); delete globalThis.__FORMATJS_RELATIVETIMEFORMAT_DATA__; } //#endregion //# sourceMappingURL=polyfill-force.js.map