@astroscope/eslint-plugin-i18n 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +99 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ var noModuleLevelT = {
|
|
|
16
16
|
schema: []
|
|
17
17
|
},
|
|
18
18
|
create(context) {
|
|
19
|
+
if (context.filename.endsWith(".astro")) return {};
|
|
19
20
|
return {
|
|
20
21
|
CallExpression(node) {
|
|
21
22
|
if (node.callee.type !== "Identifier" || node.callee.name !== "t") return;
|
|
@@ -40,14 +41,21 @@ var DEFAULT_IGNORE_PATTERNS = [
|
|
|
40
41
|
// numbers
|
|
41
42
|
/^\s*\|\s*$/,
|
|
42
43
|
// pipe separators
|
|
43
|
-
/^\s*[•·–—]\s
|
|
44
|
+
/^\s*[•·–—]\s*$/,
|
|
44
45
|
// bullets / dashes
|
|
46
|
+
/^[\s\p{P}\p{S}]+$/u,
|
|
47
|
+
// punctuation / symbols only (e.g. "(", ",", "/ —")
|
|
48
|
+
/^#[0-9a-fA-F]{3,8}$/,
|
|
49
|
+
// hex colors (e.g. "#003366", "#fff")
|
|
50
|
+
/^\d+x\d+$/
|
|
51
|
+
// dimensions (e.g. "180x180")
|
|
45
52
|
];
|
|
46
53
|
var DEFAULT_IGNORE_ATTRIBUTES = [
|
|
47
|
-
|
|
48
|
-
"class",
|
|
54
|
+
// html attributes
|
|
49
55
|
"id",
|
|
50
|
-
"
|
|
56
|
+
"class",
|
|
57
|
+
"className",
|
|
58
|
+
"style",
|
|
51
59
|
"href",
|
|
52
60
|
"src",
|
|
53
61
|
"type",
|
|
@@ -59,9 +67,70 @@ var DEFAULT_IGNORE_ATTRIBUTES = [
|
|
|
59
67
|
"rel",
|
|
60
68
|
"method",
|
|
61
69
|
"action",
|
|
70
|
+
"loading",
|
|
71
|
+
"decoding",
|
|
72
|
+
"autoComplete",
|
|
73
|
+
"allow",
|
|
74
|
+
"as",
|
|
75
|
+
"sizes",
|
|
76
|
+
"color",
|
|
77
|
+
"crossorigin",
|
|
78
|
+
"referrerpolicy",
|
|
79
|
+
"charset",
|
|
80
|
+
"lang",
|
|
81
|
+
"form",
|
|
82
|
+
"key",
|
|
83
|
+
"slot",
|
|
84
|
+
// common component props
|
|
85
|
+
"variant",
|
|
86
|
+
"size",
|
|
87
|
+
"mode",
|
|
88
|
+
"orientation",
|
|
89
|
+
"align",
|
|
90
|
+
"icon",
|
|
91
|
+
"tag",
|
|
92
|
+
"tagName",
|
|
93
|
+
// html aria attributes (non-text)
|
|
94
|
+
"aria-hidden",
|
|
95
|
+
"aria-live",
|
|
96
|
+
"aria-atomic",
|
|
97
|
+
// astro attributes
|
|
98
|
+
"class:list",
|
|
99
|
+
// testing attributes
|
|
62
100
|
"data-testid",
|
|
63
101
|
"data-cy",
|
|
64
|
-
|
|
102
|
+
// svg attributes
|
|
103
|
+
"d",
|
|
104
|
+
"viewBox",
|
|
105
|
+
"xmlns",
|
|
106
|
+
"fill",
|
|
107
|
+
"stroke",
|
|
108
|
+
"strokeWidth",
|
|
109
|
+
"strokeLinecap",
|
|
110
|
+
"strokeLinejoin",
|
|
111
|
+
"clipPath",
|
|
112
|
+
"transform",
|
|
113
|
+
"points",
|
|
114
|
+
"pathLength",
|
|
115
|
+
"filter",
|
|
116
|
+
"filterUnits",
|
|
117
|
+
"colorInterpolationFilters",
|
|
118
|
+
"floodOpacity",
|
|
119
|
+
"in",
|
|
120
|
+
"in2",
|
|
121
|
+
"result",
|
|
122
|
+
"stroke-linecap",
|
|
123
|
+
"stroke-linejoin",
|
|
124
|
+
"clip-rule",
|
|
125
|
+
"fill-rule",
|
|
126
|
+
"path",
|
|
127
|
+
"values"
|
|
128
|
+
];
|
|
129
|
+
var DEFAULT_IGNORE_ATTRIBUTE_PATTERNS = [
|
|
130
|
+
/className$/i,
|
|
131
|
+
// *ClassName, *classname (e.g. labelClassName, pictureClassName)
|
|
132
|
+
/^data-/
|
|
133
|
+
// data-* attributes
|
|
65
134
|
];
|
|
66
135
|
var noRawStringsInJsx = {
|
|
67
136
|
meta: {
|
|
@@ -91,21 +160,24 @@ var noRawStringsInJsx = {
|
|
|
91
160
|
},
|
|
92
161
|
create(context) {
|
|
93
162
|
const options = context.options[0] ?? {};
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
const ignoreAttributes = /* @__PURE__ */ new Set([...DEFAULT_IGNORE_ATTRIBUTES, ...options.ignoreAttributes ?? []]);
|
|
163
|
+
const allPatterns = options.ignorePatterns ? options.ignorePatterns.map((p) => new RegExp(p)) : DEFAULT_IGNORE_PATTERNS;
|
|
164
|
+
const ignoreAttributes = new Set(options.ignoreAttributes ?? DEFAULT_IGNORE_ATTRIBUTES);
|
|
97
165
|
function shouldIgnore(text) {
|
|
98
166
|
return allPatterns.some((p) => p.test(text));
|
|
99
167
|
}
|
|
168
|
+
function shouldIgnoreAttribute(name) {
|
|
169
|
+
if (ignoreAttributes.has(name)) return true;
|
|
170
|
+
return DEFAULT_IGNORE_ATTRIBUTE_PATTERNS.some((p) => p.test(name));
|
|
171
|
+
}
|
|
100
172
|
function isInsideIgnoredAttribute(node) {
|
|
101
173
|
const parent = node.parent;
|
|
102
174
|
if (parent?.type === "JSXAttribute") {
|
|
103
175
|
const attrName = parent.name?.type === "JSXIdentifier" ? parent.name.name : parent.name?.type === "JSXNamespacedName" ? `${parent.name.namespace.name}:${parent.name.name.name}` : null;
|
|
104
|
-
if (attrName &&
|
|
176
|
+
if (attrName && shouldIgnoreAttribute(attrName)) return true;
|
|
105
177
|
}
|
|
106
178
|
if (parent?.type === "JSXExpressionContainer" && parent.parent?.type === "JSXAttribute") {
|
|
107
179
|
const attrName = parent.parent.name?.type === "JSXIdentifier" ? parent.parent.name.name : null;
|
|
108
|
-
if (attrName &&
|
|
180
|
+
if (attrName && shouldIgnoreAttribute(attrName)) return true;
|
|
109
181
|
}
|
|
110
182
|
return false;
|
|
111
183
|
}
|
|
@@ -129,12 +201,28 @@ var noRawStringsInJsx = {
|
|
|
129
201
|
if (shouldIgnore(text)) return;
|
|
130
202
|
if (isInsideIgnoredAttribute(node)) return;
|
|
131
203
|
const attrName = node.name?.type === "JSXIdentifier" ? node.name.name : node.name?.type === "JSXNamespacedName" ? `${node.name.namespace.name}:${node.name.name.name}` : null;
|
|
132
|
-
if (attrName &&
|
|
204
|
+
if (attrName && shouldIgnoreAttribute(attrName)) return;
|
|
133
205
|
context.report({
|
|
134
206
|
node: node.value,
|
|
135
207
|
messageId: "rawString",
|
|
136
208
|
data: { text: text.length > 40 ? `${text.slice(0, 40)}...` : text }
|
|
137
209
|
});
|
|
210
|
+
},
|
|
211
|
+
// string literals inside JSX expressions: <div title={value ?? 'fallback'} /> or <div>{'text'}</div>
|
|
212
|
+
Literal(node) {
|
|
213
|
+
if (typeof node.value !== "string") return;
|
|
214
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
215
|
+
const inJsxExpression = ancestors.some((a) => a.type === "JSXExpressionContainer");
|
|
216
|
+
if (!inJsxExpression) return;
|
|
217
|
+
if (ancestors.some((a) => a.type === "CallExpression")) return;
|
|
218
|
+
const text = node.value;
|
|
219
|
+
if (shouldIgnore(text)) return;
|
|
220
|
+
if (isInsideIgnoredAttribute(node)) return;
|
|
221
|
+
context.report({
|
|
222
|
+
node,
|
|
223
|
+
messageId: "rawString",
|
|
224
|
+
data: { text: text.length > 40 ? `${text.slice(0, 40)}...` : text }
|
|
225
|
+
});
|
|
138
226
|
}
|
|
139
227
|
};
|
|
140
228
|
}
|