@intlayer/core 8.2.2 → 8.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/cjs/deepTransformPlugins/getMissingLocalesContent.cjs +1 -1
  2. package/dist/cjs/deepTransformPlugins/getMissingLocalesContent.cjs.map +1 -1
  3. package/dist/cjs/dictionaryManipulator/mergeDictionaries.cjs +1 -1
  4. package/dist/cjs/dictionaryManipulator/mergeDictionaries.cjs.map +1 -1
  5. package/dist/cjs/interpreter/getIntlayer.cjs +1 -1
  6. package/dist/cjs/interpreter/getIntlayer.cjs.map +1 -1
  7. package/dist/cjs/localization/getBrowserLocale.cjs.map +1 -1
  8. package/dist/cjs/localization/getLocalizedUrl.cjs +1 -1
  9. package/dist/cjs/localization/getLocalizedUrl.cjs.map +1 -1
  10. package/dist/cjs/localization/localeDetector.cjs.map +1 -1
  11. package/dist/cjs/markdown/compiler.cjs +2 -2
  12. package/dist/cjs/markdown/compiler.cjs.map +1 -1
  13. package/dist/cjs/markdown/constants.cjs.map +1 -1
  14. package/dist/cjs/markdown/parser.cjs +1 -1
  15. package/dist/cjs/markdown/parser.cjs.map +1 -1
  16. package/dist/cjs/markdown/renderer.cjs +1 -1
  17. package/dist/cjs/markdown/renderer.cjs.map +1 -1
  18. package/dist/cjs/markdown/utils.cjs +5 -5
  19. package/dist/cjs/markdown/utils.cjs.map +1 -1
  20. package/dist/cjs/transpiler/file/file.cjs +1 -1
  21. package/dist/esm/deepTransformPlugins/getMissingLocalesContent.mjs +1 -1
  22. package/dist/esm/deepTransformPlugins/getMissingLocalesContent.mjs.map +1 -1
  23. package/dist/esm/dictionaryManipulator/mergeDictionaries.mjs +1 -1
  24. package/dist/esm/dictionaryManipulator/mergeDictionaries.mjs.map +1 -1
  25. package/dist/esm/interpreter/getIntlayer.mjs +1 -1
  26. package/dist/esm/interpreter/getIntlayer.mjs.map +1 -1
  27. package/dist/esm/localization/getBrowserLocale.mjs.map +1 -1
  28. package/dist/esm/localization/getLocalizedUrl.mjs +1 -1
  29. package/dist/esm/localization/getLocalizedUrl.mjs.map +1 -1
  30. package/dist/esm/localization/localeDetector.mjs.map +1 -1
  31. package/dist/esm/markdown/compiler.mjs +6 -6
  32. package/dist/esm/markdown/compiler.mjs.map +1 -1
  33. package/dist/esm/markdown/constants.mjs.map +1 -1
  34. package/dist/esm/markdown/parser.mjs +1 -1
  35. package/dist/esm/markdown/parser.mjs.map +1 -1
  36. package/dist/esm/markdown/renderer.mjs +1 -1
  37. package/dist/esm/markdown/renderer.mjs.map +1 -1
  38. package/dist/esm/markdown/utils.mjs +6 -6
  39. package/dist/esm/markdown/utils.mjs.map +1 -1
  40. package/dist/esm/transpiler/file/file.mjs +1 -1
  41. package/dist/esm/transpiler/file/fileBrowser.mjs +1 -1
  42. package/dist/esm/transpiler/file/fileBrowser.mjs.map +1 -1
  43. package/dist/types/deepTransformPlugins/getMissingLocalesContent.d.ts.map +1 -1
  44. package/dist/types/interpreter/getIntlayer.d.ts.map +1 -1
  45. package/dist/types/localization/getLocalizedUrl.d.ts +1 -1
  46. package/dist/types/localization/getLocalizedUrl.d.ts.map +1 -1
  47. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","names":["UNESCAPE_R","CR_NEWLINE_R","FORMFEED_R","TAB_R","DURATION_DELAY_TRIGGER","HTML_CUSTOM_ATTR_R","CAPTURE_LETTER_AFTER_HYPHEN","ATTRIBUTES_TO_SANITIZE","INTERPOLATION_R","TABLE_RIGHT_ALIGN","TABLE_CENTER_ALIGN","TABLE_LEFT_ALIGN","TABLE_TRIM_PIPES"],"sources":["../../../src/markdown/utils.ts"],"sourcesContent":["import {\n ATTRIBUTES_TO_SANITIZE,\n CAPTURE_LETTER_AFTER_HYPHEN,\n CR_NEWLINE_R,\n DURATION_DELAY_TRIGGER,\n FORMFEED_R,\n HTML_CUSTOM_ATTR_R,\n INTERPOLATION_R,\n TAB_R,\n TABLE_CENTER_ALIGN,\n TABLE_LEFT_ALIGN,\n TABLE_RIGHT_ALIGN,\n TABLE_TRIM_PIPES,\n UNESCAPE_R,\n} from './constants';\nimport type { NestedParser, ParserResult, ParseState, Rule } from './types';\n\n// ============================================================================\n// STRING UTILITIES\n// ============================================================================\n\n/**\n * Trim trailing whitespace from a string.\n */\nexport const trimEnd = (str: string): string => {\n let end = str.length;\n\n while (end > 0 && str[end - 1] <= ' ') end--;\n\n return str.slice(0, end);\n};\n\n/**\n * Check if string starts with prefix.\n */\nexport const startsWith = (str: string, prefix: string): boolean => {\n return str.startsWith(prefix);\n};\n\n/**\n * Remove symmetrical leading and trailing quotes.\n */\nexport const unquote = (str: string): string => {\n const first = str[0];\n\n if (\n (first === '\"' || first === \"'\") &&\n str.length >= 2 &&\n str[str.length - 1] === first\n ) {\n return str.slice(1, -1);\n }\n\n return str;\n};\n\n/**\n * Unescape backslash-escaped characters.\n */\nexport const unescapeString = (rawString: string): string =>\n rawString ? rawString.replace(UNESCAPE_R, '$1') : rawString;\n\n/**\n * Join class names, filtering out falsy values.\n */\nexport const cx = (...args: any[]): string => args.filter(Boolean).join(' ');\n\n/**\n * Get a nested property from an object using dot notation.\n */\nexport const get = (src: any, path: string, fb?: any): any => {\n let ptr = src;\n const frags = path.split('.');\n\n while (frags.length) {\n ptr = ptr[frags[0]];\n\n if (ptr === undefined) break;\n else frags.shift();\n }\n\n return ptr ?? fb;\n};\n\n// ============================================================================\n// SLUGIFY\n// ============================================================================\n\n/**\n * Convert a string to a URL-safe slug.\n * Based on https://stackoverflow.com/a/18123682/1141611\n */\nexport const slugify = (str: string): string =>\n str\n .replace(/[ÀÁÂÃÄÅàáâãä忯]/g, 'a')\n .replace(/[çÇ]/g, 'c')\n .replace(/[ðÐ]/g, 'd')\n .replace(/[ÈÉÊËéèêë]/g, 'e')\n .replace(/[ÏïÎîÍíÌì]/g, 'i')\n .replace(/[Ññ]/g, 'n')\n .replace(/[øØœŒÕõÔôÓóÒò]/g, 'o')\n .replace(/[ÜüÛûÚúÙù]/g, 'u')\n .replace(/[ŸÿÝý]/g, 'y')\n .replace(/[^a-z0-9- ]/gi, '')\n .replace(/ /gi, '-')\n .toLowerCase();\n\n// ============================================================================\n// SANITIZER\n// ============================================================================\n\nconst SANITIZE_R = /(javascript|vbscript|data(?!:image)):/i;\n\n/**\n * Sanitize URLs to prevent XSS attacks.\n * Returns null if the URL is unsafe.\n */\nexport const sanitizer = (input: string): string | null => {\n try {\n const decoded = decodeURIComponent(input).replace(/[^A-Za-z0-9/:]/g, '');\n\n if (SANITIZE_R.test(decoded)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n decoded\n );\n }\n\n return null;\n }\n } catch (_e) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input could not be decoded due to malformed syntax or characters, it will not be rendered.',\n input\n );\n }\n\n // decodeURIComponent sometimes throws a URIError\n return null;\n }\n\n return input;\n};\n\n// ============================================================================\n// WHITESPACE NORMALIZATION\n// ============================================================================\n\n/**\n * Normalize whitespace in source string.\n */\nexport const normalizeWhitespace = (source: string): string => {\n const start = performance.now();\n const result = source\n .replace(CR_NEWLINE_R, '\\n')\n .replace(FORMFEED_R, '')\n .replace(TAB_R, ' ');\n\n const duration = performance.now() - start;\n\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `normalizeWhitespace: ${duration.toFixed(3)}ms, source length: ${source.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Safely remove a uniform leading indentation from lines, but do NOT touch\n * the content inside fenced code blocks (``` or ~~~).\n */\nexport const trimLeadingWhitespaceOutsideFences = (\n text: string,\n whitespace: string\n): string => {\n const start = performance.now();\n if (!whitespace) return text;\n\n const lines = text.split('\\n');\n let inFence = false;\n let fenceToken: string | null = null;\n\n const isFenceLine = (line: string): RegExpMatchArray | null =>\n line.match(/^\\s*(`{3,}|~{3,})/);\n\n const maybeToggleFence = (line: string): void => {\n const m = isFenceLine(line);\n\n if (!m) return;\n\n const token = m[1];\n\n if (!inFence) {\n inFence = true;\n fenceToken = token;\n } else if (fenceToken && line.includes(fenceToken)) {\n inFence = false;\n fenceToken = null;\n }\n };\n\n const out = lines.map((line) => {\n const fenceMatch = isFenceLine(line);\n if (fenceMatch) {\n const trimmedFenceLine = line.startsWith(whitespace)\n ? line.slice(whitespace.length)\n : line;\n maybeToggleFence(line);\n return trimmedFenceLine;\n }\n\n if (inFence) {\n return line;\n }\n\n return line.startsWith(whitespace) ? line.slice(whitespace.length) : line;\n });\n\n const result = out.join('\\n');\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `trimLeadingWhitespaceOutsideFences: ${duration.toFixed(3)}ms, text length: ${text.length}, lines count: ${lines.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Normalize HTML attribute key to JSX prop name.\n */\nexport const normalizeAttributeKey = (key: string): string => {\n const hyphenIndex = key.indexOf('-');\n\n if (hyphenIndex !== -1 && key.match(HTML_CUSTOM_ATTR_R) === null) {\n key = key.replace(CAPTURE_LETTER_AFTER_HYPHEN, (_, letter) => {\n return letter.toUpperCase();\n });\n }\n\n return key;\n};\n\ntype StyleTuple = [key: string, value: string];\n\n/**\n * Parse a CSS style string into an array of [key, value] tuples.\n */\nexport const parseStyleAttribute = (styleString: string): StyleTuple[] => {\n const start = performance.now();\n const styles: StyleTuple[] = [];\n let buffer = '';\n let inUrl = false;\n let inQuotes = false;\n let quoteChar: '\"' | \"'\" | '' = '';\n\n if (!styleString) return styles;\n\n for (let i = 0; i < styleString.length; i++) {\n const char = styleString[i];\n\n if ((char === '\"' || char === \"'\") && !inUrl) {\n if (!inQuotes) {\n inQuotes = true;\n quoteChar = char;\n } else if (char === quoteChar) {\n inQuotes = false;\n quoteChar = '';\n }\n }\n\n if (char === '(' && buffer.endsWith('url')) {\n inUrl = true;\n } else if (char === ')' && inUrl) {\n inUrl = false;\n }\n\n if (char === ';' && !inQuotes && !inUrl) {\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n buffer = '';\n } else {\n buffer += char;\n }\n }\n\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n\n const duration = performance.now() - start;\n\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseStyleAttribute: ${duration.toFixed(3)}ms, styleString length: ${styleString.length}, styles count: ${styles.length}`\n );\n }\n\n return styles;\n};\n\n/**\n * Convert an attribute value to a Node prop value.\n */\nexport const attributeValueToNodePropValue = (\n tag: string,\n key: string,\n value: string,\n sanitizeUrlFn: (\n value: string,\n tag: string,\n attribute: string\n ) => string | null\n): any => {\n if (key === 'style') {\n return parseStyleAttribute(value).reduce(\n (styles, [styleKey, styleValue]) => {\n const camelCasedKey = styleKey.replace(/(-[a-z])/g, (substr) =>\n substr[1].toUpperCase()\n );\n\n (styles as Record<string, any>)[camelCasedKey] = sanitizeUrlFn(\n styleValue,\n tag,\n styleKey\n );\n\n return styles;\n },\n {} as Record<string, any>\n );\n } else if (ATTRIBUTES_TO_SANITIZE.indexOf(key) !== -1) {\n return sanitizeUrlFn(unescapeString(value), tag, key);\n } else if (value.match(INTERPOLATION_R)) {\n value = unescapeString(value.slice(1, value.length - 1));\n }\n\n if (value === 'true') {\n return true;\n } else if (value === 'false') {\n return false;\n }\n\n return value;\n};\n\n// ============================================================================\n// TABLE PARSING\n// ============================================================================\n\n/**\n * Parse table alignment from a separator row.\n */\nexport const parseTableAlignCapture = (\n alignCapture: string\n): 'left' | 'right' | 'center' => {\n if (TABLE_RIGHT_ALIGN.test(alignCapture)) {\n return 'right';\n } else if (TABLE_CENTER_ALIGN.test(alignCapture)) {\n return 'center';\n } else if (TABLE_LEFT_ALIGN.test(alignCapture)) {\n return 'left';\n }\n\n return 'left';\n};\n\n/**\n * Parse table alignment row.\n */\nexport const parseTableAlign = (\n source: string\n): ('left' | 'right' | 'center')[] => {\n const alignText = source.replace(TABLE_TRIM_PIPES, '').split('|');\n return alignText.map(parseTableAlignCapture);\n};\n\n/**\n * Parse a single table row.\n */\nexport const parseTableRow = (\n source: string,\n parse: NestedParser,\n state: ParseState,\n tableOutput: boolean\n): ParserResult[][] => {\n const start = performance.now();\n const prevInTable = state.inTable;\n\n state.inTable = true;\n\n const cells: ParserResult[][] = [[]];\n let acc = '';\n\n const flush = (): void => {\n if (!acc) return;\n\n const cell = cells[cells.length - 1];\n cell.push.apply(cell, parse(acc, state));\n acc = '';\n };\n\n source\n .trim()\n .split(/(`[^`]*`|\\\\\\||\\|)/)\n .filter(Boolean)\n .forEach((fragment, i, arr) => {\n if (fragment.trim() === '|') {\n flush();\n\n if (tableOutput) {\n if (i !== 0 && i !== arr.length - 1) {\n cells.push([]);\n }\n\n return;\n }\n }\n\n acc += fragment;\n });\n\n flush();\n\n state.inTable = prevInTable;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseTableRow: ${duration.toFixed(3)}ms, source length: ${source.length}, cells count: ${cells.length}`\n );\n }\n\n return cells;\n};\n\n/**\n * Parse table cells (multiple rows).\n */\nexport const parseTableCells = (\n source: string,\n parse: NestedParser,\n state: ParseState\n): ParserResult[][][] => {\n const start = performance.now();\n const rowsText = source.trim().split('\\n');\n\n const result = rowsText.map((rowText) =>\n parseTableRow(rowText, parse, state, true)\n );\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseTableCells: ${duration.toFixed(3)}ms, source length: ${source.length}, rows count: ${rowsText.length}`\n );\n }\n\n return result;\n};\n\n// ============================================================================\n// PARSING HELPERS\n// ============================================================================\n\n/**\n * Check if a rule qualifies for the current source and state.\n */\nexport const qualifies = (\n source: string,\n state: ParseState,\n qualify: NonNullable<Rule<any>['_qualify']>\n): boolean => {\n if (Array.isArray(qualify)) {\n for (let i = 0; i < qualify.length; i++) {\n if (startsWith(source, qualify[i])) return true;\n }\n\n return false;\n }\n\n return (qualify as (source: string, state: ParseState) => boolean)(\n source,\n state\n );\n};\n\n/**\n * Marks a matcher function as eligible for being run inside an inline context.\n */\nexport const allowInline = <T extends (...args: any[]) => any>(\n fn: T\n): T & { inline: 1 } => {\n (fn as any).inline = 1;\n return fn as T & { inline: 1 };\n};\n\n/**\n * Creates a match function for an inline scoped element from a regex.\n */\nexport const inlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for inline elements except links.\n */\nexport const simpleInlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for a block scoped element from a regex.\n */\nexport const blockRegex =\n (regex: RegExp) =>\n (source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return null;\n } else {\n return regex.exec(source);\n }\n };\n\n/**\n * Creates a match function from a regex, ignoring block/inline scope.\n */\nexport const anyScopeRegex = (\n fn: RegExp | ((source: string, state: ParseState) => RegExpMatchArray | null)\n) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (typeof fn === 'function') {\n return fn(source, state);\n }\n return fn.exec(source);\n });\n\n/**\n * Parse inline content (including links).\n */\nexport const parseInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n state.inline = true;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Parse simple inline content (no links).\n */\nexport const parseSimpleInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n\n state.inline = false;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseSimpleInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Parse block content.\n */\nexport const parseBlock = (\n parse: NestedParser,\n children: string,\n state: ParseState = {}\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline || false;\n state.inline = false;\n const normalizedChildren = trimEnd(children);\n const needsTerminator = /\\n\\n$/.test(normalizedChildren) === false;\n const blockInput = needsTerminator\n ? normalizedChildren.endsWith('\\n')\n ? `${normalizedChildren}\\n`\n : `${normalizedChildren}\\n\\n`\n : normalizedChildren;\n\n const result = parse(blockInput, state);\n state.inline = isCurrentlyInline;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseBlock: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Helper to parse capture group 2 as inline content.\n */\nexport const parseCaptureInline = (\n capture: RegExpMatchArray,\n parse: NestedParser,\n state: ParseState\n): { children: ParserResult[] } => {\n return {\n children: parseInline(parse, capture[2], state),\n };\n};\n\n/**\n * Helper that captures nothing (empty object).\n */\nexport const captureNothing = (): Record<string, never> => ({});\n\n/**\n * Helper that renders nothing (null).\n */\nexport const renderNothing = (): null => null;\n\n/**\n * Check if any regex in a list matches the input.\n */\nexport const some = (regexes: RegExp[], input: string): boolean => {\n for (let i = 0; i < regexes.length; i++) {\n if (regexes[i].test(input)) {\n return true;\n }\n }\n return false;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","names":["UNESCAPE_R","CR_NEWLINE_R","FORMFEED_R","TAB_R","HTML_CUSTOM_ATTR_R","CAPTURE_LETTER_AFTER_HYPHEN","ATTRIBUTES_TO_SANITIZE","INTERPOLATION_R","TABLE_RIGHT_ALIGN","TABLE_CENTER_ALIGN","TABLE_LEFT_ALIGN","TABLE_TRIM_PIPES"],"sources":["../../../src/markdown/utils.ts"],"sourcesContent":["import {\n ATTRIBUTES_TO_SANITIZE,\n CAPTURE_LETTER_AFTER_HYPHEN,\n CR_NEWLINE_R,\n DURATION_DELAY_TRIGGER,\n FORMFEED_R,\n HTML_CUSTOM_ATTR_R,\n INTERPOLATION_R,\n TAB_R,\n TABLE_CENTER_ALIGN,\n TABLE_LEFT_ALIGN,\n TABLE_RIGHT_ALIGN,\n TABLE_TRIM_PIPES,\n UNESCAPE_R,\n} from './constants';\nimport type { NestedParser, ParserResult, ParseState, Rule } from './types';\n\n// ============================================================================\n// STRING UTILITIES\n// ============================================================================\n\n/**\n * Trim trailing whitespace from a string.\n */\nexport const trimEnd = (str: string): string => {\n let end = str.length;\n\n while (end > 0 && str[end - 1] <= ' ') end--;\n\n return str.slice(0, end);\n};\n\n/**\n * Check if string starts with prefix.\n */\nexport const startsWith = (str: string, prefix: string): boolean => {\n return str.startsWith(prefix);\n};\n\n/**\n * Remove symmetrical leading and trailing quotes.\n */\nexport const unquote = (str: string): string => {\n const first = str[0];\n\n if (\n (first === '\"' || first === \"'\") &&\n str.length >= 2 &&\n str[str.length - 1] === first\n ) {\n return str.slice(1, -1);\n }\n\n return str;\n};\n\n/**\n * Unescape backslash-escaped characters.\n */\nexport const unescapeString = (rawString: string): string =>\n rawString ? rawString.replace(UNESCAPE_R, '$1') : rawString;\n\n/**\n * Join class names, filtering out falsy values.\n */\nexport const cx = (...args: any[]): string => args.filter(Boolean).join(' ');\n\n/**\n * Get a nested property from an object using dot notation.\n */\nexport const get = (src: any, path: string, fb?: any): any => {\n let ptr = src;\n const frags = path.split('.');\n\n while (frags.length) {\n ptr = ptr[frags[0]];\n\n if (ptr === undefined) break;\n else frags.shift();\n }\n\n return ptr ?? fb;\n};\n\n// ============================================================================\n// SLUGIFY\n// ============================================================================\n\n/**\n * Convert a string to a URL-safe slug.\n * Based on https://stackoverflow.com/a/18123682/1141611\n */\nexport const slugify = (str: string): string =>\n str\n .replace(/[ÀÁÂÃÄÅàáâãä忯]/g, 'a')\n .replace(/[çÇ]/g, 'c')\n .replace(/[ðÐ]/g, 'd')\n .replace(/[ÈÉÊËéèêë]/g, 'e')\n .replace(/[ÏïÎîÍíÌì]/g, 'i')\n .replace(/[Ññ]/g, 'n')\n .replace(/[øØœŒÕõÔôÓóÒò]/g, 'o')\n .replace(/[ÜüÛûÚúÙù]/g, 'u')\n .replace(/[ŸÿÝý]/g, 'y')\n .replace(/[^a-z0-9- ]/gi, '')\n .replace(/ /gi, '-')\n .toLowerCase();\n\n// ============================================================================\n// SANITIZER\n// ============================================================================\n\nconst SANITIZE_R = /(javascript|vbscript|data(?!:image)):/i;\n\n/**\n * Sanitize URLs to prevent XSS attacks.\n * Returns null if the URL is unsafe.\n */\nexport const sanitizer = (input: string): string | null => {\n try {\n const decoded = decodeURIComponent(input).replace(/[^A-Za-z0-9/:]/g, '');\n\n if (SANITIZE_R.test(decoded)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n decoded\n );\n }\n\n return null;\n }\n } catch (_e) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input could not be decoded due to malformed syntax or characters, it will not be rendered.',\n input\n );\n }\n\n // decodeURIComponent sometimes throws a URIError\n return null;\n }\n\n return input;\n};\n\n// ============================================================================\n// WHITESPACE NORMALIZATION\n// ============================================================================\n\n/**\n * Normalize whitespace in source string.\n */\nexport const normalizeWhitespace = (source: string): string => {\n const start = performance.now();\n const result = source\n .replace(CR_NEWLINE_R, '\\n')\n .replace(FORMFEED_R, '')\n .replace(TAB_R, ' ');\n\n const duration = performance.now() - start;\n\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `normalizeWhitespace: ${duration.toFixed(3)}ms, source length: ${source.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Safely remove a uniform leading indentation from lines, but do NOT touch\n * the content inside fenced code blocks (``` or ~~~).\n */\nexport const trimLeadingWhitespaceOutsideFences = (\n text: string,\n whitespace: string\n): string => {\n const start = performance.now();\n if (!whitespace) return text;\n\n const lines = text.split('\\n');\n let inFence = false;\n let fenceToken: string | null = null;\n\n const isFenceLine = (line: string): RegExpMatchArray | null =>\n line.match(/^\\s*(`{3,}|~{3,})/);\n\n const maybeToggleFence = (line: string): void => {\n const m = isFenceLine(line);\n\n if (!m) return;\n\n const token = m[1];\n\n if (!inFence) {\n inFence = true;\n fenceToken = token;\n } else if (fenceToken && line.includes(fenceToken)) {\n inFence = false;\n fenceToken = null;\n }\n };\n\n const out = lines.map((line) => {\n const fenceMatch = isFenceLine(line);\n if (fenceMatch) {\n const trimmedFenceLine = line.startsWith(whitespace)\n ? line.slice(whitespace.length)\n : line;\n maybeToggleFence(line);\n return trimmedFenceLine;\n }\n\n if (inFence) {\n return line;\n }\n\n return line.startsWith(whitespace) ? line.slice(whitespace.length) : line;\n });\n\n const result = out.join('\\n');\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `trimLeadingWhitespaceOutsideFences: ${duration.toFixed(3)}ms, text length: ${text.length}, lines count: ${lines.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Normalize HTML attribute key to JSX prop name.\n */\nexport const normalizeAttributeKey = (key: string): string => {\n const hyphenIndex = key.indexOf('-');\n\n if (hyphenIndex !== -1 && key.match(HTML_CUSTOM_ATTR_R) === null) {\n key = key.replace(CAPTURE_LETTER_AFTER_HYPHEN, (_, letter) => {\n return letter.toUpperCase();\n });\n }\n\n return key;\n};\n\ntype StyleTuple = [key: string, value: string];\n\n/**\n * Parse a CSS style string into an array of [key, value] tuples.\n */\nexport const parseStyleAttribute = (styleString: string): StyleTuple[] => {\n const start = performance.now();\n const styles: StyleTuple[] = [];\n let buffer = '';\n let inUrl = false;\n let inQuotes = false;\n let quoteChar: '\"' | \"'\" | '' = '';\n\n if (!styleString) return styles;\n\n for (let i = 0; i < styleString.length; i++) {\n const char = styleString[i];\n\n if ((char === '\"' || char === \"'\") && !inUrl) {\n if (!inQuotes) {\n inQuotes = true;\n quoteChar = char;\n } else if (char === quoteChar) {\n inQuotes = false;\n quoteChar = '';\n }\n }\n\n if (char === '(' && buffer.endsWith('url')) {\n inUrl = true;\n } else if (char === ')' && inUrl) {\n inUrl = false;\n }\n\n if (char === ';' && !inQuotes && !inUrl) {\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n buffer = '';\n } else {\n buffer += char;\n }\n }\n\n const declaration = buffer.trim();\n\n if (declaration) {\n const colonIndex = declaration.indexOf(':');\n if (colonIndex > 0) {\n const key = declaration.slice(0, colonIndex).trim();\n const value = declaration.slice(colonIndex + 1).trim();\n styles.push([key, value]);\n }\n }\n\n const duration = performance.now() - start;\n\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseStyleAttribute: ${duration.toFixed(3)}ms, styleString length: ${styleString.length}, styles count: ${styles.length}`\n );\n }\n\n return styles;\n};\n\n/**\n * Convert an attribute value to a Node prop value.\n */\nexport const attributeValueToNodePropValue = (\n tag: string,\n key: string,\n value: string,\n sanitizeUrlFn: (\n value: string,\n tag: string,\n attribute: string\n ) => string | null\n): any => {\n if (key === 'style') {\n return parseStyleAttribute(value).reduce(\n (styles, [styleKey, styleValue]) => {\n const camelCasedKey = styleKey.replace(/(-[a-z])/g, (substr) =>\n substr[1].toUpperCase()\n );\n\n (styles as Record<string, any>)[camelCasedKey] = sanitizeUrlFn(\n styleValue,\n tag,\n styleKey\n );\n\n return styles;\n },\n {} as Record<string, any>\n );\n } else if (ATTRIBUTES_TO_SANITIZE.indexOf(key) !== -1) {\n return sanitizeUrlFn(unescapeString(value), tag, key);\n } else if (value.match(INTERPOLATION_R)) {\n value = unescapeString(value.slice(1, value.length - 1));\n }\n\n if (value === 'true') {\n return true;\n } else if (value === 'false') {\n return false;\n }\n\n return value;\n};\n\n// ============================================================================\n// TABLE PARSING\n// ============================================================================\n\n/**\n * Parse table alignment from a separator row.\n */\nexport const parseTableAlignCapture = (\n alignCapture: string\n): 'left' | 'right' | 'center' => {\n if (TABLE_RIGHT_ALIGN.test(alignCapture)) {\n return 'right';\n } else if (TABLE_CENTER_ALIGN.test(alignCapture)) {\n return 'center';\n } else if (TABLE_LEFT_ALIGN.test(alignCapture)) {\n return 'left';\n }\n\n return 'left';\n};\n\n/**\n * Parse table alignment row.\n */\nexport const parseTableAlign = (\n source: string\n): ('left' | 'right' | 'center')[] => {\n const alignText = source.replace(TABLE_TRIM_PIPES, '').split('|');\n return alignText.map(parseTableAlignCapture);\n};\n\n/**\n * Parse a single table row.\n */\nexport const parseTableRow = (\n source: string,\n parse: NestedParser,\n state: ParseState,\n tableOutput: boolean\n): ParserResult[][] => {\n const start = performance.now();\n const prevInTable = state.inTable;\n\n state.inTable = true;\n\n const cells: ParserResult[][] = [[]];\n let acc = '';\n\n const flush = (): void => {\n if (!acc) return;\n\n const cell = cells[cells.length - 1];\n cell.push.apply(cell, parse(acc, state));\n acc = '';\n };\n\n source\n .trim()\n .split(/(`[^`]*`|\\\\\\||\\|)/)\n .filter(Boolean)\n .forEach((fragment, i, arr) => {\n if (fragment.trim() === '|') {\n flush();\n\n if (tableOutput) {\n if (i !== 0 && i !== arr.length - 1) {\n cells.push([]);\n }\n\n return;\n }\n }\n\n acc += fragment;\n });\n\n flush();\n\n state.inTable = prevInTable;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseTableRow: ${duration.toFixed(3)}ms, source length: ${source.length}, cells count: ${cells.length}`\n );\n }\n\n return cells;\n};\n\n/**\n * Parse table cells (multiple rows).\n */\nexport const parseTableCells = (\n source: string,\n parse: NestedParser,\n state: ParseState\n): ParserResult[][][] => {\n const start = performance.now();\n const rowsText = source.trim().split('\\n');\n\n const result = rowsText.map((rowText) =>\n parseTableRow(rowText, parse, state, true)\n );\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseTableCells: ${duration.toFixed(3)}ms, source length: ${source.length}, rows count: ${rowsText.length}`\n );\n }\n\n return result;\n};\n\n// ============================================================================\n// PARSING HELPERS\n// ============================================================================\n\n/**\n * Check if a rule qualifies for the current source and state.\n */\nexport const qualifies = (\n source: string,\n state: ParseState,\n qualify: NonNullable<Rule<any>['_qualify']>\n): boolean => {\n if (Array.isArray(qualify)) {\n for (let i = 0; i < qualify.length; i++) {\n if (startsWith(source, qualify[i])) return true;\n }\n\n return false;\n }\n\n return (qualify as (source: string, state: ParseState) => boolean)(\n source,\n state\n );\n};\n\n/**\n * Marks a matcher function as eligible for being run inside an inline context.\n */\nexport const allowInline = <T extends (...args: any[]) => any>(\n fn: T\n): T & { inline: 1 } => {\n (fn as any).inline = 1;\n return fn as T & { inline: 1 };\n};\n\n/**\n * Creates a match function for an inline scoped element from a regex.\n */\nexport const inlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for inline elements except links.\n */\nexport const simpleInlineRegex = (regex: RegExp) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return regex.exec(source);\n } else {\n return null;\n }\n });\n\n/**\n * Creates a match function for a block scoped element from a regex.\n */\nexport const blockRegex =\n (regex: RegExp) =>\n (source: string, state: ParseState): RegExpMatchArray | null => {\n if (state.inline || state.simple) {\n return null;\n } else {\n return regex.exec(source);\n }\n };\n\n/**\n * Creates a match function from a regex, ignoring block/inline scope.\n */\nexport const anyScopeRegex = (\n fn: RegExp | ((source: string, state: ParseState) => RegExpMatchArray | null)\n) =>\n allowInline((source: string, state: ParseState): RegExpMatchArray | null => {\n if (typeof fn === 'function') {\n return fn(source, state);\n }\n return fn.exec(source);\n });\n\n/**\n * Parse inline content (including links).\n */\nexport const parseInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n state.inline = true;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Parse simple inline content (no links).\n */\nexport const parseSimpleInline = (\n parse: NestedParser,\n children: string,\n state: ParseState\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline ?? false;\n const isCurrentlySimple = state.simple ?? false;\n\n state.inline = false;\n state.simple = true;\n const result = parse(children, state);\n state.inline = isCurrentlyInline;\n state.simple = isCurrentlySimple;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseSimpleInline: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Parse block content.\n */\nexport const parseBlock = (\n parse: NestedParser,\n children: string,\n state: ParseState = {}\n): ParserResult[] => {\n const start = performance.now();\n const isCurrentlyInline = state.inline || false;\n state.inline = false;\n const normalizedChildren = trimEnd(children);\n const needsTerminator = /\\n\\n$/.test(normalizedChildren) === false;\n const blockInput = needsTerminator\n ? normalizedChildren.endsWith('\\n')\n ? `${normalizedChildren}\\n`\n : `${normalizedChildren}\\n\\n`\n : normalizedChildren;\n\n const result = parse(blockInput, state);\n state.inline = isCurrentlyInline;\n\n const duration = performance.now() - start;\n if (duration > DURATION_DELAY_TRIGGER) {\n console.log(\n `parseBlock: ${duration.toFixed(3)}ms, children length: ${children.length}, result count: ${result.length}`\n );\n }\n\n return result;\n};\n\n/**\n * Helper to parse capture group 2 as inline content.\n */\nexport const parseCaptureInline = (\n capture: RegExpMatchArray,\n parse: NestedParser,\n state: ParseState\n): { children: ParserResult[] } => {\n return {\n children: parseInline(parse, capture[2], state),\n };\n};\n\n/**\n * Helper that captures nothing (empty object).\n */\nexport const captureNothing = (): Record<string, never> => ({});\n\n/**\n * Helper that renders nothing (null).\n */\nexport const renderNothing = (): null => null;\n\n/**\n * Check if any regex in a list matches the input.\n */\nexport const some = (regexes: RegExp[], input: string): boolean => {\n for (let i = 0; i < regexes.length; i++) {\n if (regexes[i].test(input)) {\n return true;\n }\n }\n return false;\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../../_virtual/_rolldown/runtime.cjs`);let e=require(`@intlayer/types`),t=require(`node:fs`),n=require(`node:path`),r=require(`@intlayer/config/logger`);const i=(i,a,o)=>{let s=i.startsWith(`./`)||i.startsWith(`../`),c=(0,r.getAppLogger)(),l;if((0,n.isAbsolute)(i)?(c(`Using absolute path for file is not recommended. Use relative paths instead. Path: ${i}, imported from: ${a}`,{level:`warn`}),l=i):l=s?(0,n.resolve)(a,i):(0,n.resolve)(o,i),(0,t.existsSync)(l)&&(0,t.statSync)(l).isFile())try{let r=(0,t.readFileSync)(l,`utf8`);return(0,e.formatNodeType)(e.NodeType.File,i,{content:r,fixedPath:(0,n.relative)(o,l)})}catch{c(`Unable to read path: ${(0,r.colorizePath)((0,n.relative)(o,l))}`,{level:`warn`})}else c(`File not found: ${(0,r.colorizePath)((0,n.relative)(o,l))}`,{level:`warn`});return(0,e.formatNodeType)(e.NodeType.File,i,{content:`-`})},a=e=>{let{INTLAYER_FILE_PATH:t,INTLAYER_BASE_DIR:r}=globalThis;return i(e,(0,n.dirname)(t),r)};exports.file=a,exports.fileContent=i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../../_virtual/_rolldown/runtime.cjs`);let e=require(`@intlayer/types`),t=require(`@intlayer/config/logger`),n=require(`node:fs`),r=require(`node:path`);const i=(i,a,o)=>{let s=i.startsWith(`./`)||i.startsWith(`../`),c=(0,t.getAppLogger)(),l;if((0,r.isAbsolute)(i)?(c(`Using absolute path for file is not recommended. Use relative paths instead. Path: ${i}, imported from: ${a}`,{level:`warn`}),l=i):l=s?(0,r.resolve)(a,i):(0,r.resolve)(o,i),(0,n.existsSync)(l)&&(0,n.statSync)(l).isFile())try{let t=(0,n.readFileSync)(l,`utf8`);return(0,e.formatNodeType)(e.NodeType.File,i,{content:t,fixedPath:(0,r.relative)(o,l)})}catch{c(`Unable to read path: ${(0,t.colorizePath)((0,r.relative)(o,l))}`,{level:`warn`})}else c(`File not found: ${(0,t.colorizePath)((0,r.relative)(o,l))}`,{level:`warn`});return(0,e.formatNodeType)(e.NodeType.File,i,{content:`-`})},a=e=>{let{INTLAYER_FILE_PATH:t,INTLAYER_BASE_DIR:n}=globalThis;return i(e,(0,r.dirname)(t),n)};exports.file=a,exports.fileContent=i;
