@generaltranslation/gt-next-lint 14.0.27 → 14.0.29

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.
@@ -1,19 +1,17 @@
1
- "use strict";
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/configs/recommended.ts
2
3
  /**
3
- * Recommended ESLint configuration for GT-Next
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.recommended = void 0;
7
- exports.recommended = {
8
- plugins: ['gt-next'],
9
- rules: {
10
- 'gt-next/no-dynamic-jsx': true,
11
- 'gt-next/no-dynamic-string': true,
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","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEU,QAAA,WAAW,GAAG;IACzB,OAAO,EAAE,CAAC,SAAS,CAAC;IACpB,KAAK,EAAE;QACL,wBAAwB,EAAE,IAAI;QAC9B,2BAA2B,EAAE,IAAI;KAClC;IACD,QAAQ,EAAE;QACR,KAAK,EAAE;YACL,OAAO,EAAE,QAAQ;SAClB;KACF;CACF,CAAC"}
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
- "use strict";
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
- * GT-Next ESLint Plugin
4
- *
5
- * Provides ESLint rules for General Translation Next.js integration.
6
- * This plugin detects unwrapped dynamic content in translation components
7
- * and provides better error reporting with file locations and line numbers.
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
- meta: {
14
- name: '@generaltranslation/gt-next-lint',
15
- version: '1.0.0',
16
- },
17
- rules: {
18
- 'no-dynamic-jsx': no_dynamic_jsx_1.noDynamicJsx,
19
- 'no-dynamic-string': no_dynamic_string_1.noDynamicString,
20
- },
21
- configs: {
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","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;AAEH,2DAAsD;AACtD,iEAA4D;AAC5D,uDAAoD;AAEpD,MAAM,MAAM,GAAG;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,kCAAkC;QACxC,OAAO,EAAE,OAAO;KACjB;IACD,KAAK,EAAE;QACL,gBAAgB,EAAE,6BAAY;QAC9B,mBAAmB,EAAE,mCAAe;KACrC;IACD,OAAO,EAAE;QACP,WAAW,EAAX,yBAAW;KACZ;CACF,CAAC;AAEF,iBAAS,MAAM,CAAC"}
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
- "use strict";
2
- /**
3
- * ESLint rule: no-dynamic-jsx
4
- *
5
- * Detects unwrapped dynamic content in GT-Next translation components.
6
- * Equivalent to the SWC plugin functionality but with proper ESLint error reporting.
7
- *
8
- * This rule checks for JSX expressions ({dynamic content}) inside <T> components
9
- * that are not wrapped in variable components (<Var>, <DateTime>, <Num>, <Currency>).
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
- return TRANSLATION_COMPONENTS.includes(name);
12
+ return TRANSLATION_COMPONENTS.includes(name);
18
13
  }
19
14
  function isVariableComponent(name) {
20
- return VARIABLE_COMPONENTS.includes(name);
15
+ return VARIABLE_COMPONENTS.includes(name);
21
16
  }
22
- exports.noDynamicJsx = {
23
- meta: {
24
- type: 'problem',
25
- docs: {
26
- description: 'Detect unwrapped dynamic content in GT-Next translation components',
27
- category: 'Best Practices',
28
- recommended: true,
29
- url: 'https://github.com/generaltranslation/gt/tree/main/packages/next-lint#no-dynamic-jsx',
30
- },
31
- fixable: undefined,
32
- schema: [],
33
- messages: {
34
- dynamicJsx: 'Dynamic content in <T> component should be wrapped in a variable component (<Var>, <DateTime>, <Num>, or <Currency>)',
35
- },
36
- },
37
- create(context) {
38
- const state = {
39
- translationStack: 0,
40
- variableStack: 0,
41
- imports: {
42
- translationComponents: new Set(),
43
- variableComponents: new Set(),
44
- namespaceImports: new Set(),
45
- assignedTranslationComponents: new Set(),
46
- assignedVariableComponents: new Set(),
47
- },
48
- };
49
- function getElementName(node) {
50
- if (!(0, utils_1.isAstNode)(node) || !(0, utils_1.isAstNode)(node.openingElement))
51
- return null;
52
- const name = node.openingElement.name;
53
- if (!(0, utils_1.isAstNode)(name))
54
- return null;
55
- if (name.type === 'JSXIdentifier') {
56
- return (0, utils_1.getNodeName)(name);
57
- }
58
- if (name.type === 'JSXMemberExpression') {
59
- const obj = name.object;
60
- const prop = name.property;
61
- if ((0, utils_1.isAstNode)(obj) &&
62
- (0, utils_1.isAstNode)(prop) &&
63
- obj.type === 'JSXIdentifier' &&
64
- prop.type === 'JSXIdentifier') {
65
- const objectName = (0, utils_1.getNodeName)(obj);
66
- const propertyName = (0, utils_1.getNodeName)(prop);
67
- return objectName && propertyName
68
- ? `${objectName}.${propertyName}`
69
- : null;
70
- }
71
- }
72
- return null;
73
- }
74
- function isNamespaceTranslationComponent(elementName) {
75
- const parts = elementName.split('.');
76
- if (parts.length === 2) {
77
- const [namespace, component] = parts;
78
- return (state.imports.namespaceImports.has(namespace) &&
79
- isTranslationComponent(component));
80
- }
81
- return false;
82
- }
83
- function isNamespaceVariableComponent(elementName) {
84
- const parts = elementName.split('.');
85
- if (parts.length === 2) {
86
- const [namespace, component] = parts;
87
- return (state.imports.namespaceImports.has(namespace) &&
88
- isVariableComponent(component));
89
- }
90
- return false;
91
- }
92
- function isInsideJSXAttribute(node) {
93
- if (!(0, utils_1.isAstNode)(node))
94
- return false;
95
- // Walk up the AST to check if this expression is inside a JSX attribute
96
- let currentNode = (0, utils_1.isAstNode)(node.parent) ? node.parent : null;
97
- while (currentNode) {
98
- if (currentNode.type === 'JSXAttribute') {
99
- return true;
100
- }
101
- // If we reach a JSX element, we're in element content, not attributes
102
- if (currentNode.type === 'JSXElement') {
103
- return false;
104
- }
105
- currentNode = (0, utils_1.isAstNode)(currentNode.parent) ? currentNode.parent : null;
106
- }
107
- return false;
108
- }
109
- // Check if the node is a comment
110
- function isComment(expression) {
111
- if (!(0, utils_1.isAstNode)(expression))
112
- return false;
113
- return expression.type === 'Block' || expression.type === 'Line';
114
- }
115
- // Check if empty
116
- function isEmpty(expression) {
117
- if (!(0, utils_1.isAstNode)(expression))
118
- return false;
119
- return expression.type === 'JSXEmptyExpression';
120
- }
121
- return {
122
- // Track imports from GT-Next modules
123
- ImportDeclaration(node) {
124
- if (!(0, utils_1.isAstNode)(node) || !(0, utils_1.isAstNode)(node.source))
125
- return;
126
- if (node.source?.type === 'Literal' &&
127
- typeof node.source.value === 'string') {
128
- const source = node.source.value;
129
- if ((0, utils_1.isGTModule)(source)) {
130
- const specifiers = Array.isArray(node.specifiers)
131
- ? node.specifiers
132
- : [];
133
- for (const specifier of specifiers) {
134
- if (!(0, utils_1.isAstNode)(specifier))
135
- continue;
136
- if (specifier.type === 'ImportSpecifier') {
137
- const importedName = (0, utils_1.getNodeName)(specifier.imported) || '';
138
- const localName = (0, utils_1.getNodeName)(specifier.local) || '';
139
- if (isTranslationComponent(importedName)) {
140
- state.imports.translationComponents.add(localName);
141
- }
142
- else if (isVariableComponent(importedName)) {
143
- state.imports.variableComponents.add(localName);
144
- }
145
- }
146
- else if (specifier.type === 'ImportNamespaceSpecifier') {
147
- const localName = (0, utils_1.getNodeName)(specifier.local) || '';
148
- state.imports.namespaceImports.add(localName);
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
- "use strict";
2
- /**
3
- * ESLint rule: no-dynamic-string
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
- return TRANSLATION_FUNCTIONS.includes(name);
6
+ return TRANSLATION_FUNCTIONS.includes(name);
15
7
  }
16
- exports.noDynamicString = {
17
- meta: {
18
- type: 'problem',
19
- docs: {
20
- description: 'Translation functions must use string literals as the first argument',
21
- category: 'Best Practices',
22
- recommended: true,
23
- url: 'https://github.com/generaltranslation/gt/tree/main/packages/next-lint#no-dynamic-string',
24
- },
25
- fixable: undefined,
26
- schema: [],
27
- messages: {
28
- 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.",
29
- },
30
- },
31
- create(context) {
32
- // Track imported GT functions and their aliases
33
- const trackedFunctions = new Map();
34
- // Track variables assigned from translation function calls
35
- const translationVariables = new Set();
36
- function trackImport(localName, importedName, source) {
37
- if ((0, utils_1.isGTModule)(source) && isTranslationFunction(importedName)) {
38
- trackedFunctions.set(localName, {
39
- name: importedName,
40
- isTranslationFunction: true,
41
- });
42
- }
43
- }
44
- function trackNamespaceImport(localName, source) {
45
- if ((0, utils_1.isGTModule)(source)) {
46
- trackedFunctions.set(localName, {
47
- name: localName,
48
- isTranslationFunction: false, // It's a namespace, not directly callable
49
- });
50
- }
51
- }
52
- function validateTranslationCall(node) {
53
- if (!(0, utils_1.isAstNode)(node) || !Array.isArray(node.arguments))
54
- return;
55
- const firstArg = node.arguments[0];
56
- if (!firstArg)
57
- return; // No arguments
58
- if (!(0, utils_1.isStringLiteral)(firstArg)) {
59
- context.report({
60
- node: firstArg,
61
- messageId: 'dynamicString',
62
- });
63
- }
64
- }
65
- function handleCallExpression(node) {
66
- if (!(0, utils_1.isAstNode)(node) || !(0, utils_1.isAstNode)(node.callee))
67
- return;
68
- if (node.callee.type === 'Identifier') {
69
- // Direct function calls: t(), useGT(), etc.
70
- const functionName = (0, utils_1.getNodeName)(node.callee);
71
- if (!functionName)
72
- return;
73
- if (trackedFunctions.has(functionName)) {
74
- const tracked = trackedFunctions.get(functionName);
75
- if (tracked.isTranslationFunction) {
76
- validateTranslationCall(node);
77
- }
78
- }
79
- else if (translationVariables.has(functionName)) {
80
- // Variable assigned from translation function
81
- validateTranslationCall(node);
82
- }
83
- }
84
- else if (node.callee.type === 'MemberExpression') {
85
- // Member expressions: GT.tx(), namespace.function()
86
- const objectName = (0, utils_1.getNodeName)(node.callee.object);
87
- const propertyName = (0, utils_1.getNodeName)(node.callee.property);
88
- if (!objectName || !propertyName)
89
- return;
90
- if (trackedFunctions.has(objectName) &&
91
- isTranslationFunction(propertyName)) {
92
- validateTranslationCall(node);
93
- }
94
- }
95
- }
96
- function handleAssignment(node) {
97
- // Track variables assigned from translation function calls
98
- if ((0, utils_1.isAstNode)(node) &&
99
- node.type === 'VariableDeclarator' &&
100
- (0, utils_1.isAstNode)(node.id) &&
101
- node.id.type === 'Identifier' &&
102
- (0, utils_1.isAstNode)(node.init)) {
103
- if (node.init.type === 'CallExpression') {
104
- const callExpression = node.init;
105
- if ((0, utils_1.isAstNode)(callExpression.callee) &&
106
- callExpression.callee.type === 'Identifier') {
107
- const functionName = (0, utils_1.getNodeName)(callExpression.callee);
108
- if (!functionName)
109
- return;
110
- if (trackedFunctions.has(functionName)) {
111
- const tracked = trackedFunctions.get(functionName);
112
- if (tracked.isTranslationFunction) {
113
- // This variable now holds a translation function
114
- const variableName = (0, utils_1.getNodeName)(node.id);
115
- if (variableName)
116
- translationVariables.add(variableName);
117
- }
118
- }
119
- }
120
- else if ((0, utils_1.isAstNode)(callExpression.callee) &&
121
- callExpression.callee.type === 'MemberExpression') {
122
- // Handle namespace calls like: const t = GT.useGT();
123
- const objectName = (0, utils_1.getNodeName)(callExpression.callee.object);
124
- const propertyName = (0, utils_1.getNodeName)(callExpression.callee.property);
125
- if (objectName &&
126
- propertyName &&
127
- trackedFunctions.has(objectName) &&
128
- isTranslationFunction(propertyName)) {
129
- // This variable now holds a translation function
130
- const variableName = (0, utils_1.getNodeName)(node.id);
131
- if (variableName)
132
- translationVariables.add(variableName);
133
- }
134
- }
135
- }
136
- else if (node.init.type === 'AwaitExpression' &&
137
- (0, utils_1.isAstNode)(node.init.argument) &&
138
- node.init.argument.type === 'CallExpression') {
139
- // Handle await getGT() case
140
- const callExpression = node.init.argument;
141
- if ((0, utils_1.isAstNode)(callExpression.callee) &&
142
- callExpression.callee.type === 'Identifier') {
143
- const functionName = (0, utils_1.getNodeName)(callExpression.callee);
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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"}
@@ -1,25 +1,27 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isAstNode = isAstNode;
4
- exports.getNodeName = getNodeName;
5
- exports.isGTModule = isGTModule;
6
- exports.isStringLiteral = isStringLiteral;
7
- const GT_MODULES = ['gt-next', 'gt-next/client', 'gt-next/server'];
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
- return typeof value === 'object' && value !== null && 'type' in value;
9
+ return typeof value === "object" && value !== null && "type" in value;
10
10
  }
11
11
  function getNodeName(value) {
12
- return isAstNode(value) && typeof value.name === 'string' ? value.name : null;
12
+ return isAstNode(value) && typeof value.name === "string" ? value.name : null;
13
13
  }
14
14
  function isGTModule(source) {
15
- return GT_MODULES.includes(source);
15
+ return GT_MODULES.includes(source);
16
16
  }
17
17
  function isStringLiteral(node) {
18
- if (!isAstNode(node))
19
- return false;
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
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/rules/utils.ts"],"names":[],"mappings":";;AAOA,8BAEC;AAED,kCAEC;AAED,gCAEC;AAED,0CAQC;AA3BD,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAOnE,SAAgB,SAAS,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAC;AACxE,CAAC;AAED,SAAgB,WAAW,CAAC,KAAc;IACxC,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAChF,CAAC;AAED,SAAgB,UAAU,CAAC,MAAc;IACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,eAAe,CAAC,IAAa;IAC3C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,CACL,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC;QAC3D,CAAC,IAAI,CAAC,IAAI,KAAK,iBAAiB;YAC9B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;YAC/B,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CACjC,CAAC;AACJ,CAAC"}
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.27",
3
+ "version": "14.0.29",
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.27"
40
+ "gt-next": "6.16.29"
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
- "transpile": "tsc",
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": "tsc --watch",
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",