UNPKG

@hi18n/core

Version:

Message internationalization meets immutability and type-safety - core runtime

1 lines 13.9 kB
{"version":3,"file":"msgfmt-eval.mjs","names":["defaultErrorHandler","ArgumentTypeError","MessageEvaluationError","MissingArgumentError","evaluateMessage","msg","options","numberValue","Array","isArray","reduced","reduceSubmessages","map","part","collect","type","value","params","name","undefined","argName","argType","expectedType","got","formatOptions","modifiedValue","argStyle","maximumFractionDigits","Math","round","Error","style","Intl","NumberFormat","handleError","locale","format","isDateLike","timeZone","Object","assign","dateStyle","timeStyle","DateTimeFormat","relativeValue","offset","BigInt","rule","PluralRules","pluralRules","select","Number","branch","branches","selector","message","wrap","submessages","every","x","join","length","push","obj","getFullYear"],"sources":["../src/msgfmt-eval.ts"],"sourcesContent":["import { defaultErrorHandler, ErrorHandler } from \"./error-handling.js\";\nimport {\n ArgumentTypeError,\n MessageEvaluationError,\n MissingArgumentError,\n} from \"./errors.js\";\nimport { CompiledMessage } from \"./msgfmt.js\";\n\nexport type EvalOption<T> = {\n id?: string | undefined;\n locale: string;\n timeZone?: string | undefined;\n params?: Record<string, unknown>;\n handleError?: ErrorHandler | undefined;\n collect?: ((submessages: (T | string)[]) => T | string) | undefined;\n wrap?:\n | ((component: unknown, message: T | string | undefined) => T | string)\n | undefined;\n};\n\nexport function evaluateMessage<T = string>(\n msg: CompiledMessage,\n options: EvalOption<T>,\n numberValue?: number | bigint\n): T | string {\n if (typeof msg === \"string\") {\n return msg;\n } else if (Array.isArray(msg)) {\n const reduced = reduceSubmessages(\n msg.map((part) => evaluateMessage(part, options, numberValue))\n );\n if (typeof reduced === \"string\") {\n return reduced;\n }\n const { collect } = options;\n if (!collect)\n throw new MessageEvaluationError(\n \"Invalid message: not a default-collectable message\"\n );\n return collect(reduced);\n } else if (msg.type === \"Var\") {\n const value = (options.params ?? {})[msg.name];\n if (value === undefined)\n throw new MissingArgumentError({\n argName: msg.name,\n });\n switch (msg.argType) {\n case undefined:\n if (typeof value !== \"string\")\n throw new MessageEvaluationError(\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n `Invalid argument ${msg.name}: expected string, got ${value}`\n );\n return value;\n case \"number\": {\n if (typeof value !== \"number\" && typeof value !== \"bigint\") {\n throw new ArgumentTypeError({\n argName: msg.name,\n expectedType: \"number\",\n got: value,\n });\n }\n const formatOptions: Intl.NumberFormatOptions = {};\n let modifiedValue = value;\n switch (msg.argStyle) {\n case \"integer\":\n // https://github.com/openjdk/jdk/blob/739769c8fc4b496f08a92225a12d07414537b6c0/src/java.base/share/classes/sun/util/locale/provider/NumberFormatProviderImpl.java#L196-L198\n formatOptions.maximumFractionDigits = 0;\n if (typeof value === \"number\") modifiedValue = Math.round(value);\n break;\n case \"currency\":\n // Need to provide an appropriate currency from somewhere\n throw new Error(\"Unimplemented: argStyle=currency\");\n case \"percent\":\n formatOptions.style = msg.argStyle;\n break;\n }\n if (\n (typeof Intl === \"undefined\" || !Intl.NumberFormat) &&\n (msg.argStyle === undefined || msg.argStyle === \"integer\")\n ) {\n (options.handleError ?? defaultErrorHandler)(\n new Error(\"Missing Intl.NumberFormat\"),\n \"warn\"\n );\n return `${modifiedValue}`;\n }\n // TODO: allow injecting polyfill\n return new Intl.NumberFormat(options.locale, formatOptions).format(\n modifiedValue\n );\n }\n case \"date\":\n case \"time\": {\n if (!isDateLike(value)) {\n throw new ArgumentTypeError({\n argName: msg.name,\n expectedType: \"Date\",\n got: value,\n });\n }\n if (typeof options.timeZone !== \"string\") {\n throw new MissingArgumentError({\n argName: \"timeZone\",\n });\n }\n const formatOptions: Intl.DateTimeFormatOptions = {\n timeZone: options.timeZone,\n };\n if (typeof msg.argStyle === \"object\") {\n // parsed object from the skeleton\n Object.assign(formatOptions, msg.argStyle);\n } else {\n if (msg.argType === \"date\") {\n formatOptions.dateStyle = msg.argStyle ?? \"medium\";\n } else {\n formatOptions.timeStyle = msg.argStyle ?? \"medium\";\n }\n }\n // TODO: allow injecting polyfill\n return new Intl.DateTimeFormat(options.locale, formatOptions).format(\n value\n );\n }\n default:\n throw new Error(`Unimplemented: argType=${msg.argType ?? \"string\"}`);\n }\n } else if (msg.type === \"Plural\") {\n const value = (options.params ?? {})[msg.name];\n let relativeValue: number | bigint;\n if (value === undefined) {\n throw new MissingArgumentError({\n argName: msg.name,\n });\n }\n if (typeof value === \"number\") {\n relativeValue = value - (msg.offset ?? 0);\n } else if (typeof value === \"bigint\") {\n relativeValue = value - BigInt(msg.offset ?? 0);\n } else {\n throw new ArgumentTypeError({\n argName: msg.name,\n expectedType: \"number\",\n got: value,\n });\n }\n const rule: string = (() => {\n if (typeof Intl === \"undefined\" || !Intl.PluralRules) {\n (options.handleError ?? defaultErrorHandler)(\n new Error(\"Missing Intl.PluralRules\"),\n \"warn\"\n );\n return \"other\";\n }\n // TODO: allow injecting polyfill\n const pluralRules = new Intl.PluralRules(options.locale);\n return pluralRules.select(Number(relativeValue));\n })();\n for (const branch of msg.branches) {\n if (\n branch.selector === Number(value) ||\n branch.selector === rule ||\n branch.selector === \"other\"\n ) {\n return evaluateMessage(branch.message, options, relativeValue);\n }\n }\n throw new MessageEvaluationError(\n `Non-exhaustive plural branches for ${value}`\n );\n } else if (msg.type === \"Number\" && numberValue !== undefined) {\n // TODO: allow injecting polyfill\n return new Intl.NumberFormat(options.locale).format(numberValue);\n } else if (msg.type === \"Element\") {\n const { wrap } = options;\n if (!wrap)\n throw new MessageEvaluationError(\n \"Invalid message: unexpected elementArg\"\n );\n const value = (options.params ?? {})[msg.name];\n if (value === undefined)\n throw new MissingArgumentError({\n argName: msg.name,\n });\n return wrap(\n value,\n msg.message !== undefined\n ? evaluateMessage(msg.message, options, numberValue)\n : undefined\n );\n }\n throw new MessageEvaluationError(\"Invalid message\");\n}\n\nfunction reduceSubmessages<T>(\n submessages: (T | string)[]\n): string | (T | string)[] {\n if (submessages.every((x): x is string => typeof x === \"string\")) {\n return submessages.join(\"\");\n }\n const reduced: (T | string)[] = [];\n for (const x of submessages) {\n if (x === \"\") continue;\n if (\n typeof x === \"string\" &&\n typeof reduced[reduced.length - 1] === \"string\"\n ) {\n reduced[reduced.length - 1] += x;\n } else {\n reduced.push(x);\n }\n }\n return reduced;\n}\n\nfunction isDateLike(obj: unknown): obj is Date {\n return (\n typeof obj === \"object\" &&\n typeof (obj as { getFullYear?: unknown }).getFullYear === \"function\"\n );\n}\n"],"mappings":"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"}