2
2
  //# sourceMappingURL=file.cjs.map
@@ -1,2 +1,2 @@
1
- import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{NodeType as t}from"@intlayer/types";import n from"@intlayer/config/built";const r=(e,t=[])=>typeof e!=`object`||!e||Array.isArray(e)?[]:Object.keys(e).flatMap(n=>{let i=[...t,n];return[i,...r(e[n],i)]}),i=(e,t)=>{let n=e;for(let e of t){if(typeof n!=`object`||!n||!(e in n))return!1;n=n[e]}return!0},a=(e,n)=>({id:`check-missing-locales-plugin`,canHandle:e=>typeof e==`object`&&e?.nodeType===t.Translation,transform:(a,o,s)=>{let c=a[t.Translation],l=new Set;for(let t of e)c[t]&&r(c[t]).forEach(e=>{l.add(JSON.stringify(e))});for(let t of e){if(!c[t]){n(t);continue}for(let e of l){let r=JSON.parse(e);if(!i(c[t],r)){n(t);break}}}for(let e in c){let t=c[e];s(t,{...o,children:t})}return a}}),o=(t,r=n?.internationalization?.locales,i)=>{let o=new Set,s=[a(r,e=>o.add(e)),...i.plugins??[]];return e(t,{...i,plugins:s}),Array.from(o)},s=(e,t=n?.internationalization?.locales)=>o(e.content,t,{dictionaryKey:e.key,keyPath:[]});export{a as checkMissingLocalesPlugin,o as getMissingLocalesContent,s as getMissingLocalesContentFromDictionary};
1
+ import{deepTransformNode as e}from"../interpreter/getContent/deepTransform.mjs";import{NodeType as t}from"@intlayer/types";import n from"@intlayer/config/built";const r=(e,t=[])=>typeof e!=`object`||!e||Array.isArray(e)?[]:Object.keys(e).flatMap(n=>{let i=[...t,n],a=e[n];return a===null?[i]:[i,...r(a,i)]}),i=(e,t=[])=>typeof e!=`object`||!e||Array.isArray(e)?[]:Object.keys(e).flatMap(n=>{let r=[...t,n],a=e[n];return a===null?[]:[r,...i(a,r)]}),a=(e,t)=>{let n=e;for(let e of t){if(typeof n!=`object`||!n||!(e in n))return!1;n=n[e]}return!0},o=(e,t)=>{let n=e;for(let e of t){if(typeof n!=`object`||!n||!(e in n))return!1;n=n[e]}return n!==null},s=(e,n)=>({id:`check-missing-locales-plugin`,canHandle:e=>typeof e==`object`&&e?.nodeType===t.Translation,transform:(s,c,l)=>{let u=s[t.Translation],d=new Set,f=new Set;for(let t of e){let e=u[t];e&&typeof e==`object`&&!Array.isArray(e)&&(r(e).forEach(e=>{d.add(JSON.stringify(e))}),i(e).forEach(e=>{f.add(JSON.stringify(e))}))}let p=e.some(e=>u[e]!==void 0&&u[e]!==null);for(let t of e){let e=u[t];if(e===null){p&&n(t);continue}if(!e){n(t);continue}let r=!1;for(let i of d)if(!a(e,JSON.parse(i))){n(t),r=!0;break}if(!r){for(let r of f)if(!o(e,JSON.parse(r))){n(t);break}}}for(let e in u){let t=u[e];l(t,{...c,children:t})}return s}}),c=(t,r=n?.internationalization?.locales,i)=>{let a=new Set,o=[s(r,e=>a.add(e)),...i.plugins??[]];return e(t,{...i,plugins:o}),Array.from(a)},l=(e,t=n?.internationalization?.locales)=>c(e.content,t,{dictionaryKey:e.key,keyPath:[]});export{s as checkMissingLocalesPlugin,c as getMissingLocalesContent,l as getMissingLocalesContentFromDictionary};
2
2
  //# sourceMappingURL=getMissingLocalesContent.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getMissingLocalesContent.mjs","names":[],"sources":["../../../src/deepTransformPlugins/getMissingLocalesContent.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type { Dictionary } from '@intlayer/types';\nimport {\n type ContentNode,\n type Locale,\n type LocalesValues,\n NodeType,\n} from '@intlayer/types';\nimport type { DeepTransformContent, NodeProps, Plugins } from '../interpreter';\nimport { deepTransformNode } from '../interpreter/getContent/deepTransform';\nimport type { TranslationContent } from '../transpiler';\n\nconst getDeepKeyPaths = (obj: any, prefix: string[] = []): string[][] => {\n if (typeof obj !== 'object' || obj === null) {\n return [];\n }\n\n // Skip array indices - arrays of different lengths shouldn't trigger missing translations\n // Each locale can have arrays with different numbers of elements (e.g., keywords)\n if (Array.isArray(obj)) {\n return [];\n }\n\n return Object.keys(obj).flatMap((key) => {\n const newPath = [...prefix, key];\n return [newPath, ...getDeepKeyPaths(obj[key], newPath)];\n });\n};\n\nconst hasDeepKeyPath = (obj: any, keyPath: string[]): boolean => {\n let current = obj;\n for (const key of keyPath) {\n if (\n current === undefined ||\n current === null ||\n typeof current !== 'object'\n ) {\n return false;\n }\n if (!(key in current)) {\n return false;\n }\n current = current[key];\n }\n\n return true;\n};\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const checkMissingLocalesPlugin = (\n locales: Locale[],\n onMissingLocale: (locale: Locale) => void\n): Plugins => ({\n id: 'check-missing-locales-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Translation,\n transform: (node: TranslationContent, props, deepTransformNode) => {\n const translations = node[NodeType.Translation] as Record<string, any>;\n const allKeys = new Set<string>();\n\n for (const locale of locales) {\n if (translations[locale]) {\n getDeepKeyPaths(translations[locale]).forEach((path) => {\n allKeys.add(JSON.stringify(path));\n });\n }\n }\n\n for (const locale of locales) {\n if (!translations[locale]) {\n onMissingLocale(locale);\n continue;\n }\n\n for (const pathStr of allKeys) {\n const path = JSON.parse(pathStr);\n if (!hasDeepKeyPath(translations[locale], path)) {\n onMissingLocale(locale);\n break;\n }\n }\n }\n\n // Continue traversal inside the translation values, but avoid re-applying this plugin on the same node\n for (const key in translations) {\n const child = translations[key];\n deepTransformNode(child, {\n ...props,\n children: child,\n });\n }\n\n // Return the original node; the return value is ignored by the caller\n return node;\n },\n});\n\n/**\n * Return the content of a node with only the translation plugin.\n *\n * @param node The node to transform.\n * @param locales The locales to check for missing translations.\n */\nexport const getMissingLocalesContent = <T extends ContentNode>(\n node: T,\n locales: LocalesValues[] = configuration?.internationalization?.locales,\n nodeProps: NodeProps\n): Locale[] => {\n const missingLocales = new Set<Locale>();\n\n const plugins: Plugins[] = [\n checkMissingLocalesPlugin(locales as Locale[], (locale) =>\n missingLocales.add(locale)\n ),\n ...(nodeProps.plugins ?? []),\n ];\n\n deepTransformNode(node, {\n ...nodeProps,\n plugins,\n }) as DeepTransformContent<T>;\n\n return Array.from(missingLocales);\n};\n\nexport const getMissingLocalesContentFromDictionary = (\n dictionary: Dictionary,\n locales: LocalesValues[] = configuration?.internationalization?.locales\n) =>\n getMissingLocalesContent(dictionary.content, locales, {\n dictionaryKey: dictionary.key,\n keyPath: [],\n });\n"],"mappings":"iKAYA,MAAM,GAAmB,EAAU,EAAmB,EAAE,GAClD,OAAO,GAAQ,WAAY,GAM3B,MAAM,QAAQ,EAAI,CACb,EAAE,CAGJ,OAAO,KAAK,EAAI,CAAC,QAAS,GAAQ,CACvC,IAAM,EAAU,CAAC,GAAG,EAAQ,EAAI,CAChC,MAAO,CAAC,EAAS,GAAG,EAAgB,EAAI,GAAM,EAAQ,CAAC,EACvD,CAGE,GAAkB,EAAU,IAA+B,CAC/D,IAAI,EAAU,EACd,IAAK,IAAM,KAAO,EAAS,CAQzB,GAJE,OAAO,GAAY,WAFnB,GAME,EAAE,KAAO,GACX,MAAO,GAET,EAAU,EAAQ,GAGpB,MAAO,IAII,GACX,EACA,KACa,CACb,GAAI,+BACJ,UAAY,GACV,OAAO,GAAS,UAAY,GAAM,WAAa,EAAS,YAC1D,WAAY,EAA0B,EAAO,IAAsB,CACjE,IAAM,EAAe,EAAK,EAAS,aAC7B,EAAU,IAAI,IAEpB,IAAK,IAAM,KAAU,EACf,EAAa,IACf,EAAgB,EAAa,GAAQ,CAAC,QAAS,GAAS,CACtD,EAAQ,IAAI,KAAK,UAAU,EAAK,CAAC,EACjC,CAIN,IAAK,IAAM,KAAU,EAAS,CAC5B,GAAI,CAAC,EAAa,GAAS,CACzB,EAAgB,EAAO,CACvB,SAGF,IAAK,IAAM,KAAW,EAAS,CAC7B,IAAM,EAAO,KAAK,MAAM,EAAQ,CAChC,GAAI,CAAC,EAAe,EAAa,GAAS,EAAK,CAAE,CAC/C,EAAgB,EAAO,CACvB,QAMN,IAAK,IAAM,KAAO,EAAc,CAC9B,IAAM,EAAQ,EAAa,GAC3B,EAAkB,EAAO,CACvB,GAAG,EACH,SAAU,EACX,CAAC,CAIJ,OAAO,GAEV,EAQY,GACX,EACA,EAA2B,GAAe,sBAAsB,QAChE,IACa,CACb,IAAM,EAAiB,IAAI,IAErB,EAAqB,CACzB,EAA0B,EAAsB,GAC9C,EAAe,IAAI,EAAO,CAC3B,CACD,GAAI,EAAU,SAAW,EAAE,CAC5B,CAOD,OALA,EAAkB,EAAM,CACtB,GAAG,EACH,UACD,CAAC,CAEK,MAAM,KAAK,EAAe,EAGtB,GACX,EACA,EAA2B,GAAe,sBAAsB,UAEhE,EAAyB,EAAW,QAAS,EAAS,CACpD,cAAe,EAAW,IAC1B,QAAS,EAAE,CACZ,CAAC"}
