{"version":3,"file":"tags.cjs","sources":["../src/tags.ts"],"sourcesContent":["import { NanointlPlugin } from './makeIntl';\nimport { AstNode, PostParser } from './parse';\nimport { ExternalSerializer } from './serialize';\nimport {\n  UnwrapLinkedSleeve,\n  LinkedSleeveNexusLimit,\n  Increment,\n  Decrement,\n  ICUVariablesMapFromTemplate,\n  SerializationResult,\n} from './typings';\n\ntype TagNode = {\n  type: 'external';\n  name: 'tag';\n  variableName: string;\n  data: { children: TagsAstNode[] };\n};\nexport type TagsAstNode = string | TagNode;\nexport type TagsParsingStore = {\n  parentAstChain: TagsAstNode[][];\n  ast: (TagsAstNode | AstNode)[];\n  tagsChain: TagNode[];\n};\n\nexport const makeTagsParsingExternalStore = (): TagsParsingStore => ({\n  parentAstChain: [],\n  ast: [],\n  tagsChain: [],\n});\n\nexport const tagsChunkParser = (message: string, externalStore?: TagsParsingStore): TagsAstNode[] | undefined => {\n  const store: TagsParsingStore = externalStore ?? makeTagsParsingExternalStore();\n  let closingTag = false;\n  let tagAttrsSkip = false;\n  let currentAstPart: TagsAstNode | null = null;\n\n  const pushCurrentPartToAst = () => {\n    if (currentAstPart) {\n      if (typeof currentAstPart === 'string' && typeof store.ast[store.ast.length - 1] === 'string') {\n        store.ast[store.ast.length - 1] += currentAstPart;\n      } else {\n        store.ast.push(currentAstPart);\n      }\n    }\n  };\n\n  for (let i = 0; i < message.length; i++) {\n    const char = message[i];\n\n    if (tagAttrsSkip && char !== '>') {\n      continue;\n    }\n\n    if (char === '<') {\n      closingTag = false;\n      pushCurrentPartToAst();\n      currentAstPart = {\n        type: 'external',\n        name: 'tag',\n        variableName: '',\n        data: { children: [] },\n      };\n    } else {\n      if (currentAstPart === null) currentAstPart = '';\n      if (typeof currentAstPart === 'string') currentAstPart += char;\n      if (typeof currentAstPart === 'object' && currentAstPart.name === 'tag') {\n        if (char === ' ' || char === '\\n' || char === '\\r' || char === '\\t') {\n          tagAttrsSkip = true;\n          continue;\n        } else if (char === '/') {\n          closingTag = true;\n        } else if (char === '>') {\n          tagAttrsSkip = false;\n          pushCurrentPartToAst();\n          if (!closingTag) {\n            store.tagsChain.push(currentAstPart);\n            store.parentAstChain.push(store.ast as TagsAstNode[]);\n            store.ast = currentAstPart.data.children;\n          } else {\n            const prevChar = message[i - 1];\n            const singleTag = prevChar === '/';\n            if (!singleTag) {\n              const parentTag = store.tagsChain.pop();\n              if (parentTag?.variableName !== currentAstPart?.variableName) {\n                throw new Error(\n                  `Wrong order of tags: got \"${currentAstPart.variableName}\" on closing of \"${parentTag?.variableName}\"`,\n                );\n              }\n              store.ast.pop();\n              if (store.parentAstChain.length > 0) store.ast = store.parentAstChain.pop()!;\n            }\n          }\n          currentAstPart = null;\n        } else {\n          currentAstPart.variableName += char;\n        }\n      }\n    }\n  }\n\n  if (typeof currentAstPart === 'object' && currentAstPart?.name === 'tag') {\n    throw new Error(`Unclosed tag ${currentAstPart.variableName}`);\n  }\n  pushCurrentPartToAst();\n  if (!externalStore) return (store.parentAstChain[0] ?? store.ast) as any;\n};\n\nexport const tagsPostParser: PostParser<AstNode[], AstNode[]> = (icuAst: AstNode[]) => {\n  const store = makeTagsParsingExternalStore();\n\n  for (const node of icuAst) {\n    if (typeof node === 'string') tagsChunkParser(node, store);\n    else if (node.type === 'select') {\n      const options: typeof node.options = {};\n      for (const option in node.options) {\n        options[option as keyof typeof options] = tagsPostParser(node.options[option]) as AstNode[];\n      }\n      store.ast.push({ ...node, options });\n    } else if (node.type === 'plural') {\n      const options: typeof node.options = { exacts: {} };\n      for (const option in node.options) {\n        if (option === 'exacts') {\n          for (const exact in node.options.exacts) {\n            options.exacts![exact] = tagsPostParser(node.options.exacts[exact]) as AstNode[];\n          }\n        } else {\n          options[option as Exclude<keyof typeof options, 'exacts'>] = tagsPostParser(\n            node.options[option as keyof typeof options] as AstNode[],\n          ) as AstNode[];\n        }\n      }\n      store.ast.push({ ...node, options });\n    } else {\n      store.ast.push(node);\n    }\n  }\n\n  if (store.parentAstChain.length !== 0) {\n    throw new Error(`Unclosed tag ${store.parentAstChain[0][0]}`);\n  }\n  return store.ast as AstNode[];\n};\n\nexport const tagsPostSerializer: ExternalSerializer<{ children: AstNode[] }> = (\n  params,\n  value,\n  _intl,\n  serializeNested,\n  node,\n  values,\n) => {\n  const variableName = (node as { variableName: string })?.variableName;\n  if (!value) {\n    if (values.tagsFallback) value = values.tagsFallback;\n    else throw new Error(`Serializer for \"${variableName}\" was not provided`);\n  }\n  const renderChildren = value as (params: { children: unknown; tag: string }) => string;\n  return renderChildren?.({ children: serializeNested(params?.children ?? []), tag: variableName });\n};\n\nexport const tagsPlugin: NanointlPlugin<any> = {\n  name: 'tags-plugin',\n  init(options) {\n    options.addSerializer('tag', tagsPostSerializer);\n    options.addPostParser(tagsPostParser as PostParser<AstNode[], AstNode[]>);\n  },\n};\n\ntype TraverseTagContent<\n  TagName extends string,\n  Template extends string,\n  Depth extends number = 0,\n  NexusLength extends number = 0,\n  Escaping extends boolean = false,\n> = NexusLength extends LinkedSleeveNexusLimit\n  ? { next: UnwrapLinkedSleeve<TraverseTagContent<TagName, Template, Depth, 0, Escaping>> }\n  : Template extends `${infer Char}${infer Rest}`\n  ? Escaping extends false\n    ? Char extends \"'\"\n      ? Rest extends `'${infer Rest}`\n        ? [\"'\", TraverseTagContent<TagName, Rest, Depth, Increment<NexusLength>, Escaping>]\n        : TraverseTagContent<TagName, Rest, Depth, Increment<NexusLength>, true>\n      : Template extends `<${TagName}>${infer Rest}`\n      ? [`<${TagName}>`, TraverseTagContent<TagName, Rest, Increment<Depth>, Increment<NexusLength>, Escaping>]\n      : Template extends `<${TagName} ${infer TagAttributes}>${infer Rest}`\n      ? [`<${TagName} ${TagAttributes}>`, TraverseTagContent<TagName, Rest, Increment<Depth>, Increment<NexusLength>, Escaping>]\n      : Template extends `</${TagName}>${infer Rest}`\n      ? Depth extends 0\n        ? []\n        : [`</${TagName}>`, TraverseTagContent<TagName, Rest, Decrement<Depth>, Increment<NexusLength>, Escaping>]\n      : [Char, TraverseTagContent<TagName, Rest, Depth, Increment<NexusLength>, Escaping>]\n    : Char extends \"'\"\n    ? TraverseTagContent<TagName, Rest, Depth, Increment<NexusLength>, false>\n    : [Char, TraverseTagContent<TagName, Rest, Depth, Increment<NexusLength>, Escaping>]\n  : [];\n\ntype ExtractTagChildrenContent<\n  TagName extends string,\n  Template extends string,\n  Result = UnwrapLinkedSleeve<TraverseTagContent<TagName, Template>>[0],\n> = Result extends string ? Result : '';\n\ntype ChildrenSerializationResults<\n  Template extends string,\n  Values extends {} = {},\n> = keyof ICUVariablesMapFromTemplate<Template> extends keyof Values\n  ? SerializationResult<Pick<Values, keyof ICUVariablesMapFromTemplate<Template>>>\n  : any;\n\ntype TagsParser<Template extends string, Values extends {} = {}> = Template extends `${string}<${infer TagInner}>${infer After}`\n  ? TagInner extends `/${string}`\n    ? TagsParser<After>\n    : TagInner extends `${infer TagName} ${string}`\n    ? {\n        vars: [\n          {\n            name: TagName;\n            type: (props: { children: ChildrenSerializationResults<ExtractTagChildrenContent<TagName, After>, Values> }) => any;\n          },\n          ...TagsParser<After>['vars'],\n        ];\n      }\n    : TagInner extends `${infer TagName}/`\n    ? {\n        vars: [\n          {\n            name: TagName;\n            // eslint-disable-next-line @typescript-eslint/no-unused-vars\n            type: () => any;\n          },\n          ...TagsParser<After>['vars'],\n        ];\n      }\n    : {\n        vars: [\n          {\n            name: TagInner;\n            type: (props: { children: ChildrenSerializationResults<ExtractTagChildrenContent<TagInner, After>, Values> }) => any;\n          },\n          ...TagsParser<After>['vars'],\n        ];\n      }\n  : { vars: [] };\n\ndeclare global {\n  // @ts-ignore\n  interface NanointlOverallParsers<Template extends string, Values extends {} = {}> {\n    tags: TagsParser<Template, Values>;\n  }\n}\n"],"names":["makeTagsParsingExternalStore","message","externalStore","store","parentAstChain","ast","tagsChain","closingTag","tagAttrsSkip","pushCurrentPartToAst","currentAstPart","length","push","i","char","type","name","variableName","data","children","parentTag","pop","_currentAstPart","Error","_currentAstPart2","_store$parentAstChain","icuAst","node","tagsChunkParser","options","option","tagsPostParser","_extends","_options","exacts","exact","params","value","_intl","serializeNested","values","_params$children","tagsFallback","tag","tagsPlugin","init","addSerializer","tagsPostSerializer","addPostParser"],"mappings":"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"}