gtx-cli 2.3.4 → 2.3.6-alpha.1
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.
- package/CHANGELOG.md +6 -0
- package/package.json +23 -18
- package/dist/api/checkFileTranslations.d.ts +0 -23
- package/dist/api/checkFileTranslations.js +0 -236
- package/dist/api/downloadFileBatch.d.ts +0 -20
- package/dist/api/downloadFileBatch.js +0 -113
- package/dist/api/sendFiles.d.ts +0 -17
- package/dist/api/sendFiles.js +0 -115
- package/dist/api/uploadFiles.d.ts +0 -27
- package/dist/api/uploadFiles.js +0 -40
- package/dist/cli/base.d.ts +0 -32
- package/dist/cli/base.js +0 -335
- package/dist/cli/commands/stage.d.ts +0 -5
- package/dist/cli/commands/stage.js +0 -100
- package/dist/cli/commands/translate.d.ts +0 -6
- package/dist/cli/commands/translate.js +0 -63
- package/dist/cli/flags.d.ts +0 -3
- package/dist/cli/flags.js +0 -38
- package/dist/cli/next.d.ts +0 -11
- package/dist/cli/next.js +0 -20
- package/dist/cli/react.d.ts +0 -18
- package/dist/cli/react.js +0 -175
- package/dist/config/generateSettings.d.ts +0 -9
- package/dist/config/generateSettings.js +0 -171
- package/dist/config/optionPresets.d.ts +0 -2
- package/dist/config/optionPresets.js +0 -56
- package/dist/config/resolveConfig.d.ts +0 -4
- package/dist/config/resolveConfig.js +0 -19
- package/dist/config/utils.d.ts +0 -2
- package/dist/config/utils.js +0 -4
- package/dist/config/validateSettings.d.ts +0 -3
- package/dist/config/validateSettings.js +0 -32
- package/dist/console/colors.d.ts +0 -5
- package/dist/console/colors.js +0 -16
- package/dist/console/index.d.ts +0 -21
- package/dist/console/index.js +0 -24
- package/dist/console/logging.d.ts +0 -53
- package/dist/console/logging.js +0 -185
- package/dist/formats/files/fileMapping.d.ts +0 -11
- package/dist/formats/files/fileMapping.js +0 -82
- package/dist/formats/files/save.d.ts +0 -5
- package/dist/formats/files/save.js +0 -17
- package/dist/formats/files/supportedFiles.d.ts +0 -10
- package/dist/formats/files/supportedFiles.js +0 -18
- package/dist/formats/files/translate.d.ts +0 -4
- package/dist/formats/files/translate.js +0 -119
- package/dist/formats/files/upload.d.ts +0 -13
- package/dist/formats/files/upload.js +0 -136
- package/dist/formats/gt/save.d.ts +0 -9
- package/dist/formats/gt/save.js +0 -26
- package/dist/formats/json/flattenJson.d.ts +0 -14
- package/dist/formats/json/flattenJson.js +0 -64
- package/dist/formats/json/mergeJson.d.ts +0 -13
- package/dist/formats/json/mergeJson.js +0 -257
- package/dist/formats/json/parseJson.d.ts +0 -2
- package/dist/formats/json/parseJson.js +0 -108
- package/dist/formats/json/utils.d.ts +0 -47
- package/dist/formats/json/utils.js +0 -149
- package/dist/formats/utils.d.ts +0 -2
- package/dist/formats/utils.js +0 -24
- package/dist/formats/yaml/mergeYaml.d.ts +0 -5
- package/dist/formats/yaml/mergeYaml.js +0 -55
- package/dist/formats/yaml/parseYaml.d.ts +0 -5
- package/dist/formats/yaml/parseYaml.js +0 -23
- package/dist/formats/yaml/utils.d.ts +0 -2
- package/dist/formats/yaml/utils.js +0 -22
- package/dist/fs/config/loadConfig.d.ts +0 -1
- package/dist/fs/config/loadConfig.js +0 -9
- package/dist/fs/config/parseFilesConfig.d.ts +0 -27
- package/dist/fs/config/parseFilesConfig.js +0 -126
- package/dist/fs/config/setupConfig.d.ts +0 -17
- package/dist/fs/config/setupConfig.js +0 -50
- package/dist/fs/config/updateConfig.d.ts +0 -10
- package/dist/fs/config/updateConfig.js +0 -36
- package/dist/fs/config/updateVersions.d.ts +0 -10
- package/dist/fs/config/updateVersions.js +0 -30
- package/dist/fs/copyFile.d.ts +0 -7
- package/dist/fs/copyFile.js +0 -39
- package/dist/fs/createLoadTranslationsFile.d.ts +0 -1
- package/dist/fs/createLoadTranslationsFile.js +0 -36
- package/dist/fs/determineFramework.d.ts +0 -5
- package/dist/fs/determineFramework.js +0 -46
- package/dist/fs/findFilepath.d.ts +0 -36
- package/dist/fs/findFilepath.js +0 -89
- package/dist/fs/getPackageResource.d.ts +0 -1
- package/dist/fs/getPackageResource.js +0 -6
- package/dist/fs/index.d.ts +0 -1
- package/dist/fs/index.js +0 -1
- package/dist/fs/loadJSON.d.ts +0 -6
- package/dist/fs/loadJSON.js +0 -17
- package/dist/fs/matchFiles.d.ts +0 -1
- package/dist/fs/matchFiles.js +0 -8
- package/dist/fs/saveJSON.d.ts +0 -1
- package/dist/fs/saveJSON.js +0 -7
- package/dist/fs/utils.d.ts +0 -1
- package/dist/fs/utils.js +0 -16
- package/dist/hooks/postProcess.d.ts +0 -4
- package/dist/hooks/postProcess.js +0 -110
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -20
- package/dist/main.d.ts +0 -2
- package/dist/main.js +0 -9
- package/dist/next/config/parseNextConfig.d.ts +0 -10
- package/dist/next/config/parseNextConfig.js +0 -53
- package/dist/next/jsx/utils.d.ts +0 -7
- package/dist/next/jsx/utils.js +0 -42
- package/dist/next/parse/handleInitGT.d.ts +0 -7
- package/dist/next/parse/handleInitGT.js +0 -208
- package/dist/next/parse/wrapContent.d.ts +0 -11
- package/dist/next/parse/wrapContent.js +0 -163
- package/dist/react/config/createESBuildConfig.d.ts +0 -2
- package/dist/react/config/createESBuildConfig.js +0 -119
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.d.ts +0 -8
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +0 -111
- package/dist/react/jsx/evaluateJsx.d.ts +0 -17
- package/dist/react/jsx/evaluateJsx.js +0 -85
- package/dist/react/jsx/trimJsxStringChildren.d.ts +0 -7
- package/dist/react/jsx/trimJsxStringChildren.js +0 -95
- package/dist/react/jsx/utils/constants.d.ts +0 -10
- package/dist/react/jsx/utils/constants.js +0 -31
- package/dist/react/jsx/utils/parseAst.d.ts +0 -30
- package/dist/react/jsx/utils/parseAst.js +0 -277
- package/dist/react/jsx/utils/parseJsx.d.ts +0 -21
- package/dist/react/jsx/utils/parseJsx.js +0 -244
- package/dist/react/jsx/utils/parseStringFunction.d.ts +0 -16
- package/dist/react/jsx/utils/parseStringFunction.js +0 -411
- package/dist/react/jsx/utils/validateStringFunction.d.ts +0 -7
- package/dist/react/jsx/utils/validateStringFunction.js +0 -31
- package/dist/react/jsx/wrapJsx.d.ts +0 -51
- package/dist/react/jsx/wrapJsx.js +0 -387
- package/dist/react/parse/createDictionaryUpdates.d.ts +0 -3
- package/dist/react/parse/createDictionaryUpdates.js +0 -169
- package/dist/react/parse/createInlineUpdates.d.ts +0 -6
- package/dist/react/parse/createInlineUpdates.js +0 -122
- package/dist/react/parse/wrapContent.d.ts +0 -11
- package/dist/react/parse/wrapContent.js +0 -162
- package/dist/react/utils/flattenDictionary.d.ts +0 -20
- package/dist/react/utils/flattenDictionary.js +0 -75
- package/dist/react/utils/getEntryAndMetadata.d.ts +0 -5
- package/dist/react/utils/getEntryAndMetadata.js +0 -11
- package/dist/react/utils/getVariableName.d.ts +0 -25
- package/dist/react/utils/getVariableName.js +0 -37
- package/dist/setup/userInput.d.ts +0 -4
- package/dist/setup/userInput.js +0 -29
- package/dist/setup/wizard.d.ts +0 -2
- package/dist/setup/wizard.js +0 -127
- package/dist/translation/parse.d.ts +0 -15
- package/dist/translation/parse.js +0 -76
- package/dist/translation/stage.d.ts +0 -2
- package/dist/translation/stage.js +0 -44
- package/dist/translation/validate.d.ts +0 -2
- package/dist/translation/validate.js +0 -50
- package/dist/types/data/json.d.ts +0 -6
- package/dist/types/data/json.js +0 -1
- package/dist/types/data.d.ts +0 -30
- package/dist/types/data.js +0 -1
- package/dist/types/files.d.ts +0 -1
- package/dist/types/files.js +0 -1
- package/dist/types/index.d.ts +0 -173
- package/dist/types/index.js +0 -1
- package/dist/utils/addExplicitAnchorIds.d.ts +0 -24
- package/dist/utils/addExplicitAnchorIds.js +0 -260
- package/dist/utils/constants.d.ts +0 -2
- package/dist/utils/constants.js +0 -2
- package/dist/utils/credentials.d.ts +0 -12
- package/dist/utils/credentials.js +0 -119
- package/dist/utils/flattenJsonFiles.d.ts +0 -2
- package/dist/utils/flattenJsonFiles.js +0 -36
- package/dist/utils/gt.d.ts +0 -2
- package/dist/utils/gt.js +0 -2
- package/dist/utils/hash.d.ts +0 -6
- package/dist/utils/hash.js +0 -11
- package/dist/utils/headers.d.ts +0 -1
- package/dist/utils/headers.js +0 -14
- package/dist/utils/installPackage.d.ts +0 -3
- package/dist/utils/installPackage.js +0 -77
- package/dist/utils/localizeStaticImports.d.ts +0 -15
- package/dist/utils/localizeStaticImports.js +0 -341
- package/dist/utils/localizeStaticUrls.d.ts +0 -19
- package/dist/utils/localizeStaticUrls.js +0 -432
- package/dist/utils/packageInfo.d.ts +0 -3
- package/dist/utils/packageInfo.js +0 -17
- package/dist/utils/packageJson.d.ts +0 -6
- package/dist/utils/packageJson.js +0 -76
- package/dist/utils/packageManager.d.ts +0 -28
- package/dist/utils/packageManager.js +0 -269
- package/dist/utils/processAnchorIds.d.ts +0 -6
- package/dist/utils/processAnchorIds.js +0 -47
- package/dist/utils/sanitizeFileContent.d.ts +0 -6
- package/dist/utils/sanitizeFileContent.js +0 -29
- package/dist/utils/validateMdx.d.ts +0 -10
- package/dist/utils/validateMdx.js +0 -25
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import { createFileMapping } from '../formats/files/fileMapping.js';
|
|
3
|
-
import micromatch from 'micromatch';
|
|
4
|
-
import { unified } from 'unified';
|
|
5
|
-
import remarkParse from 'remark-parse';
|
|
6
|
-
import remarkMdx from 'remark-mdx';
|
|
7
|
-
import remarkFrontmatter from 'remark-frontmatter';
|
|
8
|
-
import remarkStringify from 'remark-stringify';
|
|
9
|
-
import { visit } from 'unist-util-visit';
|
|
10
|
-
import escapeHtmlInTextNodes from 'gt-remark';
|
|
11
|
-
const { isMatch } = micromatch;
|
|
12
|
-
/**
|
|
13
|
-
* Localizes static urls in content files.
|
|
14
|
-
* Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
|
|
15
|
-
* @param settings - The settings object containing the project configuration.
|
|
16
|
-
* @returns void
|
|
17
|
-
*
|
|
18
|
-
* @TODO This is an experimental feature, and only works in very specific cases. This needs to be improved before
|
|
19
|
-
* it can be enabled by default.
|
|
20
|
-
*
|
|
21
|
-
* Before this becomes a non-experimental feature, we need to:
|
|
22
|
-
* - Support more file types
|
|
23
|
-
* - Support more complex paths
|
|
24
|
-
*/
|
|
25
|
-
export default async function localizeStaticUrls(settings, targetLocales) {
|
|
26
|
-
if (!settings.files ||
|
|
27
|
-
(Object.keys(settings.files.placeholderPaths).length === 1 &&
|
|
28
|
-
settings.files.placeholderPaths.gt)) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const { resolvedPaths: sourceFiles } = settings.files;
|
|
32
|
-
// Use filtered locales if provided, otherwise use all locales
|
|
33
|
-
const locales = targetLocales || settings.locales;
|
|
34
|
-
const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths, settings.locales, // Always use all locales for mapping, filter later
|
|
35
|
-
settings.defaultLocale);
|
|
36
|
-
// Process all file types at once with a single call
|
|
37
|
-
const processPromises = [];
|
|
38
|
-
// First, process default locale files (from source files)
|
|
39
|
-
// This is needed because they might not be in the fileMapping if they're not being translated
|
|
40
|
-
// Only process default locale if it's in the target locales filter
|
|
41
|
-
if (!fileMapping[settings.defaultLocale] &&
|
|
42
|
-
locales.includes(settings.defaultLocale)) {
|
|
43
|
-
const defaultLocaleFiles = [];
|
|
44
|
-
// Collect all .md and .mdx files from sourceFiles
|
|
45
|
-
if (sourceFiles.md) {
|
|
46
|
-
defaultLocaleFiles.push(...sourceFiles.md);
|
|
47
|
-
}
|
|
48
|
-
if (sourceFiles.mdx) {
|
|
49
|
-
defaultLocaleFiles.push(...sourceFiles.mdx);
|
|
50
|
-
}
|
|
51
|
-
if (defaultLocaleFiles.length > 0) {
|
|
52
|
-
const defaultPromise = Promise.all(defaultLocaleFiles.map(async (filePath) => {
|
|
53
|
-
// Check if file exists before processing
|
|
54
|
-
if (!fs.existsSync(filePath)) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
// Get file content
|
|
58
|
-
const fileContent = await fs.promises.readFile(filePath, 'utf8');
|
|
59
|
-
// Localize the file using default locale
|
|
60
|
-
const result = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, settings.defaultLocale, // Process as default locale
|
|
61
|
-
settings.options?.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.excludeStaticUrls, settings.options?.baseDomain);
|
|
62
|
-
// Only write the file if there were changes
|
|
63
|
-
if (result.hasChanges) {
|
|
64
|
-
await fs.promises.writeFile(filePath, result.content);
|
|
65
|
-
}
|
|
66
|
-
}));
|
|
67
|
-
processPromises.push(defaultPromise);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
// Then process all other locales from fileMapping
|
|
71
|
-
const mappingPromises = Object.entries(fileMapping)
|
|
72
|
-
.filter(([locale, filesMap]) => locales.includes(locale)) // Filter by target locales
|
|
73
|
-
.map(async ([locale, filesMap]) => {
|
|
74
|
-
// Get all files that are md or mdx
|
|
75
|
-
const targetFiles = Object.values(filesMap).filter((path) => path.endsWith('.md') || path.endsWith('.mdx'));
|
|
76
|
-
// Replace the placeholder path with the target path
|
|
77
|
-
await Promise.all(targetFiles.map(async (filePath) => {
|
|
78
|
-
// Check if file exists before processing
|
|
79
|
-
if (!fs.existsSync(filePath)) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
// Get file content
|
|
83
|
-
const fileContent = await fs.promises.readFile(filePath, 'utf8');
|
|
84
|
-
// Localize the file (handles both URLs and hrefs in single AST pass)
|
|
85
|
-
const result = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, locale, settings.options?.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.excludeStaticUrls, settings.options?.baseDomain);
|
|
86
|
-
// Only write the file if there were changes
|
|
87
|
-
if (result.hasChanges) {
|
|
88
|
-
await fs.promises.writeFile(filePath, result.content);
|
|
89
|
-
}
|
|
90
|
-
}));
|
|
91
|
-
});
|
|
92
|
-
processPromises.push(...mappingPromises);
|
|
93
|
-
await Promise.all(processPromises);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Determines if a URL should be processed based on pattern matching
|
|
97
|
-
*/
|
|
98
|
-
function shouldProcessUrl(originalUrl, patternHead, targetLocale, defaultLocale, baseDomain) {
|
|
99
|
-
// Check fragment-only URLs like "#id-name"
|
|
100
|
-
if (/^\s*#/.test(originalUrl)) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
const patternWithoutSlash = patternHead.replace(/\/$/, '');
|
|
104
|
-
// Handle absolute URLs with baseDomain
|
|
105
|
-
let urlToCheck = originalUrl;
|
|
106
|
-
if (baseDomain && originalUrl.startsWith(baseDomain)) {
|
|
107
|
-
urlToCheck = originalUrl.substring(baseDomain.length);
|
|
108
|
-
}
|
|
109
|
-
if (targetLocale === defaultLocale) {
|
|
110
|
-
// For default locale processing, check if URL contains the pattern
|
|
111
|
-
return urlToCheck.includes(patternWithoutSlash);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
// For non-default locales, check if URL starts with pattern
|
|
115
|
-
return urlToCheck.startsWith(patternWithoutSlash);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Determines if a URL should be processed based on the base domain
|
|
120
|
-
*/
|
|
121
|
-
function shouldProcessAbsoluteUrl(originalUrl, baseDomain) {
|
|
122
|
-
return originalUrl.startsWith(baseDomain);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Checks if a URL should be excluded based on exclusion patterns
|
|
126
|
-
*/
|
|
127
|
-
function isUrlExcluded(originalUrl, exclude, defaultLocale) {
|
|
128
|
-
const excludePatterns = exclude.map((p) => p.replace(/\[locale\]/g, defaultLocale));
|
|
129
|
-
return excludePatterns.some((pattern) => isMatch(originalUrl, pattern));
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Main URL transformation function that delegates to specific scenarios
|
|
133
|
-
*/
|
|
134
|
-
export function transformUrlPath(originalUrl, patternHead, targetLocale, defaultLocale, hideDefaultLocale) {
|
|
135
|
-
const originalPathArray = originalUrl
|
|
136
|
-
.split('/')
|
|
137
|
-
.filter((path) => path !== '');
|
|
138
|
-
const patternHeadArray = patternHead.split('/').filter((path) => path !== '');
|
|
139
|
-
// check if the pattern head matches the original path
|
|
140
|
-
if (!checkIfPathMatchesPattern(originalPathArray, patternHeadArray)) {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
if (patternHeadArray.length > originalPathArray.length) {
|
|
144
|
-
return null; // Pattern is longer than the URL path
|
|
145
|
-
}
|
|
146
|
-
let result = null;
|
|
147
|
-
if (targetLocale === defaultLocale) {
|
|
148
|
-
if (hideDefaultLocale) {
|
|
149
|
-
// check if default locale is already present
|
|
150
|
-
if (originalPathArray?.[patternHeadArray.length] !== defaultLocale) {
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
// remove default locale
|
|
154
|
-
const newPathArray = [
|
|
155
|
-
...originalPathArray.slice(0, patternHeadArray.length),
|
|
156
|
-
...originalPathArray.slice(patternHeadArray.length + 1),
|
|
157
|
-
];
|
|
158
|
-
result = newPathArray.join('/');
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
// check if default locale is already present
|
|
162
|
-
if (originalPathArray?.[patternHeadArray.length] === defaultLocale) {
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
// insert default locale
|
|
166
|
-
const newPathArray = [
|
|
167
|
-
...originalPathArray.slice(0, patternHeadArray.length),
|
|
168
|
-
defaultLocale,
|
|
169
|
-
...originalPathArray.slice(patternHeadArray.length),
|
|
170
|
-
];
|
|
171
|
-
result = newPathArray.join('/');
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
else if (hideDefaultLocale) {
|
|
175
|
-
const newPathArray = [
|
|
176
|
-
...originalPathArray.slice(0, patternHeadArray.length),
|
|
177
|
-
targetLocale,
|
|
178
|
-
...originalPathArray.slice(patternHeadArray.length),
|
|
179
|
-
];
|
|
180
|
-
result = newPathArray.join('/');
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
// check default locale
|
|
184
|
-
if (originalPathArray?.[patternHeadArray.length] !== defaultLocale) {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
// replace default locale with target locale
|
|
188
|
-
const newPathArray = [...originalPathArray];
|
|
189
|
-
newPathArray[patternHeadArray.length] = targetLocale;
|
|
190
|
-
result = newPathArray.join('/');
|
|
191
|
-
}
|
|
192
|
-
// check for leading and trailing slashes
|
|
193
|
-
if (originalUrl.startsWith('/')) {
|
|
194
|
-
result = '/' + result;
|
|
195
|
-
}
|
|
196
|
-
if (originalUrl.endsWith('/')) {
|
|
197
|
-
result = result + '/';
|
|
198
|
-
}
|
|
199
|
-
return result;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* AST-based transformation for MDX files using remark-mdx
|
|
203
|
-
*/
|
|
204
|
-
function transformMdxUrls(mdxContent, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', exclude = [], baseDomain) {
|
|
205
|
-
const transformedUrls = [];
|
|
206
|
-
if (!pattern.startsWith('/')) {
|
|
207
|
-
pattern = '/' + pattern;
|
|
208
|
-
}
|
|
209
|
-
const patternHead = pattern.split('[locale]')[0];
|
|
210
|
-
// Quick check: if the file doesn't contain the pattern, skip expensive AST parsing
|
|
211
|
-
// For default locale processing, we also need to check if content might need adjustment
|
|
212
|
-
if (targetLocale === defaultLocale) {
|
|
213
|
-
// For default locale files, we always need to check as we're looking for either:
|
|
214
|
-
// - paths without locale (when hideDefaultLocale=false)
|
|
215
|
-
// - paths with default locale (when hideDefaultLocale=true)
|
|
216
|
-
const patternWithoutSlash = patternHead.replace(/\/$/, '');
|
|
217
|
-
if (!mdxContent.includes(patternWithoutSlash)) {
|
|
218
|
-
return {
|
|
219
|
-
content: mdxContent,
|
|
220
|
-
hasChanges: false,
|
|
221
|
-
transformedUrls: [],
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
// For non-default locales, use the original logic
|
|
227
|
-
if (!mdxContent.includes(patternHead.replace(/\/$/, ''))) {
|
|
228
|
-
return {
|
|
229
|
-
content: mdxContent,
|
|
230
|
-
hasChanges: false,
|
|
231
|
-
transformedUrls: [],
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
// Parse the MDX content into an AST
|
|
236
|
-
let processedAst;
|
|
237
|
-
try {
|
|
238
|
-
const parseProcessor = unified()
|
|
239
|
-
.use(remarkParse)
|
|
240
|
-
.use(remarkFrontmatter, ['yaml', 'toml'])
|
|
241
|
-
.use(remarkMdx);
|
|
242
|
-
const ast = parseProcessor.parse(mdxContent);
|
|
243
|
-
processedAst = parseProcessor.runSync(ast);
|
|
244
|
-
}
|
|
245
|
-
catch (error) {
|
|
246
|
-
console.warn(`Failed to parse MDX content: ${error instanceof Error ? error.message : String(error)}`);
|
|
247
|
-
console.warn('Returning original content unchanged due to parsing error.');
|
|
248
|
-
return {
|
|
249
|
-
content: mdxContent,
|
|
250
|
-
hasChanges: false,
|
|
251
|
-
transformedUrls,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
// Helper function to transform URL based on pattern
|
|
255
|
-
const transformUrl = (originalUrl, linkType) => {
|
|
256
|
-
// Check if URL should be processed
|
|
257
|
-
if (!shouldProcessUrl(originalUrl, patternHead, targetLocale, defaultLocale, baseDomain)) {
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
// Skip absolute URLs (http://, https://, //, etc.)
|
|
261
|
-
if (baseDomain && shouldProcessAbsoluteUrl(originalUrl, baseDomain)) {
|
|
262
|
-
// Get everything after the base domain
|
|
263
|
-
const afterDomain = originalUrl.substring(baseDomain.length);
|
|
264
|
-
const transformedPath = transformUrlPath(afterDomain, patternHead, targetLocale, defaultLocale, hideDefaultLocale);
|
|
265
|
-
if (!transformedPath) {
|
|
266
|
-
return null;
|
|
267
|
-
}
|
|
268
|
-
transformedUrls.push({
|
|
269
|
-
originalPath: originalUrl,
|
|
270
|
-
newPath: transformedPath,
|
|
271
|
-
type: linkType,
|
|
272
|
-
});
|
|
273
|
-
return transformedPath ? baseDomain + transformedPath : null;
|
|
274
|
-
}
|
|
275
|
-
// Exclude colon-prefixed URLs (http://, https://, //, etc.)
|
|
276
|
-
if (originalUrl.split('?')[0].includes(':')) {
|
|
277
|
-
return null;
|
|
278
|
-
}
|
|
279
|
-
// Transform the URL based on locale and configuration
|
|
280
|
-
const newUrl = transformUrlPath(originalUrl, patternHead, targetLocale, defaultLocale, hideDefaultLocale);
|
|
281
|
-
if (!newUrl) {
|
|
282
|
-
return null;
|
|
283
|
-
}
|
|
284
|
-
// Check exclusions
|
|
285
|
-
if (isUrlExcluded(originalUrl, exclude, defaultLocale)) {
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
transformedUrls.push({
|
|
289
|
-
originalPath: originalUrl,
|
|
290
|
-
newPath: newUrl,
|
|
291
|
-
type: linkType,
|
|
292
|
-
});
|
|
293
|
-
return newUrl;
|
|
294
|
-
};
|
|
295
|
-
// Visit markdown link nodes: [text](url)
|
|
296
|
-
visit(processedAst, 'link', (node) => {
|
|
297
|
-
if (node.url) {
|
|
298
|
-
const newUrl = transformUrl(node.url, 'markdown');
|
|
299
|
-
if (newUrl) {
|
|
300
|
-
node.url = newUrl;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
// Visit JSX/HTML elements for href attributes: <a href="url"> or <Card href="url">
|
|
305
|
-
visit(processedAst, ['mdxJsxFlowElement', 'mdxJsxTextElement'], (node) => {
|
|
306
|
-
const jsxNode = node;
|
|
307
|
-
if (jsxNode.attributes) {
|
|
308
|
-
for (const attr of jsxNode.attributes) {
|
|
309
|
-
if (attr.type === 'mdxJsxAttribute' &&
|
|
310
|
-
attr.name === 'href' &&
|
|
311
|
-
attr.value) {
|
|
312
|
-
// Handle MdxJsxAttribute with string or MdxJsxAttributeValueExpression
|
|
313
|
-
const hrefValue = typeof attr.value === 'string' ? attr.value : attr.value.value;
|
|
314
|
-
if (typeof hrefValue === 'string') {
|
|
315
|
-
const newUrl = transformUrl(hrefValue, 'href');
|
|
316
|
-
if (newUrl) {
|
|
317
|
-
if (typeof attr.value === 'string') {
|
|
318
|
-
attr.value = newUrl;
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
attr.value.value = newUrl;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
// Visit raw JSX nodes for href attributes in JSX strings
|
|
330
|
-
visit(processedAst, 'jsx', (node) => {
|
|
331
|
-
if (node.value && typeof node.value === 'string') {
|
|
332
|
-
const jsxContent = node.value;
|
|
333
|
-
// Use regex to find href attributes in the JSX string
|
|
334
|
-
const hrefRegex = /href\s*=\s*["']([^"']+)["']/g;
|
|
335
|
-
let match;
|
|
336
|
-
const replacements = [];
|
|
337
|
-
// Reset regex lastIndex to avoid issues with global flag
|
|
338
|
-
hrefRegex.lastIndex = 0;
|
|
339
|
-
while ((match = hrefRegex.exec(jsxContent)) !== null) {
|
|
340
|
-
const originalHref = match[1];
|
|
341
|
-
const newUrl = transformUrl(originalHref, 'href');
|
|
342
|
-
if (newUrl) {
|
|
343
|
-
// Store replacement info
|
|
344
|
-
const oldHrefAttr = match[0]; // The full match like 'href="/quickstart"'
|
|
345
|
-
const quote = oldHrefAttr.includes('"') ? '"' : "'";
|
|
346
|
-
const newHrefAttr = `href=${quote}${newUrl}${quote}`;
|
|
347
|
-
replacements.push({
|
|
348
|
-
start: match.index,
|
|
349
|
-
end: match.index + oldHrefAttr.length,
|
|
350
|
-
oldHrefAttr,
|
|
351
|
-
newHrefAttr,
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
// Apply replacements in reverse order (from end to start) to avoid position shifts
|
|
356
|
-
if (replacements.length > 0) {
|
|
357
|
-
let newJsxContent = jsxContent;
|
|
358
|
-
replacements
|
|
359
|
-
.sort((a, b) => b.start - a.start)
|
|
360
|
-
.forEach(({ start, end, newHrefAttr }) => {
|
|
361
|
-
newJsxContent =
|
|
362
|
-
newJsxContent.slice(0, start) +
|
|
363
|
-
newHrefAttr +
|
|
364
|
-
newJsxContent.slice(end);
|
|
365
|
-
});
|
|
366
|
-
node.value = newJsxContent;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
// Convert the modified AST back to MDX string
|
|
371
|
-
let content;
|
|
372
|
-
try {
|
|
373
|
-
const stringifyProcessor = unified()
|
|
374
|
-
.use(remarkFrontmatter, ['yaml', 'toml'])
|
|
375
|
-
.use(remarkMdx)
|
|
376
|
-
.use(escapeHtmlInTextNodes)
|
|
377
|
-
.use(remarkStringify, {
|
|
378
|
-
handlers: {
|
|
379
|
-
// Handler to prevent escaping (avoids '<' -> '\<')
|
|
380
|
-
text(node) {
|
|
381
|
-
return node.value;
|
|
382
|
-
},
|
|
383
|
-
},
|
|
384
|
-
});
|
|
385
|
-
const outTree = stringifyProcessor.runSync(processedAst);
|
|
386
|
-
content = stringifyProcessor.stringify(outTree);
|
|
387
|
-
}
|
|
388
|
-
catch (error) {
|
|
389
|
-
console.warn(`Failed to stringify MDX content: ${error instanceof Error ? error.message : String(error)}`);
|
|
390
|
-
console.warn('Returning original content unchanged due to stringify error.');
|
|
391
|
-
return {
|
|
392
|
-
content: mdxContent,
|
|
393
|
-
hasChanges: false,
|
|
394
|
-
transformedUrls: [],
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
// Handle newline formatting to match original input
|
|
398
|
-
if (content.endsWith('\n') && !mdxContent.endsWith('\n')) {
|
|
399
|
-
content = content.slice(0, -1);
|
|
400
|
-
}
|
|
401
|
-
// Preserve leading newlines from original content
|
|
402
|
-
if (mdxContent.startsWith('\n') && !content.startsWith('\n')) {
|
|
403
|
-
content = '\n' + content;
|
|
404
|
-
}
|
|
405
|
-
return {
|
|
406
|
-
content,
|
|
407
|
-
hasChanges: transformedUrls.length > 0,
|
|
408
|
-
transformedUrls,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
// AST-based transformation for MDX files using remark
|
|
412
|
-
function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
|
|
413
|
-
exclude = [], baseDomain) {
|
|
414
|
-
// Use AST-based transformation for MDX files
|
|
415
|
-
return transformMdxUrls(file, defaultLocale, targetLocale, hideDefaultLocale, pattern, exclude, baseDomain || '');
|
|
416
|
-
}
|
|
417
|
-
function cleanPath(path) {
|
|
418
|
-
let cleanedPath = path.startsWith('/') ? path.slice(1) : path;
|
|
419
|
-
cleanedPath = cleanedPath.endsWith('/')
|
|
420
|
-
? cleanedPath.slice(0, -1)
|
|
421
|
-
: cleanedPath;
|
|
422
|
-
return cleanedPath;
|
|
423
|
-
}
|
|
424
|
-
function checkIfPathMatchesPattern(originalUrlArray, patternHeadArray) {
|
|
425
|
-
// check if the pattern head matches the original path
|
|
426
|
-
for (let i = 0; i < patternHeadArray.length; i++) {
|
|
427
|
-
if (patternHeadArray[i] !== originalUrlArray?.[i]) {
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return true;
|
|
432
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
export async function getPackageInfo(packageName) {
|
|
3
|
-
try {
|
|
4
|
-
const output = execSync(`npm list -g ${packageName}`, {
|
|
5
|
-
encoding: 'utf8',
|
|
6
|
-
stdio: 'pipe',
|
|
7
|
-
});
|
|
8
|
-
const match = output.match(new RegExp(`${packageName}@([\\d\\.\\w-]+)`));
|
|
9
|
-
if (match && match[1]) {
|
|
10
|
-
return { version: match[1] };
|
|
11
|
-
}
|
|
12
|
-
return undefined;
|
|
13
|
-
}
|
|
14
|
-
catch (error) {
|
|
15
|
-
return undefined;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare function searchForPackageJson(cwd?: string): Promise<Record<string, any> | null>;
|
|
2
|
-
export declare function getPackageJson(cwd?: string): Promise<Record<string, any> | null>;
|
|
3
|
-
export declare function getCLIVersion(): string;
|
|
4
|
-
export declare function updatePackageJson(packageJson: Record<string, any>, cwd?: string): Promise<void>;
|
|
5
|
-
export declare function isPackageInstalled(packageName: string, packageJson: Record<string, any>, asDevDependency?: boolean, checkBoth?: boolean): boolean;
|
|
6
|
-
export declare function getPackageVersion(packageName: string, packageJson: Record<string, any>): string | undefined;
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { logError } from '../console/logging.js';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import fs from 'node:fs';
|
|
5
|
-
import { fromPackageRoot } from '../fs/getPackageResource.js';
|
|
6
|
-
// search for package.json such that we can run init in non-js projects
|
|
7
|
-
export async function searchForPackageJson(cwd = process.cwd()) {
|
|
8
|
-
// Get the current working directory (where the CLI is being run)
|
|
9
|
-
const packageJsonPath = path.join(cwd, 'package.json');
|
|
10
|
-
// Check if package.json exists
|
|
11
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
try {
|
|
15
|
-
return JSON.parse(await fs.promises.readFile(packageJsonPath, 'utf8'));
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export async function getPackageJson(cwd = process.cwd()) {
|
|
22
|
-
const packageJsonPath = path.join(cwd, 'package.json');
|
|
23
|
-
// Check if package.json exists
|
|
24
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
return JSON.parse(await fs.promises.readFile(packageJsonPath, 'utf8'));
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
export function getCLIVersion() {
|
|
35
|
-
const packageJsonPath = fromPackageRoot('package.json');
|
|
36
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
37
|
-
return 'unknown';
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).version;
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
return 'unknown';
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
export async function updatePackageJson(packageJson, cwd = process.cwd()) {
|
|
47
|
-
try {
|
|
48
|
-
await fs.promises.writeFile(path.join(cwd, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
logError(chalk.red('Error updating package.json: ' + String(error)));
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
// check if a package is installed in the package.json file
|
|
56
|
-
export function isPackageInstalled(packageName, packageJson, asDevDependency = false, checkBoth = false) {
|
|
57
|
-
const dependencies = checkBoth
|
|
58
|
-
? {
|
|
59
|
-
...packageJson.devDependencies,
|
|
60
|
-
...packageJson.dependencies,
|
|
61
|
-
}
|
|
62
|
-
: asDevDependency
|
|
63
|
-
? packageJson.devDependencies
|
|
64
|
-
: packageJson.dependencies;
|
|
65
|
-
if (!dependencies) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
return dependencies[packageName] !== undefined;
|
|
69
|
-
}
|
|
70
|
-
export function getPackageVersion(packageName, packageJson) {
|
|
71
|
-
const dependencies = {
|
|
72
|
-
...packageJson.dependencies,
|
|
73
|
-
...packageJson.devDependencies,
|
|
74
|
-
};
|
|
75
|
-
return dependencies[packageName] ?? undefined;
|
|
76
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export interface PackageManager {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
label: string;
|
|
5
|
-
installCommand: string;
|
|
6
|
-
installAllCommand: string;
|
|
7
|
-
buildCommand: string;
|
|
8
|
-
runScriptCommand: string;
|
|
9
|
-
flags: string;
|
|
10
|
-
forceInstallFlag: string;
|
|
11
|
-
devDependencyFlag: string;
|
|
12
|
-
registry?: string;
|
|
13
|
-
detect: (cwd: string) => boolean;
|
|
14
|
-
addOverride: (pkgName: string, pkgVersion: string) => Promise<void>;
|
|
15
|
-
}
|
|
16
|
-
export declare class NoPackageManagerError extends Error {
|
|
17
|
-
constructor(message: string);
|
|
18
|
-
}
|
|
19
|
-
export declare const BUN: PackageManager;
|
|
20
|
-
export declare const DENO: PackageManager;
|
|
21
|
-
export declare const YARN_V1: PackageManager;
|
|
22
|
-
/** YARN V2/3/4 */
|
|
23
|
-
export declare const YARN_V2: PackageManager;
|
|
24
|
-
export declare const PNPM: PackageManager;
|
|
25
|
-
export declare const NPM: PackageManager;
|
|
26
|
-
export declare const packageManagers: PackageManager[];
|
|
27
|
-
export declare function _detectPackageManger(cwd: string): PackageManager | null;
|
|
28
|
-
export declare function getPackageManager(cwd?: string, specifiedPackageManager?: string, errorIfNotFound?: boolean): Promise<PackageManager>;
|