gtx-cli 2.0.22 → 2.0.23-alpha.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.
@@ -17,6 +17,7 @@ export type TranslateOptions = {
17
17
  experimentalHideDefaultLocale?: boolean;
18
18
  experimentalFlattenJsonFiles?: boolean;
19
19
  experimentalLocalizeStaticImports?: boolean;
20
+ experimentalExcludeStaticUrls?: string[];
20
21
  };
21
22
  export type LoginOptions = {
22
23
  keyType?: 'development' | 'production';
@@ -109,10 +109,14 @@ export async function generateSettings(options, cwd = process.cwd()) {
109
109
  : undefined;
110
110
  mergedOptions = {
111
111
  ...mergedOptions,
112
- experimentalLocalizeStaticImports: gtConfig.options?.experimentalLocalizeStaticImports,
113
- experimentalLocalizeStaticUrls: gtConfig.options?.experimentalLocalizeStaticUrls,
114
- experimentalHideDefaultLocale: gtConfig.options?.experimentalHideDefaultLocale,
115
- experimentalFlattenJsonFiles: gtConfig.options?.experimentalFlattenJsonFiles,
112
+ experimentalLocalizeStaticImports: gtConfig.options?.experimentalLocalizeStaticImports ||
113
+ options.experimentalLocalizeStaticImports,
114
+ experimentalLocalizeStaticUrls: gtConfig.options?.experimentalLocalizeStaticUrls ||
115
+ options.experimentalLocalizeStaticUrls,
116
+ experimentalHideDefaultLocale: gtConfig.options?.experimentalHideDefaultLocale ||
117
+ options.experimentalHideDefaultLocale,
118
+ experimentalFlattenJsonFiles: gtConfig.options?.experimentalFlattenJsonFiles ||
119
+ options.experimentalFlattenJsonFiles,
116
120
  };
117
121
  // Add additional options if provided
118
122
  if (mergedOptions.options) {
@@ -2,8 +2,8 @@ import { getLocaleProperties } from 'generaltranslation';
2
2
  import { exit, logError } from '../../console/logging.js';
3
3
  import { JSONPath } from 'jsonpath-plus';
4
4
  import { flattenJson } from './flattenJson.js';
5
- import micromatch from 'micromatch';
6
5
  import path from 'node:path';
6
+ import micromatch from 'micromatch';
7
7
  const { isMatch } = micromatch;
8
8
  // Find the matching source item in an array
9
9
  // where the key matches the identifying locale property
@@ -114,6 +114,8 @@ export type AdditionalOptions = {
114
114
  experimentalLocalizeStaticUrls?: boolean;
115
115
  experimentalHideDefaultLocale?: boolean;
116
116
  experimentalFlattenJsonFiles?: boolean;
117
+ experimentalExcludeStaticUrls?: string[];
118
+ experimentalExcludeStaticImports?: string[];
117
119
  };
118
120
  export type JsonSchema = {
119
121
  preset?: 'mintlify';
@@ -1,6 +1,8 @@
1
1
  import * as fs from 'fs';
2
2
  import { createFileMapping } from '../formats/files/fileMapping.js';
3
3
  import { logError } from '../console/logging.js';
4
+ import micromatch from 'micromatch';
5
+ const { isMatch } = micromatch;
4
6
  /**
5
7
  * Localizes static imports in content files.
6
8
  * Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
@@ -31,38 +33,52 @@ export default async function localizeStaticImports(settings) {
31
33
  // Get file content
32
34
  const fileContent = await fs.promises.readFile(filePath, 'utf8');
33
35
  // Localize the file
34
- const localizedFile = localizeStaticImportsForFile(fileContent, settings.defaultLocale, locale, settings.options?.docsHideDefaultLocaleImport || false, settings.options?.docsImportPattern);
36
+ const localizedFile = localizeStaticImportsForFile(fileContent, settings.defaultLocale, locale, settings.options?.docsHideDefaultLocaleImport || false, settings.options?.docsImportPattern, settings.options?.experimentalExcludeStaticImports);
35
37
  // Write the localized file to the target path
36
38
  await fs.promises.writeFile(filePath, localizedFile);
37
39
  }));
38
40
  }));
39
41
  }
40
42
  // Naive find and replace, in the future, construct an AST
41
- function localizeStaticImportsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]' // eg /docs/[locale] or /[locale]
42
- ) {
43
+ function localizeStaticImportsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
44
+ exclude = []) {
43
45
  if (!pattern.startsWith('/')) {
44
46
  pattern = '/' + pattern;
45
47
  }
46
48
  // 1. Search for all instances of:
47
49
  const patternHead = pattern.split('[locale]')[0];
50
+ // Escape special regex characters and remove trailing slash if present
51
+ const escapedPatternHead = patternHead
52
+ .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
53
+ .replace(/\/$/, '');
48
54
  let regex;
49
55
  if (hideDefaultLocale) {
50
- const trimmedPatternHead = patternHead.endsWith('/')
51
- ? patternHead.slice(0, -1)
52
- : patternHead;
53
- // Match complete markdown links: `import { Foo } from '@/docs/[locale]/foo.md'`
54
- regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${trimmedPatternHead}(.*?)\\2`, 'g');
56
+ // Match complete import statements: `import { Foo } from '/docs/foo.md'`
57
+ regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${escapedPatternHead}(?:/([^"']*?))?\\2`, 'g');
55
58
  }
56
59
  else {
57
- // Match complete markdown links with default locale: `import { Foo } from '@/docs/${defaultLocale}/foo.md'`
58
- regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${patternHead}${defaultLocale}(.*?)\\2`, 'g');
60
+ // Match complete import statements with default locale: `import { Foo } from '/docs/${defaultLocale}/foo.md'`
61
+ regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${escapedPatternHead}/${defaultLocale}(?:/([^"']*?))?\\2`, 'g');
59
62
  }
60
63
  const matches = file.match(regex);
61
64
  if (!matches) {
62
65
  return file;
63
66
  }
67
+ exclude = exclude.map((pattern) => pattern.replace(/\[locale\]/g, defaultLocale));
64
68
  // 2. Replace the default locale with the target locale in all matched instances
65
69
  const localizedFile = file.replace(regex, (match, bindings, quoteType, pathContent) => {
70
+ // Check if this path should be excluded from localization
71
+ if (exclude.length > 0) {
72
+ let matchPath = patternHead;
73
+ if (pathContent) {
74
+ matchPath = hideDefaultLocale
75
+ ? `${patternHead}${pathContent}`
76
+ : `${patternHead}${defaultLocale}/${pathContent}`;
77
+ }
78
+ if (exclude.some((pattern) => isMatch(matchPath, pattern))) {
79
+ return match; // Don't localize excluded paths
80
+ }
81
+ }
66
82
  // get the quote type
67
83
  quoteType = match.match(/["']/)?.[0] || '"';
68
84
  if (!quoteType) {
@@ -81,12 +97,12 @@ function localizeStaticImportsForFile(file, defaultLocale, targetLocale, hideDef
81
97
  if (!pathContent || pathContent === '') {
82
98
  return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}${quoteType}`;
83
99
  }
84
- return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}${pathContent}${quoteType}`;
100
+ return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}/${pathContent}${quoteType}`;
85
101
  }
86
102
  else {
87
103
  // For non-hideDefaultLocale, replace defaultLocale with targetLocale
88
104
  // pathContent contains everything after the default locale (no leading slash if present)
89
- return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}${pathContent}${quoteType}`;
105
+ return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}${pathContent ? '/' + pathContent : ''}${quoteType}`;
90
106
  }
91
107
  });
92
108
  return localizedFile;
@@ -1,5 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import { createFileMapping } from '../formats/files/fileMapping.js';
3
+ import micromatch from 'micromatch';
4
+ const { isMatch } = micromatch;
3
5
  /**
4
6
  * Localizes static urls in content files.
5
7
  * Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
@@ -30,16 +32,16 @@ export default async function localizeStaticUrls(settings) {
30
32
  // Get file content
31
33
  const fileContent = await fs.promises.readFile(filePath, 'utf8');
32
34
  // Localize the file
33
- const localizedFile = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern);
34
- const localizedFileHrefs = localizeStaticHrefsForFile(localizedFile, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern);
35
+ const localizedFile = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.experimentalExcludeStaticUrls);
36
+ const localizedFileHrefs = localizeStaticHrefsForFile(localizedFile, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.experimentalExcludeStaticUrls);
35
37
  // Write the localized file to the target path
36
38
  await fs.promises.writeFile(filePath, localizedFileHrefs);
37
39
  }));
38
40
  }));
39
41
  }
40
42
  // Naive find and replace, in the future, construct an AST
41
- function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]' // eg /docs/[locale] or /[locale]
42
- ) {
43
+ function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
44
+ exclude = []) {
43
45
  if (!pattern.startsWith('/')) {
44
46
  pattern = '/' + pattern;
45
47
  }
@@ -62,8 +64,21 @@ function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaul
62
64
  if (!matches) {
63
65
  return file;
64
66
  }
67
+ exclude = exclude.map((pattern) => pattern.replace(/\[locale\]/g, defaultLocale));
65
68
  // 2. Replace the default locale with the target locale in all matched instances
66
69
  const localizedFile = file.replace(regex, (match, pathContent) => {
70
+ if (exclude.length > 0) {
71
+ // Check if this path should be excluded from localization
72
+ let matchPath = patternHead;
73
+ if (pathContent) {
74
+ matchPath = hideDefaultLocale
75
+ ? `${patternHead}${pathContent}`
76
+ : `${patternHead}${defaultLocale}/${pathContent}`;
77
+ }
78
+ if (exclude.some((pattern) => isMatch(matchPath, pattern))) {
79
+ return match; // Don't localize excluded paths
80
+ }
81
+ }
67
82
  if (hideDefaultLocale) {
68
83
  // For hideDefaultLocale, check if path already has target locale
69
84
  if (pathContent) {
@@ -81,13 +96,14 @@ function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaul
81
96
  else {
82
97
  // For non-hideDefaultLocale, replace defaultLocale with targetLocale
83
98
  // pathContent contains everything after the default locale (no leading slash if present)
84
- return `](${patternHead}${targetLocale}${pathContent ? '/' + pathContent : ''})`;
99
+ const result = `](${patternHead}${targetLocale}${pathContent ? '/' + pathContent : ''})`;
100
+ return result;
85
101
  }
86
102
  });
87
103
  return localizedFile;
88
104
  }
89
- function localizeStaticHrefsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]' // eg /docs/[locale] or /[locale]
90
- ) {
105
+ function localizeStaticHrefsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
106
+ exclude = []) {
91
107
  if (!pattern.startsWith('/')) {
92
108
  pattern = '/' + pattern;
93
109
  }
@@ -110,8 +126,21 @@ function localizeStaticHrefsForFile(file, defaultLocale, targetLocale, hideDefau
110
126
  if (!matches) {
111
127
  return file;
112
128
  }
129
+ exclude = exclude.map((pattern) => pattern.replace(/\[locale\]/g, defaultLocale));
113
130
  // 2. Replace the default locale with the target locale in all matched instances
114
131
  const localizedFile = file.replace(regex, (match, pathContent) => {
132
+ // Check if this path should be excluded from localization
133
+ if (exclude.length > 0) {
134
+ let matchPath = patternHead;
135
+ if (pathContent) {
136
+ matchPath = hideDefaultLocale
137
+ ? `${patternHead}${pathContent}`
138
+ : `${patternHead}${defaultLocale}/${pathContent}`;
139
+ }
140
+ if (exclude.some((pattern) => isMatch(matchPath, pattern))) {
141
+ return match; // Don't localize excluded paths
142
+ }
143
+ }
115
144
  if (hideDefaultLocale) {
116
145
  // For hideDefaultLocale, check if path already has target locale
117
146
  if (pathContent) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.0.22",
3
+ "version": "2.0.23-alpha.0",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [