@intlayer/babel 8.2.3 → 8.3.0-canary.0

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 (83) hide show
  1. package/dist/cjs/babel-plugin-intlayer-extract.cjs +1 -1
  2. package/dist/cjs/babel-plugin-intlayer-extract.cjs.map +1 -1
  3. package/dist/cjs/babel-plugin-intlayer-optimize.cjs +1 -1
  4. package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
  5. package/dist/cjs/extractContent/contentWriter.cjs +1 -1
  6. package/dist/cjs/extractContent/contentWriter.cjs.map +1 -1
  7. package/dist/cjs/extractContent/extractContent.cjs +1 -1
  8. package/dist/cjs/extractContent/extractContent.cjs.map +1 -1
  9. package/dist/cjs/extractContent/index.cjs +1 -1
  10. package/dist/cjs/extractContent/processTsxFile.cjs +5 -5
  11. package/dist/cjs/extractContent/processTsxFile.cjs.map +1 -1
  12. package/dist/cjs/extractContent/utils/constants.cjs +1 -1
  13. package/dist/cjs/extractContent/utils/constants.cjs.map +1 -1
  14. package/dist/cjs/extractContent/utils/detectPackageName.cjs +1 -1
  15. package/dist/cjs/extractContent/utils/detectPackageName.cjs.map +1 -1
  16. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs +2 -0
  17. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs.map +1 -0
  18. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs +1 -1
  19. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs.map +1 -1
  20. package/dist/cjs/extractContent/utils/getOrGenerateKey.cjs.map +1 -1
  21. package/dist/cjs/extractContent/utils/index.cjs +1 -1
  22. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs +1 -1
  23. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs.map +1 -1
  24. package/dist/cjs/getExtractPluginOptions.cjs +1 -1
  25. package/dist/cjs/getExtractPluginOptions.cjs.map +1 -1
  26. package/dist/cjs/getOptimizePluginOptions.cjs +1 -1
  27. package/dist/cjs/getOptimizePluginOptions.cjs.map +1 -1
  28. package/dist/cjs/index.cjs +1 -1
  29. package/dist/esm/babel-plugin-intlayer-extract.mjs +1 -1
  30. package/dist/esm/babel-plugin-intlayer-extract.mjs.map +1 -1
  31. package/dist/esm/babel-plugin-intlayer-optimize.mjs +1 -1
  32. package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
  33. package/dist/esm/extractContent/contentWriter.mjs +1 -1
  34. package/dist/esm/extractContent/contentWriter.mjs.map +1 -1
  35. package/dist/esm/extractContent/extractContent.mjs +1 -1
  36. package/dist/esm/extractContent/extractContent.mjs.map +1 -1
  37. package/dist/esm/extractContent/index.mjs +1 -1
  38. package/dist/esm/extractContent/processTsxFile.mjs +5 -5
  39. package/dist/esm/extractContent/processTsxFile.mjs.map +1 -1
  40. package/dist/esm/extractContent/utils/constants.mjs +1 -1
  41. package/dist/esm/extractContent/utils/constants.mjs.map +1 -1
  42. package/dist/esm/extractContent/utils/detectPackageName.mjs +1 -1
  43. package/dist/esm/extractContent/utils/detectPackageName.mjs.map +1 -1
  44. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs +2 -0
  45. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs.map +1 -0
  46. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs +1 -1
  47. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs.map +1 -1
  48. package/dist/esm/extractContent/utils/getOrGenerateKey.mjs.map +1 -1
  49. package/dist/esm/extractContent/utils/index.mjs +1 -1
  50. package/dist/esm/extractContent/utils/resolveDictionaryKey.mjs +1 -1
  51. package/dist/esm/extractContent/utils/resolveDictionaryKey.mjs.map +1 -1
  52. package/dist/esm/getExtractPluginOptions.mjs +1 -1
  53. package/dist/esm/getExtractPluginOptions.mjs.map +1 -1
  54. package/dist/esm/getOptimizePluginOptions.mjs +1 -1
  55. package/dist/esm/getOptimizePluginOptions.mjs.map +1 -1
  56. package/dist/esm/index.mjs +1 -1
  57. package/dist/types/babel-plugin-intlayer-extract.d.ts +14 -9
  58. package/dist/types/babel-plugin-intlayer-extract.d.ts.map +1 -1
  59. package/dist/types/extractContent/babelProcessor.d.ts +1 -1
  60. package/dist/types/extractContent/contentWriter.d.ts +22 -13
  61. package/dist/types/extractContent/contentWriter.d.ts.map +1 -1
  62. package/dist/types/extractContent/extractContent.d.ts +6 -30
  63. package/dist/types/extractContent/extractContent.d.ts.map +1 -1
  64. package/dist/types/extractContent/index.d.ts +8 -3
  65. package/dist/types/extractContent/processTsxFile.d.ts +3 -2
  66. package/dist/types/extractContent/processTsxFile.d.ts.map +1 -1
  67. package/dist/types/extractContent/utils/constants.d.ts +6 -2
  68. package/dist/types/extractContent/utils/constants.d.ts.map +1 -1
  69. package/dist/types/extractContent/utils/detectPackageName.d.ts +3 -1
  70. package/dist/types/extractContent/utils/detectPackageName.d.ts.map +1 -1
  71. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts +28 -0
  72. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts.map +1 -0
  73. package/dist/types/extractContent/utils/extractDictionaryKey.d.ts +1 -1
  74. package/dist/types/extractContent/utils/extractDictionaryKey.d.ts.map +1 -1
  75. package/dist/types/extractContent/utils/index.d.ts +3 -2
  76. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts +1 -1
  77. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts.map +1 -1
  78. package/dist/types/getExtractPluginOptions.d.ts +9 -2
  79. package/dist/types/getExtractPluginOptions.d.ts.map +1 -1
  80. package/dist/types/getOptimizePluginOptions.d.ts +1 -1
  81. package/dist/types/getOptimizePluginOptions.d.ts.map +1 -1
  82. package/dist/types/index.d.ts +9 -4
  83. package/package.json +21 -22
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./constants.cjs`),t=require(`./detectPackageName.cjs`),n=require(`./extractDictionaryKey.cjs`),r=require(`./generateKey.cjs`),i=require(`./getComponentName.cjs`),a=require(`./getExistingIntlayerInfo.cjs`),o=require(`./getOrGenerateKey.cjs`),s=require(`./resolveDictionaryKey.cjs`),c=require(`./shouldExtract.cjs`);exports.ATTRIBUTES_TO_EXTRACT=e.ATTRIBUTES_TO_EXTRACT,exports.detectPackageName=t.detectPackageName,exports.extractDictionaryKey=n.extractDictionaryKey,exports.extractDictionaryKeyFromPath=n.extractDictionaryKeyFromPath,exports.generateKey=r.generateKey,exports.getComponentName=i.getComponentName,exports.getExistingIntlayerInfo=a.getExistingIntlayerInfo,exports.getOrGenerateKey=o.getOrGenerateKey,exports.packageList=e.packageList,exports.resolveDictionaryKey=s.resolveDictionaryKey,exports.shouldExtract=c.shouldExtract;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./extractDictionaryKey.cjs`),t=require(`./extractDictionaryInfo.cjs`),n=require(`./constants.cjs`),r=require(`./detectPackageName.cjs`),i=require(`./generateKey.cjs`),a=require(`./getComponentName.cjs`),o=require(`./getExistingIntlayerInfo.cjs`),s=require(`./getOrGenerateKey.cjs`),c=require(`./resolveDictionaryKey.cjs`),l=require(`./shouldExtract.cjs`);exports.ATTRIBUTES_TO_EXTRACT=n.ATTRIBUTES_TO_EXTRACT,exports.SERVER_CAPABLE_PACKAGES=n.SERVER_CAPABLE_PACKAGES,exports.detectPackageName=r.detectPackageName,exports.extractDictionaryInfo=t.extractDictionaryInfo,exports.extractDictionaryKey=e.extractDictionaryKey,exports.extractDictionaryKeyFromPath=e.extractDictionaryKeyFromPath,exports.generateKey=i.generateKey,exports.getComponentName=a.getComponentName,exports.getExistingIntlayerInfo=o.getExistingIntlayerInfo,exports.getOrGenerateKey=s.getOrGenerateKey,exports.getOutput=t.getOutput,exports.packageList=n.packageList,exports.resolveContentFilePaths=t.resolveContentFilePaths,exports.resolveDictionaryKey=c.resolveDictionaryKey,exports.shouldExtract=l.shouldExtract;
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../../_virtual/_rolldown/runtime.cjs`);let e=require(`node:path`),t=require(`node:fs`),n=require(`@intlayer/unmerged-dictionaries-entry`);const r=(r,i,a,o,s=new Set)=>{let c=o??(0,n.getUnmergedDictionaries)(a)??{},{fileExtensions:l}=a.content,u=(0,e.dirname)(i),d=l[0],f=d.startsWith(`.`)?d:`.${d}`,p=0;for(;p<100;){let n=p===0?r:`${r}${p}`,i=c[n],a=(0,e.join)(u,`${n}${f}`),o=s.has(n),l=i&&i.length>0,d=(0,t.existsSync)(a);if(!o&&!l&&!d)return n;p++}return r};exports.resolveDictionaryKey=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../../_virtual/_rolldown/runtime.cjs`);let e=require(`node:fs`),t=require(`node:path`),n=require(`@intlayer/unmerged-dictionaries-entry`);const r=(r,i,a,o,s=new Set)=>{let c=o??(0,n.getUnmergedDictionaries)(a)??{},{fileExtensions:l}=a.content,u=(0,t.dirname)(i),d=l[0],f=d.startsWith(`.`)?d:`.${d}`,p=0;for(;p<100;){let n=p===0?r:`${r}${p}`,i=c[n],a=(0,t.join)(u,`${n}${f}`),o=s.has(n),l=i&&i.length>0,d=(0,e.existsSync)(a);if(!o&&!l&&!d)return n;p++}return r};exports.resolveDictionaryKey=r;
2
2
  //# sourceMappingURL=resolveDictionaryKey.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolveDictionaryKey.cjs","names":[],"sources":["../../../../src/extractContent/utils/resolveDictionaryKey.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { Dictionary, IntlayerConfig } from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\n/**\n * Resolves a unique dictionary key, checking for existing dictionaries and files.\n * Note: this chokidar-specific variant fetches unmergedDictionaries internally\n * from the configuration (unlike the `@intlayer/babel` version which takes it as a parameter).\n */\nexport const resolveDictionaryKey = (\n initialKey: string,\n filePath: string,\n configuration: IntlayerConfig,\n unmergedDictionaries?: Record<string, unknown>,\n usedKeys: Set<string> = new Set()\n): string => {\n const dicts =\n unmergedDictionaries ?? getUnmergedDictionaries(configuration) ?? {};\n\n const { fileExtensions } = configuration.content;\n\n const dirName = dirname(filePath);\n const firstExtension = fileExtensions[0];\n const extension = firstExtension.startsWith('.')\n ? firstExtension\n : `.${firstExtension}`;\n\n let index = 0;\n\n while (index < 100) {\n const keyToTest = index === 0 ? initialKey : `${initialKey}${index}`;\n const dictionaries = dicts[keyToTest] as Dictionary[] | undefined;\n const contentFilePath = join(dirName, `${keyToTest}${extension}`);\n const isKeyUsed = usedKeys.has(keyToTest);\n const hasDictionaries = dictionaries && dictionaries.length > 0;\n const fileExists = existsSync(contentFilePath);\n\n if (!isKeyUsed && !hasDictionaries && !fileExists) {\n return keyToTest;\n }\n index++;\n }\n\n return initialKey;\n};\n"],"mappings":"sNAUA,MAAa,GACX,EACA,EACA,EACA,EACA,EAAwB,IAAI,MACjB,CACX,IAAM,EACJ,IAAA,EAAA,EAAA,yBAAgD,EAAc,EAAI,EAAE,CAEhE,CAAE,kBAAmB,EAAc,QAEnC,GAAA,EAAA,EAAA,SAAkB,EAAS,CAC3B,EAAiB,EAAe,GAChC,EAAY,EAAe,WAAW,IAAI,CAC5C,EACA,IAAI,IAEJ,EAAQ,EAEZ,KAAO,EAAQ,KAAK,CAClB,IAAM,EAAY,IAAU,EAAI,EAAa,GAAG,IAAa,IACvD,EAAe,EAAM,GACrB,GAAA,EAAA,EAAA,MAAuB,EAAS,GAAG,IAAY,IAAY,CAC3D,EAAY,EAAS,IAAI,EAAU,CACnC,EAAkB,GAAgB,EAAa,OAAS,EACxD,GAAA,EAAA,EAAA,YAAwB,EAAgB,CAE9C,GAAI,CAAC,GAAa,CAAC,GAAmB,CAAC,EACrC,OAAO,EAET,IAGF,OAAO"}
