@intlayer/babel 9.3.1 → 9.3.2

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 (43) hide show
  1. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs +66 -8
  2. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs.map +1 -1
  3. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs +142 -53
  4. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs.map +1 -1
  5. package/dist/cjs/extractContent/babelProcessor.cjs +7 -8
  6. package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
  7. package/dist/cjs/extractContent/extractContent.cjs +3 -4
  8. package/dist/cjs/extractContent/extractContent.cjs.map +1 -1
  9. package/dist/cjs/extractContent/index.cjs +0 -1
  10. package/dist/cjs/extractContent/utils/constants.cjs +0 -13
  11. package/dist/cjs/extractContent/utils/constants.cjs.map +1 -1
  12. package/dist/cjs/extractContent/utils/index.cjs +1 -4
  13. package/dist/cjs/index.cjs +1 -1
  14. package/dist/esm/babel-plugin-intlayer-field-rename.mjs +67 -9
  15. package/dist/esm/babel-plugin-intlayer-field-rename.mjs.map +1 -1
  16. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs +142 -54
  17. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs.map +1 -1
  18. package/dist/esm/extractContent/babelProcessor.mjs +1 -2
  19. package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
  20. package/dist/esm/extractContent/extractContent.mjs +1 -2
  21. package/dist/esm/extractContent/extractContent.mjs.map +1 -1
  22. package/dist/esm/extractContent/index.mjs +2 -2
  23. package/dist/esm/extractContent/utils/constants.mjs +1 -13
  24. package/dist/esm/extractContent/utils/constants.mjs.map +1 -1
  25. package/dist/esm/extractContent/utils/index.mjs +2 -3
  26. package/dist/esm/index.mjs +3 -3
  27. package/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
  28. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +16 -1
  29. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts.map +1 -1
  30. package/dist/types/extractContent/babelProcessor.d.ts.map +1 -1
  31. package/dist/types/extractContent/extractContent.d.ts.map +1 -1
  32. package/dist/types/extractContent/index.d.ts +2 -2
  33. package/dist/types/extractContent/utils/constants.d.ts +1 -7
  34. package/dist/types/extractContent/utils/constants.d.ts.map +1 -1
  35. package/dist/types/extractContent/utils/index.d.ts +2 -3
  36. package/dist/types/index.d.ts +3 -3
  37. package/package.json +9 -9
  38. package/dist/cjs/extractContent/utils/shouldExtract.cjs +0 -38
  39. package/dist/cjs/extractContent/utils/shouldExtract.cjs.map +0 -1
  40. package/dist/esm/extractContent/utils/shouldExtract.mjs +0 -37
  41. package/dist/esm/extractContent/utils/shouldExtract.mjs.map +0 -1
  42. package/dist/types/extractContent/utils/shouldExtract.d.ts +0 -15
  43. package/dist/types/extractContent/utils/shouldExtract.d.ts.map +0 -1
@@ -2,9 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  const require_extractContent_utils_extractDictionaryKey = require('./utils/extractDictionaryKey.cjs');
4
4
  const require_extractContent_contentWriter = require('./contentWriter.cjs');
5
- const require_extractContent_utils_constants = require('./utils/constants.cjs');
6
5
  const require_extractContent_utils_generateKey = require('./utils/generateKey.cjs');
7
- const require_extractContent_utils_shouldExtract = require('./utils/shouldExtract.cjs');
8
6
  const require_extractContent_babelProcessor = require('./babelProcessor.cjs');
9
7
  const require_extractContent_processTsxFile = require('./processTsxFile.cjs');
10
8
  let node_path = require("node:path");
@@ -17,6 +15,7 @@ let _intlayer_config_utils = require("@intlayer/config/utils");
17
15
  let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
18
16
  let _intlayer_engine_cli = require("@intlayer/engine/cli");
19
17
  let node_child_process = require("node:child_process");
18
+ let _intlayer_config_extract = require("@intlayer/config/extract");
20
19
 
21
20
  //#region src/extractContent/extractContent.ts
22
21
  let vueCompiler = null;
