{"version":3,"file":"IntlCache-WZk0rKvj.mjs","names":[],"sources":["../src/settings/settings.ts","../src/errors/formattingErrors.ts","../src/formatting/custom-formats/CutoffFormat/constants.ts","../src/formatting/custom-formats/CutoffFormat/CutoffFormat.ts","../src/cache/IntlCache.ts"],"sourcesContent":["export const libraryDefaultLocale = 'en' as const;\nexport const defaultTimeout = 60000;\n","export const createInvalidCutoffStyleError = (style: string) =>\n  `generaltranslation Formatting Error: Invalid cutoff style: ${style}.`;\n","import { CutoffFormatStyle, ResolvedTerminatorOptions } from './types';\n\nexport const DEFAULT_CUTOFF_FORMAT_STYLE: CutoffFormatStyle = 'ellipsis';\n\nexport const DEFAULT_TERMINATOR_KEY = 'DEFAULT_TERMINATOR_KEY';\n\nexport const TERMINATOR_MAP: Record<\n  CutoffFormatStyle,\n  Record<string | typeof DEFAULT_TERMINATOR_KEY, ResolvedTerminatorOptions>\n> = {\n  ellipsis: {\n    fr: {\n      terminator: '…',\n      separator: '\\u202F',\n    },\n    zh: {\n      terminator: '……',\n      separator: undefined,\n    },\n    ja: {\n      terminator: '……',\n      separator: undefined,\n    },\n    [DEFAULT_TERMINATOR_KEY]: {\n      terminator: '…',\n      separator: undefined,\n    },\n  },\n  none: {\n    [DEFAULT_TERMINATOR_KEY]: {\n      terminator: undefined,\n      separator: undefined,\n    },\n  },\n};\n","import { createInvalidCutoffStyleError } from '../../../errors/formattingErrors';\nimport { libraryDefaultLocale } from '../../../settings/settings';\nimport {\n  DEFAULT_CUTOFF_FORMAT_STYLE,\n  DEFAULT_TERMINATOR_KEY,\n  TERMINATOR_MAP,\n} from './constants';\nimport {\n  CutoffFormat,\n  CutoffFormatOptions,\n  CutoffFormatStyle,\n  PostpendedCutoffParts,\n  PrependedCutoffParts,\n  ResolvedCutoffFormatOptions,\n  ResolvedTerminatorOptions,\n} from './types';\n\nexport class CutoffFormatConstructor implements CutoffFormat {\n  private locale: string;\n  private options: ResolvedCutoffFormatOptions;\n  private additionLength: number;\n  /**\n   * Constructor\n   * @param {Intl.LocalesArgument} locales - The locales to use for formatting.\n   * @param {CutoffFormatOptions} options - The options for formatting.\n   * @param {number} [options.maxChars] - The maximum number of characters to display.\n   * - Undefined values are treated as no cutoff.\n   * - Negative values follow .slice() behavior and terminator will be added before the value.\n   * - 0 will result in an empty string.\n   * - If cutoff results in an empty string, no terminator is added.\n   * @param {CutoffFormatStyle} [options.style='ellipsis'] - The style of the terminator.\n   * @param {string} [options.terminator] - Optional override the terminator to use.\n   * @param {string} [options.separator] - Optional override the separator to use between the terminator and the value.\n   * - If no terminator is provided, then separator is ignored.\n   *\n   * @example\n   * const format = new CutoffFormat('en', { maxChars: 5 });\n   * format.format('Hello, world!'); // 'Hello...'\n   *\n   * const format = new CutoffFormat('en', { maxChars: -3 });\n   * format.format('Hello, world!'); // '...ld!'\n   */\n  constructor(\n    locales: Intl.LocalesArgument,\n    options: CutoffFormatOptions = {}\n  ) {\n    // Determine locale (this replicates Intl.NumberFormat behavior including silent failure)\n    try {\n      // Normalize locales to string\n      const localesList = !locales\n        ? [libraryDefaultLocale]\n        : Array.isArray(locales)\n          ? locales.map((l) => String(l))\n          : [String(locales)];\n      const canonicalLocales = Intl.getCanonicalLocales(localesList);\n      this.locale = canonicalLocales.length\n        ? canonicalLocales[0]\n        : libraryDefaultLocale;\n    } catch {\n      this.locale = libraryDefaultLocale;\n    }\n\n    // Follows Intl.NumberFormat behavior of throwing an error when currency is invalid\n    if (!TERMINATOR_MAP[options.style ?? DEFAULT_CUTOFF_FORMAT_STYLE]) {\n      throw new Error(\n        createInvalidCutoffStyleError(\n          options.style ?? DEFAULT_CUTOFF_FORMAT_STYLE\n        )\n      );\n    }\n\n    // Resolve terminator options.\n    let style: CutoffFormatStyle | undefined;\n    let presetTerminatorOptions: ResolvedTerminatorOptions | undefined;\n    if (options.maxChars !== undefined) {\n      style = options.style ?? DEFAULT_CUTOFF_FORMAT_STYLE;\n      // TODO: need more sophisticated locale negotiation if we want to add support for region/script/etc.-specific terminators in the future\n      const languageCode = new Intl.Locale(this.locale).language;\n      presetTerminatorOptions =\n        TERMINATOR_MAP[style][languageCode] ||\n        TERMINATOR_MAP[style][DEFAULT_TERMINATOR_KEY];\n    }\n    let terminator: ResolvedTerminatorOptions['terminator'] =\n      options.terminator ?? presetTerminatorOptions?.terminator;\n    let separator: ResolvedTerminatorOptions['separator'] =\n      terminator != null\n        ? (options.separator ?? presetTerminatorOptions?.separator)\n        : undefined;\n    // // Remove terminator and separator if maxChars does have enough space\n    this.additionLength = (terminator?.length ?? 0) + (separator?.length ?? 0);\n    if (\n      options.maxChars !== undefined &&\n      Math.abs(options.maxChars) < this.additionLength\n    ) {\n      terminator = undefined;\n      separator = undefined;\n    }\n\n    this.options = {\n      maxChars: options.maxChars,\n      style,\n      terminator,\n      separator,\n    };\n  }\n\n  /**\n   * Format a value according to the cutoff options, returning a formatted string.\n   *\n   * @param {string} value - The string value to format with cutoff behavior.\n   * @returns {string} The formatted string with terminator applied if cutoff occurs.\n   *\n   * @example\n   * const formatter = new CutoffFormatConstructor('en', { maxChars: 8, style: 'ellipsis' });\n   * formatter.format('Hello, world!'); // Returns 'Hello, w...'\n   */\n  format(value: string): string {\n    return this.formatToParts(value).join('');\n  }\n\n  /**\n   * Format a value to parts according to the cutoff options, returning an array of string parts.\n   * This method breaks down the formatted result into individual components for more granular control.\n   *\n   * @param {string} value - The string value to format with cutoff behavior.\n   * @returns {PrependedCutoffParts | PostpendedCutoffParts} An array of string parts representing the formatted result.\n   *   - For positive maxChars: [cutoffValue, separator?, terminator?]\n   *   - For negative maxChars: [terminator?, separator?, cutoffValue]\n   *   - For no cutoff: [originalValue]\n   *\n   * @example\n   * const formatter = new CutoffFormatConstructor('en', { maxChars: 5, style: 'ellipsis' });\n   * formatter.formatToParts('Hello, world!'); // Returns ['Hello', '...']\n   */\n  formatToParts(value: string): PrependedCutoffParts | PostpendedCutoffParts {\n    const { maxChars, terminator, separator } = this.options;\n\n    // Slice our value\n    // const additionLength = (terminator?.length ?? 0) + (separator?.length ?? 0);\n    const adjustedChars =\n      maxChars === undefined || Math.abs(maxChars) >= value.length\n        ? maxChars\n        : maxChars >= 0\n          ? Math.max(0, maxChars - this.additionLength)\n          : Math.min(0, maxChars + this.additionLength);\n    const slicedValue =\n      adjustedChars !== undefined && adjustedChars > -1\n        ? value.slice(0, adjustedChars)\n        : value.slice(adjustedChars);\n\n    // No cutoff, no terminator -> value only\n    if (\n      maxChars == null ||\n      adjustedChars == null ||\n      adjustedChars === 0 ||\n      terminator == null ||\n      value.length <= Math.abs(maxChars)\n    ) {\n      return [slicedValue];\n    }\n\n    // Postpended cutoff.\n    if (adjustedChars > 0) {\n      return separator != null\n        ? [slicedValue, separator, terminator]\n        : [slicedValue, terminator];\n    }\n    // Prepended cutoff.\n    else {\n      return separator != null\n        ? [terminator, separator, slicedValue]\n        : [terminator, slicedValue];\n    }\n  }\n\n  /**\n   * Get the resolved options\n   * @returns {ResolvedCutoffFormatOptions} The resolved options.\n   */\n  resolvedOptions(): ResolvedCutoffFormatOptions {\n    return this.options;\n  }\n}\n","import { libraryDefaultLocale } from '../settings/settings';\nimport { CutoffFormatConstructor } from '../formatting/custom-formats/CutoffFormat/CutoffFormat';\nimport {\n  ConstructorType,\n  CustomIntlConstructors,\n  CustomIntlType,\n  IntlCacheObject,\n} from './types';\n\n/**\n * Object mapping constructor names to their respective constructor functions\n * Includes all native Intl constructors plus custom ones like CutoffFormat\n */\nconst CustomIntl: CustomIntlType = {\n  Collator: Intl.Collator,\n  DateTimeFormat: Intl.DateTimeFormat,\n  DisplayNames: Intl.DisplayNames,\n  ListFormat: Intl.ListFormat,\n  Locale: Intl.Locale,\n  NumberFormat: Intl.NumberFormat,\n  PluralRules: Intl.PluralRules,\n  RelativeTimeFormat: Intl.RelativeTimeFormat,\n  Segmenter: Intl.Segmenter,\n  CutoffFormat: CutoffFormatConstructor,\n};\n\n/**\n * Cache for Intl and custom format instances to avoid repeated instantiation\n * Uses a two-level structure: constructor name -> cache key -> instance.\n */\nclass IntlCache {\n  private cache: IntlCacheObject;\n\n  constructor() {\n    this.cache = {};\n  }\n\n  /**\n   * Generates a consistent cache key from locales and options.\n   * Handles all LocalesArgument types (string, Locale, array, undefined).\n   */\n  private _generateKey(locales: Intl.LocalesArgument, options = {}) {\n    // Normalize locales to string representation\n    const localeKey = !locales\n      ? 'undefined'\n      : Array.isArray(locales)\n        ? locales.map((l) => String(l)).join(',')\n        : String(locales);\n\n    // Sort option keys to ensure consistent key generation regardless of property order\n    const sortedOptions = options\n      ? JSON.stringify(options, Object.keys(options).sort())\n      : '{}';\n    return `${localeKey}:${sortedOptions}`;\n  }\n\n  /**\n   * Gets a cached Intl instance or creates a new one if not found\n   * @param constructor The name of the Intl constructor to use.\n   * @param args Constructor arguments (locales, options).\n   * @returns Cached or newly created Intl instance.\n   */\n  get<K extends keyof CustomIntlConstructors>(\n    constructor: K,\n    ...args: ConstructorParameters<CustomIntlConstructors[K]>\n  ): InstanceType<ConstructorType<K>> {\n    const [locales = libraryDefaultLocale, options = {}] = args;\n    const key = this._generateKey(locales, options);\n    let intlObject = this.cache[constructor]?.[key];\n\n    if (intlObject === undefined) {\n      // Create new instance and cache it\n      intlObject = new CustomIntl[constructor](...args);\n      if (!this.cache[constructor]) this.cache[constructor] = {};\n      this.cache[constructor][key] = intlObject;\n    }\n\n    return intlObject;\n  }\n}\n\n/**\n * Global instance of the Intl cache for use throughout the application\n */\nexport const intlCache = new IntlCache();\n"],"mappings":"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"}