1
+ {"version":3,"file":"resolveDictionaryKey.cjs","names":[],"sources":["../../../../src/extractContent/utils/resolveDictionaryKey.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\n/**\n * Resolves a unique dictionary key, checking for existing dictionaries and files.\n * Note: this chokidar-specific variant fetches unmergedDictionaries internally\n * from the configuration (unlike the `@intlayer/babel` version which takes it as a parameter).\n */\nexport const resolveDictionaryKey = (\n initialKey: string,\n filePath: string,\n configuration: IntlayerConfig,\n unmergedDictionaries?: Record<string, unknown>,\n usedKeys: Set<string> = new Set()\n): string => {\n const dicts =\n unmergedDictionaries ?? getUnmergedDictionaries(configuration) ?? {};\n\n const { fileExtensions } = configuration.content;\n\n const dirName = dirname(filePath);\n const firstExtension = fileExtensions[0];\n const extension = firstExtension.startsWith('.')\n ? firstExtension\n : `.${firstExtension}`;\n\n let index = 0;\n\n while (index < 100) {\n const keyToTest = index === 0 ? initialKey : `${initialKey}${index}`;\n const dictionaries = dicts[keyToTest] as Dictionary[] | undefined;\n const contentFilePath = join(dirName, `${keyToTest}${extension}`);\n const isKeyUsed = usedKeys.has(keyToTest);\n const hasDictionaries = dictionaries && dictionaries.length > 0;\n const fileExists = existsSync(contentFilePath);\n\n if (!isKeyUsed && !hasDictionaries && !fileExists) {\n return keyToTest;\n }\n index++;\n }\n\n return initialKey;\n};\n"],"mappings":"sNAWA,MAAa,GACX,EACA,EACA,EACA,EACA,EAAwB,IAAI,MACjB,CACX,IAAM,EACJ,IAAA,EAAA,EAAA,yBAAgD,EAAc,EAAI,EAAE,CAEhE,CAAE,kBAAmB,EAAc,QAEnC,GAAA,EAAA,EAAA,SAAkB,EAAS,CAC3B,EAAiB,EAAe,GAChC,EAAY,EAAe,WAAW,IAAI,CAC5C,EACA,IAAI,IAEJ,EAAQ,EAEZ,KAAO,EAAQ,KAAK,CAClB,IAAM,EAAY,IAAU,EAAI,EAAa,GAAG,IAAa,IACvD,EAAe,EAAM,GACrB,GAAA,EAAA,EAAA,MAAuB,EAAS,GAAG,IAAY,IAAY,CAC3D,EAAY,EAAS,IAAI,EAAU,CACnC,EAAkB,GAAgB,EAAa,OAAS,EACxD,GAAA,EAAA,EAAA,YAAwB,EAAgB,CAE9C,GAAI,CAAC,GAAa,CAAC,GAAmB,CAAC,EACrC,OAAO,EAET,IAGF,OAAO"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./_virtual/_rolldown/runtime.cjs`);let e=require(`node:path`),t=require(`@intlayer/config/logger`),n=require(`@intlayer/config/node`),r=require(`node:fs`),i=require(`node:fs/promises`),a=require(`@intlayer/chokidar/build`);const o=(o=process.env.INTLAYER_IS_DEV_COMMAND)=>{let s=(0,n.getConfiguration)(),{baseDir:c}=s.content,l=(0,e.join)(c,s.compiler?.outputDir??`compiler`),u=async e=>{try{if(!(0,r.existsSync)(e))return null;let t=await(0,i.readFile)(e,`utf-8`);if(!t||t.trim()===``)return null;let n=JSON.parse(t);return Array.isArray(n)?n[0]??null:n}catch(t){return(0,r.existsSync)(e)&&(await(0,i.readFile)(e,`utf-8`)).trim()!==``&&console.warn(`[intlayer] Warning: Failed to read existing dictionary at ${e}. It might be corrupt. Translations may be lost. Error:`,t),null}},d=(e,t,n)=>{let r={},i=t?.content,a=Object.keys(e).sort();for(let t of a){let a=e[t],o=i?.[t];o&&o.nodeType===`translation`&&o.translation?r[t]={...o,nodeType:`translation`,translation:{...o.translation,[n]:o.translation[n]??a}}:r[t]={nodeType:`translation`,translation:{[n]:a}}}return r},f=async t=>{let{dictionaryKey:n,content:r,locale:i}=t;try{let t=await u((0,e.join)(l,`${n}.content.json`)),o=d(r,t,i),f={...t,key:n,content:o,filePath:(0,e.join)((0,e.relative)(c,l),`${n}.content.json`)},p=await(0,a.writeContentDeclaration)(f,s,{newDictionariesPath:(0,e.relative)(c,l)});await(0,a.buildDictionary)([{...f,filePath:(0,e.relative)(c,p.path)}],s)}catch(e){if(console.error(`[intlayer] Failed to process extracted content for ${n}:`,e),e instanceof SyntaxError&&e.message.includes(`Unexpected end of JSON input`)){let t=e.message.match(/^(.*\.json):\s*Unexpected end of JSON input/);if(t){let e=t[1];try{let t=require(`fs`).readFileSync(e,`utf-8`);console.error(`[intlayer] Content of the corrupted file (${e}):\n"${t}"`)}catch(t){console.error(`[intlayer] Could not read corrupted file ${e}`,t)}}}}},p=String(o)===`true`,m=s.compiler?.enabled===`build-only`?!p:s.compiler?.enabled??!0,h=(0,t.getAppLogger)(s);return s.compiler?.enabled===`build-only`&&p&&h(`${(0,t.colorize)(`Compiler:`,t.ANSIColors.GREY_DARK)} i18n function is not inserted in the code in dev mode to optimize build time. (to test i18n in dev mode set compiler.enabled to true)`),{enabled:m,defaultLocale:s.internationalization.defaultLocale,prefix:s.compiler?.dictionaryKeyPrefix,saveComponents:s.compiler?.saveComponents,onExtract:f}};exports.getExtractPluginOptions=o;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./_virtual/_rolldown/runtime.cjs`);const e=require(`./extractContent/contentWriter.cjs`);let t=require(`@intlayer/chokidar/utils`),n=require(`@intlayer/config/logger`),r=require(`@intlayer/config/node`);const i=(i=(0,r.getConfiguration)(),a=process.env.INTLAYER_IS_DEV_COMMAND)=>{let o=String(a)===`true`,s=o?`dev`:`build`,c=(0,n.getAppLogger)(i);i.compiler?.enabled===`build-only`&&o&&c(`${(0,n.colorize)(`Compiler:`,n.ANSIColors.GREY_DARK)} i18n function is not inserted in the code in dev mode to optimize build time. (to test i18n in dev mode set compiler.enabled to true)`);let l=i.compiler?.enabled??r.DefaultValues.Compiler.COMPILER_ENABLED;l===`build-only`&&(l=s?s===`build`:process.env.NODE_ENV===`production`);let u=(0,t.buildFilesList)({transformPattern:i.build.traversePattern??i.compiler?.transformPattern,excludePattern:[...i.content.fileExtensions.map(e=>`**/*${e}`),...Array.isArray(i.compiler.excludePattern)?i.compiler.excludePattern:[i.compiler.excludePattern]],baseDir:i.system.baseDir});return{enabled:l,configuration:i,filesList:u,onExtract:async({dictionaryKey:t,content:r,filePath:a})=>{try{await e.writeContentHelper(r,t,a,i)}catch(e){c([`Failed to process extracted content for ${(0,n.colorizeKey)(t)}:`,e],{level:`error`})}}}};exports.getExtractPluginOptions=i;
2
2
  //# sourceMappingURL=getExtractPluginOptions.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getExtractPluginOptions.cjs","names":["ANSIColors"],"sources":["../../src/getExtractPluginOptions.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport {\n buildDictionary,\n writeContentDeclaration,\n} from '@intlayer/chokidar/build';\nimport { ANSIColors, colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport type { Dictionary } from '@intlayer/types';\nimport type {\n ExtractPluginOptions,\n ExtractResult,\n} from './babel-plugin-intlayer-extract';\n\n/**\n * Translation node structure used in dictionaries\n */\ntype TranslationNode = {\n nodeType: 'translation';\n translation: Record<string, string>;\n};\n\n/**\n * Dictionary content structure - map of keys to translation nodes\n */\ntype DictionaryContentMap = Record<string, TranslationNode>;\n\n/**\n * Get the options for the Intlayer Babel extraction plugin\n * This function loads the Intlayer configuration and sets up the onExtract callback\n * to write dictionaries to the filesystem.\n */\nexport const getExtractPluginOptions = (\n isDev = process.env.INTLAYER_IS_DEV_COMMAND\n): ExtractPluginOptions => {\n const config = getConfiguration();\n const { baseDir } = config.content;\n\n const compilerDir = join(baseDir, config.compiler?.outputDir ?? 'compiler');\n\n /**\n * Read existing dictionary file if it exists\n */\n const readExistingDictionary = async (\n dictionaryPath: string\n ): Promise<Dictionary | null> => {\n try {\n if (!existsSync(dictionaryPath)) {\n return null;\n }\n const content = await readFile(dictionaryPath, 'utf-8');\n\n if (!content || content.trim() === '') {\n return null;\n }\n\n const parsed = JSON.parse(content);\n\n if (Array.isArray(parsed)) {\n return (parsed[0] ?? null) as Dictionary | null;\n }\n\n return parsed as Dictionary;\n } catch (error) {\n if (existsSync(dictionaryPath)) {\n const content = await readFile(dictionaryPath, 'utf-8');\n\n if (content.trim() !== '') {\n console.warn(\n `[intlayer] Warning: Failed to read existing dictionary at ${dictionaryPath}. It might be corrupt. Translations may be lost. Error:`,\n error\n );\n }\n }\n return null;\n }\n };\n\n /**\n * Merge extracted content with existing dictionary, preserving translations.\n * - Keys in extracted but not in existing: added with default locale only\n * - Keys in both: preserve existing translations, update default locale value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\n const mergeWithExistingDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n ): DictionaryContentMap => {\n const mergedContent: DictionaryContentMap = {};\n const existingContent = existingDictionary?.content as\n | DictionaryContentMap\n | undefined;\n\n const sortedKeys = Object.keys(extractedContent).sort();\n\n for (const key of sortedKeys) {\n const value = extractedContent[key];\n const existingEntry = existingContent?.[key];\n\n if (\n existingEntry &&\n existingEntry.nodeType === 'translation' &&\n existingEntry.translation\n ) {\n // Key exists in both - preserve existing translations AND existing metadata\n mergedContent[key] = {\n ...existingEntry,\n nodeType: 'translation',\n translation: {\n ...existingEntry.translation,\n [defaultLocale]: existingEntry.translation[defaultLocale] ?? value,\n },\n };\n } else {\n // New key - add with default locale only\n mergedContent[key] = {\n nodeType: 'translation',\n translation: {\n [defaultLocale]: value,\n },\n };\n }\n }\n\n return mergedContent;\n };\n\n const handleExtractedContent = async (result: ExtractResult) => {\n const { dictionaryKey, content, locale } = result;\n\n try {\n const dictionaryPath = join(compilerDir, `${dictionaryKey}.content.json`);\n\n // Read existing dictionary to preserve translations\n const existingDictionary = await readExistingDictionary(dictionaryPath);\n\n // Merge extracted content with existing translations\n const mergedContent = mergeWithExistingDictionary(\n content,\n existingDictionary,\n locale\n );\n\n const dictionary: Dictionary = {\n ...existingDictionary,\n key: dictionaryKey,\n content: mergedContent,\n filePath: join(\n relative(baseDir, compilerDir),\n `${dictionaryKey}.content.json`\n ),\n };\n\n const writeResult = await writeContentDeclaration(dictionary, config, {\n newDictionariesPath: relative(baseDir, compilerDir),\n });\n\n // Build the dictionary immediately\n const dictionaryToBuild: Dictionary = {\n ...dictionary,\n filePath: relative(baseDir, writeResult.path),\n };\n\n await buildDictionary([dictionaryToBuild], config);\n } catch (error: any) {\n console.error(\n `[intlayer] Failed to process extracted content for ${dictionaryKey}:`,\n error\n );\n if (\n error instanceof SyntaxError &&\n error.message.includes('Unexpected end of JSON input')\n ) {\n const match = error.message.match(\n /^(.*\\.json):\\s*Unexpected end of JSON input/\n );\n if (match) {\n const filePath = match[1];\n try {\n const fs = require('fs');\n const fileContent = fs.readFileSync(filePath, 'utf-8');\n console.error(\n `[intlayer] Content of the corrupted file (${filePath}):\\n\"${fileContent}\"`\n );\n } catch (e) {\n console.error(\n `[intlayer] Could not read corrupted file ${filePath}`,\n e\n );\n }\n }\n }\n }\n };\n\n const isDevBoolean = String(isDev) === 'true';\n const isEnabled =\n config.compiler?.enabled === 'build-only'\n ? !isDevBoolean\n : (config.compiler?.enabled ?? true);\n\n const logger = getAppLogger(config);\n\n if (config.compiler?.enabled === 'build-only' && isDevBoolean) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} i18n function is not inserted in the code in dev mode to optimize build time. (to test i18n in dev mode set compiler.enabled to true)`\n );\n }\n\n return {\n enabled: isEnabled,\n defaultLocale: config.internationalization.defaultLocale,\n prefix: config.compiler?.dictionaryKeyPrefix,\n saveComponents: config.compiler?.saveComponents,\n // filesList can be passed if needed, but usually handled by include/exclude in build tool\n onExtract: handleExtractedContent,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"getExtractPluginOptions.cjs","names":["ANSIColors","DefaultValues","writeContentHelper"],"sources":["../../src/getExtractPluginOptions.ts"],"sourcesContent":["import { buildFilesList } from '@intlayer/chokidar/utils';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { DefaultValues, getConfiguration } from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { ExtractPluginOptions } from './babel-plugin-intlayer-extract';\nimport { writeContentHelper } from './extractContent/contentWriter';\n\n/**\n * Mode of the compiler\n * - 'dev': Development mode with HMR support\n * - 'build': Production build mode\n */\nexport type CompilerMode = 'dev' | 'build';\n\n/**\n * Get the options for the Intlayer Babel extraction plugin\n * This function loads the Intlayer configuration and sets up the onExtract callback\n * to write dictionaries to the filesystem.\n */\nexport const getExtractPluginOptions = (\n configuration: IntlayerConfig = getConfiguration(),\n isDev = process.env.INTLAYER_IS_DEV_COMMAND\n): ExtractPluginOptions => {\n const isDevBoolean = String(isDev) === 'true';\n\n const compilerMode: CompilerMode = isDevBoolean ? 'dev' : 'build';\n\n const logger = getAppLogger(configuration);\n\n if (configuration.compiler?.enabled === 'build-only' && isDevBoolean) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} i18n function is not inserted in the code in dev mode to optimize build time. (to test i18n in dev mode set compiler.enabled to true)`\n );\n }\n\n let enabled =\n configuration.compiler?.enabled ?? DefaultValues.Compiler.COMPILER_ENABLED;\n\n if (enabled === 'build-only') {\n if (compilerMode) {\n enabled = compilerMode === 'build';\n } else {\n // Fallback if mode isn't explicitly provided (e.g. pure babel plugin context)\n enabled = process.env.NODE_ENV === 'production';\n }\n }\n\n const transformPattern =\n configuration.build.traversePattern ??\n configuration.compiler?.transformPattern;\n\n const excludePattern = [\n // Ensure extensions are treated as glob patterns (e.g., **/*.ts)\n ...configuration.content.fileExtensions.map((ext) => `**/*${ext}`),\n\n ...(Array.isArray(configuration.compiler.excludePattern)\n ? configuration.compiler.excludePattern\n : [configuration.compiler.excludePattern]),\n ] as string[];\n\n const filesList = buildFilesList({\n transformPattern,\n excludePattern,\n baseDir: configuration.system.baseDir,\n });\n\n return {\n enabled,\n configuration,\n filesList,\n onExtract: async ({ dictionaryKey, content, filePath }) => {\n try {\n await writeContentHelper(\n content,\n dictionaryKey,\n filePath,\n configuration\n );\n } catch (error) {\n logger(\n [\n `Failed to process extracted content for ${colorizeKey(dictionaryKey)}:`,\n error,\n ],\n { level: 'error' }\n );\n }\n },\n };\n};\n"],"mappings":"uRAwBA,MAAa,GACX,GAAA,EAAA,EAAA,mBAAkD,CAClD,EAAQ,QAAQ,IAAI,0BACK,CACzB,IAAM,EAAe,OAAO,EAAM,GAAK,OAEjC,EAA6B,EAAe,MAAQ,QAEpD,GAAA,EAAA,EAAA,cAAsB,EAAc,CAEtC,EAAc,UAAU,UAAY,cAAgB,GACtD,EACE,IAAA,EAAA,EAAA,UAAY,YAAaA,EAAAA,WAAW,UAAU,CAAC,wIAChD,CAGH,IAAI,EACF,EAAc,UAAU,SAAWC,EAAAA,cAAc,SAAS,iBAExD,IAAY,eACd,AAIE,EAJE,EACQ,IAAiB,QAGjB,QAAQ,IAAI,WAAa,cAiBvC,IAAM,GAAA,EAAA,EAAA,gBAA2B,CAC/B,iBAbA,EAAc,MAAM,iBACpB,EAAc,UAAU,iBAaxB,eAXqB,CAErB,GAAG,EAAc,QAAQ,eAAe,IAAK,GAAQ,OAAO,IAAM,CAElE,GAAI,MAAM,QAAQ,EAAc,SAAS,eAAe,CACpD,EAAc,SAAS,eACvB,CAAC,EAAc,SAAS,eAAe,CAC5C,CAKC,QAAS,EAAc,OAAO,QAC/B,CAAC,CAEF,MAAO,CACL,UACA,gBACA,YACA,UAAW,MAAO,CAAE,gBAAe,UAAS,cAAe,CACzD,GAAI,CACF,MAAMC,EAAAA,mBACJ,EACA,EACA,EACA,EACD,OACM,EAAO,CACd,EACE,CACE,4CAAA,EAAA,EAAA,aAAuD,EAAc,CAAC,GACtE,EACD,CACD,CAAE,MAAO,QAAS,CACnB,GAGN"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./_virtual/_rolldown/runtime.cjs`);let e=require(`node:path`),t=require(`@intlayer/config/node`),n=require(`@intlayer/chokidar/utils`);const r=e=>{try{let{getDictionaries:t}=require(`@intlayer/dictionaries-entry`),n=t(e);return Object.values(n)}catch{return[]}},i=i=>{let{configOptions:a,dictionaries:o,overrides:s}=i??{},c=(0,t.getConfiguration)(a),{mainDir:l,dictionariesDir:u,unmergedDictionariesDir:d,dynamicDictionariesDir:f,fetchDictionariesDir:p}=c.system,{importMode:m,optimize:h}=c.build,g=(0,n.getComponentTransformPatternSync)(c),_=(0,e.join)(l,`dictionaries.mjs`),v=(0,e.join)(l,`unmerged_dictionaries.mjs`),y=(0,e.join)(l,`dynamic_dictionaries.mjs`),b=(0,e.join)(l,`fetch_dictionaries.mjs`),x=[...g,_,v],S=o??r(c),C={};return S.forEach(e=>{C[e.key]=e.importMode??m}),{optimize:h,dictionariesDir:u,dictionariesEntryPath:_,unmergedDictionariesDir:d,unmergedDictionariesEntryPath:v,dynamicDictionariesDir:f,dynamicDictionariesEntryPath:y,fetchDictionariesDir:p,fetchDictionariesEntryPath:b,replaceDictionaryEntry:!0,importMode:m,dictionaryModeMap:C,filesList:x,...s}};exports.getOptimizePluginOptions=i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./_virtual/_rolldown/runtime.cjs`);let e=require(`@intlayer/chokidar/utils`),t=require(`@intlayer/config/node`),n=require(`node:path`);const r=e=>{try{let{getDictionaries:t}=require(`@intlayer/dictionaries-entry`),n=t(e);return Object.values(n)}catch{return[]}},i=i=>{let{configOptions:a,dictionaries:o,overrides:s}=i??{},c=(0,t.getConfiguration)(a),{mainDir:l,dictionariesDir:u,unmergedDictionariesDir:d,dynamicDictionariesDir:f,fetchDictionariesDir:p}=c.system,{importMode:m,optimize:h}=c.build,g=(0,e.getComponentTransformPatternSync)(c),_=(0,n.join)(l,`dictionaries.mjs`),v=(0,n.join)(l,`unmerged_dictionaries.mjs`),y=(0,n.join)(l,`dynamic_dictionaries.mjs`),b=(0,n.join)(l,`fetch_dictionaries.mjs`),x=[...g,_,v],S=o??r(c),C={};return S.forEach(e=>{C[e.key]=e.importMode??m}),{optimize:h,dictionariesDir:u,dictionariesEntryPath:_,unmergedDictionariesDir:d,unmergedDictionariesEntryPath:v,dynamicDictionariesDir:f,dynamicDictionariesEntryPath:y,fetchDictionariesDir:p,fetchDictionariesEntryPath:b,replaceDictionaryEntry:!0,importMode:m,dictionaryModeMap:C,filesList:x,...s}};exports.getOptimizePluginOptions=i;