@@ -35,8 +34,8 @@ const processFileInternal = (filePath, packageName, options, dependencies, saveC
35
34
  const { vueCompiler, svelteCompiler, unmergedDictionaries, configuration } = dependencies;
36
35
  const compilerCommonOptions = {
37
36
  generateKey: require_extractContent_utils_generateKey.generateKey,
38
- shouldExtract: require_extractContent_utils_shouldExtract.shouldExtract,
39
- attributesToExtract: require_extractContent_utils_constants.ATTRIBUTES_TO_EXTRACT,
37
+ shouldExtract: _intlayer_config_extract.shouldExtract,
38
+ attributesToExtract: _intlayer_config_extract.ATTRIBUTES_TO_EXTRACT,
40
39
  extractDictionaryKeyFromPath: require_extractContent_utils_extractDictionaryKey.extractDictionaryKeyFromPath,
41
40
  extractTsContent: (ast, code, keys, config, path) => require_extractContent_babelProcessor.extractTsContent(ast, code, keys, config, path, unmergedDictionaries)
42
41
  };
@@ -1 +1 @@
1
- {"version":3,"file":"extractContent.cjs","names":["readFileSync","extractDictionaryKey","extname","ATTRIBUTES_TO_EXTRACT","extractTsContent","colorizePath","ANSIColors","processTsxFile","detectFormatCommand","writeContentHelper","relative","colorize","getConfiguration","getAppLogger","getUnmergedDictionaries","getProjectRequire"],"sources":["../../../src/extractContent/extractContent.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { extname, relative } from 'node:path';\nimport type * as t from '@babel/types';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport { detectFormatCommand } from '@intlayer/engine/cli';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { extractTsContent } from './babelProcessor';\nimport { writeContentHelper } from './contentWriter';\nimport { processTsxFile } from './processTsxFile';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n extractDictionaryKeyFromPath,\n type PackageName,\n shouldExtract,\n} from './utils';\nimport { extractDictionaryKey } from './utils/extractDictionaryKey';\nimport { generateKey } from './utils/generateKey';\n\nexport type ExtractIntlayerOptions = {\n configOptions?: GetConfigurationOptions;\n codeOnly?: boolean;\n declarationOnly?: boolean;\n unmergedDictionaries?: Record<string, unknown>;\n configuration?: IntlayerConfig;\n code?: string;\n onExtract?: (result: {\n key: string;\n content: Record<string, string>;\n filePath: string;\n }) => void | Promise<void>;\n};\n\ntype ExternalCompilerResult = {\n extractedContent: Record<string, string>;\n code: string;\n};\n\ntype ExternalCompilerOptions = {\n generateKey: typeof generateKey;\n shouldExtract: typeof shouldExtract;\n attributesToExtract: typeof ATTRIBUTES_TO_EXTRACT;\n extractDictionaryKeyFromPath: typeof extractDictionaryKeyFromPath;\n extractTsContent: (\n ast: unknown,\n code: string,\n keys: Set<string>,\n config: IntlayerConfig,\n path: string\n ) => ReturnType<typeof extractTsContent>;\n};\n\ntype VueCompiler = typeof import('@intlayer/vue-compiler');\ntype SvelteCompiler = typeof import('@intlayer/svelte-compiler');\n\n// Module caches\nlet vueCompiler: VueCompiler | null = null;\nlet svelteCompiler: SvelteCompiler | null = null;\n\ntype InternalExtractResult = {\n extractedContentMap: Record<string, Record<string, string>> | null;\n transformedCode: string | null;\n};\n\nconst formatCompilerResult = (\n componentKey: string,\n res?: ExternalCompilerResult\n): InternalExtractResult | undefined => {\n if (!res) return undefined;\n\n return {\n extractedContentMap: { [componentKey]: res.extractedContent },\n transformedCode: res.code,\n };\n};\n\ntype Dependencies = {\n vueCompiler: VueCompiler | null;\n svelteCompiler: SvelteCompiler | null;\n unmergedDictionaries: Record<string, unknown>;\n configuration: IntlayerConfig;\n};\n\nconst processFileInternal = (\n filePath: string,\n packageName: PackageName,\n options: ExtractIntlayerOptions | undefined,\n dependencies: Dependencies,\n saveComponent: boolean,\n providedComponentKey?: string\n): InternalExtractResult | undefined => {\n const fileText = options?.code ?? readFileSync(filePath, 'utf-8');\n const componentKey =\n providedComponentKey ??\n extractDictionaryKey(\n filePath,\n fileText,\n dependencies.configuration.compiler.dictionaryKeyPrefix\n );\n const ext = extname(filePath);\n\n const { vueCompiler, svelteCompiler, unmergedDictionaries, configuration } =\n dependencies;\n\n const compilerCommonOptions: ExternalCompilerOptions = {\n generateKey,\n shouldExtract,\n attributesToExtract: ATTRIBUTES_TO_EXTRACT,\n extractDictionaryKeyFromPath,\n extractTsContent: (ast, code, keys, config, path) =>\n extractTsContent(\n ast as t.File,\n code,\n keys,\n config,\n path,\n unmergedDictionaries\n ),\n };\n\n if (ext === '.vue') {\n if (!vueCompiler) {\n throw new Error(\n `Please install ${colorizePath('@intlayer/vue-compiler', ANSIColors.YELLOW)} to process Vue files.`\n );\n }\n\n const res = vueCompiler.processVueFile(\n filePath,\n componentKey,\n packageName,\n compilerCommonOptions,\n saveComponent,\n fileText\n );\n\n if (res) {\n return formatCompilerResult(componentKey, res);\n }\n }\n\n if (ext === '.svelte') {\n if (!svelteCompiler) {\n throw new Error(\n `Please install ${colorizePath('@intlayer/svelte-compiler', ANSIColors.YELLOW)} to process Svelte files.`\n );\n }\n\n const res = svelteCompiler.processSvelteFile(\n filePath,\n componentKey,\n packageName,\n compilerCommonOptions,\n saveComponent,\n fileText\n );\n\n if (res) {\n return formatCompilerResult(componentKey, res);\n }\n }\n\n if (ext === '.astro') {\n const frontmatterMatch = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(fileText);\n let fakeTsxCode = fileText;\n let hasFrontmatter = false;\n\n if (frontmatterMatch) {\n hasFrontmatter = true;\n const matchStart = frontmatterMatch.index;\n const matchEnd = matchStart + frontmatterMatch[0].length;\n\n const before = fileText.substring(0, matchStart);\n const matchText = frontmatterMatch[0];\n const after = fileText.substring(matchEnd);\n\n const newMatchText = matchText\n .replace(/^---/, '///')\n .replace(/---$/, '///');\n fakeTsxCode = before + newMatchText + after;\n } else {\n // Add empty frontmatter with a dummy statement so imports get injected properly\n fakeTsxCode = `///\\n;\\n///\\n${fileText}`;\n }\n\n const result = processTsxFile(\n filePath,\n componentKey,\n packageName,\n configuration,\n false, // don't let processTsxFile write — we reconstruct the full file below\n unmergedDictionaries,\n fakeTsxCode\n );\n\n if (!result) return undefined;\n\n let modifiedFullCode = result.modifiedCode\n .replace(/^\\s*\\/\\/\\//, '---')\n .replace(/\\n\\/\\/\\//, '\\n---');\n\n if (!hasFrontmatter) {\n modifiedFullCode = modifiedFullCode.replace(/\\n;\\n---\\n/, '\\n---\\n');\n }\n\n if (saveComponent) {\n writeFileSync(filePath, modifiedFullCode);\n\n const formatCommand = detectFormatCommand(configuration);\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', filePath), {\n stdio: 'inherit',\n cwd: dependencies.configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n }\n\n return {\n extractedContentMap: result.extractedContent,\n transformedCode: modifiedFullCode,\n };\n }\n\n if (['.tsx', '.jsx', '.ts', '.js', '.cjs', '.mjs'].includes(ext)) {\n const result = processTsxFile(\n filePath,\n componentKey,\n packageName,\n configuration,\n saveComponent,\n unmergedDictionaries,\n fileText\n );\n\n if (result) {\n return {\n extractedContentMap: result.extractedContent,\n transformedCode: result.modifiedCode,\n };\n }\n }\n\n return undefined;\n};\n\nconst handleExtractionSideEffects = async (\n extractedContentMap: Record<string, Record<string, string>>,\n filePath: string,\n options: ExtractIntlayerOptions | undefined,\n {\n configuration,\n baseDir,\n appLogger,\n }: {\n configuration: IntlayerConfig;\n baseDir: string;\n appLogger: ReturnType<typeof getAppLogger>;\n },\n saveComponent: boolean\n) => {\n if (options?.onExtract) {\n for (const [key, content] of Object.entries(extractedContentMap)) {\n await options.onExtract({ key, content, filePath });\n }\n }\n\n const writeContent = !options?.codeOnly && !options?.onExtract;\n\n if (writeContent) {\n for (const [key, content] of Object.entries(extractedContentMap)) {\n const contentFilePath = await writeContentHelper(\n content,\n key,\n filePath,\n configuration\n );\n\n const relativeContentFilePath = relative(baseDir, contentFilePath);\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Created content file: ${colorizePath(relativeContentFilePath)}`\n );\n }\n }\n\n if (saveComponent) {\n const formatCommand = detectFormatCommand(configuration);\n\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', filePath), {\n stdio: 'inherit',\n cwd: baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Updated component: ${colorizePath(relative(baseDir, filePath))}`\n );\n }\n};\n\ntype ExtractResult = {\n transformedCode: string | null;\n extractedContentMap: Record<string, Record<string, string>>;\n};\n\ntype ExtractContext = {\n configuration: IntlayerConfig;\n appLogger: ReturnType<typeof getAppLogger>;\n baseDir: string;\n unmergedDictionaries: Record<string, unknown>;\n saveComponent: boolean;\n componentExtension: string;\n};\n\nconst buildContext = (\n filePath: string,\n options: ExtractIntlayerOptions | undefined\n): ExtractContext => {\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n const { baseDir } = configuration.system;\n const unmergedDictionaries =\n options?.unmergedDictionaries ?? getUnmergedDictionaries(configuration);\n const saveComponent = !options?.declarationOnly;\n const componentExtension = extname(filePath);\n\n return {\n configuration,\n appLogger,\n baseDir,\n unmergedDictionaries,\n saveComponent,\n componentExtension,\n };\n};\n\nexport const extractContent = async (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayerOptions\n): Promise<ExtractResult | undefined> => {\n const {\n configuration,\n appLogger,\n baseDir,\n unmergedDictionaries,\n saveComponent,\n componentExtension,\n } = buildContext(filePath, options);\n\n if (componentExtension === '.vue' && !vueCompiler) {\n try {\n vueCompiler = await import('@intlayer/vue-compiler');\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/vue-compiler', ANSIColors.YELLOW)} to process Vue files.`\n );\n }\n }\n\n if (componentExtension === '.svelte' && !svelteCompiler) {\n try {\n svelteCompiler = await import('@intlayer/svelte-compiler');\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/svelte-compiler', ANSIColors.YELLOW)} to process Svelte files.`\n );\n }\n }\n\n const fileText = options?.code ?? readFileSync(filePath, 'utf-8');\n const dictionaryKey = extractDictionaryKey(\n filePath,\n fileText,\n configuration.compiler.dictionaryKeyPrefix\n );\n\n const result = processFileInternal(\n filePath,\n packageName,\n options,\n { vueCompiler, svelteCompiler, unmergedDictionaries, configuration },\n saveComponent,\n dictionaryKey\n );\n\n if (!result?.extractedContentMap) {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} No extractable text found in ${colorizePath(relative(baseDir, filePath))}`,\n { isVerbose: true }\n );\n return undefined;\n }\n\n await handleExtractionSideEffects(\n result.extractedContentMap,\n filePath,\n options,\n { configuration, baseDir, appLogger },\n saveComponent\n );\n\n return {\n transformedCode: result.transformedCode,\n extractedContentMap: result.extractedContentMap,\n };\n};\n\n/**\n * Synchronous variant of `extractContent` — used by the Babel plugin which\n * runs in a sync transform context (e.g. Next.js / Webpack).\n *\n * Differences from `extractContent`:\n * - Loads external compilers (Vue, Svelte) via `require()` instead of `import()`\n * - Fires `onExtract` callbacks as fire-and-forget (cannot await in sync context)\n * - Does NOT write dictionary files or run the code formatter; callers that\n * need persistence should supply an `onExtract` callback\n */\nexport const extractContentSync = (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayerOptions\n): ExtractResult | undefined => {\n const {\n configuration,\n appLogger,\n baseDir,\n unmergedDictionaries,\n saveComponent,\n componentExtension,\n } = buildContext(filePath, options);\n\n const requireFn = getProjectRequire();\n\n if (componentExtension === '.vue' && !vueCompiler) {\n try {\n vueCompiler = requireFn('@intlayer/vue-compiler') as VueCompiler;\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/vue-compiler', ANSIColors.YELLOW)} to process Vue files.`\n );\n }\n }\n\n if (componentExtension === '.svelte' && !svelteCompiler) {\n try {\n svelteCompiler = requireFn('@intlayer/svelte-compiler') as SvelteCompiler;\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/svelte-compiler', ANSIColors.YELLOW)} to process Svelte files.`\n );\n }\n }\n\n const result = processFileInternal(\n filePath,\n packageName,\n options,\n { vueCompiler, svelteCompiler, unmergedDictionaries, configuration },\n saveComponent\n );\n\n if (!result?.extractedContentMap) {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} No extractable text found in ${colorizePath(relative(baseDir, filePath))}`,\n { isVerbose: true }\n );\n return undefined;\n }\n\n const { extractedContentMap, transformedCode } = result;\n\n if (options?.onExtract) {\n for (const [key, content] of Object.entries(extractedContentMap)) {\n void options.onExtract({ key, content, filePath });\n }\n }\n\n return { transformedCode, extractedContentMap };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA+DA,IAAI,cAAkC;AACtC,IAAI,iBAAwC;AAO5C,MAAM,wBACJ,cACA,QACsC;CACtC,IAAI,CAAC,KAAK,OAAO;CAEjB,OAAO;EACL,qBAAqB,GAAG,eAAe,IAAI,iBAAiB;EAC5D,iBAAiB,IAAI;CACvB;AACF;AASA,MAAM,uBACJ,UACA,aACA,SACA,cACA,eACA,yBACsC;CACtC,MAAM,WAAW,SAAS,YAAQA,sBAAa,UAAU,OAAO;CAChE,MAAM,eACJ,wBACAC,uEACE,UACA,UACA,aAAa,cAAc,SAAS,mBACtC;CACF,MAAM,UAAMC,mBAAQ,QAAQ;CAE5B,MAAM,EAAE,aAAa,gBAAgB,sBAAsB,kBACzD;CAEF,MAAM,wBAAiD;EACrD;EACA;EACA,qBAAqBC;EACrB;EACA,mBAAmB,KAAK,MAAM,MAAM,QAAQ,SAC1CC,uDACE,KACA,MACA,MACA,QACA,MACA,oBACF;CACJ;CAEA,IAAI,QAAQ,QAAQ;EAClB,IAAI,CAAC,aACH,MAAM,IAAI,MACR,sBAAkBC,sCAAa,0BAA0BC,wBAAW,MAAM,EAAE,uBAC9E;EAGF,MAAM,MAAM,YAAY,eACtB,UACA,cACA,aACA,uBACA,eACA,QACF;EAEA,IAAI,KACF,OAAO,qBAAqB,cAAc,GAAG;CAEjD;CAEA,IAAI,QAAQ,WAAW;EACrB,IAAI,CAAC,gBACH,MAAM,IAAI,MACR,sBAAkBD,sCAAa,6BAA6BC,wBAAW,MAAM,EAAE,0BACjF;EAGF,MAAM,MAAM,eAAe,kBACzB,UACA,cACA,aACA,uBACA,eACA,QACF;EAEA,IAAI,KACF,OAAO,qBAAqB,cAAc,GAAG;CAEjD;CAEA,IAAI,QAAQ,UAAU;EACpB,MAAM,mBAAmB,8BAA8B,KAAK,QAAQ;EACpE,IAAI,cAAc;EAClB,IAAI,iBAAiB;EAErB,IAAI,kBAAkB;GACpB,iBAAiB;GACjB,MAAM,aAAa,iBAAiB;GACpC,MAAM,WAAW,aAAa,iBAAiB,EAAE,CAAC;GAElD,MAAM,SAAS,SAAS,UAAU,GAAG,UAAU;GAC/C,MAAM,YAAY,iBAAiB;GACnC,MAAM,QAAQ,SAAS,UAAU,QAAQ;GAKzC,cAAc,SAHO,UAClB,QAAQ,QAAQ,KAAK,CAAC,CACtB,QAAQ,QAAQ,KACe,IAAI;EACxC,OAEE,cAAc,gBAAgB;EAGhC,MAAM,SAASC,qDACb,UACA,cACA,aACA,eACA,OACA,sBACA,WACF;EAEA,IAAI,CAAC,QAAQ,OAAO;EAEpB,IAAI,mBAAmB,OAAO,aAC3B,QAAQ,cAAc,KAAK,CAAC,CAC5B,QAAQ,YAAY,OAAO;EAE9B,IAAI,CAAC,gBACH,mBAAmB,iBAAiB,QAAQ,cAAc,SAAS;EAGrE,IAAI,eAAe;GACjB,2BAAc,UAAU,gBAAgB;GAExC,MAAM,oBAAgBC,0CAAoB,aAAa;GACvD,IAAI,eACF,IAAI;IACF,iCAAS,cAAc,QAAQ,YAAY,QAAQ,GAAG;KACpD,OAAO;KACP,KAAK,aAAa,cAAc,OAAO;IACzC,CAAC;GACH,SAAS,OAAO;IACd,QAAQ,MAAM,KAAK;GACrB;EAEJ;EAEA,OAAO;GACL,qBAAqB,OAAO;GAC5B,iBAAiB;EACnB;CACF;CAEA,IAAI;EAAC;EAAQ;EAAQ;EAAO;EAAO;EAAQ;CAAM,CAAC,CAAC,SAAS,GAAG,GAAG;EAChE,MAAM,SAASD,qDACb,UACA,cACA,aACA,eACA,eACA,sBACA,QACF;EAEA,IAAI,QACF,OAAO;GACL,qBAAqB,OAAO;GAC5B,iBAAiB,OAAO;EAC1B;CAEJ;AAGF;AAEA,MAAM,8BAA8B,OAClC,qBACA,UACA,SACA,EACE,eACA,SACA,aAMF,kBACG;CACH,IAAI,SAAS,WACX,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,mBAAmB,GAC7D,MAAM,QAAQ,UAAU;EAAE;EAAK;EAAS;CAAS,CAAC;CAMtD,IAFqB,CAAC,SAAS,YAAY,CAAC,SAAS,WAGnD,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,mBAAmB,GAAG;EAChE,MAAM,kBAAkB,MAAME,wDAC5B,SACA,KACA,UACA,aACF;EAEA,MAAM,8BAA0BC,oBAAS,SAAS,eAAe;EACjE,UACE,OAAGC,kCAAS,aAAaL,wBAAW,SAAS,EAAE,6BAAyBD,sCAAa,uBAAuB,GAC9G;CACF;CAGF,IAAI,eAAe;EACjB,MAAM,oBAAgBG,0CAAoB,aAAa;EAEvD,IAAI,eACF,IAAI;GACF,iCAAS,cAAc,QAAQ,YAAY,QAAQ,GAAG;IACpD,OAAO;IACP,KAAK;GACP,CAAC;EACH,SAAS,OAAO;GACd,QAAQ,MAAM,KAAK;EACrB;EAGF,UACE,OAAGG,kCAAS,aAAaL,wBAAW,SAAS,EAAE,0BAAsBD,0CAAaK,oBAAS,SAAS,QAAQ,CAAC,GAC/G;CACF;AACF;AAgBA,MAAM,gBACJ,UACA,YACmB;CACnB,MAAM,gBACJ,SAAS,qBAAiBE,wCAAiB,SAAS,aAAa;CACnE,MAAM,gBAAYC,sCAAa,aAAa;CAC5C,MAAM,EAAE,YAAY,cAAc;CAMlC,OAAO;EACL;EACA;EACA;EACA,sBARA,SAAS,4BAAwBC,+DAAwB,aAAa;EAStE,gBARqB,SAAS;EAS9B,wBARyBZ,mBAAQ,QAQhB;CACnB;AACF;AAEA,MAAa,iBAAiB,OAC5B,UACA,aACA,YACuC;CACvC,MAAM,EACJ,eACA,WACA,SACA,sBACA,eACA,uBACE,aAAa,UAAU,OAAO;CAElC,IAAI,uBAAuB,UAAU,CAAC,aACpC,IAAI;EACF,cAAc,MAAM,OAAO;CAC7B,QAAQ;EACN,UACE,OAAGS,kCAAS,aAAaL,wBAAW,SAAS,EAAE,eAAWD,sCAAa,0BAA0BC,wBAAW,MAAM,EAAE,uBACtH;CACF;CAGF,IAAI,uBAAuB,aAAa,CAAC,gBACvC,IAAI;EACF,iBAAiB,MAAM,OAAO;CAChC,QAAQ;EACN,UACE,OAAGK,kCAAS,aAAaL,wBAAW,SAAS,EAAE,eAAWD,sCAAa,6BAA6BC,wBAAW,MAAM,EAAE,0BACzH;CACF;CAGF,MAAM,WAAW,SAAS,YAAQN,sBAAa,UAAU,OAAO;CAChE,MAAM,gBAAgBC,uEACpB,UACA,UACA,cAAc,SAAS,mBACzB;CAEA,MAAM,SAAS,oBACb,UACA,aACA,SACA;EAAE;EAAa;EAAgB;EAAsB;CAAc,GACnE,eACA,aACF;CAEA,IAAI,CAAC,QAAQ,qBAAqB;EAChC,UACE,OAAGU,kCAAS,aAAaL,wBAAW,SAAS,EAAE,oCAAgCD,0CAAaK,oBAAS,SAAS,QAAQ,CAAC,KACvH,EAAE,WAAW,KAAK,CACpB;EACA;CACF;CAEA,MAAM,4BACJ,OAAO,qBACP,UACA,SACA;EAAE;EAAe;EAAS;CAAU,GACpC,aACF;CAEA,OAAO;EACL,iBAAiB,OAAO;EACxB,qBAAqB,OAAO;CAC9B;AACF;;;;;;;;;;;AAYA,MAAa,sBACX,UACA,aACA,YAC8B;CAC9B,MAAM,EACJ,eACA,WACA,SACA,sBACA,eACA,uBACE,aAAa,UAAU,OAAO;CAElC,MAAM,gBAAYK,0CAAkB;CAEpC,IAAI,uBAAuB,UAAU,CAAC,aACpC,IAAI;EACF,cAAc,UAAU,wBAAwB;CAClD,QAAQ;EACN,UACE,OAAGJ,kCAAS,aAAaL,wBAAW,SAAS,EAAE,eAAWD,sCAAa,0BAA0BC,wBAAW,MAAM,EAAE,uBACtH;CACF;CAGF,IAAI,uBAAuB,aAAa,CAAC,gBACvC,IAAI;EACF,iBAAiB,UAAU,2BAA2B;CACxD,QAAQ;EACN,UACE,OAAGK,kCAAS,aAAaL,wBAAW,SAAS,EAAE,eAAWD,sCAAa,6BAA6BC,wBAAW,MAAM,EAAE,0BACzH;CACF;CAGF,MAAM,SAAS,oBACb,UACA,aACA,SACA;EAAE;EAAa;EAAgB;EAAsB;CAAc,GACnE,aACF;CAEA,IAAI,CAAC,QAAQ,qBAAqB;EAChC,UACE,OAAGK,kCAAS,aAAaL,wBAAW,SAAS,EAAE,oCAAgCD,0CAAaK,oBAAS,SAAS,QAAQ,CAAC,KACvH,EAAE,WAAW,KAAK,CACpB;EACA;CACF;CAEA,MAAM,EAAE,qBAAqB,oBAAoB;CAEjD,IAAI,SAAS,WACX,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,mBAAmB,GAC7D,AAAK,QAAQ,UAAU;EAAE;EAAK;EAAS;CAAS,CAAC;CAIrD,OAAO;EAAE;EAAiB;CAAoB;AAChD"}
1
+ {"version":3,"file":"extractContent.cjs","names":["readFileSync","extractDictionaryKey","extname","ATTRIBUTES_TO_EXTRACT","extractTsContent","colorizePath","ANSIColors","processTsxFile","detectFormatCommand","writeContentHelper","relative","colorize","getConfiguration","getAppLogger","getUnmergedDictionaries","getProjectRequire"],"sources":["../../../src/extractContent/extractContent.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { extname, relative } from 'node:path';\nimport type * as t from '@babel/types';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { ATTRIBUTES_TO_EXTRACT, shouldExtract } from '@intlayer/config/extract';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport { detectFormatCommand } from '@intlayer/engine/cli';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { extractTsContent } from './babelProcessor';\nimport { writeContentHelper } from './contentWriter';\nimport { processTsxFile } from './processTsxFile';\nimport { extractDictionaryKeyFromPath, type PackageName } from './utils';\nimport { extractDictionaryKey } from './utils/extractDictionaryKey';\nimport { generateKey } from './utils/generateKey';\n\nexport type ExtractIntlayerOptions = {\n configOptions?: GetConfigurationOptions;\n codeOnly?: boolean;\n declarationOnly?: boolean;\n unmergedDictionaries?: Record<string, unknown>;\n configuration?: IntlayerConfig;\n code?: string;\n onExtract?: (result: {\n key: string;\n content: Record<string, string>;\n filePath: string;\n }) => void | Promise<void>;\n};\n\ntype ExternalCompilerResult = {\n extractedContent: Record<string, string>;\n code: string;\n};\n\ntype ExternalCompilerOptions = {\n generateKey: typeof generateKey;\n shouldExtract: typeof shouldExtract;\n attributesToExtract: typeof ATTRIBUTES_TO_EXTRACT;\n extractDictionaryKeyFromPath: typeof extractDictionaryKeyFromPath;\n extractTsContent: (\n ast: unknown,\n code: string,\n keys: Set<string>,\n config: IntlayerConfig,\n path: string\n ) => ReturnType<typeof extractTsContent>;\n};\n\ntype VueCompiler = typeof import('@intlayer/vue-compiler');\ntype SvelteCompiler = typeof import('@intlayer/svelte-compiler');\n\n// Module caches\nlet vueCompiler: VueCompiler | null = null;\nlet svelteCompiler: SvelteCompiler | null = null;\n\ntype InternalExtractResult = {\n extractedContentMap: Record<string, Record<string, string>> | null;\n transformedCode: string | null;\n};\n\nconst formatCompilerResult = (\n componentKey: string,\n res?: ExternalCompilerResult\n): InternalExtractResult | undefined => {\n if (!res) return undefined;\n\n return {\n extractedContentMap: { [componentKey]: res.extractedContent },\n transformedCode: res.code,\n };\n};\n\ntype Dependencies = {\n vueCompiler: VueCompiler | null;\n svelteCompiler: SvelteCompiler | null;\n unmergedDictionaries: Record<string, unknown>;\n configuration: IntlayerConfig;\n};\n\nconst processFileInternal = (\n filePath: string,\n packageName: PackageName,\n options: ExtractIntlayerOptions | undefined,\n dependencies: Dependencies,\n saveComponent: boolean,\n providedComponentKey?: string\n): InternalExtractResult | undefined => {\n const fileText = options?.code ?? readFileSync(filePath, 'utf-8');\n const componentKey =\n providedComponentKey ??\n extractDictionaryKey(\n filePath,\n fileText,\n dependencies.configuration.compiler.dictionaryKeyPrefix\n );\n const ext = extname(filePath);\n\n const { vueCompiler, svelteCompiler, unmergedDictionaries, configuration } =\n dependencies;\n\n const compilerCommonOptions: ExternalCompilerOptions = {\n generateKey,\n shouldExtract,\n attributesToExtract: ATTRIBUTES_TO_EXTRACT,\n extractDictionaryKeyFromPath,\n extractTsContent: (ast, code, keys, config, path) =>\n extractTsContent(\n ast as t.File,\n code,\n keys,\n config,\n path,\n unmergedDictionaries\n ),\n };\n\n if (ext === '.vue') {\n if (!vueCompiler) {\n throw new Error(\n `Please install ${colorizePath('@intlayer/vue-compiler', ANSIColors.YELLOW)} to process Vue files.`\n );\n }\n\n const res = vueCompiler.processVueFile(\n filePath,\n componentKey,\n packageName,\n compilerCommonOptions,\n saveComponent,\n fileText\n );\n\n if (res) {\n return formatCompilerResult(componentKey, res);\n }\n }\n\n if (ext === '.svelte') {\n if (!svelteCompiler) {\n throw new Error(\n `Please install ${colorizePath('@intlayer/svelte-compiler', ANSIColors.YELLOW)} to process Svelte files.`\n );\n }\n\n const res = svelteCompiler.processSvelteFile(\n filePath,\n componentKey,\n packageName,\n compilerCommonOptions,\n saveComponent,\n fileText\n );\n\n if (res) {\n return formatCompilerResult(componentKey, res);\n }\n }\n\n if (ext === '.astro') {\n const frontmatterMatch = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(fileText);\n let fakeTsxCode = fileText;\n let hasFrontmatter = false;\n\n if (frontmatterMatch) {\n hasFrontmatter = true;\n const matchStart = frontmatterMatch.index;\n const matchEnd = matchStart + frontmatterMatch[0].length;\n\n const before = fileText.substring(0, matchStart);\n const matchText = frontmatterMatch[0];\n const after = fileText.substring(matchEnd);\n\n const newMatchText = matchText\n .replace(/^---/, '///')\n .replace(/---$/, '///');\n fakeTsxCode = before + newMatchText + after;\n } else {\n // Add empty frontmatter with a dummy statement so imports get injected properly\n fakeTsxCode = `///\\n;\\n///\\n${fileText}`;\n }\n\n const result = processTsxFile(\n filePath,\n componentKey,\n packageName,\n configuration,\n false, // don't let processTsxFile write — we reconstruct the full file below\n unmergedDictionaries,\n fakeTsxCode\n );\n\n if (!result) return undefined;\n\n let modifiedFullCode = result.modifiedCode\n .replace(/^\\s*\\/\\/\\//, '---')\n .replace(/\\n\\/\\/\\//, '\\n---');\n\n if (!hasFrontmatter) {\n modifiedFullCode = modifiedFullCode.replace(/\\n;\\n---\\n/, '\\n---\\n');\n }\n\n if (saveComponent) {\n writeFileSync(filePath, modifiedFullCode);\n\n const formatCommand = detectFormatCommand(configuration);\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', filePath), {\n stdio: 'inherit',\n cwd: dependencies.configuration.system.baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n }\n\n return {\n extractedContentMap: result.extractedContent,\n transformedCode: modifiedFullCode,\n };\n }\n\n if (['.tsx', '.jsx', '.ts', '.js', '.cjs', '.mjs'].includes(ext)) {\n const result = processTsxFile(\n filePath,\n componentKey,\n packageName,\n configuration,\n saveComponent,\n unmergedDictionaries,\n fileText\n );\n\n if (result) {\n return {\n extractedContentMap: result.extractedContent,\n transformedCode: result.modifiedCode,\n };\n }\n }\n\n return undefined;\n};\n\nconst handleExtractionSideEffects = async (\n extractedContentMap: Record<string, Record<string, string>>,\n filePath: string,\n options: ExtractIntlayerOptions | undefined,\n {\n configuration,\n baseDir,\n appLogger,\n }: {\n configuration: IntlayerConfig;\n baseDir: string;\n appLogger: ReturnType<typeof getAppLogger>;\n },\n saveComponent: boolean\n) => {\n if (options?.onExtract) {\n for (const [key, content] of Object.entries(extractedContentMap)) {\n await options.onExtract({ key, content, filePath });\n }\n }\n\n const writeContent = !options?.codeOnly && !options?.onExtract;\n\n if (writeContent) {\n for (const [key, content] of Object.entries(extractedContentMap)) {\n const contentFilePath = await writeContentHelper(\n content,\n key,\n filePath,\n configuration\n );\n\n const relativeContentFilePath = relative(baseDir, contentFilePath);\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Created content file: ${colorizePath(relativeContentFilePath)}`\n );\n }\n }\n\n if (saveComponent) {\n const formatCommand = detectFormatCommand(configuration);\n\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', filePath), {\n stdio: 'inherit',\n cwd: baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Updated component: ${colorizePath(relative(baseDir, filePath))}`\n );\n }\n};\n\ntype ExtractResult = {\n transformedCode: string | null;\n extractedContentMap: Record<string, Record<string, string>>;\n};\n\ntype ExtractContext = {\n configuration: IntlayerConfig;\n appLogger: ReturnType<typeof getAppLogger>;\n baseDir: string;\n unmergedDictionaries: Record<string, unknown>;\n saveComponent: boolean;\n componentExtension: string;\n};\n\nconst buildContext = (\n filePath: string,\n options: ExtractIntlayerOptions | undefined\n): ExtractContext => {\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n const { baseDir } = configuration.system;\n const unmergedDictionaries =\n options?.unmergedDictionaries ?? getUnmergedDictionaries(configuration);\n const saveComponent = !options?.declarationOnly;\n const componentExtension = extname(filePath);\n\n return {\n configuration,\n appLogger,\n baseDir,\n unmergedDictionaries,\n saveComponent,\n componentExtension,\n };\n};\n\nexport const extractContent = async (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayerOptions\n): Promise<ExtractResult | undefined> => {\n const {\n configuration,\n appLogger,\n baseDir,\n unmergedDictionaries,\n saveComponent,\n componentExtension,\n } = buildContext(filePath, options);\n\n if (componentExtension === '.vue' && !vueCompiler) {\n try {\n vueCompiler = await import('@intlayer/vue-compiler');\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/vue-compiler', ANSIColors.YELLOW)} to process Vue files.`\n );\n }\n }\n\n if (componentExtension === '.svelte' && !svelteCompiler) {\n try {\n svelteCompiler = await import('@intlayer/svelte-compiler');\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/svelte-compiler', ANSIColors.YELLOW)} to process Svelte files.`\n );\n }\n }\n\n const fileText = options?.code ?? readFileSync(filePath, 'utf-8');\n const dictionaryKey = extractDictionaryKey(\n filePath,\n fileText,\n configuration.compiler.dictionaryKeyPrefix\n );\n\n const result = processFileInternal(\n filePath,\n packageName,\n options,\n { vueCompiler, svelteCompiler, unmergedDictionaries, configuration },\n saveComponent,\n dictionaryKey\n );\n\n if (!result?.extractedContentMap) {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} No extractable text found in ${colorizePath(relative(baseDir, filePath))}`,\n { isVerbose: true }\n );\n return undefined;\n }\n\n await handleExtractionSideEffects(\n result.extractedContentMap,\n filePath,\n options,\n { configuration, baseDir, appLogger },\n saveComponent\n );\n\n return {\n transformedCode: result.transformedCode,\n extractedContentMap: result.extractedContentMap,\n };\n};\n\n/**\n * Synchronous variant of `extractContent` — used by the Babel plugin which\n * runs in a sync transform context (e.g. Next.js / Webpack).\n *\n * Differences from `extractContent`:\n * - Loads external compilers (Vue, Svelte) via `require()` instead of `import()`\n * - Fires `onExtract` callbacks as fire-and-forget (cannot await in sync context)\n * - Does NOT write dictionary files or run the code formatter; callers that\n * need persistence should supply an `onExtract` callback\n */\nexport const extractContentSync = (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayerOptions\n): ExtractResult | undefined => {\n const {\n configuration,\n appLogger,\n baseDir,\n unmergedDictionaries,\n saveComponent,\n componentExtension,\n } = buildContext(filePath, options);\n\n const requireFn = getProjectRequire();\n\n if (componentExtension === '.vue' && !vueCompiler) {\n try {\n vueCompiler = requireFn('@intlayer/vue-compiler') as VueCompiler;\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/vue-compiler', ANSIColors.YELLOW)} to process Vue files.`\n );\n }\n }\n\n if (componentExtension === '.svelte' && !svelteCompiler) {\n try {\n svelteCompiler = requireFn('@intlayer/svelte-compiler') as SvelteCompiler;\n } catch {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Install ${colorizePath('@intlayer/svelte-compiler', ANSIColors.YELLOW)} to process Svelte files.`\n );\n }\n }\n\n const result = processFileInternal(\n filePath,\n packageName,\n options,\n { vueCompiler, svelteCompiler, unmergedDictionaries, configuration },\n saveComponent\n );\n\n if (!result?.extractedContentMap) {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} No extractable text found in ${colorizePath(relative(baseDir, filePath))}`,\n { isVerbose: true }\n );\n return undefined;\n }\n\n const { extractedContentMap, transformedCode } = result;\n\n if (options?.onExtract) {\n for (const [key, content] of Object.entries(extractedContentMap)) {\n void options.onExtract({ key, content, filePath });\n }\n }\n\n return { transformedCode, extractedContentMap };\n};\n"],"mappings":"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"}
@@ -8,7 +8,6 @@ const require_extractContent_utils_generateKey = require('./utils/generateKey.cj
8
8
  const require_extractContent_utils_getComponentName = require('./utils/getComponentName.cjs');
9
9
  const require_extractContent_extractContent = require('./extractContent.cjs');
10
10
 
11
- exports.ATTRIBUTES_TO_EXTRACT = require_extractContent_utils_constants.ATTRIBUTES_TO_EXTRACT;
12
11
  exports.SERVER_CAPABLE_PACKAGES = require_extractContent_utils_constants.SERVER_CAPABLE_PACKAGES;
13
12
  exports.detectPackageName = require_extractContent_utils_detectPackageName.detectPackageName;
14
13
  exports.extractContent = require_extractContent_extractContent.extractContent;
@@ -1,18 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  //#region src/extractContent/utils/constants.ts
3
3
  /**
4
- * Attributes that should be extracted as translatable strings from JSX/HTML elements.
5
- * This is the single source of truth shared across all Intlayer compiler packages
6
- * (@intlayer/babel, @intlayer/vue-compiler, @intlayer/svelte-compiler, @intlayer/engine).
7
- */
8
- const ATTRIBUTES_TO_EXTRACT = [
9
- "title",
10
- "placeholder",
11
- "alt",
12
- "aria-label",
13
- "label"
14
- ];
15
- /**
16
4
  * The list of supported Intlayer integration packages.
17
5
  * This is the single source of truth for package name validation.
18
6
  *
@@ -37,7 +25,6 @@ const packageList = [
37
25
  const SERVER_CAPABLE_PACKAGES = /* @__PURE__ */ new Set(["next-intlayer"]);
38
26
 
39
27
  //#endregion
40
- exports.ATTRIBUTES_TO_EXTRACT = ATTRIBUTES_TO_EXTRACT;
41
28
  exports.SERVER_CAPABLE_PACKAGES = SERVER_CAPABLE_PACKAGES;
42
29
  exports.packageList = packageList;
43
30
  //# sourceMappingURL=constants.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.cjs","names":[],"sources":["../../../../src/extractContent/utils/constants.ts"],"sourcesContent":["/**\n * Attributes that should be extracted as translatable strings from JSX/HTML elements.\n * This is the single source of truth shared across all Intlayer compiler packages\n * (@intlayer/babel, @intlayer/vue-compiler, @intlayer/svelte-compiler, @intlayer/engine).\n */\nexport const ATTRIBUTES_TO_EXTRACT = [\n 'title',\n 'placeholder',\n 'alt',\n 'aria-label',\n 'label',\n] as const;\n\n/**\n * The list of supported Intlayer integration packages.\n * This is the single source of truth for package name validation.\n *\n * Order matter for resolution\n */\nexport const packageList = [\n 'next-intlayer',\n 'react-intlayer',\n 'vue-intlayer',\n 'svelte-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n 'angular-intlayer',\n 'lit-intlayer',\n 'express-intlayer',\n 'hono-intlayer',\n 'fastify-intlayer',\n 'adonis-intlayer',\n 'intlayer',\n] as const;\n\n/** Packages that support a `/server` sub-path for React Server Components. */\nexport const SERVER_CAPABLE_PACKAGES: ReadonlySet<string> = new Set([\n 'next-intlayer',\n]);\n\nexport type PackageName = (typeof packageList)[number];\n"],"mappings":";;;;;;;AAKA,MAAa,wBAAwB;CACnC;CACA;CACA;CACA;CACA;AACF;;;;;;;AAQA,MAAa,cAAc;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,0CAA+C,IAAI,IAAI,CAClE,eACF,CAAC"}
1
+ {"version":3,"file":"constants.cjs","names":[],"sources":["../../../../src/extractContent/utils/constants.ts"],"sourcesContent":["/**\n * The list of supported Intlayer integration packages.\n * This is the single source of truth for package name validation.\n *\n * Order matter for resolution\n */\nexport const packageList = [\n 'next-intlayer',\n 'react-intlayer',\n 'vue-intlayer',\n 'svelte-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n 'angular-intlayer',\n 'lit-intlayer',\n 'express-intlayer',\n 'hono-intlayer',\n 'fastify-intlayer',\n 'adonis-intlayer',\n 'intlayer',\n] as const;\n\n/** Packages that support a `/server` sub-path for React Server Components. */\nexport const SERVER_CAPABLE_PACKAGES: ReadonlySet<string> = new Set([\n 'next-intlayer',\n]);\n\nexport type PackageName = (typeof packageList)[number];\n"],"mappings":";;;;;;;;AAMA,MAAa,cAAc;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,0CAA+C,IAAI,IAAI,CAClE,eACF,CAAC"}
@@ -8,9 +8,7 @@ const require_extractContent_utils_getComponentName = require('./getComponentNam
8
8
  const require_extractContent_utils_getExistingIntlayerInfo = require('./getExistingIntlayerInfo.cjs');
9
9
  const require_extractContent_utils_getOrGenerateKey = require('./getOrGenerateKey.cjs');
10
10
  const require_extractContent_utils_resolveDictionaryKey = require('./resolveDictionaryKey.cjs');
11
- const require_extractContent_utils_shouldExtract = require('./shouldExtract.cjs');
12
11
 
13
- exports.ATTRIBUTES_TO_EXTRACT = require_extractContent_utils_constants.ATTRIBUTES_TO_EXTRACT;
14
12
  exports.SERVER_CAPABLE_PACKAGES = require_extractContent_utils_constants.SERVER_CAPABLE_PACKAGES;
15
13
  exports.detectPackageName = require_extractContent_utils_detectPackageName.detectPackageName;
16
14
  exports.extractDictionaryInfo = require_extractContent_utils_extractDictionaryInfo.extractDictionaryInfo;
@@ -23,5 +21,4 @@ exports.getOrGenerateKey = require_extractContent_utils_getOrGenerateKey.getOrGe
23
21
  exports.getOutput = require_extractContent_utils_extractDictionaryInfo.getOutput;
24
22
  exports.packageList = require_extractContent_utils_constants.packageList;
25
23
  exports.resolveContentFilePaths = require_extractContent_utils_extractDictionaryInfo.resolveContentFilePaths;
26
- exports.resolveDictionaryKey = require_extractContent_utils_resolveDictionaryKey.resolveDictionaryKey;
27
- exports.shouldExtract = require_extractContent_utils_shouldExtract.shouldExtract;
24
+ exports.resolveDictionaryKey = require_extractContent_utils_resolveDictionaryKey.resolveDictionaryKey;
@@ -19,8 +19,8 @@ const require_babel_plugin_intlayer_minify = require('./babel-plugin-intlayer-mi
19
19
  const require_getOptimizePluginOptions = require('./getOptimizePluginOptions.cjs');
20
20
  const require_getPurgePluginOptions = require('./getPurgePluginOptions.cjs');
21
21
 
22
- exports.ATTRIBUTES_TO_EXTRACT = require_extractContent_utils_constants.ATTRIBUTES_TO_EXTRACT;
23
22
  exports.BABEL_PARSER_OPTIONS = require_transformers.BABEL_PARSER_OPTIONS;
23
+ exports.CHAINABLE_RUNTIME_METHOD_NAMES = require_babel_plugin_intlayer_usage_analyzer.CHAINABLE_RUNTIME_METHOD_NAMES;
24
24
  exports.DEFAULT_COMPAT_CALLERS = require_babel_plugin_intlayer_usage_analyzer.DEFAULT_COMPAT_CALLERS;
25
25
  exports.INTLAYER_CALLER_NAMES = require_babel_plugin_intlayer_usage_analyzer.INTLAYER_CALLER_NAMES;
26
26
  exports.INTLAYER_USAGE_REGEX = require_transformers.INTLAYER_USAGE_REGEX;
@@ -1,4 +1,4 @@
1
- import { INTLAYER_CALLER_NAMES } from "./babel-plugin-intlayer-usage-analyzer.mjs";
1
+ import { CHAINABLE_RUNTIME_METHOD_NAMES, INTLAYER_CALLER_NAMES } from "./babel-plugin-intlayer-usage-analyzer.mjs";
2
2
 
3
3
  //#region src/babel-plugin-intlayer-field-rename.ts
4
4
  /**
@@ -233,6 +233,69 @@ const walkObjectDestructuring = (babelTypes, refPath, renameMap) => {
233
233
  renameObjectPatternProperties(babelTypes, parentNode.id, refPath, renameMap);
234
234
  };
235
235
  /**
236
+ * Renames every field access reachable from `rootPath`, whose value is the
237
+ * dictionary content root.
238
+ *
239
+ * Combines the three ways a content root is consumed: a member-access chain,
240
+ * a destructuring assignment, and a chainable runtime helper such as
241
+ * `.onChange(cb)`.
242
+ */
243
+ const renameContentConsumers = (babelTypes, rootPath, renameMap) => {
244
+ const { finalPath, finalRenameMap } = walkRenameChain(babelTypes, rootPath, renameMap);
245
+ walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);
246
+ renameChainedRuntimeCall(babelTypes, finalPath, finalRenameMap);
247
+ };
248
+ /**
249
+ * Handles `content.onChange(cb)` — a runtime subscription rather than a field
250
+ * access (see {@link CHAINABLE_RUNTIME_METHOD_NAMES}).
251
+ *
252
+ * `walkRenameChain` stops at `onChange` because it is absent from the rename
253
+ * map, which would leave the callback body reading the original field names
254
+ * while the compiled JSON has already been renamed. This restarts the rename
255
+ * walk on both sides of the call:
256
+ *
257
+ * - the callback's first parameter receives the same content root, so its
258
+ * accesses are renamed with the same map;
259
+ * - the helper returns the content object, so the chain continues past it.
260
+ *
261
+ * @param refPath - Path whose value is the content root (the object the
262
+ * chainable method would be called on).
263
+ */
264
+ const renameChainedRuntimeCall = (babelTypes, refPath, renameMap) => {
265
+ if (renameMap.size === 0) return;
266
+ const memberPath = refPath.parentPath;
267
+ if (!memberPath) return;
268
+ const memberNode = memberPath.node;
269
+ if (!babelTypes.isMemberExpression(memberNode) && !babelTypes.isOptionalMemberExpression(memberNode) || memberNode.object !== refPath.node) return;
270
+ const propertyNode = memberNode.property;
271
+ const methodName = memberNode.computed ? babelTypes.isStringLiteral(propertyNode) ? propertyNode.value : void 0 : babelTypes.isIdentifier(propertyNode) ? propertyNode.name : void 0;
272
+ if (!methodName || !CHAINABLE_RUNTIME_METHOD_NAMES.has(methodName)) return;
273
+ const callPath = memberPath.parentPath;
274
+ if (!callPath) return;
275
+ if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) return;
276
+ if (callPath.node.callee !== memberNode) return;
277
+ const argumentPaths = callPath.get("arguments");
278
+ for (const argumentPath of argumentPaths) {
279
+ if (!argumentPath.isArrowFunctionExpression() && !argumentPath.isFunctionExpression()) continue;
280
+ const [firstParameterPath] = argumentPath.get("params");
281
+ if (!firstParameterPath) continue;
282
+ if (firstParameterPath.isObjectPattern()) {
283
+ renameObjectPatternProperties(babelTypes, firstParameterPath.node, argumentPath, renameMap);
284
+ continue;
285
+ }
286
+ if (!firstParameterPath.isIdentifier()) continue;
287
+ const parameterBinding = argumentPath.scope.getBinding(firstParameterPath.node.name);
288
+ if (!parameterBinding) continue;
289
+ for (const parameterRefPath of parameterBinding.referencePaths) renameContentConsumers(babelTypes, parameterRefPath, renameMap);
290
+ }
291
+ renameContentConsumers(babelTypes, callPath, renameMap);
292
+ const declaratorNode = callPath.parent;
293
+ if (babelTypes.isVariableDeclarator(declaratorNode) && babelTypes.isIdentifier(declaratorNode.id) && declaratorNode.init === callPath.node) {
294
+ const resultBinding = callPath.scope.getBinding(declaratorNode.id.name);
295
+ for (const resultRefPath of resultBinding?.referencePaths ?? []) renameContentConsumers(babelTypes, resultRefPath, renameMap);
296
+ }
297
+ };
298
+ /**
236
299
  * Collects the local aliases under which `useIntlayer` / `getIntlayer` are
237
300
  * imported in the given program (e.g. `import { useIntlayer as useI } …`
238
301
  * yields `useI` → `useIntlayer`).
@@ -302,23 +365,18 @@ const renameIntlayerFieldAccesses = (babelTypes, programPath, pruneContext) => {
302
365
  return;
303
366
  }
304
367
  if ((babelTypes.isMemberExpression(parentNode) || babelTypes.isOptionalMemberExpression(parentNode)) && parentNode.object === callExpressionPath.node) {
305
- const { finalPath, finalRenameMap } = walkRenameChain(babelTypes, callExpressionPath, fieldRenameMap);
306
- walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);
368
+ renameContentConsumers(babelTypes, callExpressionPath, fieldRenameMap);
307
369
  return;
308
370
  }
309
371
  if (babelTypes.isVariableDeclarator(parentNode) && babelTypes.isIdentifier(parentNode.id)) {
310
372
  const variableBinding = callExpressionPath.scope.getBinding(parentNode.id.name);
311
373
  if (!variableBinding) return;
312
374
  for (const variableReferencePath of variableBinding.referencePaths) {
313
- const { finalPath, finalRenameMap } = walkRenameChain(babelTypes, variableReferencePath, fieldRenameMap);
314
- walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);
375
+ renameContentConsumers(babelTypes, variableReferencePath, fieldRenameMap);
315
376
  const refParent = variableReferencePath.parent;
316
377
  if ((babelTypes.isCallExpression(refParent) || babelTypes.isOptionalCallExpression(refParent)) && refParent.callee === variableReferencePath.node) {
317
378
  const callPath = variableReferencePath.parentPath;
318
- if (callPath) {
319
- const { finalPath: signalFinalPath, finalRenameMap: signalFinalRenameMap } = walkRenameChain(babelTypes, callPath, fieldRenameMap);
320
- walkObjectDestructuring(babelTypes, signalFinalPath, signalFinalRenameMap);
321
- }
379
+ if (callPath) renameContentConsumers(babelTypes, callPath, fieldRenameMap);
322
380
  }
323
381
  }
324
382
  }
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-field-rename.mjs","names":[],"sources":["../../src/babel-plugin-intlayer-field-rename.ts"],"sourcesContent":["import type { NodePath, PluginObject } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport {\n INTLAYER_CALLER_NAMES,\n type IntlayerCallerName,\n type NestedRenameEntry,\n type NestedRenameMap,\n type PruneContext,\n} from './babel-plugin-intlayer-usage-analyzer';\n\n// ── Field-name helpers ────────────────────────────────────────────────────────\n\n/**\n * Intlayer internal property names that must never be used as short-name\n * targets. These appear inside content-node values (e.g. `{ nodeType:\n * \"translation\", … }`) and are read by the intlayer runtime.\n */\nconst RESERVED_CONTENT_FIELD_NAMES = new Set(['nodeType']);\n\n/** Alphabet used to derive short field aliases (`a`, `b`, …, `aa`, `ab`, …). */\nconst SHORT_NAME_ALPHABET = 'abcdefghijklmnopqrstuvwxyz';\n\n/**\n * Converts a zero-based index to a short alphabetic identifier.\n * 0 → 'a', 1 → 'b', …, 25 → 'z', 26 → 'aa', 27 → 'ab', …\n */\nexport const generateShortFieldName = (index: number): string => {\n if (!Number.isInteger(index) || index < 0) {\n throw new RangeError(\n `generateShortFieldName expects a non-negative integer index, received: ${index}`\n );\n }\n\n const remainder = index % SHORT_NAME_ALPHABET.length;\n const quotient = Math.floor(index / SHORT_NAME_ALPHABET.length);\n\n return quotient === 0 && SHORT_NAME_ALPHABET[remainder]\n ? SHORT_NAME_ALPHABET[remainder]\n : generateShortFieldName(quotient - 1) + SHORT_NAME_ALPHABET[remainder];\n};\n\n/**\n * Recursively builds a `NestedRenameMap` from a compiled dictionary content\n * value by traversing the intlayer node structure.\n *\n * Rules:\n * - If the value has `nodeType: 'translation'`, user-defined fields live\n * inside `translation[locale]`. Recurse into the first locale's value.\n * - All other intlayer runtime nodes (enumeration, condition, gender, …) are\n * treated as leaves — their internal keys must never be renamed.\n * - Arrays produce an empty children map. Array elements are not traversed\n * because consumers may access them via `.map()` / `.filter()` callbacks,\n * which the source-code rename walk cannot enter. Renaming element fields\n * in the JSON without the matching source-code rename would produce\n * mismatched key names and runtime crashes.\n * The `[0]` pass-through in `walkRenameChain` is preserved so that direct\n * indexed access (`field[0].sub`) silently terminates at the empty children\n * map without breaking anything.\n * - Plain objects are user-defined records: ALL non-reserved keys are renamed\n * with short alphabetic aliases (a, b, c, …) and each value is recursed into.\n * - Primitives produce an empty map (no further renaming).\n *\n * The rename map is built from ALL user-defined fields (not just consumed ones).\n * Both the JSON rename and the source-code rename use the same map, so the\n * short names are always consistent regardless of which fields are pruned.\n *\n * @param contentValue - The dictionary content value to analyse.\n */\nexport const buildNestedRenameMapFromContent = (\n contentValue: unknown\n): NestedRenameMap => {\n if (\n !contentValue ||\n typeof contentValue !== 'object' ||\n Array.isArray(contentValue)\n ) {\n return new Map();\n }\n\n const record = contentValue as Record<string, unknown>;\n\n // Any object with `nodeType: string` is an intlayer runtime node.\n if (typeof record.nodeType === 'string') {\n // Translation node: user-defined fields live inside translation[locale].\n if (\n record.nodeType === 'translation' &&\n record.translation &&\n typeof record.translation === 'object' &&\n !Array.isArray(record.translation)\n ) {\n const firstLocaleValue = Object.values(\n record.translation as Record<string, unknown>\n )[0];\n return buildNestedRenameMapFromContent(firstLocaleValue);\n }\n\n // All other intlayer nodes (enumeration, pluralization, conditions, …)\n // resolve to a single value at runtime through a call the source-code\n // rename walk cannot traverse (e.g. `content.myEnum(count)`), and the\n // JSON renamers only descend into translation nodes. Treat them as\n // leaves so the source and JSON sides always stay consistent.\n return new Map();\n }\n\n // Exclude React elements from being treated as user-defined records.\n // JSX elements in the compiled JSON have a $$typeof property (usually Symbol(react.element)).\n if (\n record.$$typeof ||\n (record.type && record.props && Object.hasOwn(record, 'ref'))\n ) {\n return new Map();\n }\n\n // User-defined record: rename ALL non-reserved keys with stable alphabetic\n // aliases sorted alphabetically so the mapping is deterministic.\n const sortedKeys = Object.keys(record)\n .filter((key) => !RESERVED_CONTENT_FIELD_NAMES.has(key))\n .sort();\n\n const renameMap: NestedRenameMap = new Map();\n\n for (let i = 0; i < sortedKeys.length; i++) {\n const key = sortedKeys[i];\n\n if (!key) continue;\n\n const children = buildNestedRenameMapFromContent(record[key]);\n\n renameMap.set(key, { shortName: generateShortFieldName(i), children });\n }\n\n return renameMap;\n};\n\n/**\n * Walks `fieldPath` through a {@link NestedRenameMap} and returns the entry at\n * the final path segment, or `undefined` when any segment is missing (e.g. the\n * path crosses an array or leaf value whose children are not mapped).\n *\n * Used to locate the rename entry of an opaquely-consumed content value so its\n * children map can be cleared before the JSON rename is applied.\n *\n * @param renameMap - The root rename map to walk.\n * @param fieldPath - Original (pre-rename) field names from the content root.\n */\nexport const getNestedRenameEntryAtPath = (\n renameMap: NestedRenameMap,\n fieldPath: readonly string[]\n): NestedRenameEntry | undefined => {\n let currentRenameMap = renameMap;\n let renameEntry: NestedRenameEntry | undefined;\n\n for (const fieldName of fieldPath) {\n renameEntry = currentRenameMap.get(fieldName);\n if (!renameEntry) return undefined;\n currentRenameMap = renameEntry.children;\n }\n\n return renameEntry;\n};\n\n// ── Serialisation for non-Babel consumers ─────────────────────────────────────\n\n/**\n * JSON-serialisable form of a {@link NestedRenameEntry}.\n *\n * Mirrors `FieldRenameNode` in the `@intlayer/swc` crate — both sides must stay\n * in sync.\n */\nexport type SerializedFieldRenameEntry = {\n /** Short alphabetic alias the field is renamed to (`'a'`, `'b'`, …). */\n shortName: string;\n /** Rename table of the fields nested inside this one. */\n children: SerializedFieldRenameMap;\n};\n\n/** JSON-serialisable form of a {@link NestedRenameMap}. */\nexport type SerializedFieldRenameMap = Record<\n string,\n SerializedFieldRenameEntry\n>;\n\n/** Recursively converts a {@link NestedRenameMap} to its serialisable form. */\nconst serializeNestedRenameMap = (\n renameMap: NestedRenameMap\n): SerializedFieldRenameMap => {\n const serialized: SerializedFieldRenameMap = {};\n\n for (const [fieldName, renameEntry] of renameMap) {\n serialized[fieldName] = {\n shortName: renameEntry.shortName,\n children: serializeNestedRenameMap(renameEntry.children),\n };\n }\n\n return serialized;\n};\n\n/**\n * Converts the field-rename tables of a {@link PruneContext} into a plain JSON\n * object, keyed by dictionary key.\n *\n * Consumed by bundler integrations that cannot run the Babel rename plugin and\n * must forward the tables to another transformer — currently the `@intlayer/swc`\n * Wasm plugin used by Next.js, which rewrites the source accesses itself.\n *\n * Dictionaries flagged as structural edge cases are omitted: the JSON pipeline\n * leaves them untouched, so their source accesses must stay untouched too.\n * Empty tables are omitted as well, so the result is empty when there is\n * nothing to rename.\n */\nexport const serializeFieldRenameMap = (\n pruneContext: PruneContext\n): Record<string, SerializedFieldRenameMap> => {\n const serialized: Record<string, SerializedFieldRenameMap> = {};\n\n for (const [\n dictionaryKey,\n renameMap,\n ] of pruneContext.dictionaryKeyToFieldRenameMap) {\n if (renameMap.size === 0) continue;\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) continue;\n\n serialized[dictionaryKey] = serializeNestedRenameMap(renameMap);\n }\n\n return serialized;\n};\n\n// ── Field-rename Babel plugin ─────────────────────────────────────────────────\n\n/**\n * Walks a MemberExpression chain starting from `startPath`, renaming each\n * property found in `currentRenameMap` at the corresponding nesting level.\n *\n * Numeric computed accesses (array indices such as `[0]`, `[1]`) are treated\n * as transparent pass-throughs: the rename map is kept unchanged and the walk\n * continues past the index. This means `content.field[0].sub` is handled\n * correctly — `field` and `sub` are both renamed while `[0]` is left intact.\n */\nconst walkRenameChain = (\n babelTypes: typeof BabelTypes,\n startPath: NodePath<BabelTypes.Node>,\n currentRenameMap: NestedRenameMap\n): {\n finalPath: NodePath<BabelTypes.Node>;\n finalRenameMap: NestedRenameMap;\n} => {\n let refPath: NodePath<BabelTypes.Node> = startPath;\n let renameMap = currentRenameMap;\n\n while (true) {\n const parentPath = refPath.parentPath;\n if (!parentPath) break;\n\n const parentNode = parentPath.node;\n\n if (\n (!babelTypes.isMemberExpression(parentNode) &&\n !babelTypes.isOptionalMemberExpression(parentNode)) ||\n (parentNode as BabelTypes.MemberExpression).object !== refPath.node\n ) {\n break;\n }\n\n const memberNode = parentNode as BabelTypes.MemberExpression;\n\n // Numeric index access ([0], [1], …): advance past the array accessor\n // without touching the rename map. The next iteration will attempt to\n // rename the property that follows the index.\n if (\n memberNode.computed &&\n babelTypes.isNumericLiteral(memberNode.property)\n ) {\n refPath = parentPath;\n continue;\n }\n\n // Nothing left to rename at this level — stop.\n if (renameMap.size === 0) break;\n\n let fieldName: string | undefined;\n\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n fieldName = memberNode.property.name;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n fieldName = memberNode.property.value;\n } else {\n break; // dynamic computed key – stop\n }\n\n const renameEntry = renameMap.get(fieldName);\n if (!renameEntry) break; // not in map – stop\n\n // Apply the rename\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n memberNode.property.name = renameEntry.shortName;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n memberNode.property.value = renameEntry.shortName;\n }\n\n refPath = parentPath;\n renameMap = renameEntry.children;\n }\n\n return { finalPath: refPath, finalRenameMap: renameMap };\n};\n\n/**\n * Renames the properties of a destructuring `ObjectPattern` using `renameMap`,\n * recursing into nested patterns and following the references of bound local\n * variables.\n *\n * Handled property shapes:\n *\n * { fieldA } → { shortA: fieldA }\n * { fieldA: localVar } → { shortA: localVar }\n * { fieldA = fallback } → { shortA: fieldA = fallback }\n * { fieldA: { nested } } → { shortA: { shortN: nested } }\n * { ['fieldA']: x } → { ['shortA']: x }\n * { [dynamicKey]: x } → left untouched (dynamic key – not renamable)\n *\n * @param babelTypes - Babel types helper.\n * @param objectPattern - The destructuring pattern to rename.\n * @param scopePath - A path whose scope resolves the pattern's bindings.\n * @param renameMap - Rename table for the current nesting level.\n */\nconst renameObjectPatternProperties = (\n babelTypes: typeof BabelTypes,\n objectPattern: BabelTypes.ObjectPattern,\n scopePath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n for (const property of objectPattern.properties) {\n if (!babelTypes.isObjectProperty(property)) continue;\n\n // Computed keys: a static string key ({ ['title']: x }) is renamable in\n // place; any other computed key is dynamic and must be left untouched —\n // replacing it with an identifier would create a variable reference.\n if (property.computed && !babelTypes.isStringLiteral(property.key)) {\n continue;\n }\n\n const keyName = babelTypes.isIdentifier(property.key)\n ? property.key.name\n : babelTypes.isStringLiteral(property.key)\n ? property.key.value\n : null;\n if (!keyName) continue;\n\n const renameEntry = renameMap.get(keyName);\n if (!renameEntry) continue;\n\n if (property.computed) {\n // { ['fieldA']: x } → { ['shortA']: x }\n (property.key as BabelTypes.StringLiteral).value = renameEntry.shortName;\n } else {\n // { fieldA } → { shortA: fieldA }\n // { fieldA: localVar } → { shortA: localVar }\n if (property.shorthand) {\n property.shorthand = false;\n }\n property.key = babelTypes.identifier(renameEntry.shortName);\n }\n\n if (renameEntry.children.size === 0) continue;\n\n // A default value ({ fieldA = fallback }) wraps the actual binding target.\n const bindingTarget = babelTypes.isAssignmentPattern(property.value)\n ? property.value.left\n : property.value;\n\n // Nested pattern: const { fieldA: { nested } } = … — rename its keys\n // with this entry's children map.\n if (babelTypes.isObjectPattern(bindingTarget)) {\n renameObjectPatternProperties(\n babelTypes,\n bindingTarget,\n scopePath,\n renameEntry.children\n );\n continue;\n }\n\n // Identifier binding: recursively walk references to the local variable.\n if (babelTypes.isIdentifier(bindingTarget)) {\n const localVarBinding = scopePath.scope.getBinding(bindingTarget.name);\n if (!localVarBinding) continue;\n\n for (const nestedRefPath of localVarBinding.referencePaths) {\n const { finalPath, finalRenameMap } = walkRenameChain(\n babelTypes,\n nestedRefPath,\n renameEntry.children\n );\n walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);\n }\n }\n }\n};\n\n/**\n * Walks an object-destructuring assignment whose right-hand side is `refPath`,\n * renaming each destructured key that is found in `renameMap`.\n *\n * Handles the \"secondary destructuring\" pattern that `walkRenameChain` cannot\n * reach because the reference is not a MemberExpression:\n *\n * const { webhooksSection } = useIntlayer('build-settings');\n * const { modal, validationErrors } = webhooksSection;\n * → const { a: modal, b: validationErrors } = webhooksSection;\n *\n * After renaming each key, {@link renameObjectPatternProperties} recursively\n * walks references to the newly-bound local variables, calling both\n * `walkRenameChain` (for subsequent member-access chains like\n * `validationErrors.invalidUrl`) and this function again (for further levels\n * of secondary destructuring).\n */\nconst walkObjectDestructuring = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const parentNode = refPath.parent;\n\n // Only handle: const { a, b } = refVar\n if (\n !babelTypes.isVariableDeclarator(parentNode) ||\n !babelTypes.isObjectPattern(parentNode.id) ||\n parentNode.init !== refPath.node\n ) {\n return;\n }\n\n renameObjectPatternProperties(babelTypes, parentNode.id, refPath, renameMap);\n};\n\n/**\n * Collects the local aliases under which `useIntlayer` / `getIntlayer` are\n * imported in the given program (e.g. `import { useIntlayer as useI } …`\n * yields `useI` → `useIntlayer`).\n *\n * Import declarations can only appear at the top level of a module, so the\n * program body is scanned directly instead of traversing the whole AST.\n */\nconst collectIntlayerCallerLocalNames = (\n babelTypes: typeof BabelTypes,\n programNode: BabelTypes.Program\n): Map<string, string> => {\n const intlayerCallerLocalNameMap = new Map<string, string>();\n\n for (const statement of programNode.body) {\n if (!babelTypes.isImportDeclaration(statement)) continue;\n\n for (const importSpecifier of statement.specifiers) {\n if (!babelTypes.isImportSpecifier(importSpecifier)) continue;\n\n const importedName = babelTypes.isIdentifier(importSpecifier.imported)\n ? importSpecifier.imported.name\n : importSpecifier.imported.value;\n\n if (INTLAYER_CALLER_NAMES.includes(importedName as IntlayerCallerName)) {\n intlayerCallerLocalNameMap.set(\n importSpecifier.local.name,\n importedName\n );\n }\n }\n }\n\n return intlayerCallerLocalNameMap;\n};\n\n/**\n * Rewrites dictionary content field accesses in the given program to the\n * short aliases defined in `pruneContext.dictionaryKeyToFieldRenameMap`.\n *\n * Handled patterns (mirrors the usage analyser):\n *\n * const { fieldA, fieldB } = useIntlayer('key')\n * → const { shortA: fieldA, shortB: fieldB } = useIntlayer('key')\n *\n * useIntlayer('key').fieldA\n * → useIntlayer('key').shortA\n *\n * const result = useIntlayer('key'); result.fieldA\n * → const result = useIntlayer('key'); result.shortA\n *\n * const { fieldA } = useIntlayer('key');\n * const { nested } = fieldA; // secondary destructuring\n * → const { shortA: fieldA } = useIntlayer('key');\n * const { shortN: nested } = fieldA;\n *\n * Exposed as a standalone function so that both\n * {@link makeFieldRenameBabelPlugin} and `intlayerMinifyBabelPlugin` can\n * invoke it from their own `Program.exit` visitors.\n */\nexport const renameIntlayerFieldAccesses = (\n babelTypes: typeof BabelTypes,\n programPath: NodePath<BabelTypes.Program>,\n pruneContext: PruneContext\n): void => {\n if (pruneContext.dictionaryKeyToFieldRenameMap.size === 0) return;\n\n const intlayerCallerLocalNameMap = collectIntlayerCallerLocalNames(\n babelTypes,\n programPath.node\n );\n if (intlayerCallerLocalNameMap.size === 0) return;\n\n // Visit all useIntlayer / getIntlayer call-sites and rename field accesses\n programPath.traverse({\n CallExpression: (callExpressionPath) => {\n const calleeNode = callExpressionPath.node.callee;\n let localCallerName: string | undefined;\n\n if (babelTypes.isIdentifier(calleeNode)) {\n localCallerName = calleeNode.name;\n } else if (\n babelTypes.isMemberExpression(calleeNode) &&\n babelTypes.isIdentifier(calleeNode.property)\n ) {\n localCallerName = calleeNode.property.name;\n }\n\n if (!localCallerName || !intlayerCallerLocalNameMap.has(localCallerName))\n return;\n\n const callArguments = callExpressionPath.node.arguments;\n if (callArguments.length === 0) return;\n\n const firstArgument = callArguments[0];\n let dictionaryKey: string | undefined;\n\n if (babelTypes.isStringLiteral(firstArgument)) {\n dictionaryKey = firstArgument.value;\n } else if (\n babelTypes.isTemplateLiteral(firstArgument) &&\n firstArgument.expressions.length === 0 &&\n firstArgument.quasis.length === 1 &&\n firstArgument.quasis[0]\n ) {\n dictionaryKey =\n firstArgument.quasis[0].value.cooked ??\n firstArgument.quasis[0].value.raw;\n }\n\n if (!dictionaryKey) return;\n\n // Dictionaries flagged as structural edge cases are left completely\n // untouched by the JSON pipeline — keep their source accesses untouched\n // too so both sides stay consistent.\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) return;\n\n const fieldRenameMap =\n pruneContext.dictionaryKeyToFieldRenameMap.get(dictionaryKey);\n if (!fieldRenameMap || fieldRenameMap.size === 0) return;\n\n const parentNode = callExpressionPath.parent;\n\n // ── Case 1: const { fieldA, fieldB } = useIntlayer('key') ────────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isObjectPattern(parentNode.id)\n ) {\n walkObjectDestructuring(babelTypes, callExpressionPath, fieldRenameMap);\n return;\n }\n\n // ── Case 2: useIntlayer('key').fieldA.nested ─────────────────────\n if (\n (babelTypes.isMemberExpression(parentNode) ||\n babelTypes.isOptionalMemberExpression(parentNode)) &&\n (parentNode as BabelTypes.MemberExpression).object ===\n callExpressionPath.node\n ) {\n const { finalPath, finalRenameMap } = walkRenameChain(\n babelTypes,\n callExpressionPath,\n fieldRenameMap\n );\n walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);\n return;\n }\n\n // ── Case 3: const result = useIntlayer('key'); result.fieldA ─────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isIdentifier(parentNode.id)\n ) {\n const variableBinding = callExpressionPath.scope.getBinding(\n parentNode.id.name\n );\n if (!variableBinding) return;\n\n for (const variableReferencePath of variableBinding.referencePaths) {\n // Direct access: result.fieldA or const { fieldA } = result\n const { finalPath, finalRenameMap } = walkRenameChain(\n babelTypes,\n variableReferencePath,\n fieldRenameMap\n );\n walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);\n\n // Signal accessor: result().fieldA or const { fieldA } = result()\n // walkRenameChain stops at a CallExpression parent, so we need to\n // start a new walk from the call-expression node itself.\n const refParent = variableReferencePath.parent;\n if (\n (babelTypes.isCallExpression(refParent) ||\n babelTypes.isOptionalCallExpression(refParent)) &&\n (refParent as BabelTypes.CallExpression).callee ===\n variableReferencePath.node\n ) {\n const callPath = variableReferencePath.parentPath;\n if (callPath) {\n const {\n finalPath: signalFinalPath,\n finalRenameMap: signalFinalRenameMap,\n } = walkRenameChain(babelTypes, callPath, fieldRenameMap);\n walkObjectDestructuring(\n babelTypes,\n signalFinalPath,\n signalFinalRenameMap\n );\n }\n }\n }\n }\n },\n });\n};\n\n/**\n * Creates a Babel plugin that rewrites dictionary content field accesses in\n * source files to their short aliases via\n * {@link renameIntlayerFieldAccesses}.\n *\n * This plugin must run in a separate `transformAsync` pass **before**\n * `intlayerOptimizeBabelPlugin`, because the latter replaces `useIntlayer`\n * with `useDictionary`, erasing the dictionary-key information needed here.\n */\nexport const makeFieldRenameBabelPlugin =\n (pruneContext: PruneContext) =>\n ({ types: babelTypes }: { types: typeof BabelTypes }): PluginObject => ({\n name: 'intlayer-field-rename',\n visitor: {\n Program: {\n exit: (programPath) => {\n renameIntlayerFieldAccesses(babelTypes, programPath, pruneContext);\n },\n },\n },\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"babel-plugin-intlayer-field-rename.mjs","names":[],"sources":["../../src/babel-plugin-intlayer-field-rename.ts"],"sourcesContent":["import type { NodePath, PluginObject } from '@babel/core';\nimport type * as BabelTypes from '@babel/types';\nimport {\n CHAINABLE_RUNTIME_METHOD_NAMES,\n INTLAYER_CALLER_NAMES,\n type IntlayerCallerName,\n type NestedRenameEntry,\n type NestedRenameMap,\n type PruneContext,\n} from './babel-plugin-intlayer-usage-analyzer';\n\n// ── Field-name helpers ────────────────────────────────────────────────────────\n\n/**\n * Intlayer internal property names that must never be used as short-name\n * targets. These appear inside content-node values (e.g. `{ nodeType:\n * \"translation\", … }`) and are read by the intlayer runtime.\n */\nconst RESERVED_CONTENT_FIELD_NAMES = new Set(['nodeType']);\n\n/** Alphabet used to derive short field aliases (`a`, `b`, …, `aa`, `ab`, …). */\nconst SHORT_NAME_ALPHABET = 'abcdefghijklmnopqrstuvwxyz';\n\n/**\n * Converts a zero-based index to a short alphabetic identifier.\n * 0 → 'a', 1 → 'b', …, 25 → 'z', 26 → 'aa', 27 → 'ab', …\n */\nexport const generateShortFieldName = (index: number): string => {\n if (!Number.isInteger(index) || index < 0) {\n throw new RangeError(\n `generateShortFieldName expects a non-negative integer index, received: ${index}`\n );\n }\n\n const remainder = index % SHORT_NAME_ALPHABET.length;\n const quotient = Math.floor(index / SHORT_NAME_ALPHABET.length);\n\n return quotient === 0 && SHORT_NAME_ALPHABET[remainder]\n ? SHORT_NAME_ALPHABET[remainder]\n : generateShortFieldName(quotient - 1) + SHORT_NAME_ALPHABET[remainder];\n};\n\n/**\n * Recursively builds a `NestedRenameMap` from a compiled dictionary content\n * value by traversing the intlayer node structure.\n *\n * Rules:\n * - If the value has `nodeType: 'translation'`, user-defined fields live\n * inside `translation[locale]`. Recurse into the first locale's value.\n * - All other intlayer runtime nodes (enumeration, condition, gender, …) are\n * treated as leaves — their internal keys must never be renamed.\n * - Arrays produce an empty children map. Array elements are not traversed\n * because consumers may access them via `.map()` / `.filter()` callbacks,\n * which the source-code rename walk cannot enter. Renaming element fields\n * in the JSON without the matching source-code rename would produce\n * mismatched key names and runtime crashes.\n * The `[0]` pass-through in `walkRenameChain` is preserved so that direct\n * indexed access (`field[0].sub`) silently terminates at the empty children\n * map without breaking anything.\n * - Plain objects are user-defined records: ALL non-reserved keys are renamed\n * with short alphabetic aliases (a, b, c, …) and each value is recursed into.\n * - Primitives produce an empty map (no further renaming).\n *\n * The rename map is built from ALL user-defined fields (not just consumed ones).\n * Both the JSON rename and the source-code rename use the same map, so the\n * short names are always consistent regardless of which fields are pruned.\n *\n * @param contentValue - The dictionary content value to analyse.\n */\nexport const buildNestedRenameMapFromContent = (\n contentValue: unknown\n): NestedRenameMap => {\n if (\n !contentValue ||\n typeof contentValue !== 'object' ||\n Array.isArray(contentValue)\n ) {\n return new Map();\n }\n\n const record = contentValue as Record<string, unknown>;\n\n // Any object with `nodeType: string` is an intlayer runtime node.\n if (typeof record.nodeType === 'string') {\n // Translation node: user-defined fields live inside translation[locale].\n if (\n record.nodeType === 'translation' &&\n record.translation &&\n typeof record.translation === 'object' &&\n !Array.isArray(record.translation)\n ) {\n const firstLocaleValue = Object.values(\n record.translation as Record<string, unknown>\n )[0];\n return buildNestedRenameMapFromContent(firstLocaleValue);\n }\n\n // All other intlayer nodes (enumeration, pluralization, conditions, …)\n // resolve to a single value at runtime through a call the source-code\n // rename walk cannot traverse (e.g. `content.myEnum(count)`), and the\n // JSON renamers only descend into translation nodes. Treat them as\n // leaves so the source and JSON sides always stay consistent.\n return new Map();\n }\n\n // Exclude React elements from being treated as user-defined records.\n // JSX elements in the compiled JSON have a $$typeof property (usually Symbol(react.element)).\n if (\n record.$$typeof ||\n (record.type && record.props && Object.hasOwn(record, 'ref'))\n ) {\n return new Map();\n }\n\n // User-defined record: rename ALL non-reserved keys with stable alphabetic\n // aliases sorted alphabetically so the mapping is deterministic.\n const sortedKeys = Object.keys(record)\n .filter((key) => !RESERVED_CONTENT_FIELD_NAMES.has(key))\n .sort();\n\n const renameMap: NestedRenameMap = new Map();\n\n for (let i = 0; i < sortedKeys.length; i++) {\n const key = sortedKeys[i];\n\n if (!key) continue;\n\n const children = buildNestedRenameMapFromContent(record[key]);\n\n renameMap.set(key, { shortName: generateShortFieldName(i), children });\n }\n\n return renameMap;\n};\n\n/**\n * Walks `fieldPath` through a {@link NestedRenameMap} and returns the entry at\n * the final path segment, or `undefined` when any segment is missing (e.g. the\n * path crosses an array or leaf value whose children are not mapped).\n *\n * Used to locate the rename entry of an opaquely-consumed content value so its\n * children map can be cleared before the JSON rename is applied.\n *\n * @param renameMap - The root rename map to walk.\n * @param fieldPath - Original (pre-rename) field names from the content root.\n */\nexport const getNestedRenameEntryAtPath = (\n renameMap: NestedRenameMap,\n fieldPath: readonly string[]\n): NestedRenameEntry | undefined => {\n let currentRenameMap = renameMap;\n let renameEntry: NestedRenameEntry | undefined;\n\n for (const fieldName of fieldPath) {\n renameEntry = currentRenameMap.get(fieldName);\n if (!renameEntry) return undefined;\n currentRenameMap = renameEntry.children;\n }\n\n return renameEntry;\n};\n\n// ── Serialisation for non-Babel consumers ─────────────────────────────────────\n\n/**\n * JSON-serialisable form of a {@link NestedRenameEntry}.\n *\n * Mirrors `FieldRenameNode` in the `@intlayer/swc` crate — both sides must stay\n * in sync.\n */\nexport type SerializedFieldRenameEntry = {\n /** Short alphabetic alias the field is renamed to (`'a'`, `'b'`, …). */\n shortName: string;\n /** Rename table of the fields nested inside this one. */\n children: SerializedFieldRenameMap;\n};\n\n/** JSON-serialisable form of a {@link NestedRenameMap}. */\nexport type SerializedFieldRenameMap = Record<\n string,\n SerializedFieldRenameEntry\n>;\n\n/** Recursively converts a {@link NestedRenameMap} to its serialisable form. */\nconst serializeNestedRenameMap = (\n renameMap: NestedRenameMap\n): SerializedFieldRenameMap => {\n const serialized: SerializedFieldRenameMap = {};\n\n for (const [fieldName, renameEntry] of renameMap) {\n serialized[fieldName] = {\n shortName: renameEntry.shortName,\n children: serializeNestedRenameMap(renameEntry.children),\n };\n }\n\n return serialized;\n};\n\n/**\n * Converts the field-rename tables of a {@link PruneContext} into a plain JSON\n * object, keyed by dictionary key.\n *\n * Consumed by bundler integrations that cannot run the Babel rename plugin and\n * must forward the tables to another transformer — currently the `@intlayer/swc`\n * Wasm plugin used by Next.js, which rewrites the source accesses itself.\n *\n * Dictionaries flagged as structural edge cases are omitted: the JSON pipeline\n * leaves them untouched, so their source accesses must stay untouched too.\n * Empty tables are omitted as well, so the result is empty when there is\n * nothing to rename.\n */\nexport const serializeFieldRenameMap = (\n pruneContext: PruneContext\n): Record<string, SerializedFieldRenameMap> => {\n const serialized: Record<string, SerializedFieldRenameMap> = {};\n\n for (const [\n dictionaryKey,\n renameMap,\n ] of pruneContext.dictionaryKeyToFieldRenameMap) {\n if (renameMap.size === 0) continue;\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) continue;\n\n serialized[dictionaryKey] = serializeNestedRenameMap(renameMap);\n }\n\n return serialized;\n};\n\n// ── Field-rename Babel plugin ─────────────────────────────────────────────────\n\n/**\n * Walks a MemberExpression chain starting from `startPath`, renaming each\n * property found in `currentRenameMap` at the corresponding nesting level.\n *\n * Numeric computed accesses (array indices such as `[0]`, `[1]`) are treated\n * as transparent pass-throughs: the rename map is kept unchanged and the walk\n * continues past the index. This means `content.field[0].sub` is handled\n * correctly — `field` and `sub` are both renamed while `[0]` is left intact.\n */\nconst walkRenameChain = (\n babelTypes: typeof BabelTypes,\n startPath: NodePath<BabelTypes.Node>,\n currentRenameMap: NestedRenameMap\n): {\n finalPath: NodePath<BabelTypes.Node>;\n finalRenameMap: NestedRenameMap;\n} => {\n let refPath: NodePath<BabelTypes.Node> = startPath;\n let renameMap = currentRenameMap;\n\n while (true) {\n const parentPath = refPath.parentPath;\n if (!parentPath) break;\n\n const parentNode = parentPath.node;\n\n if (\n (!babelTypes.isMemberExpression(parentNode) &&\n !babelTypes.isOptionalMemberExpression(parentNode)) ||\n (parentNode as BabelTypes.MemberExpression).object !== refPath.node\n ) {\n break;\n }\n\n const memberNode = parentNode as BabelTypes.MemberExpression;\n\n // Numeric index access ([0], [1], …): advance past the array accessor\n // without touching the rename map. The next iteration will attempt to\n // rename the property that follows the index.\n if (\n memberNode.computed &&\n babelTypes.isNumericLiteral(memberNode.property)\n ) {\n refPath = parentPath;\n continue;\n }\n\n // Nothing left to rename at this level — stop.\n if (renameMap.size === 0) break;\n\n let fieldName: string | undefined;\n\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n fieldName = memberNode.property.name;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n fieldName = memberNode.property.value;\n } else {\n break; // dynamic computed key – stop\n }\n\n const renameEntry = renameMap.get(fieldName);\n if (!renameEntry) break; // not in map – stop\n\n // Apply the rename\n if (!memberNode.computed && babelTypes.isIdentifier(memberNode.property)) {\n memberNode.property.name = renameEntry.shortName;\n } else if (\n memberNode.computed &&\n babelTypes.isStringLiteral(memberNode.property)\n ) {\n memberNode.property.value = renameEntry.shortName;\n }\n\n refPath = parentPath;\n renameMap = renameEntry.children;\n }\n\n return { finalPath: refPath, finalRenameMap: renameMap };\n};\n\n/**\n * Renames the properties of a destructuring `ObjectPattern` using `renameMap`,\n * recursing into nested patterns and following the references of bound local\n * variables.\n *\n * Handled property shapes:\n *\n * { fieldA } → { shortA: fieldA }\n * { fieldA: localVar } → { shortA: localVar }\n * { fieldA = fallback } → { shortA: fieldA = fallback }\n * { fieldA: { nested } } → { shortA: { shortN: nested } }\n * { ['fieldA']: x } → { ['shortA']: x }\n * { [dynamicKey]: x } → left untouched (dynamic key – not renamable)\n *\n * @param babelTypes - Babel types helper.\n * @param objectPattern - The destructuring pattern to rename.\n * @param scopePath - A path whose scope resolves the pattern's bindings.\n * @param renameMap - Rename table for the current nesting level.\n */\nconst renameObjectPatternProperties = (\n babelTypes: typeof BabelTypes,\n objectPattern: BabelTypes.ObjectPattern,\n scopePath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n for (const property of objectPattern.properties) {\n if (!babelTypes.isObjectProperty(property)) continue;\n\n // Computed keys: a static string key ({ ['title']: x }) is renamable in\n // place; any other computed key is dynamic and must be left untouched —\n // replacing it with an identifier would create a variable reference.\n if (property.computed && !babelTypes.isStringLiteral(property.key)) {\n continue;\n }\n\n const keyName = babelTypes.isIdentifier(property.key)\n ? property.key.name\n : babelTypes.isStringLiteral(property.key)\n ? property.key.value\n : null;\n if (!keyName) continue;\n\n const renameEntry = renameMap.get(keyName);\n if (!renameEntry) continue;\n\n if (property.computed) {\n // { ['fieldA']: x } → { ['shortA']: x }\n (property.key as BabelTypes.StringLiteral).value = renameEntry.shortName;\n } else {\n // { fieldA } → { shortA: fieldA }\n // { fieldA: localVar } → { shortA: localVar }\n if (property.shorthand) {\n property.shorthand = false;\n }\n property.key = babelTypes.identifier(renameEntry.shortName);\n }\n\n if (renameEntry.children.size === 0) continue;\n\n // A default value ({ fieldA = fallback }) wraps the actual binding target.\n const bindingTarget = babelTypes.isAssignmentPattern(property.value)\n ? property.value.left\n : property.value;\n\n // Nested pattern: const { fieldA: { nested } } = … — rename its keys\n // with this entry's children map.\n if (babelTypes.isObjectPattern(bindingTarget)) {\n renameObjectPatternProperties(\n babelTypes,\n bindingTarget,\n scopePath,\n renameEntry.children\n );\n continue;\n }\n\n // Identifier binding: recursively walk references to the local variable.\n if (babelTypes.isIdentifier(bindingTarget)) {\n const localVarBinding = scopePath.scope.getBinding(bindingTarget.name);\n if (!localVarBinding) continue;\n\n for (const nestedRefPath of localVarBinding.referencePaths) {\n const { finalPath, finalRenameMap } = walkRenameChain(\n babelTypes,\n nestedRefPath,\n renameEntry.children\n );\n walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);\n }\n }\n }\n};\n\n/**\n * Walks an object-destructuring assignment whose right-hand side is `refPath`,\n * renaming each destructured key that is found in `renameMap`.\n *\n * Handles the \"secondary destructuring\" pattern that `walkRenameChain` cannot\n * reach because the reference is not a MemberExpression:\n *\n * const { webhooksSection } = useIntlayer('build-settings');\n * const { modal, validationErrors } = webhooksSection;\n * → const { a: modal, b: validationErrors } = webhooksSection;\n *\n * After renaming each key, {@link renameObjectPatternProperties} recursively\n * walks references to the newly-bound local variables, calling both\n * `walkRenameChain` (for subsequent member-access chains like\n * `validationErrors.invalidUrl`) and this function again (for further levels\n * of secondary destructuring).\n */\nconst walkObjectDestructuring = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const parentNode = refPath.parent;\n\n // Only handle: const { a, b } = refVar\n if (\n !babelTypes.isVariableDeclarator(parentNode) ||\n !babelTypes.isObjectPattern(parentNode.id) ||\n parentNode.init !== refPath.node\n ) {\n return;\n }\n\n renameObjectPatternProperties(babelTypes, parentNode.id, refPath, renameMap);\n};\n\n/**\n * Renames every field access reachable from `rootPath`, whose value is the\n * dictionary content root.\n *\n * Combines the three ways a content root is consumed: a member-access chain,\n * a destructuring assignment, and a chainable runtime helper such as\n * `.onChange(cb)`.\n */\nconst renameContentConsumers = (\n babelTypes: typeof BabelTypes,\n rootPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n const { finalPath, finalRenameMap } = walkRenameChain(\n babelTypes,\n rootPath,\n renameMap\n );\n walkObjectDestructuring(babelTypes, finalPath, finalRenameMap);\n renameChainedRuntimeCall(babelTypes, finalPath, finalRenameMap);\n};\n\n/**\n * Handles `content.onChange(cb)` — a runtime subscription rather than a field\n * access (see {@link CHAINABLE_RUNTIME_METHOD_NAMES}).\n *\n * `walkRenameChain` stops at `onChange` because it is absent from the rename\n * map, which would leave the callback body reading the original field names\n * while the compiled JSON has already been renamed. This restarts the rename\n * walk on both sides of the call:\n *\n * - the callback's first parameter receives the same content root, so its\n * accesses are renamed with the same map;\n * - the helper returns the content object, so the chain continues past it.\n *\n * @param refPath - Path whose value is the content root (the object the\n * chainable method would be called on).\n */\nconst renameChainedRuntimeCall = (\n babelTypes: typeof BabelTypes,\n refPath: NodePath<BabelTypes.Node>,\n renameMap: NestedRenameMap\n): void => {\n if (renameMap.size === 0) return;\n\n const memberPath = refPath.parentPath;\n if (!memberPath) return;\n\n const memberNode = memberPath.node;\n if (\n (!babelTypes.isMemberExpression(memberNode) &&\n !babelTypes.isOptionalMemberExpression(memberNode)) ||\n (memberNode as BabelTypes.MemberExpression).object !== refPath.node\n ) {\n return;\n }\n\n const propertyNode = (memberNode as BabelTypes.MemberExpression).property;\n const methodName = (memberNode as BabelTypes.MemberExpression).computed\n ? babelTypes.isStringLiteral(propertyNode)\n ? propertyNode.value\n : undefined\n : babelTypes.isIdentifier(propertyNode)\n ? propertyNode.name\n : undefined;\n\n if (!methodName || !CHAINABLE_RUNTIME_METHOD_NAMES.has(methodName)) return;\n\n const callPath = memberPath.parentPath;\n if (!callPath) return;\n if (!callPath.isCallExpression() && !callPath.isOptionalCallExpression()) {\n return;\n }\n if ((callPath.node as BabelTypes.CallExpression).callee !== memberNode) {\n return;\n }\n\n const argumentPaths = callPath.get(\n 'arguments'\n ) as NodePath<BabelTypes.Node>[];\n\n for (const argumentPath of argumentPaths) {\n if (\n !argumentPath.isArrowFunctionExpression() &&\n !argumentPath.isFunctionExpression()\n ) {\n continue;\n }\n\n const [firstParameterPath] = argumentPath.get(\n 'params'\n ) as NodePath<BabelTypes.Node>[];\n if (!firstParameterPath) continue;\n\n // ({ title }) => … — destructured directly in the parameter list.\n if (firstParameterPath.isObjectPattern()) {\n renameObjectPatternProperties(\n babelTypes,\n firstParameterPath.node,\n argumentPath,\n renameMap\n );\n continue;\n }\n\n // (content) => … — rename each access on the parameter.\n if (!firstParameterPath.isIdentifier()) continue;\n\n const parameterBinding = argumentPath.scope.getBinding(\n firstParameterPath.node.name\n );\n if (!parameterBinding) continue;\n\n for (const parameterRefPath of parameterBinding.referencePaths) {\n renameContentConsumers(babelTypes, parameterRefPath, renameMap);\n }\n }\n\n // The helper returns the content object itself, so keep walking past it —\n // both when the result is used inline and when it is stored in a variable\n // (`const content = useIntlayer('key').onChange(cb)`).\n renameContentConsumers(babelTypes, callPath, renameMap);\n\n const declaratorNode = callPath.parent;\n if (\n babelTypes.isVariableDeclarator(declaratorNode) &&\n babelTypes.isIdentifier(declaratorNode.id) &&\n declaratorNode.init === callPath.node\n ) {\n const resultBinding = callPath.scope.getBinding(declaratorNode.id.name);\n for (const resultRefPath of resultBinding?.referencePaths ?? []) {\n renameContentConsumers(babelTypes, resultRefPath, renameMap);\n }\n }\n};\n\n/**\n * Collects the local aliases under which `useIntlayer` / `getIntlayer` are\n * imported in the given program (e.g. `import { useIntlayer as useI } …`\n * yields `useI` → `useIntlayer`).\n *\n * Import declarations can only appear at the top level of a module, so the\n * program body is scanned directly instead of traversing the whole AST.\n */\nconst collectIntlayerCallerLocalNames = (\n babelTypes: typeof BabelTypes,\n programNode: BabelTypes.Program\n): Map<string, string> => {\n const intlayerCallerLocalNameMap = new Map<string, string>();\n\n for (const statement of programNode.body) {\n if (!babelTypes.isImportDeclaration(statement)) continue;\n\n for (const importSpecifier of statement.specifiers) {\n if (!babelTypes.isImportSpecifier(importSpecifier)) continue;\n\n const importedName = babelTypes.isIdentifier(importSpecifier.imported)\n ? importSpecifier.imported.name\n : importSpecifier.imported.value;\n\n if (INTLAYER_CALLER_NAMES.includes(importedName as IntlayerCallerName)) {\n intlayerCallerLocalNameMap.set(\n importSpecifier.local.name,\n importedName\n );\n }\n }\n }\n\n return intlayerCallerLocalNameMap;\n};\n\n/**\n * Rewrites dictionary content field accesses in the given program to the\n * short aliases defined in `pruneContext.dictionaryKeyToFieldRenameMap`.\n *\n * Handled patterns (mirrors the usage analyser):\n *\n * const { fieldA, fieldB } = useIntlayer('key')\n * → const { shortA: fieldA, shortB: fieldB } = useIntlayer('key')\n *\n * useIntlayer('key').fieldA\n * → useIntlayer('key').shortA\n *\n * const result = useIntlayer('key'); result.fieldA\n * → const result = useIntlayer('key'); result.shortA\n *\n * const { fieldA } = useIntlayer('key');\n * const { nested } = fieldA; // secondary destructuring\n * → const { shortA: fieldA } = useIntlayer('key');\n * const { shortN: nested } = fieldA;\n *\n * Exposed as a standalone function so that both\n * {@link makeFieldRenameBabelPlugin} and `intlayerMinifyBabelPlugin` can\n * invoke it from their own `Program.exit` visitors.\n */\nexport const renameIntlayerFieldAccesses = (\n babelTypes: typeof BabelTypes,\n programPath: NodePath<BabelTypes.Program>,\n pruneContext: PruneContext\n): void => {\n if (pruneContext.dictionaryKeyToFieldRenameMap.size === 0) return;\n\n const intlayerCallerLocalNameMap = collectIntlayerCallerLocalNames(\n babelTypes,\n programPath.node\n );\n if (intlayerCallerLocalNameMap.size === 0) return;\n\n // Visit all useIntlayer / getIntlayer call-sites and rename field accesses\n programPath.traverse({\n CallExpression: (callExpressionPath) => {\n const calleeNode = callExpressionPath.node.callee;\n let localCallerName: string | undefined;\n\n if (babelTypes.isIdentifier(calleeNode)) {\n localCallerName = calleeNode.name;\n } else if (\n babelTypes.isMemberExpression(calleeNode) &&\n babelTypes.isIdentifier(calleeNode.property)\n ) {\n localCallerName = calleeNode.property.name;\n }\n\n if (!localCallerName || !intlayerCallerLocalNameMap.has(localCallerName))\n return;\n\n const callArguments = callExpressionPath.node.arguments;\n if (callArguments.length === 0) return;\n\n const firstArgument = callArguments[0];\n let dictionaryKey: string | undefined;\n\n if (babelTypes.isStringLiteral(firstArgument)) {\n dictionaryKey = firstArgument.value;\n } else if (\n babelTypes.isTemplateLiteral(firstArgument) &&\n firstArgument.expressions.length === 0 &&\n firstArgument.quasis.length === 1 &&\n firstArgument.quasis[0]\n ) {\n dictionaryKey =\n firstArgument.quasis[0].value.cooked ??\n firstArgument.quasis[0].value.raw;\n }\n\n if (!dictionaryKey) return;\n\n // Dictionaries flagged as structural edge cases are left completely\n // untouched by the JSON pipeline — keep their source accesses untouched\n // too so both sides stay consistent.\n if (pruneContext.dictionariesWithEdgeCases.has(dictionaryKey)) return;\n\n const fieldRenameMap =\n pruneContext.dictionaryKeyToFieldRenameMap.get(dictionaryKey);\n if (!fieldRenameMap || fieldRenameMap.size === 0) return;\n\n const parentNode = callExpressionPath.parent;\n\n // ── Case 1: const { fieldA, fieldB } = useIntlayer('key') ────────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isObjectPattern(parentNode.id)\n ) {\n walkObjectDestructuring(babelTypes, callExpressionPath, fieldRenameMap);\n return;\n }\n\n // ── Case 2: useIntlayer('key').fieldA.nested ─────────────────────\n // (also useIntlayer('key').onChange(cb))\n if (\n (babelTypes.isMemberExpression(parentNode) ||\n babelTypes.isOptionalMemberExpression(parentNode)) &&\n (parentNode as BabelTypes.MemberExpression).object ===\n callExpressionPath.node\n ) {\n renameContentConsumers(babelTypes, callExpressionPath, fieldRenameMap);\n return;\n }\n\n // ── Case 3: const result = useIntlayer('key'); result.fieldA ─────\n if (\n babelTypes.isVariableDeclarator(parentNode) &&\n babelTypes.isIdentifier(parentNode.id)\n ) {\n const variableBinding = callExpressionPath.scope.getBinding(\n parentNode.id.name\n );\n if (!variableBinding) return;\n\n for (const variableReferencePath of variableBinding.referencePaths) {\n // Direct access: result.fieldA, const { fieldA } = result, or the\n // chainable result.onChange(cb)\n renameContentConsumers(\n babelTypes,\n variableReferencePath,\n fieldRenameMap\n );\n\n // Signal accessor: result().fieldA or const { fieldA } = result()\n // walkRenameChain stops at a CallExpression parent, so we need to\n // start a new walk from the call-expression node itself.\n const refParent = variableReferencePath.parent;\n if (\n (babelTypes.isCallExpression(refParent) ||\n babelTypes.isOptionalCallExpression(refParent)) &&\n (refParent as BabelTypes.CallExpression).callee ===\n variableReferencePath.node\n ) {\n const callPath = variableReferencePath.parentPath;\n if (callPath) {\n renameContentConsumers(babelTypes, callPath, fieldRenameMap);\n }\n }\n }\n }\n },\n });\n};\n\n/**\n * Creates a Babel plugin that rewrites dictionary content field accesses in\n * source files to their short aliases via\n * {@link renameIntlayerFieldAccesses}.\n *\n * This plugin must run in a separate `transformAsync` pass **before**\n * `intlayerOptimizeBabelPlugin`, because the latter replaces `useIntlayer`\n * with `useDictionary`, erasing the dictionary-key information needed here.\n */\nexport const makeFieldRenameBabelPlugin =\n (pruneContext: PruneContext) =>\n ({ types: babelTypes }: { types: typeof BabelTypes }): PluginObject => ({\n name: 'intlayer-field-rename',\n visitor: {\n Program: {\n exit: (programPath) => {\n renameIntlayerFieldAccesses(babelTypes, programPath, pruneContext);\n },\n },\n },\n });\n"],"mappings":"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"}