1
+ {"version":3,"file":"getMissingLocalesContent.mjs","names":[],"sources":["../../../src/deepTransformPlugins/getMissingLocalesContent.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type { Dictionary } from '@intlayer/types';\nimport {\n type ContentNode,\n type Locale,\n type LocalesValues,\n NodeType,\n} from '@intlayer/types';\nimport type { DeepTransformContent, NodeProps, Plugins } from '../interpreter';\nimport { deepTransformNode } from '../interpreter/getContent/deepTransform';\nimport type { TranslationContent } from '../transpiler';\n\n/**\n * Returns all key paths present in obj, INCLUDING those whose leaf value is null.\n * Used for structural presence checks (a locale must have every key another locale has,\n * even if the value is a null placeholder).\n */\nconst getAllKeyPaths = (obj: any, prefix: string[] = []): string[][] => {\n if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {\n return [];\n }\n\n return Object.keys(obj).flatMap((key) => {\n const newPath = [...prefix, key];\n const value = obj[key];\n // Stop recursing into null include the path but don't descend further\n if (value === null) {\n return [newPath];\n }\n return [newPath, ...getAllKeyPaths(value, newPath)];\n });\n};\n\n/**\n * Returns key paths whose leaf value is non-null.\n * Used for translation value checks (a locale must not have null where another locale\n * already has a real translated value).\n */\nconst getNonNullKeyPaths = (obj: any, prefix: string[] = []): string[][] => {\n if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {\n return [];\n }\n\n return Object.keys(obj).flatMap((key) => {\n const newPath = [...prefix, key];\n const value = obj[key];\n // Skip null-valued keys entirely\n if (value === null) {\n return [];\n }\n return [newPath, ...getNonNullKeyPaths(value, newPath)];\n });\n};\n\n/**\n * Returns true if the key path EXISTS in obj (even if the terminal value is null).\n * Used for the structural presence check.\n */\nconst hasKey = (obj: any, keyPath: string[]): boolean => {\n let current = obj;\n for (const key of keyPath) {\n if (\n current === undefined ||\n current === null ||\n typeof current !== 'object'\n ) {\n return false;\n }\n if (!(key in current)) {\n return false;\n }\n current = current[key];\n }\n return true; // key exists; value may be null\n};\n\n/**\n * Returns true if the key path exists in obj AND the terminal value is non-null.\n * Used for the translation value check.\n */\nconst hasNonNullValue = (obj: any, keyPath: string[]): boolean => {\n let current = obj;\n for (const key of keyPath) {\n if (\n current === undefined ||\n current === null ||\n typeof current !== 'object'\n ) {\n return false;\n }\n if (!(key in current)) {\n return false;\n }\n current = current[key];\n }\n // null is treated as a missing translation (e.g., i18next-scanner sets null for untranslated keys)\n return current !== null;\n};\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const checkMissingLocalesPlugin = (\n locales: Locale[],\n onMissingLocale: (locale: Locale) => void\n): Plugins => ({\n id: 'check-missing-locales-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Translation,\n transform: (node: TranslationContent, props, deepTransformNode) => {\n const translations = node[NodeType.Translation] as Record<string, any>;\n\n /**\n * Two path sets built from all locales' content:\n *\n * presentPaths — every key path that exists in ANY locale, even those whose value\n * is null. A locale that is missing a path from this set is structurally incomplete\n * (the key doesn't exist at all).\n *\n * nonNullPaths — every key path that has a non-null value in at least one locale.\n * A locale that has the key but with null, when another locale already has a real\n * value, needs translation.\n */\n const presentPaths = new Set<string>();\n const nonNullPaths = new Set<string>();\n\n for (const locale of locales) {\n const value = translations[locale];\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n getAllKeyPaths(value).forEach((path) => {\n presentPaths.add(JSON.stringify(path));\n });\n\n getNonNullKeyPaths(value).forEach((path) => {\n nonNullPaths.add(JSON.stringify(path));\n });\n }\n }\n\n // If no locale has any content at all (all are null/undefined), the key is\n // universally pending — don't flag anyone.\n const hasAnyDefinedValue = locales.some(\n (locale) =>\n translations[locale] !== undefined && translations[locale] !== null\n );\n\n for (const locale of locales) {\n const value = translations[locale];\n\n if (value === null) {\n // Entire locale content is a null placeholder.\n // Flag only when some other locale already has real content.\n if (hasAnyDefinedValue) {\n onMissingLocale(locale);\n }\n continue;\n }\n\n if (!value) {\n // undefined / entirely absent\n onMissingLocale(locale);\n continue;\n }\n\n let flagged = false;\n\n // Structural check: every key that exists in any locale must also exist here\n // (even if the local value is null — at least the key must be present).\n for (const pathStr of presentPaths) {\n if (!hasKey(value, JSON.parse(pathStr))) {\n onMissingLocale(locale);\n flagged = true;\n break;\n }\n }\n\n if (!flagged) {\n // Value check: every key that has a non-null value in some locale must also\n // be non-null here (null = untranslated, needs filling).\n for (const pathStr of nonNullPaths) {\n if (!hasNonNullValue(value, JSON.parse(pathStr))) {\n onMissingLocale(locale);\n break;\n }\n }\n }\n }\n\n // Continue traversal inside the translation values\n for (const key in translations) {\n const child = translations[key];\n deepTransformNode(child, {\n ...props,\n children: child,\n });\n }\n\n // Return the original node; the return value is ignored by the caller\n return node;\n },\n});\n\n/**\n * Return the content of a node with only the translation plugin.\n *\n * @param node The node to transform.\n * @param locales The locales to check for missing translations.\n */\nexport const getMissingLocalesContent = <T extends ContentNode>(\n node: T,\n locales: LocalesValues[] = configuration?.internationalization?.locales,\n nodeProps: NodeProps\n): Locale[] => {\n const missingLocales = new Set<Locale>();\n\n const plugins: Plugins[] = [\n checkMissingLocalesPlugin(locales as Locale[], (locale) =>\n missingLocales.add(locale)\n ),\n ...(nodeProps.plugins ?? []),\n ];\n\n deepTransformNode(node, {\n ...nodeProps,\n plugins,\n }) as DeepTransformContent<T>;\n\n return Array.from(missingLocales);\n};\n\nexport const getMissingLocalesContentFromDictionary = (\n dictionary: Dictionary,\n locales: LocalesValues[] = configuration?.internationalization?.locales\n) =>\n getMissingLocalesContent(dictionary.content, locales, {\n dictionaryKey: dictionary.key,\n keyPath: [],\n });\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{getMultilingualDictionary as e}from"../deepTransformPlugins/getMultilingualDictionary.mjs";import{getNodeType as t}from"./getNodeType.mjs";import{colorizeKey as n,getAppLogger as r}from"@intlayer/config/client";import i from"@intlayer/config/built";const a=(e,a,o,s,c=[])=>{let l=r(i);if(e==null||a==null)return;let u=t(e),d=t(a);if(!(u===`unknown`||d===`unknown`)&&u!==d){l([`Error: Dictionary ${n(s)} has a multiple content files with type mismatch at path "${c.join(`.`)}": Cannot merge ${u} with ${d} while merging ${o}`],{level:`error`});return}},o=(e,t)=>{if(e==null)return t;if(t==null||typeof e!=`object`||typeof t!=`object`)return e;if(Array.isArray(e)&&Array.isArray(t))return s(e,t);if(typeof e==`object`&&typeof t==`object`){let n={},r=new Set([...Object.keys(e),...Object.keys(t)]);for(let i of r)n[i]=o(e[i],t[i]);return n}return e},s=(e,t)=>{let n=e.every(e=>typeof e!=`object`||!e),r=t.every(e=>typeof e!=`object`||!e);if(n&&r)return t;let i=[],a=Math.max(e.length,t.length);for(let n=0;n<a;n++){let r=e[n],a=t[n];r===void 0&&a===void 0||(r===void 0?i.push(a):a===void 0?i.push(r):typeof r==`object`&&typeof a==`object`&&r!==null&&a!==null?(`key`in r&&`key`in a&&(r.key,a.key),i.push(o(r,a))):i.push(r))}return i},c=t=>{let n=Array.from(new Set(t.filter(e=>e.localId).map(e=>e.localId))),r=t.map(e=>e.key);if(new Set(r).size!==1)throw Error(`All dictionaries must have the same key`);let i=t[0].content;for(let n=1;n<t.length;n++){let r=e(t[n]);a(i,r.content,r.localId,r.key,[]),i=o(i,r.content)}return{key:t[0].key,content:i,localIds:n}};export{c as mergeDictionaries};
1
+ import{getMultilingualDictionary as e}from"../deepTransformPlugins/getMultilingualDictionary.mjs";import{getNodeType as t}from"./getNodeType.mjs";import n from"@intlayer/config/built";import{colorizeKey as r,getAppLogger as i}from"@intlayer/config/logger";const a=(e,a,o,s,c=[])=>{let l=i(n);if(e==null||a==null)return;let u=t(e),d=t(a);if(!(u===`unknown`||d===`unknown`)&&u!==d){l([`Error: Dictionary ${r(s)} has a multiple content files with type mismatch at path "${c.join(`.`)}": Cannot merge ${u} with ${d} while merging ${o}`],{level:`error`});return}},o=(e,t)=>{if(e==null)return t;if(t==null||typeof e!=`object`||typeof t!=`object`)return e;if(Array.isArray(e)&&Array.isArray(t))return s(e,t);if(typeof e==`object`&&typeof t==`object`){let n={},r=new Set([...Object.keys(e),...Object.keys(t)]);for(let i of r)n[i]=o(e[i],t[i]);return n}return e},s=(e,t)=>{let n=e.every(e=>typeof e!=`object`||!e),r=t.every(e=>typeof e!=`object`||!e);if(n&&r)return t;let i=[],a=Math.max(e.length,t.length);for(let n=0;n<a;n++){let r=e[n],a=t[n];r===void 0&&a===void 0||(r===void 0?i.push(a):a===void 0?i.push(r):typeof r==`object`&&typeof a==`object`&&r!==null&&a!==null?(`key`in r&&`key`in a&&(r.key,a.key),i.push(o(r,a))):i.push(r))}return i},c=t=>{let n=Array.from(new Set(t.filter(e=>e.localId).map(e=>e.localId))),r=t.map(e=>e.key);if(new Set(r).size!==1)throw Error(`All dictionaries must have the same key`);let i=t[0].content;for(let n=1;n<t.length;n++){let r=e(t[n]);a(i,r.content,r.localId,r.key,[]),i=o(i,r.content)}return{key:t[0].key,content:i,localIds:n}};export{c as mergeDictionaries};
2
2
  //# sourceMappingURL=mergeDictionaries.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mergeDictionaries.mjs","names":[],"sources":["../../../src/dictionaryManipulator/mergeDictionaries.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/client';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types';\nimport { getMultilingualDictionary } from '../deepTransformPlugins';\nimport { getNodeType } from './getNodeType';\n\n// Extended type that includes arrays for internal merge operations\ntype MergeableContent = ContentNode | ContentNode[];\n\nconst checkTypesMatch = (\n object1: ContentNode,\n object2: ContentNode,\n object2LocalId: LocalDictionaryId | undefined,\n dictionaryKey: string,\n path: string[] = []\n): void => {\n const appLogger = getAppLogger(configuration);\n\n // If either side is missing/undefined, allow merge without error\n if (\n object1 === undefined ||\n object1 === null ||\n object2 === undefined ||\n object2 === null\n )\n return;\n\n const type1 = getNodeType(object1);\n const type2 = getNodeType(object2);\n\n // Unknown types are treated as flexible; skip strict mismatch reporting\n if (type1 === 'unknown' || type2 === 'unknown') return;\n\n if (type1 !== type2) {\n appLogger(\n [\n `Error: Dictionary ${colorizeKey(dictionaryKey)} has a multiple content files with type mismatch at path \"${path.join('.')}\": Cannot merge ${type1} with ${type2} while merging ${object2LocalId}`,\n ],\n {\n level: 'error',\n }\n );\n\n return;\n }\n};\n\n// Custom merge function that prefers destination (first dictionary) values\nconst customMerge = (\n destination: ContentNode,\n source: ContentNode\n): MergeableContent => {\n // If destination is undefined/null, use source\n if (destination === undefined || destination === null) {\n return source;\n }\n\n // If source is undefined/null, use destination\n if (source === undefined || source === null) {\n return destination;\n }\n\n // For primitive values, prefer destination (first dictionary)\n if (typeof destination !== 'object' || typeof source !== 'object') {\n return destination;\n }\n\n // For arrays, use our custom array merge\n if (Array.isArray(destination) && Array.isArray(source)) {\n return arrayMerge(\n destination as ContentNode[],\n source as ContentNode[]\n ) as MergeableContent;\n }\n\n // For objects, recursively merge with our custom logic\n if (typeof destination === 'object' && typeof source === 'object') {\n const result: Record<string, MergeableContent> = {};\n const allKeys = new Set([\n ...Object.keys(destination as unknown as Record<string, ContentNode>),\n ...Object.keys(source as unknown as Record<string, ContentNode>),\n ]);\n\n for (const key of allKeys) {\n result[key] = customMerge(\n (destination as unknown as Record<string, ContentNode>)[key],\n (source as unknown as Record<string, ContentNode>)[key]\n );\n }\n\n return result as unknown as MergeableContent;\n }\n\n // Fallback to destination\n return destination;\n};\n\n// Custom array merge strategy that merges arrays by key when present, otherwise by index\nconst arrayMerge = (\n destinationArray: ContentNode[],\n sourceArray: ContentNode[]\n): MergeableContent[] => {\n // Check if both arrays contain only primitives\n const destHasOnlyPrimitives = destinationArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n const sourceHasOnlyPrimitives = sourceArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n\n // If both arrays contain only primitives, use the source array (second dictionary)\n if (destHasOnlyPrimitives && sourceHasOnlyPrimitives) {\n return sourceArray;\n }\n\n // Otherwise, merge by index with object merging logic\n const result: MergeableContent[] = [];\n const maxLength = Math.max(destinationArray.length, sourceArray.length);\n\n for (let i = 0; i < maxLength; i++) {\n const destItem = destinationArray[i];\n const sourceItem = sourceArray[i];\n\n if (destItem === undefined && sourceItem === undefined) {\n } else if (destItem === undefined) {\n // Only source exists, add it\n result.push(sourceItem);\n } else if (sourceItem === undefined) {\n // Only destination exists, add it\n result.push(destItem);\n } else {\n // Both exist, merge them\n if (\n typeof destItem === 'object' &&\n typeof sourceItem === 'object' &&\n destItem !== null &&\n sourceItem !== null\n ) {\n // Check if both objects have a 'key' property for keyed merging\n if (\n 'key' in destItem &&\n 'key' in sourceItem &&\n (destItem as Record<string, string>).key ===\n (sourceItem as Record<string, string>).key\n ) {\n // Merge objects with same key, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n } else {\n // Merge objects by index, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n }\n } else {\n // For primitives or non-objects, use destination value (first dictionary)\n result.push(destItem);\n }\n }\n }\n\n return result;\n};\n\nexport const mergeDictionaries = (dictionaries: Dictionary[]): Dictionary => {\n const localIds = Array.from(\n new Set<LocalDictionaryId>(\n dictionaries.filter((dict) => dict.localId).map((dict) => dict.localId!)\n )\n );\n\n const dictionariesKeys = dictionaries.map((dict) => dict.key);\n\n // Check if all dictionaries have the same key\n if (new Set(dictionariesKeys).size !== 1) {\n throw new Error('All dictionaries must have the same key');\n }\n\n let mergedContent: Dictionary['content'] = dictionaries[0].content;\n\n for (let i = 1; i < dictionaries.length; i++) {\n // If the dictionary is a per-locale dictionary, transform it to a partial multilingual dictionary\n const currentDictionary = getMultilingualDictionary(dictionaries[i]);\n\n // Check types before merging\n checkTypesMatch(\n mergedContent,\n currentDictionary.content,\n currentDictionary.localId,\n currentDictionary.key,\n []\n );\n\n mergedContent = customMerge(\n mergedContent,\n currentDictionary.content\n ) as ContentNode;\n }\n\n const mergedDictionary: Dictionary = {\n key: dictionaries[0].key,\n content: mergedContent,\n localIds,\n };\n\n return mergedDictionary;\n};\n"],"mappings":"gQAaA,MAAM,GACJ,EACA,EACA,EACA,EACA,EAAiB,EAAE,GACV,CACT,IAAM,EAAY,EAAa,EAAc,CAG7C,GACE,GACY,MACZ,GACY,KAEZ,OAEF,IAAM,EAAQ,EAAY,EAAQ,CAC5B,EAAQ,EAAY,EAAQ,CAG9B,SAAU,WAAa,IAAU,YAEjC,IAAU,EAAO,CACnB,EACE,CACE,qBAAqB,EAAY,EAAc,CAAC,4DAA4D,EAAK,KAAK,IAAI,CAAC,kBAAkB,EAAM,QAAQ,EAAM,iBAAiB,IACnL,CACD,CACE,MAAO,QACR,CACF,CAED,SAKE,GACJ,EACA,IACqB,CAErB,GAAI,GAA6C,KAC/C,OAAO,EAST,GALI,GAAmC,MAKnC,OAAO,GAAgB,UAAY,OAAO,GAAW,SACvD,OAAO,EAIT,GAAI,MAAM,QAAQ,EAAY,EAAI,MAAM,QAAQ,EAAO,CACrD,OAAO,EACL,EACA,EACD,CAIH,GAAI,OAAO,GAAgB,UAAY,OAAO,GAAW,SAAU,CACjE,IAAM,EAA2C,EAAE,CAC7C,EAAU,IAAI,IAAI,CACtB,GAAG,OAAO,KAAK,EAAsD,CACrE,GAAG,OAAO,KAAK,EAAiD,CACjE,CAAC,CAEF,IAAK,IAAM,KAAO,EAChB,EAAO,GAAO,EACX,EAAuD,GACvD,EAAkD,GACpD,CAGH,OAAO,EAIT,OAAO,GAIH,GACJ,EACA,IACuB,CAEvB,IAAM,EAAwB,EAAiB,MAC5C,GAAS,OAAO,GAAS,WAAY,EACvC,CACK,EAA0B,EAAY,MACzC,GAAS,OAAO,GAAS,WAAY,EACvC,CAGD,GAAI,GAAyB,EAC3B,OAAO,EAIT,IAAM,EAA6B,EAAE,CAC/B,EAAY,KAAK,IAAI,EAAiB,OAAQ,EAAY,OAAO,CAEvE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,IAAK,CAClC,IAAM,EAAW,EAAiB,GAC5B,EAAa,EAAY,GAE3B,IAAa,IAAA,IAAa,IAAe,IAAA,KAClC,IAAa,IAAA,GAEtB,EAAO,KAAK,EAAW,CACd,IAAe,IAAA,GAExB,EAAO,KAAK,EAAS,CAInB,OAAO,GAAa,UACpB,OAAO,GAAe,UACtB,IAAa,MACb,IAAe,MAIb,QAAS,GACT,QAAS,IACR,EAAoC,IAClC,EAAsC,KAGzC,EAAO,KAAK,EAAY,EAAU,EAAW,CAAC,EAOhD,EAAO,KAAK,EAAS,EAK3B,OAAO,GAGI,EAAqB,GAA2C,CAC3E,IAAM,EAAW,MAAM,KACrB,IAAI,IACF,EAAa,OAAQ,GAAS,EAAK,QAAQ,CAAC,IAAK,GAAS,EAAK,QAAS,CACzE,CACF,CAEK,EAAmB,EAAa,IAAK,GAAS,EAAK,IAAI,CAG7D,GAAI,IAAI,IAAI,EAAiB,CAAC,OAAS,EACrC,MAAU,MAAM,0CAA0C,CAG5D,IAAI,EAAuC,EAAa,GAAG,QAE3D,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,OAAQ,IAAK,CAE5C,IAAM,EAAoB,EAA0B,EAAa,GAAG,CAGpE,EACE,EACA,EAAkB,QAClB,EAAkB,QAClB,EAAkB,IAClB,EAAE,CACH,CAED,EAAgB,EACd,EACA,EAAkB,QACnB,CASH,MANqC,CACnC,IAAK,EAAa,GAAG,IACrB,QAAS,EACT,WACD"}
1
+ {"version":3,"file":"mergeDictionaries.mjs","names":[],"sources":["../../../src/dictionaryManipulator/mergeDictionaries.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport type {\n ContentNode,\n Dictionary,\n LocalDictionaryId,\n} from '@intlayer/types';\nimport { getMultilingualDictionary } from '../deepTransformPlugins';\nimport { getNodeType } from './getNodeType';\n\n// Extended type that includes arrays for internal merge operations\ntype MergeableContent = ContentNode | ContentNode[];\n\nconst checkTypesMatch = (\n object1: ContentNode,\n object2: ContentNode,\n object2LocalId: LocalDictionaryId | undefined,\n dictionaryKey: string,\n path: string[] = []\n): void => {\n const appLogger = getAppLogger(configuration);\n\n // If either side is missing/undefined, allow merge without error\n if (\n object1 === undefined ||\n object1 === null ||\n object2 === undefined ||\n object2 === null\n )\n return;\n\n const type1 = getNodeType(object1);\n const type2 = getNodeType(object2);\n\n // Unknown types are treated as flexible; skip strict mismatch reporting\n if (type1 === 'unknown' || type2 === 'unknown') return;\n\n if (type1 !== type2) {\n appLogger(\n [\n `Error: Dictionary ${colorizeKey(dictionaryKey)} has a multiple content files with type mismatch at path \"${path.join('.')}\": Cannot merge ${type1} with ${type2} while merging ${object2LocalId}`,\n ],\n {\n level: 'error',\n }\n );\n\n return;\n }\n};\n\n// Custom merge function that prefers destination (first dictionary) values\nconst customMerge = (\n destination: ContentNode,\n source: ContentNode\n): MergeableContent => {\n // If destination is undefined/null, use source\n if (destination === undefined || destination === null) {\n return source;\n }\n\n // If source is undefined/null, use destination\n if (source === undefined || source === null) {\n return destination;\n }\n\n // For primitive values, prefer destination (first dictionary)\n if (typeof destination !== 'object' || typeof source !== 'object') {\n return destination;\n }\n\n // For arrays, use our custom array merge\n if (Array.isArray(destination) && Array.isArray(source)) {\n return arrayMerge(\n destination as ContentNode[],\n source as ContentNode[]\n ) as MergeableContent;\n }\n\n // For objects, recursively merge with our custom logic\n if (typeof destination === 'object' && typeof source === 'object') {\n const result: Record<string, MergeableContent> = {};\n const allKeys = new Set([\n ...Object.keys(destination as unknown as Record<string, ContentNode>),\n ...Object.keys(source as unknown as Record<string, ContentNode>),\n ]);\n\n for (const key of allKeys) {\n result[key] = customMerge(\n (destination as unknown as Record<string, ContentNode>)[key],\n (source as unknown as Record<string, ContentNode>)[key]\n );\n }\n\n return result as unknown as MergeableContent;\n }\n\n // Fallback to destination\n return destination;\n};\n\n// Custom array merge strategy that merges arrays by key when present, otherwise by index\nconst arrayMerge = (\n destinationArray: ContentNode[],\n sourceArray: ContentNode[]\n): MergeableContent[] => {\n // Check if both arrays contain only primitives\n const destHasOnlyPrimitives = destinationArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n const sourceHasOnlyPrimitives = sourceArray.every(\n (item) => typeof item !== 'object' || item === null\n );\n\n // If both arrays contain only primitives, use the source array (second dictionary)\n if (destHasOnlyPrimitives && sourceHasOnlyPrimitives) {\n return sourceArray;\n }\n\n // Otherwise, merge by index with object merging logic\n const result: MergeableContent[] = [];\n const maxLength = Math.max(destinationArray.length, sourceArray.length);\n\n for (let i = 0; i < maxLength; i++) {\n const destItem = destinationArray[i];\n const sourceItem = sourceArray[i];\n\n if (destItem === undefined && sourceItem === undefined) {\n } else if (destItem === undefined) {\n // Only source exists, add it\n result.push(sourceItem);\n } else if (sourceItem === undefined) {\n // Only destination exists, add it\n result.push(destItem);\n } else {\n // Both exist, merge them\n if (\n typeof destItem === 'object' &&\n typeof sourceItem === 'object' &&\n destItem !== null &&\n sourceItem !== null\n ) {\n // Check if both objects have a 'key' property for keyed merging\n if (\n 'key' in destItem &&\n 'key' in sourceItem &&\n (destItem as Record<string, string>).key ===\n (sourceItem as Record<string, string>).key\n ) {\n // Merge objects with same key, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n } else {\n // Merge objects by index, preferring destination (first dictionary) values\n result.push(customMerge(destItem, sourceItem));\n }\n } else {\n // For primitives or non-objects, use destination value (first dictionary)\n result.push(destItem);\n }\n }\n }\n\n return result;\n};\n\nexport const mergeDictionaries = (dictionaries: Dictionary[]): Dictionary => {\n const localIds = Array.from(\n new Set<LocalDictionaryId>(\n dictionaries.filter((dict) => dict.localId).map((dict) => dict.localId!)\n )\n );\n\n const dictionariesKeys = dictionaries.map((dict) => dict.key);\n\n // Check if all dictionaries have the same key\n if (new Set(dictionariesKeys).size !== 1) {\n throw new Error('All dictionaries must have the same key');\n }\n\n let mergedContent: Dictionary['content'] = dictionaries[0].content;\n\n for (let i = 1; i < dictionaries.length; i++) {\n // If the dictionary is a per-locale dictionary, transform it to a partial multilingual dictionary\n const currentDictionary = getMultilingualDictionary(dictionaries[i]);\n\n // Check types before merging\n checkTypesMatch(\n mergedContent,\n currentDictionary.content,\n currentDictionary.localId,\n currentDictionary.key,\n []\n );\n\n mergedContent = customMerge(\n mergedContent,\n currentDictionary.content\n ) as ContentNode;\n }\n\n const mergedDictionary: Dictionary = {\n key: dictionaries[0].key,\n content: mergedContent,\n localIds,\n };\n\n return mergedDictionary;\n};\n"],"mappings":"gQAaA,MAAM,GACJ,EACA,EACA,EACA,EACA,EAAiB,EAAE,GACV,CACT,IAAM,EAAY,EAAa,EAAc,CAG7C,GACE,GACY,MACZ,GACY,KAEZ,OAEF,IAAM,EAAQ,EAAY,EAAQ,CAC5B,EAAQ,EAAY,EAAQ,CAG9B,SAAU,WAAa,IAAU,YAEjC,IAAU,EAAO,CACnB,EACE,CACE,qBAAqB,EAAY,EAAc,CAAC,4DAA4D,EAAK,KAAK,IAAI,CAAC,kBAAkB,EAAM,QAAQ,EAAM,iBAAiB,IACnL,CACD,CACE,MAAO,QACR,CACF,CAED,SAKE,GACJ,EACA,IACqB,CAErB,GAAI,GAA6C,KAC/C,OAAO,EAST,GALI,GAAmC,MAKnC,OAAO,GAAgB,UAAY,OAAO,GAAW,SACvD,OAAO,EAIT,GAAI,MAAM,QAAQ,EAAY,EAAI,MAAM,QAAQ,EAAO,CACrD,OAAO,EACL,EACA,EACD,CAIH,GAAI,OAAO,GAAgB,UAAY,OAAO,GAAW,SAAU,CACjE,IAAM,EAA2C,EAAE,CAC7C,EAAU,IAAI,IAAI,CACtB,GAAG,OAAO,KAAK,EAAsD,CACrE,GAAG,OAAO,KAAK,EAAiD,CACjE,CAAC,CAEF,IAAK,IAAM,KAAO,EAChB,EAAO,GAAO,EACX,EAAuD,GACvD,EAAkD,GACpD,CAGH,OAAO,EAIT,OAAO,GAIH,GACJ,EACA,IACuB,CAEvB,IAAM,EAAwB,EAAiB,MAC5C,GAAS,OAAO,GAAS,WAAY,EACvC,CACK,EAA0B,EAAY,MACzC,GAAS,OAAO,GAAS,WAAY,EACvC,CAGD,GAAI,GAAyB,EAC3B,OAAO,EAIT,IAAM,EAA6B,EAAE,CAC/B,EAAY,KAAK,IAAI,EAAiB,OAAQ,EAAY,OAAO,CAEvE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,IAAK,CAClC,IAAM,EAAW,EAAiB,GAC5B,EAAa,EAAY,GAE3B,IAAa,IAAA,IAAa,IAAe,IAAA,KAClC,IAAa,IAAA,GAEtB,EAAO,KAAK,EAAW,CACd,IAAe,IAAA,GAExB,EAAO,KAAK,EAAS,CAInB,OAAO,GAAa,UACpB,OAAO,GAAe,UACtB,IAAa,MACb,IAAe,MAIb,QAAS,GACT,QAAS,IACR,EAAoC,IAClC,EAAsC,KAGzC,EAAO,KAAK,EAAY,EAAU,EAAW,CAAC,EAOhD,EAAO,KAAK,EAAS,EAK3B,OAAO,GAGI,EAAqB,GAA2C,CAC3E,IAAM,EAAW,MAAM,KACrB,IAAI,IACF,EAAa,OAAQ,GAAS,EAAK,QAAQ,CAAC,IAAK,GAAS,EAAK,QAAS,CACzE,CACF,CAEK,EAAmB,EAAa,IAAK,GAAS,EAAK,IAAI,CAG7D,GAAI,IAAI,IAAI,EAAiB,CAAC,OAAS,EACrC,MAAU,MAAM,0CAA0C,CAG5D,IAAI,EAAuC,EAAa,GAAG,QAE3D,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,OAAQ,IAAK,CAE5C,IAAM,EAAoB,EAA0B,EAAa,GAAG,CAGpE,EACE,EACA,EAAkB,QAClB,EAAkB,QAClB,EAAkB,IAClB,EAAE,CACH,CAED,EAAgB,EACd,EACA,EAAkB,QACnB,CASH,MANqC,CACnC,IAAK,EAAa,GAAG,IACrB,QAAS,EACT,WACD"}
@@ -1,2 +1,2 @@
1
- import{getDictionary as e}from"./getDictionary.mjs";import{colorizeKey as t,getAppLogger as n}from"@intlayer/config/client";import r from"@intlayer/config/built";import{getDictionaries as i}from"@intlayer/dictionaries-entry";const a=(e=``)=>new Proxy(()=>e,{get:(t,n)=>{if(n===`toJSON`||n===Symbol.toPrimitive||n===`toString`)return()=>e;if(n!==`then`)return a(e?`${e}.${String(n)}`:String(n))},apply:()=>e}),o=(o,s,c)=>{let l=i()[o];return l?e(l,s,c):(n(r)(`Dictionary ${t(o)} was not found. Using fallback proxy.`,{level:`warn`,isVerbose:!0}),a(o))};export{o as getIntlayer};
1
+ import{getDictionary as e}from"./getDictionary.mjs";import t from"@intlayer/config/built";import{colorizeKey as n,getAppLogger as r}from"@intlayer/config/logger";import{getDictionaries as i}from"@intlayer/dictionaries-entry";const a=(e=``)=>new Proxy(()=>e,{get:(t,n)=>{if(n===`toJSON`||n===Symbol.toPrimitive||n===`toString`)return()=>e;if(n!==`then`)return a(e?`${e}.${String(n)}`:String(n))},apply:()=>e}),o=(o,s,c)=>{let l=i()[o];return l?e(l,s,c):(r(t)(`Dictionary ${n(o)} was not found. Using fallback proxy.`,{level:`warn`,isVerbose:!0}),a(o))};export{o as getIntlayer};
2
2
  //# sourceMappingURL=getIntlayer.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getIntlayer.mjs","names":[],"sources":["../../../src/interpreter/getIntlayer.ts"],"sourcesContent":["// packages/@intlayer/core/src/interpreter/getIntlayer.ts\n\nimport configuration from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/client';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type {\n DeclaredLocales,\n DictionaryKeys,\n DictionaryRegistryContent,\n DictionaryRegistryElement,\n LocalesValues,\n} from '@intlayer/types';\nimport type {\n DeepTransformContent,\n IInterpreterPluginState,\n Plugins,\n} from './getContent';\nimport { getDictionary } from './getDictionary';\n\n/**\n * Creates a Recursive Proxy that returns the path of the accessed key\n * stringified. This prevents the app from crashing on undefined access.\n */\nconst createSafeFallback = (path = ''): any => {\n return new Proxy(\n // Target is a function so it can be called if the dictionary expects a function\n () => path,\n {\n get: (_target, prop) => {\n // Handle common object methods to prevent infinite recursion or weird behavior\n if (\n prop === 'toJSON' ||\n prop === Symbol.toPrimitive ||\n prop === 'toString'\n ) {\n return () => path;\n }\n if (prop === 'then') {\n return undefined; // Prevent it from being treated as a Promise\n }\n\n // Recursively build the path (e.g., \"myDictionary.home.title\")\n const nextPath = path ? `${path}.${String(prop)}` : String(prop);\n return createSafeFallback(nextPath);\n },\n // If the code tries to execute the missing key as a function: t.title()\n apply: () => {\n return path;\n },\n }\n );\n};\n\nexport const getIntlayer = <\n T extends DictionaryKeys,\n L extends LocalesValues = DeclaredLocales,\n>(\n key: T,\n locale?: L,\n plugins?: Plugins[]\n): DeepTransformContent<\n DictionaryRegistryContent<T>,\n IInterpreterPluginState,\n L\n> => {\n const dictionaries = getDictionaries();\n const dictionary = dictionaries[key as T] as DictionaryRegistryElement<T>;\n\n if (!dictionary) {\n // Log a warning instead of throwing (so developers know it's missing)\n const logger = getAppLogger(configuration);\n logger(\n `Dictionary ${colorizeKey(key as string)} was not found. Using fallback proxy.`,\n {\n level: 'warn',\n isVerbose: true,\n }\n );\n\n if (process.env.NODE_ENV === 'development') {\n // Return the Safe Proxy\n // We initialize it with the dictionary key name so the UI shows \"my-dictionary.someKey\"\n return createSafeFallback(key as string);\n }\n\n return createSafeFallback(key as string);\n }\n\n return getDictionary<DictionaryRegistryElement<T>, L>(\n dictionary,\n locale,\n plugins\n );\n};\n"],"mappings":"iOAuBA,MAAM,GAAsB,EAAO,KAC1B,IAAI,UAEH,EACN,CACE,KAAM,EAAS,IAAS,CAEtB,GACE,IAAS,UACT,IAAS,OAAO,aAChB,IAAS,WAET,UAAa,EAEX,OAAS,OAMb,OAAO,EADU,EAAO,GAAG,EAAK,GAAG,OAAO,EAAK,GAAK,OAAO,EAAK,CAC7B,EAGrC,UACS,EAEV,CACF,CAGU,GAIX,EACA,EACA,IAKG,CAEH,IAAM,EADe,GAAiB,CACN,GAsBhC,OApBK,EAoBE,EACL,EACA,EACA,EACD,EAtBgB,EAAa,EAAc,CAExC,cAAc,EAAY,EAAc,CAAC,uCACzC,CACE,MAAO,OACP,UAAW,GACZ,CACF,CAQM,EAAmB,EAAc"}
1
+ {"version":3,"file":"getIntlayer.mjs","names":[],"sources":["../../../src/interpreter/getIntlayer.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type {\n DeclaredLocales,\n DictionaryKeys,\n DictionaryRegistryContent,\n DictionaryRegistryElement,\n LocalesValues,\n} from '@intlayer/types';\nimport type {\n DeepTransformContent,\n IInterpreterPluginState,\n Plugins,\n} from './getContent';\nimport { getDictionary } from './getDictionary';\n\n/**\n * Creates a Recursive Proxy that returns the path of the accessed key\n * stringified. This prevents the app from crashing on undefined access.\n */\nconst createSafeFallback = (path = ''): any => {\n return new Proxy(\n // Target is a function so it can be called if the dictionary expects a function\n () => path,\n {\n get: (_target, prop) => {\n // Handle common object methods to prevent infinite recursion or weird behavior\n if (\n prop === 'toJSON' ||\n prop === Symbol.toPrimitive ||\n prop === 'toString'\n ) {\n return () => path;\n }\n if (prop === 'then') {\n return undefined; // Prevent it from being treated as a Promise\n }\n\n // Recursively build the path (e.g., \"myDictionary.home.title\")\n const nextPath = path ? `${path}.${String(prop)}` : String(prop);\n return createSafeFallback(nextPath);\n },\n // If the code tries to execute the missing key as a function: t.title()\n apply: () => {\n return path;\n },\n }\n );\n};\n\nexport const getIntlayer = <\n T extends DictionaryKeys,\n L extends LocalesValues = DeclaredLocales,\n>(\n key: T,\n locale?: L,\n plugins?: Plugins[]\n): DeepTransformContent<\n DictionaryRegistryContent<T>,\n IInterpreterPluginState,\n L\n> => {\n const dictionaries = getDictionaries();\n const dictionary = dictionaries[key as T] as DictionaryRegistryElement<T>;\n\n if (!dictionary) {\n // Log a warning instead of throwing (so developers know it's missing)\n const logger = getAppLogger(configuration);\n logger(\n `Dictionary ${colorizeKey(key as string)} was not found. Using fallback proxy.`,\n {\n level: 'warn',\n isVerbose: true,\n }\n );\n\n if (process.env.NODE_ENV === 'development') {\n // Return the Safe Proxy\n // We initialize it with the dictionary key name so the UI shows \"my-dictionary.someKey\"\n return createSafeFallback(key as string);\n }\n\n return createSafeFallback(key as string);\n }\n\n return getDictionary<DictionaryRegistryElement<T>, L>(\n dictionary,\n locale,\n plugins\n );\n};\n"],"mappings":"iOAqBA,MAAM,GAAsB,EAAO,KAC1B,IAAI,UAEH,EACN,CACE,KAAM,EAAS,IAAS,CAEtB,GACE,IAAS,UACT,IAAS,OAAO,aAChB,IAAS,WAET,UAAa,EAEX,OAAS,OAMb,OAAO,EADU,EAAO,GAAG,EAAK,GAAG,OAAO,EAAK,GAAK,OAAO,EAAK,CAC7B,EAGrC,UACS,EAEV,CACF,CAGU,GAIX,EACA,EACA,IAKG,CAEH,IAAM,EADe,GAAiB,CACN,GAsBhC,OApBK,EAoBE,EACL,EACA,EACA,EACD,EAtBgB,EAAa,EAAc,CAExC,cAAc,EAAY,EAAc,CAAC,uCACzC,CACE,MAAO,OACP,UAAW,GACZ,CACF,CAQM,EAAmB,EAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"getBrowserLocale.mjs","names":[],"sources":["../../../src/localization/getBrowserLocale.tsx"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { type Locale, Locales } from '@intlayer/types';\nimport {\n getLocaleFromStorage,\n type LocaleStorageOptions,\n} from '../utils/localeStorage';\nimport { localeDetector } from './localeDetector';\n\nexport enum LanguageDetector {\n Querystring = 'querystring',\n Storage = 'storage',\n Navigator = 'navigator',\n HtmlTag = 'htmlTag',\n}\n\nexport const localeStorageOptions: LocaleStorageOptions = {\n getCookie: (name: string) =>\n document.cookie\n .split(';')\n .find((c) => c.trim().startsWith(`${name}=`))\n ?.split('=')[1],\n getLocaleStorage: (name: string) => localStorage.getItem(name),\n getSessionStorage: (name: string) => sessionStorage.getItem(name),\n isCookieEnabled: true,\n setCookieStore: (name, value, attributes) =>\n cookieStore.set({\n name,\n value,\n path: attributes.path,\n domain: attributes.domain,\n expires: attributes.expires,\n sameSite: attributes.sameSite,\n }),\n setCookieString: (_name, cookie) => {\n // biome-ignore lint/suspicious/noDocumentCookie: set cookie fallback\n document.cookie = cookie;\n },\n setSessionStorage: (name, value) => sessionStorage.setItem(name, value),\n setLocaleStorage: (name, value) => localStorage.setItem(name, value),\n};\n\n// Default settings for the language detector\ntype LanguageDetectorOptions = {\n order?: LanguageDetector[];\n lookupQuerystring?: string;\n htmlTag?: HTMLElement | null;\n};\n\nconst getDefaultsOptions = (): LanguageDetectorOptions => {\n return {\n order: [\n LanguageDetector.Querystring,\n LanguageDetector.Storage,\n LanguageDetector.Navigator,\n LanguageDetector.HtmlTag,\n ],\n lookupQuerystring: 'locale',\n htmlTag: typeof document !== 'undefined' ? document.documentElement : null,\n };\n};\n\nconst detectLanguage = (\n order: string[],\n options: LanguageDetectorOptions\n): Record<LanguageDetector, Locale | undefined> => {\n const detected: Record<LanguageDetector, Locale | undefined> = {} as Record<\n LanguageDetector,\n Locale | undefined\n >;\n\n const queryStringDetector = () => {\n if (typeof window === 'undefined') return;\n const search = window.location.search || '';\n const params = new URLSearchParams(search);\n const value = params.get(options.lookupQuerystring ?? '');\n if (value) {\n detected[LanguageDetector.Querystring] = value as Locale;\n }\n };\n\n const storageDetector = () => {\n if (typeof window === 'undefined') return;\n\n const locale = getLocaleFromStorage({\n getCookie: (name: string) => {\n try {\n const cookies = document.cookie.split(';');\n const cookieName = `${name}=`;\n\n const cookie = cookies.find((cookie) =>\n cookie.trim().startsWith(cookieName)\n );\n\n if (cookie) {\n return cookie.split('=')[1].trim();\n }\n } catch {}\n return undefined;\n },\n getSessionStorage: (name: string) => {\n try {\n return window.sessionStorage.getItem(name) ?? undefined;\n } catch {}\n return undefined;\n },\n getLocaleStorage: (name: string) => {\n try {\n return window.localStorage.getItem(name) ?? undefined;\n } catch {}\n return undefined;\n },\n });\n\n if (locale) {\n detected[LanguageDetector.Storage] = locale;\n }\n };\n\n const navigatorDetector = () => {\n if (typeof navigator === 'undefined') return;\n\n const { internationalization } = configuration;\n const languages = navigator.languages ?? [navigator.language];\n\n // Use localeDetector to find the best matching locale\n const locale = localeDetector(\n { 'accept-language': languages.join(',') },\n internationalization.locales,\n internationalization.defaultLocale\n );\n\n if (locale) {\n detected[LanguageDetector.Navigator] = locale;\n }\n };\n\n const htmlTagDetector = () => {\n const htmlTag = options.htmlTag;\n if (htmlTag && typeof htmlTag.getAttribute === 'function') {\n const lang = htmlTag.getAttribute('lang');\n if (lang) {\n const { internationalization } = configuration;\n\n // Validate and resolve the locale\n const locale = localeDetector(\n { 'accept-language': lang },\n internationalization.locales,\n internationalization.defaultLocale\n );\n\n detected[LanguageDetector.HtmlTag] = locale;\n }\n }\n };\n\n // Map detector names to their corresponding functions\n const detectors: Record<string, () => void> = {\n [LanguageDetector.Querystring]: queryStringDetector,\n [LanguageDetector.Storage]: storageDetector,\n [LanguageDetector.Navigator]: navigatorDetector,\n [LanguageDetector.HtmlTag]: htmlTagDetector,\n };\n\n // Use the provided order to run each detector\n order.forEach((detectorName) => {\n detectors[detectorName]?.();\n });\n\n return detected;\n};\n\nconst getFirstAvailableLocale = (\n locales: Record<LanguageDetector, Locale | undefined>,\n order: LanguageDetector[]\n): Locale => {\n const { internationalization } = configuration;\n\n for (const detector of order) {\n const locale = locales[detector];\n\n if (locale && internationalization.locales.includes(locale)) {\n return locale;\n }\n }\n\n return internationalization?.defaultLocale ?? Locales.ENGLISH;\n};\n\n/**\n * Core language detector function for browser environments.\n *\n * Detects the user's preferred locale by checking multiple sources in order:\n * 1. Query string parameter\n * 2. Storage (cookies, localStorage, sessionStorage) - uses getLocaleFromStorage\n * 3. Navigator languages - uses localeDetector\n * 4. HTML lang attribute - uses localeDetector\n *\n * @param userOptions - Optional configuration for detection order and lookup keys\n * @returns The detected locale or the default locale\n *\n * @example\n * const locale = getBrowserLocale({ order: [LanguageDetector.Storage, LanguageDetector.Navigator] });\n */\nexport const getBrowserLocale = (\n userOptions: LanguageDetectorOptions | undefined = {}\n): Locale => {\n const options = { ...getDefaultsOptions(), ...userOptions };\n\n const locales = detectLanguage(options.order ?? [], options);\n\n return getFirstAvailableLocale(locales, options.order ?? []);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"getBrowserLocale.mjs","names":[],"sources":["../../../src/localization/getBrowserLocale.tsx"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { type Locale, Locales } from '@intlayer/types';\nimport {\n getLocaleFromStorage,\n type LocaleStorageOptions,\n} from '../utils/localeStorage';\nimport { localeDetector } from './localeDetector';\n\nexport enum LanguageDetector {\n Querystring = 'querystring',\n Storage = 'storage',\n Navigator = 'navigator',\n HtmlTag = 'htmlTag',\n}\n\nexport const localeStorageOptions: LocaleStorageOptions = {\n getCookie: (name: string) =>\n document.cookie\n .split(';')\n .find((c) => c.trim().startsWith(`${name}=`))\n ?.split('=')[1],\n getLocaleStorage: (name: string) => localStorage.getItem(name),\n getSessionStorage: (name: string) => sessionStorage.getItem(name),\n isCookieEnabled: true,\n setCookieStore: (name, value, attributes) =>\n cookieStore.set({\n name,\n value,\n path: attributes.path,\n domain: attributes.domain,\n expires: attributes.expires,\n sameSite: attributes.sameSite,\n }),\n setCookieString: (_name, cookie) => {\n // biome-ignore lint/suspicious/noDocumentCookie: set cookie fallback\n document.cookie = cookie;\n },\n setSessionStorage: (name, value) => sessionStorage.setItem(name, value),\n setLocaleStorage: (name, value) => localStorage.setItem(name, value),\n};\n\n// Default settings for the language detector\ntype LanguageDetectorOptions = {\n order?: LanguageDetector[];\n lookupQuerystring?: string;\n htmlTag?: HTMLElement | null;\n};\n\nconst getDefaultsOptions = (): LanguageDetectorOptions => {\n return {\n order: [\n LanguageDetector.Querystring,\n LanguageDetector.Storage,\n LanguageDetector.Navigator,\n LanguageDetector.HtmlTag,\n ],\n lookupQuerystring: 'locale',\n htmlTag: typeof document !== 'undefined' ? document.documentElement : null,\n };\n};\n\nconst detectLanguage = (\n order: string[],\n options: LanguageDetectorOptions\n): Record<LanguageDetector, Locale | undefined> => {\n const detected: Record<LanguageDetector, Locale | undefined> = {} as Record<\n LanguageDetector,\n Locale | undefined\n >;\n\n const queryStringDetector = () => {\n if (typeof window === 'undefined') return;\n const search = window.location.search || '';\n const params = new URLSearchParams(search);\n const value = params.get(options.lookupQuerystring ?? '');\n if (value) {\n detected[LanguageDetector.Querystring] = value as Locale;\n }\n };\n\n const storageDetector = () => {\n if (typeof window === 'undefined') return;\n\n const locale = getLocaleFromStorage({\n getCookie: (name: string) => {\n try {\n const cookies = document.cookie.split(';');\n const cookieName = `${name}=`;\n\n const cookie = cookies.find((cookie) =>\n cookie.trim().startsWith(cookieName)\n );\n\n if (cookie) {\n return cookie.split('=')[1].trim();\n }\n } catch {}\n return undefined;\n },\n getSessionStorage: (name: string) => {\n try {\n return window.sessionStorage.getItem(name) ?? undefined;\n } catch {}\n return undefined;\n },\n getLocaleStorage: (name: string) => {\n try {\n return window.localStorage.getItem(name) ?? undefined;\n } catch {}\n return undefined;\n },\n });\n\n if (locale) {\n detected[LanguageDetector.Storage] = locale;\n }\n };\n\n const navigatorDetector = () => {\n if (typeof navigator === 'undefined') return;\n\n const { internationalization } = configuration;\n const languages = navigator.languages ?? [navigator.language];\n\n // Use localeDetector to find the best matching locale\n const locale = localeDetector(\n { 'accept-language': languages.join(',') },\n internationalization.locales,\n internationalization.defaultLocale\n );\n\n if (locale) {\n detected[LanguageDetector.Navigator] = locale;\n }\n };\n\n const htmlTagDetector = () => {\n const htmlTag = options.htmlTag;\n if (htmlTag && typeof htmlTag.getAttribute === 'function') {\n const lang = htmlTag.getAttribute('lang');\n if (lang) {\n const { internationalization } = configuration;\n\n // Validate and resolve the locale\n const locale = localeDetector(\n { 'accept-language': lang },\n internationalization.locales,\n internationalization.defaultLocale\n );\n\n detected[LanguageDetector.HtmlTag] = locale;\n }\n }\n };\n\n // Map detector names to their corresponding functions\n const detectors: Record<string, () => void> = {\n [LanguageDetector.Querystring]: queryStringDetector,\n [LanguageDetector.Storage]: storageDetector,\n [LanguageDetector.Navigator]: navigatorDetector,\n [LanguageDetector.HtmlTag]: htmlTagDetector,\n };\n\n // Use the provided order to run each detector\n order.forEach((detectorName) => {\n detectors[detectorName]?.();\n });\n\n return detected;\n};\n\nconst getFirstAvailableLocale = (\n locales: Record<LanguageDetector, Locale | undefined>,\n order: LanguageDetector[]\n): Locale => {\n const { internationalization } = configuration;\n\n for (const detector of order) {\n const locale = locales[detector];\n\n if (locale && internationalization.locales.includes(locale)) {\n return locale;\n }\n }\n\n return internationalization?.defaultLocale ?? Locales.ENGLISH;\n};\n\n/**\n * Core language detector function for browser environments.\n *\n * Detects the user's preferred locale by checking multiple sources in order:\n * 1. Query string parameter\n * 2. Storage (cookies, localStorage, sessionStorage) - uses getLocaleFromStorage\n * 3. Navigator languages - uses localeDetector\n * 4. HTML lang attribute - uses localeDetector\n *\n * @param userOptions - Optional configuration for detection order and lookup keys\n * @returns The detected locale or the default locale\n *\n * @example\n * const locale = getBrowserLocale({ order: [LanguageDetector.Storage, LanguageDetector.Navigator] });\n */\nexport const getBrowserLocale = (\n userOptions: LanguageDetectorOptions | undefined = {}\n): Locale => {\n const options = { ...getDefaultsOptions(), ...userOptions };\n\n const locales = detectLanguage(options.order ?? [], options);\n\n return getFirstAvailableLocale(locales, options.order ?? []);\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{checkIsURLAbsolute as e}from"../utils/checkIsURLAbsolute.mjs";import{getPathWithoutLocale as t}from"./getPathWithoutLocale.mjs";import{getPrefix as n}from"./getPrefix.mjs";import{getCanonicalPath as r,getLocalizedPath as i,getRewriteRules as a}from"./rewriteUtils.mjs";import{DefaultValues as o}from"@intlayer/config/client";import s from"@intlayer/config/built";const c=(c,l,u={})=>{let{defaultLocale:d,mode:f,locales:p,rewrite:m}={defaultLocale:s?.internationalization?.defaultLocale??o.Internationalization.DEFAULT_LOCALE,mode:s?.routing?.mode??o.Routing.ROUTING_MODE,locales:s?.internationalization?.locales??o.Internationalization.LOCALES,rewrite:s?.routing?.rewrite,...u},h=t(c,p),g=a(m,`url`);if(f===`no-prefix`)return i(r(h,void 0,g),l,g).path;let _=e(h),v=_?new URL(h):new URL(h,`http://example.com`),y=_?`${v.protocol}//${v.host}`:``,b=i(r(v.pathname,void 0,g),l,g).path;if(f===`search-params`){let e=new URLSearchParams(v.search);e.set(`locale`,l.toString());let t=e.toString(),n=t?`${b}?${t}`:b;return _?`${y}${n}${v.hash}`:`${n}${v.hash}`}let{prefix:x}=n(l,{defaultLocale:d,mode:f,locales:p}),S=`/${x}${b}`;return S=S.replaceAll(/\/+/g,`/`),S.length>1&&S.endsWith(`/`)&&(S=S.slice(0,-1)),_?`${y}${S}${v.search}${v.hash}`:`${S}${v.search}${v.hash}`};export{c as getLocalizedUrl};
1
+ import{checkIsURLAbsolute as e}from"../utils/checkIsURLAbsolute.mjs";import{getPathWithoutLocale as t}from"./getPathWithoutLocale.mjs";import{getPrefix as n}from"./getPrefix.mjs";import{getCanonicalPath as r,getLocalizedPath as i,getRewriteRules as a}from"./rewriteUtils.mjs";import{DefaultValues as o}from"@intlayer/config/client";import s from"@intlayer/config/built";const c=(c,l=s?.internationalization?.defaultLocale,u={})=>{let{defaultLocale:d,mode:f,locales:p,rewrite:m}={defaultLocale:s?.internationalization?.defaultLocale??o.Internationalization.DEFAULT_LOCALE,mode:s?.routing?.mode??o.Routing.ROUTING_MODE,locales:s?.internationalization?.locales??o.Internationalization.LOCALES,rewrite:s?.routing?.rewrite,...u},h=t(c,p),g=a(m,`url`);if(f===`no-prefix`)return i(r(h,void 0,g),l,g).path;let _=e(h),v=_?new URL(h):new URL(h,`http://example.com`),y=_?`${v.protocol}//${v.host}`:``,b=i(r(v.pathname,void 0,g),l,g).path;if(f===`search-params`){let e=new URLSearchParams(v.search);e.set(`locale`,l.toString());let t=e.toString(),n=t?`${b}?${t}`:b;return _?`${y}${n}${v.hash}`:`${n}${v.hash}`}let{prefix:x}=n(l,{defaultLocale:d,mode:f,locales:p}),S=`/${x}${b}`;return S=S.replaceAll(/\/+/g,`/`),S.length>1&&S.endsWith(`/`)&&(S=S.slice(0,-1)),_?`${y}${S}${v.search}${v.hash}`:`${S}${v.search}${v.hash}`};export{c as getLocalizedUrl};
2
2
  //# sourceMappingURL=getLocalizedUrl.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getLocalizedUrl.mjs","names":[],"sources":["../../../src/localization/getLocalizedUrl.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { DefaultValues } from '@intlayer/config/client';\nimport type { Locale, LocalesValues, RoutingConfig } from '@intlayer/types';\nimport { checkIsURLAbsolute } from '../utils/checkIsURLAbsolute';\nimport { getPathWithoutLocale } from './getPathWithoutLocale';\nimport { getPrefix } from './getPrefix';\nimport {\n getCanonicalPath,\n getLocalizedPath,\n getRewriteRules,\n} from './rewriteUtils';\n\n/**\n * Generate URL by prefixing the given URL with the referenced locale or adding search parameters\n * based on the routing mode. Handles both absolute and relative URLs appropriately.\n *\n * This function gets the locales, default locale, and routing mode from the configuration if not provided.\n *\n * Example:\n *\n * ```ts\n * // prefix-no-default mode\n * getLocalizedUrl('/about', 'fr', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'prefix-no-default' });\n * // Returns '/fr/about' for the French locale\n * // Returns '/about' for the English locale (default)\n *\n * // prefix-all mode\n * getLocalizedUrl('/about', 'en', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'prefix-all' });\n * // Returns '/en/about' for the English locale\n * // Returns '/fr/about' for the French locale\n *\n * // search-params mode\n * getLocalizedUrl('/about', 'fr', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'search-params' });\n * // Returns '/about?locale=fr' for the French locale\n *\n * // no-prefix mode\n * getLocalizedUrl('/about', 'fr', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'no-prefix' });\n * // Returns '/about' for any locale\n * ```\n *\n * @param url - The original URL string to be processed.\n * @param currentLocale - The current locale.\n * @param options - Configuration options\n * @param options.locales - Optional array of supported locales. Defaults to configured locales.\n * @param options.defaultLocale - The default locale. Defaults to configured default locale.\n * @param options.mode - URL routing mode for locale handling. Defaults to configured mode.\n * @returns The localized URL for the current locale.\n */\nexport const getLocalizedUrl = (\n url: string,\n currentLocale: LocalesValues,\n options: {\n locales?: LocalesValues[];\n defaultLocale?: LocalesValues;\n mode?: RoutingConfig['mode'];\n rewrite?: RoutingConfig['rewrite'];\n } = {}\n): string => {\n const { defaultLocale, mode, locales, rewrite } = {\n defaultLocale:\n configuration?.internationalization?.defaultLocale ??\n DefaultValues.Internationalization.DEFAULT_LOCALE,\n mode: configuration?.routing?.mode ?? DefaultValues.Routing.ROUTING_MODE,\n locales:\n configuration?.internationalization?.locales ??\n DefaultValues.Internationalization.LOCALES,\n rewrite: configuration?.routing?.rewrite,\n ...options,\n };\n\n const urlWithoutLocale = getPathWithoutLocale(url, locales);\n\n const urlRewriteRules = getRewriteRules(rewrite, 'url');\n\n if (mode === 'no-prefix') {\n // Resolve to canonical path first from the potentially localized input URL\n const canonicalPathname = getCanonicalPath(\n urlWithoutLocale,\n undefined,\n urlRewriteRules\n );\n\n // Localize the canonical path for the target locale\n return getLocalizedPath(\n canonicalPathname,\n currentLocale as Locale,\n urlRewriteRules\n ).path;\n }\n\n const isAbsoluteUrl = checkIsURLAbsolute(urlWithoutLocale);\n\n const parsedUrl = isAbsoluteUrl\n ? new URL(urlWithoutLocale)\n : new URL(urlWithoutLocale, 'http://example.com');\n\n const baseUrl = isAbsoluteUrl\n ? `${parsedUrl.protocol}//${parsedUrl.host}`\n : '';\n\n // Resolve to canonical path first\n const canonicalPathname = getCanonicalPath(\n parsedUrl.pathname,\n undefined,\n urlRewriteRules\n );\n\n // Localize the canonical path for the target locale\n const translatedPathname = getLocalizedPath(\n canonicalPathname,\n currentLocale as Locale,\n urlRewriteRules\n ).path;\n\n if (mode === 'search-params') {\n const searchParams = new URLSearchParams(parsedUrl.search);\n searchParams.set('locale', currentLocale.toString());\n\n const queryString = searchParams.toString();\n const pathWithQuery = queryString\n ? `${translatedPathname}?${queryString}`\n : translatedPathname;\n\n return isAbsoluteUrl\n ? `${baseUrl}${pathWithQuery}${parsedUrl.hash}`\n : `${pathWithQuery}${parsedUrl.hash}`;\n }\n\n const { prefix } = getPrefix(currentLocale, {\n defaultLocale,\n mode,\n locales,\n });\n\n let localizedPath = `/${prefix}${translatedPathname}`;\n\n localizedPath = localizedPath.replaceAll(/\\/+/g, '/');\n\n if (localizedPath.length > 1 && localizedPath.endsWith('/')) {\n localizedPath = localizedPath.slice(0, -1);\n }\n\n const finalUrl = isAbsoluteUrl\n ? `${baseUrl}${localizedPath}${parsedUrl.search}${parsedUrl.hash}`\n : `${localizedPath}${parsedUrl.search}${parsedUrl.hash}`;\n\n return finalUrl;\n};\n"],"mappings":"kXAgDA,MAAa,GACX,EACA,EACA,EAKI,EAAE,GACK,CACX,GAAM,CAAE,gBAAe,OAAM,UAAS,WAAY,CAChD,cACE,GAAe,sBAAsB,eACrC,EAAc,qBAAqB,eACrC,KAAM,GAAe,SAAS,MAAQ,EAAc,QAAQ,aAC5D,QACE,GAAe,sBAAsB,SACrC,EAAc,qBAAqB,QACrC,QAAS,GAAe,SAAS,QACjC,GAAG,EACJ,CAEK,EAAmB,EAAqB,EAAK,EAAQ,CAErD,EAAkB,EAAgB,EAAS,MAAM,CAEvD,GAAI,IAAS,YASX,OAAO,EAPmB,EACxB,EACA,IAAA,GACA,EACD,CAKC,EACA,EACD,CAAC,KAGJ,IAAM,EAAgB,EAAmB,EAAiB,CAEpD,EAAY,EACd,IAAI,IAAI,EAAiB,CACzB,IAAI,IAAI,EAAkB,qBAAqB,CAE7C,EAAU,EACZ,GAAG,EAAU,SAAS,IAAI,EAAU,OACpC,GAUE,EAAqB,EAPD,EACxB,EAAU,SACV,IAAA,GACA,EACD,CAKC,EACA,EACD,CAAC,KAEF,GAAI,IAAS,gBAAiB,CAC5B,IAAM,EAAe,IAAI,gBAAgB,EAAU,OAAO,CAC1D,EAAa,IAAI,SAAU,EAAc,UAAU,CAAC,CAEpD,IAAM,EAAc,EAAa,UAAU,CACrC,EAAgB,EAClB,GAAG,EAAmB,GAAG,IACzB,EAEJ,OAAO,EACH,GAAG,IAAU,IAAgB,EAAU,OACvC,GAAG,IAAgB,EAAU,OAGnC,GAAM,CAAE,UAAW,EAAU,EAAe,CAC1C,gBACA,OACA,UACD,CAAC,CAEE,EAAgB,IAAI,IAAS,IAYjC,MAVA,GAAgB,EAAc,WAAW,OAAQ,IAAI,CAEjD,EAAc,OAAS,GAAK,EAAc,SAAS,IAAI,GACzD,EAAgB,EAAc,MAAM,EAAG,GAAG,EAG3B,EACb,GAAG,IAAU,IAAgB,EAAU,SAAS,EAAU,OAC1D,GAAG,IAAgB,EAAU,SAAS,EAAU"}
1
+ {"version":3,"file":"getLocalizedUrl.mjs","names":[],"sources":["../../../src/localization/getLocalizedUrl.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { DefaultValues } from '@intlayer/config/client';\nimport type { Locale, LocalesValues, RoutingConfig } from '@intlayer/types';\nimport { checkIsURLAbsolute } from '../utils/checkIsURLAbsolute';\nimport { getPathWithoutLocale } from './getPathWithoutLocale';\nimport { getPrefix } from './getPrefix';\nimport {\n getCanonicalPath,\n getLocalizedPath,\n getRewriteRules,\n} from './rewriteUtils';\n\n/**\n * Generate URL by prefixing the given URL with the referenced locale or adding search parameters\n * based on the routing mode. Handles both absolute and relative URLs appropriately.\n *\n * This function gets the locales, default locale, and routing mode from the configuration if not provided.\n *\n * Example:\n *\n * ```ts\n * // prefix-no-default mode\n * getLocalizedUrl('/about', 'fr', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'prefix-no-default' });\n * // Returns '/fr/about' for the French locale\n * // Returns '/about' for the English locale (default)\n *\n * // prefix-all mode\n * getLocalizedUrl('/about', 'en', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'prefix-all' });\n * // Returns '/en/about' for the English locale\n * // Returns '/fr/about' for the French locale\n *\n * // search-params mode\n * getLocalizedUrl('/about', 'fr', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'search-params' });\n * // Returns '/about?locale=fr' for the French locale\n *\n * // no-prefix mode\n * getLocalizedUrl('/about', 'fr', { locales: ['en', 'fr'], defaultLocale: 'en', mode: 'no-prefix' });\n * // Returns '/about' for any locale\n * ```\n *\n * @param url - The original URL string to be processed.\n * @param currentLocale - The current locale.\n * @param options - Configuration options\n * @param options.locales - Optional array of supported locales. Defaults to configured locales.\n * @param options.defaultLocale - The default locale. Defaults to configured default locale.\n * @param options.mode - URL routing mode for locale handling. Defaults to configured mode.\n * @returns The localized URL for the current locale.\n */\nexport const getLocalizedUrl = (\n url: string,\n currentLocale: LocalesValues = configuration?.internationalization\n ?.defaultLocale,\n options: {\n locales?: LocalesValues[];\n defaultLocale?: LocalesValues;\n mode?: RoutingConfig['mode'];\n rewrite?: RoutingConfig['rewrite'];\n } = {}\n): string => {\n const { defaultLocale, mode, locales, rewrite } = {\n defaultLocale:\n configuration?.internationalization?.defaultLocale ??\n DefaultValues.Internationalization.DEFAULT_LOCALE,\n mode: configuration?.routing?.mode ?? DefaultValues.Routing.ROUTING_MODE,\n locales:\n configuration?.internationalization?.locales ??\n DefaultValues.Internationalization.LOCALES,\n rewrite: configuration?.routing?.rewrite,\n ...options,\n };\n\n const urlWithoutLocale = getPathWithoutLocale(url, locales);\n\n const urlRewriteRules = getRewriteRules(rewrite, 'url');\n\n if (mode === 'no-prefix') {\n // Resolve to canonical path first from the potentially localized input URL\n const canonicalPathname = getCanonicalPath(\n urlWithoutLocale,\n undefined,\n urlRewriteRules\n );\n\n // Localize the canonical path for the target locale\n return getLocalizedPath(\n canonicalPathname,\n currentLocale as Locale,\n urlRewriteRules\n ).path;\n }\n\n const isAbsoluteUrl = checkIsURLAbsolute(urlWithoutLocale);\n\n const parsedUrl = isAbsoluteUrl\n ? new URL(urlWithoutLocale)\n : new URL(urlWithoutLocale, 'http://example.com');\n\n const baseUrl = isAbsoluteUrl\n ? `${parsedUrl.protocol}//${parsedUrl.host}`\n : '';\n\n // Resolve to canonical path first\n const canonicalPathname = getCanonicalPath(\n parsedUrl.pathname,\n undefined,\n urlRewriteRules\n );\n\n // Localize the canonical path for the target locale\n const translatedPathname = getLocalizedPath(\n canonicalPathname,\n currentLocale as Locale,\n urlRewriteRules\n ).path;\n\n if (mode === 'search-params') {\n const searchParams = new URLSearchParams(parsedUrl.search);\n searchParams.set('locale', currentLocale.toString());\n\n const queryString = searchParams.toString();\n const pathWithQuery = queryString\n ? `${translatedPathname}?${queryString}`\n : translatedPathname;\n\n return isAbsoluteUrl\n ? `${baseUrl}${pathWithQuery}${parsedUrl.hash}`\n : `${pathWithQuery}${parsedUrl.hash}`;\n }\n\n const { prefix } = getPrefix(currentLocale, {\n defaultLocale,\n mode,\n locales,\n });\n\n let localizedPath = `/${prefix}${translatedPathname}`;\n\n localizedPath = localizedPath.replaceAll(/\\/+/g, '/');\n\n if (localizedPath.length > 1 && localizedPath.endsWith('/')) {\n localizedPath = localizedPath.slice(0, -1);\n }\n\n const finalUrl = isAbsoluteUrl\n ? `${baseUrl}${localizedPath}${parsedUrl.search}${parsedUrl.hash}`\n : `${localizedPath}${parsedUrl.search}${parsedUrl.hash}`;\n\n return finalUrl;\n};\n"],"mappings":"kXAgDA,MAAa,GACX,EACA,EAA+B,GAAe,sBAC1C,cACJ,EAKI,EAAE,GACK,CACX,GAAM,CAAE,gBAAe,OAAM,UAAS,WAAY,CAChD,cACE,GAAe,sBAAsB,eACrC,EAAc,qBAAqB,eACrC,KAAM,GAAe,SAAS,MAAQ,EAAc,QAAQ,aAC5D,QACE,GAAe,sBAAsB,SACrC,EAAc,qBAAqB,QACrC,QAAS,GAAe,SAAS,QACjC,GAAG,EACJ,CAEK,EAAmB,EAAqB,EAAK,EAAQ,CAErD,EAAkB,EAAgB,EAAS,MAAM,CAEvD,GAAI,IAAS,YASX,OAAO,EAPmB,EACxB,EACA,IAAA,GACA,EACD,CAKC,EACA,EACD,CAAC,KAGJ,IAAM,EAAgB,EAAmB,EAAiB,CAEpD,EAAY,EACd,IAAI,IAAI,EAAiB,CACzB,IAAI,IAAI,EAAkB,qBAAqB,CAE7C,EAAU,EACZ,GAAG,EAAU,SAAS,IAAI,EAAU,OACpC,GAUE,EAAqB,EAPD,EACxB,EAAU,SACV,IAAA,GACA,EACD,CAKC,EACA,EACD,CAAC,KAEF,GAAI,IAAS,gBAAiB,CAC5B,IAAM,EAAe,IAAI,gBAAgB,EAAU,OAAO,CAC1D,EAAa,IAAI,SAAU,EAAc,UAAU,CAAC,CAEpD,IAAM,EAAc,EAAa,UAAU,CACrC,EAAgB,EAClB,GAAG,EAAmB,GAAG,IACzB,EAEJ,OAAO,EACH,GAAG,IAAU,IAAgB,EAAU,OACvC,GAAG,IAAgB,EAAU,OAGnC,GAAM,CAAE,UAAW,EAAU,EAAe,CAC1C,gBACA,OACA,UACD,CAAC,CAEE,EAAgB,IAAI,IAAS,IAYjC,MAVA,GAAgB,EAAc,WAAW,OAAQ,IAAI,CAEjD,EAAc,OAAS,GAAK,EAAc,SAAS,IAAI,GACzD,EAAgB,EAAc,MAAM,EAAG,GAAG,EAG3B,EACb,GAAG,IAAU,IAAgB,EAAU,SAAS,EAAU,OAC1D,GAAG,IAAgB,EAAU,SAAS,EAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"localeDetector.mjs","names":[],"sources":["../../../src/localization/localeDetector.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types';\nimport { localeResolver } from './localeResolver';\n\n/**\n * Constants\n */\nconst LANGUAGE_FORMAT_REGULAR_EXPRESSION =\n /^\\s*([^\\s\\-;]+)(?:-([^\\s;]+))?\\s*(?:;(.*))?$/;\nconst DEFAULT_QUALITY_SCORE = 1;\n\n/**\n * Enumeration for specificity weights.\n * Higher values indicate a more precise match.\n */\nenum SpecificityWeight {\n None = 0,\n Broad = 1, // Matches prefix (e.g., 'en' matches 'en-US')\n Prefix = 2, // Matches prefix in reverse (e.g., 'en-US' matches 'en')\n Exact = 4, // Matches exact string (e.g., 'en-US' matches 'en-US')\n}\n\n/**\n * Represents a parsed language tag from the header.\n */\ntype LanguagePreference = {\n languageCode: string;\n regionCode?: string;\n fullLocale: string;\n qualityScore: number;\n originalIndex: number;\n};\n\n/**\n * Represents the result of matching a requested language against an available language.\n */\ntype MatchResult = {\n providedIndex: number;\n headerIndex: number;\n qualityScore: number;\n specificityScore: number;\n};\n\n/**\n * Parses a single language tag string from the Accept-Language header.\n * Example input: \"en-US;q=0.8\"\n */\nconst parseLanguageTag = (\n tagString: string,\n index: number\n): LanguagePreference | null => {\n const match = LANGUAGE_FORMAT_REGULAR_EXPRESSION.exec(tagString);\n if (!match) {\n return null;\n }\n\n const languageCode = match[1];\n const regionCode = match[2];\n const parameters = match[3];\n\n // Construct the full locale string (e.g., \"en-US\" or \"en\")\n const fullLocale = regionCode\n ? `${languageCode}-${regionCode}`\n : languageCode;\n\n let qualityScore = DEFAULT_QUALITY_SCORE;\n\n // Parse parameters to find the quality score (\"q\")\n if (parameters) {\n const parameterList = parameters.split(';');\n for (const parameter of parameterList) {\n const [key, value] = parameter.split('=');\n if (key === 'q') {\n qualityScore = parseFloat(value);\n }\n }\n }\n\n return {\n languageCode,\n regionCode,\n qualityScore,\n originalIndex: index,\n fullLocale,\n };\n};\n\n/**\n * Parses the entire Accept-Language header string into a list of preferences.\n */\nconst parseAcceptLanguageHeader = (\n headerValue: string\n): LanguagePreference[] => {\n const rawTags = headerValue.split(',');\n const preferences: LanguagePreference[] = [];\n\n for (let index = 0; index < rawTags.length; index++) {\n const tag = rawTags[index].trim();\n const parsedLanguage = parseLanguageTag(tag, index);\n\n if (parsedLanguage) {\n preferences.push(parsedLanguage);\n }\n }\n\n return preferences;\n};\n\n/**\n * Calculates the specificity of a match between a provided language and a requested preference.\n */\nconst calculateMatchSpecificity = (\n providedLanguage: string,\n preference: LanguagePreference,\n providedIndex: number\n): MatchResult | null => {\n const parsedProvided = parseLanguageTag(providedLanguage, providedIndex);\n if (!parsedProvided) {\n return null;\n }\n\n let specificityScore = SpecificityWeight.None;\n\n const preferenceFullLower = preference.fullLocale.toLowerCase();\n const preferencePrefixLower = preference.languageCode.toLowerCase();\n const providedFullLower = parsedProvided.fullLocale.toLowerCase();\n const providedPrefixLower = parsedProvided.languageCode.toLowerCase();\n\n if (preferenceFullLower === providedFullLower) {\n specificityScore |= SpecificityWeight.Exact;\n } else if (preferencePrefixLower === providedFullLower) {\n specificityScore |= SpecificityWeight.Prefix;\n } else if (preferenceFullLower === providedPrefixLower) {\n specificityScore |= SpecificityWeight.Broad;\n } else if (preference.fullLocale !== '*') {\n return null;\n }\n\n return {\n providedIndex,\n headerIndex: preference.originalIndex,\n qualityScore: preference.qualityScore,\n specificityScore,\n };\n};\n\n/**\n * Determines the best match for a specific available language against the list of user accepted languages.\n */\nconst getBestMatchForLanguage = (\n providedLanguage: string,\n acceptedPreferences: LanguagePreference[],\n providedIndex: number\n): MatchResult => {\n // Initialize with a non-match priority\n let bestMatch: MatchResult = {\n headerIndex: -1,\n qualityScore: 0,\n specificityScore: 0,\n providedIndex,\n };\n\n for (const preference of acceptedPreferences) {\n const matchSpec = calculateMatchSpecificity(\n providedLanguage,\n preference,\n providedIndex\n );\n\n if (matchSpec) {\n // Compare current best match with new match\n const scoreDifference =\n bestMatch.specificityScore - matchSpec.specificityScore ||\n bestMatch.qualityScore - matchSpec.qualityScore ||\n bestMatch.headerIndex - matchSpec.headerIndex;\n\n // If the new match is better (difference < 0), update priority\n if (scoreDifference < 0) {\n bestMatch = matchSpec;\n }\n }\n }\n\n return bestMatch;\n};\n\n/**\n * Comparator function to sort language matches.\n * Sorting order:\n * 1. Quality Score (Descending)\n * 2. Specificity Score (Descending)\n * 3. Order in Header (Ascending - lower index is better)\n * 4. Order in Provided List (Ascending)\n */\nconst compareMatchResults = (a: MatchResult, b: MatchResult): number => {\n return (\n b.qualityScore - a.qualityScore ||\n b.specificityScore - a.specificityScore ||\n a.headerIndex - b.headerIndex ||\n a.providedIndex - b.providedIndex ||\n 0\n );\n};\n\n/**\n * Derives the list of preferred languages based on the Accept-Language header\n * and an optional list of available languages.\n */\nexport const getPreferredLanguages = (\n acceptHeader: string | undefined,\n availableLanguages?: string[]\n): string[] => {\n // RFC 2616 sec 14.4: no header implies '*'\n const headerValue = acceptHeader === undefined ? '*' : acceptHeader || '';\n const acceptedPreferences = parseAcceptLanguageHeader(headerValue);\n\n // If no specific languages are provided to filter against, return the header languages sorted by quality\n if (!availableLanguages) {\n return acceptedPreferences\n .filter((preference) => preference.qualityScore > 0)\n .sort((a, b) => b.qualityScore - a.qualityScore) // Simple sort by quality\n .map((preference) => preference.fullLocale);\n }\n\n // Map available languages to their match priority against the header\n const matchResults = availableLanguages.map((language, index) =>\n getBestMatchForLanguage(language, acceptedPreferences, index)\n );\n\n return matchResults\n .filter((result) => result.qualityScore > 0)\n .sort(compareMatchResults)\n .map((result) => availableLanguages[result.providedIndex]);\n};\n\n/**\n * Detects the locale from the request headers.\n *\n * Headers are provided by the browser/client and can be used to determine the user's preferred language.\n * This function intersects the user's `Accept-Language` header with the application's available locales.\n */\nexport const localeDetector = (\n headers: Record<string, string | undefined>,\n availableLocales?: Locale[],\n defaultLocale?: Locale\n): Locale => {\n const acceptLanguageHeader = headers['accept-language'];\n\n const preferredLocaleStrings = getPreferredLanguages(\n acceptLanguageHeader,\n availableLocales as string[]\n );\n\n return localeResolver(\n preferredLocaleStrings as Locale[],\n availableLocales,\n defaultLocale\n );\n};\n"],"mappings":"sDAMA,MAAM,EACJ,+CAOF,IAAK,EAAA,SAAA,EAAL,OACE,GAAA,EAAA,KAAA,GAAA,OACA,EAAA,EAAA,MAAA,GAAA,QACA,EAAA,EAAA,OAAA,GAAA,SACA,EAAA,EAAA,MAAA,GAAA,WAJG,GAAA,EAAA,CAAA,CAgCL,MAAM,GACJ,EACA,IAC8B,CAC9B,IAAM,EAAQ,EAAmC,KAAK,EAAU,CAChE,GAAI,CAAC,EACH,OAAO,KAGT,IAAM,EAAe,EAAM,GACrB,EAAa,EAAM,GACnB,EAAa,EAAM,GAGnB,EAAa,EACf,GAAG,EAAa,GAAG,IACnB,EAEA,EAAe,EAGnB,GAAI,EAAY,CACd,IAAM,EAAgB,EAAW,MAAM,IAAI,CAC3C,IAAK,IAAM,KAAa,EAAe,CACrC,GAAM,CAAC,EAAK,GAAS,EAAU,MAAM,IAAI,CACrC,IAAQ,MACV,EAAe,WAAW,EAAM,GAKtC,MAAO,CACL,eACA,aACA,eACA,cAAe,EACf,aACD,EAMG,EACJ,GACyB,CACzB,IAAM,EAAU,EAAY,MAAM,IAAI,CAChC,EAAoC,EAAE,CAE5C,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAQ,OAAQ,IAAS,CAEnD,IAAM,EAAiB,EADX,EAAQ,GAAO,MAAM,CACY,EAAM,CAE/C,GACF,EAAY,KAAK,EAAe,CAIpC,OAAO,GAMH,GACJ,EACA,EACA,IACuB,CACvB,IAAM,EAAiB,EAAiB,EAAkB,EAAc,CACxE,GAAI,CAAC,EACH,OAAO,KAGT,IAAI,EAAmB,EAAkB,KAEnC,EAAsB,EAAW,WAAW,aAAa,CACzD,EAAwB,EAAW,aAAa,aAAa,CAC7D,EAAoB,EAAe,WAAW,aAAa,CAC3D,EAAsB,EAAe,aAAa,aAAa,CAErE,GAAI,IAAwB,EAC1B,GAAoB,EAAkB,cAC7B,IAA0B,EACnC,GAAoB,EAAkB,eAC7B,IAAwB,EACjC,GAAoB,EAAkB,cAC7B,EAAW,aAAe,IACnC,OAAO,KAGT,MAAO,CACL,gBACA,YAAa,EAAW,cACxB,aAAc,EAAW,aACzB,mBACD,EAMG,GACJ,EACA,EACA,IACgB,CAEhB,IAAI,EAAyB,CAC3B,YAAa,GACb,aAAc,EACd,iBAAkB,EAClB,gBACD,CAED,IAAK,IAAM,KAAc,EAAqB,CAC5C,IAAM,EAAY,EAChB,EACA,EACA,EACD,CAEG,IAGA,EAAU,iBAAmB,EAAU,kBACvC,EAAU,aAAe,EAAU,cACnC,EAAU,YAAc,EAAU,aAGd,IACpB,EAAY,GAKlB,OAAO,GAWH,GAAuB,EAAgB,IAEzC,EAAE,aAAe,EAAE,cACnB,EAAE,iBAAmB,EAAE,kBACvB,EAAE,YAAc,EAAE,aAClB,EAAE,cAAgB,EAAE,eACpB,EAQS,GACX,EACA,IACa,CAGb,IAAM,EAAsB,EADR,IAAiB,IAAA,GAAY,IAAM,GAAgB,GACL,CAelE,OAZK,EAQgB,EAAmB,KAAK,EAAU,IACrD,EAAwB,EAAU,EAAqB,EAAM,CAC9D,CAGE,OAAQ,GAAW,EAAO,aAAe,EAAE,CAC3C,KAAK,EAAoB,CACzB,IAAK,GAAW,EAAmB,EAAO,eAAe,CAdnD,EACJ,OAAQ,GAAe,EAAW,aAAe,EAAE,CACnD,MAAM,EAAG,IAAM,EAAE,aAAe,EAAE,aAAa,CAC/C,IAAK,GAAe,EAAW,WAAW,EAoBpC,GACX,EACA,EACA,IACW,CACX,IAAM,EAAuB,EAAQ,mBAOrC,OAAO,EALwB,EAC7B,EACA,EACD,CAIC,EACA,EACD"}
1
+ {"version":3,"file":"localeDetector.mjs","names":[],"sources":["../../../src/localization/localeDetector.ts"],"sourcesContent":["import type { Locale } from '@intlayer/types';\nimport { localeResolver } from './localeResolver';\n\n/**\n * Constants\n */\nconst LANGUAGE_FORMAT_REGULAR_EXPRESSION =\n /^\\s*([^\\s\\-;]+)(?:-([^\\s;]+))?\\s*(?:;(.*))?$/;\nconst DEFAULT_QUALITY_SCORE = 1;\n\n/**\n * Enumeration for specificity weights.\n * Higher values indicate a more precise match.\n */\nenum SpecificityWeight {\n None = 0,\n Broad = 1, // Matches prefix (e.g., 'en' matches 'en-US')\n Prefix = 2, // Matches prefix in reverse (e.g., 'en-US' matches 'en')\n Exact = 4, // Matches exact string (e.g., 'en-US' matches 'en-US')\n}\n\n/**\n * Represents a parsed language tag from the header.\n */\ntype LanguagePreference = {\n languageCode: string;\n regionCode?: string;\n fullLocale: string;\n qualityScore: number;\n originalIndex: number;\n};\n\n/**\n * Represents the result of matching a requested language against an available language.\n */\ntype MatchResult = {\n providedIndex: number;\n headerIndex: number;\n qualityScore: number;\n specificityScore: number;\n};\n\n/**\n * Parses a single language tag string from the Accept-Language header.\n * Example input: \"en-US;q=0.8\"\n */\nconst parseLanguageTag = (\n tagString: string,\n index: number\n): LanguagePreference | null => {\n const match = LANGUAGE_FORMAT_REGULAR_EXPRESSION.exec(tagString);\n if (!match) {\n return null;\n }\n\n const languageCode = match[1];\n const regionCode = match[2];\n const parameters = match[3];\n\n // Construct the full locale string (e.g., \"en-US\" or \"en\")\n const fullLocale = regionCode\n ? `${languageCode}-${regionCode}`\n : languageCode;\n\n let qualityScore = DEFAULT_QUALITY_SCORE;\n\n // Parse parameters to find the quality score (\"q\")\n if (parameters) {\n const parameterList = parameters.split(';');\n for (const parameter of parameterList) {\n const [key, value] = parameter.split('=');\n if (key === 'q') {\n qualityScore = parseFloat(value);\n }\n }\n }\n\n return {\n languageCode,\n regionCode,\n qualityScore,\n originalIndex: index,\n fullLocale,\n };\n};\n\n/**\n * Parses the entire Accept-Language header string into a list of preferences.\n */\nconst parseAcceptLanguageHeader = (\n headerValue: string\n): LanguagePreference[] => {\n const rawTags = headerValue.split(',');\n const preferences: LanguagePreference[] = [];\n\n for (let index = 0; index < rawTags.length; index++) {\n const tag = rawTags[index].trim();\n const parsedLanguage = parseLanguageTag(tag, index);\n\n if (parsedLanguage) {\n preferences.push(parsedLanguage);\n }\n }\n\n return preferences;\n};\n\n/**\n * Calculates the specificity of a match between a provided language and a requested preference.\n */\nconst calculateMatchSpecificity = (\n providedLanguage: string,\n preference: LanguagePreference,\n providedIndex: number\n): MatchResult | null => {\n const parsedProvided = parseLanguageTag(providedLanguage, providedIndex);\n if (!parsedProvided) {\n return null;\n }\n\n let specificityScore = SpecificityWeight.None;\n\n const preferenceFullLower = preference.fullLocale.toLowerCase();\n const preferencePrefixLower = preference.languageCode.toLowerCase();\n const providedFullLower = parsedProvided.fullLocale.toLowerCase();\n const providedPrefixLower = parsedProvided.languageCode.toLowerCase();\n\n if (preferenceFullLower === providedFullLower) {\n specificityScore |= SpecificityWeight.Exact;\n } else if (preferencePrefixLower === providedFullLower) {\n specificityScore |= SpecificityWeight.Prefix;\n } else if (preferenceFullLower === providedPrefixLower) {\n specificityScore |= SpecificityWeight.Broad;\n } else if (preference.fullLocale !== '*') {\n return null;\n }\n\n return {\n providedIndex,\n headerIndex: preference.originalIndex,\n qualityScore: preference.qualityScore,\n specificityScore,\n };\n};\n\n/**\n * Determines the best match for a specific available language against the list of user accepted languages.\n */\nconst getBestMatchForLanguage = (\n providedLanguage: string,\n acceptedPreferences: LanguagePreference[],\n providedIndex: number\n): MatchResult => {\n // Initialize with a non-match priority\n let bestMatch: MatchResult = {\n headerIndex: -1,\n qualityScore: 0,\n specificityScore: 0,\n providedIndex,\n };\n\n for (const preference of acceptedPreferences) {\n const matchSpec = calculateMatchSpecificity(\n providedLanguage,\n preference,\n providedIndex\n );\n\n if (matchSpec) {\n // Compare current best match with new match\n const scoreDifference =\n bestMatch.specificityScore - matchSpec.specificityScore ||\n bestMatch.qualityScore - matchSpec.qualityScore ||\n bestMatch.headerIndex - matchSpec.headerIndex;\n\n // If the new match is better (difference < 0), update priority\n if (scoreDifference < 0) {\n bestMatch = matchSpec;\n }\n }\n }\n\n return bestMatch;\n};\n\n/**\n * Comparator function to sort language matches.\n * Sorting order:\n * 1. Quality Score (Descending)\n * 2. Specificity Score (Descending)\n * 3. Order in Header (Ascending - lower index is better)\n * 4. Order in Provided List (Ascending)\n */\nconst compareMatchResults = (a: MatchResult, b: MatchResult): number => {\n return (\n b.qualityScore - a.qualityScore ||\n b.specificityScore - a.specificityScore ||\n a.headerIndex - b.headerIndex ||\n a.providedIndex - b.providedIndex ||\n 0\n );\n};\n\n/**\n * Derives the list of preferred languages based on the Accept-Language header\n * and an optional list of available languages.\n */\nexport const getPreferredLanguages = (\n acceptHeader: string | undefined,\n availableLanguages?: string[]\n): string[] => {\n // RFC 2616 sec 14.4: no header implies '*'\n const headerValue = acceptHeader === undefined ? '*' : acceptHeader || '';\n const acceptedPreferences = parseAcceptLanguageHeader(headerValue);\n\n // If no specific languages are provided to filter against, return the header languages sorted by quality\n if (!availableLanguages) {\n return acceptedPreferences\n .filter((preference) => preference.qualityScore > 0)\n .sort((a, b) => b.qualityScore - a.qualityScore) // Simple sort by quality\n .map((preference) => preference.fullLocale);\n }\n\n // Map available languages to their match priority against the header\n const matchResults = availableLanguages.map((language, index) =>\n getBestMatchForLanguage(language, acceptedPreferences, index)\n );\n\n return matchResults\n .filter((result) => result.qualityScore > 0)\n .sort(compareMatchResults)\n .map((result) => availableLanguages[result.providedIndex]);\n};\n\n/**\n * Detects the locale from the request headers.\n *\n * Headers are provided by the browser/client and can be used to determine the user's preferred language.\n * This function intersects the user's `Accept-Language` header with the application's available locales.\n */\nexport const localeDetector = (\n headers: Record<string, string | undefined>,\n availableLocales?: Locale[],\n defaultLocale?: Locale\n): Locale => {\n const acceptLanguageHeader = headers['accept-language'];\n\n const preferredLocaleStrings = getPreferredLanguages(\n acceptLanguageHeader,\n availableLocales as string[]\n );\n\n return localeResolver(\n preferredLocaleStrings as Locale[],\n availableLocales,\n defaultLocale\n );\n};\n"],"mappings":"sDAMA,MAAM,EACJ,+CAOF,IAAK,EAAL,SAAA,EAAA,OACE,GAAA,EAAA,KAAA,GAAA,OACA,EAAA,EAAA,MAAA,GAAA,QACA,EAAA,EAAA,OAAA,GAAA,SACA,EAAA,EAAA,MAAA,GAAA,WAJG,GAAA,EAAA,CAKJ,CA2BD,MAAM,GACJ,EACA,IAC8B,CAC9B,IAAM,EAAQ,EAAmC,KAAK,EAAU,CAChE,GAAI,CAAC,EACH,OAAO,KAGT,IAAM,EAAe,EAAM,GACrB,EAAa,EAAM,GACnB,EAAa,EAAM,GAGnB,EAAa,EACf,GAAG,EAAa,GAAG,IACnB,EAEA,EAAe,EAGnB,GAAI,EAAY,CACd,IAAM,EAAgB,EAAW,MAAM,IAAI,CAC3C,IAAK,IAAM,KAAa,EAAe,CACrC,GAAM,CAAC,EAAK,GAAS,EAAU,MAAM,IAAI,CACrC,IAAQ,MACV,EAAe,WAAW,EAAM,GAKtC,MAAO,CACL,eACA,aACA,eACA,cAAe,EACf,aACD,EAMG,EACJ,GACyB,CACzB,IAAM,EAAU,EAAY,MAAM,IAAI,CAChC,EAAoC,EAAE,CAE5C,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAQ,OAAQ,IAAS,CAEnD,IAAM,EAAiB,EADX,EAAQ,GAAO,MAAM,CACY,EAAM,CAE/C,GACF,EAAY,KAAK,EAAe,CAIpC,OAAO,GAMH,GACJ,EACA,EACA,IACuB,CACvB,IAAM,EAAiB,EAAiB,EAAkB,EAAc,CACxE,GAAI,CAAC,EACH,OAAO,KAGT,IAAI,EAAmB,EAAkB,KAEnC,EAAsB,EAAW,WAAW,aAAa,CACzD,EAAwB,EAAW,aAAa,aAAa,CAC7D,EAAoB,EAAe,WAAW,aAAa,CAC3D,EAAsB,EAAe,aAAa,aAAa,CAErE,GAAI,IAAwB,EAC1B,GAAoB,EAAkB,cAC7B,IAA0B,EACnC,GAAoB,EAAkB,eAC7B,IAAwB,EACjC,GAAoB,EAAkB,cAC7B,EAAW,aAAe,IACnC,OAAO,KAGT,MAAO,CACL,gBACA,YAAa,EAAW,cACxB,aAAc,EAAW,aACzB,mBACD,EAMG,GACJ,EACA,EACA,IACgB,CAEhB,IAAI,EAAyB,CAC3B,YAAa,GACb,aAAc,EACd,iBAAkB,EAClB,gBACD,CAED,IAAK,IAAM,KAAc,EAAqB,CAC5C,IAAM,EAAY,EAChB,EACA,EACA,EACD,CAEG,IAGA,EAAU,iBAAmB,EAAU,kBACvC,EAAU,aAAe,EAAU,cACnC,EAAU,YAAc,EAAU,aAGd,IACpB,EAAY,GAKlB,OAAO,GAWH,GAAuB,EAAgB,IAEzC,EAAE,aAAe,EAAE,cACnB,EAAE,iBAAmB,EAAE,kBACvB,EAAE,YAAc,EAAE,aAClB,EAAE,cAAgB,EAAE,eACpB,EAQS,GACX,EACA,IACa,CAGb,IAAM,EAAsB,EADR,IAAiB,IAAA,GAAY,IAAM,GAAgB,GACL,CAelE,OAZK,EAQgB,EAAmB,KAAK,EAAU,IACrD,EAAwB,EAAU,EAAqB,EAAM,CAC9D,CAGE,OAAQ,GAAW,EAAO,aAAe,EAAE,CAC3C,KAAK,EAAoB,CACzB,IAAK,GAAW,EAAmB,EAAO,eAAe,CAdnD,EACJ,OAAQ,GAAe,EAAW,aAAe,EAAE,CACnD,MAAM,EAAG,IAAM,EAAE,aAAe,EAAE,aAAa,CAC/C,IAAK,GAAe,EAAW,WAAW,EAoBpC,GACX,EACA,EACA,IACW,CACX,IAAM,EAAuB,EAAQ,mBAOrC,OAAO,EALwB,EAC7B,EACA,EACD,CAIC,EACA,EACD"}
@@ -1,13 +1,13 @@
1
- import{ATTRIBUTE_TO_NODE_PROP_MAP as e,ATTR_EXTRACTOR_R as t,BLOCKQUOTE_ALERT_R as n,BLOCKQUOTE_R as r,BLOCKQUOTE_TRIM_LEFT_MULTILINE_R as i,BLOCK_END_R as a,BREAK_LINE_R as o,BREAK_THEMATIC_R as s,CODE_BLOCK_FENCED_R as c,CODE_BLOCK_R as l,CODE_INLINE_R as u,CONSECUTIVE_NEWLINE_R as d,CUSTOM_COMPONENT_R as f,DO_NOT_PROCESS_HTML_ELEMENTS as p,FOOTNOTE_R as m,FOOTNOTE_REFERENCE_R as h,FRONT_MATTER_R as g,GFM_TASK_R as _,HEADING_ATX_COMPLIANT_R as ee,HEADING_R as te,HEADING_SETEXT_R as v,HTML_BLOCK_ELEMENT_R as y,HTML_CHAR_CODE_R as b,HTML_COMMENT_R as ne,HTML_LEFT_TRIM_AMOUNT_R as x,HTML_SELF_CLOSING_ELEMENT_R as S,LINK_AUTOLINK_BARE_URL_R as C,LINK_AUTOLINK_R as w,LIST_LOOKBEHIND_R as T,NAMED_CODES_TO_UNICODE as E,NP_TABLE_R as D,ORDERED as O,ORDERED_LIST_ITEM_PREFIX_R as re,ORDERED_LIST_ITEM_R as ie,ORDERED_LIST_R as ae,PARAGRAPH_R as oe,Priority as k,REFERENCE_IMAGE_OR_LINK as se,REFERENCE_IMAGE_R as ce,REFERENCE_LINK_R as le,RuleType as A,SHORTCODE_R as ue,SHOULD_RENDER_AS_BLOCK_R as j,TEXT_BOLD_R as de,TEXT_EMPHASIZED_R as fe,TEXT_ESCAPED_R as pe,TEXT_MARKED_R as me,TEXT_PLAIN_R as he,TEXT_STRIKETHROUGHED_R as ge,TRIM_STARTING_NEWLINES as M,UNORDERED as _e,UNORDERED_LIST_ITEM_PREFIX_R as ve,UNORDERED_LIST_ITEM_R as ye,UNORDERED_LIST_R as N}from"./constants.mjs";import{allowInline as P,anyScopeRegex as F,attributeValueToNodePropValue as I,blockRegex as L,captureNothing as R,cx as z,get as B,inlineRegex as V,normalizeAttributeKey as H,parseBlock as U,parseCaptureInline as W,parseInline as G,parseSimpleInline as be,parseTableAlign as xe,parseTableCells as Se,parseTableRow as Ce,renderNothing as K,sanitizer as we,simpleInlineRegex as q,slugify as J,some as Te,startsWith as Ee,trimEnd as Y,trimLeadingWhitespaceOutsideFences as X,unescapeString as Z,unquote as De}from"./utils.mjs";import{parserFor as Q}from"./parser.mjs";import{createRenderer as Oe,renderFor as ke}from"./renderer.mjs";const Ae=/^!\[(.*?)\]\( *((?:\([^)]*\)|[^() ])*) *"?([^)"]*)?"?\)/,je=RegExp(`^\\[((?:\\[[^\\[\\]]*(?:\\[[^\\[\\]]*\\][^\\[\\]]*)*\\]|[^\\[\\]])*)\\]\\(\\s*<?((?:\\([^)]*\\)|[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['"]([\\s\\S]*?)['"])?\\s*\\)`),Me=(e,t)=>{if(typeof e!=`string`)return e;let n=B(t,e);if(!n&&typeof e==`string`){let r=e.toLowerCase(),i=Object.keys(t).find(e=>e.toLowerCase()===r);i&&(n=B(t,i))}return n||e},Ne=(e,t)=>{let{runtime:n,components:r={}}=e,i=t.tagfilter?[`title`,`textarea`,`style`,`xmp`,`iframe`,`noembed`,`noframes`,`script`,`plaintext`]:[];return(e,t,...a)=>{if(typeof e==`string`&&i.includes(e.toLowerCase()))return null;let o=typeof e==`string`,s=z(t?.className,t?.class),c={},l=!1;if(t)for(let e in t){let n=t[e];n!=null&&(e===`className`||e===`class`?l||=(s&&(c.className=s),!0):c[e]=n)}!l&&s&&(c.className=s);let u=c;n.normalizeProps&&o&&(u=n.normalizeProps(e,c));let d=Me(e,r);return n.createElement(d,u,...a.length===1?[a[0]]:a)}},Pe=(e,t,g,oe,j,M,I,z)=>{let B=e=>t.slugify?t.slugify(e,J):J(e),H=t.sanitizer??we,De=t.namedCodesToUnicode?{...E,...t.namedCodesToUnicode}:E,Q=t=>{let n=t===O,r=n?ae:N,i=n?ie:ye,o=n?re:ve;return{_qualify:e=>o.test(e),_match:P((e,t)=>{let n=T.exec(t.prevCapture??``),i=t.list??(!t.inline&&!t.simple);if(n&&i){let t=(n[1]||``)+e;return r.exec(t)}return null}),_order:k.HIGH,_parse(e,t,r){let s=e[2],c=n?+s.slice(0,-1):void 0,l=e[0].replace(a,`
1
+ import{ATTRIBUTE_TO_NODE_PROP_MAP as e,ATTR_EXTRACTOR_R as t,BLOCKQUOTE_ALERT_R as n,BLOCKQUOTE_R as r,BLOCKQUOTE_TRIM_LEFT_MULTILINE_R as i,BLOCK_END_R as a,BREAK_LINE_R as o,BREAK_THEMATIC_R as s,CODE_BLOCK_FENCED_R as c,CODE_BLOCK_R as l,CODE_INLINE_R as u,CONSECUTIVE_NEWLINE_R as d,CUSTOM_COMPONENT_R as f,DO_NOT_PROCESS_HTML_ELEMENTS as p,FOOTNOTE_R as m,FOOTNOTE_REFERENCE_R as h,FRONT_MATTER_R as g,GFM_TASK_R as _,HEADING_ATX_COMPLIANT_R as ee,HEADING_R as te,HEADING_SETEXT_R as ne,HTML_BLOCK_ELEMENT_R as v,HTML_CHAR_CODE_R as y,HTML_COMMENT_R as re,HTML_LEFT_TRIM_AMOUNT_R as b,HTML_SELF_CLOSING_ELEMENT_R as x,LINK_AUTOLINK_BARE_URL_R as S,LINK_AUTOLINK_R as C,LIST_LOOKBEHIND_R as w,NAMED_CODES_TO_UNICODE as T,NP_TABLE_R as E,ORDERED_LIST_ITEM_PREFIX_R as ie,ORDERED_LIST_ITEM_R as ae,ORDERED_LIST_R as D,PARAGRAPH_R as O,Priority as k,REFERENCE_IMAGE_OR_LINK as oe,REFERENCE_IMAGE_R as se,REFERENCE_LINK_R as ce,RuleType as A,SHORTCODE_R as le,SHOULD_RENDER_AS_BLOCK_R as j,TEXT_BOLD_R as ue,TEXT_EMPHASIZED_R as de,TEXT_ESCAPED_R as fe,TEXT_MARKED_R as pe,TEXT_PLAIN_R as me,TEXT_STRIKETHROUGHED_R as he,TRIM_STARTING_NEWLINES as M,UNORDERED_LIST_ITEM_PREFIX_R as ge,UNORDERED_LIST_ITEM_R as _e,UNORDERED_LIST_R as N}from"./constants.mjs";import{allowInline as P,anyScopeRegex as F,attributeValueToNodePropValue as I,blockRegex as L,captureNothing as R,cx as z,get as B,inlineRegex as V,normalizeAttributeKey as H,parseBlock as U,parseCaptureInline as W,parseInline as G,parseSimpleInline as ve,parseTableAlign as ye,parseTableCells as be,parseTableRow as xe,renderNothing as K,sanitizer as Se,simpleInlineRegex as q,slugify as J,some as Ce,startsWith as we,trimEnd as Y,trimLeadingWhitespaceOutsideFences as Te,unescapeString as X,unquote as Ee}from"./utils.mjs";import{parserFor as Z}from"./parser.mjs";import{createRenderer as Q,renderFor as De}from"./renderer.mjs";const Oe=/^!\[(.*?)\]\( *((?:\([^)]*\)|[^() ])*) *"?([^)"]*)?"?\)/,ke=RegExp(`^\\[((?:\\[[^\\[\\]]*(?:\\[[^\\[\\]]*\\][^\\[\\]]*)*\\]|[^\\[\\]])*)\\]\\(\\s*<?((?:\\([^)]*\\)|[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['"]([\\s\\S]*?)['"])?\\s*\\)`),Ae=(e,t)=>{if(typeof e!=`string`)return e;let n=B(t,e);if(!n&&typeof e==`string`){let r=e.toLowerCase(),i=Object.keys(t).find(e=>e.toLowerCase()===r);i&&(n=B(t,i))}return n||e},je=(e,t)=>{let{runtime:n,components:r={}}=e,i=t.tagfilter?[`title`,`textarea`,`style`,`xmp`,`iframe`,`noembed`,`noframes`,`script`,`plaintext`]:[];return(e,t,...a)=>{if(typeof e==`string`&&i.includes(e.toLowerCase()))return null;let o=typeof e==`string`,s=z(t?.className,t?.class),c={},l=!1;if(t)for(let e in t){let n=t[e];n!=null&&(e===`className`||e===`class`?l||=(s&&(c.className=s),!0):c[e]=n)}!l&&s&&(c.className=s);let u=c;n.normalizeProps&&o&&(u=n.normalizeProps(e,c));let d=Ae(e,r);return n.createElement(d,u,...a.length===1?[a[0]]:a)}},Me=(e,t,g,O,j,M,I,z)=>{let B=e=>t.slugify?t.slugify(e,J):J(e),H=t.sanitizer??Se,Ee=t.namedCodesToUnicode?{...T,...t.namedCodesToUnicode}:T,Z=t=>{let n=t===1,r=n?D:N,i=n?ae:_e,o=n?ie:ge;return{_qualify:e=>o.test(e),_match:P((e,t)=>{let n=w.exec(t.prevCapture??``),i=t.list??(!t.inline&&!t.simple);if(n&&i){let t=(n[1]||``)+e;return r.exec(t)}return null}),_order:k.HIGH,_parse(e,t,r){let s=e[2],c=n?+s.slice(0,-1):void 0,l=e[0].replace(a,`
2
2
  `).match(i);if(!l)return{items:[],ordered:n,start:c};let u=!1;return{items:l.map((e,n)=>{let i=o.exec(e),a=i?i[0].length:0,s=RegExp(`^ {1,${a}}`,`gm`),c=e.replace(s,``).replace(o,``),d=n===l.length-1,f=c.indexOf(`
3
3
 
4
- `)!==-1||d&&u;u=f;let p=r.inline,m=r.list;r.list=!0;let h;f?(r.inline=!1,h=`${Y(c)}\n\n`):(r.inline=!0,h=Y(c));let g=t(h,r);return r.inline=p,r.list=m,g}),ordered:n,start:c}},_render(t,n,r={}){let i=t.ordered?`ol`:`ul`,a={key:r.key};return t.ordered&&t.start!=null&&(a.start=t.start),e(i,a,...t.items.map((t,i)=>e(`li`,{key:i},n(t,r))))}}},Oe=(e,t)=>{if(t.inline||t.simple||t.inHTML&&e.indexOf(`
4
+ `)!==-1||d&&u;u=f;let p=r.inline,m=r.list;r.list=!0;let h;f?(r.inline=!1,h=`${Y(c)}\n\n`):(r.inline=!0,h=Y(c));let g=t(h,r);return r.inline=p,r.list=m,g}),ordered:n,start:c}},_render(t,n,r={}){let i=t.ordered?`ol`:`ul`,a={key:r.key};return t.ordered&&t.start!=null&&(a.start=t.start),e(i,a,...t.items.map((t,i)=>e(`li`,{key:i},n(t,r))))}}},Q=(e,t)=>{if(t.inline||t.simple||t.inHTML&&e.indexOf(`
5
5
 
6
6
  `)===-1&&t.prevCapture?.indexOf(`
7
7
 
8
8
  `)===-1)return null;let n=0;for(;;){let t=e.indexOf(`
9
- `,n),r=e.slice(n,t===-1?void 0:t+1);if(Te(z,r)||t===-1||!r.trim())break;n=t+1}let r=e.slice(0,n);if(r===``)return null;let i=Y(r);return i===``?null:[r,void 0,i]};return{[A.blockQuote]:{_qualify:[`>`],_match:L(r),_order:k.HIGH,_parse(e,t,r){let a=e[0].replace(i,``).match(n),o=a?.[1],s=a?.[2]??``;return{alert:o,children:s.indexOf(`
10
- `)===-1?G(t,s,r):U(t,s,r)}},_render(t,n,r={}){let i={key:r.key};return t.alert&&(i.className=`markdown-alert-${B(t.alert.toLowerCase())}`,t.children.unshift({attrs:{},children:[{type:A.text,text:t.alert}],noInnerParse:!0,type:A.htmlBlock,tag:`header`})),e(`blockquote`,i,n(t.children,r))}},[A.breakLine]:{_qualify:[` `],_match:F(o),_order:k.HIGH,_parse:R,_render(t,n,r={}){return e(`br`,{key:r.key})}},[A.breakThematic]:{_qualify:[`--`,`__`,`**`,`- `,`* `,`_ `],_match:L(s),_order:k.HIGH,_parse:R,_render(t,n,r={}){return e(`hr`,{key:r.key})}},[A.codeBlock]:{_qualify:[` `],_match:L(l),_order:k.MAX,_parse(e){return{type:A.codeBlock,lang:void 0,text:Z(Y(e[0].replace(/^ {4}/gm,``)))}},_render(t,n,r={}){let i={...t.attrs??{}},a=t.lang?`lang-${t.lang}`:`lang-plaintext`;return i.className=i.className?`${i.className} ${a}`:a,t.lang&&!i.lang&&(i.lang=t.lang),e(`pre`,{key:r.key},e(`code`,i,t.text))}},[A.codeFenced]:{_qualify:["```",`~~~`],_match:L(c),_order:k.MAX,_parse(e){return{attrs:M(`code`,e[3]??``),lang:e[2]||void 0,text:e[4],type:A.codeBlock}}},[A.codeInline]:{_qualify:["`"],_match:q(u),_order:k.LOW,_parse(e){return{text:Z(e[2])}},_render(t,n,r={}){return e(`code`,{key:r.key},t.text)}},[A.footnote]:{_qualify:[`[^`],_match:L(m),_order:k.MAX,_parse(e){return oe.push({footnote:e[2],identifier:e[1]}),{}},_render:K},[A.footnoteReference]:{_qualify:[`[^`],_match:V(h),_order:k.HIGH,_parse(e){return{target:`#${B(e[1])}`,text:e[1]}},_render(t,n,r={}){return e(`a`,{key:r.key,href:H(t.target,`a`,`href`)??void 0},e(`sup`,{key:r.key},t.text))}},[A.gfmTask]:{_qualify:[`[ ]`,`[x]`],_match:V(_),_order:k.HIGH,_parse(e){return{completed:e[1].toLowerCase()===`x`}},_render(t,n,r={}){return e(`input`,{checked:t.completed,key:r.key,readOnly:!0,type:`checkbox`})}},[A.heading]:{_qualify:[`#`],_match:L(g.enforceAtxHeadings?ee:te),_order:k.HIGH,_parse(e,t,n){return{children:G(t,e[2],n),id:B(e[2]),level:e[1].length}},_render(t,n,r={}){return e(`h${t.level}`,{id:t.id,key:r.key},n(t.children,r))}},[A.headingSetext]:{_qualify:e=>{let t=e.indexOf(`
11
- `);return t>0&&t<e.length-1&&(e[t+1]===`=`||e[t+1]===`-`)},_match:L(v),_order:k.MAX,_parse(e,t,n){return{children:G(t,e[1],n),level:e[2]===`=`?1:2,type:A.heading}}},[A.htmlBlock]:{_qualify:e=>{if(g.disableParsingRawHTML)return!1;let t=e.match(/^ *<([a-z][a-z0-9:-]*)\b/i);if(!t)return!1;let n=t[1];return e.toLowerCase().indexOf(`</${n.toLowerCase()}>`)!==-1},_match:F(y),_order:k.HIGH,_parse(e,t,n){let r=e[3].match(x)?.[1]??``,i=X(e[3],r),a=I(i)?U:G,o=e[1].trim(),s=p.indexOf(o.toLowerCase())!==-1,c=s?o.toLowerCase():o,l={attrs:M(c,e[2]??``),noInnerParse:s,tag:c};if(n.inAnchor=n.inAnchor||o.toLowerCase()===`a`,s)l.text=e[3];else{let e=n.inHTML;n.inHTML=!0,l.children=a(t,i,n),n.inHTML=e}return n.inAnchor=!1,l},_render(t,n,r={}){return e(t.tag,{key:r.key,...t.attrs??{}},t.text??(t.children?n(t.children,r):``))}},[A.htmlComment]:{_qualify:[`<!`],_match:F(ne),_order:k.HIGH,_parse:R,_render:K},[A.htmlSelfClosing]:{_qualify:e=>g.disableParsingRawHTML?!1:/^ *<([a-zA-Z][a-zA-Z0-9:]*)[\s>/]/.test(e),_match:F(S),_order:k.HIGH,_parse(e){let t=e[1].trim();return{attrs:M(t,e[2]||``),tag:t}},_render(t,n,r={}){return e(t.tag,{key:r.key,...t.attrs??{}})}},[A.customComponent]:{_qualify:e=>/^ *<([A-Z][a-zA-Z0-9]*)/.test(e),_match:F(f),_order:k.MAX,_parse(e,t,n){let r=e[3].match(x)?.[1]??``,i=X(e[3],r),a=I(i)?U:G,o=e[1].trim(),s={attrs:M(o,e[2]??``),noInnerParse:!1,tag:o},c=n.inHTML;return n.inHTML=!0,s.children=a(t,i,n),n.inHTML=c,s},_render(t,n,r={}){return e(t.tag,{key:r.key,...t.attrs??{}},t.text??(t.children?n(t.children,r):``))}},[A.paragraph]:{_match:Oe,_order:k.LOW,_parse:W,_render(t,n,r={}){return e(`p`,{key:r.key},n(t.children,r))}},[A.image]:{_qualify:[`![`],_match:q(Ae),_order:k.HIGH,_parse(e){return{alt:Z(e[1]),target:Z(e[2]),title:Z(e[3])}},_render(t,n,r={}){return e(`img`,{key:r.key,alt:t.alt??void 0,title:t.title??void 0,src:H(t.target,`img`,`src`)??void 0})}},[A.link]:{_qualify:[`[`],_match:V(je),_order:k.LOW,_parse(e,t,n){return{children:be(t,e[1],n),target:Z(e[2]),title:Z(e[3])}},_render(t,n,r={}){let i=H(t.target,`a`,`href`);return e(`a`,{key:r.key,href:i??void 0,title:t.title??void 0},n(t.children,r))}},[A.linkAngleBraceStyleDetector]:{_qualify:[`<`],_match:V(w),_order:k.MAX,_parse(e){let t=e[1],n=!1;return t.indexOf(`@`)!==-1&&t.indexOf(`//`)===-1&&(n=!0,t=t.replace(`mailto:`,``)),{children:[{text:t,type:A.text}],target:n?`mailto:${t}`:t,type:A.link}}},[A.linkBareUrlDetector]:{_qualify:(e,t)=>!!(t.inline&&!t.inAnchor&&!g.disableAutoLink&&(Ee(e,`http://`)||Ee(e,`https://`))),_match:V(C),_order:k.MAX,_parse(e){return{children:[{text:e[1],type:A.text}],target:e[1],type:A.link}}},[A.newlineCoalescer]:{_match:L(d),_order:k.LOW,_parse:R,_render(){return`
12
- `}},[A.orderedList]:Q(O),[A.unorderedList]:Q(_e),[A.ref]:{_qualify:[`[`],_match:F(se),_order:k.MAX,_parse(e){return j[e[1]]={target:e[2],title:e[4]},{}},_render:K},[A.refImage]:{_qualify:[`![`],_match:q(ce),_order:k.MAX,_parse(e){return{alt:e[1]?Z(e[1]):void 0,ref:e[2]}},_render(t,n,r={}){let i=j[t.ref];return i?e(`img`,{key:r.key,alt:t.alt,src:H(i.target,`img`,`src`)??void 0,title:i.title}):null}},[A.refLink]:{_qualify:e=>e[0]===`[`&&e.indexOf(`](`)===-1,_match:V(le),_order:k.MAX,_parse(e,t,n){return{children:be(t,e[1],n),fallbackChildren:e[0],ref:e[2]}},_render(t,n,r={}){let i=j[t.ref];return i?e(`a`,{key:r.key,href:H(i.target,`a`,`href`)??void 0,title:i.title},n(t.children,r)):e(`span`,{key:r.key},t.fallbackChildren)}},[A.table]:{_qualify:[`|`],_match:L(D),_order:k.HIGH,_parse(e,t,n){n.inline=!0;let r=e[2]?xe(e[2]):[],i=e[3]?Se(e[3],t,n):[],a=Ce(e[1],t,n,!!i.length);return n.inline=!1,i.length?{align:r,cells:i,header:a,type:A.table}:{children:a.flat(),type:A.paragraph}},_render(t,n,r={}){let i=t,a=e=>i.align[e]?{textAlign:i.align[e]}:{};return e(`table`,{key:r.key},e(`thead`,null,e(`tr`,null,...i.header.map((t,i)=>e(`th`,{key:i,style:a(i)},n(t,r))))),e(`tbody`,null,...i.cells.map((t,i)=>e(`tr`,{key:i},...t.map((t,i)=>e(`td`,{key:i,style:a(i)},n(t,r)))))))}},[A.tableSeparator]:{_match:(e,t)=>t.inTable&&e[0]===`|`?/^\|/.exec(e):null,_order:k.HIGH,_parse(){return{type:A.tableSeparator}},_render(){return` | `}},[A.text]:{_match:P((e,t)=>ue.exec(e)||he.exec(e)||/^[\s\S]/.exec(e)),_order:k.MIN,_parse(e){let t=e[0];return{text:t.indexOf(`&`)===-1?t:t.replace(b,(e,t)=>De[t]||e)}},_render(e){return e.text}},[A.textBolded]:{_qualify:[`**`,`__`],_match:q(de),_order:k.MED,_parse(e,t,n){return{children:t(e[2],n)}},_render(t,n,r={}){return e(`strong`,{key:r.key},n(t.children,r))}},[A.textEmphasized]:{_qualify:[`*`,`_`],_match:q(fe),_order:k.LOW,_parse(e,t,n){return{children:t(e[2],n)}},_render(t,n,r={}){return e(`em`,{key:r.key},n(t.children,r))}},[A.textEscaped]:{_qualify:[`\\`],_match:q(pe),_order:k.HIGH,_parse(e){return{text:e[1],type:A.text}}},[A.textMarked]:{_qualify:[`==`],_match:q(me),_order:k.LOW,_parse:W,_render(t,n,r={}){return e(`mark`,{key:r.key},n(t.children,r))}},[A.textStrikethroughed]:{_qualify:[`~~`],_match:q(ge),_order:k.LOW,_parse:W,_render(t,n,r={}){return e(`del`,{key:r.key},n(t.children,r))}}}},$=(n=``,i,a={})=>{let o=i.components??{},s=e=>i.slugify?i.slugify(e,J):J(e),u=Ne(i,a),d=[],p={},m=(n,r)=>{if(!r||!r.trim())return null;let a=r.match(t);return a?a.reduce((t,r)=>{let a=r.indexOf(`=`);if(a!==-1){let o=H(r.slice(0,a)).trim(),s=De(r.slice(a+1).trim()),c=e[o]??o;if(c===`ref`)return t;t[c]=I(n,o,s,i.sanitizer??we),typeof t[c]==`string`&&(y.test(t[c])||S.test(t[c]))&&(t[c]=w(t[c].trim()))}else r!==`style`&&(t[e[r]??r]=!0);return t},{}):null},h=[r,c,l,a.enforceAtxHeadings?ee:te,v,D,ae,N,f],_=Pe(u,i,a,d,p,m,e=>{let t=e.replace(M,``),n=t.length>2048?t.slice(0,2048):t;return Te(a.disableParsingRawHTML?h:[...h,oe,y,ne,S,f],n)},h),b=a.disableParsingRawHTML?Object.keys(_).reduce((e,t)=>(t!==A.htmlBlock&&t!==A.htmlSelfClosing&&(e[t]=_[t]),e),{}):_,x=Q(b),C=ke(Oe(b,a.renderRule)),w=e=>{let t=a.preserveFrontmatter?e:e.replace(g,``),n=a.forceInline||!a.forceBlock&&j.test(t.replace(M,``))===!1,r=C(x(n?t:`${Y(t).replace(M,``)}\n\n`,{inline:n}),{inline:n});for(;typeof r[r.length-1]==`string`&&!r[r.length-1].trim();)r.pop();if(a.wrapper===null)return r;let i=a.wrapper??(n?`span`:`div`);if(r.length>1||a.forceWrapper)return u(i,{key:`outer`},r);if(r.length===1){let e=r[0];if(typeof e==`string`){let t={key:`outer`};if(!n&&o){let n=B(o,`p.props`,{})??{},r=z(t.className,n.className),i={...t,...n};return r&&(i.className=r),u(`span`,i,e)}return u(`span`,t,e)}return e}return u(i,{key:`outer`},null)};if(typeof n!=`string`)throw Error(`intlayer: the first argument must be a string`);let T=w(n);return d.length?u(`div`,null,T,u(`footer`,{key:`footer`},...d.map(e=>u(`div`,{id:s(e.identifier),key:e.identifier},e.identifier,C(x(e.footnote,{inline:!0}),{inline:!0}))))):T},Fe=e=>(t,n)=>$(t,e,n),Ie=(e,t,n={})=>{let{components:r,namedCodesToUnicode:i,sanitizer:a,slugify:o,...s}=n;return $(e,{runtime:t,components:r,namedCodesToUnicode:i,sanitizer:a,slugify:o},s)};export{$ as compile,Ie as compileWithOptions,Fe as createCompiler};
9
+ `,n),r=e.slice(n,t===-1?void 0:t+1);if(Ce(z,r)||t===-1||!r.trim())break;n=t+1}let r=e.slice(0,n);if(r===``)return null;let i=Y(r);return i===``?null:[r,void 0,i]};return{[A.blockQuote]:{_qualify:[`>`],_match:L(r),_order:k.HIGH,_parse(e,t,r){let a=e[0].replace(i,``).match(n),o=a?.[1],s=a?.[2]??``;return{alert:o,children:s.indexOf(`
10
+ `)===-1?G(t,s,r):U(t,s,r)}},_render(t,n,r={}){let i={key:r.key};return t.alert&&(i.className=`markdown-alert-${B(t.alert.toLowerCase())}`,t.children.unshift({attrs:{},children:[{type:A.text,text:t.alert}],noInnerParse:!0,type:A.htmlBlock,tag:`header`})),e(`blockquote`,i,n(t.children,r))}},[A.breakLine]:{_qualify:[` `],_match:F(o),_order:k.HIGH,_parse:R,_render(t,n,r={}){return e(`br`,{key:r.key})}},[A.breakThematic]:{_qualify:[`--`,`__`,`**`,`- `,`* `,`_ `],_match:L(s),_order:k.HIGH,_parse:R,_render(t,n,r={}){return e(`hr`,{key:r.key})}},[A.codeBlock]:{_qualify:[` `],_match:L(l),_order:k.MAX,_parse(e){return{type:A.codeBlock,lang:void 0,text:X(Y(e[0].replace(/^ {4}/gm,``)))}},_render(t,n,r={}){let i={...t.attrs??{}},a=t.lang?`lang-${t.lang}`:`lang-plaintext`;return i.className=i.className?`${i.className} ${a}`:a,t.lang&&!i.lang&&(i.lang=t.lang),e(`pre`,{key:r.key},e(`code`,i,t.text))}},[A.codeFenced]:{_qualify:["```",`~~~`],_match:L(c),_order:k.MAX,_parse(e){return{attrs:M(`code`,e[3]??``),lang:e[2]||void 0,text:e[4],type:A.codeBlock}}},[A.codeInline]:{_qualify:["`"],_match:q(u),_order:k.LOW,_parse(e){return{text:X(e[2])}},_render(t,n,r={}){return e(`code`,{key:r.key},t.text)}},[A.footnote]:{_qualify:[`[^`],_match:L(m),_order:k.MAX,_parse(e){return O.push({footnote:e[2],identifier:e[1]}),{}},_render:K},[A.footnoteReference]:{_qualify:[`[^`],_match:V(h),_order:k.HIGH,_parse(e){return{target:`#${B(e[1])}`,text:e[1]}},_render(t,n,r={}){return e(`a`,{key:r.key,href:H(t.target,`a`,`href`)??void 0},e(`sup`,{key:r.key},t.text))}},[A.gfmTask]:{_qualify:[`[ ]`,`[x]`],_match:V(_),_order:k.HIGH,_parse(e){return{completed:e[1].toLowerCase()===`x`}},_render(t,n,r={}){return e(`input`,{checked:t.completed,key:r.key,readOnly:!0,type:`checkbox`})}},[A.heading]:{_qualify:[`#`],_match:L(g.enforceAtxHeadings?ee:te),_order:k.HIGH,_parse(e,t,n){return{children:G(t,e[2],n),id:B(e[2]),level:e[1].length}},_render(t,n,r={}){return e(`h${t.level}`,{id:t.id,key:r.key},n(t.children,r))}},[A.headingSetext]:{_qualify:e=>{let t=e.indexOf(`
11
+ `);return t>0&&t<e.length-1&&(e[t+1]===`=`||e[t+1]===`-`)},_match:L(ne),_order:k.MAX,_parse(e,t,n){return{children:G(t,e[1],n),level:e[2]===`=`?1:2,type:A.heading}}},[A.htmlBlock]:{_qualify:e=>{if(g.disableParsingRawHTML)return!1;let t=e.match(/^ *<([a-z][a-z0-9:-]*)\b/i);if(!t)return!1;let n=t[1];return e.toLowerCase().indexOf(`</${n.toLowerCase()}>`)!==-1},_match:F(v),_order:k.HIGH,_parse(e,t,n){let r=e[3].match(b)?.[1]??``,i=Te(e[3],r),a=I(i)?U:G,o=e[1].trim(),s=p.indexOf(o.toLowerCase())!==-1,c=s?o.toLowerCase():o,l={attrs:M(c,e[2]??``),noInnerParse:s,tag:c};if(n.inAnchor=n.inAnchor||o.toLowerCase()===`a`,s)l.text=e[3];else{let e=n.inHTML;n.inHTML=!0,l.children=a(t,i,n),n.inHTML=e}return n.inAnchor=!1,l},_render(t,n,r={}){return e(t.tag,{key:r.key,...t.attrs??{}},t.text??(t.children?n(t.children,r):``))}},[A.htmlComment]:{_qualify:[`<!`],_match:F(re),_order:k.HIGH,_parse:R,_render:K},[A.htmlSelfClosing]:{_qualify:e=>g.disableParsingRawHTML?!1:/^ *<([a-zA-Z][a-zA-Z0-9:]*)[\s>/]/.test(e),_match:F(x),_order:k.HIGH,_parse(e){let t=e[1].trim();return{attrs:M(t,e[2]||``),tag:t}},_render(t,n,r={}){return e(t.tag,{key:r.key,...t.attrs??{}})}},[A.customComponent]:{_qualify:e=>/^ *<([A-Z][a-zA-Z0-9]*)/.test(e),_match:F(f),_order:k.MAX,_parse(e,t,n){let r=e[3].match(b)?.[1]??``,i=Te(e[3],r),a=I(i)?U:G,o=e[1].trim(),s={attrs:M(o,e[2]??``),noInnerParse:!1,tag:o},c=n.inHTML;return n.inHTML=!0,s.children=a(t,i,n),n.inHTML=c,s},_render(t,n,r={}){return e(t.tag,{key:r.key,...t.attrs??{}},t.text??(t.children?n(t.children,r):``))}},[A.paragraph]:{_match:Q,_order:k.LOW,_parse:W,_render(t,n,r={}){return e(`p`,{key:r.key},n(t.children,r))}},[A.image]:{_qualify:[`![`],_match:q(Oe),_order:k.HIGH,_parse(e){return{alt:X(e[1]),target:X(e[2]),title:X(e[3])}},_render(t,n,r={}){return e(`img`,{key:r.key,alt:t.alt??void 0,title:t.title??void 0,src:H(t.target,`img`,`src`)??void 0})}},[A.link]:{_qualify:[`[`],_match:V(ke),_order:k.LOW,_parse(e,t,n){return{children:ve(t,e[1],n),target:X(e[2]),title:X(e[3])}},_render(t,n,r={}){let i=H(t.target,`a`,`href`);return e(`a`,{key:r.key,href:i??void 0,title:t.title??void 0},n(t.children,r))}},[A.linkAngleBraceStyleDetector]:{_qualify:[`<`],_match:V(C),_order:k.MAX,_parse(e){let t=e[1],n=!1;return t.indexOf(`@`)!==-1&&t.indexOf(`//`)===-1&&(n=!0,t=t.replace(`mailto:`,``)),{children:[{text:t,type:A.text}],target:n?`mailto:${t}`:t,type:A.link}}},[A.linkBareUrlDetector]:{_qualify:(e,t)=>!!(t.inline&&!t.inAnchor&&!g.disableAutoLink&&(we(e,`http://`)||we(e,`https://`))),_match:V(S),_order:k.MAX,_parse(e){return{children:[{text:e[1],type:A.text}],target:e[1],type:A.link}}},[A.newlineCoalescer]:{_match:L(d),_order:k.LOW,_parse:R,_render(){return`
12
+ `}},[A.orderedList]:Z(1),[A.unorderedList]:Z(2),[A.ref]:{_qualify:[`[`],_match:F(oe),_order:k.MAX,_parse(e){return j[e[1]]={target:e[2],title:e[4]},{}},_render:K},[A.refImage]:{_qualify:[`![`],_match:q(se),_order:k.MAX,_parse(e){return{alt:e[1]?X(e[1]):void 0,ref:e[2]}},_render(t,n,r={}){let i=j[t.ref];return i?e(`img`,{key:r.key,alt:t.alt,src:H(i.target,`img`,`src`)??void 0,title:i.title}):null}},[A.refLink]:{_qualify:e=>e[0]===`[`&&e.indexOf(`](`)===-1,_match:V(ce),_order:k.MAX,_parse(e,t,n){return{children:ve(t,e[1],n),fallbackChildren:e[0],ref:e[2]}},_render(t,n,r={}){let i=j[t.ref];return i?e(`a`,{key:r.key,href:H(i.target,`a`,`href`)??void 0,title:i.title},n(t.children,r)):e(`span`,{key:r.key},t.fallbackChildren)}},[A.table]:{_qualify:[`|`],_match:L(E),_order:k.HIGH,_parse(e,t,n){n.inline=!0;let r=e[2]?ye(e[2]):[],i=e[3]?be(e[3],t,n):[],a=xe(e[1],t,n,!!i.length);return n.inline=!1,i.length?{align:r,cells:i,header:a,type:A.table}:{children:a.flat(),type:A.paragraph}},_render(t,n,r={}){let i=t,a=e=>i.align[e]?{textAlign:i.align[e]}:{};return e(`table`,{key:r.key},e(`thead`,null,e(`tr`,null,...i.header.map((t,i)=>e(`th`,{key:i,style:a(i)},n(t,r))))),e(`tbody`,null,...i.cells.map((t,i)=>e(`tr`,{key:i},...t.map((t,i)=>e(`td`,{key:i,style:a(i)},n(t,r)))))))}},[A.tableSeparator]:{_match:(e,t)=>t.inTable&&e[0]===`|`?/^\|/.exec(e):null,_order:k.HIGH,_parse(){return{type:A.tableSeparator}},_render(){return` | `}},[A.text]:{_match:P((e,t)=>le.exec(e)||me.exec(e)||/^[\s\S]/.exec(e)),_order:k.MIN,_parse(e){let t=e[0];return{text:t.indexOf(`&`)===-1?t:t.replace(y,(e,t)=>Ee[t]||e)}},_render(e){return e.text}},[A.textBolded]:{_qualify:[`**`,`__`],_match:q(ue),_order:k.MED,_parse(e,t,n){return{children:t(e[2],n)}},_render(t,n,r={}){return e(`strong`,{key:r.key},n(t.children,r))}},[A.textEmphasized]:{_qualify:[`*`,`_`],_match:q(de),_order:k.LOW,_parse(e,t,n){return{children:t(e[2],n)}},_render(t,n,r={}){return e(`em`,{key:r.key},n(t.children,r))}},[A.textEscaped]:{_qualify:[`\\`],_match:q(fe),_order:k.HIGH,_parse(e){return{text:e[1],type:A.text}}},[A.textMarked]:{_qualify:[`==`],_match:q(pe),_order:k.LOW,_parse:W,_render(t,n,r={}){return e(`mark`,{key:r.key},n(t.children,r))}},[A.textStrikethroughed]:{_qualify:[`~~`],_match:q(he),_order:k.LOW,_parse:W,_render(t,n,r={}){return e(`del`,{key:r.key},n(t.children,r))}}}},$=(n=``,i,a={})=>{let o=i.components??{},s=e=>i.slugify?i.slugify(e,J):J(e),u=je(i,a),d=[],p={},m=(n,r)=>{if(!r||!r.trim())return null;let a=r.match(t);return a?a.reduce((t,r)=>{let a=r.indexOf(`=`);if(a!==-1){let o=H(r.slice(0,a)).trim(),s=Ee(r.slice(a+1).trim()),c=e[o]??o;if(c===`ref`)return t;t[c]=I(n,o,s,i.sanitizer??Se),typeof t[c]==`string`&&(v.test(t[c])||x.test(t[c]))&&(t[c]=C(t[c].trim()))}else r!==`style`&&(t[e[r]??r]=!0);return t},{}):null},h=[r,c,l,a.enforceAtxHeadings?ee:te,ne,E,D,N,f],_=Me(u,i,a,d,p,m,e=>{let t=e.replace(M,``),n=t.length>2048?t.slice(0,2048):t;return Ce(a.disableParsingRawHTML?h:[...h,O,v,re,x,f],n)},h),y=a.disableParsingRawHTML?Object.keys(_).reduce((e,t)=>(t!==A.htmlBlock&&t!==A.htmlSelfClosing&&(e[t]=_[t]),e),{}):_,b=Z(y),S=De(Q(y,a.renderRule)),C=e=>{let t=a.preserveFrontmatter?e:e.replace(g,``),n=a.forceInline||!a.forceBlock&&j.test(t.replace(M,``))===!1,r=S(b(n?t:`${Y(t).replace(M,``)}\n\n`,{inline:n}),{inline:n});for(;typeof r[r.length-1]==`string`&&!r[r.length-1].trim();)r.pop();if(a.wrapper===null)return r;let i=a.wrapper??(n?`span`:`div`);if(r.length>1||a.forceWrapper)return u(i,{key:`outer`},r);if(r.length===1){let e=r[0];if(typeof e==`string`){let t={key:`outer`};if(!n&&o){let n=B(o,`p.props`,{})??{},r=z(t.className,n.className),i={...t,...n};return r&&(i.className=r),u(`span`,i,e)}return u(`span`,t,e)}return e}return u(i,{key:`outer`},null)};if(typeof n!=`string`)throw Error(`intlayer: the first argument must be a string`);let w=C(n);return d.length?u(`div`,null,w,u(`footer`,{key:`footer`},...d.map(e=>u(`div`,{id:s(e.identifier),key:e.identifier},e.identifier,S(b(e.footnote,{inline:!0}),{inline:!0}))))):w},Ne=e=>(t,n)=>$(t,e,n),Pe=(e,t,n={})=>{let{components:r,namedCodesToUnicode:i,sanitizer:a,slugify:o,...s}=n;return $(e,{runtime:t,components:r,namedCodesToUnicode:i,sanitizer:a,slugify:o},s)};export{$ as compile,Pe as compileWithOptions,Ne as createCompiler};
13
13
  //# sourceMappingURL=compiler.mjs.map