{"version":3,"file":"serialize.mjs","sources":["../src/serialize.ts"],"sourcesContent":["import { IntlBase } from './intlBase';\nimport { AstNode } from './parse';\n\nexport type ExternalSerializer<Params = unknown> = (\n  params: Params | null,\n  variableValue: unknown,\n  intl: IntlBase,\n  serializeNested: (ast: AstNode[]) => unknown,\n  node: AstNode,\n  values: Record<string, string | number | boolean | undefined | unknown>,\n) => string;\nexport type ExternalSerializers<Params = unknown> = {\n  [serializerName: string]: ExternalSerializer<Params>;\n};\n\nexport type VerboseSerialization = {\n  [variableName: string]: unknown;\n};\n\ntype Reducer<T> = {\n  getInit: () => T;\n  reduce: (acc: T, item: unknown, nodeType: 'string' | 'variable' | 'plural' | 'select' | 'external' | 'unknown') => T;\n};\nconst defaultReducer: Reducer<string | (string | unknown)[]> = {\n  getInit: () => '',\n  reduce: (acc, item) => {\n    if (typeof item !== 'object') {\n      if (Array.isArray(acc)) {\n        if (typeof acc[acc.length - 1] !== 'object') acc[acc.length - 1] += String(item);\n        else acc.push(String(item));\n      } else {\n        acc += String(item);\n      }\n    } else {\n      if (Array.isArray(acc)) acc.push(item);\n      else if (acc === '') return [item];\n      else return [acc, item];\n    }\n    return acc;\n  },\n};\n\nexport type SerializeIcuOptions = {\n  externalSerializers?: ExternalSerializers;\n  reducer?: Reducer<any>;\n  original?: string;\n};\n\nexport const serializeIcu = <T = string>(\n  ast: AstNode[],\n  values: Record<string, string | number | boolean | undefined | unknown>,\n  intl: IntlBase,\n  options?: SerializeIcuOptions,\n): T => {\n  const serializeNested = (ast: AstNode[]) => serializeIcu(ast, values, intl, options);\n  const reducer = options?.reducer ?? (defaultReducer as any as Reducer<T>);\n  let result = reducer.getInit();\n  for (const node of ast) {\n    if (typeof node === 'string') {\n      result = reducer.reduce(result, node, 'string');\n    } else if (typeof node === 'object' && node !== null) {\n      if (node.type === 'pure-text') {\n        result = reducer.reduce(result, node.text, 'string');\n      } else if (node.type === 'variable') {\n        if (!values || !(node.name in values)) {\n          throw new Error(`Variable \"${node.name}\" was not provided for string \"${options?.original}\"`);\n        }\n        let value = values[node.name as keyof typeof values];\n        if (typeof value === 'number' && node.offset) value -= node.offset.value;\n        if (value !== false && value !== null && value !== undefined) {\n          result = reducer.reduce(result, value, 'variable');\n        }\n      } else if (node.type === 'plural') {\n        const value = values?.[node.variable.name as keyof typeof values];\n        const exactRule = node.options.exacts?.[value as keyof typeof node.options.exacts];\n        let nestedAst = value;\n        if (exactRule) {\n          nestedAst = exactRule;\n        } else {\n          const finalValue = (value as number) - (node.offset?.value ?? 0);\n          const pluralBase = node.cardinal ? intl.pluralRulesCardinal : intl.pluralRulesOrdinal;\n          const selected = pluralBase.select(finalValue);\n          nestedAst = node.options[selected] ?? node.options.other;\n        }\n        if (Array.isArray(nestedAst)) {\n          result = reducer.reduce(result, serializeIcu(nestedAst, values, intl, options), 'plural');\n        } else {\n          result = reducer.reduce(result, nestedAst, 'plural');\n        }\n      } else if (node.type === 'select') {\n        const value = values?.[node.variable.name as keyof typeof values];\n        const nestedAst = node.options[value as keyof typeof node.options] ?? node.options.other ?? String(value);\n        result = reducer.reduce(result, serializeIcu(nestedAst as AstNode[], values, intl, options), 'select');\n      } else if (node.type === 'external') {\n        const value = values[node.variableName];\n        if (!options?.externalSerializers?.[node.name]) {\n          if (!node.optionsPart && node.name === 'number') {\n            result = reducer.reduce(result, new Intl.NumberFormat(intl.locale).format(value as number), 'external');\n            continue;\n          }\n          throw new Error(`No serializer provided for type ${node.name}`);\n        }\n        const subResult = options.externalSerializers?.[node.name](\n          node.data,\n          values[node.variableName],\n          intl,\n          serializeNested,\n          node,\n          values,\n        );\n        if (Array.isArray(subResult)) {\n          for (const chunk of subResult) {\n            result = reducer.reduce(result, chunk, 'external');\n          }\n        } else {\n          result = reducer.reduce(result, subResult, 'external');\n        }\n      } else {\n        result = reducer.reduce(result, node, 'unknown');\n      }\n    }\n  }\n  return result;\n};\n\nexport type PreSerializer<InputAst extends AstNode[], OutputAst extends AstNode[]> = (inputAst: InputAst) => OutputAst;\n"],"names":["getInit","reduce","acc","item","Array","isArray","length","String","push","ast","values","intl","options","_options$reducer","_step","serializeNested","serializeIcu","reducer","defaultReducer","result","_iterator","done","node","value","type","text","name","original","offset","_node$options$exacts","_value","variable","exactRule","exacts","nestedAst","_node$offset$value","_node$offset","_node$options$selecte","finalValue","cardinal","pluralRulesCardinal","pluralRulesOrdinal","select","selected","other","_ref","_node$options$_value","_options$externalSeri","_options$externalSeri2","variableName","externalSerializers","optionsPart","NumberFormat","locale","format","Error","data","subResult"],"mappings":"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"}