2
2
  //# sourceMappingURL=getOptimizePluginOptions.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"getOptimizePluginOptions.cjs","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { getComponentTransformPatternSync } from '@intlayer/chokidar/utils';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { Dictionary, IntlayerConfig } from '@intlayer/types';\nimport type { OptimizePluginOptions } from './babel-plugin-intlayer-optimize';\n\ntype GetOptimizePluginOptionsParams = {\n /**\n * Configuration options for loading intlayer config\n */\n configOptions?: GetConfigurationOptions;\n /**\n * Pre-loaded dictionaries (optional - will be loaded if not provided)\n */\n dictionaries?: Dictionary[];\n /**\n * Override specific options\n */\n overrides?: Partial<OptimizePluginOptions>;\n};\n\n/**\n * Load dictionaries from the dictionaries-entry package\n */\nconst loadDictionaries = (config: IntlayerConfig): Dictionary[] => {\n try {\n // Dynamic require to avoid build-time dependency issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getDictionaries } = require('@intlayer/dictionaries-entry');\n const dictionariesRecord = getDictionaries(config) as Record<\n string,\n Dictionary\n >;\n return Object.values(dictionariesRecord);\n } catch {\n // If dictionaries-entry is not available, return empty array\n return [];\n }\n};\n\n/**\n * Get the options for the Intlayer Babel optimization plugin\n * This function loads the Intlayer configuration and returns the paths\n * needed for dictionary optimization and import rewriting.\n */\nexport const getOptimizePluginOptions = (\n params?: GetOptimizePluginOptionsParams\n): OptimizePluginOptions => {\n const {\n configOptions,\n dictionaries: providedDictionaries,\n overrides,\n } = params ?? {};\n\n const config = getConfiguration(configOptions);\n const {\n mainDir,\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n } = config.system;\n const { importMode, optimize } = config.build;\n\n // Build files list from traverse pattern\n const filesListPattern = getComponentTransformPatternSync(config);\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n ];\n\n // Load dictionaries if not provided\n const dictionaries = providedDictionaries ?? loadDictionaries(config);\n\n const dictionaryModeMap: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n > = {};\n\n dictionaries.forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] = dictionary.importMode ?? importMode;\n });\n\n return {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesDir,\n unmergedDictionariesEntryPath,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n replaceDictionaryEntry: true,\n importMode,\n dictionaryModeMap,\n filesList,\n ...overrides,\n };\n};\n"],"mappings":"mNA2BA,MAAM,EAAoB,GAAyC,CACjE,GAAI,CAGF,GAAM,CAAE,mBAAoB,QAAQ,+BAA+B,CAC7D,EAAqB,EAAgB,EAAO,CAIlD,OAAO,OAAO,OAAO,EAAmB,MAClC,CAEN,MAAO,EAAE,GASA,EACX,GAC0B,CAC1B,GAAM,CACJ,gBACA,aAAc,EACd,aACE,GAAU,EAAE,CAEV,GAAA,EAAA,EAAA,kBAA0B,EAAc,CACxC,CACJ,UACA,kBACA,0BACA,yBACA,wBACE,EAAO,OACL,CAAE,aAAY,YAAa,EAAO,MAGlC,GAAA,EAAA,EAAA,kCAAoD,EAAO,CAE3D,GAAA,EAAA,EAAA,MAA6B,EAAS,mBAAmB,CACzD,GAAA,EAAA,EAAA,MACJ,EACA,4BACD,CACK,GAAA,EAAA,EAAA,MACJ,EACA,2BACD,CACK,GAAA,EAAA,EAAA,MAAkC,EAAS,yBAAyB,CAEpE,EAAY,CAChB,GAAG,EACH,EACA,EACD,CAGK,EAAe,GAAwB,EAAiB,EAAO,CAE/D,EAGF,EAAE,CAMN,OAJA,EAAa,QAAS,GAAe,CACnC,EAAkB,EAAW,KAAO,EAAW,YAAc,GAC7D,CAEK,CACL,WACA,kBACA,wBACA,0BACA,gCACA,yBACA,+BACA,uBACA,6BACA,uBAAwB,GACxB,aACA,oBACA,YACA,GAAG,EACJ"}
1
+ {"version":3,"file":"getOptimizePluginOptions.cjs","names":[],"sources":["../../src/getOptimizePluginOptions.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { getComponentTransformPatternSync } from '@intlayer/chokidar/utils';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { OptimizePluginOptions } from './babel-plugin-intlayer-optimize';\n\ntype GetOptimizePluginOptionsParams = {\n /**\n * Configuration options for loading intlayer config\n */\n configOptions?: GetConfigurationOptions;\n /**\n * Pre-loaded dictionaries (optional - will be loaded if not provided)\n */\n dictionaries?: Dictionary[];\n /**\n * Override specific options\n */\n overrides?: Partial<OptimizePluginOptions>;\n};\n\n/**\n * Load dictionaries from the dictionaries-entry package\n */\nconst loadDictionaries = (config: IntlayerConfig): Dictionary[] => {\n try {\n // Dynamic require to avoid build-time dependency issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { getDictionaries } = require('@intlayer/dictionaries-entry');\n const dictionariesRecord = getDictionaries(config) as Record<\n string,\n Dictionary\n >;\n return Object.values(dictionariesRecord);\n } catch {\n // If dictionaries-entry is not available, return empty array\n return [];\n }\n};\n\n/**\n * Get the options for the Intlayer Babel optimization plugin\n * This function loads the Intlayer configuration and returns the paths\n * needed for dictionary optimization and import rewriting.\n */\nexport const getOptimizePluginOptions = (\n params?: GetOptimizePluginOptionsParams\n): OptimizePluginOptions => {\n const {\n configOptions,\n dictionaries: providedDictionaries,\n overrides,\n } = params ?? {};\n\n const config = getConfiguration(configOptions);\n const {\n mainDir,\n dictionariesDir,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n fetchDictionariesDir,\n } = config.system;\n const { importMode, optimize } = config.build;\n\n // Build files list from traverse pattern\n const filesListPattern = getComponentTransformPatternSync(config);\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n const fetchDictionariesEntryPath = join(mainDir, 'fetch_dictionaries.mjs');\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by an empty object if import made dynamic\n ];\n\n // Load dictionaries if not provided\n const dictionaries = providedDictionaries ?? loadDictionaries(config);\n\n const dictionaryModeMap: Record<\n string,\n 'static' | 'dynamic' | 'fetch' | undefined\n > = {};\n\n dictionaries.forEach((dictionary) => {\n dictionaryModeMap[dictionary.key] = dictionary.importMode ?? importMode;\n });\n\n return {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesDir,\n unmergedDictionariesEntryPath,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n fetchDictionariesEntryPath,\n replaceDictionaryEntry: true,\n importMode,\n dictionaryModeMap,\n filesList,\n ...overrides,\n };\n};\n"],"mappings":"mNA4BA,MAAM,EAAoB,GAAyC,CACjE,GAAI,CAGF,GAAM,CAAE,mBAAoB,QAAQ,+BAA+B,CAC7D,EAAqB,EAAgB,EAAO,CAIlD,OAAO,OAAO,OAAO,EAAmB,MAClC,CAEN,MAAO,EAAE,GASA,EACX,GAC0B,CAC1B,GAAM,CACJ,gBACA,aAAc,EACd,aACE,GAAU,EAAE,CAEV,GAAA,EAAA,EAAA,kBAA0B,EAAc,CACxC,CACJ,UACA,kBACA,0BACA,yBACA,wBACE,EAAO,OACL,CAAE,aAAY,YAAa,EAAO,MAGlC,GAAA,EAAA,EAAA,kCAAoD,EAAO,CAE3D,GAAA,EAAA,EAAA,MAA6B,EAAS,mBAAmB,CACzD,GAAA,EAAA,EAAA,MACJ,EACA,4BACD,CACK,GAAA,EAAA,EAAA,MACJ,EACA,2BACD,CACK,GAAA,EAAA,EAAA,MAAkC,EAAS,yBAAyB,CAEpE,EAAY,CAChB,GAAG,EACH,EACA,EACD,CAGK,EAAe,GAAwB,EAAiB,EAAO,CAE/D,EAGF,EAAE,CAMN,OAJA,EAAa,QAAS,GAAe,CACnC,EAAkB,EAAW,KAAO,EAAW,YAAc,GAC7D,CAEK,CACL,WACA,kBACA,wBACA,0BACA,gCACA,yBACA,+BACA,uBACA,6BACA,uBAAwB,GACxB,aACA,oBACA,YACA,GAAG,EACJ"}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./extractContent/utils/constants.cjs`),t=require(`./extractContent/utils/detectPackageName.cjs`),n=require(`./babel-plugin-intlayer-extract.cjs`),r=require(`./babel-plugin-intlayer-optimize.cjs`),i=require(`./getExtractPluginOptions.cjs`),a=require(`./getOptimizePluginOptions.cjs`),o=require(`./extractContent/extractContent.cjs`);exports.ATTRIBUTES_TO_EXTRACT=e.ATTRIBUTES_TO_EXTRACT,exports.detectPackageName=t.detectPackageName,exports.extractContent=o.extractContent,exports.getExtractPluginOptions=i.getExtractPluginOptions,exports.getOptimizePluginOptions=a.getOptimizePluginOptions,exports.intlayerExtractBabelPlugin=n.intlayerExtractBabelPlugin,exports.intlayerOptimizeBabelPlugin=r.intlayerOptimizeBabelPlugin,exports.packageList=e.packageList;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./extractContent/utils/extractDictionaryKey.cjs`),t=require(`./extractContent/utils/extractDictionaryInfo.cjs`),n=require(`./extractContent/contentWriter.cjs`),r=require(`./getExtractPluginOptions.cjs`),i=require(`./extractContent/utils/constants.cjs`),a=require(`./extractContent/utils/detectPackageName.cjs`),o=require(`./extractContent/utils/generateKey.cjs`),s=require(`./extractContent/utils/getComponentName.cjs`),c=require(`./extractContent/extractContent.cjs`),l=require(`./babel-plugin-intlayer-extract.cjs`),u=require(`./getOptimizePluginOptions.cjs`),d=require(`./babel-plugin-intlayer-optimize.cjs`);exports.ATTRIBUTES_TO_EXTRACT=i.ATTRIBUTES_TO_EXTRACT,exports.SERVER_CAPABLE_PACKAGES=i.SERVER_CAPABLE_PACKAGES,exports.detectPackageName=a.detectPackageName,exports.extractContent=c.extractContent,exports.extractContentSync=c.extractContentSync,exports.extractDictionaryInfo=t.extractDictionaryInfo,exports.extractDictionaryKey=e.extractDictionaryKey,exports.extractDictionaryKeyFromPath=e.extractDictionaryKeyFromPath,exports.generateKey=o.generateKey,exports.getComponentName=s.getComponentName,exports.getExtractPluginOptions=r.getExtractPluginOptions,exports.getOptimizePluginOptions=u.getOptimizePluginOptions,exports.getOutput=t.getOutput,exports.intlayerExtractBabelPlugin=l.intlayerExtractBabelPlugin,exports.intlayerOptimizeBabelPlugin=d.intlayerOptimizeBabelPlugin,exports.mergeWithExistingMultilingualDictionary=n.mergeWithExistingMultilingualDictionary,exports.mergeWithExistingPerLocaleDictionary=n.mergeWithExistingPerLocaleDictionary,exports.packageList=i.packageList,exports.resolveContentFilePaths=t.resolveContentFilePaths,exports.writeContentHelper=n.writeContentHelper;
@@ -1,2 +1,2 @@
1
- import{detectPackageName as e}from"./extractContent/utils/detectPackageName.mjs";import{extractDictionaryKeyFromPath as t}from"./extractContent/utils/extractDictionaryKey.mjs";import{processTsxFile as n}from"./extractContent/processTsxFile.mjs";import{dirname as r,extname as i,relative as a}from"node:path";import{parse as o}from"@babel/parser";import{ANSIColors as s,colorize as c,colorizePath as l,getAppLogger as u}from"@intlayer/config/logger";import{getConfiguration as d}from"@intlayer/config/node";const f=new Set([`next-intlayer`]),p=p=>({name:`babel-plugin-intlayer-extract`,visitor:{Program:{enter(p,m){let h=m.opts;if(h.enabled===!1)return;let g=m.file.opts.filename;if(!g)return;let _=i(g);if(![`.tsx`,`.jsx`,`.ts`,`.js`].includes(_)||h.filesList&&!h.filesList.includes(g))return;let v=m.file.code??``;if(!v)return;let y=d(),b=u(y),x=h.packageName??e(r(g))??`react-intlayer`,S=t(g,h.prefix??`comp-`),C=h.saveComponents??!1,w=p.node.directives.some(e=>e.value.value===`use client`),T=n(g,S,f.has(x)&&!w?`${x}/server`:x,y,C,{},v);if(!T)return;let{extractedContent:E,modifiedCode:D}=T;if(h.onExtract){let e=h.defaultLocale??y.internationalization.defaultLocale;for(let[t,n]of Object.entries(E))h.onExtract({dictionaryKey:t,filePath:g,content:n,locale:e})}try{let e=o(D,{sourceType:`module`,plugins:[`jsx`,`typescript`]});p.node.body=e.program.body,p.node.directives=e.program.directives,b(`${c(`Compiler:`,s.GREY_DARK)} Extracted content from ${l(a(y.content.baseDir,g))}`,{level:`debug`})}catch(e){console.error(`[intlayer] Failed to parse transformed code for ${g}:`,e)}}}}});export{p as intlayerExtractBabelPlugin};
1
+ import{detectPackageName as e}from"./extractContent/utils/detectPackageName.mjs";import{extractContentSync as t}from"./extractContent/extractContent.mjs";import{ANSIColors as n,colorize as r,colorizePath as i,getAppLogger as a}from"@intlayer/config/logger";import{relative as o}from"node:path";import{parse as s}from"@babel/parser";const c=c=>({name:`babel-plugin-intlayer-extract`,visitor:{Program:{enter(c,l){let u=l.opts;if(u.enabled===!1)return;let d=l.file.opts.filename;if(!d||u.filesList&&!u.filesList.includes(d))return;let f=l.file.code??``;if(!f)return;let p=a(u.configuration),m=u.packageName??e(d),{saveComponents:h}=u.configuration.compiler,g=t(d,m,{configuration:u.configuration,code:f,onExtract:e=>{u.onExtract&&u.onExtract({dictionaryKey:e.key,filePath:d,content:e.content,locale:u.configuration.internationalization.defaultLocale})},declarationOnly:!h});if(!g)return;let{transformedCode:_}=g;if(_)try{let e=s(_,{sourceType:`module`,plugins:[`jsx`,`typescript`]});c.node.body=e.program.body,c.node.directives=e.program.directives,p(`${r(`Compiler:`,n.GREY_DARK)} Extracted content from ${i(o(u.configuration.system.baseDir,d))}`,{level:`debug`})}catch(e){console.error(`[intlayer] Failed to parse transformed code for ${d}:`,e)}}}}});export{c as intlayerExtractBabelPlugin};
2
2
  //# sourceMappingURL=babel-plugin-intlayer-extract.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"babel-plugin-intlayer-extract.mjs","names":[],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"sourcesContent":["import { dirname, extname, relative } from 'node:path';\nimport type { PluginObj, PluginPass } from '@babel/core';\nimport { parse } from '@babel/parser';\nimport type * as BabelTypes from '@babel/types';\nimport {\n ANSIColors,\n colorize,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { getConfiguration } from '@intlayer/config/node';\nimport { processTsxFile } from './extractContent/processTsxFile';\nimport type { PackageName } from './extractContent/utils/constants';\nimport { detectPackageName } from './extractContent/utils/detectPackageName';\nimport { extractDictionaryKeyFromPath } from './extractContent/utils/extractDictionaryKey';\n\n/** Packages that support a `/server` sub-path for React Server Components. */\nconst SERVER_CAPABLE_PACKAGES: ReadonlySet<string> = new Set(['next-intlayer']);\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: Record<string, string>;\n locale: string;\n};\n\nexport type ExtractPluginOptions = {\n defaultLocale?: string;\n packageName?: string;\n filesList?: string[];\n shouldExtract?: (text: string) => boolean;\n enabled?: boolean;\n prefix?: string;\n saveComponents?: boolean;\n formatCommand?: string;\n /**\n * Callback invoked for each extracted dictionary key/content pair.\n * Used by `getExtractPluginOptions` to write dictionaries to disk.\n * May be async — the plugin will fire-and-forget (Babel transforms are sync).\n */\n onExtract?: (result: ExtractResult) => void | Promise<void>;\n};\n\ntype State = PluginPass & { opts: ExtractPluginOptions };\n\n/**\n * Babel plugin that extracts translatable content from source files and\n * injects Intlayer hooks (`useIntlayer` / `getIntlayer`) automatically.\n *\n * Designed for use with Babel-based build tools such as Next.js and Webpack.\n *\n * @example babel.config.js\n * ```js\n * const { intlayerExtractBabelPlugin, getExtractPluginOptions } = require('@intlayer/babel');\n * module.exports = {\n * presets: ['next/babel'],\n * plugins: [\n * [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n * ],\n * };\n * ```\n */\nexport const intlayerExtractBabelPlugin = (babel: {\n types: typeof BabelTypes;\n}): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-extract',\n\n visitor: {\n Program: {\n enter(programPath, state) {\n const opts = state.opts;\n\n if (opts.enabled === false) return;\n\n const filename = state.file.opts.filename;\n if (!filename) return;\n\n const ext = extname(filename);\n if (!['.tsx', '.jsx', '.ts', '.js'].includes(ext)) return;\n\n if (opts.filesList && !opts.filesList.includes(filename)) return;\n\n // Grab the original source from the Babel file object\n const fileCode: string = (state.file as any).code ?? '';\n if (!fileCode) return;\n\n const configuration = getConfiguration();\n const appLogger = getAppLogger(configuration);\n\n const packageName = (opts.packageName ??\n detectPackageName(dirname(filename)) ??\n 'react-intlayer') as PackageName;\n\n const prefix = opts.prefix ?? 'comp-';\n const componentKey = extractDictionaryKeyFromPath(filename, prefix);\n const saveComponents = opts.saveComponents ?? false;\n\n // For packages that expose a `/server` entry (e.g. next-intlayer),\n // use that sub-path when no \"use client\" directive is present so that\n // React Server Components receive the correct import.\n const hasUseClient = programPath.node.directives.some(\n (d) => d.value.value === 'use client'\n );\n const effectivePackageName =\n SERVER_CAPABLE_PACKAGES.has(packageName) && !hasUseClient\n ? `${packageName}/server`\n : packageName;\n\n const result = processTsxFile(\n filename,\n componentKey,\n effectivePackageName,\n configuration,\n saveComponents,\n {}, // unmergedDictionaries — not needed for Babel plugin use case\n fileCode\n );\n\n if (!result) return;\n\n const { extractedContent, modifiedCode } = result;\n\n // Fire-and-forget: Babel transforms are synchronous, but onExtract may\n // be async (e.g. writing files). We don't await here.\n if (opts.onExtract) {\n const defaultLocale =\n opts.defaultLocale ??\n configuration.internationalization.defaultLocale;\n\n for (const [key, content] of Object.entries(extractedContent)) {\n void opts.onExtract({\n dictionaryKey: key,\n filePath: filename,\n content,\n locale: defaultLocale,\n });\n }\n }\n\n // Replace the Babel AST with the transformed code by re-parsing it.\n // This lets Babel serialise the injected hooks/imports through its\n // own code generator, preserving compatibility with other plugins.\n try {\n const newAst = parse(modifiedCode, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n programPath.node.body = newAst.program.body;\n programPath.node.directives = newAst.program.directives;\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(relative(configuration.content.baseDir, filename))}`,\n { level: 'debug' }\n );\n } catch (error) {\n console.error(\n `[intlayer] Failed to parse transformed code for ${filename}:`,\n error\n );\n }\n },\n },\n },\n };\n};\n"],"mappings":"0fAiBA,MAAM,EAA+C,IAAI,IAAI,CAAC,gBAAgB,CAAC,CA6ClE,EAA8B,IAGlC,CACL,KAAM,gCAEN,QAAS,CACP,QAAS,CACP,MAAM,EAAa,EAAO,CACxB,IAAM,EAAO,EAAM,KAEnB,GAAI,EAAK,UAAY,GAAO,OAE5B,IAAM,EAAW,EAAM,KAAK,KAAK,SACjC,GAAI,CAAC,EAAU,OAEf,IAAM,EAAM,EAAQ,EAAS,CAG7B,GAFI,CAAC,CAAC,OAAQ,OAAQ,MAAO,MAAM,CAAC,SAAS,EAAI,EAE7C,EAAK,WAAa,CAAC,EAAK,UAAU,SAAS,EAAS,CAAE,OAG1D,IAAM,EAAoB,EAAM,KAAa,MAAQ,GACrD,GAAI,CAAC,EAAU,OAEf,IAAM,EAAgB,GAAkB,CAClC,EAAY,EAAa,EAAc,CAEvC,EAAe,EAAK,aACxB,EAAkB,EAAQ,EAAS,CAAC,EACpC,iBAGI,EAAe,EAA6B,EADnC,EAAK,QAAU,QACqC,CAC7D,EAAiB,EAAK,gBAAkB,GAKxC,EAAe,EAAY,KAAK,WAAW,KAC9C,GAAM,EAAE,MAAM,QAAU,aAC1B,CAMK,EAAS,EACb,EACA,EANA,EAAwB,IAAI,EAAY,EAAI,CAAC,EACzC,GAAG,EAAY,SACf,EAMJ,EACA,EACA,EAAE,CACF,EACD,CAED,GAAI,CAAC,EAAQ,OAEb,GAAM,CAAE,mBAAkB,gBAAiB,EAI3C,GAAI,EAAK,UAAW,CAClB,IAAM,EACJ,EAAK,eACL,EAAc,qBAAqB,cAErC,IAAK,GAAM,CAAC,EAAK,KAAY,OAAO,QAAQ,EAAiB,CACtD,EAAK,UAAU,CAClB,cAAe,EACf,SAAU,EACV,UACA,OAAQ,EACT,CAAC,CAON,GAAI,CACF,IAAM,EAAS,EAAM,EAAc,CACjC,WAAY,SACZ,QAAS,CAAC,MAAO,aAAa,CAC/B,CAAC,CAEF,EAAY,KAAK,KAAO,EAAO,QAAQ,KACvC,EAAY,KAAK,WAAa,EAAO,QAAQ,WAE7C,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,0BAA0B,EAAa,EAAS,EAAc,QAAQ,QAAS,EAAS,CAAC,GACxI,CAAE,MAAO,QAAS,CACnB,OACM,EAAO,CACd,QAAQ,MACN,mDAAmD,EAAS,GAC5D,EACD,GAGN,CACF,CACF"}
