@astroscope/eslint-plugin-i18n 0.1.1 → 0.1.3
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 +135 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,14 +41,21 @@ var DEFAULT_IGNORE_PATTERNS = [
|
|
|
41
41
|
// numbers
|
|
42
42
|
/^\s*\|\s*$/,
|
|
43
43
|
// pipe separators
|
|
44
|
-
/^\s*[•·–—]\s
|
|
44
|
+
/^\s*[•·–—]\s*$/,
|
|
45
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")
|
|
46
52
|
];
|
|
47
53
|
var DEFAULT_IGNORE_ATTRIBUTES = [
|
|
48
|
-
|
|
49
|
-
"class",
|
|
54
|
+
// html attributes
|
|
50
55
|
"id",
|
|
51
|
-
"
|
|
56
|
+
"class",
|
|
57
|
+
"className",
|
|
58
|
+
"style",
|
|
52
59
|
"href",
|
|
53
60
|
"src",
|
|
54
61
|
"type",
|
|
@@ -60,9 +67,93 @@ var DEFAULT_IGNORE_ATTRIBUTES = [
|
|
|
60
67
|
"rel",
|
|
61
68
|
"method",
|
|
62
69
|
"action",
|
|
70
|
+
"loading",
|
|
71
|
+
"decoding",
|
|
72
|
+
"autoComplete",
|
|
73
|
+
"allow",
|
|
74
|
+
"as",
|
|
75
|
+
"sizes",
|
|
76
|
+
"color",
|
|
77
|
+
"crossorigin",
|
|
78
|
+
"fetchPriority",
|
|
79
|
+
"fetchpriority",
|
|
80
|
+
"referrerpolicy",
|
|
81
|
+
"charset",
|
|
82
|
+
"lang",
|
|
83
|
+
"property",
|
|
84
|
+
"itemprop",
|
|
85
|
+
"itemtype",
|
|
86
|
+
"form",
|
|
87
|
+
"key",
|
|
88
|
+
"slot",
|
|
89
|
+
// common component props
|
|
90
|
+
"variant",
|
|
91
|
+
"size",
|
|
92
|
+
"mode",
|
|
93
|
+
"orientation",
|
|
94
|
+
"align",
|
|
95
|
+
"icon",
|
|
96
|
+
"tag",
|
|
97
|
+
"tagName",
|
|
98
|
+
// html aria attributes (non-text)
|
|
99
|
+
"aria-hidden",
|
|
100
|
+
"aria-live",
|
|
101
|
+
"aria-atomic",
|
|
102
|
+
// astro attributes
|
|
103
|
+
"class:list",
|
|
104
|
+
// testing attributes
|
|
63
105
|
"data-testid",
|
|
64
106
|
"data-cy",
|
|
65
|
-
|
|
107
|
+
// svg attributes
|
|
108
|
+
"d",
|
|
109
|
+
"viewBox",
|
|
110
|
+
"xmlns",
|
|
111
|
+
"fill",
|
|
112
|
+
"stroke",
|
|
113
|
+
"strokeWidth",
|
|
114
|
+
"strokeLinecap",
|
|
115
|
+
"strokeLinejoin",
|
|
116
|
+
"clipPath",
|
|
117
|
+
"transform",
|
|
118
|
+
"points",
|
|
119
|
+
"pathLength",
|
|
120
|
+
"filter",
|
|
121
|
+
"filterUnits",
|
|
122
|
+
"colorInterpolationFilters",
|
|
123
|
+
"floodOpacity",
|
|
124
|
+
"in",
|
|
125
|
+
"in2",
|
|
126
|
+
"result",
|
|
127
|
+
"stroke-linecap",
|
|
128
|
+
"stroke-linejoin",
|
|
129
|
+
"clip-rule",
|
|
130
|
+
"fill-rule",
|
|
131
|
+
"path",
|
|
132
|
+
"values",
|
|
133
|
+
"operator",
|
|
134
|
+
"mode",
|
|
135
|
+
"stdDeviation",
|
|
136
|
+
"dy",
|
|
137
|
+
"dx",
|
|
138
|
+
"x",
|
|
139
|
+
"y",
|
|
140
|
+
"x1",
|
|
141
|
+
"x2",
|
|
142
|
+
"y1",
|
|
143
|
+
"y2",
|
|
144
|
+
"cx",
|
|
145
|
+
"cy",
|
|
146
|
+
"r",
|
|
147
|
+
"rx",
|
|
148
|
+
"ry",
|
|
149
|
+
"width",
|
|
150
|
+
"height"
|
|
151
|
+
];
|
|
152
|
+
var DEFAULT_IGNORE_ATTRIBUTE_PATTERNS = [
|
|
153
|
+
/classNames?$/i,
|
|
154
|
+
// *ClassName, *classNames, *classname (e.g. labelClassName, classNames)
|
|
155
|
+
/^data-/
|
|
156
|
+
// data-* attributes
|
|
66
157
|
];
|
|
67
158
|
var noRawStringsInJsx = {
|
|
68
159
|
meta: {
|
|
@@ -92,21 +183,30 @@ var noRawStringsInJsx = {
|
|
|
92
183
|
},
|
|
93
184
|
create(context) {
|
|
94
185
|
const options = context.options[0] ?? {};
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const ignoreAttributes = /* @__PURE__ */ new Set([...DEFAULT_IGNORE_ATTRIBUTES, ...options.ignoreAttributes ?? []]);
|
|
186
|
+
const allPatterns = options.ignorePatterns ? options.ignorePatterns.map((p) => new RegExp(p)) : DEFAULT_IGNORE_PATTERNS;
|
|
187
|
+
const ignoreAttributes = new Set(options.ignoreAttributes ?? DEFAULT_IGNORE_ATTRIBUTES);
|
|
98
188
|
function shouldIgnore(text) {
|
|
99
189
|
return allPatterns.some((p) => p.test(text));
|
|
100
190
|
}
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
191
|
+
function shouldIgnoreAttribute(name) {
|
|
192
|
+
if (ignoreAttributes.has(name)) return true;
|
|
193
|
+
return DEFAULT_IGNORE_ATTRIBUTE_PATTERNS.some((p) => p.test(name));
|
|
194
|
+
}
|
|
195
|
+
function getAttributeName(node) {
|
|
196
|
+
if (node.name?.type === "JSXIdentifier") return node.name.name;
|
|
197
|
+
if (node.name?.type === "JSXNamespacedName") {
|
|
198
|
+
return `${node.name.namespace.name}:${node.name.name.name}`;
|
|
106
199
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
function isInsideIgnoredAttribute(node) {
|
|
203
|
+
let current = node.parent;
|
|
204
|
+
while (current) {
|
|
205
|
+
if (current.type === "JSXAttribute") {
|
|
206
|
+
const attrName = getAttributeName(current);
|
|
207
|
+
return attrName ? shouldIgnoreAttribute(attrName) : false;
|
|
208
|
+
}
|
|
209
|
+
current = current.parent;
|
|
110
210
|
}
|
|
111
211
|
return false;
|
|
112
212
|
}
|
|
@@ -130,12 +230,30 @@ var noRawStringsInJsx = {
|
|
|
130
230
|
if (shouldIgnore(text)) return;
|
|
131
231
|
if (isInsideIgnoredAttribute(node)) return;
|
|
132
232
|
const attrName = node.name?.type === "JSXIdentifier" ? node.name.name : node.name?.type === "JSXNamespacedName" ? `${node.name.namespace.name}:${node.name.name.name}` : null;
|
|
133
|
-
if (attrName &&
|
|
233
|
+
if (attrName && shouldIgnoreAttribute(attrName)) return;
|
|
134
234
|
context.report({
|
|
135
235
|
node: node.value,
|
|
136
236
|
messageId: "rawString",
|
|
137
237
|
data: { text: text.length > 40 ? `${text.slice(0, 40)}...` : text }
|
|
138
238
|
});
|
|
239
|
+
},
|
|
240
|
+
// string literals inside JSX expressions: <div title={value ?? 'fallback'} /> or <div>{'text'}</div>
|
|
241
|
+
Literal(node) {
|
|
242
|
+
if (typeof node.value !== "string") return;
|
|
243
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
244
|
+
const inJsxExpression = ancestors.some((a) => a.type === "JSXExpressionContainer");
|
|
245
|
+
if (!inJsxExpression) return;
|
|
246
|
+
if (ancestors.some((a) => a.type === "CallExpression")) return;
|
|
247
|
+
if (node.parent?.type === "BinaryExpression") return;
|
|
248
|
+
if (node.parent?.type === "TSAsExpression") return;
|
|
249
|
+
const text = node.value;
|
|
250
|
+
if (shouldIgnore(text)) return;
|
|
251
|
+
if (isInsideIgnoredAttribute(node)) return;
|
|
252
|
+
context.report({
|
|
253
|
+
node,
|
|
254
|
+
messageId: "rawString",
|
|
255
|
+
data: { text: text.length > 40 ? `${text.slice(0, 40)}...` : text }
|
|
256
|
+
});
|
|
139
257
|
}
|
|
140
258
|
};
|
|
141
259
|
}
|