gtx-cli 2.3.6-alpha.2 → 2.3.6

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 (192) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/api/checkFileTranslations.d.ts +23 -0
  3. package/dist/api/checkFileTranslations.js +236 -0
  4. package/dist/api/downloadFileBatch.d.ts +20 -0
  5. package/dist/api/downloadFileBatch.js +113 -0
  6. package/dist/api/sendFiles.d.ts +17 -0
  7. package/dist/api/sendFiles.js +115 -0
  8. package/dist/api/uploadFiles.d.ts +27 -0
  9. package/dist/api/uploadFiles.js +40 -0
  10. package/dist/cli/base.d.ts +32 -0
  11. package/dist/cli/base.js +335 -0
  12. package/dist/cli/commands/stage.d.ts +5 -0
  13. package/dist/cli/commands/stage.js +100 -0
  14. package/dist/cli/commands/translate.d.ts +6 -0
  15. package/dist/cli/commands/translate.js +63 -0
  16. package/dist/cli/flags.d.ts +3 -0
  17. package/dist/cli/flags.js +38 -0
  18. package/dist/cli/next.d.ts +11 -0
  19. package/dist/cli/next.js +20 -0
  20. package/dist/cli/react.d.ts +18 -0
  21. package/dist/cli/react.js +175 -0
  22. package/dist/config/generateSettings.d.ts +9 -0
  23. package/dist/config/generateSettings.js +176 -0
  24. package/dist/config/optionPresets.d.ts +2 -0
  25. package/dist/config/optionPresets.js +56 -0
  26. package/dist/config/resolveConfig.d.ts +4 -0
  27. package/dist/config/resolveConfig.js +19 -0
  28. package/dist/config/utils.d.ts +2 -0
  29. package/dist/config/utils.js +4 -0
  30. package/dist/config/validateSettings.d.ts +3 -0
  31. package/dist/config/validateSettings.js +32 -0
  32. package/dist/console/colors.d.ts +5 -0
  33. package/dist/console/colors.js +16 -0
  34. package/dist/console/index.d.ts +21 -0
  35. package/dist/console/index.js +24 -0
  36. package/dist/console/logging.d.ts +53 -0
  37. package/dist/console/logging.js +185 -0
  38. package/dist/formats/files/fileMapping.d.ts +11 -0
  39. package/dist/formats/files/fileMapping.js +82 -0
  40. package/dist/formats/files/save.d.ts +5 -0
  41. package/dist/formats/files/save.js +17 -0
  42. package/dist/formats/files/supportedFiles.d.ts +10 -0
  43. package/dist/formats/files/supportedFiles.js +18 -0
  44. package/dist/formats/files/translate.d.ts +4 -0
  45. package/dist/formats/files/translate.js +119 -0
  46. package/dist/formats/files/upload.d.ts +13 -0
  47. package/dist/formats/files/upload.js +136 -0
  48. package/dist/formats/gt/save.d.ts +9 -0
  49. package/dist/formats/gt/save.js +26 -0
  50. package/dist/formats/json/flattenJson.d.ts +14 -0
  51. package/dist/formats/json/flattenJson.js +64 -0
  52. package/dist/formats/json/mergeJson.d.ts +13 -0
  53. package/dist/formats/json/mergeJson.js +257 -0
  54. package/dist/formats/json/parseJson.d.ts +2 -0
  55. package/dist/formats/json/parseJson.js +108 -0
  56. package/dist/formats/json/utils.d.ts +47 -0
  57. package/dist/formats/json/utils.js +149 -0
  58. package/dist/formats/utils.d.ts +2 -0
  59. package/dist/formats/utils.js +24 -0
  60. package/dist/formats/yaml/mergeYaml.d.ts +5 -0
  61. package/dist/formats/yaml/mergeYaml.js +55 -0
  62. package/dist/formats/yaml/parseYaml.d.ts +5 -0
  63. package/dist/formats/yaml/parseYaml.js +23 -0
  64. package/dist/formats/yaml/utils.d.ts +2 -0
  65. package/dist/formats/yaml/utils.js +22 -0
  66. package/dist/fs/config/loadConfig.d.ts +1 -0
  67. package/dist/fs/config/loadConfig.js +9 -0
  68. package/dist/fs/config/parseFilesConfig.d.ts +27 -0
  69. package/dist/fs/config/parseFilesConfig.js +129 -0
  70. package/dist/fs/config/setupConfig.d.ts +17 -0
  71. package/dist/fs/config/setupConfig.js +50 -0
  72. package/dist/fs/config/updateConfig.d.ts +10 -0
  73. package/dist/fs/config/updateConfig.js +36 -0
  74. package/dist/fs/config/updateVersions.d.ts +10 -0
  75. package/dist/fs/config/updateVersions.js +30 -0
  76. package/dist/fs/copyFile.d.ts +7 -0
  77. package/dist/fs/copyFile.js +39 -0
  78. package/dist/fs/createLoadTranslationsFile.d.ts +1 -0
  79. package/dist/fs/createLoadTranslationsFile.js +36 -0
  80. package/dist/fs/determineFramework.d.ts +5 -0
  81. package/dist/fs/determineFramework.js +46 -0
  82. package/dist/fs/findFilepath.d.ts +36 -0
  83. package/dist/fs/findFilepath.js +89 -0
  84. package/dist/fs/getPackageResource.d.ts +1 -0
  85. package/dist/fs/getPackageResource.js +6 -0
  86. package/dist/fs/index.d.ts +1 -0
  87. package/dist/fs/index.js +1 -0
  88. package/dist/fs/loadJSON.d.ts +6 -0
  89. package/dist/fs/loadJSON.js +17 -0
  90. package/dist/fs/matchFiles.d.ts +1 -0
  91. package/dist/fs/matchFiles.js +8 -0
  92. package/dist/fs/saveJSON.d.ts +1 -0
  93. package/dist/fs/saveJSON.js +7 -0
  94. package/dist/fs/utils.d.ts +1 -0
  95. package/dist/fs/utils.js +16 -0
  96. package/dist/hooks/postProcess.d.ts +4 -0
  97. package/dist/hooks/postProcess.js +110 -0
  98. package/dist/index.d.ts +4 -0
  99. package/dist/index.js +20 -0
  100. package/dist/main.d.ts +2 -0
  101. package/dist/main.js +9 -0
  102. package/dist/next/config/parseNextConfig.d.ts +10 -0
  103. package/dist/next/config/parseNextConfig.js +53 -0
  104. package/dist/next/jsx/utils.d.ts +7 -0
  105. package/dist/next/jsx/utils.js +42 -0
  106. package/dist/next/parse/handleInitGT.d.ts +7 -0
  107. package/dist/next/parse/handleInitGT.js +208 -0
  108. package/dist/next/parse/wrapContent.d.ts +11 -0
  109. package/dist/next/parse/wrapContent.js +163 -0
  110. package/dist/react/config/createESBuildConfig.d.ts +2 -0
  111. package/dist/react/config/createESBuildConfig.js +119 -0
  112. package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.d.ts +8 -0
  113. package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +111 -0
  114. package/dist/react/jsx/evaluateJsx.d.ts +17 -0
  115. package/dist/react/jsx/evaluateJsx.js +85 -0
  116. package/dist/react/jsx/trimJsxStringChildren.d.ts +7 -0
  117. package/dist/react/jsx/trimJsxStringChildren.js +95 -0
  118. package/dist/react/jsx/utils/constants.d.ts +10 -0
  119. package/dist/react/jsx/utils/constants.js +31 -0
  120. package/dist/react/jsx/utils/parseAst.d.ts +30 -0
  121. package/dist/react/jsx/utils/parseAst.js +277 -0
  122. package/dist/react/jsx/utils/parseJsx.d.ts +21 -0
  123. package/dist/react/jsx/utils/parseJsx.js +244 -0
  124. package/dist/react/jsx/utils/parseStringFunction.d.ts +16 -0
  125. package/dist/react/jsx/utils/parseStringFunction.js +411 -0
  126. package/dist/react/jsx/utils/validateStringFunction.d.ts +7 -0
  127. package/dist/react/jsx/utils/validateStringFunction.js +31 -0
  128. package/dist/react/jsx/wrapJsx.d.ts +51 -0
  129. package/dist/react/jsx/wrapJsx.js +387 -0
  130. package/dist/react/parse/createDictionaryUpdates.d.ts +3 -0
  131. package/dist/react/parse/createDictionaryUpdates.js +169 -0
  132. package/dist/react/parse/createInlineUpdates.d.ts +6 -0
  133. package/dist/react/parse/createInlineUpdates.js +122 -0
  134. package/dist/react/parse/wrapContent.d.ts +11 -0
  135. package/dist/react/parse/wrapContent.js +162 -0
  136. package/dist/react/utils/flattenDictionary.d.ts +20 -0
  137. package/dist/react/utils/flattenDictionary.js +75 -0
  138. package/dist/react/utils/getEntryAndMetadata.d.ts +5 -0
  139. package/dist/react/utils/getEntryAndMetadata.js +11 -0
  140. package/dist/react/utils/getVariableName.d.ts +25 -0
  141. package/dist/react/utils/getVariableName.js +37 -0
  142. package/dist/setup/userInput.d.ts +4 -0
  143. package/dist/setup/userInput.js +29 -0
  144. package/dist/setup/wizard.d.ts +2 -0
  145. package/dist/setup/wizard.js +127 -0
  146. package/dist/translation/parse.d.ts +15 -0
  147. package/dist/translation/parse.js +76 -0
  148. package/dist/translation/stage.d.ts +2 -0
  149. package/dist/translation/stage.js +44 -0
  150. package/dist/translation/validate.d.ts +2 -0
  151. package/dist/translation/validate.js +50 -0
  152. package/dist/types/data/json.d.ts +6 -0
  153. package/dist/types/data/json.js +1 -0
  154. package/dist/types/data.d.ts +30 -0
  155. package/dist/types/data.js +1 -0
  156. package/dist/types/files.d.ts +1 -0
  157. package/dist/types/files.js +1 -0
  158. package/dist/types/index.d.ts +173 -0
  159. package/dist/types/index.js +1 -0
  160. package/dist/utils/addExplicitAnchorIds.d.ts +24 -0
  161. package/dist/utils/addExplicitAnchorIds.js +260 -0
  162. package/dist/utils/constants.d.ts +2 -0
  163. package/dist/utils/constants.js +2 -0
  164. package/dist/utils/credentials.d.ts +12 -0
  165. package/dist/utils/credentials.js +119 -0
  166. package/dist/utils/flattenJsonFiles.d.ts +2 -0
  167. package/dist/utils/flattenJsonFiles.js +36 -0
  168. package/dist/utils/gt.d.ts +2 -0
  169. package/dist/utils/gt.js +2 -0
  170. package/dist/utils/hash.d.ts +6 -0
  171. package/dist/utils/hash.js +11 -0
  172. package/dist/utils/headers.d.ts +1 -0
  173. package/dist/utils/headers.js +14 -0
  174. package/dist/utils/installPackage.d.ts +3 -0
  175. package/dist/utils/installPackage.js +77 -0
  176. package/dist/utils/localizeStaticImports.d.ts +15 -0
  177. package/dist/utils/localizeStaticImports.js +341 -0
  178. package/dist/utils/localizeStaticUrls.d.ts +19 -0
  179. package/dist/utils/localizeStaticUrls.js +432 -0
  180. package/dist/utils/packageInfo.d.ts +3 -0
  181. package/dist/utils/packageInfo.js +17 -0
  182. package/dist/utils/packageJson.d.ts +6 -0
  183. package/dist/utils/packageJson.js +76 -0
  184. package/dist/utils/packageManager.d.ts +28 -0
  185. package/dist/utils/packageManager.js +269 -0
  186. package/dist/utils/processAnchorIds.d.ts +6 -0
  187. package/dist/utils/processAnchorIds.js +47 -0
  188. package/dist/utils/sanitizeFileContent.d.ts +6 -0
  189. package/dist/utils/sanitizeFileContent.js +29 -0
  190. package/dist/utils/validateMdx.d.ts +10 -0
  191. package/dist/utils/validateMdx.js +25 -0
  192. package/package.json +3 -3