1
+ {"version":3,"file":"babel-plugin-intlayer-extract.mjs","names":[],"sources":["../../src/babel-plugin-intlayer-extract.ts"],"sourcesContent":["import { relative } from 'node:path';\nimport type { PluginObj, PluginPass } from '@babel/core';\nimport { parse } from '@babel/parser';\nimport type * as BabelTypes from '@babel/types';\nimport {\n ANSIColors,\n colorize,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport { extractContentSync } from './extractContent/extractContent';\nimport type { PackageName } from './extractContent/utils/constants';\nimport { detectPackageName } from './extractContent/utils/detectPackageName';\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: Record<string, string>;\n locale: Locale;\n};\n\nexport type ExtractPluginOptions = {\n packageName?: PackageName;\n filesList: string[];\n enabled: boolean;\n\n shouldExtract?: (text: string) => boolean;\n configuration: IntlayerConfig;\n /**\n * Callback invoked for each extracted dictionary key/content pair.\n * Used by `getExtractPluginOptions` to write dictionaries to disk.\n * May be async — the plugin will fire-and-forget (Babel transforms are sync).\n */\n onExtract?: (result: ExtractResult) => void | Promise<void>;\n /**\n * Defines the output files path.\n */\n output?: FilePathPattern;\n};\n\ntype State = PluginPass & { opts: ExtractPluginOptions };\n\n/**\n * Babel plugin that extracts translatable content from source files and\n * injects Intlayer hooks (`useIntlayer` / `getIntlayer`) automatically.\n *\n * Designed for use with Babel-based build tools such as Next.js and Webpack.\n *\n * @example babel.config.js\n * ```js\n * const { intlayerExtractBabelPlugin, getExtractPluginOptions } = require('@intlayer/babel');\n * module.exports = {\n * presets: ['next/babel'],\n * plugins: [\n * [intlayerExtractBabelPlugin, getExtractPluginOptions()],\n * ],\n * };\n * ```\n */\nexport const intlayerExtractBabelPlugin = (_babel: {\n types: typeof BabelTypes;\n}): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-extract',\n\n visitor: {\n Program: {\n enter(programPath, state) {\n const opts = state.opts;\n\n // Merge plugin options with the unified compiler config\n const isEnabled = opts.enabled;\n\n if (isEnabled === false) return;\n\n const filename = state.file.opts.filename;\n\n if (!filename) return;\n\n if (opts.filesList && !opts.filesList.includes(filename)) return;\n\n const fileCode: string = state.file.code ?? '';\n if (!fileCode) return;\n\n const appLogger = getAppLogger(opts.configuration);\n const packageName = opts.packageName ?? detectPackageName(filename);\n\n const { saveComponents } = opts.configuration.compiler;\n\n const result = extractContentSync(filename, packageName, {\n configuration: opts.configuration,\n code: fileCode,\n onExtract: (extractResult: {\n key: string;\n content: Record<string, string>;\n }) => {\n if (opts.onExtract) {\n void opts.onExtract({\n dictionaryKey: extractResult.key,\n filePath: filename,\n content: extractResult.content,\n locale: opts.configuration.internationalization.defaultLocale,\n });\n }\n },\n declarationOnly: !saveComponents,\n });\n\n if (!result) return;\n\n const { transformedCode: modifiedCode } = result;\n\n if (!modifiedCode) return;\n\n // Replace the Babel AST with the transformed code by re-parsing it.\n // This lets Babel serialise the injected hooks/imports through its\n // own code generator, preserving compatibility with other plugins.\n try {\n const newAst = parse(modifiedCode, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n\n programPath.node.body = newAst.program.body;\n programPath.node.directives = newAst.program.directives;\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted content from ${colorizePath(relative(opts.configuration.system.baseDir, filename))}`,\n { level: 'debug' }\n );\n } catch (error) {\n console.error(\n `[intlayer] Failed to parse transformed code for ${filename}:`,\n error\n );\n }\n },\n },\n },\n };\n};\n"],"mappings":"4UA8DA,MAAa,EAA8B,IAGlC,CACL,KAAM,gCAEN,QAAS,CACP,QAAS,CACP,MAAM,EAAa,EAAO,CACxB,IAAM,EAAO,EAAM,KAKnB,GAFkB,EAAK,UAEL,GAAO,OAEzB,IAAM,EAAW,EAAM,KAAK,KAAK,SAIjC,GAFI,CAAC,GAED,EAAK,WAAa,CAAC,EAAK,UAAU,SAAS,EAAS,CAAE,OAE1D,IAAM,EAAmB,EAAM,KAAK,MAAQ,GAC5C,GAAI,CAAC,EAAU,OAEf,IAAM,EAAY,EAAa,EAAK,cAAc,CAC5C,EAAc,EAAK,aAAe,EAAkB,EAAS,CAE7D,CAAE,kBAAmB,EAAK,cAAc,SAExC,EAAS,EAAmB,EAAU,EAAa,CACvD,cAAe,EAAK,cACpB,KAAM,EACN,UAAY,GAGN,CACA,EAAK,WACF,EAAK,UAAU,CAClB,cAAe,EAAc,IAC7B,SAAU,EACV,QAAS,EAAc,QACvB,OAAQ,EAAK,cAAc,qBAAqB,cACjD,CAAC,EAGN,gBAAiB,CAAC,EACnB,CAAC,CAEF,GAAI,CAAC,EAAQ,OAEb,GAAM,CAAE,gBAAiB,GAAiB,EAErC,KAKL,GAAI,CACF,IAAM,EAAS,EAAM,EAAc,CACjC,WAAY,SACZ,QAAS,CAAC,MAAO,aAAa,CAC/B,CAAC,CAEF,EAAY,KAAK,KAAO,EAAO,QAAQ,KACvC,EAAY,KAAK,WAAa,EAAO,QAAQ,WAE7C,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,0BAA0B,EAAa,EAAS,EAAK,cAAc,OAAO,QAAS,EAAS,CAAC,GAC5I,CAAE,MAAO,QAAS,CACnB,OACM,EAAO,CACd,QAAQ,MACN,mDAAmD,EAAS,GAC5D,EACD,GAGN,CACF,CACF"}
@@ -1,2 +1,2 @@
1
- import{dirname as e,join as t,relative as n}from"node:path";import{normalizePath as r}from"@intlayer/config/utils";import{getPathHash as i}from"@intlayer/chokidar/utils";const a=[`intlayer`,`@intlayer/core`,`react-intlayer`,`react-intlayer/client`,`react-intlayer/server`,`next-intlayer`,`next-intlayer/client`,`next-intlayer/server`,`svelte-intlayer`,`vue-intlayer`,`angular-intlayer`,`preact-intlayer`,`solid-intlayer`],o=[`useIntlayer`,`getIntlayer`],s=[`react-intlayer`,`react-intlayer/client`,`react-intlayer/server`,`next-intlayer`,`next-intlayer/client`,`next-intlayer/server`,`preact-intlayer`,`vue-intlayer`,`solid-intlayer`,`svelte-intlayer`,`angular-intlayer`],c={getIntlayer:`getDictionary`,useIntlayer:`useDictionary`},l={useIntlayer:`useDictionaryDynamic`},u=(e,t)=>{let n=i(e);return t.identifier(`_${n}`)},d=(i,a,o,s,c,l)=>{let u=t(a,`${c}.json`);l===`fetch`&&(u=t(s,`${c}.mjs`)),l===`dynamic`&&(u=t(o,`${c}.mjs`));let d=n(e(i),u);return d=r(d),!d.startsWith(`./`)&&!d.startsWith(`../`)&&(d=`./${d}`),d},f=e=>{let{types:t}=e;return{name:`babel-plugin-intlayer-transform`,pre(){if(this._newStaticImports=new Map,this._newDynamicImports=new Map,this._callerMap=new Map,this._isIncluded=!0,this._hasValidImport=!1,this._isDictEntry=!1,this._useDynamicHelpers=!1,this.opts.optimize===!1){this._isIncluded=!1;return}let e=this.file.opts.filename;if(this.opts.filesList&&e&&!this.opts.filesList.includes(e)){this._isIncluded=!1;return}},visitor:{Program:{enter(e,n){let r=n.file.opts.filename;n.opts.replaceDictionaryEntry&&r===n.opts.dictionariesEntryPath&&(n._isDictEntry=!0,e.traverse({ImportDeclaration(e){e.remove()},VariableDeclarator(e){t.isObjectExpression(e.node.init)&&(e.node.init.properties=[])}}))},exit(e,n){if(n._isDictEntry||!n._isIncluded)return;let r=!1;if(e.traverse({CallExpression(e){let i=e.node.callee;if(!t.isIdentifier(i)||n._callerMap?.get(i.name)!==`useIntlayer`)return;let a=e.node.arguments[0],o;if(a&&t.isStringLiteral(a)?o=a.value:a&&t.isTemplateLiteral(a)&&a.expressions.length===0&&a.quasis.length===1&&(o=a.quasis[0].value.cooked??a.quasis[0].value.raw),!o)return;let s=n.opts.dictionaryModeMap?.[o];(s===`dynamic`||s===`fetch`)&&(r=!0)}}),e.traverse({ImportDeclaration(e){let i=e.node.source.value;if(a.includes(i)){n._hasValidImport=!0;for(let a of e.node.specifiers){if(!t.isImportSpecifier(a))continue;let e=t.isIdentifier(a.imported)?a.imported.name:a.imported.value;o.includes(e)&&n._callerMap?.set(a.local.name,e);let u=n.opts.importMode,d=(u===`dynamic`||u===`fetch`||r)&&s.includes(i);d&&(n._useDynamicHelpers=!0);let f;f=d?{...c,...l}:c;let p=f[e];p&&(a.imported=t.identifier(p))}}},CallExpression(e){let r=e.node.callee;if(!t.isIdentifier(r))return;let a=n._callerMap?.get(r.name);if(!a)return;n._hasValidImport=!0;let o=e.node.arguments[0],s;if(o&&t.isStringLiteral(o)?s=o.value:o&&t.isTemplateLiteral(o)&&o.expressions.length===0&&o.quasis.length===1&&(s=o.quasis[0].value.cooked??o.quasis[0].value.raw),!s)return;let c=n.opts.importMode,l=a===`useIntlayer`,d=!!n._useDynamicHelpers,f=`static`,p=n.opts.dictionaryModeMap?.[s];l&&d?p?f=p:c===`dynamic`?f=`dynamic`:c===`fetch`&&(f=`fetch`):l&&!d&&(p===`dynamic`||p===`fetch`)&&(f=p);let m;if(f===`fetch`){let r=n._newDynamicImports?.get(s);if(!r){let e=i(s);r=t.identifier(`_${e}_fetch`),n._newDynamicImports?.set(s,r)}m=r,e.node.arguments=[t.identifier(m.name),...e.node.arguments]}else if(f===`dynamic`){let r=n._newDynamicImports?.get(s);if(!r){let e=i(s);r=t.identifier(`_${e}_dyn`),n._newDynamicImports?.set(s,r)}m=r,e.node.arguments=[t.identifier(m.name),...e.node.arguments]}else{let r=n._newStaticImports?.get(s);r||(r=u(s,t),n._newStaticImports?.set(s,r)),m=r,e.node.arguments[0]=t.identifier(m.name)}}}),!n._hasValidImport)return;let f=n.file.opts.filename,p=n.opts.dictionariesDir,m=n.opts.dynamicDictionariesDir,h=n.opts.fetchDictionariesDir,g=[];for(let[e,r]of n._newStaticImports){let n=d(f,p,m,h,e,`static`),i=t.importDeclaration([t.importDefaultSpecifier(t.identifier(r.name))],t.stringLiteral(n));i.attributes=[t.importAttribute(t.identifier(`type`),t.stringLiteral(`json`))],g.push(i)}for(let[e,r]of n._newDynamicImports){let n=d(f,p,m,h,e,r.name.endsWith(`_fetch`)?`fetch`:`dynamic`);g.push(t.importDeclaration([t.importDefaultSpecifier(t.identifier(r.name))],t.stringLiteral(n)))}if(!g.length)return;let _=e.get(`body`),v=0;for(let e of _){let n=e.node;if(t.isExpressionStatement(n)&&t.isStringLiteral(n.expression)&&!n.expression.value.startsWith(`import`)&&!n.expression.value.startsWith(`require`))v+=1;else break}e.node.body.splice(v,0,...g)}}}}};export{f as intlayerOptimizeBabelPlugin};
1
+ import{getPathHash as e}from"@intlayer/chokidar/utils";import{dirname as t,join as n,relative as r}from"node:path";import{normalizePath as i}from"@intlayer/config/utils";const a=[`intlayer`,`@intlayer/core`,`react-intlayer`,`react-intlayer/client`,`react-intlayer/server`,`next-intlayer`,`next-intlayer/client`,`next-intlayer/server`,`svelte-intlayer`,`vue-intlayer`,`angular-intlayer`,`preact-intlayer`,`solid-intlayer`],o=[`useIntlayer`,`getIntlayer`],s=[`react-intlayer`,`react-intlayer/client`,`react-intlayer/server`,`next-intlayer`,`next-intlayer/client`,`next-intlayer/server`,`preact-intlayer`,`vue-intlayer`,`solid-intlayer`,`svelte-intlayer`,`angular-intlayer`],c={getIntlayer:`getDictionary`,useIntlayer:`useDictionary`},l={useIntlayer:`useDictionaryDynamic`},u=(t,n)=>{let r=e(t);return n.identifier(`_${r}`)},d=(e,a,o,s,c,l)=>{let u=n(a,`${c}.json`);l===`fetch`&&(u=n(s,`${c}.mjs`)),l===`dynamic`&&(u=n(o,`${c}.mjs`));let d=r(t(e),u);return d=i(d),!d.startsWith(`./`)&&!d.startsWith(`../`)&&(d=`./${d}`),d},f=t=>{let{types:n}=t;return{name:`babel-plugin-intlayer-transform`,pre(){if(this._newStaticImports=new Map,this._newDynamicImports=new Map,this._callerMap=new Map,this._isIncluded=!0,this._hasValidImport=!1,this._isDictEntry=!1,this._useDynamicHelpers=!1,this.opts.optimize===!1){this._isIncluded=!1;return}let e=this.file.opts.filename;if(this.opts.filesList&&e&&!this.opts.filesList.includes(e)){this._isIncluded=!1;return}},visitor:{Program:{enter(e,t){let r=t.file.opts.filename;t.opts.replaceDictionaryEntry&&r===t.opts.dictionariesEntryPath&&(t._isDictEntry=!0,e.traverse({ImportDeclaration(e){e.remove()},VariableDeclarator(e){n.isObjectExpression(e.node.init)&&(e.node.init.properties=[])}}))},exit(t,r){if(r._isDictEntry||!r._isIncluded)return;let i=!1;if(t.traverse({CallExpression(e){let t=e.node.callee;if(!n.isIdentifier(t)||r._callerMap?.get(t.name)!==`useIntlayer`)return;let a=e.node.arguments[0],o;if(a&&n.isStringLiteral(a)?o=a.value:a&&n.isTemplateLiteral(a)&&a.expressions.length===0&&a.quasis.length===1&&(o=a.quasis[0].value.cooked??a.quasis[0].value.raw),!o)return;let s=r.opts.dictionaryModeMap?.[o];(s===`dynamic`||s===`fetch`)&&(i=!0)}}),t.traverse({ImportDeclaration(e){let t=e.node.source.value;if(a.includes(t)){r._hasValidImport=!0;for(let a of e.node.specifiers){if(!n.isImportSpecifier(a))continue;let e=n.isIdentifier(a.imported)?a.imported.name:a.imported.value;o.includes(e)&&r._callerMap?.set(a.local.name,e);let u=r.opts.importMode,d=(u===`dynamic`||u===`fetch`||i)&&s.includes(t);d&&(r._useDynamicHelpers=!0);let f;f=d?{...c,...l}:c;let p=f[e];p&&(a.imported=n.identifier(p))}}},CallExpression(t){let i=t.node.callee;if(!n.isIdentifier(i))return;let a=r._callerMap?.get(i.name);if(!a)return;r._hasValidImport=!0;let o=t.node.arguments[0],s;if(o&&n.isStringLiteral(o)?s=o.value:o&&n.isTemplateLiteral(o)&&o.expressions.length===0&&o.quasis.length===1&&(s=o.quasis[0].value.cooked??o.quasis[0].value.raw),!s)return;let c=r.opts.importMode,l=a===`useIntlayer`,d=!!r._useDynamicHelpers,f=`static`,p=r.opts.dictionaryModeMap?.[s];l&&d?p?f=p:c===`dynamic`?f=`dynamic`:c===`fetch`&&(f=`fetch`):l&&!d&&(p===`dynamic`||p===`fetch`)&&(f=p);let m;if(f===`fetch`){let i=r._newDynamicImports?.get(s);if(!i){let t=e(s);i=n.identifier(`_${t}_fetch`),r._newDynamicImports?.set(s,i)}m=i,t.node.arguments=[n.identifier(m.name),...t.node.arguments]}else if(f===`dynamic`){let i=r._newDynamicImports?.get(s);if(!i){let t=e(s);i=n.identifier(`_${t}_dyn`),r._newDynamicImports?.set(s,i)}m=i,t.node.arguments=[n.identifier(m.name),...t.node.arguments]}else{let e=r._newStaticImports?.get(s);e||(e=u(s,n),r._newStaticImports?.set(s,e)),m=e,t.node.arguments[0]=n.identifier(m.name)}}}),!r._hasValidImport)return;let f=r.file.opts.filename,p=r.opts.dictionariesDir,m=r.opts.dynamicDictionariesDir,h=r.opts.fetchDictionariesDir,g=[];for(let[e,t]of r._newStaticImports){let r=d(f,p,m,h,e,`static`),i=n.importDeclaration([n.importDefaultSpecifier(n.identifier(t.name))],n.stringLiteral(r));i.attributes=[n.importAttribute(n.identifier(`type`),n.stringLiteral(`json`))],g.push(i)}for(let[e,t]of r._newDynamicImports){let r=d(f,p,m,h,e,t.name.endsWith(`_fetch`)?`fetch`:`dynamic`);g.push(n.importDeclaration([n.importDefaultSpecifier(n.identifier(t.name))],n.stringLiteral(r)))}if(!g.length)return;let _=t.get(`body`),v=0;for(let e of _){let t=e.node;if(n.isExpressionStatement(t)&&n.isStringLiteral(t.expression)&&!t.expression.value.startsWith(`import`)&&!t.expression.value.startsWith(`require`))v+=1;else break}t.node.body.splice(v,0,...g)}}}}};export{f as intlayerOptimizeBabelPlugin};
2
2
  //# sourceMappingURL=babel-plugin-intlayer-optimize.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"babelProcessor.mjs","names":[],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n for (const path of componentPaths) {\n const existingInfo = getExistingIntlayerInfo(path);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n componentKeyMap.set(path.node, globalFileKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n hookMap.set(path.node, isComponent ? 'useIntlayer' : 'getIntlayer');\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n if (\n parent.isCallExpression() &&\n t.isMemberExpression(parent.node.callee)\n ) {\n if (\n t.isIdentifier(parent.node.callee.object) &&\n parent.node.callee.object.name === 'console' &&\n t.isIdentifier(parent.node.callee.property) &&\n parent.node.callee.property.name === 'log'\n ) {\n return;\n }\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n const hasReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) return true;\n\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentPaths.find(\n (path) => path.node === currentPath?.node\n );\n\n if (ancestorPath) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) => {\n let rPath: NodePath | null = replacement.path;\n while (rPath) {\n if (rPath.node === ancestorPath.node) return true;\n\n rPath = rPath.parentPath;\n }\n return false;\n });\n const existingInfo = getExistingIntlayerInfo(ancestorPath);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"babelProcessor.mjs","names":[],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n for (const path of componentPaths) {\n const existingInfo = getExistingIntlayerInfo(path);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n componentKeyMap.set(path.node, globalFileKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n hookMap.set(path.node, isComponent ? 'useIntlayer' : 'getIntlayer');\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n if (\n parent.isCallExpression() &&\n t.isMemberExpression(parent.node.callee)\n ) {\n if (\n t.isIdentifier(parent.node.callee.object) &&\n parent.node.callee.object.name === 'console' &&\n t.isIdentifier(parent.node.callee.property) &&\n parent.node.callee.property.name === 'log'\n ) {\n return;\n }\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n const hasReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) return true;\n\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentPaths.find(\n (path) => path.node === currentPath?.node\n );\n\n if (ancestorPath) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) => {\n let rPath: NodePath | null = replacement.path;\n while (rPath) {\n if (rPath.node === ancestorPath.node) return true;\n\n rPath = rPath.parentPath;\n }\n return false;\n });\n const existingInfo = getExistingIntlayerInfo(ancestorPath);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{basename as e,dirname as t,extname as n,join as r,relative as i,resolve as a}from"node:path";import{writeContentDeclaration as o}from"@intlayer/chokidar/cli";import{getUnmergedDictionaries as s}from"@intlayer/unmerged-dictionaries-entry";const c=(o,c,l,u)=>{let{baseDir:d,fileExtensions:f}=l.content,p=(s(l)??{})[c];if(p?.[0]?.filePath)return{contentFilePath:a(d,p[0].filePath),relativeContentFilePath:p[0].filePath};let m=u?a(u):t(o),h=f[0],g=h.startsWith(`.`)?h:`.${h}`,_=e(o,n(o)),v=r(m,`${_.charAt(0).toLowerCase()+_.slice(1)}${g}`);return{contentFilePath:v,relativeContentFilePath:i(d,v)}},l=(e,t,n,r)=>{let{defaultLocale:i}=r.internationalization;if(r?.dictionary?.locale)return{key:t,content:e,locale:i,filePath:n};let a={};for(let[t,n]of Object.entries(e))a[t]={nodeType:`translation`,translation:{[i]:n}};return{key:t,content:a,filePath:n}},u=async(e,n,r,a,s)=>{let{contentFilePath:u,relativeContentFilePath:d}=c(r,n,a,s);return await o(l(e,n,d,a),a,{newDictionariesPath:i(a.content.baseDir,t(u))}),u};export{l as createDictionary,c as resolveContentFilePath,u as writeContentHelper};
