gtx-cli 0.0.1 → 0.0.2
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/README.md +4 -7
- package/dist/api/waitForUpdates.d.ts +1 -0
- package/dist/api/waitForUpdates.js +89 -0
- package/dist/cli/base.d.ts +3 -0
- package/dist/cli/base.js +11 -0
- package/dist/cli/next.d.ts +18 -0
- package/dist/cli/next.js +162 -0
- package/dist/cli/react.d.ts +29 -0
- package/dist/cli/react.js +550 -0
- package/dist/console/console.d.ts +8 -0
- package/dist/console/console.js +65 -0
- package/dist/console/errors.d.ts +1 -0
- package/dist/console/errors.js +4 -0
- package/dist/console/index.d.ts +1 -0
- package/dist/console/index.js +2 -0
- package/dist/console/warnings.d.ts +7 -0
- package/dist/console/warnings.js +47 -0
- package/dist/fs/config/loadConfig.d.ts +1 -0
- package/dist/fs/config/loadConfig.js +15 -0
- package/dist/fs/config/setupConfig.d.ts +8 -0
- package/dist/fs/config/setupConfig.js +37 -0
- package/dist/fs/config/updateConfig.d.ts +10 -0
- package/dist/fs/config/updateConfig.js +33 -0
- package/dist/fs/findFilepath.d.ts +15 -0
- package/dist/fs/findFilepath.js +49 -0
- package/dist/fs/findJsxFilepath.d.ts +7 -0
- package/dist/fs/findJsxFilepath.js +36 -0
- package/dist/fs/index.d.ts +1 -0
- package/dist/fs/index.js +2 -0
- package/dist/fs/loadJSON.d.ts +6 -0
- package/dist/fs/loadJSON.js +23 -0
- package/dist/fs/saveTranslations.d.ts +3 -0
- package/dist/fs/saveTranslations.js +57 -0
- package/dist/hooks/postProcess.d.ts +4 -0
- package/dist/hooks/postProcess.js +101 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +84 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +11 -0
- package/dist/next/config/parseNextConfig.d.ts +10 -0
- package/dist/next/config/parseNextConfig.js +55 -0
- package/dist/next/jsx/utils.d.ts +7 -0
- package/dist/next/jsx/utils.js +82 -0
- package/dist/next/parse/handleInitGT.d.ts +5 -0
- package/dist/next/parse/handleInitGT.js +167 -0
- package/dist/next/parse/index.d.ts +4 -0
- package/dist/next/parse/index.js +14 -0
- package/dist/next/parse/scanForContent.d.ts +13 -0
- package/dist/next/parse/scanForContent.js +189 -0
- package/dist/react/config/createESBuildConfig.d.ts +2 -0
- package/dist/react/config/createESBuildConfig.js +134 -0
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.d.ts +1 -0
- package/dist/react/data-_gt/addGTIdentifierToSyntaxTree.js +92 -0
- package/dist/react/jsx/evaluateJsx.d.ts +17 -0
- package/dist/react/jsx/evaluateJsx.js +133 -0
- package/dist/react/jsx/trimJsxStringChildren.d.ts +7 -0
- package/dist/react/jsx/trimJsxStringChildren.js +97 -0
- package/dist/react/jsx/utils/parseAst.d.ts +30 -0
- package/dist/react/jsx/utils/parseAst.js +320 -0
- package/dist/react/jsx/utils/parseJsx.d.ts +13 -0
- package/dist/react/jsx/utils/parseJsx.js +236 -0
- package/dist/react/jsx/utils/parseStringFunction.d.ts +12 -0
- package/dist/react/jsx/utils/parseStringFunction.js +120 -0
- package/dist/react/jsx/wrapJsx.d.ts +51 -0
- package/dist/react/jsx/wrapJsx.js +407 -0
- package/dist/react/parse/createDictionaryUpdates.d.ts +5 -0
- package/dist/react/parse/createDictionaryUpdates.js +77 -0
- package/dist/react/parse/createInlineUpdates.d.ts +5 -0
- package/dist/react/parse/createInlineUpdates.js +141 -0
- package/dist/react/parse/index.d.ts +3 -0
- package/dist/react/parse/index.js +12 -0
- package/dist/react/parse/scanForContent.d.ts +13 -0
- package/dist/react/parse/scanForContent.js +200 -0
- package/dist/react/types.d.ts +13 -0
- package/dist/react/types.js +2 -0
- package/dist/react/utils/flattenDictionary.d.ts +10 -0
- package/dist/react/utils/flattenDictionary.js +38 -0
- package/dist/react/utils/getEntryAndMetadata.d.ts +5 -0
- package/dist/react/utils/getEntryAndMetadata.js +14 -0
- package/dist/react/utils/getVariableName.d.ts +2 -0
- package/dist/react/utils/getVariableName.js +20 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +2 -0
- package/package.json +9 -2
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.attributes = void 0;
|
|
40
|
+
exports.parseStrings = parseStrings;
|
|
41
|
+
const generaltranslation_1 = require("generaltranslation");
|
|
42
|
+
const t = __importStar(require("@babel/types"));
|
|
43
|
+
const evaluateJsx_1 = require("../evaluateJsx");
|
|
44
|
+
const warnings_1 = require("../../../console/warnings");
|
|
45
|
+
const generator_1 = __importDefault(require("@babel/generator"));
|
|
46
|
+
exports.attributes = ['id', 'context'];
|
|
47
|
+
/**
|
|
48
|
+
* For the following example code:
|
|
49
|
+
* const tx = useGT();
|
|
50
|
+
* tx('string to translate', { id: 'exampleId', context: 'exampleContext' });
|
|
51
|
+
*
|
|
52
|
+
* This function will find all call expressions of useGT(), then find all call expressions
|
|
53
|
+
* of the subsequent tx() calls, and append the content and metadata to the updates array.
|
|
54
|
+
*/
|
|
55
|
+
function parseStrings(importName, path, updates, errors, file) {
|
|
56
|
+
var _a;
|
|
57
|
+
(_a = path.scope.bindings[importName]) === null || _a === void 0 ? void 0 : _a.referencePaths.forEach((refPath) => {
|
|
58
|
+
var _a;
|
|
59
|
+
// Find call expressions of useGT() / await getGT()
|
|
60
|
+
const callExpr = refPath.findParent((p) => p.isCallExpression());
|
|
61
|
+
if (callExpr) {
|
|
62
|
+
// Get the parent, handling both await and non-await cases
|
|
63
|
+
const parentPath = callExpr.parentPath;
|
|
64
|
+
const effectiveParent = (parentPath === null || parentPath === void 0 ? void 0 : parentPath.node.type) === 'AwaitExpression'
|
|
65
|
+
? parentPath.parentPath
|
|
66
|
+
: parentPath;
|
|
67
|
+
if (effectiveParent &&
|
|
68
|
+
effectiveParent.node.type === 'VariableDeclarator' &&
|
|
69
|
+
effectiveParent.node.id.type === 'Identifier') {
|
|
70
|
+
const tFuncName = effectiveParent.node.id.name;
|
|
71
|
+
// Get the scope from the variable declaration
|
|
72
|
+
const variableScope = effectiveParent.scope;
|
|
73
|
+
(_a = variableScope.bindings[tFuncName]) === null || _a === void 0 ? void 0 : _a.referencePaths.forEach((tPath) => {
|
|
74
|
+
if (tPath.parent.type === 'CallExpression' &&
|
|
75
|
+
tPath.parent.arguments.length > 0) {
|
|
76
|
+
const arg = tPath.parent.arguments[0];
|
|
77
|
+
if (arg.type === 'StringLiteral' ||
|
|
78
|
+
(t.isTemplateLiteral(arg) && arg.expressions.length === 0)) {
|
|
79
|
+
const source = arg.type === 'StringLiteral'
|
|
80
|
+
? arg.value
|
|
81
|
+
: arg.quasis[0].value.raw;
|
|
82
|
+
// split the string into content (same as runtime behavior)
|
|
83
|
+
const content = (0, generaltranslation_1.splitStringToContent)(source);
|
|
84
|
+
// get metadata and id from options
|
|
85
|
+
const options = tPath.parent.arguments[1];
|
|
86
|
+
let metadata = {};
|
|
87
|
+
if (options && options.type === 'ObjectExpression') {
|
|
88
|
+
options.properties.forEach((prop) => {
|
|
89
|
+
if (prop.type === 'ObjectProperty' &&
|
|
90
|
+
prop.key.type === 'Identifier') {
|
|
91
|
+
const attribute = prop.key.name;
|
|
92
|
+
if (exports.attributes.includes(attribute) &&
|
|
93
|
+
t.isExpression(prop.value)) {
|
|
94
|
+
const result = (0, evaluateJsx_1.isStaticExpression)(prop.value);
|
|
95
|
+
if (!result.isStatic) {
|
|
96
|
+
errors.push((0, warnings_1.warnNonStaticExpression)(file, attribute, (0, generator_1.default)(prop.value).code));
|
|
97
|
+
}
|
|
98
|
+
if (result.isStatic && result.value) {
|
|
99
|
+
metadata[attribute] = result.value;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
updates.push({
|
|
106
|
+
type: 'content',
|
|
107
|
+
source: content,
|
|
108
|
+
metadata,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else if (t.isTemplateLiteral(arg)) {
|
|
112
|
+
// warn if template literal
|
|
113
|
+
errors.push((0, warnings_1.warnTemplateLiteral)(file, (0, generator_1.default)(arg).code));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { ImportItem } from './utils/parseAst';
|
|
3
|
+
/**
|
|
4
|
+
* Recursively wraps a JSX element with a <T> component and unique id
|
|
5
|
+
* @param node - The JSX element to wrap
|
|
6
|
+
* @param updates - The updates array
|
|
7
|
+
* @param errors - The errors array
|
|
8
|
+
* @param file - The file name
|
|
9
|
+
* @param options - Optional component names for T and Var
|
|
10
|
+
*/
|
|
11
|
+
export interface WrapResult {
|
|
12
|
+
node: t.JSXElement | t.JSXFragment;
|
|
13
|
+
hasMeaningfulContent: boolean;
|
|
14
|
+
wrappedInT: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Recursively traverse a JSX element and wrap variables with a <Var> component
|
|
18
|
+
* @param node - The JSX element to wrap
|
|
19
|
+
* @param options - Optional component names for T and Var
|
|
20
|
+
* @param isMeaningful - A function to determine if a node is meaningful
|
|
21
|
+
* @returns The wrapped JSX element
|
|
22
|
+
*/
|
|
23
|
+
export declare function wrapJsxElement(node: t.JSXElement | t.JSXFragment, options: {
|
|
24
|
+
createIds: boolean;
|
|
25
|
+
TComponent?: string;
|
|
26
|
+
VarComponent?: string;
|
|
27
|
+
idPrefix: string;
|
|
28
|
+
idCount: number;
|
|
29
|
+
usedImports: ImportItem[];
|
|
30
|
+
modified: boolean;
|
|
31
|
+
warnings: string[];
|
|
32
|
+
file: string;
|
|
33
|
+
}, isMeaningful: (node: t.Node) => boolean, mark: boolean): WrapResult;
|
|
34
|
+
/**
|
|
35
|
+
* Wraps a JSX element with a <T> component and unique id
|
|
36
|
+
* @param rootNode - The JSX element to wrap
|
|
37
|
+
* @param options - Optional component names for T and Var
|
|
38
|
+
* @param isMeaningful - A function to determine if a node is meaningful
|
|
39
|
+
* @returns The wrapped JSX element
|
|
40
|
+
*/
|
|
41
|
+
export declare function handleJsxElement(rootNode: t.JSXElement | t.JSXFragment, options: {
|
|
42
|
+
createIds: boolean;
|
|
43
|
+
usedImports: ImportItem[];
|
|
44
|
+
TComponent?: string;
|
|
45
|
+
VarComponent?: string;
|
|
46
|
+
idPrefix: string;
|
|
47
|
+
idCount: number;
|
|
48
|
+
modified: boolean;
|
|
49
|
+
warnings: string[];
|
|
50
|
+
file: string;
|
|
51
|
+
}, isMeaningful: (node: t.Node) => boolean): WrapResult;
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.wrapJsxElement = wrapJsxElement;
|
|
37
|
+
exports.handleJsxElement = handleJsxElement;
|
|
38
|
+
const t = __importStar(require("@babel/types"));
|
|
39
|
+
const evaluateJsx_1 = require("./evaluateJsx");
|
|
40
|
+
const warnings_1 = require("../../console/warnings");
|
|
41
|
+
function wrapJsxExpression(node, options, isMeaningful, mark) {
|
|
42
|
+
const expression = t.isParenthesizedExpression(node.expression)
|
|
43
|
+
? node.expression.expression
|
|
44
|
+
: node.expression;
|
|
45
|
+
// Ignore all template literals - they should not be counted as meaningful
|
|
46
|
+
if (t.isTemplateLiteral(expression) && expression.expressions.length > 0) {
|
|
47
|
+
return {
|
|
48
|
+
node,
|
|
49
|
+
hasMeaningfulContent: false,
|
|
50
|
+
wrappedInT: false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Handle both JSX Elements and Fragments
|
|
54
|
+
if (t.isJSXElement(expression) || t.isJSXFragment(expression)) {
|
|
55
|
+
const result = wrapJsxElement(expression, options, isMeaningful, mark);
|
|
56
|
+
// re-wrap the result in a JSXExpressionContainer
|
|
57
|
+
if (t.isParenthesizedExpression(node.expression)) {
|
|
58
|
+
node.expression.expression = result.node;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
node.expression = result.node;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
node,
|
|
65
|
+
hasMeaningfulContent: result.hasMeaningfulContent,
|
|
66
|
+
wrappedInT: result.wrappedInT,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// Handle conditional expressions (ternary)
|
|
70
|
+
else if (t.isConditionalExpression(expression)) {
|
|
71
|
+
const consequent = t.isParenthesizedExpression(expression.consequent)
|
|
72
|
+
? expression.consequent.expression
|
|
73
|
+
: expression.consequent;
|
|
74
|
+
const alternate = t.isParenthesizedExpression(expression.alternate)
|
|
75
|
+
? expression.alternate.expression
|
|
76
|
+
: expression.alternate;
|
|
77
|
+
// Handle consequent
|
|
78
|
+
if (t.isJSXElement(consequent) || t.isJSXFragment(consequent)) {
|
|
79
|
+
const result = handleJsxElement(consequent, options, isMeaningful);
|
|
80
|
+
// Re-insert into parenthesized expression if necessary
|
|
81
|
+
if (t.isParenthesizedExpression(expression.consequent)) {
|
|
82
|
+
expression.consequent.expression = result.node;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
expression.consequent = result.node;
|
|
86
|
+
}
|
|
87
|
+
// Warn about ternary (should use branch instead)
|
|
88
|
+
if (result.wrappedInT && !mark) {
|
|
89
|
+
options.warnings.push((0, warnings_1.warnTernary)(options.file));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else if (t.isConditionalExpression(consequent) ||
|
|
93
|
+
t.isLogicalExpression(consequent)) {
|
|
94
|
+
// Recursively handle nested ternary in consequent
|
|
95
|
+
const consequentResult = wrapJsxExpression(t.jsxExpressionContainer(consequent), options, isMeaningful, mark);
|
|
96
|
+
if (t.isJSXExpressionContainer(consequentResult.node) &&
|
|
97
|
+
t.isExpression(consequentResult.node.expression)) {
|
|
98
|
+
expression.consequent = consequentResult.node.expression;
|
|
99
|
+
// Re-insert into parenthesized expression if necessary
|
|
100
|
+
if (t.isParenthesizedExpression(expression.consequent)) {
|
|
101
|
+
expression.consequent.expression = consequentResult.node.expression;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
expression.consequent = consequentResult.node.expression;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (t.isTemplateLiteral(consequent) &&
|
|
109
|
+
consequent.expressions.length > 0) {
|
|
110
|
+
// Ignore template literals in consequent with expressions (${}), don't wrap them
|
|
111
|
+
// Do nothing
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
if ((0, evaluateJsx_1.isStaticValue)(consequent)) {
|
|
115
|
+
const wrapped = wrapExpressionWithT(consequent, options, false);
|
|
116
|
+
// Re-insert into parenthesized expression if necessary
|
|
117
|
+
if (t.isParenthesizedExpression(expression.consequent)) {
|
|
118
|
+
expression.consequent.expression = wrapped;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
expression.consequent = wrapped;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Handle alternate
|
|
126
|
+
if (t.isJSXElement(alternate) || t.isJSXFragment(alternate)) {
|
|
127
|
+
const result = handleJsxElement(alternate, options, isMeaningful);
|
|
128
|
+
// Re-insert into parenthesized expression if necessary
|
|
129
|
+
if (t.isParenthesizedExpression(expression.alternate)) {
|
|
130
|
+
expression.alternate.expression = result.node;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
expression.alternate = result.node;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (t.isConditionalExpression(alternate) ||
|
|
137
|
+
t.isLogicalExpression(alternate)) {
|
|
138
|
+
// Recursively handle nested ternary in alternate
|
|
139
|
+
const alternateResult = wrapJsxExpression(t.jsxExpressionContainer(alternate), options, isMeaningful, mark);
|
|
140
|
+
if (t.isJSXExpressionContainer(alternateResult.node) &&
|
|
141
|
+
t.isExpression(alternateResult.node.expression)) {
|
|
142
|
+
expression.alternate = alternateResult.node.expression;
|
|
143
|
+
// Re-insert into parenthesized expression if necessary
|
|
144
|
+
if (t.isParenthesizedExpression(expression.alternate)) {
|
|
145
|
+
expression.alternate.expression = alternateResult.node.expression;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
expression.alternate = alternateResult.node.expression;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (t.isTemplateLiteral(alternate) &&
|
|
153
|
+
alternate.expressions.length > 0) {
|
|
154
|
+
// Ignore template literals in alternate with expressions (${}), don't wrap them
|
|
155
|
+
// Do nothing
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
if ((0, evaluateJsx_1.isStaticValue)(alternate)) {
|
|
159
|
+
const wrapped = wrapExpressionWithT(alternate, options, false);
|
|
160
|
+
// Re-insert into parenthesized expression if necessary
|
|
161
|
+
if (t.isParenthesizedExpression(expression.alternate)) {
|
|
162
|
+
expression.alternate.expression = wrapped;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
expression.alternate = wrapped;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Handle logical expressions (&& and ||)
|
|
171
|
+
else if (t.isLogicalExpression(expression)) {
|
|
172
|
+
const left = t.isParenthesizedExpression(expression.left)
|
|
173
|
+
? expression.left.expression
|
|
174
|
+
: expression.left;
|
|
175
|
+
const right = t.isParenthesizedExpression(expression.right)
|
|
176
|
+
? expression.right.expression
|
|
177
|
+
: expression.right;
|
|
178
|
+
if (t.isJSXElement(left) || t.isJSXFragment(left)) {
|
|
179
|
+
const result = handleJsxElement(left, options, isMeaningful);
|
|
180
|
+
// Re-insert into parenthesized expression if necessary
|
|
181
|
+
if (t.isParenthesizedExpression(expression.left)) {
|
|
182
|
+
expression.left.expression = result.node;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
expression.left = result.node;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else if (t.isLogicalExpression(left) || t.isConditionalExpression(left)) {
|
|
189
|
+
// Recursively handle nested logical expressions
|
|
190
|
+
const leftResult = wrapJsxExpression(t.jsxExpressionContainer(left), options, isMeaningful, mark);
|
|
191
|
+
if (t.isJSXExpressionContainer(leftResult.node) &&
|
|
192
|
+
t.isExpression(leftResult.node.expression)) {
|
|
193
|
+
// Re-insert into parenthesized expression if necessary
|
|
194
|
+
if (t.isParenthesizedExpression(expression.left)) {
|
|
195
|
+
expression.left.expression = leftResult.node.expression;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
expression.left = leftResult.node.expression;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
else if (t.isTemplateLiteral(left) && left.expressions.length > 0) {
|
|
203
|
+
// Ignore template literals with expressions (${}) in left side of logical expression
|
|
204
|
+
// Do nothing - don't wrap them
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
if ((0, evaluateJsx_1.isStaticValue)(left) && expression.operator !== '&&') {
|
|
208
|
+
const wrapped = wrapExpressionWithT(left, options, false);
|
|
209
|
+
// Re-insert into parenthesized expression if necessary
|
|
210
|
+
if (t.isParenthesizedExpression(expression.left)) {
|
|
211
|
+
expression.left.expression = wrapped;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
expression.left = wrapped;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (t.isJSXElement(right) || t.isJSXFragment(right)) {
|
|
219
|
+
const result = handleJsxElement(right, options, isMeaningful);
|
|
220
|
+
// Re-insert into parenthesized expression if necessary
|
|
221
|
+
if (t.isParenthesizedExpression(expression.right)) {
|
|
222
|
+
expression.right.expression = result.node;
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
expression.right = result.node;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else if (t.isLogicalExpression(right) ||
|
|
229
|
+
t.isConditionalExpression(right)) {
|
|
230
|
+
// Recursively handle nested logical expressions
|
|
231
|
+
const rightResult = wrapJsxExpression(t.jsxExpressionContainer(right), options, isMeaningful, mark);
|
|
232
|
+
if (t.isJSXExpressionContainer(rightResult.node) &&
|
|
233
|
+
t.isExpression(rightResult.node.expression)) {
|
|
234
|
+
// Re-insert into parenthesized expression if necessary
|
|
235
|
+
if (t.isParenthesizedExpression(expression.right)) {
|
|
236
|
+
expression.right.expression = rightResult.node.expression;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
expression.right = rightResult.node.expression;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else if (t.isTemplateLiteral(right) && right.expressions.length > 0) {
|
|
244
|
+
// Ignore template literals with expressions (${}) in right side of logical expression
|
|
245
|
+
// Do nothing - don't wrap them
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
if ((0, evaluateJsx_1.isStaticValue)(right)) {
|
|
249
|
+
const wrapped = wrapExpressionWithT(right, options, false);
|
|
250
|
+
// Re-insert into parenthesized expression if necessary
|
|
251
|
+
if (t.isParenthesizedExpression(expression.right)) {
|
|
252
|
+
expression.right.expression = wrapped;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
expression.right = wrapped;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
const staticCheck = (0, evaluateJsx_1.isStaticExpression)(expression);
|
|
261
|
+
// If the expression is not static or if it's already wrapped in T,
|
|
262
|
+
// wrap with Var
|
|
263
|
+
if (!staticCheck.isStatic) {
|
|
264
|
+
return {
|
|
265
|
+
node: wrapWithVar(node, options, mark),
|
|
266
|
+
hasMeaningfulContent: false,
|
|
267
|
+
wrappedInT: false,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// If it's a static expression, check if it's meaningful
|
|
271
|
+
return {
|
|
272
|
+
node,
|
|
273
|
+
hasMeaningfulContent: false,
|
|
274
|
+
wrappedInT: false,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Recursively traverse a JSX element and wrap variables with a <Var> component
|
|
279
|
+
* @param node - The JSX element to wrap
|
|
280
|
+
* @param options - Optional component names for T and Var
|
|
281
|
+
* @param isMeaningful - A function to determine if a node is meaningful
|
|
282
|
+
* @returns The wrapped JSX element
|
|
283
|
+
*/
|
|
284
|
+
function wrapJsxElement(node, options, isMeaningful, mark) {
|
|
285
|
+
const TComponentName = options.TComponent || 'T';
|
|
286
|
+
const VarComponentName = options.VarComponent || 'Var';
|
|
287
|
+
// Handle both JSX Elements and Fragments
|
|
288
|
+
if (t.isJSXElement(node) || t.isJSXFragment(node)) {
|
|
289
|
+
// For elements, check if it's already a T or Var component
|
|
290
|
+
if (t.isJSXElement(node)) {
|
|
291
|
+
const name = node.openingElement.name;
|
|
292
|
+
if (t.isJSXIdentifier(name) &&
|
|
293
|
+
(name.name === TComponentName || name.name === VarComponentName)) {
|
|
294
|
+
return {
|
|
295
|
+
node,
|
|
296
|
+
hasMeaningfulContent: false,
|
|
297
|
+
wrappedInT: name.name === TComponentName,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Process children recursively (DFS postorder)
|
|
302
|
+
let hasMeaningfulContent = false;
|
|
303
|
+
let wrappedInT = false;
|
|
304
|
+
const processedChildren = node.children.map((child) => {
|
|
305
|
+
if (t.isJSXElement(child) || t.isJSXFragment(child)) {
|
|
306
|
+
const result = wrapJsxElement(child, options, isMeaningful, mark);
|
|
307
|
+
hasMeaningfulContent =
|
|
308
|
+
hasMeaningfulContent || result.hasMeaningfulContent;
|
|
309
|
+
wrappedInT = wrappedInT || result.wrappedInT;
|
|
310
|
+
return result.node;
|
|
311
|
+
}
|
|
312
|
+
if (t.isJSXExpressionContainer(child)) {
|
|
313
|
+
const result = wrapJsxExpression(child, options, isMeaningful, mark);
|
|
314
|
+
wrappedInT = wrappedInT || result.wrappedInT;
|
|
315
|
+
// Expressions are never meaningful because they will either:
|
|
316
|
+
// 1. be sub-wrapped in a T (if they contain meaningful content)
|
|
317
|
+
// 2. be wrapped in a Var (if they are not static)
|
|
318
|
+
return result.node;
|
|
319
|
+
}
|
|
320
|
+
const isMeaningfulVal = isMeaningful(child);
|
|
321
|
+
if (isMeaningfulVal) {
|
|
322
|
+
hasMeaningfulContent = true;
|
|
323
|
+
}
|
|
324
|
+
return child;
|
|
325
|
+
});
|
|
326
|
+
node.children = processedChildren;
|
|
327
|
+
return {
|
|
328
|
+
node,
|
|
329
|
+
hasMeaningfulContent: hasMeaningfulContent,
|
|
330
|
+
wrappedInT: wrappedInT,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
// For any other node types, return as-is
|
|
334
|
+
return {
|
|
335
|
+
node,
|
|
336
|
+
hasMeaningfulContent: false,
|
|
337
|
+
wrappedInT: false,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Wraps a JSX element with a <T> component and unique id
|
|
342
|
+
* @param rootNode - The JSX element to wrap
|
|
343
|
+
* @param options - Optional component names for T and Var
|
|
344
|
+
* @param isMeaningful - A function to determine if a node is meaningful
|
|
345
|
+
* @returns The wrapped JSX element
|
|
346
|
+
*/
|
|
347
|
+
function handleJsxElement(rootNode, options, isMeaningful) {
|
|
348
|
+
const result = wrapJsxElement(rootNode, options, isMeaningful, true);
|
|
349
|
+
// Only wrap with T at the root level if there's meaningful content
|
|
350
|
+
if (result.hasMeaningfulContent) {
|
|
351
|
+
const output = wrapJsxElement(result.node, options, isMeaningful, false);
|
|
352
|
+
const node = wrapWithT(output.node, options, false);
|
|
353
|
+
return {
|
|
354
|
+
node,
|
|
355
|
+
hasMeaningfulContent: true,
|
|
356
|
+
wrappedInT: true,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
node: result.node,
|
|
361
|
+
hasMeaningfulContent: false,
|
|
362
|
+
wrappedInT: result.wrappedInT,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function wrapWithT(node, options, mark) {
|
|
366
|
+
if (mark) {
|
|
367
|
+
return node;
|
|
368
|
+
}
|
|
369
|
+
const TComponentName = options.TComponent || 'T';
|
|
370
|
+
const uniqueId = `${options.idPrefix}.${options.idCount}`;
|
|
371
|
+
options.modified = true;
|
|
372
|
+
options.idCount++;
|
|
373
|
+
if (!options.usedImports.includes(TComponentName)) {
|
|
374
|
+
options.usedImports.push(TComponentName);
|
|
375
|
+
}
|
|
376
|
+
if (options.createIds) {
|
|
377
|
+
return t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(TComponentName), [t.jsxAttribute(t.jsxIdentifier('id'), t.stringLiteral(uniqueId))], false), t.jsxClosingElement(t.jsxIdentifier(TComponentName)), [node], false);
|
|
378
|
+
}
|
|
379
|
+
return t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(TComponentName), [], false), t.jsxClosingElement(t.jsxIdentifier(TComponentName)), [node], false);
|
|
380
|
+
}
|
|
381
|
+
function wrapExpressionWithT(node, options, mark) {
|
|
382
|
+
if (mark) {
|
|
383
|
+
return node;
|
|
384
|
+
}
|
|
385
|
+
const TComponentName = options.TComponent || 'T';
|
|
386
|
+
const uniqueId = `${options.idPrefix}.${options.idCount}`;
|
|
387
|
+
options.modified = true;
|
|
388
|
+
options.idCount++;
|
|
389
|
+
if (!options.usedImports.includes(TComponentName)) {
|
|
390
|
+
options.usedImports.push(TComponentName);
|
|
391
|
+
}
|
|
392
|
+
if (options.createIds) {
|
|
393
|
+
return t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(TComponentName), [t.jsxAttribute(t.jsxIdentifier('id'), t.stringLiteral(uniqueId))], false), t.jsxClosingElement(t.jsxIdentifier(TComponentName)), [t.jsxExpressionContainer(node)], false);
|
|
394
|
+
}
|
|
395
|
+
return t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(TComponentName), [], false), t.jsxClosingElement(t.jsxIdentifier(TComponentName)), [t.jsxExpressionContainer(node)], false);
|
|
396
|
+
}
|
|
397
|
+
function wrapWithVar(node, options, mark) {
|
|
398
|
+
if (mark) {
|
|
399
|
+
return node;
|
|
400
|
+
}
|
|
401
|
+
const VarComponentName = options.VarComponent || 'Var';
|
|
402
|
+
options.modified = true;
|
|
403
|
+
if (!options.usedImports.includes(VarComponentName)) {
|
|
404
|
+
options.usedImports.push(VarComponentName);
|
|
405
|
+
}
|
|
406
|
+
return t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier(VarComponentName), [], false), t.jsxClosingElement(t.jsxIdentifier(VarComponentName)), [node], false);
|
|
407
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.default = createDictionaryUpdates;
|
|
16
|
+
const react_1 = __importDefault(require("react"));
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
const os_1 = __importDefault(require("os"));
|
|
20
|
+
const esbuild_1 = require("esbuild");
|
|
21
|
+
const flattenDictionary_1 = __importDefault(require("../utils/flattenDictionary"));
|
|
22
|
+
const generaltranslation_1 = require("generaltranslation");
|
|
23
|
+
const loadJSON_1 = __importDefault(require("../../fs/loadJSON"));
|
|
24
|
+
const id_1 = require("generaltranslation/id");
|
|
25
|
+
const getEntryAndMetadata_1 = __importDefault(require("../utils/getEntryAndMetadata"));
|
|
26
|
+
function createDictionaryUpdates(options, esbuildConfig) {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
let dictionary;
|
|
29
|
+
// ---- HANDLE JSON STRING DICTIONARY ----- //
|
|
30
|
+
if (options.dictionary.endsWith('.json')) {
|
|
31
|
+
dictionary = (0, flattenDictionary_1.default)((0, loadJSON_1.default)(options.dictionary) || {});
|
|
32
|
+
}
|
|
33
|
+
// ----- HANDLE REACT DICTIONARY ---- //
|
|
34
|
+
else {
|
|
35
|
+
const result = yield (0, esbuild_1.build)(Object.assign(Object.assign({}, esbuildConfig), { entryPoints: [options.dictionary], write: false }));
|
|
36
|
+
const bundledCode = result.outputFiles[0].text;
|
|
37
|
+
const tempFilePath = path_1.default.join(os_1.default.tmpdir(), 'bundled-dictionary.js');
|
|
38
|
+
fs_1.default.writeFileSync(tempFilePath, bundledCode);
|
|
39
|
+
globalThis.React = react_1.default;
|
|
40
|
+
// Load the module using require
|
|
41
|
+
let dictionaryModule;
|
|
42
|
+
try {
|
|
43
|
+
dictionaryModule = require(tempFilePath);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error(`Failed to load the bundled dictionary code:`, error);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
// Clean up the temporary file
|
|
51
|
+
fs_1.default.unlinkSync(tempFilePath);
|
|
52
|
+
}
|
|
53
|
+
dictionary = (0, flattenDictionary_1.default)(dictionaryModule.default ||
|
|
54
|
+
dictionaryModule.dictionary ||
|
|
55
|
+
dictionaryModule);
|
|
56
|
+
}
|
|
57
|
+
if (!Object.keys(dictionary).length)
|
|
58
|
+
throw new Error(`Dictionary filepath provided: "${options.dictionary}", but no entries found.`);
|
|
59
|
+
// ----- CREATE PARTIAL UPDATES ----- //
|
|
60
|
+
let updates = [];
|
|
61
|
+
for (const id of Object.keys(dictionary)) {
|
|
62
|
+
let { entry, metadata: props, // context, etc.
|
|
63
|
+
} = (0, getEntryAndMetadata_1.default)(dictionary[id]);
|
|
64
|
+
const source = (0, generaltranslation_1.splitStringToContent)(entry);
|
|
65
|
+
const context = props === null || props === void 0 ? void 0 : props.context;
|
|
66
|
+
const metadata = Object.assign(Object.assign({ id }, (context && { context })), {
|
|
67
|
+
// This hash isn't actually used by the GT API, just for consistency sake
|
|
68
|
+
hash: (0, id_1.hashJsxChildren)(Object.assign(Object.assign({ source }, (context && { context })), (id && { id }))) });
|
|
69
|
+
updates.push({
|
|
70
|
+
type: 'content',
|
|
71
|
+
source,
|
|
72
|
+
metadata,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return updates;
|
|
76
|
+
});
|
|
77
|
+
}
|