{"version":3,"file":"ICU.cjs","names":["html","insert","enu","plural","gender","NodeTypes","deepTransformNode"],"sources":["../../../src/messageFormat/ICU.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { deepTransformNode } from '../interpreter';\nimport { enu, gender, html, insert, plural } from '../transpiler';\n\n/**\n * ICU MessageFormat Converter\n *\n * This module converts between ICU MessageFormat and Intlayer's internal format.\n *\n * IMPORTANT: Two different formats are used:\n *\n * 1. ICU MessageFormat (external format):\n *    - Simple variables: {name}\n *    - Formatted variables: {amount, number, currency}\n *    - Plural: {count, plural, =0 {none} other {# items}}\n *    - Select: {gender, select, male {He} female {She} other {They}}\n *\n * 2. Intlayer Internal Format:\n *    - Simple variables: {{name}}  (double braces for clarity and to distinguish from literal text)\n *    - Formatted variables: {amount, number, currency}  (keeps ICU format)\n *    - Plural: enu({ 0: 'none', fallback: '{{count}} items' })\n *    - Select/Gender: gender({ male: 'He', female: 'She', fallback: 'They' })\n *\n * Conversion flow:\n * - ICU → Intlayer: {name} → {{name}}\n * - Intlayer → ICU: {{name}} → {name}\n *\n * The double braces in Intlayer format serve to:\n * - Distinguish variables from literal text containing braces\n * - Work with getInsertion() runtime function which expects {{var}} patterns\n * - Provide clear visual distinction in content dictionaries\n */\n\n// Types for our AST\ntype ICUNode =\n  | string\n  | {\n      type: 'argument';\n      name: string;\n      format?: { type: string; style?: string };\n    }\n  | { type: 'plural'; name: string; options: Record<string, ICUNode[]> }\n  | { type: 'select'; name: string; options: Record<string, ICUNode[]> };\n\nexport type JsonValue =\n  | string\n  | number\n  | boolean\n  | null\n  | JsonValue[]\n  | { [key: string]: JsonValue };\n\nconst parseICU = (text: string): ICUNode[] => {\n  let index = 0;\n\n  const parseNodes = (): ICUNode[] => {\n    const nodes: ICUNode[] = [];\n    let currentText = '';\n\n    while (index < text.length) {\n      const char = text[index];\n\n      if (char === '{') {\n        if (currentText) {\n          nodes.push(currentText);\n          currentText = '';\n        }\n        index++; // skip {\n        nodes.push(parseArgument());\n      } else if (char === '}') {\n        // End of current block\n        break;\n      } else if (char === \"'\") {\n        // Escaping\n        if (index + 1 < text.length && text[index + 1] === \"'\") {\n          currentText += \"'\";\n          index += 2;\n        } else {\n          // Find next quote\n          const nextQuote = text.indexOf(\"'\", index + 1);\n          if (nextQuote !== -1) {\n            // Determine if this is escaping syntax characters\n            // For simplicity, we'll treat content between single quotes as literal\n            // provided it contains syntax chars.\n            // Standard ICU: ' quoted string '\n            // If it is just an apostrophe, it should be doubled.\n            // But simplified: take content between quotes literally.\n            currentText += text.substring(index + 1, nextQuote);\n            index = nextQuote + 1;\n          } else {\n            currentText += \"'\";\n            index++;\n          }\n        }\n      } else {\n        currentText += char;\n        index++;\n      }\n    }\n\n    if (currentText) {\n      nodes.push(currentText);\n    }\n    return nodes;\n  };\n\n  const parseArgument = (): ICUNode => {\n    // We are past '{'\n    // Parse name\n    let name = '';\n    while (index < text.length && /[^,}]/.test(text[index])) {\n      name += text[index];\n      index++;\n    }\n    name = name.trim();\n\n    if (index >= text.length) throw new Error('Unclosed argument');\n\n    if (text[index] === '}') {\n      index++;\n      return { type: 'argument', name };\n    }\n\n    // Must be comma\n    if (text[index] === ',') {\n      index++;\n      // Parse type\n      let type = '';\n      while (index < text.length && /[^,}]/.test(text[index])) {\n        type += text[index];\n        index++;\n      }\n      type = type.trim();\n\n      if (index >= text.length) throw new Error('Unclosed argument');\n\n      if (text[index] === '}') {\n        index++;\n        return { type: 'argument', name, format: { type } };\n      }\n\n      if (text[index] === ',') {\n        index++;\n\n        // If plural or select, parse options\n        if (type === 'plural' || type === 'select') {\n          // Parse options\n          const options: Record<string, ICUNode[]> = {};\n\n          while (index < text.length && text[index] !== '}') {\n            // skip whitespace\n            while (index < text.length && /\\s/.test(text[index])) index++;\n\n            // parse key\n            let key = '';\n            while (index < text.length && /[^{\\s]/.test(text[index])) {\n              key += text[index];\n              index++;\n            }\n\n            while (index < text.length && /\\s/.test(text[index])) index++;\n\n            if (text[index] !== '{')\n              throw new Error('Expected { after option key');\n            index++; // skip {\n\n            const value = parseNodes();\n\n            if (text[index] !== '}')\n              throw new Error('Expected } after option value');\n            index++; // skip }\n\n            options[key] = value;\n\n            while (index < text.length && /\\s/.test(text[index])) index++;\n          }\n\n          index++; // skip closing argument }\n\n          if (type === 'plural') {\n            return { type: 'plural', name, options };\n          } else if (type === 'select') {\n            return { type: 'select', name, options };\n          }\n        } else {\n          // Parse style for number/date/time\n          let style = '';\n          while (index < text.length && text[index] !== '}') {\n            style += text[index];\n            index++;\n          }\n          if (index >= text.length) throw new Error('Unclosed argument');\n\n          style = style.trim();\n          index++; // skip }\n\n          return { type: 'argument', name, format: { type, style } };\n        }\n      }\n    }\n\n    throw new Error('Malformed argument');\n  };\n\n  return parseNodes();\n};\n\nconst icuNodesToIntlayer = (nodes: ICUNode[]): any => {\n  if (nodes.length === 0) return '';\n  if (nodes.length === 1 && typeof nodes[0] === 'string') {\n    const node = nodes[0];\n    if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n      return html(node);\n    }\n    return node;\n  }\n\n  // Check if we can flatten to a single string (insert)\n  const canFlatten = nodes.every(\n    (node) => typeof node === 'string' || node.type === 'argument'\n  );\n  if (canFlatten) {\n    let str = '';\n    for (const node of nodes) {\n      if (typeof node === 'string') {\n        str += node;\n      } else if (typeof node !== 'string' && node.type === 'argument') {\n        if (node.format) {\n          // Formatted variables keep ICU format: {var, type, style}\n          str += `{${node.name}, ${node.format.type}${\n            node.format.style ? `, ${node.format.style}` : ''\n          }}`;\n        } else {\n          // Simple variables use Intlayer format: {{var}}\n          str += `{{${node.name}}}`;\n        }\n      }\n    }\n    if (/<[a-zA-Z0-9-]+[^>]*>/.test(str)) {\n      return html(str);\n    }\n    return insert(str);\n  }\n\n  // Mix of string and complex types.\n  // If we have just one complex type and it covers everything?\n  if (nodes.length === 1) {\n    const node = nodes[0];\n\n    if (typeof node === 'string') {\n      if (/<[a-zA-Z0-9-]+[^>]*>/.test(node)) {\n        return html(node);\n      }\n      return node;\n    }\n    if (node.type === 'argument') {\n      if (node.format) {\n        return insert(\n          `{${node.name}, ${node.format.type}${\n            node.format.style ? `, ${node.format.style}` : ''\n          }}`\n        );\n      }\n      return insert(`{{${node.name}}}`);\n    }\n    if (node.type === 'plural') {\n      const options: Record<string, any> = {};\n      let hasExactMatch = false;\n\n      for (const key of Object.keys(node.options)) {\n        if (key.startsWith('=')) {\n          hasExactMatch = true;\n          break;\n        }\n      }\n\n      if (hasExactMatch) {\n        for (const [key, val] of Object.entries(node.options)) {\n          // Map ICU keys to Intlayer keys\n          let newKey = key;\n          if (key.startsWith('=')) {\n            newKey = key.substring(1); // =0 -> 0\n          } else if (key === 'one') {\n            newKey = '1';\n          } else if (key === 'two') {\n            newKey = '2';\n          } else if (key === 'few') {\n            newKey = '<=3';\n          } else if (key === 'many') {\n            newKey = '>=4';\n          } else if (key === 'other') {\n            newKey = 'fallback';\n          }\n          // Handle # in plural value\n          // For plural, we need to pass the variable name down or replace #\n          // Intlayer uses {{n}} (or whatever var name) for simple variables\n          // We should replace # with {{n}} in the string parts of val\n          const replacedVal = val.map((v) => {\n            if (typeof v === 'string') {\n              return v.replace(/#/g, `{{${node.name}}}`);\n            }\n            return v;\n          });\n\n          options[newKey] = icuNodesToIntlayer(replacedVal);\n        }\n\n        // Preserve variable name\n        options.__intlayer_icu_var = node.name;\n\n        return enu(options);\n      } else {\n        for (const [key, val] of Object.entries(node.options)) {\n          // Handle # in plural value\n          const replacedVal = val.map((v) => {\n            if (typeof v === 'string') {\n              return v.replace(/#/g, `{{${node.name}}}`);\n            }\n            return v;\n          });\n\n          options[key] = icuNodesToIntlayer(replacedVal);\n        }\n\n        return plural(options as any);\n      }\n    }\n    if (node.type === 'select') {\n      const options: Record<string, any> = {};\n\n      for (const [key, val] of Object.entries(node.options)) {\n        options[key] = icuNodesToIntlayer(val);\n      }\n\n      // Check if it looks like gender\n      const optionKeys = Object.keys(options);\n      // It is gender if it has 'male' OR 'female' AND only contains gender keys (male, female, other)\n      const isGender =\n        (options.male || options.female) &&\n        optionKeys.every((k) =>\n          ['male', 'female', 'other', 'fallback'].includes(k)\n        );\n\n      if (isGender) {\n        return gender({\n          fallback: options.other,\n          male: options.male,\n          female: options.female,\n        });\n      }\n\n      // Preserve variable name\n      options.__intlayer_icu_var = node.name;\n\n      return enu(options);\n    }\n  }\n\n  // If multiple nodes, return array\n  return nodes.map((node) => icuNodesToIntlayer([node]));\n};\n\nconst icuToIntlayerPlugin = {\n  canHandle: (node: any) =>\n    typeof node === 'string' &&\n    (node.includes('{') ||\n      node.includes('}') ||\n      /<[a-zA-Z0-9-]+[^>]*>/.test(node)),\n  transform: (node: any) => {\n    try {\n      const ast = parseICU(node);\n      return icuNodesToIntlayer(ast);\n    } catch {\n      // If parsing fails, return original string\n      return node;\n    }\n  },\n};\n\nconst intlayerToIcuPlugin = {\n  canHandle: (node: any) => {\n    if (\n      typeof node === 'string' &&\n      (node.includes('{') || node.includes('}'))\n    ) {\n      return true;\n    }\n\n    if (\n      node &&\n      typeof node === 'object' &&\n      (node.nodeType === NodeTypes.INSERTION ||\n        node.nodeType === NodeTypes.HTML ||\n        node.nodeType === NodeTypes.ENUMERATION ||\n        node.nodeType === NodeTypes.PLURAL ||\n        node.nodeType === NodeTypes.GENDER ||\n        node.nodeType === 'composite')\n    ) {\n      return true;\n    }\n\n    if (Array.isArray(node)) {\n      if (node.length === 0) return false;\n\n      let hasNode = false;\n      let hasPlainObjectOrArray = false;\n\n      for (const item of node) {\n        if (typeof item === 'string') {\n        } else if (\n          item &&\n          typeof item === 'object' &&\n          (item.nodeType === NodeTypes.INSERTION ||\n            item.nodeType === NodeTypes.HTML ||\n            item.nodeType === NodeTypes.ENUMERATION ||\n            item.nodeType === NodeTypes.GENDER ||\n            item.nodeType === 'composite')\n        ) {\n          hasNode = true;\n        } else {\n          hasPlainObjectOrArray = true;\n        }\n      }\n\n      // If it contains plain objects or nested arrays, it's a structural array\n      if (hasPlainObjectOrArray) return false;\n      // If it contains ONLY strings, it's a structural array, not a composite string\n      if (!hasNode) return false;\n\n      return true;\n    }\n\n    return false;\n  },\n  transform: (node: any, props: any, next: any) => {\n    // Convert Intlayer's double-brace format {{var}} to ICU's single-brace format {var}\n    if (typeof node === 'string') {\n      return node.replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n    }\n\n    if (node.nodeType === NodeTypes.INSERTION) {\n      return node[NodeTypes.INSERTION].replace(/\\{\\{([^}]+)\\}\\}/g, '{$1}');\n    }\n\n    if (node.nodeType === NodeTypes.HTML) {\n      return node[NodeTypes.HTML];\n    }\n\n    if (node.nodeType === NodeTypes.PLURAL) {\n      const options = node[NodeTypes.PLURAL];\n\n      const transformedOptions: Record<string, string> = {};\n      for (const [key, val] of Object.entries(options)) {\n        const childVal = next(val, props);\n        transformedOptions[key] =\n          typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n      }\n\n      let varName = 'count';\n\n      const fallbackVal =\n        transformedOptions.other || Object.values(transformedOptions)[0];\n\n      if (fallbackVal) {\n        const match = fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n        if (match) {\n          varName = match[1];\n        }\n      }\n\n      const parts = [];\n\n      for (const [key, val] of Object.entries(transformedOptions)) {\n        let strVal = val;\n        strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n        parts.push(`${key} {${strVal}}`);\n      }\n      return `{${varName}, plural, ${parts.join(' ')}}`;\n    }\n\n    if (node.nodeType === NodeTypes.ENUMERATION) {\n      const options = node[NodeTypes.ENUMERATION];\n\n      const transformedOptions: Record<string, string> = {};\n      for (const [key, val] of Object.entries(options)) {\n        if (key === '__intlayer_icu_var') continue;\n        const childVal = next(val, props);\n        transformedOptions[key] =\n          typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n      }\n\n      let varName = options.__intlayer_icu_var || 'n';\n\n      if (!options.__intlayer_icu_var) {\n        const fallbackVal =\n          transformedOptions.fallback ||\n          transformedOptions.other ||\n          Object.values(transformedOptions)[0];\n        const match = fallbackVal.match(/\\{([a-zA-Z0-9_]+)\\}(?!,)/);\n        if (match) {\n          varName = match[1];\n        }\n      }\n\n      const keys = Object.keys(transformedOptions);\n      const pluralKeys = [\n        '1',\n        '2',\n        '<=3',\n        '>=4',\n        'fallback',\n        'other',\n        'zero',\n        'one',\n        'two',\n        'few',\n        'many',\n      ];\n\n      const isPlural = keys.every(\n        (k) => pluralKeys.includes(k) || /^[<>=]?\\d+(\\.\\d+)?$/.test(k)\n      );\n\n      const parts = [];\n\n      if (isPlural) {\n        for (const [key, val] of Object.entries(transformedOptions)) {\n          let icuKey = key;\n          if (key === 'fallback') icuKey = 'other';\n          else if (key === '<=3') icuKey = 'few';\n          else if (key === '>=4') icuKey = 'many';\n          else if (/^\\d+$/.test(key)) icuKey = `=${key}`;\n          else if (['zero', 'few', 'many'].includes(key)) icuKey = key;\n          else icuKey = 'other';\n\n          let strVal = val;\n          strVal = strVal.replace(new RegExp(`\\\\{${varName}\\\\}`, 'g'), '#');\n          parts.push(`${icuKey} {${strVal}}`);\n        }\n        return `{${varName}, plural, ${parts.join(' ')}}`;\n      } else {\n        const entries = Object.entries(transformedOptions).sort(\n          ([keyA], [keyB]) => {\n            if (keyA === 'fallback' || keyA === 'other') return 1;\n            if (keyB === 'fallback' || keyB === 'other') return -1;\n            return 0;\n          }\n        );\n\n        for (const [key, val] of entries) {\n          let icuKey = key;\n          if (key === 'fallback') icuKey = 'other';\n          parts.push(`${icuKey} {${val}}`);\n        }\n        return `{${varName}, select, ${parts.join(' ')}}`;\n      }\n    }\n\n    if (node.nodeType === NodeTypes.GENDER) {\n      const options = node[NodeTypes.GENDER];\n      const varName = 'gender';\n      const parts = [];\n\n      const entries = Object.entries(options).sort(([keyA], [keyB]) => {\n        if (keyA === 'fallback') return 1;\n        if (keyB === 'fallback') return -1;\n        return 0;\n      });\n\n      for (const [key, val] of entries) {\n        let icuKey = key;\n        if (key === 'fallback') icuKey = 'other';\n\n        const childVal = next(val, props);\n        const strVal =\n          typeof childVal === 'string' ? childVal : JSON.stringify(childVal);\n\n        parts.push(`${icuKey} {${strVal}}`);\n      }\n      return `{${varName}, select, ${parts.join(' ')}}`;\n    }\n\n    if (\n      Array.isArray(node) ||\n      (node.nodeType === 'composite' && Array.isArray(node.composite))\n    ) {\n      // handle array/composite strings that passed canHandle\n      const arr = Array.isArray(node) ? node : node.composite;\n      const items = arr.map((item: any) => next(item, props));\n      return items.join('');\n    }\n\n    return next(node, props);\n  },\n};\n\nexport const intlayerToICUFormatter = (\n  message: Dictionary['content']\n): JsonValue => {\n  return deepTransformNode(message, {\n    dictionaryKey: 'icu',\n    keyPath: [],\n    plugins: [{ id: 'icu', ...intlayerToIcuPlugin }],\n  });\n};\n\nexport const icuToIntlayerFormatter = (\n  message: Dictionary['content']\n): JsonValue => {\n  return deepTransformNode(message, {\n    dictionaryKey: 'icu',\n    keyPath: [],\n    plugins: [{ id: 'icu', ...icuToIntlayerPlugin }],\n  });\n};\n"],"mappings":"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"}