@generaltranslation/gt-next-lint 14.0.27 → 14.0.28
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/configs/recommended.js +14 -16
- package/dist/configs/recommended.js.map +1 -1
- package/dist/index.js +21 -21
- package/dist/index.js.map +1 -1
- package/dist/rules/no-dynamic-jsx.js +147 -222
- package/dist/rules/no-dynamic-jsx.js.map +1 -1
- package/dist/rules/no-dynamic-string.js +136 -219
- package/dist/rules/no-dynamic-string.js.map +1 -1
- package/dist/rules/utils.js +18 -16
- package/dist/rules/utils.js.map +1 -1
- package/package.json +6 -4
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
"
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/configs/recommended.ts
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
settings: {
|
|
14
|
-
react: {
|
|
15
|
-
version: 'detect',
|
|
16
|
-
},
|
|
17
|
-
},
|
|
4
|
+
* Recommended ESLint configuration for GT-Next
|
|
5
|
+
*/
|
|
6
|
+
const recommended = {
|
|
7
|
+
plugins: ["gt-next"],
|
|
8
|
+
rules: {
|
|
9
|
+
"gt-next/no-dynamic-jsx": true,
|
|
10
|
+
"gt-next/no-dynamic-string": true
|
|
11
|
+
},
|
|
12
|
+
settings: { react: { version: "detect" } }
|
|
18
13
|
};
|
|
14
|
+
//#endregion
|
|
15
|
+
exports.recommended = recommended;
|
|
16
|
+
|
|
19
17
|
//# sourceMappingURL=recommended.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommended.js","
|
|
1
|
+
{"version":3,"file":"recommended.js","names":[],"sources":["../../src/configs/recommended.ts"],"sourcesContent":["/**\n * Recommended ESLint configuration for GT-Next\n */\n\nexport const recommended = {\n plugins: ['gt-next'],\n rules: {\n 'gt-next/no-dynamic-jsx': true,\n 'gt-next/no-dynamic-string': true,\n },\n settings: {\n react: {\n version: 'detect',\n },\n },\n};\n"],"mappings":";;;;;AAIA,MAAa,cAAc;CACzB,SAAS,CAAC,UAAU;CACpB,OAAO;EACL,0BAA0B;EAC1B,6BAA6B;EAC9B;CACD,UAAU,EACR,OAAO,EACL,SAAS,UACV,EACF;CACF"}
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
const require_rules_no_dynamic_jsx = require("./rules/no-dynamic-jsx.js");
|
|
2
|
+
const require_rules_no_dynamic_string = require("./rules/no-dynamic-string.js");
|
|
3
|
+
const require_configs_recommended = require("./configs/recommended.js");
|
|
4
|
+
//#region src/index.ts
|
|
2
5
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const no_dynamic_jsx_1 = require("./rules/no-dynamic-jsx");
|
|
10
|
-
const no_dynamic_string_1 = require("./rules/no-dynamic-string");
|
|
11
|
-
const recommended_1 = require("./configs/recommended");
|
|
6
|
+
* GT-Next ESLint Plugin
|
|
7
|
+
*
|
|
8
|
+
* Provides ESLint rules for General Translation Next.js integration.
|
|
9
|
+
* This plugin detects unwrapped dynamic content in translation components
|
|
10
|
+
* and provides better error reporting with file locations and line numbers.
|
|
11
|
+
*/
|
|
12
12
|
const plugin = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
recommended: recommended_1.recommended,
|
|
23
|
-
},
|
|
13
|
+
meta: {
|
|
14
|
+
name: "@generaltranslation/gt-next-lint",
|
|
15
|
+
version: "1.0.0"
|
|
16
|
+
},
|
|
17
|
+
rules: {
|
|
18
|
+
"no-dynamic-jsx": require_rules_no_dynamic_jsx.noDynamicJsx,
|
|
19
|
+
"no-dynamic-string": require_rules_no_dynamic_string.noDynamicString
|
|
20
|
+
},
|
|
21
|
+
configs: { recommended: require_configs_recommended.recommended }
|
|
24
22
|
};
|
|
25
23
|
module.exports = plugin;
|
|
24
|
+
//#endregion
|
|
25
|
+
|
|
26
26
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","
|
|
1
|
+
{"version":3,"file":"index.js","names":["noDynamicJsx","noDynamicString"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * GT-Next ESLint Plugin\n *\n * Provides ESLint rules for General Translation Next.js integration.\n * This plugin detects unwrapped dynamic content in translation components\n * and provides better error reporting with file locations and line numbers.\n */\n\nimport { noDynamicJsx } from './rules/no-dynamic-jsx';\nimport { noDynamicString } from './rules/no-dynamic-string';\nimport { recommended } from './configs/recommended';\n\nconst plugin = {\n meta: {\n name: '@generaltranslation/gt-next-lint',\n version: '1.0.0',\n },\n rules: {\n 'no-dynamic-jsx': noDynamicJsx,\n 'no-dynamic-string': noDynamicString,\n },\n configs: {\n recommended,\n },\n};\n\nexport = plugin;\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,SAAS;CACb,MAAM;EACJ,MAAM;EACN,SAAS;EACV;CACD,OAAO;EACL,kBAAkBA,6BAAAA;EAClB,qBAAqBC,gCAAAA;EACtB;CACD,SAAS,EACP,aAAA,4BAAA,aACD;CACF;iBAEQ"}
|
|
@@ -1,228 +1,153 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.noDynamicJsx = void 0;
|
|
13
|
-
const utils_1 = require("./utils");
|
|
14
|
-
const TRANSLATION_COMPONENTS = ['T'];
|
|
15
|
-
const VARIABLE_COMPONENTS = ['Var', 'DateTime', 'Num', 'Currency'];
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rules_utils = require("./utils.js");
|
|
3
|
+
//#region src/rules/no-dynamic-jsx.ts
|
|
4
|
+
const TRANSLATION_COMPONENTS = ["T"];
|
|
5
|
+
const VARIABLE_COMPONENTS = [
|
|
6
|
+
"Var",
|
|
7
|
+
"DateTime",
|
|
8
|
+
"Num",
|
|
9
|
+
"Currency"
|
|
10
|
+
];
|
|
16
11
|
function isTranslationComponent(name) {
|
|
17
|
-
|
|
12
|
+
return TRANSLATION_COMPONENTS.includes(name);
|
|
18
13
|
}
|
|
19
14
|
function isVariableComponent(name) {
|
|
20
|
-
|
|
15
|
+
return VARIABLE_COMPONENTS.includes(name);
|
|
21
16
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// Track variable assignments from GT components
|
|
155
|
-
VariableDeclarator(node) {
|
|
156
|
-
if ((0, utils_1.isAstNode)(node) &&
|
|
157
|
-
(0, utils_1.isAstNode)(node.id) &&
|
|
158
|
-
(0, utils_1.isAstNode)(node.init) &&
|
|
159
|
-
node.id.type === 'Identifier' &&
|
|
160
|
-
node.init.type === 'Identifier') {
|
|
161
|
-
const varName = (0, utils_1.getNodeName)(node.id);
|
|
162
|
-
const assignedFrom = (0, utils_1.getNodeName)(node.init);
|
|
163
|
-
if (!varName || !assignedFrom)
|
|
164
|
-
return;
|
|
165
|
-
if (state.imports.translationComponents.has(assignedFrom)) {
|
|
166
|
-
state.imports.assignedTranslationComponents.add(varName);
|
|
167
|
-
}
|
|
168
|
-
else if (state.imports.variableComponents.has(assignedFrom)) {
|
|
169
|
-
state.imports.assignedVariableComponents.add(varName);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
},
|
|
173
|
-
// Detect unwrapped dynamic content
|
|
174
|
-
JSXExpressionContainer(node) {
|
|
175
|
-
if (!(0, utils_1.isAstNode)(node))
|
|
176
|
-
return;
|
|
177
|
-
// Skip expressions inside JSX attributes (e.g., <Image width={16} />)
|
|
178
|
-
if (isInsideJSXAttribute(node)) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
// Skip expressions with just a string literal (e.g., {'Hello'})
|
|
182
|
-
// Skip expressions with just a comment
|
|
183
|
-
// Skip expressions with just an empty statement
|
|
184
|
-
if ((node.expression && (0, utils_1.isStringLiteral)(node.expression)) ||
|
|
185
|
-
isComment(node.expression) ||
|
|
186
|
-
isEmpty(node.expression)) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
// Check if this expression is inside a translation component but not inside a variable component
|
|
190
|
-
let inTranslationComponent = false;
|
|
191
|
-
let inVariableComponent = false;
|
|
192
|
-
// Walk up the AST to find parent JSX elements
|
|
193
|
-
let currentNode = (0, utils_1.isAstNode)(node.parent) ? node.parent : null;
|
|
194
|
-
while (currentNode) {
|
|
195
|
-
if (currentNode.type === 'JSXElement') {
|
|
196
|
-
const elementName = getElementName(currentNode);
|
|
197
|
-
if (elementName) {
|
|
198
|
-
// Check if this is a variable component
|
|
199
|
-
if (state.imports.variableComponents.has(elementName) ||
|
|
200
|
-
state.imports.assignedVariableComponents.has(elementName) ||
|
|
201
|
-
isNamespaceVariableComponent(elementName)) {
|
|
202
|
-
inVariableComponent = true;
|
|
203
|
-
break; // If we find a variable component, we don't need to check further
|
|
204
|
-
}
|
|
205
|
-
// Check if this is a translation component
|
|
206
|
-
else if (state.imports.translationComponents.has(elementName) ||
|
|
207
|
-
state.imports.assignedTranslationComponents.has(elementName) ||
|
|
208
|
-
isNamespaceTranslationComponent(elementName)) {
|
|
209
|
-
inTranslationComponent = true;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
currentNode = (0, utils_1.isAstNode)(currentNode.parent)
|
|
214
|
-
? currentNode.parent
|
|
215
|
-
: null;
|
|
216
|
-
}
|
|
217
|
-
// Report if we're inside a translation component but not inside a variable component
|
|
218
|
-
if (inTranslationComponent && !inVariableComponent) {
|
|
219
|
-
context.report({
|
|
220
|
-
node: node,
|
|
221
|
-
messageId: 'dynamicJsx',
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
};
|
|
226
|
-
},
|
|
17
|
+
const noDynamicJsx = {
|
|
18
|
+
meta: {
|
|
19
|
+
type: "problem",
|
|
20
|
+
docs: {
|
|
21
|
+
description: "Detect unwrapped dynamic content in GT-Next translation components",
|
|
22
|
+
category: "Best Practices",
|
|
23
|
+
recommended: true,
|
|
24
|
+
url: "https://github.com/generaltranslation/gt/tree/main/packages/next-lint#no-dynamic-jsx"
|
|
25
|
+
},
|
|
26
|
+
fixable: void 0,
|
|
27
|
+
schema: [],
|
|
28
|
+
messages: { dynamicJsx: "Dynamic content in <T> component should be wrapped in a variable component (<Var>, <DateTime>, <Num>, or <Currency>)" }
|
|
29
|
+
},
|
|
30
|
+
create(context) {
|
|
31
|
+
const state = {
|
|
32
|
+
translationStack: 0,
|
|
33
|
+
variableStack: 0,
|
|
34
|
+
imports: {
|
|
35
|
+
translationComponents: /* @__PURE__ */ new Set(),
|
|
36
|
+
variableComponents: /* @__PURE__ */ new Set(),
|
|
37
|
+
namespaceImports: /* @__PURE__ */ new Set(),
|
|
38
|
+
assignedTranslationComponents: /* @__PURE__ */ new Set(),
|
|
39
|
+
assignedVariableComponents: /* @__PURE__ */ new Set()
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
function getElementName(node) {
|
|
43
|
+
if (!require_rules_utils.isAstNode(node) || !require_rules_utils.isAstNode(node.openingElement)) return null;
|
|
44
|
+
const name = node.openingElement.name;
|
|
45
|
+
if (!require_rules_utils.isAstNode(name)) return null;
|
|
46
|
+
if (name.type === "JSXIdentifier") return require_rules_utils.getNodeName(name);
|
|
47
|
+
if (name.type === "JSXMemberExpression") {
|
|
48
|
+
const obj = name.object;
|
|
49
|
+
const prop = name.property;
|
|
50
|
+
if (require_rules_utils.isAstNode(obj) && require_rules_utils.isAstNode(prop) && obj.type === "JSXIdentifier" && prop.type === "JSXIdentifier") {
|
|
51
|
+
const objectName = require_rules_utils.getNodeName(obj);
|
|
52
|
+
const propertyName = require_rules_utils.getNodeName(prop);
|
|
53
|
+
return objectName && propertyName ? `${objectName}.${propertyName}` : null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function isNamespaceTranslationComponent(elementName) {
|
|
59
|
+
const parts = elementName.split(".");
|
|
60
|
+
if (parts.length === 2) {
|
|
61
|
+
const [namespace, component] = parts;
|
|
62
|
+
return state.imports.namespaceImports.has(namespace) && isTranslationComponent(component);
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
function isNamespaceVariableComponent(elementName) {
|
|
67
|
+
const parts = elementName.split(".");
|
|
68
|
+
if (parts.length === 2) {
|
|
69
|
+
const [namespace, component] = parts;
|
|
70
|
+
return state.imports.namespaceImports.has(namespace) && isVariableComponent(component);
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
function isInsideJSXAttribute(node) {
|
|
75
|
+
if (!require_rules_utils.isAstNode(node)) return false;
|
|
76
|
+
let currentNode = require_rules_utils.isAstNode(node.parent) ? node.parent : null;
|
|
77
|
+
while (currentNode) {
|
|
78
|
+
if (currentNode.type === "JSXAttribute") return true;
|
|
79
|
+
if (currentNode.type === "JSXElement") return false;
|
|
80
|
+
currentNode = require_rules_utils.isAstNode(currentNode.parent) ? currentNode.parent : null;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
function isComment(expression) {
|
|
85
|
+
if (!require_rules_utils.isAstNode(expression)) return false;
|
|
86
|
+
return expression.type === "Block" || expression.type === "Line";
|
|
87
|
+
}
|
|
88
|
+
function isEmpty(expression) {
|
|
89
|
+
if (!require_rules_utils.isAstNode(expression)) return false;
|
|
90
|
+
return expression.type === "JSXEmptyExpression";
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
ImportDeclaration(node) {
|
|
94
|
+
if (!require_rules_utils.isAstNode(node) || !require_rules_utils.isAstNode(node.source)) return;
|
|
95
|
+
if (node.source?.type === "Literal" && typeof node.source.value === "string") {
|
|
96
|
+
const source = node.source.value;
|
|
97
|
+
if (require_rules_utils.isGTModule(source)) {
|
|
98
|
+
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
99
|
+
for (const specifier of specifiers) {
|
|
100
|
+
if (!require_rules_utils.isAstNode(specifier)) continue;
|
|
101
|
+
if (specifier.type === "ImportSpecifier") {
|
|
102
|
+
const importedName = require_rules_utils.getNodeName(specifier.imported) || "";
|
|
103
|
+
const localName = require_rules_utils.getNodeName(specifier.local) || "";
|
|
104
|
+
if (isTranslationComponent(importedName)) state.imports.translationComponents.add(localName);
|
|
105
|
+
else if (isVariableComponent(importedName)) state.imports.variableComponents.add(localName);
|
|
106
|
+
} else if (specifier.type === "ImportNamespaceSpecifier") {
|
|
107
|
+
const localName = require_rules_utils.getNodeName(specifier.local) || "";
|
|
108
|
+
state.imports.namespaceImports.add(localName);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
VariableDeclarator(node) {
|
|
115
|
+
if (require_rules_utils.isAstNode(node) && require_rules_utils.isAstNode(node.id) && require_rules_utils.isAstNode(node.init) && node.id.type === "Identifier" && node.init.type === "Identifier") {
|
|
116
|
+
const varName = require_rules_utils.getNodeName(node.id);
|
|
117
|
+
const assignedFrom = require_rules_utils.getNodeName(node.init);
|
|
118
|
+
if (!varName || !assignedFrom) return;
|
|
119
|
+
if (state.imports.translationComponents.has(assignedFrom)) state.imports.assignedTranslationComponents.add(varName);
|
|
120
|
+
else if (state.imports.variableComponents.has(assignedFrom)) state.imports.assignedVariableComponents.add(varName);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
JSXExpressionContainer(node) {
|
|
124
|
+
if (!require_rules_utils.isAstNode(node)) return;
|
|
125
|
+
if (isInsideJSXAttribute(node)) return;
|
|
126
|
+
if (node.expression && require_rules_utils.isStringLiteral(node.expression) || isComment(node.expression) || isEmpty(node.expression)) return;
|
|
127
|
+
let inTranslationComponent = false;
|
|
128
|
+
let inVariableComponent = false;
|
|
129
|
+
let currentNode = require_rules_utils.isAstNode(node.parent) ? node.parent : null;
|
|
130
|
+
while (currentNode) {
|
|
131
|
+
if (currentNode.type === "JSXElement") {
|
|
132
|
+
const elementName = getElementName(currentNode);
|
|
133
|
+
if (elementName) {
|
|
134
|
+
if (state.imports.variableComponents.has(elementName) || state.imports.assignedVariableComponents.has(elementName) || isNamespaceVariableComponent(elementName)) {
|
|
135
|
+
inVariableComponent = true;
|
|
136
|
+
break;
|
|
137
|
+
} else if (state.imports.translationComponents.has(elementName) || state.imports.assignedTranslationComponents.has(elementName) || isNamespaceTranslationComponent(elementName)) inTranslationComponent = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
currentNode = require_rules_utils.isAstNode(currentNode.parent) ? currentNode.parent : null;
|
|
141
|
+
}
|
|
142
|
+
if (inTranslationComponent && !inVariableComponent) context.report({
|
|
143
|
+
node,
|
|
144
|
+
messageId: "dynamicJsx"
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
227
149
|
};
|
|
150
|
+
//#endregion
|
|
151
|
+
exports.noDynamicJsx = noDynamicJsx;
|
|
152
|
+
|
|
228
153
|
//# sourceMappingURL=no-dynamic-jsx.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-dynamic-jsx.js","sourceRoot":"","sources":["../../src/rules/no-dynamic-jsx.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"no-dynamic-jsx.js","names":["isAstNode","getNodeName","isGTModule","isStringLiteral"],"sources":["../../src/rules/no-dynamic-jsx.ts"],"sourcesContent":["/**\n * ESLint rule: no-dynamic-jsx\n *\n * Detects unwrapped dynamic content in GT-Next translation components.\n * Equivalent to the SWC plugin functionality but with proper ESLint error reporting.\n *\n * This rule checks for JSX expressions ({dynamic content}) inside <T> components\n * that are not wrapped in variable components (<Var>, <DateTime>, <Num>, <Currency>).\n */\n\nimport type { Rule } from 'eslint';\nimport { getNodeName, isAstNode, isGTModule, isStringLiteral } from './utils';\n\nconst TRANSLATION_COMPONENTS = ['T'];\nconst VARIABLE_COMPONENTS = ['Var', 'DateTime', 'Num', 'Currency'];\n\nfunction isTranslationComponent(name: string): boolean {\n return TRANSLATION_COMPONENTS.includes(name);\n}\n\nfunction isVariableComponent(name: string): boolean {\n return VARIABLE_COMPONENTS.includes(name);\n}\n\nexport const noDynamicJsx: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Detect unwrapped dynamic content in GT-Next translation components',\n category: 'Best Practices',\n recommended: true,\n url: 'https://github.com/generaltranslation/gt/tree/main/packages/next-lint#no-dynamic-jsx',\n },\n fixable: undefined,\n schema: [],\n messages: {\n dynamicJsx:\n 'Dynamic content in <T> component should be wrapped in a variable component (<Var>, <DateTime>, <Num>, or <Currency>)',\n },\n },\n\n create(context) {\n const state = {\n translationStack: 0,\n variableStack: 0,\n imports: {\n translationComponents: new Set<string>(),\n variableComponents: new Set<string>(),\n namespaceImports: new Set<string>(),\n assignedTranslationComponents: new Set<string>(),\n assignedVariableComponents: new Set<string>(),\n },\n };\n\n function getElementName(node: unknown): string | null {\n if (!isAstNode(node) || !isAstNode(node.openingElement)) return null;\n const name = node.openingElement.name;\n if (!isAstNode(name)) return null;\n\n if (name.type === 'JSXIdentifier') {\n return getNodeName(name);\n }\n\n if (name.type === 'JSXMemberExpression') {\n const obj = name.object;\n const prop = name.property;\n if (\n isAstNode(obj) &&\n isAstNode(prop) &&\n obj.type === 'JSXIdentifier' &&\n prop.type === 'JSXIdentifier'\n ) {\n const objectName = getNodeName(obj);\n const propertyName = getNodeName(prop);\n return objectName && propertyName\n ? `${objectName}.${propertyName}`\n : null;\n }\n }\n\n return null;\n }\n\n function isNamespaceTranslationComponent(elementName: string): boolean {\n const parts = elementName.split('.');\n if (parts.length === 2) {\n const [namespace, component] = parts;\n return (\n state.imports.namespaceImports.has(namespace) &&\n isTranslationComponent(component)\n );\n }\n return false;\n }\n\n function isNamespaceVariableComponent(elementName: string): boolean {\n const parts = elementName.split('.');\n if (parts.length === 2) {\n const [namespace, component] = parts;\n return (\n state.imports.namespaceImports.has(namespace) &&\n isVariableComponent(component)\n );\n }\n return false;\n }\n\n function isInsideJSXAttribute(node: unknown): boolean {\n if (!isAstNode(node)) return false;\n // Walk up the AST to check if this expression is inside a JSX attribute\n let currentNode = isAstNode(node.parent) ? node.parent : null;\n while (currentNode) {\n if (currentNode.type === 'JSXAttribute') {\n return true;\n }\n // If we reach a JSX element, we're in element content, not attributes\n if (currentNode.type === 'JSXElement') {\n return false;\n }\n currentNode = isAstNode(currentNode.parent) ? currentNode.parent : null;\n }\n return false;\n }\n\n // Check if the node is a comment\n function isComment(expression: unknown): boolean {\n if (!isAstNode(expression)) return false;\n return expression.type === 'Block' || expression.type === 'Line';\n }\n\n // Check if empty\n function isEmpty(expression: unknown): boolean {\n if (!isAstNode(expression)) return false;\n return expression.type === 'JSXEmptyExpression';\n }\n\n return {\n // Track imports from GT-Next modules\n ImportDeclaration(node: unknown) {\n if (!isAstNode(node) || !isAstNode(node.source)) return;\n if (\n node.source?.type === 'Literal' &&\n typeof node.source.value === 'string'\n ) {\n const source = node.source.value;\n\n if (isGTModule(source)) {\n const specifiers = Array.isArray(node.specifiers)\n ? node.specifiers\n : [];\n for (const specifier of specifiers) {\n if (!isAstNode(specifier)) continue;\n if (specifier.type === 'ImportSpecifier') {\n const importedName = getNodeName(specifier.imported) || '';\n const localName = getNodeName(specifier.local) || '';\n\n if (isTranslationComponent(importedName)) {\n state.imports.translationComponents.add(localName);\n } else if (isVariableComponent(importedName)) {\n state.imports.variableComponents.add(localName);\n }\n } else if (specifier.type === 'ImportNamespaceSpecifier') {\n const localName = getNodeName(specifier.local) || '';\n state.imports.namespaceImports.add(localName);\n }\n }\n }\n }\n },\n\n // Track variable assignments from GT components\n VariableDeclarator(node: unknown) {\n if (\n isAstNode(node) &&\n isAstNode(node.id) &&\n isAstNode(node.init) &&\n node.id.type === 'Identifier' &&\n node.init.type === 'Identifier'\n ) {\n const varName = getNodeName(node.id);\n const assignedFrom = getNodeName(node.init);\n if (!varName || !assignedFrom) return;\n\n if (state.imports.translationComponents.has(assignedFrom)) {\n state.imports.assignedTranslationComponents.add(varName);\n } else if (state.imports.variableComponents.has(assignedFrom)) {\n state.imports.assignedVariableComponents.add(varName);\n }\n }\n },\n\n // Detect unwrapped dynamic content\n JSXExpressionContainer(node: unknown) {\n if (!isAstNode(node)) return;\n // Skip expressions inside JSX attributes (e.g., <Image width={16} />)\n if (isInsideJSXAttribute(node)) {\n return;\n }\n\n // Skip expressions with just a string literal (e.g., {'Hello'})\n // Skip expressions with just a comment\n // Skip expressions with just an empty statement\n if (\n (node.expression && isStringLiteral(node.expression)) ||\n isComment(node.expression) ||\n isEmpty(node.expression)\n ) {\n return;\n }\n\n // Check if this expression is inside a translation component but not inside a variable component\n let inTranslationComponent = false;\n let inVariableComponent = false;\n\n // Walk up the AST to find parent JSX elements\n let currentNode = isAstNode(node.parent) ? node.parent : null;\n while (currentNode) {\n if (currentNode.type === 'JSXElement') {\n const elementName = getElementName(currentNode);\n if (elementName) {\n // Check if this is a variable component\n if (\n state.imports.variableComponents.has(elementName) ||\n state.imports.assignedVariableComponents.has(elementName) ||\n isNamespaceVariableComponent(elementName)\n ) {\n inVariableComponent = true;\n break; // If we find a variable component, we don't need to check further\n }\n // Check if this is a translation component\n else if (\n state.imports.translationComponents.has(elementName) ||\n state.imports.assignedTranslationComponents.has(elementName) ||\n isNamespaceTranslationComponent(elementName)\n ) {\n inTranslationComponent = true;\n }\n }\n }\n currentNode = isAstNode(currentNode.parent)\n ? currentNode.parent\n : null;\n }\n\n // Report if we're inside a translation component but not inside a variable component\n if (inTranslationComponent && !inVariableComponent) {\n context.report({\n node: node as never,\n messageId: 'dynamicJsx',\n });\n }\n },\n };\n },\n};\n"],"mappings":"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"}
|
|
@@ -1,223 +1,140 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* Ensures translation functions (t, useGT, getGT) only accept string literals
|
|
6
|
-
* as their first argument. Dynamic content like template literals or string
|
|
7
|
-
* concatenation is prohibited to ensure consistent translation keys.
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.noDynamicString = void 0;
|
|
11
|
-
const utils_1 = require("./utils");
|
|
12
|
-
const TRANSLATION_FUNCTIONS = ['useGT', 'getGT'];
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rules_utils = require("./utils.js");
|
|
3
|
+
//#region src/rules/no-dynamic-string.ts
|
|
4
|
+
const TRANSLATION_FUNCTIONS = ["useGT", "getGT"];
|
|
13
5
|
function isTranslationFunction(name) {
|
|
14
|
-
|
|
6
|
+
return TRANSLATION_FUNCTIONS.includes(name);
|
|
15
7
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (!functionName)
|
|
145
|
-
return;
|
|
146
|
-
if (trackedFunctions.has(functionName)) {
|
|
147
|
-
const tracked = trackedFunctions.get(functionName);
|
|
148
|
-
if (tracked.isTranslationFunction) {
|
|
149
|
-
// This variable now holds a translation function (from awaited promise)
|
|
150
|
-
const variableName = (0, utils_1.getNodeName)(node.id);
|
|
151
|
-
if (variableName)
|
|
152
|
-
translationVariables.add(variableName);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
else if ((0, utils_1.isAstNode)(callExpression.callee) &&
|
|
157
|
-
callExpression.callee.type === 'MemberExpression') {
|
|
158
|
-
// Handle namespace calls like: const t = await GT.getGT();
|
|
159
|
-
const objectName = (0, utils_1.getNodeName)(callExpression.callee.object);
|
|
160
|
-
const propertyName = (0, utils_1.getNodeName)(callExpression.callee.property);
|
|
161
|
-
if (objectName &&
|
|
162
|
-
propertyName &&
|
|
163
|
-
trackedFunctions.has(objectName) &&
|
|
164
|
-
isTranslationFunction(propertyName)) {
|
|
165
|
-
// This variable now holds a translation function (from awaited promise)
|
|
166
|
-
const variableName = (0, utils_1.getNodeName)(node.id);
|
|
167
|
-
if (variableName)
|
|
168
|
-
translationVariables.add(variableName);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
else if (node.init.type === 'Identifier') {
|
|
173
|
-
// Handle reassignment: const t = getTranslation;
|
|
174
|
-
const assignedFrom = (0, utils_1.getNodeName)(node.init);
|
|
175
|
-
if (assignedFrom && translationVariables.has(assignedFrom)) {
|
|
176
|
-
const variableName = (0, utils_1.getNodeName)(node.id);
|
|
177
|
-
if (variableName)
|
|
178
|
-
translationVariables.add(variableName);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return {
|
|
184
|
-
ImportDeclaration(node) {
|
|
185
|
-
if (!(0, utils_1.isAstNode)(node) || !(0, utils_1.isAstNode)(node.source))
|
|
186
|
-
return;
|
|
187
|
-
const source = node.source.value;
|
|
188
|
-
if (typeof source !== 'string')
|
|
189
|
-
return;
|
|
190
|
-
if (!(0, utils_1.isGTModule)(source))
|
|
191
|
-
return;
|
|
192
|
-
const specifiers = Array.isArray(node.specifiers)
|
|
193
|
-
? node.specifiers
|
|
194
|
-
: [];
|
|
195
|
-
for (const specifier of specifiers) {
|
|
196
|
-
if (!(0, utils_1.isAstNode)(specifier))
|
|
197
|
-
continue;
|
|
198
|
-
if (specifier.type === 'ImportSpecifier') {
|
|
199
|
-
// import { useGT, tx as serverTx } from 'gt-next'
|
|
200
|
-
const importedName = (0, utils_1.getNodeName)(specifier.imported);
|
|
201
|
-
const localName = (0, utils_1.getNodeName)(specifier.local);
|
|
202
|
-
if (importedName && localName) {
|
|
203
|
-
trackImport(localName, importedName, source);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
else if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
207
|
-
// import * as GT from 'gt-next'
|
|
208
|
-
const localName = (0, utils_1.getNodeName)(specifier.local);
|
|
209
|
-
if (localName)
|
|
210
|
-
trackNamespaceImport(localName, source);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
VariableDeclarator(node) {
|
|
215
|
-
handleAssignment(node);
|
|
216
|
-
},
|
|
217
|
-
CallExpression(node) {
|
|
218
|
-
handleCallExpression(node);
|
|
219
|
-
},
|
|
220
|
-
};
|
|
221
|
-
},
|
|
8
|
+
const noDynamicString = {
|
|
9
|
+
meta: {
|
|
10
|
+
type: "problem",
|
|
11
|
+
docs: {
|
|
12
|
+
description: "Translation functions must use string literals as the first argument",
|
|
13
|
+
category: "Best Practices",
|
|
14
|
+
recommended: true,
|
|
15
|
+
url: "https://github.com/generaltranslation/gt/tree/main/packages/next-lint#no-dynamic-string"
|
|
16
|
+
},
|
|
17
|
+
fixable: void 0,
|
|
18
|
+
schema: [],
|
|
19
|
+
messages: { dynamicString: "Translation function must use a constant string literal as the first argument. Use t('Hello, {name}!', { name: value }) instead of template literals or string concatenation." }
|
|
20
|
+
},
|
|
21
|
+
create(context) {
|
|
22
|
+
const trackedFunctions = /* @__PURE__ */ new Map();
|
|
23
|
+
const translationVariables = /* @__PURE__ */ new Set();
|
|
24
|
+
function trackImport(localName, importedName, source) {
|
|
25
|
+
if (require_rules_utils.isGTModule(source) && isTranslationFunction(importedName)) trackedFunctions.set(localName, {
|
|
26
|
+
name: importedName,
|
|
27
|
+
isTranslationFunction: true
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function trackNamespaceImport(localName, source) {
|
|
31
|
+
if (require_rules_utils.isGTModule(source)) trackedFunctions.set(localName, {
|
|
32
|
+
name: localName,
|
|
33
|
+
isTranslationFunction: false
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function validateTranslationCall(node) {
|
|
37
|
+
if (!require_rules_utils.isAstNode(node) || !Array.isArray(node.arguments)) return;
|
|
38
|
+
const firstArg = node.arguments[0];
|
|
39
|
+
if (!firstArg) return;
|
|
40
|
+
if (!require_rules_utils.isStringLiteral(firstArg)) context.report({
|
|
41
|
+
node: firstArg,
|
|
42
|
+
messageId: "dynamicString"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function handleCallExpression(node) {
|
|
46
|
+
if (!require_rules_utils.isAstNode(node) || !require_rules_utils.isAstNode(node.callee)) return;
|
|
47
|
+
if (node.callee.type === "Identifier") {
|
|
48
|
+
const functionName = require_rules_utils.getNodeName(node.callee);
|
|
49
|
+
if (!functionName) return;
|
|
50
|
+
if (trackedFunctions.has(functionName)) {
|
|
51
|
+
if (trackedFunctions.get(functionName).isTranslationFunction) validateTranslationCall(node);
|
|
52
|
+
} else if (translationVariables.has(functionName)) validateTranslationCall(node);
|
|
53
|
+
} else if (node.callee.type === "MemberExpression") {
|
|
54
|
+
const objectName = require_rules_utils.getNodeName(node.callee.object);
|
|
55
|
+
const propertyName = require_rules_utils.getNodeName(node.callee.property);
|
|
56
|
+
if (!objectName || !propertyName) return;
|
|
57
|
+
if (trackedFunctions.has(objectName) && isTranslationFunction(propertyName)) validateTranslationCall(node);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function handleAssignment(node) {
|
|
61
|
+
if (require_rules_utils.isAstNode(node) && node.type === "VariableDeclarator" && require_rules_utils.isAstNode(node.id) && node.id.type === "Identifier" && require_rules_utils.isAstNode(node.init)) {
|
|
62
|
+
if (node.init.type === "CallExpression") {
|
|
63
|
+
const callExpression = node.init;
|
|
64
|
+
if (require_rules_utils.isAstNode(callExpression.callee) && callExpression.callee.type === "Identifier") {
|
|
65
|
+
const functionName = require_rules_utils.getNodeName(callExpression.callee);
|
|
66
|
+
if (!functionName) return;
|
|
67
|
+
if (trackedFunctions.has(functionName)) {
|
|
68
|
+
if (trackedFunctions.get(functionName).isTranslationFunction) {
|
|
69
|
+
const variableName = require_rules_utils.getNodeName(node.id);
|
|
70
|
+
if (variableName) translationVariables.add(variableName);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else if (require_rules_utils.isAstNode(callExpression.callee) && callExpression.callee.type === "MemberExpression") {
|
|
74
|
+
const objectName = require_rules_utils.getNodeName(callExpression.callee.object);
|
|
75
|
+
const propertyName = require_rules_utils.getNodeName(callExpression.callee.property);
|
|
76
|
+
if (objectName && propertyName && trackedFunctions.has(objectName) && isTranslationFunction(propertyName)) {
|
|
77
|
+
const variableName = require_rules_utils.getNodeName(node.id);
|
|
78
|
+
if (variableName) translationVariables.add(variableName);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} else if (node.init.type === "AwaitExpression" && require_rules_utils.isAstNode(node.init.argument) && node.init.argument.type === "CallExpression") {
|
|
82
|
+
const callExpression = node.init.argument;
|
|
83
|
+
if (require_rules_utils.isAstNode(callExpression.callee) && callExpression.callee.type === "Identifier") {
|
|
84
|
+
const functionName = require_rules_utils.getNodeName(callExpression.callee);
|
|
85
|
+
if (!functionName) return;
|
|
86
|
+
if (trackedFunctions.has(functionName)) {
|
|
87
|
+
if (trackedFunctions.get(functionName).isTranslationFunction) {
|
|
88
|
+
const variableName = require_rules_utils.getNodeName(node.id);
|
|
89
|
+
if (variableName) translationVariables.add(variableName);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} else if (require_rules_utils.isAstNode(callExpression.callee) && callExpression.callee.type === "MemberExpression") {
|
|
93
|
+
const objectName = require_rules_utils.getNodeName(callExpression.callee.object);
|
|
94
|
+
const propertyName = require_rules_utils.getNodeName(callExpression.callee.property);
|
|
95
|
+
if (objectName && propertyName && trackedFunctions.has(objectName) && isTranslationFunction(propertyName)) {
|
|
96
|
+
const variableName = require_rules_utils.getNodeName(node.id);
|
|
97
|
+
if (variableName) translationVariables.add(variableName);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} else if (node.init.type === "Identifier") {
|
|
101
|
+
const assignedFrom = require_rules_utils.getNodeName(node.init);
|
|
102
|
+
if (assignedFrom && translationVariables.has(assignedFrom)) {
|
|
103
|
+
const variableName = require_rules_utils.getNodeName(node.id);
|
|
104
|
+
if (variableName) translationVariables.add(variableName);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
ImportDeclaration(node) {
|
|
111
|
+
if (!require_rules_utils.isAstNode(node) || !require_rules_utils.isAstNode(node.source)) return;
|
|
112
|
+
const source = node.source.value;
|
|
113
|
+
if (typeof source !== "string") return;
|
|
114
|
+
if (!require_rules_utils.isGTModule(source)) return;
|
|
115
|
+
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
116
|
+
for (const specifier of specifiers) {
|
|
117
|
+
if (!require_rules_utils.isAstNode(specifier)) continue;
|
|
118
|
+
if (specifier.type === "ImportSpecifier") {
|
|
119
|
+
const importedName = require_rules_utils.getNodeName(specifier.imported);
|
|
120
|
+
const localName = require_rules_utils.getNodeName(specifier.local);
|
|
121
|
+
if (importedName && localName) trackImport(localName, importedName, source);
|
|
122
|
+
} else if (specifier.type === "ImportNamespaceSpecifier") {
|
|
123
|
+
const localName = require_rules_utils.getNodeName(specifier.local);
|
|
124
|
+
if (localName) trackNamespaceImport(localName, source);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
VariableDeclarator(node) {
|
|
129
|
+
handleAssignment(node);
|
|
130
|
+
},
|
|
131
|
+
CallExpression(node) {
|
|
132
|
+
handleCallExpression(node);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
222
136
|
};
|
|
137
|
+
//#endregion
|
|
138
|
+
exports.noDynamicString = noDynamicString;
|
|
139
|
+
|
|
223
140
|
//# sourceMappingURL=no-dynamic-string.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-dynamic-string.js","sourceRoot":"","sources":["../../src/rules/no-dynamic-string.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"no-dynamic-string.js","names":["isGTModule","isAstNode","isStringLiteral","getNodeName"],"sources":["../../src/rules/no-dynamic-string.ts"],"sourcesContent":["/**\n * ESLint rule: no-dynamic-string\n *\n * Ensures translation functions (t, useGT, getGT) only accept string literals\n * as their first argument. Dynamic content like template literals or string\n * concatenation is prohibited to ensure consistent translation keys.\n */\n\nimport type { Rule } from 'eslint';\nimport { getNodeName, isAstNode, isGTModule, isStringLiteral } from './utils';\n\nconst TRANSLATION_FUNCTIONS = ['useGT', 'getGT'];\n\ninterface TrackedFunction {\n name: string;\n isTranslationFunction: boolean;\n}\n\nfunction isTranslationFunction(name: string): boolean {\n return TRANSLATION_FUNCTIONS.includes(name);\n}\n\nexport const noDynamicString: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Translation functions must use string literals as the first argument',\n category: 'Best Practices',\n recommended: true,\n url: 'https://github.com/generaltranslation/gt/tree/main/packages/next-lint#no-dynamic-string',\n },\n fixable: undefined,\n schema: [],\n messages: {\n dynamicString:\n \"Translation function must use a constant string literal as the first argument. Use t('Hello, {name}!', { name: value }) instead of template literals or string concatenation.\",\n },\n },\n\n create(context) {\n // Track imported GT functions and their aliases\n const trackedFunctions = new Map<string, TrackedFunction>();\n // Track variables assigned from translation function calls\n const translationVariables = new Set<string>();\n\n function trackImport(\n localName: string,\n importedName: string,\n source: string\n ) {\n if (isGTModule(source) && isTranslationFunction(importedName)) {\n trackedFunctions.set(localName, {\n name: importedName,\n isTranslationFunction: true,\n });\n }\n }\n\n function trackNamespaceImport(localName: string, source: string) {\n if (isGTModule(source)) {\n trackedFunctions.set(localName, {\n name: localName,\n isTranslationFunction: false, // It's a namespace, not directly callable\n });\n }\n }\n\n function validateTranslationCall(node: unknown) {\n if (!isAstNode(node) || !Array.isArray(node.arguments)) return;\n const firstArg = node.arguments[0];\n if (!firstArg) return; // No arguments\n\n if (!isStringLiteral(firstArg)) {\n context.report({\n node: firstArg as never,\n messageId: 'dynamicString',\n });\n }\n }\n\n function handleCallExpression(node: unknown) {\n if (!isAstNode(node) || !isAstNode(node.callee)) return;\n if (node.callee.type === 'Identifier') {\n // Direct function calls: t(), useGT(), etc.\n const functionName = getNodeName(node.callee);\n if (!functionName) return;\n\n if (trackedFunctions.has(functionName)) {\n const tracked = trackedFunctions.get(functionName)!;\n if (tracked.isTranslationFunction) {\n validateTranslationCall(node);\n }\n } else if (translationVariables.has(functionName)) {\n // Variable assigned from translation function\n validateTranslationCall(node);\n }\n } else if (node.callee.type === 'MemberExpression') {\n // Member expressions: GT.tx(), namespace.function()\n const objectName = getNodeName(node.callee.object);\n const propertyName = getNodeName(node.callee.property);\n if (!objectName || !propertyName) return;\n\n if (\n trackedFunctions.has(objectName) &&\n isTranslationFunction(propertyName)\n ) {\n validateTranslationCall(node);\n }\n }\n }\n\n function handleAssignment(node: unknown) {\n // Track variables assigned from translation function calls\n if (\n isAstNode(node) &&\n node.type === 'VariableDeclarator' &&\n isAstNode(node.id) &&\n node.id.type === 'Identifier' &&\n isAstNode(node.init)\n ) {\n if (node.init.type === 'CallExpression') {\n const callExpression = node.init;\n\n if (\n isAstNode(callExpression.callee) &&\n callExpression.callee.type === 'Identifier'\n ) {\n const functionName = getNodeName(callExpression.callee);\n if (!functionName) return;\n if (trackedFunctions.has(functionName)) {\n const tracked = trackedFunctions.get(functionName)!;\n if (tracked.isTranslationFunction) {\n // This variable now holds a translation function\n const variableName = getNodeName(node.id);\n if (variableName) translationVariables.add(variableName);\n }\n }\n } else if (\n isAstNode(callExpression.callee) &&\n callExpression.callee.type === 'MemberExpression'\n ) {\n // Handle namespace calls like: const t = GT.useGT();\n const objectName = getNodeName(callExpression.callee.object);\n const propertyName = getNodeName(callExpression.callee.property);\n if (\n objectName &&\n propertyName &&\n trackedFunctions.has(objectName) &&\n isTranslationFunction(propertyName)\n ) {\n // This variable now holds a translation function\n const variableName = getNodeName(node.id);\n if (variableName) translationVariables.add(variableName);\n }\n }\n } else if (\n node.init.type === 'AwaitExpression' &&\n isAstNode(node.init.argument) &&\n node.init.argument.type === 'CallExpression'\n ) {\n // Handle await getGT() case\n const callExpression = node.init.argument;\n\n if (\n isAstNode(callExpression.callee) &&\n callExpression.callee.type === 'Identifier'\n ) {\n const functionName = getNodeName(callExpression.callee);\n if (!functionName) return;\n if (trackedFunctions.has(functionName)) {\n const tracked = trackedFunctions.get(functionName)!;\n if (tracked.isTranslationFunction) {\n // This variable now holds a translation function (from awaited promise)\n const variableName = getNodeName(node.id);\n if (variableName) translationVariables.add(variableName);\n }\n }\n } else if (\n isAstNode(callExpression.callee) &&\n callExpression.callee.type === 'MemberExpression'\n ) {\n // Handle namespace calls like: const t = await GT.getGT();\n const objectName = getNodeName(callExpression.callee.object);\n const propertyName = getNodeName(callExpression.callee.property);\n if (\n objectName &&\n propertyName &&\n trackedFunctions.has(objectName) &&\n isTranslationFunction(propertyName)\n ) {\n // This variable now holds a translation function (from awaited promise)\n const variableName = getNodeName(node.id);\n if (variableName) translationVariables.add(variableName);\n }\n }\n } else if (node.init.type === 'Identifier') {\n // Handle reassignment: const t = getTranslation;\n const assignedFrom = getNodeName(node.init);\n if (assignedFrom && translationVariables.has(assignedFrom)) {\n const variableName = getNodeName(node.id);\n if (variableName) translationVariables.add(variableName);\n }\n }\n }\n }\n\n return {\n ImportDeclaration(node: unknown) {\n if (!isAstNode(node) || !isAstNode(node.source)) return;\n const source = node.source.value;\n if (typeof source !== 'string') return;\n if (!isGTModule(source)) return;\n\n const specifiers = Array.isArray(node.specifiers)\n ? node.specifiers\n : [];\n for (const specifier of specifiers) {\n if (!isAstNode(specifier)) continue;\n if (specifier.type === 'ImportSpecifier') {\n // import { useGT, tx as serverTx } from 'gt-next'\n const importedName = getNodeName(specifier.imported);\n const localName = getNodeName(specifier.local);\n if (importedName && localName) {\n trackImport(localName, importedName, source);\n }\n } else if (specifier.type === 'ImportNamespaceSpecifier') {\n // import * as GT from 'gt-next'\n const localName = getNodeName(specifier.local);\n if (localName) trackNamespaceImport(localName, source);\n }\n }\n },\n\n VariableDeclarator(node: unknown) {\n handleAssignment(node);\n },\n\n CallExpression(node: unknown) {\n handleCallExpression(node);\n },\n };\n },\n};\n"],"mappings":"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"}
|
package/dist/rules/utils.js
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/rules/utils.ts
|
|
3
|
+
const GT_MODULES = [
|
|
4
|
+
"gt-next",
|
|
5
|
+
"gt-next/client",
|
|
6
|
+
"gt-next/server"
|
|
7
|
+
];
|
|
8
8
|
function isAstNode(value) {
|
|
9
|
-
|
|
9
|
+
return typeof value === "object" && value !== null && "type" in value;
|
|
10
10
|
}
|
|
11
11
|
function getNodeName(value) {
|
|
12
|
-
|
|
12
|
+
return isAstNode(value) && typeof value.name === "string" ? value.name : null;
|
|
13
13
|
}
|
|
14
14
|
function isGTModule(source) {
|
|
15
|
-
|
|
15
|
+
return GT_MODULES.includes(source);
|
|
16
16
|
}
|
|
17
17
|
function isStringLiteral(node) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return ((node.type === 'Literal' && typeof node.value === 'string') ||
|
|
21
|
-
(node.type === 'TemplateLiteral' &&
|
|
22
|
-
Array.isArray(node.expressions) &&
|
|
23
|
-
node.expressions.length === 0));
|
|
18
|
+
if (!isAstNode(node)) return false;
|
|
19
|
+
return node.type === "Literal" && typeof node.value === "string" || node.type === "TemplateLiteral" && Array.isArray(node.expressions) && node.expressions.length === 0;
|
|
24
20
|
}
|
|
21
|
+
//#endregion
|
|
22
|
+
exports.getNodeName = getNodeName;
|
|
23
|
+
exports.isAstNode = isAstNode;
|
|
24
|
+
exports.isGTModule = isGTModule;
|
|
25
|
+
exports.isStringLiteral = isStringLiteral;
|
|
26
|
+
|
|
25
27
|
//# sourceMappingURL=utils.js.map
|
package/dist/rules/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../src/rules/utils.ts"],"sourcesContent":["const GT_MODULES = ['gt-next', 'gt-next/client', 'gt-next/server'];\n\nexport type AstNode = {\n type: string;\n [key: string]: unknown;\n};\n\nexport function isAstNode(value: unknown): value is AstNode {\n return typeof value === 'object' && value !== null && 'type' in value;\n}\n\nexport function getNodeName(value: unknown): string | null {\n return isAstNode(value) && typeof value.name === 'string' ? value.name : null;\n}\n\nexport function isGTModule(source: string): boolean {\n return GT_MODULES.includes(source);\n}\n\nexport function isStringLiteral(node: unknown): boolean {\n if (!isAstNode(node)) return false;\n return (\n (node.type === 'Literal' && typeof node.value === 'string') ||\n (node.type === 'TemplateLiteral' &&\n Array.isArray(node.expressions) &&\n node.expressions.length === 0)\n );\n}\n"],"mappings":";;AAAA,MAAM,aAAa;CAAC;CAAW;CAAkB;CAAiB;AAOlE,SAAgB,UAAU,OAAkC;AAC1D,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU;;AAGlE,SAAgB,YAAY,OAA+B;AACzD,QAAO,UAAU,MAAM,IAAI,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;;AAG3E,SAAgB,WAAW,QAAyB;AAClD,QAAO,WAAW,SAAS,OAAO;;AAGpC,SAAgB,gBAAgB,MAAwB;AACtD,KAAI,CAAC,UAAU,KAAK,CAAE,QAAO;AAC7B,QACG,KAAK,SAAS,aAAa,OAAO,KAAK,UAAU,YACjD,KAAK,SAAS,qBACb,MAAM,QAAQ,KAAK,YAAY,IAC/B,KAAK,YAAY,WAAW"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@generaltranslation/gt-next-lint",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.28",
|
|
4
4
|
"description": "ESLint plugin for General Translation Next.js integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"eslint": "^8.0.0 || ^9.0.0",
|
|
38
38
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
39
39
|
"@typescript-eslint/parser": "^8.0.0",
|
|
40
|
-
"gt-next": "6.16.
|
|
40
|
+
"gt-next": "6.16.28"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/eslint": "^8.56.0",
|
|
@@ -45,16 +45,18 @@
|
|
|
45
45
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
46
46
|
"@typescript-eslint/parser": "^8.0.0",
|
|
47
47
|
"eslint": "^9.0.0",
|
|
48
|
+
"tsdown": "^0.21.10",
|
|
48
49
|
"typescript": "^5.9.2",
|
|
49
50
|
"vitest": "^3.2.4"
|
|
50
51
|
},
|
|
51
52
|
"scripts": {
|
|
52
53
|
"patch": "pnpm version patch",
|
|
53
|
-
"
|
|
54
|
+
"emit-types": "sh ../../scripts/emit-types.sh",
|
|
55
|
+
"transpile": "tsdown && pnpm run emit-types",
|
|
54
56
|
"build": "pnpm run transpile",
|
|
55
57
|
"build:clean": "sh ../../scripts/clean.sh && pnpm run build",
|
|
56
58
|
"build:release": "pnpm run build:clean",
|
|
57
|
-
"dev": "
|
|
59
|
+
"dev": "tsdown --watch",
|
|
58
60
|
"release": "pnpm run build:clean && pnpm publish",
|
|
59
61
|
"release:alpha": "pnpm run build:clean && pnpm publish --tag alpha",
|
|
60
62
|
"release:beta": "pnpm run build:clean && pnpm publish --tag beta",
|