@@ -0,0 +1,341 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { createFileMapping } from '../formats/files/fileMapping.js';
4
+ import micromatch from 'micromatch';
5
+ import { unified } from 'unified';
6
+ import remarkParse from 'remark-parse';
7
+ import remarkMdx from 'remark-mdx';
8
+ import remarkFrontmatter from 'remark-frontmatter';
9
+ import { visit } from 'unist-util-visit';
10
+ const { isMatch } = micromatch;
11
+ /**
12
+ * Localizes static imports in content files.
13
+ * Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
14
+ * @param settings - The settings object containing the project configuration.
15
+ * @returns void
16
+ *
17
+ * @TODO This is an experimental feature, and only works in very specific cases. This needs to be improved before
18
+ * it can be enabled by default.
19
+ *
20
+ * Before this becomes a non-experimental feature, we need to:
21
+ * - Support more file types
22
+ * - Support more complex paths
23
+ */
24
+ export default async function localizeStaticImports(settings) {
25
+ if (!settings.files ||
26
+ (Object.keys(settings.files.placeholderPaths).length === 1 &&
27
+ settings.files.placeholderPaths.gt)) {
28
+ return;
29
+ }
30
+ const { resolvedPaths: sourceFiles } = settings.files;
31
+ const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths, settings.locales, settings.defaultLocale);
32
+ // Process all file types at once with a single call
33
+ const processPromises = [];
34
+ // First, process default locale files (from source files)
35
+ // This is needed because they might not be in the fileMapping if they're not being translated
36
+ if (!fileMapping[settings.defaultLocale]) {
37
+ const defaultLocaleFiles = [];
38
+ // Collect all .md and .mdx files from sourceFiles
39
+ if (sourceFiles.md) {
40
+ defaultLocaleFiles.push(...sourceFiles.md);
41
+ }
42
+ if (sourceFiles.mdx) {
43
+ defaultLocaleFiles.push(...sourceFiles.mdx);
44
+ }
45
+ if (defaultLocaleFiles.length > 0) {
46
+ const defaultPromise = Promise.all(defaultLocaleFiles.map(async (filePath) => {
47
+ // Check if file exists before processing
48
+ if (!fs.existsSync(filePath)) {
49
+ return;
50
+ }
51
+ // Get file content
52
+ const fileContent = await fs.promises.readFile(filePath, 'utf8');
53
+ // Localize the file using default locale
54
+ const localizedFile = localizeStaticImportsForFile(fileContent, settings.defaultLocale, settings.defaultLocale, // Process as default locale
55
+ settings.options?.docsHideDefaultLocaleImport || false, settings.options?.docsImportPattern, settings.options?.excludeStaticImports, filePath);
56
+ // Write the localized file back to the same path
57
+ await fs.promises.writeFile(filePath, localizedFile);
58
+ }));
59
+ processPromises.push(defaultPromise);
60
+ }
61
+ }
62
+ // Then process all other locales from fileMapping
63
+ const mappingPromises = Object.entries(fileMapping).map(async ([locale, filesMap]) => {
64
+ // Get all files that are md or mdx
65
+ const targetFiles = Object.values(filesMap).filter((path) => path.endsWith('.md') || path.endsWith('.mdx'));
66
+ // Replace the placeholder path with the target path
67
+ await Promise.all(targetFiles.map(async (filePath) => {
68
+ // Check if file exists before processing
69
+ if (!fs.existsSync(filePath)) {
70
+ return;
71
+ }
72
+ // Get file content
73
+ const fileContent = await fs.promises.readFile(filePath, 'utf8');
74
+ // Localize the file
75
+ const localizedFile = localizeStaticImportsForFile(fileContent, settings.defaultLocale, locale, settings.options?.docsHideDefaultLocaleImport || false, settings.options?.docsImportPattern, settings.options?.excludeStaticImports, filePath);
76
+ // Write the localized file to the target path
77
+ await fs.promises.writeFile(filePath, localizedFile);
78
+ }));
79
+ });
80
+ processPromises.push(...mappingPromises);
81
+ await Promise.all(processPromises);
82
+ }
83
+ /**
84
+ * Determines if an import path should be processed based on pattern matching
85
+ */
86
+ function shouldProcessImportPath(importPath, patternHead, targetLocale, defaultLocale) {
87
+ const patternWithoutSlash = patternHead.replace(/\/$/, '');
88
+ if (targetLocale === defaultLocale) {
89
+ // For default locale processing, check if path contains the pattern
90
+ return importPath.includes(patternWithoutSlash);
91
+ }
92
+ else {
93
+ // For non-default locales, check if path starts with pattern
94
+ return importPath.includes(patternWithoutSlash);
95
+ }
96
+ }
97
+ /**
98
+ * Checks if an import path should be excluded based on exclusion patterns
99
+ */
100
+ function isImportPathExcluded(importPath, exclude, defaultLocale) {
101
+ const excludePatterns = exclude.map((p) => p.replace(/\[locale\]/g, defaultLocale));
102
+ return excludePatterns.some((pattern) => isMatch(importPath, pattern));
103
+ }
104
+ /**
105
+ * Transforms import path for default locale processing
106
+ */
107
+ function transformDefaultLocaleImportPath(fullPath, patternHead, defaultLocale, hideDefaultLocale) {
108
+ if (hideDefaultLocale) {
109
+ // Remove locale from imports that have it: '/snippets/en/file.mdx' -> '/snippets/file.mdx'
110
+ if (fullPath.includes(`/${defaultLocale}/`)) {
111
+ return fullPath.replace(`/${defaultLocale}/`, '/');
112
+ }
113
+ else if (fullPath.endsWith(`/${defaultLocale}`)) {
114
+ return fullPath.replace(`/${defaultLocale}`, '');
115
+ }
116
+ return null; // Path doesn't have default locale
117
+ }
118
+ else {
119
+ // Add locale to imports that don't have it: '/snippets/file.mdx' -> '/snippets/en/file.mdx'
120
+ if (fullPath.includes(`/${defaultLocale}/`) ||
121
+ fullPath.endsWith(`/${defaultLocale}`)) {
122
+ return null; // Already has default locale
123
+ }
124
+ if (fullPath.startsWith(patternHead)) {
125
+ const pathAfterHead = fullPath.slice(patternHead.length);
126
+ if (pathAfterHead) {
127
+ return `${patternHead}${defaultLocale}/${pathAfterHead}`;
128
+ }
129
+ else {
130
+ return `${patternHead.replace(/\/$/, '')}/${defaultLocale}`;
131
+ }
132
+ }
133
+ return null; // Path doesn't match pattern
134
+ }
135
+ }
136
+ /**
137
+ * Transforms import path for non-default locale processing with hideDefaultLocale=true
138
+ */
139
+ function transformNonDefaultLocaleImportPathWithHidden(fullPath, patternHead, targetLocale, defaultLocale) {
140
+ // Check if already localized
141
+ if (fullPath.startsWith(`${patternHead}${targetLocale}/`) ||
142
+ fullPath === `${patternHead}${targetLocale}`) {
143
+ return null;
144
+ }
145
+ // Replace default locale with target locale
146
+ const expectedPathWithDefaultLocale = `${patternHead}${defaultLocale}`;
147
+ if (fullPath.startsWith(`${expectedPathWithDefaultLocale}/`) ||
148
+ fullPath === expectedPathWithDefaultLocale) {
149
+ return fullPath.replace(`${patternHead}${defaultLocale}`, `${patternHead}${targetLocale}`);
150
+ }
151
+ // Handle exact pattern match
152
+ if (fullPath === patternHead.replace(/\/$/, '')) {
153
+ return `${patternHead.replace(/\/$/, '')}/${targetLocale}`;
154
+ }
155
+ // Add target locale to path without any locale
156
+ const pathAfterHead = fullPath.slice(patternHead.length);
157
+ return pathAfterHead
158
+ ? `${patternHead}${targetLocale}/${pathAfterHead}`
159
+ : `${patternHead}${targetLocale}`;
160
+ }
161
+ /**
162
+ * Transforms import path for non-default locale processing with hideDefaultLocale=false
163
+ */
164
+ function transformNonDefaultLocaleImportPath(fullPath, patternHead, targetLocale, defaultLocale) {
165
+ const expectedPathWithLocale = `${patternHead}${defaultLocale}`;
166
+ if (fullPath.startsWith(`${expectedPathWithLocale}/`) ||
167
+ fullPath === expectedPathWithLocale) {
168
+ // Replace existing default locale with target locale
169
+ return fullPath.replace(`${patternHead}${defaultLocale}`, `${patternHead}${targetLocale}`);
170
+ }
171
+ else if (fullPath.startsWith(patternHead)) {
172
+ // Add target locale to path that doesn't have any locale
173
+ const pathAfterHead = fullPath.slice(patternHead.length);
174
+ if (pathAfterHead) {
175
+ return `${patternHead}${targetLocale}/${pathAfterHead}`;
176
+ }
177
+ else {
178
+ return `${patternHead.replace(/\/$/, '')}/${targetLocale}`;
179
+ }
180
+ }
181
+ return null; // Path doesn't match pattern
182
+ }
183
+ /**
184
+ * Main import path transformation function that delegates to specific scenarios
185
+ */
186
+ function transformImportPath(fullPath, patternHead, targetLocale, defaultLocale, hideDefaultLocale, currentFilePath, projectRoot = process.cwd() // fallback if not provided
187
+ ) {
188
+ let newPath;
189
+ if (targetLocale === defaultLocale) {
190
+ newPath = transformDefaultLocaleImportPath(fullPath, patternHead, defaultLocale, hideDefaultLocale);
191
+ }
192
+ else if (hideDefaultLocale) {
193
+ newPath = transformNonDefaultLocaleImportPathWithHidden(fullPath, patternHead, targetLocale, defaultLocale);
194
+ }
195
+ else {
196
+ newPath = transformNonDefaultLocaleImportPath(fullPath, patternHead, targetLocale, defaultLocale);
197
+ }
198
+ if (!newPath)
199
+ return null;
200
+ if (currentFilePath) {
201
+ let resolvedPath;
202
+ if (newPath.startsWith('/')) {
203
+ // Interpret as project-root relative
204
+ resolvedPath = path.join(projectRoot, newPath.replace(/^\//, ''));
205
+ }
206
+ else {
207
+ // Relative to current file
208
+ const currentDir = path.dirname(currentFilePath);
209
+ resolvedPath = path.resolve(currentDir, newPath);
210
+ }
211
+ if (!fs.existsSync(resolvedPath)) {
212
+ return null;
213
+ }
214
+ }
215
+ return newPath;
216
+ }
217
+ /**
218
+ * AST-based transformation for MDX files using remark-mdx
219
+ */
220
+ function transformMdxImports(mdxContent, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', exclude = [], currentFilePath) {
221
+ const transformedImports = [];
222
+ // Don't auto-prefix relative patterns that start with . or ..
223
+ if (!pattern.startsWith('/') && !pattern.startsWith('.')) {
224
+ pattern = '/' + pattern;
225
+ }
226
+ const patternHead = pattern.split('[locale]')[0];
227
+ // Quick check: if the file doesn't contain the pattern, skip expensive AST parsing
228
+ // For default locale processing, we also need to check if content might need adjustment
229
+ if (targetLocale === defaultLocale) {
230
+ // For default locale files, we always need to check as we're looking for either:
231
+ // - paths without locale (when hideDefaultLocale=false)
232
+ // - paths with default locale (when hideDefaultLocale=true)
233
+ const patternWithoutSlash = patternHead.replace(/\/$/, '');
234
+ if (!mdxContent.includes(patternWithoutSlash)) {
235
+ return {
236
+ content: mdxContent,
237
+ hasChanges: false,
238
+ transformedImports: [],
239
+ };
240
+ }
241
+ }
242
+ else {
243
+ // For non-default locales, use the original logic
244
+ if (!mdxContent.includes(patternHead.replace(/\/$/, ''))) {
245
+ return {
246
+ content: mdxContent,
247
+ hasChanges: false,
248
+ transformedImports: [],
249
+ };
250
+ }
251
+ }
252
+ // Parse the MDX content into an AST
253
+ let processedAst;
254
+ try {
255
+ const parseProcessor = unified()
256
+ .use(remarkParse)
257
+ .use(remarkFrontmatter, ['yaml', 'toml'])
258
+ .use(remarkMdx);
259
+ const ast = parseProcessor.parse(mdxContent);
260
+ processedAst = parseProcessor.runSync(ast);
261
+ }
262
+ catch (error) {
263
+ console.warn(`Failed to parse MDX content: ${error instanceof Error ? error.message : String(error)}`);
264
+ console.warn('Returning original content unchanged due to parsing error.');
265
+ return {
266
+ content: mdxContent,
267
+ hasChanges: false,
268
+ transformedImports: [],
269
+ };
270
+ }
271
+ let content = mdxContent;
272
+ // Visit only mdxjsEsm nodes (import/export statements) to collect replacements
273
+ visit(processedAst, 'mdxjsEsm', (node) => {
274
+ if (node.value && node.value.includes(patternHead.replace(/\/$/, ''))) {
275
+ // Find import lines that need transformation
276
+ const lines = node.value.split('\n');
277
+ lines.forEach((line) => {
278
+ // Only process import lines that match our pattern
279
+ if (!line.trim().startsWith('import ')) {
280
+ return;
281
+ }
282
+ // Check if this line should be processed
283
+ if (!shouldProcessImportPath(line, patternHead, targetLocale, defaultLocale)) {
284
+ return;
285
+ }
286
+ // Extract the path from the import statement
287
+ const quotes = ['"', "'", '`'];
288
+ for (const quote of quotes) {
289
+ // Try both with and without trailing slash
290
+ let startPattern = `${quote}${patternHead}`;
291
+ let startIndex = line.indexOf(startPattern);
292
+ // If pattern has trailing slash but path doesn't, try without slash
293
+ if (startIndex === -1 && patternHead.endsWith('/')) {
294
+ const patternWithoutSlash = patternHead.slice(0, -1);
295
+ startPattern = `${quote}${patternWithoutSlash}`;
296
+ startIndex = line.indexOf(startPattern);
297
+ }
298
+ if (startIndex === -1)
299
+ continue;
300
+ const pathStart = startIndex + 1; // After the quote
301
+ const pathEnd = line.indexOf(quote, pathStart);
302
+ if (pathEnd === -1)
303
+ continue;
304
+ const fullPath = line.slice(pathStart, pathEnd);
305
+ // Transform the import path
306
+ const newPath = transformImportPath(fullPath, patternHead, targetLocale, defaultLocale, hideDefaultLocale, currentFilePath);
307
+ if (!newPath) {
308
+ continue; // No transformation needed
309
+ }
310
+ // Check exclusions
311
+ if (isImportPathExcluded(fullPath, exclude, defaultLocale)) {
312
+ continue;
313
+ }
314
+ // Apply the transformation to the original content
315
+ // Simply replace the import path with the new path
316
+ content = content.replace(`${quote}${fullPath}${quote}`, `${quote}${newPath}${quote}`);
317
+ transformedImports.push({ originalPath: fullPath, newPath });
318
+ break;
319
+ }
320
+ });
321
+ }
322
+ });
323
+ return {
324
+ content,
325
+ hasChanges: transformedImports.length > 0,
326
+ transformedImports,
327
+ };
328
+ }
329
+ /**
330
+ * AST-based transformation for MDX files only
331
+ */
332
+ function localizeStaticImportsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
333
+ exclude = [], currentFilePath) {
334
+ // Skip .md files entirely - they cannot have imports
335
+ if (currentFilePath && currentFilePath.endsWith('.md')) {
336
+ return file;
337
+ }
338
+ // For MDX files, use AST-based transformation
339
+ const result = transformMdxImports(file, defaultLocale, targetLocale, hideDefaultLocale, pattern, exclude, currentFilePath);
340
+ return result.content;
341
+ }
@@ -0,0 +1,19 @@
1
+ import { Settings } from '../types/index.js';
2
+ /**
3
+ * Localizes static urls in content files.
4
+ * Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
5
+ * @param settings - The settings object containing the project configuration.
6
+ * @returns void
7
+ *
8
+ * @TODO This is an experimental feature, and only works in very specific cases. This needs to be improved before
9
+ * it can be enabled by default.
10
+ *
11
+ * Before this becomes a non-experimental feature, we need to:
12
+ * - Support more file types
13
+ * - Support more complex paths
14
+ */
15
+ export default function localizeStaticUrls(settings: Settings, targetLocales?: string[]): Promise<void>;
16
+ /**
17
+ * Main URL transformation function that delegates to specific scenarios
18
+ */
19
+ export declare function transformUrlPath(originalUrl: string, patternHead: string, targetLocale: string, defaultLocale: string, hideDefaultLocale: boolean): string | null;