@uxf/scripts 10.0.0-beta.45 → 10.0.0-beta.46
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxf/scripts",
|
|
3
|
-
"version": "10.0.0-beta.
|
|
3
|
+
"version": "10.0.0-beta.46",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@commitlint/parse": "^12.1.1",
|
|
27
27
|
"axios": "^0.20.0",
|
|
28
28
|
"cheerio": "^1.0.0-rc.3",
|
|
29
|
+
"madge": "6.1.0",
|
|
29
30
|
"moment": "^2.29.0",
|
|
30
31
|
"yargs": "^16.0.3"
|
|
31
32
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const { argv, env } = require("process");
|
|
2
|
+
|
|
3
|
+
module.exports = async () => {
|
|
4
|
+
const cli = require("yargs")
|
|
5
|
+
.command("$0", "UXF i18n namespaces generator", (yargs) => {
|
|
6
|
+
yargs.demandCommand(0, 0).usage(`UXF i18n namespaces generator
|
|
7
|
+
Usage:
|
|
8
|
+
uxf-i18n-namespaces-gen [options]`);
|
|
9
|
+
})
|
|
10
|
+
.option("h", { alias: "help", group: "Options" })
|
|
11
|
+
.strict(false)
|
|
12
|
+
.exitProcess(false);
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const { help, ...options } = cli.parse(argv.slice(2));
|
|
16
|
+
|
|
17
|
+
if (Boolean(help)) {
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await require("./index");
|
|
22
|
+
} catch (e) {
|
|
23
|
+
console.error(e);
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const madge = require("madge");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const { readFileSync, readdirSync, writeFileSync } = require("fs");
|
|
6
|
+
const join = require("node:path").join;
|
|
7
|
+
|
|
8
|
+
const INCLUDE = ["src"];
|
|
9
|
+
const EXCLUDE = [];
|
|
10
|
+
|
|
11
|
+
const FILE_EXTENSIONS = ["ts", "tsx"];
|
|
12
|
+
|
|
13
|
+
const TS_CONFIG_PATH = path.resolve(process.cwd(), "tsconfig.json");
|
|
14
|
+
const TS_CONFIG = fs.existsSync(TS_CONFIG_PATH) ? TS_CONFIG_PATH : undefined;
|
|
15
|
+
|
|
16
|
+
const result = { "*": ["common"] };
|
|
17
|
+
|
|
18
|
+
function removeTrailingSlash(str) {
|
|
19
|
+
return str.replace(/\/$/, "");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const walk = (dirPath) => {
|
|
23
|
+
const dir = readdirSync(dirPath, { withFileTypes: true });
|
|
24
|
+
|
|
25
|
+
return dir.map((entry) => {
|
|
26
|
+
const childPath = join(dirPath, entry.name);
|
|
27
|
+
|
|
28
|
+
return entry.isDirectory() ? walk(childPath) : childPath;
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const findTFunctionNamespaces = (pageContent) => {
|
|
33
|
+
const regex = /\bt\("([^:]+):[^"]+"\)/g;
|
|
34
|
+
const matches = pageContent.matchAll(regex);
|
|
35
|
+
const namespaces = new Set();
|
|
36
|
+
|
|
37
|
+
for (const match of matches) {
|
|
38
|
+
const translationKey = match[0];
|
|
39
|
+
const separatorIndex = translationKey.indexOf(":");
|
|
40
|
+
if (separatorIndex !== -1) {
|
|
41
|
+
const namespace = translationKey.substring(3, separatorIndex);
|
|
42
|
+
namespaces.add(namespace);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return Array.from(namespaces);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const findTransComponentNamespaces = (pageContent) => {
|
|
50
|
+
const regex = /<Trans[^>]*?i18nKey=(['"])(.*?)\1[^>]*\/>/g;
|
|
51
|
+
const matches = pageContent.matchAll(regex);
|
|
52
|
+
const namespaces = new Set();
|
|
53
|
+
|
|
54
|
+
for (const match of matches) {
|
|
55
|
+
const [, , translationKey] = match;
|
|
56
|
+
const separatorIndex = translationKey.indexOf(":");
|
|
57
|
+
if (separatorIndex !== -1) {
|
|
58
|
+
const namespace = translationKey.substring(0, separatorIndex);
|
|
59
|
+
namespaces.add(namespace);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return Array.from(namespaces);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const findNamespaces = (pageContent) => {
|
|
67
|
+
const namespaces = [...findTFunctionNamespaces(pageContent), ...findTransComponentNamespaces(pageContent)];
|
|
68
|
+
|
|
69
|
+
return Array.from(new Set(namespaces));
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const getTree = (subtree, tree, destination, viewedFiles = []) => {
|
|
73
|
+
if (!subtree || subtree.length === 0) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
for (let child of subtree) {
|
|
78
|
+
if (viewedFiles.includes(child)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const nextSubtree = tree[child];
|
|
83
|
+
|
|
84
|
+
viewedFiles.push(child);
|
|
85
|
+
|
|
86
|
+
if (nextSubtree) {
|
|
87
|
+
destination.push(nextSubtree);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (nextSubtree && nextSubtree.length > 0) {
|
|
91
|
+
getTree(nextSubtree, tree, destination, viewedFiles);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const filePathToRoute = (filePath) => {
|
|
97
|
+
const route = filePath.replace("src/pages", "").replace(".tsx", "").replace("/index", "/");
|
|
98
|
+
|
|
99
|
+
if (route === "/") {
|
|
100
|
+
return route;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return removeTrailingSlash(route);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
function main() {
|
|
107
|
+
// Negative lookahead – ignore searching for any files
|
|
108
|
+
// that aren't part of our include list
|
|
109
|
+
const searchDirs = new RegExp(`^(?!(${INCLUDE.join("|")}))`, "i");
|
|
110
|
+
|
|
111
|
+
const pages = walk("src/pages").flat(Number.POSITIVE_INFINITY);
|
|
112
|
+
|
|
113
|
+
madge(process.cwd(), {
|
|
114
|
+
tsConfig: TS_CONFIG,
|
|
115
|
+
excludeRegExp: [searchDirs, ...EXCLUDE],
|
|
116
|
+
fileExtensions: FILE_EXTENSIONS,
|
|
117
|
+
}).then((res) => {
|
|
118
|
+
const tree = res.obj();
|
|
119
|
+
|
|
120
|
+
for (const entryPoint of pages) {
|
|
121
|
+
let namespaces = [];
|
|
122
|
+
const filesOnPath = [];
|
|
123
|
+
|
|
124
|
+
getTree([entryPoint], tree, filesOnPath);
|
|
125
|
+
|
|
126
|
+
const flattenFilesOnPath = Array.from(new Set(filesOnPath.flat(Number.POSITIVE_INFINITY)));
|
|
127
|
+
|
|
128
|
+
for (const file of flattenFilesOnPath) {
|
|
129
|
+
const fileContent = readFileSync(file).toString();
|
|
130
|
+
|
|
131
|
+
namespaces = [...namespaces, ...findNamespaces(fileContent)];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
namespaces = Array.from(new Set(namespaces)).sort();
|
|
135
|
+
|
|
136
|
+
const page = filePathToRoute(entryPoint);
|
|
137
|
+
|
|
138
|
+
if (namespaces.length > 0) {
|
|
139
|
+
result[page] = namespaces;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
writeFileSync(path.resolve(process.cwd(), "i18n-pages.json"), JSON.stringify(result, null, 4));
|
|
144
|
+
|
|
145
|
+
console.log("Namespaces generated!");
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
main();
|
|
151
|
+
} catch (e) {
|
|
152
|
+
console.error("Error:", e);
|
|
153
|
+
}
|