{"version":3,"file":"plugins.cjs","names":["NodeType","getTranslation","enumerationPlugin: Plugins","getEnumeration","conditionPlugin: Plugins","getCondition","genderPlugin: Plugins","getGender","insertionPlugin: Plugins","newKeyPath: KeyPath[]","insertionStringPlugin: Plugins","node","deepTransformNode","children","getInsertion","nestedPlugin: Plugins","getNesting","filePlugin: Plugins"],"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: 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, props),\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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"}