@intlayer/core 7.6.0-canary.1 → 8.0.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/dictionaryManipulator/editDictionaryByKeyPath.cjs +1 -1
- package/dist/cjs/dictionaryManipulator/editDictionaryByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/getContentNodeByKeyPath.cjs +1 -1
- package/dist/cjs/dictionaryManipulator/getContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/getDefaultNode.cjs +5 -0
- package/dist/cjs/dictionaryManipulator/getDefaultNode.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/getEmptyNode.cjs +1 -1
- package/dist/cjs/dictionaryManipulator/getEmptyNode.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/getNodeChildren.cjs +1 -1
- package/dist/cjs/dictionaryManipulator/getNodeChildren.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/removeContentNodeByKeyPath.cjs +1 -1
- package/dist/cjs/dictionaryManipulator/removeContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/renameContentNodeByKeyPath.cjs +1 -1
- package/dist/cjs/dictionaryManipulator/renameContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/index.cjs +56 -2
- package/dist/cjs/interpreter/getContent/deepTransform.cjs +1 -0
- package/dist/cjs/interpreter/getContent/deepTransform.cjs.map +1 -1
- package/dist/cjs/interpreter/getContent/getContent.cjs +2 -2
- package/dist/cjs/interpreter/getContent/getContent.cjs.map +1 -1
- package/dist/cjs/interpreter/getContent/plugins.cjs +3 -2
- package/dist/cjs/interpreter/getContent/plugins.cjs.map +1 -1
- package/dist/cjs/interpreter/getEnumeration.cjs.map +1 -1
- package/dist/cjs/interpreter/getHTML.cjs +106 -0
- package/dist/cjs/interpreter/getHTML.cjs.map +1 -0
- package/dist/cjs/interpreter/getInsertion.cjs +3 -1
- package/dist/cjs/interpreter/getInsertion.cjs.map +1 -1
- package/dist/cjs/interpreter/getTranslation.cjs +2 -2
- package/dist/cjs/interpreter/getTranslation.cjs.map +1 -1
- package/dist/cjs/interpreter/index.cjs +2 -0
- package/dist/cjs/localization/getBrowserLocale.cjs +1 -1
- package/dist/cjs/localization/getLocale.cjs +4 -3
- package/dist/cjs/localization/getLocale.cjs.map +1 -1
- package/dist/cjs/markdown/compiler.cjs +806 -0
- package/dist/cjs/markdown/compiler.cjs.map +1 -0
- package/dist/cjs/markdown/constants.cjs +334 -0
- package/dist/cjs/markdown/constants.cjs.map +1 -0
- package/dist/cjs/markdown/index.cjs +49 -0
- package/dist/cjs/markdown/parser.cjs +73 -0
- package/dist/cjs/markdown/parser.cjs.map +1 -0
- package/dist/cjs/markdown/renderer.cjs +68 -0
- package/dist/cjs/markdown/renderer.cjs.map +1 -0
- package/dist/cjs/markdown/types.cjs +0 -0
- package/dist/cjs/markdown/utils.cjs +397 -0
- package/dist/cjs/markdown/utils.cjs.map +1 -0
- package/dist/cjs/transpiler/html/getHTMLCustomComponents.cjs +15 -0
- package/dist/cjs/transpiler/html/getHTMLCustomComponents.cjs.map +1 -0
- package/dist/cjs/transpiler/html/index.cjs +133 -0
- package/dist/cjs/transpiler/html/index.cjs.map +1 -0
- package/dist/cjs/transpiler/index.cjs +3 -0
- package/dist/cjs/transpiler/insertion/getInsertionValues.cjs +2 -2
- package/dist/cjs/transpiler/insertion/getInsertionValues.cjs.map +1 -1
- package/dist/cjs/transpiler/insertion/insertion.cjs.map +1 -1
- package/dist/cjs/utils/intl.cjs +35 -3
- package/dist/cjs/utils/intl.cjs.map +1 -1
- package/dist/esm/dictionaryManipulator/editDictionaryByKeyPath.mjs +1 -1
- package/dist/esm/dictionaryManipulator/editDictionaryByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/getContentNodeByKeyPath.mjs +1 -1
- package/dist/esm/dictionaryManipulator/getContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/getDefaultNode.mjs +5 -0
- package/dist/esm/dictionaryManipulator/getDefaultNode.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/getEmptyNode.mjs +1 -1
- package/dist/esm/dictionaryManipulator/getEmptyNode.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/getNodeChildren.mjs +1 -1
- package/dist/esm/dictionaryManipulator/getNodeChildren.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/removeContentNodeByKeyPath.mjs +1 -1
- package/dist/esm/dictionaryManipulator/removeContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/renameContentNodeByKeyPath.mjs +1 -1
- package/dist/esm/dictionaryManipulator/renameContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/index.mjs +11 -4
- package/dist/esm/interpreter/getContent/deepTransform.mjs +1 -0
- package/dist/esm/interpreter/getContent/deepTransform.mjs.map +1 -1
- package/dist/esm/interpreter/getContent/getContent.mjs +2 -2
- package/dist/esm/interpreter/getContent/getContent.mjs.map +1 -1
- package/dist/esm/interpreter/getContent/plugins.mjs +3 -2
- package/dist/esm/interpreter/getContent/plugins.mjs.map +1 -1
- package/dist/esm/interpreter/getEnumeration.mjs.map +1 -1
- package/dist/esm/interpreter/getHTML.mjs +105 -0
- package/dist/esm/interpreter/getHTML.mjs.map +1 -0
- package/dist/esm/interpreter/getInsertion.mjs +3 -1
- package/dist/esm/interpreter/getInsertion.mjs.map +1 -1
- package/dist/esm/interpreter/getTranslation.mjs +2 -2
- package/dist/esm/interpreter/getTranslation.mjs.map +1 -1
- package/dist/esm/interpreter/index.mjs +2 -1
- package/dist/esm/localization/getBrowserLocale.mjs +1 -1
- package/dist/esm/localization/getLocale.mjs +2 -1
- package/dist/esm/localization/getLocale.mjs.map +1 -1
- package/dist/esm/markdown/compiler.mjs +804 -0
- package/dist/esm/markdown/compiler.mjs.map +1 -0
- package/dist/esm/markdown/constants.mjs +254 -0
- package/dist/esm/markdown/constants.mjs.map +1 -0
- package/dist/esm/markdown/index.mjs +7 -0
- package/dist/esm/markdown/parser.mjs +73 -0
- package/dist/esm/markdown/parser.mjs.map +1 -0
- package/dist/esm/markdown/renderer.mjs +67 -0
- package/dist/esm/markdown/renderer.mjs.map +1 -0
- package/dist/esm/markdown/types.mjs +0 -0
- package/dist/esm/markdown/utils.mjs +368 -0
- package/dist/esm/markdown/utils.mjs.map +1 -0
- package/dist/esm/transpiler/html/getHTMLCustomComponents.mjs +15 -0
- package/dist/esm/transpiler/html/getHTMLCustomComponents.mjs.map +1 -0
- package/dist/esm/transpiler/html/index.mjs +131 -0
- package/dist/esm/transpiler/html/index.mjs.map +1 -0
- package/dist/esm/transpiler/index.mjs +2 -1
- package/dist/esm/transpiler/insertion/getInsertionValues.mjs +2 -2
- package/dist/esm/transpiler/insertion/getInsertionValues.mjs.map +1 -1
- package/dist/esm/transpiler/insertion/insertion.mjs.map +1 -1
- package/dist/esm/utils/intl.mjs +35 -4
- package/dist/esm/utils/intl.mjs.map +1 -1
- package/dist/types/deepTransformPlugins/getFilterMissingTranslationsContent.d.ts +11 -10
- package/dist/types/deepTransformPlugins/getFilterTranslationsOnlyContent.d.ts +11 -10
- package/dist/types/deepTransformPlugins/getFilterTranslationsOnlyContent.d.ts.map +1 -1
- package/dist/types/deepTransformPlugins/getFilteredLocalesContent.d.ts +11 -10
- package/dist/types/deepTransformPlugins/getFilteredLocalesContent.d.ts.map +1 -1
- package/dist/types/getStorageAttributes.d.ts.map +1 -1
- package/dist/types/index.d.ts +11 -3
- package/dist/types/interpreter/getContent/getContent.d.ts +1 -1
- package/dist/types/interpreter/getContent/getContent.d.ts.map +1 -1
- package/dist/types/interpreter/getContent/index.d.ts +2 -2
- package/dist/types/interpreter/getContent/plugins.d.ts +58 -18
- package/dist/types/interpreter/getContent/plugins.d.ts.map +1 -1
- package/dist/types/interpreter/getEnumeration.d.ts +1 -1
- package/dist/types/interpreter/getHTML.d.ts +14 -0
- package/dist/types/interpreter/getHTML.d.ts.map +1 -0
- package/dist/types/interpreter/getTranslation.d.ts.map +1 -1
- package/dist/types/interpreter/index.d.ts +3 -2
- package/dist/types/localization/getLocale.d.ts.map +1 -1
- package/dist/types/markdown/compiler.d.ts +10 -0
- package/dist/types/markdown/compiler.d.ts.map +1 -0
- package/dist/types/markdown/constants.d.ts +193 -0
- package/dist/types/markdown/constants.d.ts.map +1 -0
- package/dist/types/markdown/index.d.ts +7 -0
- package/dist/types/markdown/parser.d.ts +17 -0
- package/dist/types/markdown/parser.d.ts.map +1 -0
- package/dist/types/markdown/renderer.d.ts +23 -0
- package/dist/types/markdown/renderer.d.ts.map +1 -0
- package/dist/types/markdown/types.d.ts +367 -0
- package/dist/types/markdown/types.d.ts.map +1 -0
- package/dist/types/markdown/utils.d.ts +141 -0
- package/dist/types/markdown/utils.d.ts.map +1 -0
- package/dist/types/messageFormat/ICU.d.ts.map +1 -1
- package/dist/types/transpiler/enumeration/enumeration.d.ts.map +1 -1
- package/dist/types/transpiler/html/getHTMLCustomComponents.d.ts +9 -0
- package/dist/types/transpiler/html/getHTMLCustomComponents.d.ts.map +1 -0
- package/dist/types/transpiler/html/index.d.ts +33 -0
- package/dist/types/transpiler/html/index.d.ts.map +1 -0
- package/dist/types/transpiler/index.d.ts +2 -1
- package/dist/types/utils/intl.d.ts +21 -2
- package/dist/types/utils/intl.d.ts.map +1 -1
- package/package.json +15 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getContent.mjs","names":[],"sources":["../../../../src/interpreter/getContent/getContent.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type {\n ContentNode,\n DeclaredLocales,\n LocalesValues,\n} from '@intlayer/types';\nimport { deepTransformNode } from './deepTransform';\nimport {\n conditionPlugin,\n type DeepTransformContent,\n enumerationPlugin,\n filePlugin,\n type IInterpreterPluginState,\n insertionPlugin,\n type NodeProps,\n nestedPlugin,\n type Plugins,\n translationPlugin,\n} from './plugins';\n\n/**\n * Transforms a node in a single pass, applying each plugin as needed.\n *\n * @param node The node to transform.\n * @param locale The locale to use if your transformers need it (e.g. for translations).\n */\nexport const getContent = <\n T extends ContentNode,\n L extends LocalesValues = DeclaredLocales,\n>(\n node: T,\n nodeProps: NodeProps,\n locale?: L\n) => {\n const defaultLocale = configuration?.internationalization?.defaultLocale;\n\n const plugins: Plugins[] = [\n insertionPlugin,\n translationPlugin(locale ?? defaultLocale
|
|
1
|
+
{"version":3,"file":"getContent.mjs","names":[],"sources":["../../../../src/interpreter/getContent/getContent.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type {\n ContentNode,\n DeclaredLocales,\n LocalesValues,\n} from '@intlayer/types';\nimport { deepTransformNode } from './deepTransform';\nimport {\n conditionPlugin,\n type DeepTransformContent,\n enumerationPlugin,\n filePlugin,\n type IInterpreterPluginState,\n insertionPlugin,\n type NodeProps,\n nestedPlugin,\n type Plugins,\n translationPlugin,\n} from './plugins';\n\n/**\n * Transforms a node in a single pass, applying each plugin as needed.\n *\n * @param node The node to transform.\n * @param locale The locale to use if your transformers need it (e.g. for translations).\n */\nexport const getContent = <\n T extends ContentNode,\n L extends LocalesValues = DeclaredLocales,\n>(\n node: T,\n nodeProps: NodeProps,\n locale?: L,\n fallback?: boolean\n) => {\n const defaultLocale = configuration?.internationalization?.defaultLocale;\n\n const plugins: Plugins[] = [\n insertionPlugin,\n translationPlugin(\n locale ?? defaultLocale,\n fallback ? defaultLocale : undefined\n ),\n enumerationPlugin,\n conditionPlugin,\n nestedPlugin(locale ?? defaultLocale),\n filePlugin,\n ...(nodeProps.plugins ?? []),\n ];\n\n return deepTransformNode(node, {\n ...nodeProps,\n plugins,\n }) as DeepTransformContent<T, IInterpreterPluginState, L>;\n};\n"],"mappings":";;;;;;;;;;;AA0BA,MAAa,cAIX,MACA,WACA,QACA,aACG;CACH,MAAM,gBAAgB,eAAe,sBAAsB;CAE3D,MAAM,UAAqB;EACzB;EACA,kBACE,UAAU,eACV,WAAW,gBAAgB,OAC5B;EACD;EACA;EACA,aAAa,UAAU,cAAc;EACrC;EACA,GAAI,UAAU,WAAW,EAAE;EAC5B;AAED,QAAO,kBAAkB,MAAM;EAC7B,GAAG;EACH;EACD,CAAC"}
|
|
@@ -8,7 +8,7 @@ import { NodeType } from "@intlayer/types";
|
|
|
8
8
|
|
|
9
9
|
//#region src/interpreter/getContent/plugins.ts
|
|
10
10
|
/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */
|
|
11
|
-
const translationPlugin = (locale, fallback
|
|
11
|
+
const translationPlugin = (locale, fallback) => ({
|
|
12
12
|
id: "translation-plugin",
|
|
13
13
|
canHandle: (node) => typeof node === "object" && node?.nodeType === NodeType.Translation,
|
|
14
14
|
transform: (node, props, deepTransformNode) => {
|
|
@@ -87,6 +87,7 @@ const genderPlugin = {
|
|
|
87
87
|
return (value) => getGender(result, value);
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
|
+
/** Insertion plugin. Replaces node with a function that takes quantity => string. */
|
|
90
91
|
const insertionPlugin = {
|
|
91
92
|
id: "insertion-plugin",
|
|
92
93
|
canHandle: (node) => typeof node === "object" && node?.nodeType === NodeType.Insertion,
|
|
@@ -124,7 +125,7 @@ const insertionPlugin = {
|
|
|
124
125
|
/** Nested plugin. Replaces node with the result of `getNesting`. */
|
|
125
126
|
const nestedPlugin = (locale) => ({
|
|
126
127
|
id: "nested-plugin",
|
|
127
|
-
canHandle: (node) => typeof node === "object" && node?.nodeType === NodeType.Nested,
|
|
128
|
+
canHandle: (node) => typeof node === "object" && (node?.nodeType === NodeType.Nested || node?.nodeType === "nested"),
|
|
128
129
|
transform: (node, props) => getNesting(node.nested.dictionaryKey, node.nested.path, {
|
|
129
130
|
...props,
|
|
130
131
|
locale: locale ?? props.locale
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.mjs","names":["node","deepTransformNode","children"],"sources":["../../../../src/interpreter/getContent/plugins.ts"],"sourcesContent":["import {\n type DeclaredLocales,\n type DictionaryKeys,\n type KeyPath,\n type Locale,\n type LocalesValues,\n NodeType,\n} from '@intlayer/types';\nimport type {\n ConditionContent,\n EnumerationContent,\n FileContent,\n Gender,\n GenderContent,\n InsertionContent,\n NestedContent,\n TranslationContent,\n} from '../../transpiler';\nimport { getCondition } from '../getCondition';\nimport { getEnumeration } from '../getEnumeration';\nimport { getGender } from '../getGender';\nimport { getInsertion } from '../getInsertion';\nimport { type GetNestingResult, getNesting } from '../getNesting';\nimport { getTranslation } from '../getTranslation';\n\n/** ---------------------------------------------\n * PLUGIN DEFINITION\n * --------------------------------------------- */\n\n/**\n * A plugin/transformer that can optionally transform a node during a single DFS pass.\n * - `canHandle` decides if the node is transformable by this plugin.\n * - `transform` returns the transformed node (and does not recurse further).\n *\n * > `transformFn` is a function that can be used to deeply transform inside the plugin.\n */\nexport type Plugins = {\n id: string;\n canHandle: (node: any) => boolean;\n transform: (\n node: any,\n props: NodeProps,\n transformFn: (node: any, props: NodeProps) => any\n ) => any;\n};\n\n/** ---------------------------------------------\n * TRANSLATION PLUGIN\n * --------------------------------------------- */\n\nexport type TranslationCond<T, S, L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeType.Translation]: infer U;\n}\n ? U extends Record<PropertyKey, unknown>\n ? L extends keyof U\n ? DeepTransformContent<U[L], S>\n : DeepTransformContent<U[keyof U], S>\n : never\n : never;\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const translationPlugin = (\n locale: LocalesValues,\n fallback?: LocalesValues,\n onContentNotFound?: (\n locale: LocalesValues,\n fallback: LocalesValues,\n keyPath: KeyPath[]\n ) => void\n): Plugins => ({\n id: 'translation-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Translation,\n transform: (node: TranslationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Translation]);\n\n for (const key in result) {\n const childProps = {\n ...props,\n children: result[key as keyof typeof result],\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Translation, key } as KeyPath,\n ],\n };\n result[key as keyof typeof result] = deepTransformNode(\n result[key as keyof typeof result],\n childProps\n );\n }\n\n return getTranslation(result, locale, fallback);\n },\n});\n\n/** ---------------------------------------------\n * ENUMERATION PLUGIN\n * --------------------------------------------- */\n\nexport type EnumerationCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Enumeration]: object;\n}\n ? (\n quantity: number\n ) => DeepTransformContent<\n T[NodeType.Enumeration][keyof T[NodeType.Enumeration]],\n S\n >\n : never;\n\n/** Enumeration plugin. Replaces node with a function that takes quantity => string. */\nexport const enumerationPlugin: Plugins = {\n id: 'enumeration-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Enumeration,\n transform: (node: EnumerationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Enumeration]);\n\n for (const key in result) {\n const child = result[key as unknown as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Enumeration, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (quantity: number) => getEnumeration(result, quantity);\n },\n};\n\n/** ---------------------------------------------\n * CONDITION PLUGIN\n * --------------------------------------------- */\n\nexport type ConditionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Condition]: object;\n}\n ? (\n value: boolean\n ) => DeepTransformContent<\n T[NodeType.Condition][keyof T[NodeType.Condition]],\n S\n >\n : never;\n\n/** Condition plugin. Replaces node with a function that takes boolean => string. */\nexport const conditionPlugin: Plugins = {\n id: 'condition-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Condition,\n transform: (node: ConditionContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Condition]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Condition, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (value: boolean) => getCondition(result, value);\n },\n};\n\n/** ---------------------------------------------\n * GENDER PLUGIN\n * --------------------------------------------- */\n\nexport type GenderCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Gender]: object;\n}\n ? (\n value: Gender\n ) => DeepTransformContent<T[NodeType.Gender][keyof T[NodeType.Gender]], S>\n : never;\n\n/** Gender plugin. Replaces node with a function that takes gender => string. */\nexport const genderPlugin: Plugins = {\n id: 'gender-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Gender,\n transform: (node: GenderContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Gender]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [...props.keyPath, { type: NodeType.Gender, key } as KeyPath],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (value: Gender) => getGender(result, value);\n },\n};\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\nexport type InsertionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Insertion]: infer I;\n fields?: infer U;\n}\n ? U extends readonly string[]\n ? (data: Record<U[number], string | number>) => DeepTransformContent<I, S>\n : (data: Record<string, string | number>) => DeepTransformContent<I, S>\n : never;\n\nexport const insertionPlugin: Plugins = {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Insertion,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeType.Insertion,\n },\n ];\n\n const children = node[NodeType.Insertion];\n\n /** Insertion string plugin. Replaces string node with a component that render the insertion. */\n const insertionStringPlugin: Plugins = {\n id: 'insertion-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, subProps, deepTransformNode) => {\n const transformedResult = deepTransformNode(node, {\n ...subProps,\n children: node,\n plugins: [\n ...(props.plugins ?? ([] as Plugins[])).filter(\n (plugin) => plugin.id !== 'intlayer-node-plugin'\n ),\n ],\n });\n\n return (\n values: {\n [K in InsertionContent['fields'][number]]: string | number;\n }\n ) => {\n const children = getInsertion(transformedResult, values);\n\n return deepTransformNode(children, {\n ...subProps,\n plugins: props.plugins,\n children,\n });\n };\n },\n };\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [insertionStringPlugin, ...(props.plugins ?? [])],\n });\n },\n};\n\n/** ---------------------------------------------\n * NESTED PLUGIN\n * --------------------------------------------- */\n\nexport type NestedCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Nested]: infer U;\n}\n ? U extends {\n dictionaryKey: infer K extends DictionaryKeys;\n path?: infer P;\n }\n ? GetNestingResult<K, P, S>\n : never\n : never;\n\n/** Nested plugin. Replaces node with the result of `getNesting`. */\nexport const nestedPlugin = (locale?: LocalesValues): Plugins => ({\n id: 'nested-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Nested,\n transform: (node: NestedContent, props) =>\n getNesting(node.nested.dictionaryKey, node.nested.path, {\n ...props,\n locale: (locale ?? props.locale) as Locale,\n }),\n});\n\n// /** ---------------------------------------------\n// * FILE PLUGIN\n// * --------------------------------------------- */\n\nexport type FileCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeType.File]: string;\n content?: string;\n}\n ? string\n : never;\n\n/** File plugin. Replaces node with the result of `getNesting`. */\nexport const filePlugin: Plugins = {\n id: 'file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.File,\n transform: (node: FileContent, props, deepTransform) =>\n deepTransform(node.content, {\n ...props,\n children: node.content,\n }),\n};\n\n/**\n * PLUGIN RESULT\n */\n\n/**\n * Interface that defines the properties of a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface NodeProps {\n dictionaryKey: string;\n keyPath: KeyPath[];\n plugins?: Plugins[];\n locale?: Locale;\n dictionaryPath?: string;\n children?: any;\n}\n\n/**\n * Interface that defines the plugins that can be used to transform a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface IInterpreterPlugin<T, S, L extends LocalesValues> {\n translation: TranslationCond<T, S, L>;\n insertion: InsertionCond<T, S, L>;\n enumeration: EnumerationCond<T, S, L>;\n condition: ConditionCond<T, S, L>;\n nested: NestedCond<T, S, L>;\n // file: FileCond<T>;\n}\n\n/**\n * Allow to avoid overwriting import from `intlayer` package when `IInterpreterPlugin<T>` interface is augmented in another package, such as `react-intlayer`.\n */\nexport type IInterpreterPluginState = {\n translation: true;\n enumeration: true;\n condition: true;\n insertion: true;\n nested: true;\n // file: true;\n};\n\n/**\n * Utility type to check if a plugin can be applied to a node.\n */\ntype CheckApplyPlugin<\n T,\n K extends keyof IInterpreterPlugin<T, S, L>,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = K extends keyof S // Test if the key is a key of S.\n ? // Test if the key of S is true. Then the plugin can be applied.\n S[K] extends true\n ? // Test if the key of S exist\n IInterpreterPlugin<T, S, L>[K] extends never\n ? never\n : // Test if the plugin condition is true (if it's not, the plugin is skipped for this node)\n IInterpreterPlugin<T, S, L>[K]\n : never\n : never;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\ntype Traverse<\n T,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = T extends ReadonlyArray<infer U> // Turn any read-only array into a plain mutable array\n ? Array<DeepTransformContent<U, S, L>>\n : T extends object\n ? { [K in keyof T]: DeepTransformContent<T[K], S, L> }\n : T;\n\nexport type IsAny<T> = 0 extends 1 & T ? true : false;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\nexport type DeepTransformContent<\n T,\n S = IInterpreterPluginState,\n L extends LocalesValues = DeclaredLocales,\n> = IsAny<T> extends true\n ? T\n : CheckApplyPlugin<T, keyof IInterpreterPlugin<T, S, L>, S> extends never // Check if there is a plugin for T:\n ? // No plugin was found, so try to transform T recursively:\n Traverse<T, S, L>\n : // A plugin was found – use the plugin’s transformation.\n IInterpreterPlugin<T, S, L>[keyof IInterpreterPlugin<T, S, L>];\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugins.mjs","names":["node","deepTransformNode","children"],"sources":["../../../../src/interpreter/getContent/plugins.ts"],"sourcesContent":["import {\n type DeclaredLocales,\n type DictionaryKeys,\n type KeyPath,\n type Locale,\n type LocalesValues,\n NodeType,\n} from '@intlayer/types';\nimport type {\n ConditionContent,\n EnumerationContent,\n FileContent,\n Gender,\n GenderContent,\n InsertionContent,\n NestedContent,\n TranslationContent,\n} from '../../transpiler';\nimport { getCondition } from '../getCondition';\nimport { getEnumeration } from '../getEnumeration';\nimport { getGender } from '../getGender';\nimport { getInsertion } from '../getInsertion';\nimport { type GetNestingResult, getNesting } from '../getNesting';\nimport { getTranslation } from '../getTranslation';\n\n/** ---------------------------------------------\n * PLUGIN DEFINITION\n * --------------------------------------------- */\n\n/**\n * A plugin/transformer that can optionally transform a node during a single DFS pass.\n * - `canHandle` decides if the node is transformable by this plugin.\n * - `transform` returns the transformed node (and does not recurse further).\n *\n * > `transformFn` is a function that can be used to deeply transform inside the plugin.\n */\nexport type Plugins = {\n id: string;\n canHandle: (node: any) => boolean;\n transform: (\n node: any,\n props: NodeProps,\n transformFn: (node: any, props: NodeProps) => any\n ) => any;\n};\n\n/** ---------------------------------------------\n * TRANSLATION PLUGIN\n * --------------------------------------------- */\n\nexport type TranslationCond<T, S, L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeType.Translation]: infer U;\n}\n ? U extends Record<PropertyKey, unknown>\n ? L extends keyof U\n ? DeepTransformContent<U[L], S>\n : DeepTransformContent<U[keyof U], S>\n : never\n : never;\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const translationPlugin = (\n locale: LocalesValues,\n fallback?: LocalesValues\n): Plugins => ({\n id: 'translation-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Translation,\n transform: (node: TranslationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Translation]);\n\n for (const key in result) {\n const childProps = {\n ...props,\n children: result[key as keyof typeof result],\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Translation, key } as KeyPath,\n ],\n };\n result[key as keyof typeof result] = deepTransformNode(\n result[key as keyof typeof result],\n childProps\n );\n }\n\n return getTranslation(result, locale, fallback);\n },\n});\n\n/** ---------------------------------------------\n * ENUMERATION PLUGIN\n * --------------------------------------------- */\n\nexport type EnumerationCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Enumeration]: object;\n}\n ? (\n quantity: number\n ) => DeepTransformContent<\n T[NodeType.Enumeration][keyof T[NodeType.Enumeration]],\n S\n >\n : never;\n\n/** Enumeration plugin. Replaces node with a function that takes quantity => string. */\nexport const enumerationPlugin: Plugins = {\n id: 'enumeration-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Enumeration,\n transform: (node: EnumerationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Enumeration]);\n\n for (const key in result) {\n const child = result[key as unknown as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Enumeration, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (quantity: number) => getEnumeration(result, quantity);\n },\n};\n\n/** ---------------------------------------------\n * CONDITION PLUGIN\n * --------------------------------------------- */\n\nexport type ConditionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Condition]: object;\n}\n ? (\n value: boolean\n ) => DeepTransformContent<\n T[NodeType.Condition][keyof T[NodeType.Condition]],\n S\n >\n : never;\n\n/** Condition plugin. Replaces node with a function that takes boolean => string. */\nexport const conditionPlugin: Plugins = {\n id: 'condition-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Condition,\n transform: (node: ConditionContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Condition]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Condition, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (value: boolean) => getCondition(result, value);\n },\n};\n\n/** ---------------------------------------------\n * GENDER PLUGIN\n * --------------------------------------------- */\n\nexport type GenderCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Gender]: object;\n}\n ? (\n value: Gender\n ) => DeepTransformContent<T[NodeType.Gender][keyof T[NodeType.Gender]], S>\n : never;\n\n/** Gender plugin. Replaces node with a function that takes gender => string. */\nexport const genderPlugin: Plugins = {\n id: 'gender-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Gender,\n transform: (node: GenderContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Gender]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [...props.keyPath, { type: NodeType.Gender, key } as KeyPath],\n };\n result[key as keyof typeof result] = deepTransformNode(child, childProps);\n }\n\n return (value: Gender) => getGender(result, value);\n },\n};\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\nexport type InsertionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Insertion]: string;\n fields: readonly string[];\n}\n ? (\n values: {\n [K in T['fields'][number]]: string | number;\n }\n ) => DeepTransformContent<string, S>\n : never;\n\n/** Insertion plugin. Replaces node with a function that takes quantity => string. */\nexport const insertionPlugin: Plugins = {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Insertion,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeType.Insertion,\n },\n ];\n\n const children = node[NodeType.Insertion];\n\n /** Insertion string plugin. Replaces string node with a component that render the insertion. */\n const insertionStringPlugin: Plugins = {\n id: 'insertion-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, subProps, deepTransformNode) => {\n const transformedResult = deepTransformNode(node, {\n ...subProps,\n children: node,\n plugins: [\n ...(props.plugins ?? ([] as Plugins[])).filter(\n (plugin) => plugin.id !== 'intlayer-node-plugin'\n ),\n ],\n });\n\n return (\n values: {\n [K in InsertionContent['fields'][number]]: string | number;\n }\n ) => {\n const children = getInsertion(transformedResult, values);\n\n return deepTransformNode(children, {\n ...subProps,\n plugins: props.plugins,\n children,\n });\n };\n },\n };\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [insertionStringPlugin, ...(props.plugins ?? [])],\n });\n },\n};\n\n/** ---------------------------------------------\n * NESTED PLUGIN\n * --------------------------------------------- */\n\nexport type NestedCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Nested]: infer U;\n}\n ? U extends {\n dictionaryKey: infer K extends DictionaryKeys;\n path?: infer P;\n }\n ? GetNestingResult<K, P, S>\n : never\n : never;\n\n/** Nested plugin. Replaces node with the result of `getNesting`. */\nexport const nestedPlugin = (locale?: LocalesValues): Plugins => ({\n id: 'nested-plugin',\n canHandle: (node) =>\n typeof node === 'object' &&\n (node?.nodeType === NodeType.Nested || node?.nodeType === 'nested'),\n transform: (node: NestedContent, props) =>\n getNesting(node.nested.dictionaryKey, node.nested.path, {\n ...props,\n locale: (locale ?? props.locale) as Locale,\n }),\n});\n\n/** ---------------------------------------------\n * HTML PLUGIN\n * --------------------------------------------- */\n\n/**\n * Props for HTML tag components.\n * Includes children and an index signature for attributes.\n */\nexport type HTMLTagComponentProps = {\n children?: any;\n [key: string]: any;\n};\n\n/**\n * A component that can be used to replace an HTML tag.\n * Can be a string (tag name) or a functional component.\n */\nexport type HTMLTagComponent = string | ((props: HTMLTagComponentProps) => any);\n\nexport type HTMLCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.HTML]: string;\n customComponents?: infer U;\n}\n ? {\n use: U extends readonly string[]\n ? U extends readonly []\n ? (components?: Partial<Record<string, HTMLTagComponent>>) => any\n : (\n components: { [K in U[number]]: HTMLTagComponent } & Partial<\n Record<string, HTMLTagComponent>\n >\n ) => any\n : (components?: Record<string, HTMLTagComponent>) => any;\n } & any\n : never;\n\n/**\n * Note: The `htmlPlugin` is NOT defined at the core level.\n * Each framework (react-intlayer, vue-intlayer, svelte-intlayer, solid-intlayer)\n * must implement their own `htmlPlugin` to provide default HTML tag components\n * (e.g., h1, p, span, etc.) using their native element creation APIs.\n *\n * The framework-specific plugins should:\n * 1. Create default components for standard HTML tags\n * 2. Merge user-provided components with defaults (user takes priority)\n * 3. Call `getHTML(node[NodeType.HTML], mergedComponents)`\n */\n\n/** ---------------------------------------------\n * FILE PLUGIN\n * --------------------------------------------- */\n\nexport type FileCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeType.File]: string;\n content?: string;\n}\n ? string\n : never;\n\n/** File plugin. Replaces node with the result of `getNesting`. */\nexport const filePlugin: Plugins = {\n id: 'file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.File,\n transform: (node: FileContent, props, deepTransform) =>\n deepTransform(node.content, {\n ...props,\n children: node.content,\n }),\n};\n\n/**\n * PLUGIN RESULT\n */\n\n/**\n * Interface that defines the properties of a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface NodeProps {\n dictionaryKey: string;\n keyPath: KeyPath[];\n plugins?: Plugins[];\n locale?: Locale;\n dictionaryPath?: string;\n children?: any;\n}\n\n/**\n * Interface that defines the plugins that can be used to transform a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface IInterpreterPlugin<T, S, L extends LocalesValues> {\n translation: TranslationCond<T, S, L>;\n insertion: InsertionCond<T, S, L>;\n enumeration: EnumerationCond<T, S, L>;\n condition: ConditionCond<T, S, L>;\n nested: NestedCond<T, S, L>;\n html: HTMLCond<T, S, L>;\n // file: FileCond<T>;\n}\n\n/**\n * Allow to avoid overwriting import from `intlayer` package when `IInterpreterPlugin<T>` interface is augmented in another package, such as `react-intlayer`.\n */\nexport type IInterpreterPluginState = {\n translation: true;\n enumeration: true;\n condition: true;\n insertion: true;\n nested: true;\n html: true;\n // file: true;\n};\n\n/**\n * Utility type to check if a plugin can be applied to a node.\n */\ntype CheckApplyPlugin<\n T,\n K extends keyof IInterpreterPlugin<T, S, L>,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = K extends keyof S // Test if the key is a key of S.\n ? // Test if the key of S is true. Then the plugin can be applied.\n S[K] extends true\n ? // Test if the key of S exist\n IInterpreterPlugin<T, S, L>[K] extends never\n ? never\n : // Test if the plugin condition is true (if it's not, the plugin is skipped for this node)\n IInterpreterPlugin<T, S, L>[K]\n : never\n : never;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\ntype Traverse<\n T,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = T extends ReadonlyArray<infer U> // Turn any read-only array into a plain mutable array\n ? Array<DeepTransformContent<U, S, L>>\n : T extends object\n ? { [K in keyof T]: DeepTransformContent<T[K], S, L> }\n : T;\n\nexport type IsAny<T> = 0 extends 1 & T ? true : false;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\nexport type DeepTransformContent<\n T,\n S = IInterpreterPluginState,\n L extends LocalesValues = DeclaredLocales,\n> = IsAny<T> extends true\n ? T\n : CheckApplyPlugin<T, keyof IInterpreterPlugin<T, S, L>, S> extends never // Check if there is a plugin for T:\n ? // No plugin was found, so try to transform T recursively:\n Traverse<T, S, L>\n : // A plugin was found – use the plugin’s transformation.\n IInterpreterPlugin<T, S, L>[keyof IInterpreterPlugin<T, S, L>];\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getEnumeration.mjs","names":[],"sources":["../../../src/interpreter/getEnumeration.ts"],"sourcesContent":["import type { EnterFormat, EnumerationContentState } from '../transpiler';\n\n/**\n * Find the matching condition for a quantity.\n *\n * Usage:\n *\n * ```ts\n * const key = findMatchingCondition({\n * '<=-2.3': 'You have less than -2.3',\n * '<1': 'You have less than one',\n * '2': 'You have two',\n * '>=3': 'You have three or more',\n * }, 2);\n * // '2'\n * ```\n *\n * The order of the keys will define the priority of the content.\n *\n * ```ts\n * const key = findMatchingCondition({\n * '<4': 'You have less than four',\n * '2': 'You have two',\n * }, 2);\n * // '<4'\n * ```\n *\n * If no keys match, the default key is '1'.\n */\nexport const findMatchingCondition = <Content>(\n enumerationContent: EnumerationContentState<Content>,\n quantity: number\n): EnterFormat => {\n const numericKeys = Object.keys(enumerationContent);\n\n for (const key of numericKeys) {\n const isEqual =\n (!key.startsWith('>') &&\n !key.startsWith('<') &&\n !key.startsWith('=') &&\n parseFloat(key) === quantity) ||\n (key.startsWith('=') && parseFloat(key.slice(1)) === quantity);\n const isSuperior =\n key.startsWith('>') && quantity > parseFloat(key.slice(1));\n const isSuperiorOrEqual =\n key.startsWith('>=') && quantity >= parseFloat(key.slice(2));\n const isInferior =\n key.startsWith('<') && quantity < parseFloat(key.slice(1));\n const isInferiorOrEqual =\n key.startsWith('<=') && quantity <= parseFloat(key.slice(2));\n\n if (\n isEqual ||\n isSuperior ||\n isSuperiorOrEqual ||\n isInferior ||\n isInferiorOrEqual\n ) {\n return key as EnterFormat;\n }\n }\n};\n\n/**\n * Allow to pick a content based on a quantity.\n *\n * Usage:\n *\n * ```ts\n * const content = getEnumeration({\n * '<=-2.3': 'You have less than -2.3',\n * '<1': 'You have less than one',\n * '2': 'You have two',\n * '>=3': 'You have three or more',\n * }, 2);\n * // 'You have two'\n * ```\n *\n * The order of the keys will define the priority of the content.\n *\n * ```ts\n * const content = getEnumeration({\n * '<4': 'You have less than four',\n * '2': 'You have two',\n * }, 2);\n * // 'You have less than four'\n * ```\n *\n */\nexport const getEnumeration = <Content>(\n enumerationContent: EnumerationContentState<Content>,\n quantity: number\n): Content => {\n const key =\n findMatchingCondition<Content>(enumerationContent, quantity) ?? 'fallback';\n\n // Default or error handling if no keys match\n return enumerationContent[key] as Content;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,yBACX,oBACA,
|
|
1
|
+
{"version":3,"file":"getEnumeration.mjs","names":[],"sources":["../../../src/interpreter/getEnumeration.ts"],"sourcesContent":["import type { EnterFormat, EnumerationContentState } from '../transpiler';\n\n/**\n * Find the matching condition for a quantity.\n *\n * Usage:\n *\n * ```ts\n * const key = findMatchingCondition({\n * '<=-2.3': 'You have less than -2.3',\n * '<1': 'You have less than one',\n * '2': 'You have two',\n * '>=3': 'You have three or more',\n * }, 2);\n * // '2'\n * ```\n *\n * The order of the keys will define the priority of the content.\n *\n * ```ts\n * const key = findMatchingCondition({\n * '<4': 'You have less than four',\n * '2': 'You have two',\n * }, 2);\n * // '<4'\n * ```\n *\n * If no keys match, the default key is '1'.\n */\nexport const findMatchingCondition = <Content>(\n enumerationContent: EnumerationContentState<Content>,\n quantity: number\n): EnterFormat | undefined => {\n const numericKeys = Object.keys(enumerationContent);\n\n for (const key of numericKeys) {\n const isEqual =\n (!key.startsWith('>') &&\n !key.startsWith('<') &&\n !key.startsWith('=') &&\n parseFloat(key) === quantity) ||\n (key.startsWith('=') && parseFloat(key.slice(1)) === quantity);\n const isSuperior =\n key.startsWith('>') && quantity > parseFloat(key.slice(1));\n const isSuperiorOrEqual =\n key.startsWith('>=') && quantity >= parseFloat(key.slice(2));\n const isInferior =\n key.startsWith('<') && quantity < parseFloat(key.slice(1));\n const isInferiorOrEqual =\n key.startsWith('<=') && quantity <= parseFloat(key.slice(2));\n\n if (\n isEqual ||\n isSuperior ||\n isSuperiorOrEqual ||\n isInferior ||\n isInferiorOrEqual\n ) {\n return key as EnterFormat;\n }\n }\n};\n\n/**\n * Allow to pick a content based on a quantity.\n *\n * Usage:\n *\n * ```ts\n * const content = getEnumeration({\n * '<=-2.3': 'You have less than -2.3',\n * '<1': 'You have less than one',\n * '2': 'You have two',\n * '>=3': 'You have three or more',\n * }, 2);\n * // 'You have two'\n * ```\n *\n * The order of the keys will define the priority of the content.\n *\n * ```ts\n * const content = getEnumeration({\n * '<4': 'You have less than four',\n * '2': 'You have two',\n * }, 2);\n * // 'You have less than four'\n * ```\n *\n */\nexport const getEnumeration = <Content>(\n enumerationContent: EnumerationContentState<Content>,\n quantity: number\n): Content => {\n const key =\n findMatchingCondition<Content>(enumerationContent, quantity) ?? 'fallback';\n\n // Default or error handling if no keys match\n return enumerationContent[key] as Content;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,yBACX,oBACA,aAC4B;CAC5B,MAAM,cAAc,OAAO,KAAK,mBAAmB;AAEnD,MAAK,MAAM,OAAO,aAAa;EAC7B,MAAM,UACH,CAAC,IAAI,WAAW,IAAI,IACnB,CAAC,IAAI,WAAW,IAAI,IACpB,CAAC,IAAI,WAAW,IAAI,IACpB,WAAW,IAAI,KAAK,YACrB,IAAI,WAAW,IAAI,IAAI,WAAW,IAAI,MAAM,EAAE,CAAC,KAAK;EACvD,MAAM,aACJ,IAAI,WAAW,IAAI,IAAI,WAAW,WAAW,IAAI,MAAM,EAAE,CAAC;EAC5D,MAAM,oBACJ,IAAI,WAAW,KAAK,IAAI,YAAY,WAAW,IAAI,MAAM,EAAE,CAAC;EAC9D,MAAM,aACJ,IAAI,WAAW,IAAI,IAAI,WAAW,WAAW,IAAI,MAAM,EAAE,CAAC;EAC5D,MAAM,oBACJ,IAAI,WAAW,KAAK,IAAI,YAAY,WAAW,IAAI,MAAM,EAAE,CAAC;AAE9D,MACE,WACA,cACA,qBACA,cACA,kBAEA,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+Bb,MAAa,kBACX,oBACA,aACY;AAKZ,QAAO,mBAHL,sBAA+B,oBAAoB,SAAS,IAAI"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
//#region src/interpreter/getHTML.ts
|
|
2
|
+
/**
|
|
3
|
+
* Helper to parse attributes from a tag string.
|
|
4
|
+
*/
|
|
5
|
+
const parseAttributes = (attributes) => {
|
|
6
|
+
const props = {};
|
|
7
|
+
const attrRegex = /([a-zA-Z0-9-]+)="([^"]*)"/g;
|
|
8
|
+
let match = attrRegex.exec(attributes);
|
|
9
|
+
while (match !== null) {
|
|
10
|
+
props[match[1]] = match[2];
|
|
11
|
+
match = attrRegex.exec(attributes);
|
|
12
|
+
}
|
|
13
|
+
return props;
|
|
14
|
+
};
|
|
15
|
+
const htmlCache = /* @__PURE__ */ new Map();
|
|
16
|
+
/**
|
|
17
|
+
* Allow to interpret HTML/JSX-like strings and replace tags with components.
|
|
18
|
+
*/
|
|
19
|
+
const getHTML = (content, values) => {
|
|
20
|
+
const cacheKey = JSON.stringify({
|
|
21
|
+
content,
|
|
22
|
+
components: Object.keys(values)
|
|
23
|
+
});
|
|
24
|
+
if (htmlCache.has(cacheKey)) return htmlCache.get(cacheKey);
|
|
25
|
+
const tagRegex = /<(\/)?([a-zA-Z0-9.-]+)([\s\S]*?)(\/?)>/g;
|
|
26
|
+
const elements = [];
|
|
27
|
+
const stack = [];
|
|
28
|
+
let lastIndex = 0;
|
|
29
|
+
let tagIndex = 0;
|
|
30
|
+
let match = tagRegex.exec(content);
|
|
31
|
+
const renderValue = (tagName, tagProps, children, index) => {
|
|
32
|
+
let override = values[tagName];
|
|
33
|
+
if (!override) {
|
|
34
|
+
const lowerTagName = tagName.toLowerCase();
|
|
35
|
+
const foundKey = Object.keys(values).find((key$1) => key$1.toLowerCase() === lowerTagName);
|
|
36
|
+
if (foundKey) override = values[foundKey];
|
|
37
|
+
}
|
|
38
|
+
const key = `html-tag-${tagName}-${index}`;
|
|
39
|
+
if (typeof override === "function") return override({
|
|
40
|
+
...tagProps,
|
|
41
|
+
children,
|
|
42
|
+
key
|
|
43
|
+
});
|
|
44
|
+
if (typeof override === "string") {
|
|
45
|
+
const component = values[override];
|
|
46
|
+
if (typeof component === "function") return component({
|
|
47
|
+
...tagProps,
|
|
48
|
+
children,
|
|
49
|
+
key
|
|
50
|
+
});
|
|
51
|
+
return children;
|
|
52
|
+
}
|
|
53
|
+
if (typeof override === "object" && override !== null && "tag" in override) {
|
|
54
|
+
const { tag: targetTag, props: extraProps } = override;
|
|
55
|
+
const component = values[targetTag];
|
|
56
|
+
if (typeof component === "function") return component({
|
|
57
|
+
...tagProps,
|
|
58
|
+
...extraProps,
|
|
59
|
+
children,
|
|
60
|
+
key
|
|
61
|
+
});
|
|
62
|
+
return children;
|
|
63
|
+
}
|
|
64
|
+
return children;
|
|
65
|
+
};
|
|
66
|
+
const appendChild = (child) => {
|
|
67
|
+
const target = stack.length > 0 ? stack[stack.length - 1].children : elements;
|
|
68
|
+
if (Array.isArray(child)) target.push(...child);
|
|
69
|
+
else target.push(child);
|
|
70
|
+
};
|
|
71
|
+
while (match !== null) {
|
|
72
|
+
const [fullMatch, isClosingRaw, tagName, attributesRaw, isSelfClosingRaw] = match;
|
|
73
|
+
const matchIndex = match.index;
|
|
74
|
+
if (matchIndex > lastIndex) appendChild(content.slice(lastIndex, matchIndex));
|
|
75
|
+
const isClosing = isClosingRaw === "/";
|
|
76
|
+
const isSelfClosing = isSelfClosingRaw === "/" || attributesRaw.trim().endsWith("/") || fullMatch.endsWith("/>");
|
|
77
|
+
const cleanedAttributes = attributesRaw.trim().replace(/\/$/, "").trim();
|
|
78
|
+
if (isClosing) {
|
|
79
|
+
const last = stack.pop();
|
|
80
|
+
if (last) appendChild(renderValue(tagName, last.props, last.children, tagIndex++));
|
|
81
|
+
} else if (isSelfClosing) appendChild(renderValue(tagName, parseAttributes(cleanedAttributes), [], tagIndex++));
|
|
82
|
+
else {
|
|
83
|
+
const tagProps = parseAttributes(cleanedAttributes);
|
|
84
|
+
stack.push({
|
|
85
|
+
tagName,
|
|
86
|
+
children: [],
|
|
87
|
+
props: tagProps
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
lastIndex = matchIndex + fullMatch.length;
|
|
91
|
+
match = tagRegex.exec(content);
|
|
92
|
+
}
|
|
93
|
+
if (lastIndex < content.length) appendChild(content.slice(lastIndex));
|
|
94
|
+
while (stack.length > 0) {
|
|
95
|
+
const last = stack.shift();
|
|
96
|
+
if (last) appendChild(last.children);
|
|
97
|
+
}
|
|
98
|
+
const result = elements.length === 1 ? elements[0] : elements;
|
|
99
|
+
htmlCache.set(cacheKey, result);
|
|
100
|
+
return result;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
//#endregion
|
|
104
|
+
export { getHTML };
|
|
105
|
+
//# sourceMappingURL=getHTML.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getHTML.mjs","names":["key"],"sources":["../../../src/interpreter/getHTML.ts"],"sourcesContent":["type Component = (props: any) => any;\ntype ComponentObject = {\n tag: string;\n props?: Record<string, any>;\n};\ntype Components = Record<string, Component | string | ComponentObject>;\n\n/**\n * Helper to parse attributes from a tag string.\n */\nconst parseAttributes = (attributes: string): Record<string, string> => {\n const props: Record<string, string> = {};\n const attrRegex = /([a-zA-Z0-9-]+)=\"([^\"]*)\"/g;\n\n let match = attrRegex.exec(attributes);\n while (match !== null) {\n props[match[1]] = match[2];\n match = attrRegex.exec(attributes);\n }\n return props;\n};\n\nconst htmlCache = new Map<string, any>();\n\n/**\n * Allow to interpret HTML/JSX-like strings and replace tags with components.\n */\nexport const getHTML = (content: string, values: Components): any => {\n const cacheKey = JSON.stringify({ content, components: Object.keys(values) });\n\n if (htmlCache.has(cacheKey)) {\n return htmlCache.get(cacheKey);\n }\n\n const tagRegex = /<(\\/)?([a-zA-Z0-9.-]+)([\\s\\S]*?)(\\/?)>/g;\n\n const elements: any[] = [];\n const stack: {\n tagName: string;\n children: any[];\n props: Record<string, string>;\n }[] = [];\n\n let lastIndex = 0;\n let tagIndex = 0;\n let match = tagRegex.exec(content);\n\n const renderValue = (\n tagName: string,\n tagProps: Record<string, any>,\n children: any[],\n index: number\n ) => {\n let override = values[tagName];\n\n if (!override) {\n const lowerTagName = tagName.toLowerCase();\n const foundKey = Object.keys(values).find(\n (key) => key.toLowerCase() === lowerTagName\n );\n if (foundKey) override = values[foundKey];\n }\n\n const key = `html-tag-${tagName}-${index}`;\n\n if (typeof override === 'function') {\n return override({ ...tagProps, children, key });\n }\n\n if (typeof override === 'string') {\n const component = values[override];\n if (typeof component === 'function') {\n return component({ ...tagProps, children, key });\n }\n return children;\n }\n\n if (\n typeof override === 'object' &&\n override !== null &&\n 'tag' in override\n ) {\n const { tag: targetTag, props: extraProps } = override as ComponentObject;\n const component = values[targetTag];\n if (typeof component === 'function') {\n return component({ ...tagProps, ...extraProps, children, key });\n }\n return children;\n }\n\n // Default: Skip tag, render children\n return children;\n };\n\n const appendChild = (child: any) => {\n const target =\n stack.length > 0 ? stack[stack.length - 1].children : elements;\n if (Array.isArray(child)) {\n target.push(...child);\n } else {\n target.push(child);\n }\n };\n\n while (match !== null) {\n const [fullMatch, isClosingRaw, tagName, attributesRaw, isSelfClosingRaw] =\n match;\n const matchIndex = match.index;\n\n if (matchIndex > lastIndex) {\n appendChild(content.slice(lastIndex, matchIndex));\n }\n\n const isClosing = isClosingRaw === '/';\n const isSelfClosing =\n isSelfClosingRaw === '/' ||\n attributesRaw.trim().endsWith('/') ||\n fullMatch.endsWith('/>');\n\n const cleanedAttributes = attributesRaw.trim().replace(/\\/$/, '').trim();\n\n if (isClosing) {\n const last = stack.pop();\n if (last) {\n appendChild(\n renderValue(tagName, last.props, last.children, tagIndex++)\n );\n }\n } else if (isSelfClosing) {\n const tagProps = parseAttributes(cleanedAttributes);\n appendChild(renderValue(tagName, tagProps, [], tagIndex++));\n } else {\n const tagProps = parseAttributes(cleanedAttributes);\n stack.push({ tagName, children: [], props: tagProps });\n }\n\n lastIndex = matchIndex + fullMatch.length;\n match = tagRegex.exec(content);\n }\n\n if (lastIndex < content.length) {\n appendChild(content.slice(lastIndex));\n }\n\n while (stack.length > 0) {\n const last = stack.shift();\n if (last) appendChild(last.children);\n }\n\n const result = elements.length === 1 ? elements[0] : elements;\n\n htmlCache.set(cacheKey, result);\n\n return result;\n};\n"],"mappings":"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"}
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
14
|
*/
|
|
15
|
-
const getInsertion = (content, values) => content.replace(/\{\{(.*?)\}\}/g, (_, key) =>
|
|
15
|
+
const getInsertion = (content, values) => content.replace(/\{\{\s*(.*?)\s*\}\}/g, (_, key) => {
|
|
16
|
+
return (values[key.trim()] ?? "").toString();
|
|
17
|
+
});
|
|
16
18
|
|
|
17
19
|
//#endregion
|
|
18
20
|
export { getInsertion };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getInsertion.mjs","names":[],"sources":["../../../src/interpreter/getInsertion.ts"],"sourcesContent":["import type { InsertionContent } from '../transpiler';\n\n/**\n * Allow to insert values in a string.\n *\n * Usage:\n *\n * ```ts\n * const content = getInsertion('Hello {{name}}!', {\n * name: 'John',\n * });\n * // 'Hello John!'\n * ```\n *\n */\nexport const getInsertion = (\n content: string,\n values: { [K in InsertionContent['fields'][number]]: string | number }\n) =>\n content.replace(/\\{\\{(.*?)\\}\\}/g, (_, key) => (values[
|
|
1
|
+
{"version":3,"file":"getInsertion.mjs","names":[],"sources":["../../../src/interpreter/getInsertion.ts"],"sourcesContent":["import type { InsertionContent } from '../transpiler';\n\n/**\n * Allow to insert values in a string.\n *\n * Usage:\n *\n * ```ts\n * const content = getInsertion('Hello {{name}}!', {\n * name: 'John',\n * });\n * // 'Hello John!'\n * ```\n *\n */\nexport const getInsertion = (\n content: string,\n values: { [K in InsertionContent['fields'][number]]: string | number }\n) =>\n content.replace(/\\{\\{\\s*(.*?)\\s*\\}\\}/g, (_, key) => {\n const trimmedKey = key.trim();\n return (values[trimmedKey] ?? '').toString();\n });\n"],"mappings":";;;;;;;;;;;;;;AAeA,MAAa,gBACX,SACA,WAEA,QAAQ,QAAQ,yBAAyB,GAAG,QAAQ;AAElD,SAAQ,OADW,IAAI,MAAM,KACC,IAAI,UAAU;EAC5C"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
const isPlainObject = (value) => {
|
|
7
7
|
if (value === null || typeof value !== "object") return false;
|
|
8
8
|
if (value instanceof Promise || typeof value.then === "function") return false;
|
|
9
|
-
if (value.$$typeof !== void 0) return false;
|
|
9
|
+
if (value.$$typeof !== void 0 || value.__v_isVNode !== void 0 || value._isVNode !== void 0 || value.isJSX !== void 0) return false;
|
|
10
10
|
const proto = Object.getPrototypeOf(value);
|
|
11
11
|
return proto === Object.prototype || proto === null || Array.isArray(value);
|
|
12
12
|
};
|
|
@@ -98,7 +98,7 @@ const getTranslation = (languageContent, locale, fallback) => {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
if (results.length === 0) return;
|
|
101
|
-
const cleanResults = results.map((item) => removeUndefinedValues(item));
|
|
101
|
+
const cleanResults = results.filter((item) => typeof item !== "undefined").map((item) => removeUndefinedValues(item));
|
|
102
102
|
if (cleanResults.length === 1) return cleanResults[0];
|
|
103
103
|
if (Array.isArray(cleanResults[0])) return cleanResults[0];
|
|
104
104
|
return cleanResults.reduce((acc, curr) => deepMergeObjects(acc, curr));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTranslation.mjs","names":[],"sources":["../../../src/interpreter/getTranslation.ts"],"sourcesContent":["import type { LocalesValues, StrictModeLocaleMap } from '@intlayer/types';\n\n/**\n * Check if a value is a plain object that can be safely processed.\n * Returns false for Promises, React elements, class instances, etc.\n */\nconst isPlainObject = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n // Don't process Promises (e.g., Next.js 15+ params)\n if (value instanceof Promise || typeof (value as any).then === 'function') {\n return false;\n }\n\n // Don't process React elements\n if ((value as any).$$typeof !== undefined) {\n return false;\n }\n\n // Only process plain objects and arrays\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null || Array.isArray(value);\n};\n\n/**\n * Recursively merges two objects.\n * Resembles the behavior of `defu` but respects `isPlainObject` to avoid merging React elements.\n * Arrays are replaced, not merged.\n */\nconst deepMergeObjects = (target: any, source: any): any => {\n if (target === undefined) return source;\n if (source === undefined) return target;\n\n if (Array.isArray(target)) return target;\n\n if (isPlainObject(target) && isPlainObject(source)) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (key === '__proto__' || key === 'constructor') continue;\n\n if (Object.hasOwn(target, key)) {\n result[key] = deepMergeObjects(target[key], source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n }\n\n return target;\n};\n\n/**\n * Recursively removes undefined values from an object.\n * Handles circular references by tracking visited objects.\n */\nconst removeUndefinedValues = <T>(\n object: T,\n visited = new WeakSet<object>()\n): T => {\n if (typeof object !== 'object' || object === null) {\n return object;\n }\n\n // Handle circular references - return original to avoid infinite recursion\n if (visited.has(object)) {\n return object;\n }\n visited.add(object);\n\n // Don't process non-plain objects (Promises, React elements, etc.)\n if (!isPlainObject(object)) {\n return object;\n }\n\n if (Array.isArray(object)) {\n return object.map((item) => removeUndefinedValues(item, visited)) as T;\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(object)) {\n if (value !== undefined) {\n result[key] = removeUndefinedValues(value, visited);\n }\n }\n return result as T;\n};\n\n/**\n *\n * Allow to pick a content based on a locale.\n * If not locale found, it will return the content related to the default locale.\n *\n * Return either the content editor, or the content itself depending on the configuration.\n *\n * Usage:\n *\n * ```ts\n * const content = getTranslation<string>({\n * en: 'Hello',\n * fr: 'Bonjour',\n * }, 'fr');\n * // 'Bonjour'\n * ```\n *\n * Using TypeScript:\n * - this function will require each locale to be defined if defined in the project configuration.\n * - If a locale is missing, it will make each existing locale optional and raise an error if the locale is not found.\n */\nexport const getTranslation = <Content = string>(\n languageContent: StrictModeLocaleMap<Content>,\n locale: LocalesValues,\n fallback?: LocalesValues\n): Content => {\n const results: Content[] = [];\n\n const getContent = (loc: string) =>\n languageContent[loc as keyof typeof languageContent];\n\n //
|
|
1
|
+
{"version":3,"file":"getTranslation.mjs","names":[],"sources":["../../../src/interpreter/getTranslation.ts"],"sourcesContent":["import type { LocalesValues, StrictModeLocaleMap } from '@intlayer/types';\n\n/**\n * Check if a value is a plain object that can be safely processed.\n * Returns false for Promises, React elements, class instances, etc.\n */\nconst isPlainObject = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n // Don't process Promises (e.g., Next.js 15+ params)\n if (value instanceof Promise || typeof (value as any).then === 'function') {\n return false;\n }\n\n // Don't process React elements or other framework VNodes\n if (\n (value as any).$$typeof !== undefined ||\n (value as any).__v_isVNode !== undefined ||\n (value as any)._isVNode !== undefined ||\n (value as any).isJSX !== undefined\n ) {\n return false;\n }\n\n // Only process plain objects and arrays\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null || Array.isArray(value);\n};\n\n/**\n * Recursively merges two objects.\n * Resembles the behavior of `defu` but respects `isPlainObject` to avoid merging React elements.\n * Arrays are replaced, not merged.\n */\nconst deepMergeObjects = (target: any, source: any): any => {\n if (target === undefined) return source;\n if (source === undefined) return target;\n\n if (Array.isArray(target)) return target;\n\n if (isPlainObject(target) && isPlainObject(source)) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (key === '__proto__' || key === 'constructor') continue;\n\n if (Object.hasOwn(target, key)) {\n result[key] = deepMergeObjects(target[key], source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n }\n\n return target;\n};\n\n/**\n * Recursively removes undefined values from an object.\n * Handles circular references by tracking visited objects.\n */\nconst removeUndefinedValues = <T>(\n object: T,\n visited = new WeakSet<object>()\n): T => {\n if (typeof object !== 'object' || object === null) {\n return object;\n }\n\n // Handle circular references - return original to avoid infinite recursion\n if (visited.has(object)) {\n return object;\n }\n visited.add(object);\n\n // Don't process non-plain objects (Promises, React elements, etc.)\n if (!isPlainObject(object)) {\n return object;\n }\n\n if (Array.isArray(object)) {\n return object.map((item) => removeUndefinedValues(item, visited)) as T;\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(object)) {\n if (value !== undefined) {\n result[key] = removeUndefinedValues(value, visited);\n }\n }\n return result as T;\n};\n\n/**\n *\n * Allow to pick a content based on a locale.\n * If not locale found, it will return the content related to the default locale.\n *\n * Return either the content editor, or the content itself depending on the configuration.\n *\n * Usage:\n *\n * ```ts\n * const content = getTranslation<string>({\n * en: 'Hello',\n * fr: 'Bonjour',\n * }, 'fr');\n * // 'Bonjour'\n * ```\n *\n * Using TypeScript:\n * - this function will require each locale to be defined if defined in the project configuration.\n * - If a locale is missing, it will make each existing locale optional and raise an error if the locale is not found.\n */\nexport const getTranslation = <Content = string>(\n languageContent: StrictModeLocaleMap<Content>,\n locale: LocalesValues,\n fallback?: LocalesValues\n): Content => {\n const results: Content[] = [];\n\n const getContent = (loc: string) =>\n languageContent[loc as keyof typeof languageContent];\n\n // Get Target Content\n const content = getContent(locale);\n if (typeof content === 'string') {\n return content;\n } else if (content !== undefined) {\n results.push(content);\n }\n\n // Get Target Generic Content (e.g. 'en' from 'en-US')\n if (locale.includes('-')) {\n const genericLocale = locale.split('-')[0];\n if (genericLocale in languageContent) {\n const genericContent = getContent(genericLocale);\n\n if (typeof genericContent === 'string') {\n // If we haven't found specific content yet, return generic string\n if (results.length === 0) return genericContent;\n } else if (genericContent !== undefined) {\n results.push(genericContent);\n }\n }\n }\n\n // Get Fallback Content\n if (fallback !== undefined && fallback !== locale) {\n // 3a. Fallback Specific\n if (fallback in languageContent) {\n const fallbackContent = getContent(fallback);\n\n if (typeof fallbackContent === 'string') {\n if (results.length === 0) return fallbackContent;\n } else if (fallbackContent !== undefined) {\n results.push(fallbackContent);\n }\n }\n\n // Fallback Generic (The missing piece: e.g. 'en' from 'en-GB' fallback)\n if (fallback.includes('-')) {\n const genericFallback = fallback.split('-')[0];\n const genericLocale = locale.split('-')[0];\n\n // Only add if it's different from the target generic (to avoid duplication)\n // and exists in the dictionary\n if (\n genericFallback !== genericLocale &&\n genericFallback in languageContent\n ) {\n const genericFallbackContent = getContent(genericFallback);\n\n if (typeof genericFallbackContent === 'string') {\n if (results.length === 0) return genericFallbackContent;\n } else if (genericFallbackContent !== undefined) {\n results.push(genericFallbackContent);\n }\n }\n }\n }\n\n if (results.length === 0) {\n return undefined as Content;\n }\n\n // Clean undefined values so they don't overwrite fallbacks\n // Order: [Target, Generic, Fallback, FallbackGeneric]\n // defu first argument takes precedence, so Target wins\n const cleanResults = results\n .filter((item) => typeof item !== 'undefined')\n .map((item) => removeUndefinedValues(item));\n\n // If only one result, return it directly (no merging needed)\n if (cleanResults.length === 1) {\n return cleanResults[0];\n }\n\n // If the first result is an array, return it directly (arrays replace, don't merge)\n // defu would incorrectly convert arrays to objects with numeric keys\n if (Array.isArray(cleanResults[0])) {\n return cleanResults[0];\n }\n\n // Merge objects with custom merge - first argument takes precedence\n // Cast to object[] since by this point we've already returned early for strings, arrays, and single results\n return (cleanResults as object[]).reduce((acc, curr) =>\n deepMergeObjects(acc, curr)\n ) as Content;\n};\n"],"mappings":"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"}
|
|
@@ -7,5 +7,6 @@ import { getNesting } from "./getNesting.mjs";
|
|
|
7
7
|
import { getTranslation } from "./getTranslation.mjs";
|
|
8
8
|
import { conditionPlugin, enumerationPlugin, filePlugin, genderPlugin, insertionPlugin, nestedPlugin, translationPlugin } from "./getContent/plugins.mjs";
|
|
9
9
|
import { getContent } from "./getContent/getContent.mjs";
|
|
10
|
+
import { getHTML } from "./getHTML.mjs";
|
|
10
11
|
|
|
11
|
-
export { conditionPlugin, deepTransformNode, enumerationPlugin, filePlugin, findMatchingCondition, genderPlugin, getCondition, getContent, getDictionary, getEnumeration, getIntlayer, getNesting, getTranslation, insertionPlugin, nestedPlugin, translationPlugin };
|
|
12
|
+
export { conditionPlugin, deepTransformNode, enumerationPlugin, filePlugin, findMatchingCondition, genderPlugin, getCondition, getContent, getDictionary, getEnumeration, getHTML, getIntlayer, getNesting, getTranslation, insertionPlugin, nestedPlugin, translationPlugin };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { localeDetector } from "./localeDetector.mjs";
|
|
2
1
|
import { getLocaleFromStorage } from "../utils/localeStorage.mjs";
|
|
2
|
+
import { localeDetector } from "./localeDetector.mjs";
|
|
3
3
|
import { Locales } from "@intlayer/types";
|
|
4
4
|
import configuration from "@intlayer/config/built";
|
|
5
5
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { getLocaleFromStorage } from "../utils/localeStorage.mjs";
|
|
2
|
+
import { localeResolver } from "./localeResolver.mjs";
|
|
1
3
|
import { getPreferredLanguages } from "./localeDetector.mjs";
|
|
2
4
|
import { DefaultValues } from "@intlayer/config/client";
|
|
3
5
|
import configuration from "@intlayer/config/built";
|
|
4
|
-
import { getLocaleFromStorage, localeResolver } from "@intlayer/core";
|
|
5
6
|
|
|
6
7
|
//#region src/localization/getLocale.ts
|
|
7
8
|
const getLocale = async (ctx = {}) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getLocale.mjs","names":[],"sources":["../../../src/localization/getLocale.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { DefaultValues } from '@intlayer/config/client';\nimport {
|
|
1
|
+
{"version":3,"file":"getLocale.mjs","names":[],"sources":["../../../src/localization/getLocale.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { DefaultValues } from '@intlayer/config/client';\nimport type { Locale } from '@intlayer/types';\nimport { getLocaleFromStorage } from '../utils/localeStorage';\nimport { getPreferredLanguages } from './localeDetector';\nimport { localeResolver } from './localeResolver';\n\nexport type RequestContext = {\n getHeader?: (name: string) => string | null | undefined;\n getCookie?: (name: string) => string | null | undefined;\n};\n\nexport const getLocale = async (ctx: RequestContext = {}): Promise<Locale> => {\n const defaultLocale =\n configuration?.internationalization?.defaultLocale ??\n DefaultValues.Internationalization.DEFAULT_LOCALE;\n const availableLocales =\n configuration?.internationalization?.locales ??\n DefaultValues.Internationalization.LOCALES;\n\n // Try locale from storage (cookie or header)\n const storedLocale = getLocaleFromStorage({\n getCookie: ctx.getCookie,\n getHeader: ctx.getHeader,\n });\n\n if (storedLocale) {\n return storedLocale;\n }\n\n // Fallback to Accept-Language negotiation\n const acceptLanguageHeader = ctx.getHeader?.('accept-language');\n\n if (!acceptLanguageHeader) {\n return defaultLocale;\n }\n\n const preferredLocaleStrings = getPreferredLanguages(\n acceptLanguageHeader,\n availableLocales\n );\n\n const userFallbackLocale = localeResolver(\n preferredLocaleStrings,\n availableLocales,\n defaultLocale\n );\n\n if (userFallbackLocale) {\n return userFallbackLocale;\n }\n\n // Default locale\n return defaultLocale;\n};\n"],"mappings":";;;;;;;AAYA,MAAa,YAAY,OAAO,MAAsB,EAAE,KAAsB;CAC5E,MAAM,gBACJ,eAAe,sBAAsB,iBACrC,cAAc,qBAAqB;CACrC,MAAM,mBACJ,eAAe,sBAAsB,WACrC,cAAc,qBAAqB;CAGrC,MAAM,eAAe,qBAAqB;EACxC,WAAW,IAAI;EACf,WAAW,IAAI;EAChB,CAAC;AAEF,KAAI,aACF,QAAO;CAIT,MAAM,uBAAuB,IAAI,YAAY,kBAAkB;AAE/D,KAAI,CAAC,qBACH,QAAO;CAQT,MAAM,qBAAqB,eALI,sBAC7B,sBACA,iBACD,EAIC,kBACA,cACD;AAED,KAAI,mBACF,QAAO;AAIT,QAAO"}
|