@intlayer/core
Version:
Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.
1 lines • 10.1 kB
Source Map (JSON)
{"version":3,"file":"getSplittedContent.cjs","names":["result: Record<string, any>","result: SplitResult","NodeType","recomposed: ContentNode | undefined","commonArray: any[]","perLocaleArrays: Record<string, any[]>","accumulated: SplitResult","output: Record<string, ContentNode>"],"sources":["../../../src/deepTransformPlugins/getSplittedContent.ts"],"sourcesContent":["import {\n type ContentNode,\n type DeclaredLocales,\n type Dictionary,\n NodeType,\n} from '@intlayer/types';\n\ntype SplittedContentOutput<T = ContentNode> = Record<DeclaredLocales, T> & {\n common: T;\n};\n\ntype SplitResult = Record<string, ContentNode | undefined> & {\n common?: ContentNode;\n};\n\nconst isObject = (value: unknown): value is Record<string, any> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst hasNodeType = (value: unknown): value is { nodeType: string } =>\n isObject(value) && typeof (value as any).nodeType === 'string';\n\nconst mergeValues = (\n a: ContentNode | undefined,\n b: ContentNode | undefined\n): ContentNode | undefined => {\n if (a === undefined) return b;\n if (b === undefined) return a;\n\n if (Array.isArray(a) && Array.isArray(b)) {\n // Concatenate arrays when merging sibling results\n return [...a, ...b] as unknown as ContentNode;\n }\n\n if (isObject(a) && isObject(b) && !hasNodeType(a) && !hasNodeType(b)) {\n const result: Record<string, any> = { ...a };\n for (const key of Object.keys(b)) {\n result[key] = mergeValues(\n result[key] as unknown as ContentNode | undefined,\n (b as Record<string, any>)[key] as unknown as ContentNode | undefined\n );\n }\n return result as ContentNode;\n }\n\n // For primitives or differing structures, prefer b (more recent)\n return b;\n};\n\nconst mergeSplitResults = (\n base: SplitResult,\n addition: SplitResult\n): SplitResult => {\n const result: SplitResult = { ...base };\n\n // Merge common\n result.common = mergeValues(base.common, addition.common);\n\n // Merge each locale key present in either side\n const localeKeys = new Set<string>([\n ...Object.keys(base).filter((k) => k !== 'common'),\n ...Object.keys(addition).filter((k) => k !== 'common'),\n ]);\n\n for (const key of localeKeys) {\n // @ts-ignore: dynamic keys for locales\n result[key] = mergeValues(\n base[key] as ContentNode | undefined,\n addition[key] as ContentNode | undefined\n );\n }\n\n return result;\n};\n\nconst splitNode = (node: ContentNode): SplitResult => {\n // Translation node: allocate entirely to per-locale buckets\n if (isObject(node) && (node as any)?.nodeType === NodeType.Translation) {\n const translations = (node as any)[NodeType.Translation] as Record<\n string,\n ContentNode\n >;\n\n const result: SplitResult = {};\n for (const locale of Object.keys(translations)) {\n const child = translations[locale];\n const childSplit = splitNode(child);\n\n // The content under a translation belongs to the locale, not common\n // Merge common portion of the child (if any) into the locale as well\n const mergedForLocale = mergeValues(childSplit.common, undefined);\n\n // Compose locale content: prefer the fully rebuilt child by resolving deeper translations recursively\n // which are already split inside childSplit. We need to recompose a single node for this locale.\n // Recompose by merging all keys in childSplit except 'common' into a single node, then merge child's common.\n let recomposed: ContentNode | undefined;\n for (const key of Object.keys(childSplit)) {\n if (key === 'common') continue;\n recomposed = mergeValues(\n recomposed,\n childSplit[key] as ContentNode | undefined\n );\n }\n const finalLocaleNode = mergeValues(mergedForLocale, recomposed);\n\n if (finalLocaleNode !== undefined) {\n // @ts-ignore dynamic locale key\n result[locale] = finalLocaleNode;\n }\n }\n\n return result;\n }\n\n // Arrays: split each element and merge results index-wise\n if (Array.isArray(node)) {\n const commonArray: any[] = [];\n const perLocaleArrays: Record<string, any[]> = {};\n\n node.forEach((child) => {\n const childSplit = splitNode(child as ContentNode);\n\n if (childSplit.common !== undefined) {\n commonArray.push(childSplit.common);\n }\n\n for (const key of Object.keys(childSplit)) {\n if (key === 'common') continue;\n if (!perLocaleArrays[key]) perLocaleArrays[key] = [];\n const value = childSplit[key];\n if (value !== undefined) perLocaleArrays[key].push(value);\n }\n });\n\n const result: SplitResult = {};\n if (commonArray.length > 0)\n result.common = commonArray as unknown as ContentNode;\n for (const key of Object.keys(perLocaleArrays)) {\n // @ts-ignore dynamic locale key\n result[key] = perLocaleArrays[key] as unknown as ContentNode;\n }\n return result;\n }\n\n // Objects (non-typed): recursively split properties\n if (isObject(node) && !hasNodeType(node)) {\n let accumulated: SplitResult = {};\n\n for (const key of Object.keys(node)) {\n const childSplit = splitNode((node as any)[key] as ContentNode);\n\n // Assign property into common\n if (childSplit.common !== undefined) {\n accumulated = mergeSplitResults(accumulated, {\n common: { [key]: childSplit.common } as unknown as ContentNode,\n });\n }\n\n // Assign property into each locale bucket\n for (const locale of Object.keys(childSplit)) {\n if (locale === 'common') continue;\n accumulated = mergeSplitResults(accumulated, {\n // @ts-ignore dynamic locale key\n [locale]: { [key]: childSplit[locale] } as unknown as ContentNode,\n });\n }\n }\n\n return accumulated;\n }\n\n // Primitives or typed nodes (non-translation): entirely common\n return { common: node } as SplitResult;\n};\n\nexport const getSplittedContent = (\n content: ContentNode\n): SplittedContentOutput => {\n const split = splitNode(content);\n\n // Build final output with only defined sections\n const output: Record<string, ContentNode> = {};\n if (split.common !== undefined) {\n output.common = split.common;\n }\n for (const key of Object.keys(split)) {\n if (key === 'common') continue;\n const value = split[key] as ContentNode | undefined;\n if (value !== undefined) {\n output[key] = value;\n }\n }\n\n return output as unknown as SplittedContentOutput;\n};\n\n/**\n * Splits the `content` field of a Dictionary into \"common\" and per-locale buckets.\n *\n * Given a dictionary like:\n * ```js\n * {\n * key: \"my-key\",\n * content: {\n * commonContent: \"common content\",\n * multilingualContent: t({\n * en: \"english content\",\n * fr: \"french content\",\n * de: \"german content\",\n * }),\n * },\n * }\n * ```\n *\n * It produces:\n * ```js\n * {\n * common: { commonContent: \"common content\" },\n * en: { multilingualContent: \"english content\" },\n * fr: { multilingualContent: \"french content\" },\n * de: { multilingualContent: \"german content\" },\n * }\n * ```\n *\n * @param dictionary - The input dictionary object with possible multilingual or common content.\n * @returns An object mapping \"common\" and each locale to their corresponding content subtrees.\n */\nexport const getSplittedDictionaryContent = (\n dictionary: Dictionary\n): SplittedContentOutput<Dictionary['content']> =>\n getSplittedContent(dictionary.content);\n"],"mappings":"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"}