1
+ import{resolveContentFilePaths as e}from"./utils/extractDictionaryInfo.mjs";import{existsSync as t}from"node:fs";import{mkdir as n}from"node:fs/promises";import{dirname as r,relative as i}from"node:path";import{buildDictionary as a,ensureIntlayerBundle as o,loadContentDeclaration as s,writeContentDeclaration as c}from"@intlayer/chokidar/build";import{insertContentInDictionary as l}from"@intlayer/core/plugins";let u;const d=(e,t,n)=>{let r=l(t??{key:``,content:{},filePath:``},e,n).content,i={};for(let t in e)i[t]=r[t];return i},f=(e,t)=>{let n=l(t??{key:``,content:{},filePath:``},e).content,r={};for(let t in e)r[t]=n[t];return r},p=async(l,p,m,h)=>{let{absolutePath:g,isPerLocale:_}=await e(m,p,h),{defaultLocale:v}=h.internationalization,{baseDir:y}=h.system;u||=await o(h);let b=r(g);await n(b,{recursive:!0});let x=null;if(t(g))try{x=await s(g,h,u)??null}catch(e){console.error(e)}let S=i(y,g),C;if(_){let e=f(l,x);C={...x,key:p,content:e,locale:v,filePath:S}}else{let e=d(l,x,v);C={...x,key:p,content:e,filePath:S}}let w=i(y,b),T=await c(C,h,{newDictionariesPath:w,localeList:[v]});return await a([{...C,filePath:i(y,T?.path??g)}],h),g};export{d as mergeWithExistingMultilingualDictionary,f as mergeWithExistingPerLocaleDictionary,p as writeContentHelper};
2
2
  //# sourceMappingURL=contentWriter.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"contentWriter.mjs","names":[],"sources":["../../../src/extractContent/contentWriter.ts"],"sourcesContent":["import { basename, dirname, extname, join, relative, resolve } from 'node:path';\nimport { writeContentDeclaration } from '@intlayer/chokidar/cli';\nimport type {\n Dictionary,\n DictionaryKey,\n IntlayerConfig,\n} from '@intlayer/types';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\n\nexport type TranslationNode = {\n nodeType: 'translation';\n translation: Record<string, string>;\n};\n\n/**\n * Resolves the path for the content file associated with a component.\n * Checks for existing dictionaries first.\n */\nexport const resolveContentFilePath = (\n filePath: string,\n componentKey: string,\n configuration: IntlayerConfig,\n outputDir?: string\n): { contentFilePath: string; relativeContentFilePath: string } => {\n const { baseDir, fileExtensions } = configuration.content;\n const unmergedDictionaries = getUnmergedDictionaries(configuration) ?? {};\n const existingDicts = unmergedDictionaries[componentKey] as\n | Dictionary[]\n | undefined;\n\n if (existingDicts?.[0]?.filePath) {\n return {\n contentFilePath: resolve(baseDir, existingDicts[0].filePath),\n relativeContentFilePath: existingDicts[0].filePath,\n };\n }\n\n const dirName = outputDir ? resolve(outputDir) : dirname(filePath);\n const firstExtension = fileExtensions[0];\n const extension = firstExtension.startsWith('.')\n ? firstExtension\n : `.${firstExtension}`;\n const originalFileBase = basename(filePath, extname(filePath));\n const contentBaseName =\n originalFileBase.charAt(0).toLowerCase() + originalFileBase.slice(1);\n const contentFilePath = join(dirName, `${contentBaseName}${extension}`);\n const relativeContentFilePath = relative(baseDir, contentFilePath);\n\n return { contentFilePath, relativeContentFilePath };\n};\n\n/**\n * Creates a dictionary object from extracted content.\n * Handles both single-locale and multi-locale formats based on configuration.\n */\nexport const createDictionary = (\n extractedContent: Record<string, string>,\n componentKey: string,\n relativeContentFilePath: string,\n configuration: IntlayerConfig\n): Dictionary => {\n const { defaultLocale } = configuration.internationalization;\n const isPerLocaleFile = configuration?.dictionary?.locale;\n\n if (isPerLocaleFile) {\n return {\n key: componentKey,\n content: extractedContent,\n locale: defaultLocale,\n filePath: relativeContentFilePath,\n } as Dictionary;\n }\n\n const multilingualContent: Record<string, TranslationNode> = {};\n\n for (const [key, value] of Object.entries(extractedContent)) {\n multilingualContent[key] = {\n nodeType: 'translation',\n translation: {\n [defaultLocale]: value,\n },\n };\n }\n\n return {\n key: componentKey as DictionaryKey,\n content: multilingualContent,\n filePath: relativeContentFilePath,\n } as Dictionary;\n};\n\n/**\n * Helper to write extracted content to a dictionary file.\n */\nexport const writeContentHelper = async (\n extractedContent: Record<string, string>,\n componentKey: string,\n filePath: string,\n configuration: IntlayerConfig,\n outputDir?: string\n): Promise<string> => {\n const { contentFilePath, relativeContentFilePath } = resolveContentFilePath(\n filePath,\n componentKey,\n configuration,\n outputDir\n );\n\n const dictionary = createDictionary(\n extractedContent,\n componentKey,\n relativeContentFilePath,\n configuration\n );\n\n const relativeDir = relative(\n configuration.content.baseDir,\n dirname(contentFilePath)\n );\n\n await writeContentDeclaration(dictionary, configuration, {\n newDictionariesPath: relativeDir,\n });\n\n return contentFilePath;\n};\n"],"mappings":"qPAkBA,MAAa,GACX,EACA,EACA,EACA,IACiE,CACjE,GAAM,CAAE,UAAS,kBAAmB,EAAc,QAE5C,GADuB,EAAwB,EAAc,EAAI,EAAE,EAC9B,GAI3C,GAAI,IAAgB,IAAI,SACtB,MAAO,CACL,gBAAiB,EAAQ,EAAS,EAAc,GAAG,SAAS,CAC5D,wBAAyB,EAAc,GAAG,SAC3C,CAGH,IAAM,EAAU,EAAY,EAAQ,EAAU,CAAG,EAAQ,EAAS,CAC5D,EAAiB,EAAe,GAChC,EAAY,EAAe,WAAW,IAAI,CAC5C,EACA,IAAI,IACF,EAAmB,EAAS,EAAU,EAAQ,EAAS,CAAC,CAGxD,EAAkB,EAAK,EAAS,GADpC,EAAiB,OAAO,EAAE,CAAC,aAAa,CAAG,EAAiB,MAAM,EAAE,GACX,IAAY,CAGvE,MAAO,CAAE,kBAAiB,wBAFM,EAAS,EAAS,EAAgB,CAEf,EAOxC,GACX,EACA,EACA,EACA,IACe,CACf,GAAM,CAAE,iBAAkB,EAAc,qBAGxC,GAFwB,GAAe,YAAY,OAGjD,MAAO,CACL,IAAK,EACL,QAAS,EACT,OAAQ,EACR,SAAU,EACX,CAGH,IAAM,EAAuD,EAAE,CAE/D,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAiB,CACzD,EAAoB,GAAO,CACzB,SAAU,cACV,YAAa,EACV,GAAgB,EAClB,CACF,CAGH,MAAO,CACL,IAAK,EACL,QAAS,EACT,SAAU,EACX,EAMU,EAAqB,MAChC,EACA,EACA,EACA,EACA,IACoB,CACpB,GAAM,CAAE,kBAAiB,2BAA4B,EACnD,EACA,EACA,EACA,EACD,CAkBD,OAJA,MAAM,EAZa,EACjB,EACA,EACA,EACA,EACD,CAOyC,EAAe,CACvD,oBANkB,EAClB,EAAc,QAAQ,QACtB,EAAQ,EAAgB,CACzB,CAIA,CAAC,CAEK"}
