{"version":3,"file":"IntlCache-DRDle6ei.cjs","names":[],"sources":["../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 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  PostpendedCutoffParts,\n  PrependedCutoffParts,\n  ResolvedCutoffFormatOptions,\n} from './types';\n\nexport class CutoffFormatConstructor implements CutoffFormat {\n  private locale: string;\n  private options: ResolvedCutoffFormatOptions;\n  private additionLength: number;\n\n  private static resolveLocale(locales: Intl.LocalesArgument) {\n    try {\n      // Normalize locales to string\n      const localesList = !locales\n        ? [libraryDefaultLocale]\n        : Array.isArray(locales)\n          ? locales.map(String)\n          : [String(locales)];\n      const [canonicalLocale] = Intl.getCanonicalLocales(localesList);\n      return canonicalLocale ?? libraryDefaultLocale;\n    } catch {\n      return libraryDefaultLocale;\n    }\n  }\n\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    this.locale = CutoffFormatConstructor.resolveLocale(locales);\n\n    // Follows Intl.NumberFormat behavior of throwing an error when currency is invalid\n    const style = options.style ?? DEFAULT_CUTOFF_FORMAT_STYLE;\n    if (!TERMINATOR_MAP[style]) {\n      throw new Error(createInvalidCutoffStyleError(style));\n    }\n\n    // Resolve terminator options.\n    // TODO: need more sophisticated locale negotiation if we want to add support for region/script/etc.-specific terminators in the future\n    const presetTerminatorOptions =\n      options.maxChars === undefined\n        ? undefined\n        : TERMINATOR_MAP[style][new Intl.Locale(this.locale).language] ||\n          TERMINATOR_MAP[style][DEFAULT_TERMINATOR_KEY];\n    let terminator = options.terminator ?? presetTerminatorOptions?.terminator;\n    let separator =\n      terminator != null\n        ? (options.separator ?? presetTerminatorOptions?.separator)\n        : undefined;\n    // Remove terminator and separator if maxChars cannot fit them.\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: options.maxChars === undefined ? undefined : 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 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    return separator != null\n      ? [terminator, separator, slicedValue]\n      : [terminator, slicedValue];\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  /**\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 cache = this.cache[constructor];\n    if (cache === undefined) {\n      cache = {};\n      this.cache[constructor] = cache;\n    }\n    let intlObject = cache[key];\n\n    if (intlObject === undefined) {\n      // Create new instance and cache it\n      intlObject = new CustomIntl[constructor](...args);\n      cache[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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"}