UNPKG

@hi18n/core

Version:

Message internationalization meets immutability and type-safety - core runtime

1 lines 29.1 kB
{"version":3,"file":"index.mjs","names":["evaluateMessage","parseMessage","MessageError","MissingLocaleError","MissingTranslationError","NoLocaleError","defaultErrorHandler","msg","s","todo","translationId","book","id","_book","Book","constructor","catalogs","options","_loaders","_handleError","handleError","_implicitLocale","implicitLocale","locale","catalog","Object","entries","_looseLocale","Error","hasOwn","loadCatalog","loader","default","e","level","Catalog","data","getCompiledMessage","_compiled","getTranslator","locales","selectLocale","throwPromise","t","compileAndEvaluateMessage","timeZone","params","dynamic","translateWithComponents","interpolator","collect","wrap","preloadCatalogs","localesArray","Array","isArray","filteredLocales","push","length","error","availableLocales","keys","cause","getDefaultTimeZone","Intl","DateTimeFormat","resolvedOptions","o","prototype","hasOwnProperty","call"],"sources":["../src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any */\n\nimport { CompiledMessage } from \"./msgfmt.js\";\nimport { EvalOption, evaluateMessage } from \"./msgfmt-eval.js\";\nimport { parseMessage } from \"./msgfmt-parser.js\";\nimport type {\n ComponentPlaceholder,\n InferredMessageType,\n} from \"./msgfmt-parser-types.js\";\nimport {\n MessageError,\n MissingLocaleError,\n MissingTranslationError,\n NoLocaleError,\n} from \"./errors.js\";\nimport {\n defaultErrorHandler,\n ErrorHandler,\n ErrorLevel,\n} from \"./error-handling.js\";\n\nexport type { ComponentPlaceholder } from \"./msgfmt-parser-types.js\";\nexport * from \"./errors.js\";\nexport * from \"./error-handling.js\";\n\ndeclare const messageBrandSymbol: unique symbol;\ndeclare const translationIdBrandSymbol: unique symbol;\n\n/**\n * A subtype of `string` that represents translation messages.\n *\n * @param Args parameters required by this message\n *\n * @since 0.1.0 (`@hi18n/core`)\n */\nexport type Message<Args = {}> = string & {\n [messageBrandSymbol]: (args: Args) => void;\n};\n\n/**\n * A base type for a vocabulary.\n *\n * A vocabulary here means a set of translation ids required for this book of translations.\n *\n * @since 0.1.0 (`@hi18n/core`)\n */\nexport type VocabularyBase = Record<string, Message<any>>;\n\n/**\n * Extracts parameters required by the translated message.\n *\n * @param M the message being instantiated.\n * @param C replacement for the component interpolation (like `<0></0>` or `<link></link>`).\n *\n * @since 0.1.0 (`@hi18n/core`)\n */\nexport type MessageArguments<\n M extends Message<any>,\n C\n> = InstantiateComponentTypes<\n InjectAdditionalParams<AbstractMessageArguments<M>>,\n C\n>;\n\n// It if uses Date, we need timeZone as well.\nexport type InjectAdditionalParams<Args> = true extends HasDate<\n Args[keyof Args]\n>\n ? Args & { timeZone: string }\n : Args;\n\nexport type HasDate<T> = T extends Date ? true : never;\n\nexport type AbstractMessageArguments<M extends Message<any>> =\n M extends Message<infer Args> ? Args : never;\n\nexport type InstantiateComponentTypes<Args, C> = {\n [K in keyof Args]: InstantiateComponentType<Args[K], C>;\n};\nexport type InstantiateComponentType<T, C> = T extends ComponentPlaceholder\n ? C\n : T;\n\n/**\n * A subtype of `string` that represents a dynamically-managed translation id.\n *\n * @param Vocabulary the vocabulary type of the Book it refers to\n * @param Args parameters required by this message\n *\n * @since 0.1.1 (`@hi18n/core`)\n */\nexport type TranslationId<\n Vocabulary extends VocabularyBase,\n Args = {}\n> = string & {\n [translationIdBrandSymbol]: (catalog: Vocabulary, args: Args) => void;\n};\n\n/**\n * Extracts the translation ids that don't take parameters.\n *\n * @param Vocabulary the vocabulary, a set of translation ids we can use for this book of translations.\n * @param K a dummy parameter to do a union distribution\n *\n * @since 0.1.0 (`@hi18n/core`)\n */\nexport type SimpleMessageKeys<\n Vocabulary extends VocabularyBase,\n K extends string & keyof Vocabulary = string & keyof Vocabulary\n> = K extends unknown\n ? {} extends MessageArguments<Vocabulary[K], never>\n ? K\n : never\n : never;\n\n/**\n * Infers the appropriate type for the translated message.\n *\n * At runtime, it just returns the first argument.\n *\n * @param s the translated message\n * @returns the first argument\n *\n * @since 0.1.0 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * export default new Book<Vocabulary>({\n * \"example/greeting\": msg(\"Hello, {name}!\"),\n * });\n * ```\n */\nexport function msg<S extends string>(s: S): InferredMessageType<S> {\n return s as InferredMessageType<S>;\n}\n\n/**\n * Same as {@link msg} but can be used to indicate an untranslated state.\n *\n * At runtime, it just returns the first argument.\n *\n * @param s the translated message\n * @returns the first argument\n *\n * @since 0.1.3 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * export default new Book<Vocabulary>({\n * \"example/greeting\": msg.todo(\"Hello, {name}!\"),\n * });\n * ```\n */\nmsg.todo = function todo<S extends string>(s: S): InferredMessageType<S> {\n return s as InferredMessageType<S>;\n};\n\n/**\n * Marks a translation id as dynamically used with {@link CompoundTranslatorFunction.dynamic t.dynamic}.\n *\n * At runtime, it just returns the second argument.\n *\n * @param book the book the id is linked to. Just discarded at runtime.\n * @param id the translation id.\n * @returns the second argument\n *\n * @since 0.1.1 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const menus = [\n * {\n * url: \"https://example.com/home\",\n * titleId: translationId(book, \"example/navigation/home\"),\n * },\n * {\n * url: \"https://example.com/map\",\n * titleId: translationId(book, \"example/navigation/map\"),\n * },\n * ];\n *\n * const { t } = getTranslator(book, \"en\");\n * t.dynamic(menus[i].titleId);\n * ```\n */\nexport function translationId<\n Vocabulary extends VocabularyBase,\n K extends string & keyof Vocabulary\n>(\n book: Book<Vocabulary>,\n id: K\n): TranslationId<Vocabulary, AbstractMessageArguments<Vocabulary[K]>> {\n const _book = book;\n return id as string as TranslationId<\n Vocabulary,\n AbstractMessageArguments<Vocabulary[K]>\n >;\n}\n\n/**\n * A set of translated messages, containing translations for all supported locales.\n *\n * In other words, a book is a set of {@link Catalog}s for all languages.\n *\n * @since 0.1.0 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * type Vocabulary = {\n * \"example/greeting\": Message<{ name: string }>;\n * };\n * export const book = new Book<Vocabulary>({\n * en: catalogEn,\n * ja: catalogJa,\n * });\n * ```\n *\n * @example You can use `import()` to lazy-load catalogs.\n * Note that you need to use extra setup to avoid the\n * \"Catalog not loaded\" error.\n *\n * ```ts\n * type Vocabulary = {\n * \"example/greeting\": Message<{ name: string }>;\n * };\n * export const book = new Book<Vocabulary>({\n * en: () => import(\"./en\"),\n * ja: () => import(\"./ja\"),\n * });\n * ```\n */\nexport class Book<Vocabulary extends VocabularyBase> {\n readonly catalogs: Record<string, Catalog<Vocabulary>>;\n readonly _loaders: Readonly<\n Record<string, Catalog<Vocabulary> | CatalogLoader<Vocabulary>>\n >;\n _handleError?: ErrorHandler | undefined;\n _implicitLocale?: string | undefined;\n constructor(\n catalogs: Readonly<\n Record<string, Catalog<Vocabulary> | CatalogLoader<Vocabulary>>\n >,\n options: BookOptions = {}\n ) {\n this.catalogs = {};\n this._loaders = catalogs;\n this._handleError = options.handleError;\n this._implicitLocale = options.implicitLocale;\n\n for (const [locale, catalog] of Object.entries(catalogs)) {\n // Skip lazy-loaded catalogs\n if (typeof catalog === \"function\") continue;\n\n this.catalogs[locale] = catalog;\n // @ts-expect-error deliberately breaking privacy\n if (catalog._looseLocale) {\n catalog.locale = locale;\n } else if (catalog.locale !== locale) {\n throw new Error(\n `Locale mismatch: expected ${locale}, got ${catalog.locale!}`\n );\n }\n }\n\n if (\n this._implicitLocale != null &&\n !hasOwn(catalogs, this._implicitLocale)\n ) {\n throw new Error(`Invalid implicitLocale: ${this._implicitLocale}`);\n }\n }\n\n /**\n * Load a catalog for specific locale.\n *\n * Consider using {@link preloadCatalogs} instead.\n *\n * @param locale locale to load\n *\n * @since 0.1.9 (`@hi18n/core`)\n */\n public async loadCatalog(locale: string): Promise<void> {\n const loader = this._loaders[locale];\n if (typeof loader !== \"function\") return;\n\n const { default: catalog } = await loader();\n // @ts-expect-error deliberately breaking privacy\n if (catalog._looseLocale) {\n catalog.locale = locale;\n } else if (catalog.locale !== locale) {\n throw new Error(\n `Locale mismatch: expected ${locale}, got ${catalog.locale!}`\n );\n }\n if (this.catalogs[locale] != null) return;\n this.catalogs[locale] = catalog;\n }\n\n public handleError(e: Error, level: ErrorLevel) {\n (this._handleError ?? defaultErrorHandler)(e, level);\n }\n}\n\n/**\n * @since 0.1.7 (`@hi18n/core`)\n */\nexport type BookOptions = {\n /**\n * Custom error handler. {@link defaultErrorHandler} is used by default.\n *\n * @example\n * ```ts\n * export const book = new Book({\n * en: catalogEn,\n * ja: catalogJa,\n * }, {\n * handleError(error, level) {\n * if (level === \"error\") {\n * // Report to Sentry or somewhere\n * } else {\n * console.warn(error);\n * }\n * }\n * });\n * ```\n *\n * @since 0.1.7 (`@hi18n/core`)\n */\n handleError?: ErrorHandler | undefined;\n /**\n * Locale fallback to use when no valid locale is specified.\n *\n * @example\n * ```ts\n * export const book = new Book({\n * en: catalogEn,\n * ja: catalogJa,\n * }, { implicitLocale: \"en\" });\n * ```\n *\n * @since 0.1.7 (`@hi18n/core`)\n */\n implicitLocale?: string | undefined;\n};\n\n/**\n * A function to asynchronously load a catalog.\n *\n * It is usually provided as `() => import(\"...\")`.\n *\n * @since 0.1.9 (`@hi18n/core`)\n */\nexport type CatalogLoader<Vocabulary extends VocabularyBase> = () => Promise<{\n default: Catalog<Vocabulary>;\n}>;\n\n/**\n * A set of translated messages for a specific locale.\n *\n * @since 0.1.0 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * type Vocabulary = {\n * \"example/greeting\": Message<{ name: string }>;\n * };\n * export default new Catalog<Vocabulary>(\"en\", {\n * \"example/greeting\": msg(\"Hello, {name}!\"),\n * });\n * ```\n */\nexport class Catalog<Vocabulary extends VocabularyBase> {\n // TODO: make it non-nullish and readonly in 0.2.0\n public locale?: string | undefined;\n public readonly data: Readonly<Vocabulary>;\n // TODO: remove it in 0.2.0\n private _looseLocale = false;\n private _compiled: Record<string, CompiledMessage> = {};\n /**\n * @since 0.1.6 (`@hi18n/core`)\n */\n constructor(locale: string, data: Readonly<Vocabulary>);\n /**\n * @deprecated deprecated from 0.1.6. Please specify the locale.\n * @since 0.1.0 (`@hi18n/core`)\n */\n constructor(data: Readonly<Vocabulary>);\n constructor(\n locale: string | Readonly<Vocabulary>,\n data?: Readonly<Vocabulary>\n ) {\n if (typeof locale === \"object\") {\n // For backwards-compatibility\n // TODO: remove it in 0.2.0\n this.data = locale;\n this._looseLocale = true;\n } else {\n this.locale = locale;\n this.data = data!;\n }\n }\n\n getCompiledMessage(id: string & keyof Vocabulary): CompiledMessage {\n if (!hasOwn(this._compiled, id)) {\n if (!hasOwn(this.data, id)) {\n throw new MissingTranslationError();\n }\n const msg = this.data[id]!;\n this._compiled[id] = parseMessage(msg);\n }\n return this._compiled[id]!;\n }\n}\n\n/**\n * An object returned from {@link getTranslator}.\n *\n * @since 0.1.0 (`@hi18n/core`)\n */\nexport type TranslatorObject<Vocabulary extends VocabularyBase> = {\n /**\n * Returns the translated message.\n *\n * @since 0.1.0 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t(\"example/greeting-simple\"); // => \"Hello!\"\n * ```\n */\n t: CompoundTranslatorFunction<Vocabulary>;\n\n /**\n * Similar to {@link TranslatorObject.t} but allows component interpolation\n * (i.e. to interpret commands like `<0>foo</0>` or `<link>foo</link>`)\n *\n * Users usually don't need to call it manually.\n * See the `@hi18n/react` package for its application to React.\n *\n * @param id the id of the translation\n * @param interpolator functions to customize the interpolation behavior\n * @param options the parameters of the translation.\n *\n * @since 0.1.0 (`@hi18n/core`)\n */\n translateWithComponents<T, C, K extends string & keyof Vocabulary>(\n id: K,\n interpolator: ComponentInterpolator<T, C>,\n options: MessageArguments<Vocabulary[K], C>\n ): T | string;\n};\n\ntype CompoundTranslatorFunction<Vocabulary extends VocabularyBase> =\n TranslatorFunction<Vocabulary> & {\n /**\n * Returns the translated message for a dynamic id.\n *\n * @since 0.1.1 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t.dynamic(menus[i].titleId); // => \"Map\"\n * ```\n */\n dynamic: DynamicTranslatorFunction<Vocabulary>;\n\n /**\n * Declares a translation to be made.\n *\n * At runtime, it returns the first argument.\n *\n * @param id the id of the translation\n * @param options the parameters of the translation.\n *\n * @since 0.1.1 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t.todo(\"example/greeting-simple\"); // => \"[TODO: example/greeting-simple]\"\n * ```\n */\n todo(id: string, options?: Record<string, unknown>): string;\n };\n\ntype TranslatorFunction<Vocabulary extends VocabularyBase> = {\n /**\n * Returns the translated message for a simple one.\n *\n * @param id the id of the translation\n *\n * @since 0.1.0 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t(\"example/greeting-simple\"); // => \"Hello!\"\n * ```\n */\n (id: SimpleMessageKeys<Vocabulary>): string;\n\n /**\n * Returns the translated message.\n *\n * @param id the id of the translation\n * @param options the parameters of the translation.\n *\n * @since 0.1.0 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t(\"example/greeting\", { name: \"John\" }); // => \"Hello, John!\"\n * ```\n */\n <K extends string & keyof Vocabulary>(\n id: K,\n options: MessageArguments<Vocabulary[K], never>\n ): string;\n};\n\ntype DynamicTranslatorFunction<Vocabulary extends VocabularyBase> = {\n /**\n * Returns the translated message for a simple dynamic id.\n *\n * @param id the id of the translation\n *\n * @since 0.1.1 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t.dynamic(menus[i].titleId); // => \"Map\"\n * ```\n */\n (id: TranslationId<Vocabulary, {}>): string;\n\n /**\n * Returns the translated message for a dynamic id.\n *\n * @param id the id of the translation\n * @param options the parameters of the translation.\n *\n * @since 0.1.1 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t.dynamic(greetings[i].translationId, { name: \"John\" }); // => \"Hello, John!\"\n * ```\n */\n <Args>(\n id: TranslationId<Vocabulary, Args>,\n options: InstantiateComponentTypes<InjectAdditionalParams<Args>, never>\n ): string;\n};\n\n/**\n * Used in {@link TranslatorObject.translateWithComponents} to customize\n * the behavior of component interpolation.\n *\n * @since 0.1.0 (`@hi18n/core`)\n */\nexport type ComponentInterpolator<T, C> = {\n collect: (submessages: (T | string)[]) => T | string;\n wrap: (component: C, message: T | string | undefined) => T | string;\n};\n\n/**\n * Retrieves the translation helpers from the book and the locales.\n *\n * @param book the \"book\" (i.e. the set of translations) containing the desired messages.\n * @param locales a locale or a list of locale in the order of preference (the latter being not supported yet)\n * @param options.throwPromise if true, it throws a Promise instance instead of an error. Used for React Suspense integration.\n * @returns A set of translation helpers\n *\n * @since 0.1.0 (`@hi18n/core`)\n *\n * @example\n * ```ts\n * const { t } = getTranslator(book, \"en\");\n * t(\"example/greeting-simple\"); // => \"Hello!\"\n * ```\n */\nexport function getTranslator<Vocabulary extends VocabularyBase>(\n book: Book<Vocabulary>,\n locales: string | string[],\n options: GetTranslatorOptions = {}\n): TranslatorObject<Vocabulary> {\n const locale = selectLocale(book, locales);\n const catalog = book.catalogs[locale];\n if (catalog == null) {\n if (options.throwPromise) {\n throw book.loadCatalog(locale);\n } else {\n throw new Error(`Catalog not loaded: ${locale}`);\n }\n }\n\n const t = (id: string, options: Record<string, unknown> = {}): string => {\n try {\n return compileAndEvaluateMessage<Vocabulary, string>(\n catalog,\n locale,\n id,\n {\n timeZone: options[\"timeZone\"] as string | undefined,\n params: options,\n handleError: book._handleError,\n }\n );\n } catch (e) {\n if (!(e instanceof Error)) throw e;\n\n book.handleError(e, \"error\");\n return `[${id}]`;\n }\n };\n t.dynamic = t;\n t.todo = (id: string) => {\n return `[TODO: ${id}]`;\n };\n\n return {\n t: t as CompoundTranslatorFunction<Vocabulary>,\n translateWithComponents: <T, C, K extends string & keyof Vocabulary>(\n id: K,\n interpolator: ComponentInterpolator<T, C>,\n options: MessageArguments<Vocabulary[K], C>\n ): T | string => {\n try {\n return compileAndEvaluateMessage<Vocabulary, T>(catalog, locale, id, {\n timeZone: options[\"timeZone\"] as string | undefined,\n params: options,\n handleError: book._handleError,\n collect: interpolator.collect,\n wrap: interpolator.wrap as ComponentInterpolator<T, unknown>[\"wrap\"],\n });\n } catch (e) {\n if (!(e instanceof Error)) throw e;\n\n book.handleError(e, \"error\");\n return `[${id}]`;\n }\n },\n };\n}\n\n/**\n * options for {@link getTranslator}\n *\n * @since 0.1.9 (`@hi18n/core`)\n */\nexport type GetTranslatorOptions = {\n /** if true, it throws a Promise instance instead of an error. Used for React Suspense integration. */\n throwPromise?: boolean | undefined;\n};\n\n/**\n * Starts loading and waits for catalogs so that {@link getTranslator} does not error\n * with \"Catalog not loaded\" error.\n *\n * It is a wrapper for {@link Book.loadCatalog}.\n *\n * @param book same as {@link getTranslator}'s `book` parameter.\n * @param locales same as {@link getTranslator}'s `locales` parameter.\n *\n * @since 0.1.9 (`@hi18n/core`)\n */\nexport async function preloadCatalogs<Vocabulary extends VocabularyBase>(\n book: Book<Vocabulary>,\n locales: string | string[]\n): Promise<void> {\n const locale = selectLocale(book, locales);\n const catalog = book.catalogs[locale];\n if (catalog == null) {\n await book.loadCatalog(locale);\n }\n}\n\n// To ensure deterministic behavior,\n// this function picks the locale whether the catalog has already been loaded or not.\nfunction selectLocale<Vocabulary extends VocabularyBase>(\n book: Book<Vocabulary>,\n locales: string | string[]\n): string {\n const localesArray = Array.isArray(locales) ? locales : [locales];\n\n const filteredLocales: string[] = [];\n for (const locale of localesArray) {\n if (hasOwn(book._loaders, locale)) {\n filteredLocales.push(locale);\n }\n }\n\n if (filteredLocales.length === 0) {\n const error =\n localesArray.length === 0\n ? new NoLocaleError()\n : new MissingLocaleError({\n locale: localesArray[0]!,\n availableLocales: Object.keys(book._loaders),\n });\n if (book._implicitLocale != null) {\n book.handleError(error, \"error\");\n filteredLocales.push(book._implicitLocale);\n } else {\n throw error;\n }\n }\n\n return filteredLocales[0]!;\n}\n\nfunction compileAndEvaluateMessage<Vocabulary extends VocabularyBase, T>(\n catalog: Catalog<Vocabulary>,\n locale: string,\n id: string & keyof Vocabulary,\n options: Omit<EvalOption<T>, \"id\" | \"locale\">\n) {\n try {\n return evaluateMessage<T>(catalog.getCompiledMessage(id), {\n id,\n locale,\n ...options,\n });\n } catch (e) {\n if (!(e instanceof Error)) throw e;\n\n throw new MessageError({\n cause: e,\n id,\n locale,\n });\n }\n}\n\n/**\n * A convenience helper to get the default time zone.\n * If you need more sophisticated guess for old browsers,\n * consider using other libraries like `moment.tz.guess`.\n *\n * @returns the default time zone, if anything is found. Otherwise the string \"UTC\"\n *\n * @since 0.1.3 (`@hi18n/core`)\n */\nexport function getDefaultTimeZone(): string {\n if (typeof Intl !== \"undefined\" && Intl.DateTimeFormat) {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n if (typeof timeZone === \"string\") return timeZone;\n }\n return \"UTC\";\n}\n\nfunction hasOwn(o: object, s: PropertyKey): boolean {\n return Object.prototype.hasOwnProperty.call(o, s);\n}\n"],"mappings":";;AAAA;AAGA,SAAqBA,eAArB,QAA4C,mBAA5C;AACA,SAASC,YAAT,QAA6B,qBAA7B;AAKA,SACEC,YADF,EAEEC,kBAFF,EAGEC,uBAHF,EAIEC,aAJF,QAKO,cALP;AAMA,SACEC,mBADF,QAIO,sBAJP;AAOA,cAAc,cAAd;AACA,cAAc,sBAAd;;AA4FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,GAAT,CAA+BC,CAA/B,EAA6D;EAClE,OAAOA,CAAP;AACD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACAD,GAAG,CAACE,IAAJ,GAAW,SAASA,IAAT,CAAgCD,CAAhC,EAA8D;EACvE,OAAOA,CAAP;AACD,CAFD;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,OAAO,SAASE,aAAT,CAILC,IAJK,EAKLC,EALK,EAM+D;EACpE,MAAMC,KAAK,GAAGF,IAAd;EACA,OAAOC,EAAP;AAID;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,OAAO,MAAME,IAAN,CAA8C;EAOnDC,WAAW,CACTC,QADS,EAKT;IAAA,IADAC,OACA,uEADuB,EACvB;;IAAA;;IAAA;;IAAA;;IAAA;;IACA,KAAKD,QAAL,GAAgB,EAAhB;IACA,KAAKE,QAAL,GAAgBF,QAAhB;IACA,KAAKG,YAAL,GAAoBF,OAAO,CAACG,WAA5B;IACA,KAAKC,eAAL,GAAuBJ,OAAO,CAACK,cAA/B;;IAEA,KAAK,MAAM,CAACC,MAAD,EAASC,OAAT,CAAX,IAAg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"}