1
+ {"version":3,"file":"contentWriter.mjs","names":[],"sources":["../../../src/extractContent/contentWriter.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { dirname, relative } from 'node:path';\nimport {\n buildDictionary,\n ensureIntlayerBundle,\n loadContentDeclaration,\n writeContentDeclaration,\n} from '@intlayer/chokidar/build';\nimport { insertContentInDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, DictionaryKey } from '@intlayer/types/dictionary';\nimport { resolveContentFilePaths } from './utils/extractDictionaryInfo';\n\n/**\n * Translation node structure used in dictionaries\n */\ntype TranslationNode = {\n nodeType: 'translation';\n translation: Record<string, string>;\n};\n\n/**\n * Dictionary content structure - map of keys to translation nodes\n */\ntype DictionaryContentMap = Record<string, TranslationNode>;\n\n/**\n * Cached bundle file path to optimize performance\n */\nlet cachedBundleFilePath: string | undefined;\n\n/**\n * Merge extracted content with existing dictionary for multilingual format.\n * - Keys in extracted but not in existing: added with default locale only\n * - Keys in both: preserve existing translations, update default locale value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\nexport const mergeWithExistingMultilingualDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n): DictionaryContentMap => {\n const dictionary: Dictionary =\n existingDictionary ??\n ({\n key: '',\n content: {},\n filePath: '',\n } as Dictionary);\n\n const mergedDictionary = insertContentInDictionary(\n dictionary,\n extractedContent,\n defaultLocale as Locale\n );\n\n const mergedContent = mergedDictionary.content as DictionaryContentMap;\n\n // Pruning: remove keys not in extractedContent\n const finalContent: DictionaryContentMap = {};\n for (const key in extractedContent) {\n finalContent[key] = mergedContent[key];\n }\n\n return finalContent;\n};\n\n/**\n * Merge extracted content with existing dictionary for per-locale format.\n * - Keys in extracted but not in existing: added\n * - Keys in both: update value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\nexport const mergeWithExistingPerLocaleDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null\n): Record<string, string> => {\n const dictionary: Dictionary =\n existingDictionary ??\n ({\n key: '',\n content: {},\n filePath: '',\n } as Dictionary);\n\n const mergedDictionary = insertContentInDictionary(\n dictionary,\n extractedContent\n );\n\n const mergedContent = mergedDictionary.content as Record<string, string>;\n\n // Pruning: remove keys not in extractedContent\n const finalContent: Record<string, string> = {};\n for (const key in extractedContent) {\n finalContent[key] = mergedContent[key];\n }\n\n return finalContent;\n};\n\n/**\n * Helper to write extracted content to dictionary file(s).\n */\nexport const writeContentHelper = async (\n extractedContent: Record<string, string>,\n dictionaryKey: DictionaryKey,\n filePath: string,\n configuration: IntlayerConfig\n): Promise<string> => {\n const { absolutePath, isPerLocale } = await resolveContentFilePaths(\n filePath,\n dictionaryKey,\n configuration\n );\n\n const { defaultLocale } = configuration.internationalization;\n const { baseDir } = configuration.system;\n\n if (!cachedBundleFilePath) {\n cachedBundleFilePath = await ensureIntlayerBundle(configuration);\n }\n\n const outputDir = dirname(absolutePath);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Read existing dictionary to preserve translations and metadata\n let existingDictionary: Dictionary | null = null;\n\n if (existsSync(absolutePath)) {\n try {\n const dictionary = await loadContentDeclaration(\n absolutePath,\n configuration,\n cachedBundleFilePath\n );\n\n existingDictionary = dictionary ?? null;\n } catch (error) {\n console.error(error);\n }\n }\n\n const relativeContentFilePath = relative(baseDir, absolutePath);\n\n let mergedDictionary: Dictionary;\n\n if (isPerLocale) {\n // Per-locale format: simple string content for a single locale\n const mergedContent = mergeWithExistingPerLocaleDictionary(\n extractedContent,\n existingDictionary\n );\n\n mergedDictionary = {\n // Preserve existing metadata\n ...existingDictionary,\n key: dictionaryKey,\n content: mergedContent,\n locale: defaultLocale,\n filePath: relativeContentFilePath,\n };\n } else {\n // Multilingual format: content wrapped in translation nodes for multiple locales\n const mergedContent = mergeWithExistingMultilingualDictionary(\n extractedContent,\n existingDictionary,\n defaultLocale\n );\n\n mergedDictionary = {\n // Preserve existing metadata\n ...existingDictionary,\n key: dictionaryKey,\n content: mergedContent,\n filePath: relativeContentFilePath,\n };\n }\n\n const relativeDir = relative(baseDir, outputDir);\n\n const writeResult = await writeContentDeclaration(\n mergedDictionary,\n configuration,\n {\n newDictionariesPath: relativeDir,\n localeList: [defaultLocale],\n }\n );\n\n // Build the dictionary immediately\n const dictionaryToBuild: Dictionary = {\n ...mergedDictionary,\n filePath: relative(baseDir, writeResult?.path ?? absolutePath),\n };\n\n await buildDictionary([dictionaryToBuild], configuration);\n\n return absolutePath;\n};\n"],"mappings":"6ZA+BA,IAAI,EAQJ,MAAa,GACX,EACA,EACA,IACyB,CAezB,IAAM,EANmB,EAPvB,GACC,CACC,IAAK,GACL,QAAS,EAAE,CACX,SAAU,GACX,CAID,EACA,EACD,CAEsC,QAGjC,EAAqC,EAAE,CAC7C,IAAK,IAAM,KAAO,EAChB,EAAa,GAAO,EAAc,GAGpC,OAAO,GASI,GACX,EACA,IAC2B,CAc3B,IAAM,EALmB,EAPvB,GACC,CACC,IAAK,GACL,QAAS,EAAE,CACX,SAAU,GACX,CAID,EACD,CAEsC,QAGjC,EAAuC,EAAE,CAC/C,IAAK,IAAM,KAAO,EAChB,EAAa,GAAO,EAAc,GAGpC,OAAO,GAMI,EAAqB,MAChC,EACA,EACA,EACA,IACoB,CACpB,GAAM,CAAE,eAAc,eAAgB,MAAM,EAC1C,EACA,EACA,EACD,CAEK,CAAE,iBAAkB,EAAc,qBAClC,CAAE,WAAY,EAAc,OAElC,AACE,IAAuB,MAAM,EAAqB,EAAc,CAGlE,IAAM,EAAY,EAAQ,EAAa,CAGvC,MAAM,EAAM,EAAW,CAAE,UAAW,GAAM,CAAC,CAG3C,IAAI,EAAwC,KAE5C,GAAI,EAAW,EAAa,CAC1B,GAAI,CAOF,EANmB,MAAM,EACvB,EACA,EACA,EACD,EAEkC,WAC5B,EAAO,CACd,QAAQ,MAAM,EAAM,CAIxB,IAAM,EAA0B,EAAS,EAAS,EAAa,CAE3D,EAEJ,GAAI,EAAa,CAEf,IAAM,EAAgB,EACpB,EACA,EACD,CAED,EAAmB,CAEjB,GAAG,EACH,IAAK,EACL,QAAS,EACT,OAAQ,EACR,SAAU,EACX,KACI,CAEL,IAAM,EAAgB,EACpB,EACA,EACA,EACD,CAED,EAAmB,CAEjB,GAAG,EACH,IAAK,EACL,QAAS,EACT,SAAU,EACX,CAGH,IAAM,EAAc,EAAS,EAAS,EAAU,CAE1C,EAAc,MAAM,EACxB,EACA,EACA,CACE,oBAAqB,EACrB,WAAY,CAAC,EAAc,CAC5B,CACF,CAUD,OAFA,MAAM,EAAgB,CALgB,CACpC,GAAG,EACH,SAAU,EAAS,EAAS,GAAa,MAAQ,EAAa,CAC/D,CAEwC,CAAE,EAAc,CAElD"}
@@ -1,2 +1,2 @@
1
- import{ATTRIBUTES_TO_EXTRACT as e}from"./utils/constants.mjs";import{extractDictionaryKey as t,extractDictionaryKeyFromPath as n}from"./utils/extractDictionaryKey.mjs";import{generateKey as r}from"./utils/generateKey.mjs";import{shouldExtract as i}from"./utils/shouldExtract.mjs";import{extractTsContent as a}from"./babelProcessor.mjs";import{processTsxFile as o}from"./processTsxFile.mjs";import{writeContentHelper as s}from"./contentWriter.mjs";import{extname as c,relative as l}from"node:path";import{ANSIColors as u,colorize as d,colorizePath as f,getAppLogger as p}from"@intlayer/config/logger";import{getConfiguration as m}from"@intlayer/config/node";import{execSync as h}from"node:child_process";import{readFileSync as g}from"node:fs";import{detectFormatCommand as _}from"@intlayer/chokidar/cli";import{getUnmergedDictionaries as v}from"@intlayer/unmerged-dictionaries-entry";let y=null,b=null;const x=async(x,S,C)=>{let w=!C?.declarationOnly,T=!C?.codeOnly&&!C?.onExtract,E=C?.configuration??m(C?.configOptions),D=p(E),{baseDir:O}=E.content,k=C?.unmergedDictionaries??v(E),A=C?.code??g(x,`utf-8`),j=t(x,A),M=c(x),N=l(O,x),P=null,F=null;if(M===`.vue`)try{y??=await import(`@intlayer/vue-compiler`);let t=await y.processVueFile(x,j,S,{generateKey:r,shouldExtract:i,attributesToExtract:e,extractDictionaryKeyFromPath:n,extractTsContent:(e,t,n,r,i)=>a(e,t,n,r,i,k)},w);t&&(P={[j]:t})}catch(e){throw e.code===`ERR_MODULE_NOT_FOUND`||e.message?.includes(`Cannot find module`)?Error(`Please install ${f(`@intlayer/vue-compiler`,u.YELLOW)} to process Vue files.`):e}else if(M===`.svelte`)try{b??=await import(`@intlayer/svelte-compiler`);let t=await b.processSvelteFile(x,j,S,{generateKey:r,shouldExtract:i,attributesToExtract:e,extractDictionaryKeyFromPath:n,extractTsContent:(e,t,n,r,i)=>a(e,t,n,r,i,k)},w);t&&(P={[j]:t})}catch(e){throw e.code===`ERR_MODULE_NOT_FOUND`||e.message?.includes(`Cannot find module`)?Error(`Please install ${f(`@intlayer/svelte-compiler`,u.YELLOW)} to process Svelte files.`):e}else if([`.tsx`,`.jsx`,`.ts`,`.js`].includes(M))try{let e=o(x,j,S,E,w,k,A);e&&(P=e.extractedContent,F=e.modifiedCode)}catch(e){throw e.code===`ERR_MODULE_NOT_FOUND`||e.message?.includes(`Cannot find module`)?Error(`Please install ${f(`@intlayer/babel`,u.YELLOW)} to process TSX/JSX/TS/JS files.`):e}if(!P||Object.keys(P).length===0){D(`${d(`Compiler:`,u.GREY_DARK)} No extractable text found in ${f(N)}`,{isVerbose:!0});return}if(C?.onExtract)for(let[e,t]of Object.entries(P))await C.onExtract({key:e,content:t,filePath:x});if(T)for(let[e,t]of Object.entries(P)){let n=await s(t,e,x,E,C?.outputDir),r=l(E.content.baseDir,n);D(`${d(`Compiler:`,u.GREY_DARK)} Created content file: ${f(r)}`)}if(w){let e=_(E);if(e)try{h(e.replace(`{{file}}`,x),{stdio:`inherit`,cwd:O})}catch(e){console.error(e)}D(`${d(`Compiler:`,u.GREY_DARK)} Updated component: ${f(l(O,x))}`)}return{transformedCode:F}};export{x as extractContent};
1
+ import{extractDictionaryKey as e,extractDictionaryKeyFromPath as t}from"./utils/extractDictionaryKey.mjs";import{resolveContentFilePaths as n}from"./utils/extractDictionaryInfo.mjs";import{writeContentHelper as r}from"./contentWriter.mjs";import{ATTRIBUTES_TO_EXTRACT as i}from"./utils/constants.mjs";import{generateKey as a}from"./utils/generateKey.mjs";import{shouldExtract as o}from"./utils/shouldExtract.mjs";import{extractTsContent as s}from"./babelProcessor.mjs";import{processTsxFile as c}from"./processTsxFile.mjs";import{formatPath as l}from"@intlayer/chokidar/utils";import{ANSIColors as u,colorize as d,colorizePath as f,getAppLogger as p}from"@intlayer/config/logger";import{getConfiguration as m}from"@intlayer/config/node";import{readFileSync as h}from"node:fs";import{extname as g,relative as _}from"node:path";import{getProjectRequire as v}from"@intlayer/config/utils";import{getUnmergedDictionaries as y}from"@intlayer/unmerged-dictionaries-entry";import{detectFormatCommand as b}from"@intlayer/chokidar/cli";import{execSync as x}from"node:child_process";let S=null,C=null;const w=(e,t)=>{if(t)return{extractedContentMap:{[e]:t.extractedContent},transformedCode:t.code}},T=(n,r,l,d,p,m)=>{let _=l?.code??h(n,`utf-8`),v=m??e(n,_,d.configuration.compiler.dictionaryKeyPrefix),y=g(n),{vueCompiler:b,svelteCompiler:x,unmergedDictionaries:S,configuration:C}=d,T={generateKey:a,shouldExtract:o,attributesToExtract:i,extractDictionaryKeyFromPath:t,extractTsContent:(e,t,n,r,i)=>s(e,t,n,r,i,S)};if(y===`.vue`){if(!b)throw Error(`Please install ${f(`@intlayer/vue-compiler`,u.YELLOW)} to process Vue files.`);let e=b.processVueFile(n,v,r,T,p);if(e)return w(v,e)}if(y===`.svelte`){if(!x)throw Error(`Please install ${f(`@intlayer/svelte-compiler`,u.YELLOW)} to process Svelte files.`);let e=x.processSvelteFile(n,v,r,T,p);if(e)return w(v,e)}if([`.tsx`,`.jsx`,`.ts`,`.js`,`.cjs`,`.mjs`].includes(y)){let e=c(n,v,r,C,p,S,_);if(e)return{extractedContentMap:e.extractedContent,transformedCode:e.modifiedCode}}},E=async(e,t,n,{configuration:i,baseDir:a,appLogger:o},s)=>{if(n?.onExtract)for(let[r,i]of Object.entries(e))await n.onExtract({key:r,content:i,filePath:t});if(!n?.codeOnly&&!n?.onExtract)for(let[n,s]of Object.entries(e)){let e=_(a,await r(s,n,t,i));o(`${d(`Compiler:`,u.GREY_DARK)} Created content file: ${f(e)}`)}if(s){let e=b(i);if(e)try{x(e.replace(`{{file}}`,t),{stdio:`inherit`,cwd:a})}catch(e){console.error(e)}o(`${d(`Compiler:`,u.GREY_DARK)} Updated component: ${f(_(a,t))}`)}},D=async(t,r,i)=>{let a=i?.configuration??m(i?.configOptions),o=p(a),{baseDir:s}=a.system,c=i?.unmergedDictionaries??y(a),l=!i?.declarationOnly,v=g(t);v===`.vue`&&!S&&(S=await import(`@intlayer/vue-compiler`)),v===`.svelte`&&!C&&(C=await import(`@intlayer/svelte-compiler`));let b=e(t,i?.code??h(t,`utf-8`),a.compiler.dictionaryKeyPrefix),x=await T(t,r,i,{vueCompiler:S,svelteCompiler:C,unmergedDictionaries:c,configuration:a},l,b);if(!x||!x.extractedContentMap){o(`${d(`Compiler:`,u.GREY_DARK)} No extractable text found in ${f(_(s,t))}`,{isVerbose:!0});return}let{relativePath:w}=await n(t,b,a);return o(`${d(`Compiler:`,u.GREY_DARK)} Target dictionary path: ${f(w)}`,{isVerbose:!0}),await E(x.extractedContentMap,t,i,{configuration:a,baseDir:s,appLogger:o},l),{transformedCode:x.transformedCode}},O=(e,t,n)=>{let r=n?.configuration??m(n?.configOptions),i=p(r),{baseDir:a}=r.system,o=n?.unmergedDictionaries??y(r),s=!n?.declarationOnly,c=g(e),h=v();if(c===`.vue`&&!S)try{S=h(`@intlayer/vue-compiler`)}catch{}if(c===`.svelte`&&!C)try{C=h(`@intlayer/svelte-compiler`)}catch{}let b=T(e,t,n,{vueCompiler:S,svelteCompiler:C,unmergedDictionaries:o,configuration:r},s);if(b instanceof Promise)throw Error(`Synchronous extraction failed: External compiler returned a Promise for ${l(_(a,e))}`);if(b?.extractedContentMap){let{extractedContentMap:t,transformedCode:r}=b;if(n?.onExtract)for(let[r,i]of Object.entries(t))n.onExtract({key:r,content:i,filePath:e});return{transformedCode:r,extractedContent:t}}i(`${d(`Compiler:`,u.GREY_DARK)} No extractable text found in ${f(_(a,e))}`,{isVerbose:!0})};export{D as extractContent,O as extractContentSync};
2
2
  //# sourceMappingURL=extractContent.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"extractContent.mjs","names":[],"sources":["../../../src/extractContent/extractContent.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { extname, relative } from 'node:path';\nimport { detectFormatCommand } from '@intlayer/chokidar/cli';\nimport {\n ANSIColors,\n colorize,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport type { IntlayerConfig } from '@intlayer/types';\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 outputDir?: string;\n /**\n * If true, only transform the source file — skip writing content declarations.\n */\n codeOnly?: boolean;\n /**\n * If true, only write content declarations — skip transforming the source file.\n * When set, `transformedCode` will still be returned (computed but not written to disk).\n */\n declarationOnly?: boolean;\n unmergedDictionaries?: Record<string, unknown>;\n configuration?: IntlayerConfig;\n /**\n * Raw source code to process instead of reading from disk.\n * Useful for Vite/webpack transform hooks where the code may already\n * have been modified by a previous plugin.\n */\n code?: string;\n /**\n * Callback invoked for each extracted dictionary key/content pair.\n * When provided, the caller is responsible for writing content declarations\n * (the built-in `writeContentHelper` is skipped unless `writeContent` is also true).\n * Used by Vite/webpack plugins that manage their own dictionary write pipeline.\n */\n onExtract?: (result: {\n key: string;\n content: Record<string, string>;\n filePath: string;\n }) => void | Promise<void>;\n};\n\n// Module caches for optional compiler packages\nlet vueCompiler: typeof import('@intlayer/vue-compiler') | null = null;\nlet svelteCompiler: typeof import('@intlayer/svelte-compiler') | null = null;\n\n/**\n * Extracts Intlayer content from a single source file and optionally transforms it.\n *\n * - For `.vue` / `.svelte` files the matching optional compiler package is used.\n * - For `.tsx` / `.jsx` / `.ts` / `.js` files the Babel-based `processTsxFile` is used.\n *\n * Returns `{ transformedCode }` so callers (e.g. the Vite plugin) can pass the\n * modified source back to the bundler without writing the file to disk.\n */\nexport const extractContent = async (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayerOptions\n): Promise<{ transformedCode: string | null } | undefined> => {\n const saveComponent = !options?.declarationOnly;\n const writeContent = !options?.codeOnly && !options?.onExtract;\n\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n const { baseDir } = configuration.content;\n\n const unmergedDictionaries =\n options?.unmergedDictionaries ?? getUnmergedDictionaries(configuration);\n\n const fileText = options?.code ?? readFileSync(filePath, 'utf-8');\n const componentKey = extractDictionaryKey(filePath, fileText);\n const ext = extname(filePath);\n const relativeFilePath = relative(baseDir, filePath);\n\n let extractedContentMap: Record<string, Record<string, string>> | null = null;\n let transformedCode: string | null = null;\n\n if (ext === '.vue') {\n try {\n vueCompiler ??= await import('@intlayer/vue-compiler');\n\n const res = await vueCompiler.processVueFile(\n filePath,\n componentKey,\n packageName,\n {\n generateKey,\n shouldExtract,\n attributesToExtract: ATTRIBUTES_TO_EXTRACT,\n extractDictionaryKeyFromPath,\n extractTsContent: (\n ast: any,\n code: string,\n keys: Set<string>,\n config: any,\n path: string\n ) =>\n extractTsContent(\n ast,\n code,\n keys,\n config,\n path,\n unmergedDictionaries\n ),\n },\n saveComponent\n );\n\n if (res) {\n extractedContentMap = {\n [componentKey]: res as Record<string, string>,\n };\n }\n } catch (error: any) {\n if (\n error.code === 'ERR_MODULE_NOT_FOUND' ||\n error.message?.includes('Cannot find module')\n ) {\n throw new Error(\n `Please install ${colorizePath('@intlayer/vue-compiler', ANSIColors.YELLOW)} to process Vue files.`\n );\n }\n throw error;\n }\n } else if (ext === '.svelte') {\n try {\n svelteCompiler ??= await import('@intlayer/svelte-compiler');\n\n const res = await svelteCompiler.processSvelteFile(\n filePath,\n componentKey,\n packageName,\n {\n generateKey,\n shouldExtract,\n attributesToExtract: ATTRIBUTES_TO_EXTRACT,\n extractDictionaryKeyFromPath,\n extractTsContent: (\n ast: any,\n code: string,\n keys: Set<string>,\n config: any,\n path: string\n ) =>\n extractTsContent(\n ast,\n code,\n keys,\n config,\n path,\n unmergedDictionaries\n ),\n },\n saveComponent\n );\n\n if (res) {\n extractedContentMap = {\n [componentKey]: res as Record<string, string>,\n };\n }\n } catch (error: any) {\n if (\n error.code === 'ERR_MODULE_NOT_FOUND' ||\n error.message?.includes('Cannot find module')\n ) {\n throw new Error(\n `Please install ${colorizePath('@intlayer/svelte-compiler', ANSIColors.YELLOW)} to process Svelte files.`\n );\n }\n throw error;\n }\n } else if (['.tsx', '.jsx', '.ts', '.js'].includes(ext)) {\n try {\n const result = processTsxFile(\n filePath,\n componentKey,\n packageName,\n configuration,\n saveComponent,\n unmergedDictionaries,\n fileText\n );\n\n if (result) {\n extractedContentMap = result.extractedContent;\n transformedCode = result.modifiedCode;\n }\n } catch (error: any) {\n if (\n error.code === 'ERR_MODULE_NOT_FOUND' ||\n error.message?.includes('Cannot find module')\n ) {\n throw new Error(\n `Please install ${colorizePath('@intlayer/babel', ANSIColors.YELLOW)} to process TSX/JSX/TS/JS files.`\n );\n }\n throw error;\n }\n }\n\n if (!extractedContentMap || Object.keys(extractedContentMap).length === 0) {\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} No extractable text found in ${colorizePath(relativeFilePath)}`,\n {\n isVerbose: true,\n }\n );\n return undefined;\n }\n\n // Notify caller via callback (e.g. Vite plugin's own dictionary pipeline)\n if (options?.onExtract) {\n for (const [key, content] of Object.entries(extractedContentMap)) {\n await options.onExtract({ key, content, filePath });\n }\n }\n\n // Write content declarations using the built-in helper when no custom callback\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 options?.outputDir\n );\n\n const relativeContentFilePath = relative(\n configuration.content.baseDir,\n contentFilePath\n );\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 return { transformedCode };\n};\n"],"mappings":"m3BA8DA,IAAI,EAA8D,KAC9D,EAAoE,KAWxE,MAAa,EAAiB,MAC5B,EACA,EACA,IAC4D,CAC5D,IAAM,EAAgB,CAAC,GAAS,gBAC1B,EAAe,CAAC,GAAS,UAAY,CAAC,GAAS,UAE/C,EACJ,GAAS,eAAiB,EAAiB,GAAS,cAAc,CAC9D,EAAY,EAAa,EAAc,CACvC,CAAE,WAAY,EAAc,QAE5B,EACJ,GAAS,sBAAwB,EAAwB,EAAc,CAEnE,EAAW,GAAS,MAAQ,EAAa,EAAU,QAAQ,CAC3D,EAAe,EAAqB,EAAU,EAAS,CACvD,EAAM,EAAQ,EAAS,CACvB,EAAmB,EAAS,EAAS,EAAS,CAEhD,EAAqE,KACrE,EAAiC,KAErC,GAAI,IAAQ,OACV,GAAI,CACF,IAAgB,MAAM,OAAO,0BAE7B,IAAM,EAAM,MAAM,EAAY,eAC5B,EACA,EACA,EACA,CACE,cACA,gBACA,oBAAqB,EACrB,+BACA,kBACE,EACA,EACA,EACA,EACA,IAEA,EACE,EACA,EACA,EACA,EACA,EACA,EACD,CACJ,CACD,EACD,CAEG,IACF,EAAsB,EACnB,GAAe,EACjB,QAEI,EAAY,CASnB,MAPE,EAAM,OAAS,wBACf,EAAM,SAAS,SAAS,qBAAqB,CAEnC,MACR,kBAAkB,EAAa,yBAA0B,EAAW,OAAO,CAAC,wBAC7E,CAEG,UAEC,IAAQ,UACjB,GAAI,CACF,IAAmB,MAAM,OAAO,6BAEhC,IAAM,EAAM,MAAM,EAAe,kBAC/B,EACA,EACA,EACA,CACE,cACA,gBACA,oBAAqB,EACrB,+BACA,kBACE,EACA,EACA,EACA,EACA,IAEA,EACE,EACA,EACA,EACA,EACA,EACA,EACD,CACJ,CACD,EACD,CAEG,IACF,EAAsB,EACnB,GAAe,EACjB,QAEI,EAAY,CASnB,MAPE,EAAM,OAAS,wBACf,EAAM,SAAS,SAAS,qBAAqB,CAEnC,MACR,kBAAkB,EAAa,4BAA6B,EAAW,OAAO,CAAC,2BAChF,CAEG,UAEC,CAAC,OAAQ,OAAQ,MAAO,MAAM,CAAC,SAAS,EAAI,CACrD,GAAI,CACF,IAAM,EAAS,EACb,EACA,EACA,EACA,EACA,EACA,EACA,EACD,CAEG,IACF,EAAsB,EAAO,iBAC7B,EAAkB,EAAO,oBAEpB,EAAY,CASnB,MAPE,EAAM,OAAS,wBACf,EAAM,SAAS,SAAS,qBAAqB,CAEnC,MACR,kBAAkB,EAAa,kBAAmB,EAAW,OAAO,CAAC,kCACtE,CAEG,EAIV,GAAI,CAAC,GAAuB,OAAO,KAAK,EAAoB,CAAC,SAAW,EAAG,CACzE,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,iCAAiC,EAAa,EAAiB,GAC9G,CACE,UAAW,GACZ,CACF,CACD,OAIF,GAAI,GAAS,UACX,IAAK,GAAM,CAAC,EAAK,KAAY,OAAO,QAAQ,EAAoB,CAC9D,MAAM,EAAQ,UAAU,CAAE,MAAK,UAAS,WAAU,CAAC,CAKvD,GAAI,EACF,IAAK,GAAM,CAAC,EAAK,KAAY,OAAO,QAAQ,EAAoB,CAAE,CAChE,IAAM,EAAkB,MAAM,EAC5B,EACA,EACA,EACA,EACA,GAAS,UACV,CAEK,EAA0B,EAC9B,EAAc,QAAQ,QACtB,EACD,CACD,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,yBAAyB,EAAa,EAAwB,GAC9G,CAIL,GAAI,EAAe,CACjB,IAAM,EAAgB,EAAoB,EAAc,CAExD,GAAI,EACF,GAAI,CACF,EAAS,EAAc,QAAQ,WAAY,EAAS,CAAE,CACpD,MAAO,UACP,IAAK,EACN,CAAC,OACK,EAAO,CACd,QAAQ,MAAM,EAAM,CAIxB,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,sBAAsB,EAAa,EAAS,EAAS,EAAS,CAAC,GAC/G,CAGH,MAAO,CAAE,kBAAiB"}
