gtx-cli 1.0.0-alpha.2 → 1.0.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.
- package/dist/cli/next.js +2 -2
- package/dist/cli/react.js +20 -14
- package/dist/formats/json/translate.js +1 -1
- package/dist/fs/findFilepath.js +8 -3
- package/dist/react/jsx/parse/parseStringFunction.js +1 -1
- package/dist/react/jsx/utils/parseJsx.js +1 -1
- package/dist/react/jsx/utils/parseStringFunction.js +1 -1
- package/dist/react/parse/createDictionaryUpdates.js +2 -2
- package/dist/react/parse/createInlineUpdates.js +1 -1
- package/dist/types/index.d.ts +3 -3
- package/package.json +4 -4
- package/dist/react/updates/createDictionaryUpdates.d.ts +0 -5
- package/dist/react/updates/createDictionaryUpdates.js +0 -76
- package/dist/react/updates/createInlineUpdates.d.ts +0 -5
- package/dist/react/updates/createInlineUpdates.js +0 -141
- package/dist/react/updates/scanForContent.d.ts +0 -13
- package/dist/react/updates/scanForContent.js +0 -200
package/dist/cli/next.js
CHANGED
|
@@ -19,8 +19,8 @@ const prompts_1 = require("@inquirer/prompts");
|
|
|
19
19
|
const postProcess_1 = require("../hooks/postProcess");
|
|
20
20
|
const findFilepath_1 = __importDefault(require("../fs/findFilepath"));
|
|
21
21
|
const scanForContent_1 = __importDefault(require("../next/parse/scanForContent"));
|
|
22
|
-
const createDictionaryUpdates_1 = __importDefault(require("../react/
|
|
23
|
-
const createInlineUpdates_1 = __importDefault(require("../react/
|
|
22
|
+
const createDictionaryUpdates_1 = __importDefault(require("../react/parse/createDictionaryUpdates"));
|
|
23
|
+
const createInlineUpdates_1 = __importDefault(require("../react/parse/createInlineUpdates"));
|
|
24
24
|
const handleInitGT_1 = __importDefault(require("../next/parse/handleInitGT"));
|
|
25
25
|
const react_1 = require("./react");
|
|
26
26
|
const generateSettings_1 = require("../config/generateSettings");
|
package/dist/cli/react.js
CHANGED
|
@@ -121,14 +121,7 @@ class ReactCLI extends base_1.BaseCLI {
|
|
|
121
121
|
.description('Generate a translation file for the source locale. The -t flag must be provided. This command should be used if you are handling your own translations.')
|
|
122
122
|
.option('--src <paths...>', "Filepath to directory containing the app's source code, by default ./src || ./app || ./pages || ./components", (0, findFilepath_1.findFilepaths)(['./src', './app', './pages', './components']))
|
|
123
123
|
.option('--tsconfig, --jsconfig <path>', 'Path to jsconfig or tsconfig file', (0, findFilepath_1.default)(['./tsconfig.json', './jsconfig.json']))
|
|
124
|
-
.option('--dictionary <path>', 'Path to dictionary file'
|
|
125
|
-
'./dictionary.js',
|
|
126
|
-
'./src/dictionary.js',
|
|
127
|
-
'./dictionary.json',
|
|
128
|
-
'./src/dictionary.json',
|
|
129
|
-
'./dictionary.ts',
|
|
130
|
-
'./src/dictionary.ts',
|
|
131
|
-
]))
|
|
124
|
+
.option('--dictionary <path>', 'Path to dictionary file')
|
|
132
125
|
.option('--default-language, --default-locale <locale>', 'Source locale (e.g., en)', 'en')
|
|
133
126
|
.option('--inline', 'Include inline <T> tags in addition to dictionary file', true)
|
|
134
127
|
.option('--ignore-errors', 'Ignore errors encountered while scanning for <T> tags', false)
|
|
@@ -157,8 +150,19 @@ class ReactCLI extends base_1.BaseCLI {
|
|
|
157
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
158
151
|
(0, console_1.displayAsciiTitle)();
|
|
159
152
|
(0, console_1.displayInitializingText)();
|
|
160
|
-
const { updates, errors } = yield this.createUpdates(options);
|
|
161
153
|
const settings = (0, generateSettings_1.generateSettings)(options);
|
|
154
|
+
options = Object.assign(Object.assign({}, options), settings);
|
|
155
|
+
if (!options.dictionary) {
|
|
156
|
+
options.dictionary = (0, findFilepath_1.default)([
|
|
157
|
+
'./dictionary.js',
|
|
158
|
+
'./src/dictionary.js',
|
|
159
|
+
'./dictionary.json',
|
|
160
|
+
'./src/dictionary.json',
|
|
161
|
+
'./dictionary.ts',
|
|
162
|
+
'./src/dictionary.ts',
|
|
163
|
+
]);
|
|
164
|
+
}
|
|
165
|
+
const { updates, errors } = yield this.createUpdates(options);
|
|
162
166
|
if (errors.length > 0) {
|
|
163
167
|
if (options.ignoreErrors) {
|
|
164
168
|
console.log(chalk_1.default.red(`CLI tool encountered errors while scanning for ${chalk_1.default.green('<T>')} tags.\n`));
|
|
@@ -438,11 +442,13 @@ class ReactCLI extends base_1.BaseCLI {
|
|
|
438
442
|
// {defaultLocale}.json file exists in the translationsDir, and use that as a source
|
|
439
443
|
// instead
|
|
440
444
|
const sourceFile = (0, findFilepath_1.findFileInDir)(options.translationsDir, `${options.defaultLocale}.json`);
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
445
|
+
if (sourceFile) {
|
|
446
|
+
options.dictionary = sourceFile;
|
|
447
|
+
updates = [
|
|
448
|
+
...updates,
|
|
449
|
+
...(yield this.createDictionaryUpdates(options, (0, createESBuildConfig_1.default)({}))),
|
|
450
|
+
];
|
|
451
|
+
}
|
|
446
452
|
}
|
|
447
453
|
// Scan through project for <T> tags
|
|
448
454
|
if (options.inline) {
|
package/dist/fs/findFilepath.js
CHANGED
|
@@ -58,7 +58,7 @@ function getRelativePath(file, srcDirectory) {
|
|
|
58
58
|
function findFile(filePattern, file) {
|
|
59
59
|
// Handle wildcard pattern by replacing the wildcard with the file parameter
|
|
60
60
|
const resolvedPath = filePattern.replace(/\*/, file);
|
|
61
|
-
if (fs_1.default.existsSync(resolvedPath)) {
|
|
61
|
+
if (fs_1.default.existsSync(resolvedPath) && fs_1.default.statSync(resolvedPath).isFile()) {
|
|
62
62
|
return fs_1.default.readFileSync(resolvedPath, 'utf8');
|
|
63
63
|
}
|
|
64
64
|
return '';
|
|
@@ -71,8 +71,13 @@ function findFile(filePattern, file) {
|
|
|
71
71
|
*/
|
|
72
72
|
function findFileInDir(dir, file) {
|
|
73
73
|
const resolvedPath = path_1.default.join(dir, file);
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
try {
|
|
75
|
+
if (fs_1.default.existsSync(resolvedPath)) {
|
|
76
|
+
return fs_1.default.readFileSync(resolvedPath, 'utf8');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error(error);
|
|
76
81
|
}
|
|
77
82
|
return '';
|
|
78
83
|
}
|
|
@@ -228,7 +228,7 @@ function parseJSXElement(importAliases, node, updates, errors, file) {
|
|
|
228
228
|
// <T> is valid here
|
|
229
229
|
// displayFoundTMessage(file, id);
|
|
230
230
|
updates.push({
|
|
231
|
-
|
|
231
|
+
dataFormat: 'JSX',
|
|
232
232
|
source: componentObj.tree,
|
|
233
233
|
metadata: componentObj.props,
|
|
234
234
|
});
|
|
@@ -65,9 +65,9 @@ function createDictionaryUpdates(options, esbuildConfig) {
|
|
|
65
65
|
const context = props === null || props === void 0 ? void 0 : props.context;
|
|
66
66
|
const metadata = Object.assign(Object.assign({ id }, (context && { context })), {
|
|
67
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 }))) });
|
|
68
|
+
hash: (0, id_1.hashJsxChildren)(Object.assign(Object.assign(Object.assign({ source }, (context && { context })), (id && { id })), { dataFormat: 'JSX' })) });
|
|
69
69
|
updates.push({
|
|
70
|
-
|
|
70
|
+
dataFormat: 'JSX',
|
|
71
71
|
source,
|
|
72
72
|
metadata,
|
|
73
73
|
});
|
|
@@ -133,7 +133,7 @@ function createInlineUpdates(options, pkg) {
|
|
|
133
133
|
// Post-process to add a hash to each update
|
|
134
134
|
yield Promise.all(updates.map((update) => __awaiter(this, void 0, void 0, function* () {
|
|
135
135
|
const context = update.metadata.context;
|
|
136
|
-
const hash = (0, id_1.hashJsxChildren)(Object.assign(Object.assign({ source: update.source }, (context && { context })), (update.metadata.id && { id: update.metadata.id })));
|
|
136
|
+
const hash = (0, id_1.hashJsxChildren)(Object.assign(Object.assign(Object.assign({ source: update.source }, (context && { context })), (update.metadata.id && { id: update.metadata.id })), { dataFormat: 'JSX' }));
|
|
137
137
|
update.metadata.hash = hash;
|
|
138
138
|
})));
|
|
139
139
|
return { updates, errors };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,13 +2,13 @@ import { JsxChildren } from 'generaltranslation/internal';
|
|
|
2
2
|
export type Updates = ({
|
|
3
3
|
metadata: Record<string, any>;
|
|
4
4
|
} & ({
|
|
5
|
-
|
|
5
|
+
dataFormat: 'JSX';
|
|
6
6
|
source: JsxChildren;
|
|
7
7
|
} | {
|
|
8
|
-
|
|
8
|
+
dataFormat: 'ICU';
|
|
9
9
|
source: string;
|
|
10
10
|
} | {
|
|
11
|
-
|
|
11
|
+
dataFormat: 'I18NEXT';
|
|
12
12
|
source: string;
|
|
13
13
|
}))[];
|
|
14
14
|
export type Options = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gtx-cli",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"commander": "^12.1.0",
|
|
53
53
|
"dotenv": "^16.4.5",
|
|
54
54
|
"esbuild": "^0.23.1",
|
|
55
|
-
"generaltranslation": "^6.2.1
|
|
56
|
-
"
|
|
57
|
-
"
|
|
55
|
+
"generaltranslation": "^6.2.1",
|
|
56
|
+
"ora": "^8.2.0",
|
|
57
|
+
"yaml": "^2.7.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@biomejs/biome": "1.9.4",
|
|
@@ -1,76 +0,0 @@
|
|
|
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 internal_1 = require("gt-react/internal");
|
|
22
|
-
const generaltranslation_1 = require("generaltranslation");
|
|
23
|
-
const loadJSON_1 = __importDefault(require("../../fs/loadJSON"));
|
|
24
|
-
const id_1 = require("generaltranslation/id");
|
|
25
|
-
function createDictionaryUpdates(options, esbuildConfig) {
|
|
26
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
-
let dictionary;
|
|
28
|
-
// ---- HANDLE JSON STRING DICTIONARY ----- //
|
|
29
|
-
if (options.dictionary.endsWith('.json')) {
|
|
30
|
-
dictionary = (0, internal_1.flattenDictionary)((0, loadJSON_1.default)(options.dictionary) || {});
|
|
31
|
-
}
|
|
32
|
-
// ----- HANDLE REACT DICTIONARY ---- //
|
|
33
|
-
else {
|
|
34
|
-
const result = yield (0, esbuild_1.build)(Object.assign(Object.assign({}, esbuildConfig), { entryPoints: [options.dictionary], write: false }));
|
|
35
|
-
const bundledCode = result.outputFiles[0].text;
|
|
36
|
-
const tempFilePath = path_1.default.join(os_1.default.tmpdir(), 'bundled-dictionary.js');
|
|
37
|
-
fs_1.default.writeFileSync(tempFilePath, bundledCode);
|
|
38
|
-
globalThis.React = react_1.default;
|
|
39
|
-
// Load the module using require
|
|
40
|
-
let dictionaryModule;
|
|
41
|
-
try {
|
|
42
|
-
dictionaryModule = require(tempFilePath);
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
console.error(`Failed to load the bundled dictionary code:`, error);
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
finally {
|
|
49
|
-
// Clean up the temporary file
|
|
50
|
-
fs_1.default.unlinkSync(tempFilePath);
|
|
51
|
-
}
|
|
52
|
-
dictionary = (0, internal_1.flattenDictionary)(dictionaryModule.default ||
|
|
53
|
-
dictionaryModule.dictionary ||
|
|
54
|
-
dictionaryModule);
|
|
55
|
-
}
|
|
56
|
-
if (!Object.keys(dictionary).length)
|
|
57
|
-
throw new Error(`Dictionary filepath provided: "${options.dictionary}", but no entries found.`);
|
|
58
|
-
// ----- CREATE PARTIAL UPDATES ----- //
|
|
59
|
-
let updates = [];
|
|
60
|
-
for (const id of Object.keys(dictionary)) {
|
|
61
|
-
let { entry, metadata: props, // context, etc.
|
|
62
|
-
} = (0, internal_1.getEntryAndMetadata)(dictionary[id]);
|
|
63
|
-
const source = (0, generaltranslation_1.splitStringToContent)(entry);
|
|
64
|
-
const context = props === null || props === void 0 ? void 0 : props.context;
|
|
65
|
-
const metadata = Object.assign(Object.assign({ id }, (context && { context })), {
|
|
66
|
-
// This hash isn't actually used by the GT API, just for consistency sake
|
|
67
|
-
hash: (0, id_1.hashJsxChildren)(Object.assign(Object.assign({ source }, (context && { context })), (id && { id }))) });
|
|
68
|
-
updates.push({
|
|
69
|
-
type: 'JSX',
|
|
70
|
-
source,
|
|
71
|
-
metadata,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
return updates;
|
|
75
|
-
});
|
|
76
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
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 = createInlineUpdates;
|
|
16
|
-
const fs_1 = __importDefault(require("fs"));
|
|
17
|
-
const path_1 = __importDefault(require("path"));
|
|
18
|
-
const parser_1 = require("@babel/parser");
|
|
19
|
-
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
20
|
-
const id_1 = require("generaltranslation/id");
|
|
21
|
-
const parseJsx_1 = require("../jsx/utils/parseJsx");
|
|
22
|
-
const parseStringFunction_1 = require("../jsx/utils/parseStringFunction");
|
|
23
|
-
const parseAst_1 = require("../jsx/utils/parseAst");
|
|
24
|
-
function createInlineUpdates(options, pkg) {
|
|
25
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const updates = [];
|
|
27
|
-
const errors = [];
|
|
28
|
-
// Use the provided app directory or default to the current directory
|
|
29
|
-
const srcDirectory = options.src || ['./'];
|
|
30
|
-
// Define the file extensions to look for
|
|
31
|
-
const extensions = ['.js', '.jsx', '.tsx'];
|
|
32
|
-
/**
|
|
33
|
-
* Recursively scan the directory and collect all files with the specified extensions,
|
|
34
|
-
* excluding files or directories that start with a dot (.)
|
|
35
|
-
* @param dir - The directory to scan
|
|
36
|
-
* @returns An array of file paths
|
|
37
|
-
*/
|
|
38
|
-
function getFiles(dir) {
|
|
39
|
-
let files = [];
|
|
40
|
-
const items = fs_1.default.readdirSync(dir);
|
|
41
|
-
for (const item of items) {
|
|
42
|
-
// Skip hidden files and directories
|
|
43
|
-
if (item.startsWith('.'))
|
|
44
|
-
continue;
|
|
45
|
-
const fullPath = path_1.default.join(dir, item);
|
|
46
|
-
const stat = fs_1.default.statSync(fullPath);
|
|
47
|
-
if (stat.isDirectory()) {
|
|
48
|
-
// Recursively scan subdirectories
|
|
49
|
-
files = files.concat(getFiles(fullPath));
|
|
50
|
-
}
|
|
51
|
-
else if (extensions.includes(path_1.default.extname(item))) {
|
|
52
|
-
// Add files with the specified extensions
|
|
53
|
-
files.push(fullPath);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return files;
|
|
57
|
-
}
|
|
58
|
-
const files = srcDirectory.flatMap((dir) => getFiles(dir));
|
|
59
|
-
for (const file of files) {
|
|
60
|
-
const code = fs_1.default.readFileSync(file, 'utf8');
|
|
61
|
-
let ast;
|
|
62
|
-
try {
|
|
63
|
-
ast = (0, parser_1.parse)(code, {
|
|
64
|
-
sourceType: 'module',
|
|
65
|
-
plugins: ['jsx', 'typescript'],
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
console.error(`Error parsing file ${file}:`, error);
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const translationFuncs = [
|
|
73
|
-
'useGT',
|
|
74
|
-
'getGT',
|
|
75
|
-
'T',
|
|
76
|
-
'Var',
|
|
77
|
-
'DateTime',
|
|
78
|
-
'Currency',
|
|
79
|
-
'Num',
|
|
80
|
-
'Branch',
|
|
81
|
-
'Plural',
|
|
82
|
-
];
|
|
83
|
-
const importAliases = {};
|
|
84
|
-
// handle imports & alias & handle string functions
|
|
85
|
-
(0, traverse_1.default)(ast, {
|
|
86
|
-
ImportDeclaration(path) {
|
|
87
|
-
if (path.node.source.value.startsWith(pkg)) {
|
|
88
|
-
const importName = (0, parseAst_1.extractImportName)(path.node, pkg, translationFuncs);
|
|
89
|
-
for (const name of importName) {
|
|
90
|
-
if (name.original === 'useGT' || name.original === 'getGT') {
|
|
91
|
-
(0, parseStringFunction_1.parseStrings)(name.local, path, updates, errors, file);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
importAliases[name.local] = name.original;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
VariableDeclarator(path) {
|
|
100
|
-
var _a;
|
|
101
|
-
// Check if the init is a require call
|
|
102
|
-
if (((_a = path.node.init) === null || _a === void 0 ? void 0 : _a.type) === 'CallExpression' &&
|
|
103
|
-
path.node.init.callee.type === 'Identifier' &&
|
|
104
|
-
path.node.init.callee.name === 'require') {
|
|
105
|
-
// Check if it's requiring our package
|
|
106
|
-
const args = path.node.init.arguments;
|
|
107
|
-
if (args.length === 1 &&
|
|
108
|
-
args[0].type === 'StringLiteral' &&
|
|
109
|
-
args[0].value.startsWith(pkg)) {
|
|
110
|
-
const parentPath = path.parentPath;
|
|
111
|
-
if (parentPath.isVariableDeclaration()) {
|
|
112
|
-
const importName = (0, parseAst_1.extractImportName)(parentPath.node, pkg, translationFuncs);
|
|
113
|
-
for (const name of importName) {
|
|
114
|
-
if (name.original === 'useGT' || name.original === 'getGT') {
|
|
115
|
-
(0, parseStringFunction_1.parseStrings)(name.local, parentPath, updates, errors, file);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
importAliases[name.local] = name.original;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
// Parse <T> components
|
|
127
|
-
(0, traverse_1.default)(ast, {
|
|
128
|
-
JSXElement(path) {
|
|
129
|
-
(0, parseJsx_1.parseJSXElement)(importAliases, path.node, updates, errors, file);
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
// Post-process to add a hash to each update
|
|
134
|
-
yield Promise.all(updates.map((update) => __awaiter(this, void 0, void 0, function* () {
|
|
135
|
-
const context = update.metadata.context;
|
|
136
|
-
const hash = (0, id_1.hashJsxChildren)(Object.assign(Object.assign({ source: update.source }, (context && { context })), (update.metadata.id && { id: update.metadata.id })));
|
|
137
|
-
update.metadata.hash = hash;
|
|
138
|
-
})));
|
|
139
|
-
return { updates, errors };
|
|
140
|
-
});
|
|
141
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { SupportedFrameworks, WrapOptions } from '../../types';
|
|
2
|
-
/**
|
|
3
|
-
* Wraps all JSX elements in the src directory with a <T> tag, with unique ids.
|
|
4
|
-
* - Ignores pure strings
|
|
5
|
-
*
|
|
6
|
-
* @param options - The options object
|
|
7
|
-
* @returns An object containing the updates and errors
|
|
8
|
-
*/
|
|
9
|
-
export default function scanForContent(options: WrapOptions, pkg: 'gt-next' | 'gt-react', framework: SupportedFrameworks): Promise<{
|
|
10
|
-
errors: string[];
|
|
11
|
-
filesUpdated: string[];
|
|
12
|
-
warnings: string[];
|
|
13
|
-
}>;
|
|
@@ -1,200 +0,0 @@
|
|
|
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
-
};
|
|
47
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.default = scanForContent;
|
|
49
|
-
const fs_1 = __importDefault(require("fs"));
|
|
50
|
-
const path_1 = __importDefault(require("path"));
|
|
51
|
-
const t = __importStar(require("@babel/types"));
|
|
52
|
-
const parser_1 = require("@babel/parser");
|
|
53
|
-
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
54
|
-
const generator_1 = __importDefault(require("@babel/generator"));
|
|
55
|
-
const findJsxFilepath_1 = require("../../fs/findJsxFilepath");
|
|
56
|
-
const evaluateJsx_1 = require("../jsx/evaluateJsx");
|
|
57
|
-
const wrapJsx_1 = require("../jsx/wrapJsx");
|
|
58
|
-
const findFilepath_1 = require("../../fs/findFilepath");
|
|
59
|
-
const parseAst_1 = require("../jsx/utils/parseAst");
|
|
60
|
-
const IMPORT_MAP = {
|
|
61
|
-
T: { name: 'T', source: 'gt-react' },
|
|
62
|
-
Var: { name: 'Var', source: 'gt-react' },
|
|
63
|
-
GTT: { name: 'T', source: 'gt-react' },
|
|
64
|
-
GTVar: { name: 'Var', source: 'gt-react' },
|
|
65
|
-
GTProvider: { name: 'GTProvider', source: 'gt-react' },
|
|
66
|
-
// getLocale: { name: 'getLocale', source: 'gt-react/server' },
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* Wraps all JSX elements in the src directory with a <T> tag, with unique ids.
|
|
70
|
-
* - Ignores pure strings
|
|
71
|
-
*
|
|
72
|
-
* @param options - The options object
|
|
73
|
-
* @returns An object containing the updates and errors
|
|
74
|
-
*/
|
|
75
|
-
function scanForContent(options, pkg, framework) {
|
|
76
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
-
const errors = [];
|
|
78
|
-
const warnings = [];
|
|
79
|
-
const srcDirectory = options.src || ['./'];
|
|
80
|
-
const files = srcDirectory.flatMap((dir) => (0, findJsxFilepath_1.getFiles)(dir));
|
|
81
|
-
const filesUpdated = [];
|
|
82
|
-
for (const file of files) {
|
|
83
|
-
const baseFileName = path_1.default.basename(file);
|
|
84
|
-
const configPath = path_1.default.relative(path_1.default.dirname(file), path_1.default.resolve(process.cwd(), options.config));
|
|
85
|
-
// Ensure the path starts with ./ or ../
|
|
86
|
-
const normalizedConfigPath = configPath.startsWith('.')
|
|
87
|
-
? configPath
|
|
88
|
-
: './' + configPath;
|
|
89
|
-
const code = fs_1.default.readFileSync(file, 'utf8');
|
|
90
|
-
// Create relative path from src directory and remove extension
|
|
91
|
-
const relativePath = (0, findFilepath_1.getRelativePath)(file, srcDirectory[0]);
|
|
92
|
-
let ast;
|
|
93
|
-
try {
|
|
94
|
-
ast = (0, parser_1.parse)(code, {
|
|
95
|
-
sourceType: 'module',
|
|
96
|
-
plugins: ['jsx', 'typescript'],
|
|
97
|
-
tokens: true,
|
|
98
|
-
createParenthesizedExpressions: true,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
console.error(`Error parsing file ${file}:`, error);
|
|
103
|
-
errors.push(`Failed to parse ${file}: ${error}`);
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
let modified = false;
|
|
107
|
-
let usedImports = [];
|
|
108
|
-
let { importAlias, initialImports } = (0, parseAst_1.generateImportMap)(ast, pkg);
|
|
109
|
-
// If the file already has a T import, skip processing it
|
|
110
|
-
if (initialImports.includes(IMPORT_MAP.T.name)) {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
let globalId = 0;
|
|
114
|
-
(0, traverse_1.default)(ast, {
|
|
115
|
-
JSXElement(path) {
|
|
116
|
-
var _a;
|
|
117
|
-
if (framework === 'next-pages' &&
|
|
118
|
-
options.addGTProvider &&
|
|
119
|
-
(baseFileName === '_app.tsx' || baseFileName === '_app.jsx')) {
|
|
120
|
-
// Check if this is the top-level JSX element in the default export
|
|
121
|
-
let isDefaultExport = false;
|
|
122
|
-
let currentPath = path;
|
|
123
|
-
// Check if GTProvider already exists in the ancestors
|
|
124
|
-
let hasGTProvider = false;
|
|
125
|
-
while (currentPath.parentPath) {
|
|
126
|
-
if (t.isJSXElement(currentPath.node) &&
|
|
127
|
-
t.isJSXIdentifier(currentPath.node.openingElement.name) &&
|
|
128
|
-
currentPath.node.openingElement.name.name === 'GTProvider') {
|
|
129
|
-
hasGTProvider = true;
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
if (t.isExportDefaultDeclaration(currentPath.parentPath.node)) {
|
|
133
|
-
isDefaultExport = true;
|
|
134
|
-
}
|
|
135
|
-
currentPath = currentPath.parentPath;
|
|
136
|
-
}
|
|
137
|
-
if (isDefaultExport && !hasGTProvider) {
|
|
138
|
-
// Wrap the JSX element with GTProvider
|
|
139
|
-
const gtProviderJsx = t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier('GTProvider'), [t.jsxSpreadAttribute(t.identifier('gtConfig'))], false), t.jsxClosingElement(t.jsxIdentifier('GTProvider')), [path.node]);
|
|
140
|
-
path.replaceWith(gtProviderJsx);
|
|
141
|
-
usedImports.push('GTProvider');
|
|
142
|
-
usedImports.push({
|
|
143
|
-
local: 'gtConfig',
|
|
144
|
-
imported: 'default',
|
|
145
|
-
source: normalizedConfigPath,
|
|
146
|
-
});
|
|
147
|
-
modified = true;
|
|
148
|
-
path.skip();
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// Check if this JSX element has any JSX element ancestors
|
|
153
|
-
let currentPath = path;
|
|
154
|
-
if (t.isJSXElement((_a = currentPath.parentPath) === null || _a === void 0 ? void 0 : _a.node)) {
|
|
155
|
-
// If we found a JSX parent, skip processing this node
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
// At this point, we're only processing top-level JSX elements
|
|
159
|
-
const opts = Object.assign(Object.assign({}, importAlias), { idPrefix: relativePath, idCount: globalId, usedImports, modified: false, createIds: !options.disableIds, warnings,
|
|
160
|
-
file });
|
|
161
|
-
const wrapped = (0, wrapJsx_1.handleJsxElement)(path.node, opts, evaluateJsx_1.isMeaningful);
|
|
162
|
-
path.replaceWith(wrapped.node);
|
|
163
|
-
// Update global counters
|
|
164
|
-
modified = modified || opts.modified;
|
|
165
|
-
globalId = opts.idCount;
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
if (!modified)
|
|
169
|
-
continue;
|
|
170
|
-
let needsImport = usedImports.filter((imp) => typeof imp === 'string'
|
|
171
|
-
? !initialImports.includes(imp)
|
|
172
|
-
: !initialImports.includes(imp.local));
|
|
173
|
-
if (needsImport.length > 0) {
|
|
174
|
-
(0, parseAst_1.createImports)(ast, needsImport, IMPORT_MAP);
|
|
175
|
-
}
|
|
176
|
-
try {
|
|
177
|
-
const output = (0, generator_1.default)(ast, {
|
|
178
|
-
retainLines: true,
|
|
179
|
-
retainFunctionParens: true,
|
|
180
|
-
comments: true,
|
|
181
|
-
compact: 'auto',
|
|
182
|
-
}, code);
|
|
183
|
-
// Post-process the output to fix import spacing
|
|
184
|
-
let processedCode = output.code;
|
|
185
|
-
if (needsImport.length > 0) {
|
|
186
|
-
// Add newline after the comment only
|
|
187
|
-
processedCode = processedCode.replace(/((?:import\s*{\s*(?:T|GTT|Var|GTVar|GTProvider|getLocale)(?:\s*,\s*(?:T|GTT|Var|GTVar|GTProvider|getLocale))*\s*}\s*from|const\s*{\s*(?:T|GTT|Var|GTVar|GTProvider|getLocale)(?:\s*,\s*(?:T|GTT|Var|GTVar|GTProvider|getLocale))*\s*}\s*=\s*require)\s*['"]gt-(?:next|react)(?:\/server)?['"];?)/, '\n$1\n');
|
|
188
|
-
}
|
|
189
|
-
// Write the modified code back to the file
|
|
190
|
-
fs_1.default.writeFileSync(file, processedCode);
|
|
191
|
-
filesUpdated.push(file);
|
|
192
|
-
}
|
|
193
|
-
catch (error) {
|
|
194
|
-
console.error(`Error writing file ${file}:`, error);
|
|
195
|
-
errors.push(`Failed to write ${file}: ${error}`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
return { errors, filesUpdated, warnings };
|
|
199
|
-
});
|
|
200
|
-
}
|