gtx-cli 1.2.28 → 1.2.30-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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 1.2.29
4
+
5
+ ### Patch Changes
6
+
7
+ - [#400](https://github.com/generaltranslation/gt/pull/400) [`cf9c724`](https://github.com/generaltranslation/gt/commit/cf9c72488f74db5ccd7c4dca2650d75e3484d1f2) Thanks [@brian-lou](https://github.com/brian-lou)! - Reorder linter detection preference
8
+
3
9
  ## 1.2.28
4
10
 
5
11
  ### Patch Changes
package/dist/cli/react.js CHANGED
@@ -144,7 +144,7 @@ export class ReactCLI extends BaseCLI {
144
144
  }
145
145
  // User has to provide a dictionary file
146
146
  // will not read from settings.files.resolvedPaths.json
147
- const { updates, errors } = await createUpdates(options, options.dictionary, this.library === 'gt-next' ? 'gt-next' : 'gt-react');
147
+ const { updates, errors } = await createUpdates(options, options.dictionary, this.library === 'gt-next' ? 'gt-next' : 'gt-react', false);
148
148
  if (errors.length > 0) {
149
149
  if (options.ignoreErrors) {
150
150
  logWarning(chalk.yellow(`CLI tool encountered errors while scanning for translatable content. These components will not be translated.\n` +
@@ -1,9 +1,12 @@
1
1
  export declare const warnApiKeyInConfigSync: (optionsFilepath: string) => string;
2
2
  export declare const warnVariablePropSync: (file: string, attrName: string, value: string, location?: string) => string;
3
3
  export declare const warnHasUnwrappedExpressionSync: (file: string, unwrappedExpressions: string[], id?: string, location?: string) => string;
4
+ export declare const warnNestedTComponent: (file: string, location?: string) => string;
4
5
  export declare const warnNonStaticExpressionSync: (file: string, attrName: string, value: string, location?: string) => string;
5
6
  export declare const warnTemplateLiteralSync: (file: string, value: string, location?: string) => string;
6
7
  export declare const warnNonStringSync: (file: string, value: string, location?: string) => string;
8
+ export declare const warnAsyncUseGT: (file: string, location?: string) => string;
9
+ export declare const warnSyncGetGT: (file: string, location?: string) => string;
7
10
  export declare const warnTernarySync: (file: string, location?: string) => string;
8
11
  export declare const withLocation: (file: string, message: string, location?: string) => string;
9
12
  export declare const noLocalesError = "No locales found! Please provide a list of locales to translate to, or specify them in your gt.config.json file.";
@@ -3,9 +3,12 @@ import { colorizeFilepath, colorizeComponent, colorizeIdString, colorizeContent,
3
3
  export const warnApiKeyInConfigSync = (optionsFilepath) => `${colorizeFilepath(optionsFilepath)}: Your API key is exposed! Please remove it from the file and include it as an environment variable.`;
4
4
  export const warnVariablePropSync = (file, attrName, value, location) => withLocation(file, `${colorizeComponent('<T>')} component has dynamic attribute ${colorizeIdString(attrName)} with value: ${colorizeContent(value)}. Change ${colorizeIdString(attrName)} to ensure this content is translated.`, location);
5
5
  export const warnHasUnwrappedExpressionSync = (file, unwrappedExpressions, id, location) => withLocation(file, `${colorizeComponent('<T>')} component${id ? ` with id ${colorizeIdString(id)}` : ''} has children that could change at runtime. Use a variable component like ${colorizeComponent('<Var>')} to ensure this content is translated.\n${colorizeContent(unwrappedExpressions.join('\n'))}`, location);
6
+ export const warnNestedTComponent = (file, location) => withLocation(file, `Found nested <T> component. <T> components cannot be directly nested.`, location);
6
7
  export const warnNonStaticExpressionSync = (file, attrName, value, location) => withLocation(file, `Found non-static expression for attribute ${colorizeIdString(attrName)}: ${colorizeContent(value)}. Change "${colorizeIdString(attrName)}" to ensure this content is translated.`, location);
7
8
  export const warnTemplateLiteralSync = (file, value, location) => withLocation(file, `Found template literal with quasis (${colorizeContent(value)}). Change the template literal to a string to ensure this content is translated.`, location);
8
9
  export const warnNonStringSync = (file, value, location) => withLocation(file, `Found non-string literal (${colorizeContent(value)}). Change the value to a string literal to ensure this content is translated.`, location);
10
+ export const warnAsyncUseGT = (file, location) => withLocation(file, `Found useGT() in an async function. Use getGT() instead, or make the function synchronous.`, location);
11
+ export const warnSyncGetGT = (file, location) => withLocation(file, `Found getGT() in a synchronous function. Use useGT() instead, or make the function async.`, location);
9
12
  export const warnTernarySync = (file, location) => withLocation(file, 'Found ternary expression. A Branch component may be more appropriate here.', location);
10
13
  export const withLocation = (file, message, location) => `${colorizeFilepath(file)}${location ? ` (${colorizeLine(location)})` : ''}: ${message}`;
11
14
  // Re-export error messages
@@ -9,6 +9,12 @@ export async function detectFormatter() {
9
9
  return 'prettier';
10
10
  }
11
11
  catch { }
12
+ // Try ESLint
13
+ try {
14
+ await import('eslint');
15
+ return 'eslint';
16
+ }
17
+ catch { }
12
18
  // Try Biome
13
19
  try {
14
20
  return await new Promise((resolve, reject) => {
@@ -29,12 +35,6 @@ export async function detectFormatter() {
29
35
  });
30
36
  }
31
37
  catch { }
32
- // Try ESLint
33
- try {
34
- await import('eslint');
35
- return 'eslint';
36
- }
37
- catch { }
38
38
  return null;
39
39
  }
40
40
  export async function formatFiles(filesUpdated, formatter) {
@@ -0,0 +1,2 @@
1
+ export declare const GT_TRANSLATION_FUNCS: string[];
2
+ export declare const VARIABLE_COMPONENTS: string[];
@@ -0,0 +1,14 @@
1
+ // GT translation functions
2
+ export const GT_TRANSLATION_FUNCS = [
3
+ 'useGT',
4
+ 'getGT',
5
+ 'T',
6
+ 'Var',
7
+ 'DateTime',
8
+ 'Currency',
9
+ 'Num',
10
+ 'Branch',
11
+ 'Plural',
12
+ ];
13
+ // Valid variable components
14
+ export const VARIABLE_COMPONENTS = ['Var', 'DateTime', 'Currency', 'Num'];
@@ -7,7 +7,8 @@ import * as t from '@babel/types';
7
7
  * @param updates - The updates array
8
8
  * @param errors - The errors array
9
9
  * @param file - The file name
10
+ * @param insideT - Whether the current node is inside a <T> component
10
11
  * @returns The built JSX tree
11
12
  */
12
- export declare function buildJSXTree(importAliases: Record<string, string>, node: any, unwrappedExpressions: string[], updates: Updates, errors: string[], file: string): any;
13
+ export declare function buildJSXTree(importAliases: Record<string, string>, node: any, unwrappedExpressions: string[], updates: Updates, errors: string[], file: string, insideT: boolean): any;
13
14
  export declare function parseJSXElement(importAliases: Record<string, string>, node: t.JSXElement, updates: Updates, errors: string[], file: string): void;
@@ -3,12 +3,11 @@ import generateModule from '@babel/generator';
3
3
  const generate = generateModule.default || generateModule;
4
4
  import * as t from '@babel/types';
5
5
  import addGTIdentifierToSyntaxTree from '../../data-_gt/addGTIdentifierToSyntaxTree.js';
6
- import { warnHasUnwrappedExpressionSync, warnVariablePropSync, } from '../../../console/index.js';
6
+ import { warnHasUnwrappedExpressionSync, warnVariablePropSync, warnNestedTComponent, } from '../../../console/index.js';
7
7
  import { isAcceptedPluralForm } from 'generaltranslation/internal';
8
8
  import { handleChildrenWhitespace } from '../trimJsxStringChildren.js';
9
9
  import { isStaticExpression } from '../evaluateJsx.js';
10
- // Valid variable components
11
- const VARIABLE_COMPONENTS = ['Var', 'DateTime', 'Currency', 'Num'];
10
+ import { VARIABLE_COMPONENTS } from './constants.js';
12
11
  /**
13
12
  * Builds a JSX tree from a given node, recursively handling children.
14
13
  * @param node - The node to build the tree from
@@ -16,9 +15,10 @@ const VARIABLE_COMPONENTS = ['Var', 'DateTime', 'Currency', 'Num'];
16
15
  * @param updates - The updates array
17
16
  * @param errors - The errors array
18
17
  * @param file - The file name
18
+ * @param insideT - Whether the current node is inside a <T> component
19
19
  * @returns The built JSX tree
20
20
  */
21
- export function buildJSXTree(importAliases, node, unwrappedExpressions, updates, errors, file) {
21
+ export function buildJSXTree(importAliases, node, unwrappedExpressions, updates, errors, file, insideT) {
22
22
  if (t.isJSXExpressionContainer(node)) {
23
23
  // Skip JSX comments
24
24
  if (t.isJSXEmptyExpression(node.expression)) {
@@ -59,6 +59,11 @@ export function buildJSXTree(importAliases, node, unwrappedExpressions, updates,
59
59
  }
60
60
  // Convert from alias to original name
61
61
  const componentType = importAliases[typeName ?? ''];
62
+ if (componentType === 'T' && insideT) {
63
+ // Add error: No nested <T> components are allowed
64
+ errors.push(warnNestedTComponent(file, `${element.loc?.start?.line}:${element.loc?.start?.column}`));
65
+ return null;
66
+ }
62
67
  // If this JSXElement is one of the recognized variable components,
63
68
  const elementIsVariable = VARIABLE_COMPONENTS.includes(componentType);
64
69
  const props = {};
@@ -81,7 +86,7 @@ export function buildJSXTree(importAliases, node, unwrappedExpressions, updates,
81
86
  unwrappedExpressions.push(generate(attr.value).code);
82
87
  }
83
88
  }
84
- attrValue = buildJSXTree(importAliases, attr.value.expression, unwrappedExpressions, updates, errors, file);
89
+ attrValue = buildJSXTree(importAliases, attr.value.expression, unwrappedExpressions, updates, errors, file, true);
85
90
  }
86
91
  }
87
92
  props[attrName] = attrValue;
@@ -97,7 +102,7 @@ export function buildJSXTree(importAliases, node, unwrappedExpressions, updates,
97
102
  };
98
103
  }
99
104
  const children = element.children
100
- .map((child) => buildJSXTree(importAliases, child, unwrappedExpressions, updates, errors, file))
105
+ .map((child) => buildJSXTree(importAliases, child, unwrappedExpressions, updates, errors, file, true))
101
106
  .filter((child) => child !== null && child !== '');
102
107
  if (children.length === 1) {
103
108
  props.children = children[0];
@@ -115,7 +120,7 @@ export function buildJSXTree(importAliases, node, unwrappedExpressions, updates,
115
120
  // If it's a JSX fragment
116
121
  else if (t.isJSXFragment(node)) {
117
122
  const children = node.children
118
- .map((child) => buildJSXTree(importAliases, child, unwrappedExpressions, updates, errors, file))
123
+ .map((child) => buildJSXTree(importAliases, child, unwrappedExpressions, updates, errors, file, true))
119
124
  .filter((child) => child !== null && child !== '');
120
125
  const props = {};
121
126
  if (children.length === 1) {
@@ -152,65 +157,70 @@ export function parseJSXElement(importAliases, node, updates, errors, file) {
152
157
  const openingElement = node.openingElement;
153
158
  const name = openingElement.name;
154
159
  // Only proceed if it's <T> ...
155
- if (name.type === 'JSXIdentifier' && importAliases[name.name] === 'T') {
156
- const componentObj = { props: {} };
157
- // We'll track this flag to know if any unwrapped {variable} is found in children
158
- const unwrappedExpressions = [];
159
- // Gather <T>'s props
160
- openingElement.attributes.forEach((attr) => {
161
- if (!t.isJSXAttribute(attr))
162
- return;
163
- const attrName = attr.name.name;
164
- if (typeof attrName !== 'string')
165
- return;
166
- if (attr.value) {
167
- // If it's a plain string literal like id="hello"
168
- if (t.isStringLiteral(attr.value)) {
169
- componentObj.props[attrName] = attr.value.value;
170
- }
171
- // If it's an expression container like id={"hello"}, id={someVar}, etc.
172
- else if (t.isJSXExpressionContainer(attr.value)) {
173
- const expr = attr.value.expression;
174
- const code = generate(expr).code;
175
- // Only check for static expressions on id and context props
176
- if (attrName === 'id' || attrName === 'context') {
177
- const staticAnalysis = isStaticExpression(expr);
178
- if (!staticAnalysis.isStatic) {
179
- errors.push(warnVariablePropSync(file, attrName, code, `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
180
- }
181
- // Use the static value if available
182
- if (staticAnalysis.isStatic && staticAnalysis.value !== undefined) {
183
- componentObj.props[attrName] = staticAnalysis.value;
184
- }
185
- else {
186
- // Only store the code if we couldn't extract a static value
187
- componentObj.props[attrName] = code;
188
- }
160
+ if (!(name.type === 'JSXIdentifier' && importAliases[name.name] === 'T')) {
161
+ return;
162
+ }
163
+ const componentErrors = [];
164
+ const componentObj = { props: {} };
165
+ // We'll track this flag to know if any unwrapped {variable} is found in children
166
+ const unwrappedExpressions = [];
167
+ // Gather <T>'s props
168
+ openingElement.attributes.forEach((attr) => {
169
+ if (!t.isJSXAttribute(attr))
170
+ return;
171
+ const attrName = attr.name.name;
172
+ if (typeof attrName !== 'string')
173
+ return;
174
+ if (attr.value) {
175
+ // If it's a plain string literal like id="hello"
176
+ if (t.isStringLiteral(attr.value)) {
177
+ componentObj.props[attrName] = attr.value.value;
178
+ }
179
+ // If it's an expression container like id={"hello"}, id={someVar}, etc.
180
+ else if (t.isJSXExpressionContainer(attr.value)) {
181
+ const expr = attr.value.expression;
182
+ const code = generate(expr).code;
183
+ // Only check for static expressions on id and context props
184
+ if (attrName === 'id' || attrName === 'context') {
185
+ const staticAnalysis = isStaticExpression(expr);
186
+ if (!staticAnalysis.isStatic) {
187
+ componentErrors.push(warnVariablePropSync(file, attrName, code, `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
188
+ }
189
+ // Use the static value if available
190
+ if (staticAnalysis.isStatic && staticAnalysis.value !== undefined) {
191
+ componentObj.props[attrName] = staticAnalysis.value;
189
192
  }
190
193
  else {
191
- // For other attributes that aren't id or context
194
+ // Only store the code if we couldn't extract a static value
192
195
  componentObj.props[attrName] = code;
193
196
  }
194
197
  }
198
+ else {
199
+ // For other attributes that aren't id or context
200
+ componentObj.props[attrName] = code;
201
+ }
195
202
  }
196
- });
197
- // Build the JSX tree for this component
198
- const initialTree = buildJSXTree(importAliases, node, unwrappedExpressions, updates, errors, file).props.children;
199
- const whitespaceHandledTree = handleChildrenWhitespace(initialTree);
200
- const tree = addGTIdentifierToSyntaxTree(whitespaceHandledTree);
201
- componentObj.tree = tree.length === 1 ? tree[0] : tree;
202
- const id = componentObj.props.id;
203
- // If we found an unwrapped expression, skip
204
- if (unwrappedExpressions.length > 0) {
205
- errors.push(warnHasUnwrappedExpressionSync(file, unwrappedExpressions, id, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
206
203
  }
207
- if (errors.length > 0)
208
- return;
209
- // <T> is valid here
210
- updates.push({
211
- dataFormat: 'JSX',
212
- source: componentObj.tree,
213
- metadata: componentObj.props,
214
- });
204
+ });
205
+ // Build the JSX tree for this component
206
+ const initialTree = buildJSXTree(importAliases, node, unwrappedExpressions, updates, componentErrors, file, false)?.props?.children;
207
+ if (componentErrors.length > 0) {
208
+ errors.push(...componentErrors);
209
+ return;
210
+ }
211
+ const whitespaceHandledTree = handleChildrenWhitespace(initialTree);
212
+ const tree = addGTIdentifierToSyntaxTree(whitespaceHandledTree);
213
+ componentObj.tree = tree.length === 1 ? tree[0] : tree;
214
+ const id = componentObj.props.id;
215
+ // If we found an unwrapped expression, skip
216
+ if (unwrappedExpressions.length > 0) {
217
+ errors.push(warnHasUnwrappedExpressionSync(file, unwrappedExpressions, id, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
218
+ return;
215
219
  }
220
+ // <T> is valid here
221
+ updates.push({
222
+ dataFormat: 'JSX',
223
+ source: componentObj.tree,
224
+ metadata: componentObj.props,
225
+ });
216
226
  }
@@ -0,0 +1,7 @@
1
+ import { NodePath } from '@babel/traverse';
2
+ import { Updates } from '../../../types/index.js';
3
+ /**
4
+ * Validate useGT() / await getGT() calls
5
+ * 1. Validates that the call does not violate the rules of React (no hooks in async functions)
6
+ */
7
+ export declare function validateStringFunction(localImportName: string, path: NodePath, updates: Updates, errors: string[], file: string, originalImportName: string): void;
@@ -0,0 +1,30 @@
1
+ import { warnAsyncUseGT, warnSyncGetGT } from '../../../console/index.js';
2
+ /**
3
+ * Validate useGT() / await getGT() calls
4
+ * 1. Validates that the call does not violate the rules of React (no hooks in async functions)
5
+ */
6
+ export function validateStringFunction(localImportName, path, updates, errors, file, originalImportName) {
7
+ // Get the root program node to traverse the entire file
8
+ const program = path.scope.getProgramParent().path;
9
+ program.traverse({
10
+ CallExpression(callPath) {
11
+ if (callPath.node.callee.type === 'Identifier' &&
12
+ callPath.node.callee.name === localImportName) {
13
+ // Check the function scope
14
+ const functionScope = callPath.getFunctionParent();
15
+ if (originalImportName === 'useGT') {
16
+ // useGT should NOT be in an async function
17
+ if (functionScope && functionScope.node.async) {
18
+ errors.push(warnAsyncUseGT(file, `${callPath.node.loc?.start?.line}:${callPath.node.loc?.start?.column}`));
19
+ }
20
+ }
21
+ else if (originalImportName === 'getGT') {
22
+ // getGT should be in an async function
23
+ if (!functionScope || !functionScope.node.async) {
24
+ errors.push(warnSyncGetGT(file, `${callPath.node.loc?.start?.line}:${callPath.node.loc?.start?.column}`));
25
+ }
26
+ }
27
+ }
28
+ },
29
+ });
30
+ }
@@ -1,5 +1,5 @@
1
1
  import { Options, Updates } from '../../types/index.js';
2
- export default function createInlineUpdates(options: Options, pkg: 'gt-react' | 'gt-next'): Promise<{
2
+ export default function createInlineUpdates(options: Options, pkg: 'gt-react' | 'gt-next', validate: boolean): Promise<{
3
3
  updates: Updates;
4
4
  errors: string[];
5
5
  }>;
@@ -9,7 +9,9 @@ import { parseJSXElement } from '../jsx/utils/parseJsx.js';
9
9
  import { parseStrings } from '../jsx/utils/parseStringFunction.js';
10
10
  import { extractImportName } from '../jsx/utils/parseAst.js';
11
11
  import { logError } from '../../console/logging.js';
12
- export default async function createInlineUpdates(options, pkg) {
12
+ import { validateStringFunction } from '../jsx/utils/validateStringFunction.js';
13
+ import { GT_TRANSLATION_FUNCS } from '../jsx/utils/constants.js';
14
+ export default async function createInlineUpdates(options, pkg, validate) {
13
15
  const updates = [];
14
16
  const errors = [];
15
17
  // Use the provided app directory or default to the current directory
@@ -56,27 +58,20 @@ export default async function createInlineUpdates(options, pkg) {
56
58
  logError(`Error parsing file ${file}: ${error}`);
57
59
  continue;
58
60
  }
59
- const translationFuncs = [
60
- 'useGT',
61
- 'getGT',
62
- 'T',
63
- 'Var',
64
- 'DateTime',
65
- 'Currency',
66
- 'Num',
67
- 'Branch',
68
- 'Plural',
69
- ];
70
61
  const importAliases = {};
71
62
  // First pass: collect imports and process translation functions
72
63
  const translationPaths = [];
73
64
  traverse(ast, {
74
65
  ImportDeclaration(path) {
75
66
  if (path.node.source.value.startsWith(pkg)) {
76
- const importName = extractImportName(path.node, pkg, translationFuncs);
67
+ const importName = extractImportName(path.node, pkg, GT_TRANSLATION_FUNCS);
77
68
  for (const name of importName) {
78
69
  if (name.original === 'useGT' || name.original === 'getGT') {
79
- translationPaths.push({ name: name.local, path });
70
+ translationPaths.push({
71
+ localName: name.local,
72
+ path,
73
+ originalName: name.original,
74
+ });
80
75
  }
81
76
  else {
82
77
  importAliases[name.local] = name.original;
@@ -96,10 +91,14 @@ export default async function createInlineUpdates(options, pkg) {
96
91
  args[0].value.startsWith(pkg)) {
97
92
  const parentPath = path.parentPath;
98
93
  if (parentPath.isVariableDeclaration()) {
99
- const importName = extractImportName(parentPath.node, pkg, translationFuncs);
94
+ const importName = extractImportName(parentPath.node, pkg, GT_TRANSLATION_FUNCS);
100
95
  for (const name of importName) {
101
96
  if (name.original === 'useGT' || name.original === 'getGT') {
102
- translationPaths.push({ name: name.local, path: parentPath });
97
+ translationPaths.push({
98
+ localName: name.local,
99
+ path: parentPath,
100
+ originalName: name.original,
101
+ });
103
102
  }
104
103
  else {
105
104
  importAliases[name.local] = name.original;
@@ -111,7 +110,7 @@ export default async function createInlineUpdates(options, pkg) {
111
110
  },
112
111
  });
113
112
  // Process translation functions asynchronously
114
- for (const { name, path } of translationPaths) {
113
+ for (const { localName: name, path } of translationPaths) {
115
114
  parseStrings(name, path, updates, errors, file);
116
115
  }
117
116
  // Parse <T> components
@@ -120,6 +119,12 @@ export default async function createInlineUpdates(options, pkg) {
120
119
  parseJSXElement(importAliases, path.node, updates, errors, file);
121
120
  },
122
121
  });
122
+ // Extra validation (for Locadex)
123
+ if (validate) {
124
+ for (const { localName: name, path, originalName } of translationPaths) {
125
+ validateStringFunction(name, path, updates, errors, file, originalName);
126
+ }
127
+ }
123
128
  }
124
129
  // Post-process to add a hash to each update
125
130
  await Promise.all(updates.map(async (update) => {
@@ -8,7 +8,7 @@ import { Options, GenerateSourceOptions, Updates } from '../types/index.js';
8
8
  * @param pkg - The package name
9
9
  * @returns An object containing the updates and errors
10
10
  */
11
- export declare function createUpdates(options: Options | GenerateSourceOptions, sourceDictionary: string | undefined, pkg: 'gt-react' | 'gt-next'): Promise<{
11
+ export declare function createUpdates(options: Options | GenerateSourceOptions, sourceDictionary: string | undefined, pkg: 'gt-react' | 'gt-next', validate: boolean): Promise<{
12
12
  updates: Updates;
13
13
  errors: string[];
14
14
  }>;
@@ -14,7 +14,7 @@ import chalk from 'chalk';
14
14
  * @param pkg - The package name
15
15
  * @returns An object containing the updates and errors
16
16
  */
17
- export async function createUpdates(options, sourceDictionary, pkg) {
17
+ export async function createUpdates(options, sourceDictionary, pkg, validate) {
18
18
  let updates = [];
19
19
  let errors = [];
20
20
  // Parse dictionary with esbuildConfig
@@ -48,7 +48,7 @@ export async function createUpdates(options, sourceDictionary, pkg) {
48
48
  }
49
49
  // Scan through project for <T> tags
50
50
  if (options.inline) {
51
- const { updates: newUpdates, errors: newErrors } = await createInlineUpdates(options, pkg);
51
+ const { updates: newUpdates, errors: newErrors } = await createInlineUpdates(options, pkg, validate);
52
52
  errors = [...errors, ...newErrors];
53
53
  updates = [...updates, ...newUpdates];
54
54
  }
@@ -26,7 +26,7 @@ export async function stageProject(settings, pkg) {
26
26
  }
27
27
  settings.timeout = timeout.toString();
28
28
  // ---- CREATING UPDATES ---- //
29
- const { updates, errors } = await createUpdates(settings, settings.dictionary, pkg);
29
+ const { updates, errors } = await createUpdates(settings, settings.dictionary, pkg, false);
30
30
  if (errors.length > 0) {
31
31
  if (settings.ignoreErrors) {
32
32
  logWarning(chalk.yellow(`Warning: CLI tool encountered ${errors.length} syntax errors while scanning for translatable content. These components will not be translated.\n` +
@@ -14,7 +14,7 @@ export async function validateProject(settings, pkg) {
14
14
  './src/dictionary.ts',
15
15
  ]);
16
16
  }
17
- const { updates, errors } = await createUpdates(settings, settings.dictionary, pkg);
17
+ const { updates, errors } = await createUpdates(settings, settings.dictionary, pkg, true);
18
18
  if (errors.length > 0) {
19
19
  logErrorAndExit(chalk.red(`Error: CLI tool encountered ${errors.length} syntax errors while scanning for translatable content.\n` +
20
20
  errors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "1.2.28",
3
+ "version": "1.2.30-alpha.1",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -93,7 +93,7 @@
93
93
  "tsconfig-paths": "^4.2.0"
94
94
  },
95
95
  "devDependencies": {
96
- "@biomejs/biome": "1.9.4",
96
+ "@biomejs/biome": "^1.9.4",
97
97
  "@types/babel__generator": "^7.27.0",
98
98
  "@types/babel__traverse": "^7.20.6",
99
99
  "@types/figlet": "^1.7.0",