1
+ {"version":3,"file":"extractContent.mjs","names":[],"sources":["../../../src/extractContent/extractContent.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { extname, relative } from 'node:path';\nimport type * as t from '@babel/types';\nimport { detectFormatCommand } from '@intlayer/chokidar/cli';\nimport { formatPath } from '@intlayer/chokidar/utils';\nimport {\n ANSIColors,\n colorize,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getProjectRequire } from '@intlayer/config/utils';\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 { resolveContentFilePaths } from './utils/extractDictionaryInfo';\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):\n | InternalExtractResult\n | Promise<InternalExtractResult | undefined>\n | 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 );\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 );\n\n if (res) {\n return formatCompilerResult(componentKey, res);\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\nexport const extractContent = async (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayerOptions\n): Promise<{ transformedCode: string | null } | undefined> => {\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n\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 if (componentExtension === '.vue' && !vueCompiler) {\n vueCompiler = (await import(\n '@intlayer/vue-compiler'\n )) as unknown as VueCompiler;\n }\n\n if (componentExtension === '.svelte' && !svelteCompiler) {\n svelteCompiler = (await import(\n '@intlayer/svelte-compiler'\n )) as unknown as SvelteCompiler;\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 = await processFileInternal(\n filePath,\n packageName,\n options,\n { vueCompiler, svelteCompiler, unmergedDictionaries, configuration },\n saveComponent,\n dictionaryKey\n );\n\n if (!result || !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 { relativePath } = await resolveContentFilePaths(\n filePath,\n dictionaryKey,\n configuration\n );\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Target dictionary path: ${colorizePath(relativePath)}`,\n { isVerbose: true }\n );\n\n await handleExtractionSideEffects(\n result.extractedContentMap,\n filePath,\n options,\n { configuration, baseDir, appLogger },\n saveComponent\n );\n\n return { transformedCode: result.transformedCode };\n};\n\nexport const extractContentSync = (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayerOptions\n):\n | {\n transformedCode: string | null;\n extractedContent: Record<string, Record<string, string>>;\n }\n | undefined => {\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 const requireFn = getProjectRequire();\n\n if (componentExtension === '.vue' && !vueCompiler) {\n try {\n vueCompiler = requireFn('@intlayer/vue-compiler') as VueCompiler;\n } catch {\n // Ignored\n }\n }\n if (componentExtension === '.svelte' && !svelteCompiler) {\n try {\n svelteCompiler = requireFn('@intlayer/svelte-compiler') as SvelteCompiler;\n } catch {\n // Ignored\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 instanceof Promise) {\n throw new Error(\n `Synchronous extraction failed: External compiler returned a Promise for ${formatPath(relative(baseDir, filePath))}`\n );\n }\n\n if (result?.extractedContentMap) {\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, extractedContent: extractedContentMap };\n }\n\n appLogger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} No extractable text found in ${colorizePath(relative(baseDir, filePath))}`,\n { isVerbose: true }\n );\n\n return undefined;\n};\n"],"mappings":"gjCAqEA,IAAI,EAAkC,KAClC,EAAwC,KAO5C,MAAM,GACJ,EACA,IACsC,CACjC,KAEL,MAAO,CACL,oBAAqB,EAAG,GAAe,EAAI,iBAAkB,CAC7D,gBAAiB,EAAI,KACtB,EAUG,GACJ,EACA,EACA,EACA,EACA,EACA,IAIe,CACf,IAAM,EAAW,GAAS,MAAQ,EAAa,EAAU,QAAQ,CAC3D,EACJ,GACA,EACE,EACA,EACA,EAAa,cAAc,SAAS,oBACrC,CACG,EAAM,EAAQ,EAAS,CAEvB,CAAE,cAAa,iBAAgB,uBAAsB,iBACzD,EAEI,EAAiD,CACrD,cACA,gBACA,oBAAqB,EACrB,+BACA,kBAAmB,EAAK,EAAM,EAAM,EAAQ,IAC1C,EACE,EACA,EACA,EACA,EACA,EACA,EACD,CACJ,CAED,GAAI,IAAQ,OAAQ,CAClB,GAAI,CAAC,EACH,MAAU,MACR,kBAAkB,EAAa,yBAA0B,EAAW,OAAO,CAAC,wBAC7E,CAGH,IAAM,EAAM,EAAY,eACtB,EACA,EACA,EACA,EACA,EACD,CAED,GAAI,EACF,OAAO,EAAqB,EAAc,EAAI,CAIlD,GAAI,IAAQ,UAAW,CACrB,GAAI,CAAC,EACH,MAAU,MACR,kBAAkB,EAAa,4BAA6B,EAAW,OAAO,CAAC,2BAChF,CAGH,IAAM,EAAM,EAAe,kBACzB,EACA,EACA,EACA,EACA,EACD,CAED,GAAI,EACF,OAAO,EAAqB,EAAc,EAAI,CAIlD,GAAI,CAAC,OAAQ,OAAQ,MAAO,MAAO,OAAQ,OAAO,CAAC,SAAS,EAAI,CAAE,CAChE,IAAM,EAAS,EACb,EACA,EACA,EACA,EACA,EACA,EACA,EACD,CAED,GAAI,EACF,MAAO,CACL,oBAAqB,EAAO,iBAC5B,gBAAiB,EAAO,aACzB,GAOD,EAA8B,MAClC,EACA,EACA,EACA,CACE,gBACA,UACA,aAMF,IACG,CACH,GAAI,GAAS,UACX,IAAK,GAAM,CAAC,EAAK,KAAY,OAAO,QAAQ,EAAoB,CAC9D,MAAM,EAAQ,UAAU,CAAE,MAAK,UAAS,WAAU,CAAC,CAMvD,GAFqB,CAAC,GAAS,UAAY,CAAC,GAAS,UAGnD,IAAK,GAAM,CAAC,EAAK,KAAY,OAAO,QAAQ,EAAoB,CAAE,CAQhE,IAAM,EAA0B,EAAS,EAPjB,MAAM,EAC5B,EACA,EACA,EACA,EACD,CAEiE,CAClE,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,yBAAyB,EAAa,EAAwB,GAC9G,CAIL,GAAI,EAAe,CACjB,IAAM,EAAgB,EAAoB,EAAc,CAExD,GAAI,EACF,GAAI,CACF,EAAS,EAAc,QAAQ,WAAY,EAAS,CAAE,CACpD,MAAO,UACP,IAAK,EACN,CAAC,OACK,EAAO,CACd,QAAQ,MAAM,EAAM,CAIxB,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,sBAAsB,EAAa,EAAS,EAAS,EAAS,CAAC,GAC/G,GAIQ,EAAiB,MAC5B,EACA,EACA,IAC4D,CAC5D,IAAM,EACJ,GAAS,eAAiB,EAAiB,GAAS,cAAc,CAC9D,EAAY,EAAa,EAAc,CAEvC,CAAE,WAAY,EAAc,OAC5B,EACJ,GAAS,sBAAwB,EAAwB,EAAc,CACnE,EAAgB,CAAC,GAAS,gBAC1B,EAAqB,EAAQ,EAAS,CAExC,IAAuB,QAAU,CAAC,IACpC,EAAe,MAAM,OACnB,2BAIA,IAAuB,WAAa,CAAC,IACvC,EAAkB,MAAM,OACtB,8BAKJ,IAAM,EAAgB,EACpB,EAFe,GAAS,MAAQ,EAAa,EAAU,QAAQ,CAI/D,EAAc,SAAS,oBACxB,CAEK,EAAS,MAAM,EACnB,EACA,EACA,EACA,CAAE,cAAa,iBAAgB,uBAAsB,gBAAe,CACpE,EACA,EACD,CAED,GAAI,CAAC,GAAU,CAAC,EAAO,oBAAqB,CAC1C,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,gCAAgC,EAAa,EAAS,EAAS,EAAS,CAAC,GACxH,CAAE,UAAW,GAAM,CACpB,CACD,OAGF,GAAM,CAAE,gBAAiB,MAAM,EAC7B,EACA,EACA,EACD,CAeD,OAbA,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,2BAA2B,EAAa,EAAa,GACpG,CAAE,UAAW,GAAM,CACpB,CAED,MAAM,EACJ,EAAO,oBACP,EACA,EACA,CAAE,gBAAe,UAAS,YAAW,CACrC,EACD,CAEM,CAAE,gBAAiB,EAAO,gBAAiB,EAGvC,GACX,EACA,EACA,IAMe,CACf,IAAM,EACJ,GAAS,eAAiB,EAAiB,GAAS,cAAc,CAC9D,EAAY,EAAa,EAAc,CACvC,CAAE,WAAY,EAAc,OAC5B,EACJ,GAAS,sBAAwB,EAAwB,EAAc,CACnE,EAAgB,CAAC,GAAS,gBAC1B,EAAqB,EAAQ,EAAS,CAEtC,EAAY,GAAmB,CAErC,GAAI,IAAuB,QAAU,CAAC,EACpC,GAAI,CACF,EAAc,EAAU,yBAAyB,MAC3C,EAIV,GAAI,IAAuB,WAAa,CAAC,EACvC,GAAI,CACF,EAAiB,EAAU,4BAA4B,MACjD,EAKV,IAAM,EAAS,EACb,EACA,EACA,EACA,CAAE,cAAa,iBAAgB,uBAAsB,gBAAe,CACpE,EACD,CAED,GAAI,aAAkB,QACpB,MAAU,MACR,2EAA2E,EAAW,EAAS,EAAS,EAAS,CAAC,GACnH,CAGH,GAAI,GAAQ,oBAAqB,CAC/B,GAAM,CAAE,sBAAqB,mBAAoB,EAEjD,GAAI,GAAS,UACX,IAAK,GAAM,CAAC,EAAK,KAAY,OAAO,QAAQ,EAAoB,CACzD,EAAQ,UAAU,CAAE,MAAK,UAAS,WAAU,CAAC,CAItD,MAAO,CAAE,kBAAiB,iBAAkB,EAAqB,CAGnE,EACE,GAAG,EAAS,YAAa,EAAW,UAAU,CAAC,gCAAgC,EAAa,EAAS,EAAS,EAAS,CAAC,GACxH,CAAE,UAAW,GAAM,CACpB"}
@@ -1 +1 @@
1
- import{ATTRIBUTES_TO_EXTRACT as e,packageList as t}from"./utils/constants.mjs";import{detectPackageName as n}from"./utils/detectPackageName.mjs";import{extractContent as r}from"./extractContent.mjs";export{e as ATTRIBUTES_TO_EXTRACT,n as detectPackageName,r as extractContent,t as packageList};
1
+ import{extractDictionaryKey as e,extractDictionaryKeyFromPath as t}from"./utils/extractDictionaryKey.mjs";import{extractDictionaryInfo as n,getOutput as r,resolveContentFilePaths as i}from"./utils/extractDictionaryInfo.mjs";import{mergeWithExistingMultilingualDictionary as a,mergeWithExistingPerLocaleDictionary as o,writeContentHelper as s}from"./contentWriter.mjs";import{ATTRIBUTES_TO_EXTRACT as c,SERVER_CAPABLE_PACKAGES as l,packageList as u}from"./utils/constants.mjs";import{detectPackageName as d}from"./utils/detectPackageName.mjs";import{generateKey as f}from"./utils/generateKey.mjs";import{getComponentName as p}from"./utils/getComponentName.mjs";import{extractContent as m,extractContentSync as h}from"./extractContent.mjs";export{c as ATTRIBUTES_TO_EXTRACT,l as SERVER_CAPABLE_PACKAGES,d as detectPackageName,m as extractContent,h as extractContentSync,n as extractDictionaryInfo,e as extractDictionaryKey,t as extractDictionaryKeyFromPath,f as generateKey,p as getComponentName,r as getOutput,a as mergeWithExistingMultilingualDictionary,o as mergeWithExistingPerLocaleDictionary,u as packageList,i as resolveContentFilePaths,s as writeContentHelper};
@@ -1,6 +1,6 @@
1
- import{getExistingIntlayerInfo as e}from"./utils/getExistingIntlayerInfo.mjs";import{extractBabelContentForComponents as t}from"./babelProcessor.mjs";import{parse as n}from"@babel/parser";import{execSync as r}from"node:child_process";import{readFileSync as i,writeFileSync as a}from"node:fs";import o from"@babel/traverse";import*as s from"@babel/types";import{detectFormatCommand as c}from"@intlayer/chokidar/cli";const l=typeof o==`function`?o:o.default,u=(o,u,d,f,p=!0,m={},h)=>{let g=h??i(o,`utf-8`),_=n(g,{sourceType:`module`,plugins:[`jsx`,`typescript`]}),v=d===`solid-intlayer`,{extractedContent:y,replacements:b,componentsNeedingHooks:x,componentKeyMap:S,componentPaths:C,hookMap:w}=t(_,g,new Set,u,f,o,m);if(Object.keys(y).length===0)return null;let T=[],E=t=>{let n=t;for(;n;){let t=C.find(e=>e.node===n?.node);if(t){let n=e(t);if(n)return n.hook;if(x.has(t))return w.get(t.node)||`useIntlayer`}n=n.parentPath}return`useIntlayer`};for(let{path:e,key:t,type:n,variables:r,childrenToReplace:i}of b){let a=v?`content().${t}`:`content.${t}`,o=E(e)===`getIntlayer`?``:`.value`;if(n===`jsx-text`&&e.isJSXText())T.push({start:e.node.start,end:e.node.end,replacement:`{${a}}`});else if(n===`jsx-attribute`&&e.isJSXAttribute()){let t=e.node.value;t&&T.push({start:t.start,end:t.end,replacement:`{${a}${o}}`})}else if(n===`string-literal`&&e.isStringLiteral())T.push({start:e.node.start,end:e.node.end,replacement:`${a}${o}`});else if(n===`jsx-text-combined`&&i&&i.length>0){let e=`{${a}}`,t=i[0].start,n=i[i.length-1].end;T.push({start:t,end:n,replacement:e})}else if(n===`jsx-insertion`&&r&&i&&i.length>0){let e=`{${a}({ ${r.map(e=>{let[t,n]=e.split(`:`).map(e=>e.trim());return`${t}: ${n}`}).join(`, `)} })}`,t=i[0].start,n=i[i.length-1].end;T.push({start:t,end:n,replacement:e})}}let D=!1,O=!1;for(let t of x){let n=S.get(t.node),r=e(t);if(r)r.hook===`useIntlayer`&&(D=!0),r.hook===`getIntlayer`&&(O=!0);else{let e=w.get(t.node)||`useIntlayer`;e===`useIntlayer`&&(D=!0),e===`getIntlayer`&&(O=!0);let r=t.get(`body`),i=`\n const content = ${e}('${n}');\n`;if(r.isBlockStatement())T.push({start:r.node.start+1,end:r.node.start+1,replacement:i});else if(r.isExpression()){let t=r.node.start,i=r.node.end,a=-1,o=-1;for(let e=t-1;e>=0;e--){let t=g[e];if(t===`(`){a=e;break}if(t!==` `&&t!==`
2
- `&&t!==`\r`&&t!==` `)break}if(a!==-1)for(let e=i;e<g.length;e++){let t=g[e];if(t===`)`){o=e;break}if(t!==` `&&t!==`
3
- `&&t!==`\r`&&t!==` `)break}a!==-1&&o!==-1?(T.push({start:o,end:o+1,replacement:`)
4
- }`}),T.push({start:a,end:a+1,replacement:`{\n const content = ${e}('${n}');\n return (`})):(T.push({start:i,end:i,replacement:`
5
- }`}),T.push({start:t,end:t,replacement:`{\n const content = ${e}('${n}');\n return `}))}}}let k=(e,t)=>{let n;if(l(_,{ImportDeclaration(e){e.node.source.value===t&&(n=e,e.stop())}}),!n){let n=`import { ${e} } from '${t}';\n`,r=0;if(_.program.body.length>0)r=_.program.body[0].start;else if(_.program.directives&&_.program.directives.length>0){r=_.program.directives[_.program.directives.length-1].end,g[r]===`;`&&r++,T.push({start:r,end:r,replacement:`\n${n}`});return}(r===0||_.program.body.length>0&&r===_.program.body[0].start)&&T.push({start:r,end:r,replacement:n})}else if(!n.node.specifiers.some(t=>s.isImportSpecifier(t)&&s.isIdentifier(t.imported)&&t.imported.name===e)){let t=g.slice(n.node.start,n.node.end),r=t.lastIndexOf(`}`);if(r!==-1){let i=!t.slice(0,r).trim().endsWith(`,`),a=n.node.start+r,o=i?`, `:` `;T.push({start:a,end:a,replacement:`${o}${e} `})}}};D&&k(`useIntlayer`,d),O&&k(`getIntlayer`,`intlayer`),T.sort((e,t)=>t.start===e.start?t.end-e.end:t.start-e.start);let A=g;for(let e of T)A=A.slice(0,e.start)+e.replacement+A.slice(e.end);if(p){a(o,A);let e=c(f);if(e)try{r(e.replace(`{{file}}`,o),{stdio:`inherit`,cwd:f.content.baseDir})}catch(e){console.error(e)}}return{extractedContent:y,modifiedCode:A}};export{u as processTsxFile};
1
+ import{SERVER_CAPABLE_PACKAGES as e}from"./utils/constants.mjs";import{getExistingIntlayerInfo as t}from"./utils/getExistingIntlayerInfo.mjs";import{extractBabelContentForComponents as n}from"./babelProcessor.mjs";import{readFileSync as r,writeFileSync as i}from"node:fs";import{detectFormatCommand as a}from"@intlayer/chokidar/cli";import{parse as o}from"@babel/parser";import{execSync as s}from"node:child_process";import c from"@babel/traverse";import*as l from"@babel/types";const u=typeof c==`function`?c:c.default,d=(c,d,f,p,m=!0,h={},g)=>{let _=g??r(c,`utf-8`),v=o(_,{sourceType:`module`,plugins:[`jsx`,`typescript`]}),y=v.program.directives.some(e=>e.value.value===`use client`),b=e.has(f)&&!y?`${f}/server`:f,x=f===`solid-intlayer`,{extractedContent:S,replacements:C,componentsNeedingHooks:w,componentKeyMap:T,componentPaths:E,hookMap:D}=n(v,_,new Set,d,p,c,h);if(Object.keys(S).length===0)return null;let O=[],k=e=>{let n=e;for(;n;){let e=E.find(e=>e.node===n?.node);if(e){let n=t(e);if(n)return n.hook;if(w.has(e))return D.get(e.node)||`useIntlayer`}n=n.parentPath}return`useIntlayer`};for(let{path:e,key:t,type:n,variables:r,childrenToReplace:i}of C){let a=x?`content().${t}`:`content.${t}`,o=k(e)===`getIntlayer`?``:`.value`;if(n===`jsx-text`&&e.isJSXText())O.push({start:e.node.start,end:e.node.end,replacement:`{${a}}`});else if(n===`jsx-attribute`&&e.isJSXAttribute()){let t=e.node.value;t&&O.push({start:t.start,end:t.end,replacement:`{${a}${o}}`})}else if(n===`string-literal`&&e.isStringLiteral())O.push({start:e.node.start,end:e.node.end,replacement:`${a}${o}`});else if(n===`jsx-text-combined`&&i&&i.length>0){let e=`{${a}}`,t=i[0].start,n=i[i.length-1].end;O.push({start:t,end:n,replacement:e})}else if(n===`jsx-insertion`&&r&&i&&i.length>0){let e=`{${a}({ ${r.map(e=>{let[t,n]=e.split(`:`).map(e=>e.trim());return`${t}: ${n}`}).join(`, `)} })}`,t=i[0].start,n=i[i.length-1].end;O.push({start:t,end:n,replacement:e})}}let A=!1,j=!1;for(let e of w){let n=T.get(e.node),r=t(e);if(r)r.hook===`useIntlayer`&&(A=!0),r.hook===`getIntlayer`&&(j=!0);else{let t=D.get(e.node)||`useIntlayer`;t===`useIntlayer`&&(A=!0),t===`getIntlayer`&&(j=!0);let r=e.get(`body`),i=`\n const content = ${t}('${n}');\n`;if(r.isBlockStatement())O.push({start:r.node.start+1,end:r.node.start+1,replacement:i});else if(r.isExpression()){let e=r.node.start,i=r.node.end,a=-1,o=-1;for(let t=e-1;t>=0;t--){let e=_[t];if(e===`(`){a=t;break}if(e!==` `&&e!==`
2
+ `&&e!==`\r`&&e!==` `)break}if(a!==-1)for(let e=i;e<_.length;e++){let t=_[e];if(t===`)`){o=e;break}if(t!==` `&&t!==`
3
+ `&&t!==`\r`&&t!==` `)break}a!==-1&&o!==-1?(O.push({start:o,end:o+1,replacement:`)
4
+ }`}),O.push({start:a,end:a+1,replacement:`{\n const content = ${t}('${n}');\n return (`})):(O.push({start:i,end:i,replacement:`
5
+ }`}),O.push({start:e,end:e,replacement:`{\n const content = ${t}('${n}');\n return `}))}}}let M=(e,t)=>{let n;if(u(v,{ImportDeclaration(e){e.node.source.value===t&&(n=e,e.stop())}}),!n){let n=`import { ${e} } from '${t}';\n`,r=0;if(v.program.body.length>0)r=v.program.body[0].start;else if(v.program.directives&&v.program.directives.length>0){r=v.program.directives[v.program.directives.length-1].end,_[r]===`;`&&r++,O.push({start:r,end:r,replacement:`\n${n}`});return}(r===0||v.program.body.length>0&&r===v.program.body[0].start)&&O.push({start:r,end:r,replacement:n})}else if(!n.node.specifiers.some(t=>l.isImportSpecifier(t)&&l.isIdentifier(t.imported)&&t.imported.name===e)){let t=_.slice(n.node.start,n.node.end),r=t.lastIndexOf(`}`);if(r!==-1){let i=!t.slice(0,r).trim().endsWith(`,`),a=n.node.start+r,o=i?`, `:` `;O.push({start:a,end:a,replacement:`${o}${e} `})}}};A&&M(`useIntlayer`,b),j&&M(`getIntlayer`,`intlayer`),O.sort((e,t)=>t.start===e.start?t.end-e.end:t.start-e.start);let N=_;for(let e of O)N=N.slice(0,e.start)+e.replacement+N.slice(e.end);if(m){i(c,N);let e=a(p);if(e)try{s(e.replace(`{{file}}`,c),{stdio:`inherit`,cwd:p.system.baseDir})}catch(e){console.error(e)}}return{extractedContent:S,modifiedCode:N}};export{d as processTsxFile};
6
6
  //# sourceMappingURL=processTsxFile.mjs.map