@html-eslint/core 0.56.0
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/LICENSE +21 -0
- package/README.md +31 -0
- package/dist/index.d.mts +237 -0
- package/dist/index.d.ts +237 -0
- package/dist/index.js +2037 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2001 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2001 @@
|
|
|
1
|
+
// lib/rules/no-invalid-attr-value.js
|
|
2
|
+
import { element } from "html-standard";
|
|
3
|
+
var NO_INVALID_ATTR_VALUE_MESSAGE_IDS = {
|
|
4
|
+
invalid: "invalid"
|
|
5
|
+
};
|
|
6
|
+
function noInvalidAttrValue(options) {
|
|
7
|
+
const allowList = options.allow || [];
|
|
8
|
+
const compiledAllowList = allowList.map((rule) => ({
|
|
9
|
+
tag: rule.tag.toLowerCase(),
|
|
10
|
+
attr: rule.attr.toLowerCase(),
|
|
11
|
+
valuePattern: rule.valuePattern ? new RegExp(rule.valuePattern) : void 0
|
|
12
|
+
}));
|
|
13
|
+
function shouldAllow(elementName, attrKey, attrValue) {
|
|
14
|
+
return compiledAllowList.some((allowRule) => {
|
|
15
|
+
const tagMatch = allowRule.tag === elementName.toLowerCase();
|
|
16
|
+
const attrMatch = allowRule.attr === attrKey.toLowerCase();
|
|
17
|
+
if (!tagMatch || !attrMatch) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if (allowRule.valuePattern === void 0) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return allowRule.valuePattern.test(attrValue);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
/**
|
|
28
|
+
* @param {ElementNodeAdapter<
|
|
29
|
+
* ElementNode,
|
|
30
|
+
* AttributeKeyNode,
|
|
31
|
+
* AttributeValueNode
|
|
32
|
+
* >} adapter
|
|
33
|
+
* @returns {NoInvalidAttrValueResult<
|
|
34
|
+
* AttributeKeyNode,
|
|
35
|
+
* AttributeValueNode
|
|
36
|
+
* >}
|
|
37
|
+
*/
|
|
38
|
+
checkAttributes(adapter) {
|
|
39
|
+
const name = adapter.getTagName();
|
|
40
|
+
if (name.includes("-")) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
const spec = element(name);
|
|
44
|
+
const result = [];
|
|
45
|
+
for (const attribute of adapter.getAttributes()) {
|
|
46
|
+
if (attribute.key.isExpression()) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (attribute.value.isExpression()) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const attrKeyValue = attribute.key.value();
|
|
53
|
+
const attrValueValue = attribute.value.value();
|
|
54
|
+
if (attrValueValue === null) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (attrKeyValue && shouldAllow(name, attrKeyValue, attrValueValue)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (!attrKeyValue || attrValueValue === null) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const validator = spec.attributes.get(attrKeyValue);
|
|
64
|
+
if (validator) {
|
|
65
|
+
const validateResult = validator.validateValue(attrValueValue);
|
|
66
|
+
if (!validateResult.valid) {
|
|
67
|
+
result.push({
|
|
68
|
+
node: attribute.value.node() || attribute.key.node(),
|
|
69
|
+
messageId: NO_INVALID_ATTR_VALUE_MESSAGE_IDS.invalid,
|
|
70
|
+
data: {
|
|
71
|
+
value: attrValueValue || "",
|
|
72
|
+
attr: attribute.key.raw() || attrKeyValue,
|
|
73
|
+
element: name,
|
|
74
|
+
suggestion: validateResult.reason || "Use a valid value."
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// lib/utils/baseline.js
|
|
86
|
+
var BASELINE_HIGH = 10;
|
|
87
|
+
var BASELINE_LOW = 5;
|
|
88
|
+
var elements = /* @__PURE__ */ new Map([
|
|
89
|
+
["a", "10:2015"],
|
|
90
|
+
["a.attributionsourceid", "0:"],
|
|
91
|
+
["a.attributionsrc", "0:"],
|
|
92
|
+
["a.download", "10:2019"],
|
|
93
|
+
["a.href", "10:2015"],
|
|
94
|
+
["a.href.href_sms", "0:"],
|
|
95
|
+
["a.href.href_top", "10:2015"],
|
|
96
|
+
["a.hreflang", "10:2015"],
|
|
97
|
+
["a.implicit_noopener", "10:2021"],
|
|
98
|
+
["a.ping", "0:"],
|
|
99
|
+
["a.referrerpolicy", "10:2020"],
|
|
100
|
+
["a.referrerpolicy.no-referrer-when-downgrade", "0:"],
|
|
101
|
+
["a.referrerpolicy.origin-when-cross-origin", "0:"],
|
|
102
|
+
["a.referrerpolicy.unsafe-url", "0:"],
|
|
103
|
+
["a.rel", "10:2015"],
|
|
104
|
+
["a.rel.noopener", "10:2020"],
|
|
105
|
+
["a.rel.noreferrer", "10:2015"],
|
|
106
|
+
["a.target", "10:2015"],
|
|
107
|
+
["a.target.unfencedTop", "0:"],
|
|
108
|
+
["a.text_fragments", "5:2024"],
|
|
109
|
+
["a.type", "10:2015"],
|
|
110
|
+
["abbr", "10:2015"],
|
|
111
|
+
["address", "10:2015"],
|
|
112
|
+
["area", "10:2015"],
|
|
113
|
+
["area.alt", "10:2015"],
|
|
114
|
+
["area.attributionsrc", "0:"],
|
|
115
|
+
["area.coords", "10:2015"],
|
|
116
|
+
["area.download", "10:2017"],
|
|
117
|
+
["area.href", "10:2015"],
|
|
118
|
+
["area.implicit_noopener", "10:2021"],
|
|
119
|
+
["area.ping", "0:"],
|
|
120
|
+
["area.referrerpolicy", "10:2020"],
|
|
121
|
+
["area.referrerpolicy.no-referrer-when-downgrade", "0:"],
|
|
122
|
+
["area.referrerpolicy.origin-when-cross-origin", "0:"],
|
|
123
|
+
["area.referrerpolicy.unsafe-url", "0:"],
|
|
124
|
+
["area.rel", "10:2015"],
|
|
125
|
+
["area.rel.noopener", "10:2020"],
|
|
126
|
+
["area.rel.noreferrer", "10:2015"],
|
|
127
|
+
["area.shape", "10:2015"],
|
|
128
|
+
["area.target", "10:2015"],
|
|
129
|
+
["article", "10:2015"],
|
|
130
|
+
["aside", "10:2015"],
|
|
131
|
+
["audio", "10:2015"],
|
|
132
|
+
["audio.controls", "10:2015"],
|
|
133
|
+
["audio.controlslist", "0:"],
|
|
134
|
+
["audio.crossorigin", "10:2020"],
|
|
135
|
+
["audio.disableremoteplayback", "0:"],
|
|
136
|
+
["audio.loop", "10:2015"],
|
|
137
|
+
["audio.muted", "10:2018"],
|
|
138
|
+
["audio.preload", "10:2015"],
|
|
139
|
+
["audio.src", "10:2015"],
|
|
140
|
+
["b", "10:2015"],
|
|
141
|
+
["base", "10:2015"],
|
|
142
|
+
["base.href", "10:2015"],
|
|
143
|
+
["base.href.forbid_data_javascript_urls", "5:2024"],
|
|
144
|
+
["base.href.relative_url", "10:2015"],
|
|
145
|
+
["base.target", "10:2015"],
|
|
146
|
+
["bdi", "10:2020"],
|
|
147
|
+
["bdo", "10:2015"],
|
|
148
|
+
["blockquote", "10:2015"],
|
|
149
|
+
["blockquote.cite", "10:2015"],
|
|
150
|
+
["body", "10:2015"],
|
|
151
|
+
["br", "10:2015"],
|
|
152
|
+
["button", "10:2015"],
|
|
153
|
+
["button.command", "5:2025"],
|
|
154
|
+
["button.command.request-close", "5:2025"],
|
|
155
|
+
["button.commandfor", "5:2025"],
|
|
156
|
+
["button.disabled", "10:2015"],
|
|
157
|
+
["button.form", "10:2017"],
|
|
158
|
+
["button.formaction", "10:2015"],
|
|
159
|
+
["button.formenctype", "10:2015"],
|
|
160
|
+
["button.formmethod", "10:2015"],
|
|
161
|
+
["button.formnovalidate", "10:2015"],
|
|
162
|
+
["button.formtarget", "10:2015"],
|
|
163
|
+
["button.name", "10:2015"],
|
|
164
|
+
["button.popovertarget", "5:2024"],
|
|
165
|
+
["button.popovertarget.implicit_anchor_reference", "0:"],
|
|
166
|
+
["button.popovertargetaction", "5:2024"],
|
|
167
|
+
["button.type", "10:2015"],
|
|
168
|
+
["button.value", "10:2015"],
|
|
169
|
+
["canvas", "10:2015"],
|
|
170
|
+
["canvas.height", "10:2015"],
|
|
171
|
+
["canvas.width", "10:2015"],
|
|
172
|
+
["caption", "10:2015"],
|
|
173
|
+
["caption.align", "0:"],
|
|
174
|
+
["cite", "10:2015"],
|
|
175
|
+
["code", "10:2015"],
|
|
176
|
+
["col", "10:2015"],
|
|
177
|
+
["col.align", "0:"],
|
|
178
|
+
["col.char", "0:"],
|
|
179
|
+
["col.charoff", "0:"],
|
|
180
|
+
["col.span", "10:2015"],
|
|
181
|
+
["col.valign", "0:"],
|
|
182
|
+
["col.width", "0:"],
|
|
183
|
+
["colgroup", "10:2015"],
|
|
184
|
+
["colgroup.align", "0:"],
|
|
185
|
+
["colgroup.char", "0:"],
|
|
186
|
+
["colgroup.charoff", "0:"],
|
|
187
|
+
["colgroup.span", "10:2015"],
|
|
188
|
+
["colgroup.valign", "0:"],
|
|
189
|
+
["colgroup.width", "0:"],
|
|
190
|
+
["data", "10:2017"],
|
|
191
|
+
["data.value", "10:2017"],
|
|
192
|
+
["datalist", "0:"],
|
|
193
|
+
["dd", "10:2015"],
|
|
194
|
+
["del", "10:2015"],
|
|
195
|
+
["del.cite", "10:2015"],
|
|
196
|
+
["del.datetime", "10:2015"],
|
|
197
|
+
["details", "10:2020"],
|
|
198
|
+
["details.name", "5:2024"],
|
|
199
|
+
["details.open", "10:2020"],
|
|
200
|
+
["dfn", "10:2015"],
|
|
201
|
+
["dialog", "10:2022"],
|
|
202
|
+
["dialog.closedby", "0:"],
|
|
203
|
+
["dialog.open", "10:2022"],
|
|
204
|
+
["div", "10:2015"],
|
|
205
|
+
["dl", "10:2015"],
|
|
206
|
+
["dt", "10:2015"],
|
|
207
|
+
["em", "10:2015"],
|
|
208
|
+
["embed", "10:2015"],
|
|
209
|
+
["embed.height", "10:2015"],
|
|
210
|
+
["embed.src", "10:2015"],
|
|
211
|
+
["embed.type", "10:2020"],
|
|
212
|
+
["embed.width", "10:2015"],
|
|
213
|
+
["fencedframe", "0:"],
|
|
214
|
+
["fencedframe.allow", "0:"],
|
|
215
|
+
["fencedframe.height", "0:"],
|
|
216
|
+
["fencedframe.width", "0:"],
|
|
217
|
+
["fieldset", "10:2015"],
|
|
218
|
+
["fieldset.disabled", "10:2020"],
|
|
219
|
+
["fieldset.form", "10:2015"],
|
|
220
|
+
["fieldset.name", "10:2015"],
|
|
221
|
+
["figcaption", "10:2015"],
|
|
222
|
+
["figure", "10:2015"],
|
|
223
|
+
["footer", "10:2015"],
|
|
224
|
+
["form", "10:2015"],
|
|
225
|
+
["form.accept-charset", "10:2015"],
|
|
226
|
+
["form.action", "10:2015"],
|
|
227
|
+
["form.autocomplete", "10:2015"],
|
|
228
|
+
["form.enctype", "10:2015"],
|
|
229
|
+
["form.method", "10:2015"],
|
|
230
|
+
["form.name", "10:2015"],
|
|
231
|
+
["form.novalidate", "10:2017"],
|
|
232
|
+
["form.rel", "10:2023"],
|
|
233
|
+
["form.target", "10:2015"],
|
|
234
|
+
["h1", "10:2015"],
|
|
235
|
+
["h1.no_ua_styles_in_article_aside_nav_section", "0:"],
|
|
236
|
+
["h2", "10:2015"],
|
|
237
|
+
["h3", "10:2015"],
|
|
238
|
+
["h4", "10:2015"],
|
|
239
|
+
["h5", "10:2015"],
|
|
240
|
+
["h6", "10:2015"],
|
|
241
|
+
["head", "10:2015"],
|
|
242
|
+
["header", "10:2015"],
|
|
243
|
+
["hgroup", "10:2015"],
|
|
244
|
+
["hr", "10:2015"],
|
|
245
|
+
["html", "10:2015"],
|
|
246
|
+
["i", "10:2015"],
|
|
247
|
+
["iframe", "10:2015"],
|
|
248
|
+
["iframe.allow", "10:2020"],
|
|
249
|
+
["iframe.allow.accelerometer", "0:"],
|
|
250
|
+
["iframe.allow.ambient-light-sensor", "0:"],
|
|
251
|
+
["iframe.allow.attribution-reporting", "0:"],
|
|
252
|
+
["iframe.allow.bluetooth", "0:"],
|
|
253
|
+
["iframe.allow.camera", "10:2020"],
|
|
254
|
+
["iframe.allow.compute-pressure", "0:"],
|
|
255
|
+
["iframe.allow.display-capture", "0:"],
|
|
256
|
+
["iframe.allow.encrypted-media", "0:"],
|
|
257
|
+
["iframe.allow.fullscreen", "0:"],
|
|
258
|
+
["iframe.allow.gamepad", "0:"],
|
|
259
|
+
["iframe.allow.geolocation", "0:"],
|
|
260
|
+
["iframe.allow.gyroscope", "0:"],
|
|
261
|
+
["iframe.allow.hid", "0:"],
|
|
262
|
+
["iframe.allow.idle-detection", "0:"],
|
|
263
|
+
["iframe.allow.local-fonts", "0:"],
|
|
264
|
+
["iframe.allow.magnetometer", "0:"],
|
|
265
|
+
["iframe.allow.microphone", "10:2020"],
|
|
266
|
+
["iframe.allow.midi", "0:"],
|
|
267
|
+
["iframe.allow.otp-credentials", "0:"],
|
|
268
|
+
["iframe.allow.payment", "0:"],
|
|
269
|
+
["iframe.allow.picture-in-picture", "0:"],
|
|
270
|
+
["iframe.allow.publickey-credentials-create", "0:"],
|
|
271
|
+
["iframe.allow.publickey-credentials-get", "0:"],
|
|
272
|
+
["iframe.allow.screen-wake-lock", "5:2024"],
|
|
273
|
+
["iframe.allow.serial", "0:"],
|
|
274
|
+
["iframe.allow.storage-access", "0:"],
|
|
275
|
+
["iframe.allow.usb", "0:"],
|
|
276
|
+
["iframe.allow.web-share", "0:"],
|
|
277
|
+
["iframe.allow.window-management", "0:"],
|
|
278
|
+
["iframe.allow.xr-spatial-tracking", "0:"],
|
|
279
|
+
["iframe.allowfullscreen", "0:"],
|
|
280
|
+
["iframe.credentialless", "0:"],
|
|
281
|
+
["iframe.csp", "0:"],
|
|
282
|
+
["iframe.height", "10:2015"],
|
|
283
|
+
["iframe.loading", "5:2023"],
|
|
284
|
+
["iframe.name", "10:2015"],
|
|
285
|
+
["iframe.referrerpolicy", "10:2020"],
|
|
286
|
+
["iframe.referrerpolicy.no-referrer-when-downgrade", "0:"],
|
|
287
|
+
["iframe.referrerpolicy.origin-when-cross-origin", "0:"],
|
|
288
|
+
["iframe.referrerpolicy.unsafe-url", "0:"],
|
|
289
|
+
["iframe.sandbox", "10:2015"],
|
|
290
|
+
["iframe.sandbox.allow-downloads", "5:2023"],
|
|
291
|
+
["iframe.sandbox.allow-forms", "10:2020"],
|
|
292
|
+
["iframe.sandbox.allow-modals", "10:2020"],
|
|
293
|
+
["iframe.sandbox.allow-pointer-lock", "0:"],
|
|
294
|
+
["iframe.sandbox.allow-popups", "10:2015"],
|
|
295
|
+
["iframe.sandbox.allow-popups-to-escape-sandbox", "10:2020"],
|
|
296
|
+
["iframe.sandbox.allow-presentation", "0:"],
|
|
297
|
+
["iframe.sandbox.allow-same-origin", "10:2020"],
|
|
298
|
+
["iframe.sandbox.allow-scripts", "10:2020"],
|
|
299
|
+
["iframe.sandbox.allow-top-navigation", "10:2020"],
|
|
300
|
+
["iframe.sandbox.allow-top-navigation-by-user-activation", "10:2020"],
|
|
301
|
+
["iframe.sandbox.allow-top-navigation-to-custom-protocols", "0:"],
|
|
302
|
+
["iframe.src", "10:2015"],
|
|
303
|
+
["iframe.srcdoc", "10:2020"],
|
|
304
|
+
["iframe.width", "10:2015"],
|
|
305
|
+
["img", "10:2015"],
|
|
306
|
+
["img.alt", "10:2015"],
|
|
307
|
+
["img.aspect_ratio_computed_from_attributes", "10:2021"],
|
|
308
|
+
["img.attributionsrc", "0:"],
|
|
309
|
+
["img.crossorigin", "10:2015"],
|
|
310
|
+
["img.decoding", "10:2020"],
|
|
311
|
+
["img.fetchpriority", "5:2024"],
|
|
312
|
+
["img.height", "10:2015"],
|
|
313
|
+
["img.ismap", "10:2015"],
|
|
314
|
+
["img.loading", "10:2022"],
|
|
315
|
+
["img.referrerpolicy", "10:2020"],
|
|
316
|
+
["img.referrerpolicy.no-referrer-when-downgrade", "0:"],
|
|
317
|
+
["img.referrerpolicy.origin-when-cross-origin", "0:"],
|
|
318
|
+
["img.referrerpolicy.unsafe-url", "0:"],
|
|
319
|
+
["img.sizes", "10:2016"],
|
|
320
|
+
["img.sizes.auto", "0:"],
|
|
321
|
+
["img.src", "10:2015"],
|
|
322
|
+
["img.srcset", "10:2015"],
|
|
323
|
+
["img.usemap", "10:2015"],
|
|
324
|
+
["img.width", "10:2015"],
|
|
325
|
+
["input", "10:2015"],
|
|
326
|
+
["input.accept", "10:2015"],
|
|
327
|
+
["input.alpha", "0:"],
|
|
328
|
+
["input.alt", "10:2015"],
|
|
329
|
+
["input.capture", "0:"],
|
|
330
|
+
["input.checked", "10:2015"],
|
|
331
|
+
["input.colorspace", "0:"],
|
|
332
|
+
["input.dirname", "5:2023"],
|
|
333
|
+
["input.disabled", "10:2015"],
|
|
334
|
+
["input.form", "10:2015"],
|
|
335
|
+
["input.formaction", "10:2015"],
|
|
336
|
+
["input.formenctype", "10:2015"],
|
|
337
|
+
["input.formmethod", "10:2015"],
|
|
338
|
+
["input.formnovalidate", "10:2015"],
|
|
339
|
+
["input.formtarget", "10:2015"],
|
|
340
|
+
["input.list", "10:2019"],
|
|
341
|
+
["input.max", "10:2015"],
|
|
342
|
+
["input.maxlength", "10:2015"],
|
|
343
|
+
["input.min", "10:2015"],
|
|
344
|
+
["input.minlength", "10:2018"],
|
|
345
|
+
["input.multiple", "10:2015"],
|
|
346
|
+
["input.name", "10:2015"],
|
|
347
|
+
["input.pattern", "10:2015"],
|
|
348
|
+
["input.placeholder", "10:2015"],
|
|
349
|
+
["input.popovertarget", "5:2024"],
|
|
350
|
+
["input.popovertarget.implicit_anchor_reference", "0:"],
|
|
351
|
+
["input.popovertargetaction", "5:2024"],
|
|
352
|
+
["input.readonly", "10:2015"],
|
|
353
|
+
["input.required", "10:2015"],
|
|
354
|
+
["input.size", "10:2015"],
|
|
355
|
+
["input.src", "10:2015"],
|
|
356
|
+
["input.step", "10:2015"],
|
|
357
|
+
["input.switch", "0:"],
|
|
358
|
+
["input.type_button", "10:2015"],
|
|
359
|
+
["input.type_checkbox", "10:2015"],
|
|
360
|
+
["input.type_color", "0:"],
|
|
361
|
+
["input.type_color.accepts_css_colors", "0:"],
|
|
362
|
+
["input.type_date", "10:2021"],
|
|
363
|
+
["input.type_datetime-local", "10:2021"],
|
|
364
|
+
["input.type_email", "10:2015"],
|
|
365
|
+
["input.type_file", "10:2015"],
|
|
366
|
+
["input.type_hidden", "10:2015"],
|
|
367
|
+
["input.type_image", "10:2015"],
|
|
368
|
+
["input.type_month", "0:"],
|
|
369
|
+
["input.type_number", "10:2015"],
|
|
370
|
+
["input.type_password", "10:2015"],
|
|
371
|
+
["input.type_password.insecure_login_handling", "0:"],
|
|
372
|
+
["input.type_radio", "10:2015"],
|
|
373
|
+
["input.type_range", "10:2017"],
|
|
374
|
+
["input.type_range.labeled_values", "0:"],
|
|
375
|
+
["input.type_range.tick_marks", "10:2023"],
|
|
376
|
+
["input.type_range.vertical_orientation", "5:2024"],
|
|
377
|
+
["input.type_reset", "10:2015"],
|
|
378
|
+
["input.type_search", "10:2015"],
|
|
379
|
+
["input.type_submit", "10:2015"],
|
|
380
|
+
["input.type_tel", "10:2015"],
|
|
381
|
+
["input.type_text", "10:2015"],
|
|
382
|
+
["input.type_time", "10:2021"],
|
|
383
|
+
["input.type_url", "10:2015"],
|
|
384
|
+
["input.type_week", "0:"],
|
|
385
|
+
["ins", "10:2015"],
|
|
386
|
+
["ins.cite", "10:2015"],
|
|
387
|
+
["ins.datetime", "10:2015"],
|
|
388
|
+
["kbd", "10:2015"],
|
|
389
|
+
["label", "10:2015"],
|
|
390
|
+
["label.for", "10:2015"],
|
|
391
|
+
["legend", "10:2015"],
|
|
392
|
+
["li", "10:2015"],
|
|
393
|
+
["li.value", "10:2015"],
|
|
394
|
+
["link", "10:2015"],
|
|
395
|
+
["link.as", "10:2018"],
|
|
396
|
+
["link.blocking", "0:"],
|
|
397
|
+
["link.crossorigin", "10:2018"],
|
|
398
|
+
["link.disabled", "10:2015"],
|
|
399
|
+
["link.fetchpriority", "5:2024"],
|
|
400
|
+
["link.href", "10:2015"],
|
|
401
|
+
["link.hreflang", "10:2015"],
|
|
402
|
+
["link.imagesizes", "5:2023"],
|
|
403
|
+
["link.imagesrcset", "5:2023"],
|
|
404
|
+
["link.integrity", "10:2018"],
|
|
405
|
+
["link.media", "10:2015"],
|
|
406
|
+
["link.referrerpolicy", "10:2020"],
|
|
407
|
+
["link.referrerpolicy.no-referrer-when-downgrade", "0:"],
|
|
408
|
+
["link.referrerpolicy.origin-when-cross-origin", "0:"],
|
|
409
|
+
["link.referrerpolicy.unsafe-url", "0:"],
|
|
410
|
+
["link.rel", "10:2015"],
|
|
411
|
+
["link.rel.alternate_stylesheet", "0:"],
|
|
412
|
+
["link.rel.compression-dictionary", "0:"],
|
|
413
|
+
["link.rel.dns-prefetch", "5:2025"],
|
|
414
|
+
["link.rel.expect", "0:"],
|
|
415
|
+
["link.rel.manifest", "0:"],
|
|
416
|
+
["link.rel.modulepreload", "5:2023"],
|
|
417
|
+
["link.rel.preconnect", "10:2020"],
|
|
418
|
+
["link.rel.prefetch", "0:"],
|
|
419
|
+
["link.rel.preload", "10:2021"],
|
|
420
|
+
["link.rel.preload.as-fetch", "10:2021"],
|
|
421
|
+
["link.rel.preload.as-font", "10:2021"],
|
|
422
|
+
["link.rel.preload.as-image", "10:2021"],
|
|
423
|
+
["link.rel.preload.as-script", "10:2021"],
|
|
424
|
+
["link.rel.preload.as-style", "10:2021"],
|
|
425
|
+
["link.rel.preload.as-track", "0:"],
|
|
426
|
+
["link.sizes", "10:2020"],
|
|
427
|
+
["link.type", "10:2015"],
|
|
428
|
+
["main", "10:2015"],
|
|
429
|
+
["map", "10:2015"],
|
|
430
|
+
["map.name", "10:2015"],
|
|
431
|
+
["mark", "10:2015"],
|
|
432
|
+
["menu", "10:2015"],
|
|
433
|
+
["meta", "10:2015"],
|
|
434
|
+
["meta.charset", "10:2015"],
|
|
435
|
+
["meta.content", "10:2015"],
|
|
436
|
+
["meta.http-equiv", "10:2015"],
|
|
437
|
+
["meta.http-equiv.content-security-policy", "10:2017"],
|
|
438
|
+
["meta.http-equiv.content-type", "10:2017"],
|
|
439
|
+
["meta.http-equiv.refresh", "10:2015"],
|
|
440
|
+
["meta.name", "10:2015"],
|
|
441
|
+
["meta.name.application-title", "0:"],
|
|
442
|
+
["meta.name.color-scheme", "10:2022"],
|
|
443
|
+
["meta.name.referrer", "10:2020"],
|
|
444
|
+
["meta.name.theme-color", "0:"],
|
|
445
|
+
["meter", "10:2017"],
|
|
446
|
+
["meter.high", "10:2017"],
|
|
447
|
+
["meter.low", "10:2017"],
|
|
448
|
+
["meter.max", "10:2017"],
|
|
449
|
+
["meter.min", "10:2017"],
|
|
450
|
+
["meter.optimum", "10:2017"],
|
|
451
|
+
["meter.value", "10:2017"],
|
|
452
|
+
["nav", "10:2015"],
|
|
453
|
+
["noscript", "10:2015"],
|
|
454
|
+
["object", "10:2015"],
|
|
455
|
+
["object.data", "10:2015"],
|
|
456
|
+
["object.form", "10:2015"],
|
|
457
|
+
["object.height", "10:2015"],
|
|
458
|
+
["object.name", "10:2015"],
|
|
459
|
+
["object.type", "10:2015"],
|
|
460
|
+
["object.width", "10:2015"],
|
|
461
|
+
["ol", "10:2015"],
|
|
462
|
+
["ol.reversed", "10:2020"],
|
|
463
|
+
["ol.start", "10:2015"],
|
|
464
|
+
["ol.type", "10:2015"],
|
|
465
|
+
["optgroup", "10:2015"],
|
|
466
|
+
["optgroup.disabled", "0:"],
|
|
467
|
+
["optgroup.label", "10:2015"],
|
|
468
|
+
["option", "10:2015"],
|
|
469
|
+
["option.disabled", "10:2015"],
|
|
470
|
+
["option.label", "10:2015"],
|
|
471
|
+
["option.selected", "10:2015"],
|
|
472
|
+
["option.value", "10:2015"],
|
|
473
|
+
["output", "10:2018"],
|
|
474
|
+
["output.for", "10:2018"],
|
|
475
|
+
["output.form", "10:2018"],
|
|
476
|
+
["output.name", "10:2018"],
|
|
477
|
+
["p", "10:2015"],
|
|
478
|
+
["picture", "10:2016"],
|
|
479
|
+
["pre", "10:2015"],
|
|
480
|
+
["progress", "10:2015"],
|
|
481
|
+
["progress.max", "10:2015"],
|
|
482
|
+
["progress.value", "10:2015"],
|
|
483
|
+
["q", "10:2015"],
|
|
484
|
+
["q.cite", "10:2015"],
|
|
485
|
+
["rp", "10:2015"],
|
|
486
|
+
["rt", "10:2015"],
|
|
487
|
+
["ruby", "10:2015"],
|
|
488
|
+
["s", "10:2015"],
|
|
489
|
+
["samp", "10:2015"],
|
|
490
|
+
["script", "10:2015"],
|
|
491
|
+
["script.async", "10:2015"],
|
|
492
|
+
["script.attributionsrc", "0:"],
|
|
493
|
+
["script.blocking", "0:"],
|
|
494
|
+
["script.crossorigin", "10:2016"],
|
|
495
|
+
["script.defer", "10:2015"],
|
|
496
|
+
["script.fetchpriority", "5:2024"],
|
|
497
|
+
["script.integrity", "10:2018"],
|
|
498
|
+
["script.nomodule", "10:2018"],
|
|
499
|
+
["script.referrerpolicy", "10:2020"],
|
|
500
|
+
["script.referrerpolicy.no-referrer-when-downgrade", "0:"],
|
|
501
|
+
["script.referrerpolicy.origin-when-cross-origin", "0:"],
|
|
502
|
+
["script.referrerpolicy.unsafe-url", "0:"],
|
|
503
|
+
["script.src", "10:2015"],
|
|
504
|
+
["script.type", "10:2015"],
|
|
505
|
+
["script.type.importmap", "10:2023"],
|
|
506
|
+
["script.type.module", "10:2018"],
|
|
507
|
+
["script.type.speculationrules", "0:"],
|
|
508
|
+
["script.type.speculationrules.eagerness", "0:"],
|
|
509
|
+
["script.type.speculationrules.expects_no_vary_search", "0:"],
|
|
510
|
+
["script.type.speculationrules.prefetch", "0:"],
|
|
511
|
+
["script.type.speculationrules.prerender", "0:"],
|
|
512
|
+
["script.type.speculationrules.referrer_policy", "0:"],
|
|
513
|
+
["script.type.speculationrules.relative_to", "0:"],
|
|
514
|
+
["script.type.speculationrules.requires", "0:"],
|
|
515
|
+
[
|
|
516
|
+
"script.type.speculationrules.requires.anonymous-client-ip-when-cross-origin",
|
|
517
|
+
"0:"
|
|
518
|
+
],
|
|
519
|
+
["script.type.speculationrules.source_optional", "0:"],
|
|
520
|
+
["script.type.speculationrules.tag", "0:"],
|
|
521
|
+
["script.type.speculationrules.target_hint", "0:"],
|
|
522
|
+
["script.type.speculationrules.urls", "0:"],
|
|
523
|
+
["script.type.speculationrules.where", "0:"],
|
|
524
|
+
["search", "5:2023"],
|
|
525
|
+
["section", "10:2015"],
|
|
526
|
+
["select", "10:2015"],
|
|
527
|
+
["select.disabled", "10:2015"],
|
|
528
|
+
["select.form", "10:2015"],
|
|
529
|
+
["select.hr_in_select", "0:"],
|
|
530
|
+
["select.multiple", "10:2015"],
|
|
531
|
+
["select.name", "10:2015"],
|
|
532
|
+
["select.required", "10:2015"],
|
|
533
|
+
["select.size", "0:"],
|
|
534
|
+
["selectedcontent", "0:"],
|
|
535
|
+
["slot", "10:2020"],
|
|
536
|
+
["slot.name", "10:2020"],
|
|
537
|
+
["small", "10:2015"],
|
|
538
|
+
["source", "10:2015"],
|
|
539
|
+
["source.height", "10:2022"],
|
|
540
|
+
["source.media", "10:2015"],
|
|
541
|
+
["source.sizes", "10:2016"],
|
|
542
|
+
["source.src", "10:2015"],
|
|
543
|
+
["source.srcset", "10:2016"],
|
|
544
|
+
["source.type", "10:2015"],
|
|
545
|
+
["source.width", "10:2022"],
|
|
546
|
+
["span", "10:2015"],
|
|
547
|
+
["strong", "10:2015"],
|
|
548
|
+
["style", "10:2015"],
|
|
549
|
+
["style.blocking", "0:"],
|
|
550
|
+
["style.media", "10:2015"],
|
|
551
|
+
["sub", "10:2015"],
|
|
552
|
+
["summary", "10:2020"],
|
|
553
|
+
["summary.display_list_item", "0:"],
|
|
554
|
+
["sup", "10:2015"],
|
|
555
|
+
["table", "10:2015"],
|
|
556
|
+
["table.align", "0:"],
|
|
557
|
+
["table.bgcolor", "0:"],
|
|
558
|
+
["table.border", "0:"],
|
|
559
|
+
["table.cellpadding", "0:"],
|
|
560
|
+
["table.cellspacing", "0:"],
|
|
561
|
+
["table.frame", "0:"],
|
|
562
|
+
["table.rules", "0:"],
|
|
563
|
+
["table.summary", "0:"],
|
|
564
|
+
["table.width", "0:"],
|
|
565
|
+
["tbody", "10:2015"],
|
|
566
|
+
["tbody.align", "0:"],
|
|
567
|
+
["tbody.bgcolor", "0:"],
|
|
568
|
+
["tbody.char", "0:"],
|
|
569
|
+
["tbody.charoff", "0:"],
|
|
570
|
+
["tbody.valign", "0:"],
|
|
571
|
+
["td", "10:2015"],
|
|
572
|
+
["td.abbr", "0:"],
|
|
573
|
+
["td.align", "0:"],
|
|
574
|
+
["td.axis", "0:"],
|
|
575
|
+
["td.bgcolor", "0:"],
|
|
576
|
+
["td.char", "0:"],
|
|
577
|
+
["td.charoff", "0:"],
|
|
578
|
+
["td.colspan", "10:2015"],
|
|
579
|
+
["td.headers", "10:2015"],
|
|
580
|
+
["td.rowspan", "10:2015"],
|
|
581
|
+
["td.rowspan.rowspan_zero", "0:"],
|
|
582
|
+
["td.scope", "0:"],
|
|
583
|
+
["td.valign", "0:"],
|
|
584
|
+
["td.width", "0:"],
|
|
585
|
+
["template", "10:2015"],
|
|
586
|
+
["template.shadowrootclonable", "5:2024"],
|
|
587
|
+
["template.shadowrootdelegatesfocus", "5:2024"],
|
|
588
|
+
["template.shadowrootmode", "5:2024"],
|
|
589
|
+
["template.shadowrootreferencetarget", "0:"],
|
|
590
|
+
["template.shadowrootserializable", "0:"],
|
|
591
|
+
["textarea", "10:2015"],
|
|
592
|
+
["textarea.autocomplete", "10:2020"],
|
|
593
|
+
["textarea.cols", "10:2015"],
|
|
594
|
+
["textarea.dirname", "5:2023"],
|
|
595
|
+
["textarea.disabled", "10:2015"],
|
|
596
|
+
["textarea.form", "10:2015"],
|
|
597
|
+
["textarea.maxlength", "10:2015"],
|
|
598
|
+
["textarea.minlength", "10:2018"],
|
|
599
|
+
["textarea.name", "10:2015"],
|
|
600
|
+
["textarea.placeholder", "10:2015"],
|
|
601
|
+
["textarea.placeholder.line_breaks", "10:2022"],
|
|
602
|
+
["textarea.readonly", "10:2015"],
|
|
603
|
+
["textarea.required", "10:2015"],
|
|
604
|
+
["textarea.rows", "10:2015"],
|
|
605
|
+
["textarea.wrap", "10:2015"],
|
|
606
|
+
["textarea.wrap.hard", "0:"],
|
|
607
|
+
["tfoot", "10:2015"],
|
|
608
|
+
["tfoot.align", "0:"],
|
|
609
|
+
["tfoot.bgcolor", "0:"],
|
|
610
|
+
["tfoot.char", "0:"],
|
|
611
|
+
["tfoot.charoff", "0:"],
|
|
612
|
+
["tfoot.valign", "0:"],
|
|
613
|
+
["th", "10:2015"],
|
|
614
|
+
["th.abbr", "10:2015"],
|
|
615
|
+
["th.align", "0:"],
|
|
616
|
+
["th.axis", "0:"],
|
|
617
|
+
["th.bgcolor", "0:"],
|
|
618
|
+
["th.char", "0:"],
|
|
619
|
+
["th.charoff", "0:"],
|
|
620
|
+
["th.colspan", "10:2015"],
|
|
621
|
+
["th.headers", "10:2015"],
|
|
622
|
+
["th.rowspan", "10:2015"],
|
|
623
|
+
["th.rowspan.rowspan_zero", "0:"],
|
|
624
|
+
["th.scope", "10:2015"],
|
|
625
|
+
["th.valign", "0:"],
|
|
626
|
+
["th.width", "0:"],
|
|
627
|
+
["thead", "10:2015"],
|
|
628
|
+
["thead.align", "0:"],
|
|
629
|
+
["thead.bgcolor", "0:"],
|
|
630
|
+
["thead.char", "0:"],
|
|
631
|
+
["thead.charoff", "0:"],
|
|
632
|
+
["thead.valign", "0:"],
|
|
633
|
+
["time", "10:2017"],
|
|
634
|
+
["time.datetime", "10:2017"],
|
|
635
|
+
["title", "10:2015"],
|
|
636
|
+
["tr", "10:2015"],
|
|
637
|
+
["tr.align", "0:"],
|
|
638
|
+
["tr.bgcolor", "0:"],
|
|
639
|
+
["tr.char", "0:"],
|
|
640
|
+
["tr.charoff", "0:"],
|
|
641
|
+
["tr.valign", "0:"],
|
|
642
|
+
["track", "10:2015"],
|
|
643
|
+
["track.default", "10:2015"],
|
|
644
|
+
["track.kind", "10:2015"],
|
|
645
|
+
["track.label", "10:2015"],
|
|
646
|
+
["track.src", "10:2016"],
|
|
647
|
+
["track.srclang", "10:2015"],
|
|
648
|
+
["u", "10:2015"],
|
|
649
|
+
["ul", "10:2015"],
|
|
650
|
+
["var", "10:2015"],
|
|
651
|
+
["video", "10:2015"],
|
|
652
|
+
["video.aspect_ratio_computed_from_attributes", "10:2020"],
|
|
653
|
+
["video.autoplay", "10:2016"],
|
|
654
|
+
["video.controls", "10:2015"],
|
|
655
|
+
["video.controlslist", "0:"],
|
|
656
|
+
["video.crossorigin", "10:2020"],
|
|
657
|
+
["video.disablepictureinpicture", "0:"],
|
|
658
|
+
["video.disableremoteplayback", "0:"],
|
|
659
|
+
["video.height", "10:2015"],
|
|
660
|
+
["video.loop", "10:2015"],
|
|
661
|
+
["video.muted", "10:2015"],
|
|
662
|
+
["video.playsinline", "0:"],
|
|
663
|
+
["video.poster", "10:2015"],
|
|
664
|
+
["video.preload", "10:2015"],
|
|
665
|
+
["video.src", "10:2015"],
|
|
666
|
+
["video.width", "10:2015"],
|
|
667
|
+
["wbr", "10:2015"]
|
|
668
|
+
]);
|
|
669
|
+
var globalAttributes = /* @__PURE__ */ new Map([
|
|
670
|
+
["accesskey", "10:2015"],
|
|
671
|
+
["autocapitalize", "0:"],
|
|
672
|
+
["autocorrect", "0:"],
|
|
673
|
+
["autofocus", "10:2023"],
|
|
674
|
+
["contenteditable", "10:2015"],
|
|
675
|
+
["contenteditable.plaintext-only", "5:2025"],
|
|
676
|
+
["enterkeyhint", "10:2021"],
|
|
677
|
+
["exportparts", "10:2020"],
|
|
678
|
+
["inert", "10:2023"],
|
|
679
|
+
["inert.ignores_find_in_page", "0:"],
|
|
680
|
+
["inputmode", "10:2021"],
|
|
681
|
+
["is", "0:"],
|
|
682
|
+
["lang", "10:2015"],
|
|
683
|
+
["nonce", "10:2022"],
|
|
684
|
+
["nonce.nonce_hiding", "10:2022"],
|
|
685
|
+
["part", "10:2020"],
|
|
686
|
+
["popover", "5:2024"],
|
|
687
|
+
["popover.hint", "0:"],
|
|
688
|
+
["slot", "10:2020"],
|
|
689
|
+
["spellcheck", "10:2017"],
|
|
690
|
+
["style", "10:2015"],
|
|
691
|
+
["tabindex", "10:2015"],
|
|
692
|
+
["title", "10:2015"],
|
|
693
|
+
["title.multi-line_titles", "10:2018"],
|
|
694
|
+
["translate", "10:2023"],
|
|
695
|
+
["virtualkeyboardpolicy", "0:"],
|
|
696
|
+
["writingsuggestions", "0:"]
|
|
697
|
+
]);
|
|
698
|
+
|
|
699
|
+
// lib/rules/use-baseline.js
|
|
700
|
+
var USE_BASELINE_MESSAGE_IDS = {
|
|
701
|
+
noBaselineElement: "noBaselineElement",
|
|
702
|
+
notBaselineElementAttribute: "notBaselineElementAttribute",
|
|
703
|
+
notBaselineGlobalAttribute: "notBaselineGlobalAttribute"
|
|
704
|
+
};
|
|
705
|
+
function toStatusKey(...parts) {
|
|
706
|
+
return parts.map((part) => part.toLowerCase().trim()).join(".");
|
|
707
|
+
}
|
|
708
|
+
function isCustomElement(element2) {
|
|
709
|
+
return element2.includes("-");
|
|
710
|
+
}
|
|
711
|
+
function decodeStatus(encoded) {
|
|
712
|
+
const [status, year = NaN] = encoded.split(":").map((part) => Number(part));
|
|
713
|
+
return [status, year];
|
|
714
|
+
}
|
|
715
|
+
function getElementAttributeSpecificStatusKey(element2, key, value) {
|
|
716
|
+
const elementName = element2.toLowerCase();
|
|
717
|
+
const attributeKey = key.toLowerCase();
|
|
718
|
+
const attributeValue = value.toLowerCase();
|
|
719
|
+
if (elementName === "input" && attributeKey === "type") {
|
|
720
|
+
return `input.type_${attributeValue}`;
|
|
721
|
+
}
|
|
722
|
+
if (elementName === "a" && attributeKey === "href" && attributeValue.trim().startsWith("sms:")) {
|
|
723
|
+
return "a.href.href_sms";
|
|
724
|
+
}
|
|
725
|
+
if ((elementName === "td" || elementName === "th") && attributeKey === "rowspan" && attributeValue === "0") {
|
|
726
|
+
return `${elementName}.rowspan.rowspan_zero`;
|
|
727
|
+
}
|
|
728
|
+
return null;
|
|
729
|
+
}
|
|
730
|
+
function useBaseline(options) {
|
|
731
|
+
const available = options.available;
|
|
732
|
+
const baseYear = typeof available === "number" ? available : null;
|
|
733
|
+
const baseStatus = available === "widely" ? BASELINE_HIGH : BASELINE_LOW;
|
|
734
|
+
const availability = String(available);
|
|
735
|
+
function isSupported(encoded) {
|
|
736
|
+
const [status, year = NaN] = decodeStatus(encoded);
|
|
737
|
+
if (baseYear) {
|
|
738
|
+
return year <= baseYear;
|
|
739
|
+
}
|
|
740
|
+
return status >= baseStatus;
|
|
741
|
+
}
|
|
742
|
+
function isSupportedElementAttributeKey(element2, key) {
|
|
743
|
+
const elementStatus = elements.get(toStatusKey(element2, key));
|
|
744
|
+
if (!elementStatus) {
|
|
745
|
+
return true;
|
|
746
|
+
}
|
|
747
|
+
return isSupported(elementStatus);
|
|
748
|
+
}
|
|
749
|
+
function isSupportedGlobalAttributeKey(key) {
|
|
750
|
+
const globalAttrStatus = globalAttributes.get(toStatusKey(key));
|
|
751
|
+
if (!globalAttrStatus) {
|
|
752
|
+
return true;
|
|
753
|
+
}
|
|
754
|
+
return isSupported(globalAttrStatus);
|
|
755
|
+
}
|
|
756
|
+
function isSupportedElementAttributeKeyValue(element2, key, value) {
|
|
757
|
+
const elementStatus = elements.get(toStatusKey(element2, key, value));
|
|
758
|
+
if (!elementStatus) {
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
761
|
+
return isSupported(elementStatus);
|
|
762
|
+
}
|
|
763
|
+
function isSupportedGlobalAttributeKeyValue(key, value) {
|
|
764
|
+
const globalAttrStatus = globalAttributes.get(toStatusKey(key, value));
|
|
765
|
+
if (!globalAttrStatus) {
|
|
766
|
+
return true;
|
|
767
|
+
}
|
|
768
|
+
return isSupported(globalAttrStatus);
|
|
769
|
+
}
|
|
770
|
+
function isSupportedElementSpecificAttributeKeyValue(element2, key, value) {
|
|
771
|
+
const statusKey = getElementAttributeSpecificStatusKey(element2, key, value);
|
|
772
|
+
if (!statusKey) {
|
|
773
|
+
return true;
|
|
774
|
+
}
|
|
775
|
+
const elementStatus = elements.get(statusKey);
|
|
776
|
+
if (!elementStatus) {
|
|
777
|
+
return true;
|
|
778
|
+
}
|
|
779
|
+
return isSupported(elementStatus);
|
|
780
|
+
}
|
|
781
|
+
function isSupportedElement(element2) {
|
|
782
|
+
const elementEncoded = elements.get(element2);
|
|
783
|
+
if (!elementEncoded) {
|
|
784
|
+
return true;
|
|
785
|
+
}
|
|
786
|
+
return isSupported(elementEncoded);
|
|
787
|
+
}
|
|
788
|
+
return {
|
|
789
|
+
/**
|
|
790
|
+
* @param {ElementNodeAdapter<
|
|
791
|
+
* ElementNode,
|
|
792
|
+
* AttributeKeyNode,
|
|
793
|
+
* AttributeValueNode
|
|
794
|
+
* >} adapter
|
|
795
|
+
* @returns {UseBaselineResult<
|
|
796
|
+
* ElementNode,
|
|
797
|
+
* AttributeKeyNode,
|
|
798
|
+
* AttributeValueNode
|
|
799
|
+
* >}
|
|
800
|
+
*/
|
|
801
|
+
checkAttributes(adapter) {
|
|
802
|
+
const elementName = adapter.getTagName();
|
|
803
|
+
if (isCustomElement(elementName)) {
|
|
804
|
+
return [];
|
|
805
|
+
}
|
|
806
|
+
if (!isSupportedElement(elementName)) {
|
|
807
|
+
return [
|
|
808
|
+
{
|
|
809
|
+
messageId: USE_BASELINE_MESSAGE_IDS.noBaselineElement,
|
|
810
|
+
node: adapter.node(),
|
|
811
|
+
data: {
|
|
812
|
+
element: `<${elementName}>`,
|
|
813
|
+
availability
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
];
|
|
817
|
+
}
|
|
818
|
+
const result = [];
|
|
819
|
+
for (const attribute of adapter.getAttributes()) {
|
|
820
|
+
const attributeKey = attribute.key.value();
|
|
821
|
+
const attributeKeyIsExpression = attribute.key.isExpression();
|
|
822
|
+
if (!attributeKey || attributeKeyIsExpression) {
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
const attributeValue = attribute.value.value();
|
|
826
|
+
if (attributeValue === null) {
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
const attrKeyRaw = attribute.key.raw() || attributeKey;
|
|
830
|
+
if (!isSupportedElementAttributeKey(elementName, attributeKey)) {
|
|
831
|
+
result.push({
|
|
832
|
+
messageId: USE_BASELINE_MESSAGE_IDS.notBaselineElementAttribute,
|
|
833
|
+
node: attribute.key.node(),
|
|
834
|
+
data: {
|
|
835
|
+
element: `<${elementName}>`,
|
|
836
|
+
attr: attrKeyRaw,
|
|
837
|
+
availability
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
} else if (!isSupportedGlobalAttributeKey(attributeKey)) {
|
|
841
|
+
result.push({
|
|
842
|
+
messageId: USE_BASELINE_MESSAGE_IDS.notBaselineGlobalAttribute,
|
|
843
|
+
node: attribute.key.node(),
|
|
844
|
+
data: {
|
|
845
|
+
attr: attrKeyRaw,
|
|
846
|
+
availability
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
} else if (attributeValue !== null) {
|
|
850
|
+
if (!isSupportedElementAttributeKeyValue(
|
|
851
|
+
elementName,
|
|
852
|
+
attributeKey,
|
|
853
|
+
attributeValue
|
|
854
|
+
) || !isSupportedElementSpecificAttributeKeyValue(
|
|
855
|
+
elementName,
|
|
856
|
+
attributeKey,
|
|
857
|
+
attributeValue
|
|
858
|
+
)) {
|
|
859
|
+
result.push({
|
|
860
|
+
messageId: USE_BASELINE_MESSAGE_IDS.notBaselineElementAttribute,
|
|
861
|
+
node: attribute.value.node() || adapter.node(),
|
|
862
|
+
data: {
|
|
863
|
+
element: `<${elementName}>`,
|
|
864
|
+
attr: `${attrKeyRaw}="${attributeValue}"`,
|
|
865
|
+
availability
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
} else if (!isSupportedGlobalAttributeKeyValue(attributeKey, attributeValue)) {
|
|
869
|
+
const valueNode = attribute.value.node();
|
|
870
|
+
if (valueNode) {
|
|
871
|
+
result.push({
|
|
872
|
+
messageId: USE_BASELINE_MESSAGE_IDS.notBaselineGlobalAttribute,
|
|
873
|
+
node: valueNode,
|
|
874
|
+
data: {
|
|
875
|
+
attr: `${attrKeyRaw}="${attributeValue}"`,
|
|
876
|
+
availability
|
|
877
|
+
}
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
return result;
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// lib/rules/no-ineffective-attrs.js
|
|
889
|
+
var NO_INEFFECTIVE_ATTRS_MESSAGE_IDS = {
|
|
890
|
+
ineffective: "ineffective"
|
|
891
|
+
};
|
|
892
|
+
function noIneffectiveAttrs() {
|
|
893
|
+
function getAttrValue(adapter, attrName) {
|
|
894
|
+
for (const attribute of adapter.getAttributes()) {
|
|
895
|
+
const attrKeyValue = attribute.key.value();
|
|
896
|
+
if (attrKeyValue && attrKeyValue === attrName) {
|
|
897
|
+
const value = attribute.value.value();
|
|
898
|
+
return value || null;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
function hasAttr(adapter, attrName) {
|
|
904
|
+
for (const attribute of adapter.getAttributes()) {
|
|
905
|
+
const keyValue = attribute.key.value();
|
|
906
|
+
if (keyValue && keyValue.toLocaleLowerCase() === attrName.toLocaleLowerCase()) {
|
|
907
|
+
return true;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return false;
|
|
911
|
+
}
|
|
912
|
+
function isTemplateValueAttr(adapter, attrName) {
|
|
913
|
+
for (const attribute of adapter.getAttributes()) {
|
|
914
|
+
const keyValue = attribute.key.value();
|
|
915
|
+
if (keyValue && keyValue === attrName) {
|
|
916
|
+
const value = attribute.value;
|
|
917
|
+
return value.isExpression();
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
return false;
|
|
921
|
+
}
|
|
922
|
+
const checkersByTag = {
|
|
923
|
+
input: [
|
|
924
|
+
{
|
|
925
|
+
attr: "multiple",
|
|
926
|
+
when: (adapter) => {
|
|
927
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
928
|
+
return false;
|
|
929
|
+
}
|
|
930
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
931
|
+
return [
|
|
932
|
+
"text",
|
|
933
|
+
"password",
|
|
934
|
+
"radio",
|
|
935
|
+
"checkbox",
|
|
936
|
+
"image",
|
|
937
|
+
"hidden",
|
|
938
|
+
"reset",
|
|
939
|
+
"button"
|
|
940
|
+
].includes(type);
|
|
941
|
+
},
|
|
942
|
+
message: 'The "multiple" attribute has no effect on this input type.'
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
attr: "accept",
|
|
946
|
+
when: (adapter) => {
|
|
947
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
951
|
+
return type !== "file";
|
|
952
|
+
},
|
|
953
|
+
message: 'The "accept" attribute has no effect unless input type is "file".'
|
|
954
|
+
},
|
|
955
|
+
{
|
|
956
|
+
attr: "readonly",
|
|
957
|
+
when: (adapter) => {
|
|
958
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
959
|
+
return false;
|
|
960
|
+
}
|
|
961
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
962
|
+
return ["checkbox", "radio", "file", "range", "color"].includes(type);
|
|
963
|
+
},
|
|
964
|
+
message: 'The "readonly" attribute has no effect on this input type.'
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
attr: "min",
|
|
968
|
+
when: (adapter) => {
|
|
969
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
970
|
+
return false;
|
|
971
|
+
}
|
|
972
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
973
|
+
return ![
|
|
974
|
+
"number",
|
|
975
|
+
"range",
|
|
976
|
+
"date",
|
|
977
|
+
"datetime-local",
|
|
978
|
+
"month",
|
|
979
|
+
"time",
|
|
980
|
+
"week"
|
|
981
|
+
].includes(type);
|
|
982
|
+
},
|
|
983
|
+
message: 'The "min" attribute only works with numeric, date, and time input types.'
|
|
984
|
+
},
|
|
985
|
+
{
|
|
986
|
+
attr: "max",
|
|
987
|
+
when: (adapter) => {
|
|
988
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
989
|
+
return false;
|
|
990
|
+
}
|
|
991
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
992
|
+
return ![
|
|
993
|
+
"number",
|
|
994
|
+
"range",
|
|
995
|
+
"date",
|
|
996
|
+
"datetime-local",
|
|
997
|
+
"month",
|
|
998
|
+
"time",
|
|
999
|
+
"week"
|
|
1000
|
+
].includes(type);
|
|
1001
|
+
},
|
|
1002
|
+
message: 'The "max" attribute only works with numeric, date, and time input types.'
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
attr: "step",
|
|
1006
|
+
when: (adapter) => {
|
|
1007
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1008
|
+
return false;
|
|
1009
|
+
}
|
|
1010
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
1011
|
+
return ![
|
|
1012
|
+
"number",
|
|
1013
|
+
"range",
|
|
1014
|
+
"date",
|
|
1015
|
+
"datetime-local",
|
|
1016
|
+
"month",
|
|
1017
|
+
"time",
|
|
1018
|
+
"week"
|
|
1019
|
+
].includes(type);
|
|
1020
|
+
},
|
|
1021
|
+
message: 'The "step" attribute only works with numeric, date, and time input types.'
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
attr: "pattern",
|
|
1025
|
+
when: (adapter) => {
|
|
1026
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1027
|
+
return false;
|
|
1028
|
+
}
|
|
1029
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
1030
|
+
return ![
|
|
1031
|
+
"text",
|
|
1032
|
+
"search",
|
|
1033
|
+
"url",
|
|
1034
|
+
"tel",
|
|
1035
|
+
"email",
|
|
1036
|
+
"password"
|
|
1037
|
+
].includes(type);
|
|
1038
|
+
},
|
|
1039
|
+
message: 'The "pattern" attribute only works with text-based input types.'
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
attr: "maxlength",
|
|
1043
|
+
when: (adapter) => {
|
|
1044
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
1048
|
+
return ![
|
|
1049
|
+
"text",
|
|
1050
|
+
"search",
|
|
1051
|
+
"url",
|
|
1052
|
+
"tel",
|
|
1053
|
+
"email",
|
|
1054
|
+
"password"
|
|
1055
|
+
].includes(type);
|
|
1056
|
+
},
|
|
1057
|
+
message: 'The "maxlength" attribute only works with text-based input types.'
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
attr: "minlength",
|
|
1061
|
+
when: (adapter) => {
|
|
1062
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
1066
|
+
return ![
|
|
1067
|
+
"text",
|
|
1068
|
+
"search",
|
|
1069
|
+
"url",
|
|
1070
|
+
"tel",
|
|
1071
|
+
"email",
|
|
1072
|
+
"password"
|
|
1073
|
+
].includes(type);
|
|
1074
|
+
},
|
|
1075
|
+
message: 'The "minlength" attribute only works with text-based input types.'
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
attr: "placeholder",
|
|
1079
|
+
when: (adapter) => {
|
|
1080
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1081
|
+
return false;
|
|
1082
|
+
}
|
|
1083
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
1084
|
+
return ![
|
|
1085
|
+
"text",
|
|
1086
|
+
"search",
|
|
1087
|
+
"url",
|
|
1088
|
+
"tel",
|
|
1089
|
+
"email",
|
|
1090
|
+
"password",
|
|
1091
|
+
"number"
|
|
1092
|
+
].includes(type);
|
|
1093
|
+
},
|
|
1094
|
+
message: 'The "placeholder" attribute has no effect on this input type.'
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
attr: "size",
|
|
1098
|
+
when: (adapter) => {
|
|
1099
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
1103
|
+
return ![
|
|
1104
|
+
"text",
|
|
1105
|
+
"search",
|
|
1106
|
+
"url",
|
|
1107
|
+
"tel",
|
|
1108
|
+
"email",
|
|
1109
|
+
"password"
|
|
1110
|
+
].includes(type);
|
|
1111
|
+
},
|
|
1112
|
+
message: 'The "size" attribute only works with text-based input types.'
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
attr: "list",
|
|
1116
|
+
when: (adapter) => {
|
|
1117
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1118
|
+
return false;
|
|
1119
|
+
}
|
|
1120
|
+
const type = getAttrValue(adapter, "type") || "text";
|
|
1121
|
+
return [
|
|
1122
|
+
"checkbox",
|
|
1123
|
+
"radio",
|
|
1124
|
+
"file",
|
|
1125
|
+
"submit",
|
|
1126
|
+
"image",
|
|
1127
|
+
"reset",
|
|
1128
|
+
"button",
|
|
1129
|
+
"hidden"
|
|
1130
|
+
].includes(type);
|
|
1131
|
+
},
|
|
1132
|
+
message: 'The "list" attribute has no effect on this input type.'
|
|
1133
|
+
}
|
|
1134
|
+
],
|
|
1135
|
+
script: [
|
|
1136
|
+
{
|
|
1137
|
+
attr: "defer",
|
|
1138
|
+
when: (adapter) => !hasAttr(adapter, "src"),
|
|
1139
|
+
message: 'The "defer" attribute has no effect on inline scripts.'
|
|
1140
|
+
},
|
|
1141
|
+
{
|
|
1142
|
+
attr: "async",
|
|
1143
|
+
when: (adapter) => !hasAttr(adapter, "src"),
|
|
1144
|
+
message: 'The "async" attribute has no effect on inline scripts.'
|
|
1145
|
+
}
|
|
1146
|
+
],
|
|
1147
|
+
a: [
|
|
1148
|
+
{
|
|
1149
|
+
attr: "download",
|
|
1150
|
+
when: (adapter) => !hasAttr(adapter, "href"),
|
|
1151
|
+
message: 'The "download" attribute has no effect without an "href".'
|
|
1152
|
+
},
|
|
1153
|
+
{
|
|
1154
|
+
attr: "ping",
|
|
1155
|
+
when: (adapter) => !hasAttr(adapter, "href"),
|
|
1156
|
+
message: 'The "ping" attribute has no effect without an "href".'
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
attr: "target",
|
|
1160
|
+
when: (adapter) => !hasAttr(adapter, "href"),
|
|
1161
|
+
message: 'The "target" attribute has no effect without an "href".'
|
|
1162
|
+
}
|
|
1163
|
+
],
|
|
1164
|
+
audio: [
|
|
1165
|
+
{
|
|
1166
|
+
attr: "controlslist",
|
|
1167
|
+
when: (adapter) => !hasAttr(adapter, "controls"),
|
|
1168
|
+
message: 'The "controlslist" attribute has no effect without "controls".'
|
|
1169
|
+
}
|
|
1170
|
+
],
|
|
1171
|
+
video: [
|
|
1172
|
+
{
|
|
1173
|
+
attr: "controlslist",
|
|
1174
|
+
when: (adapter) => !hasAttr(adapter, "controls"),
|
|
1175
|
+
message: 'The "controlslist" attribute has no effect without "controls".'
|
|
1176
|
+
}
|
|
1177
|
+
],
|
|
1178
|
+
form: [
|
|
1179
|
+
{
|
|
1180
|
+
attr: "enctype",
|
|
1181
|
+
when: (adapter) => {
|
|
1182
|
+
if (isTemplateValueAttr(adapter, "method")) {
|
|
1183
|
+
return false;
|
|
1184
|
+
}
|
|
1185
|
+
const method = getAttrValue(adapter, "method") || "get";
|
|
1186
|
+
return method ? method.toLowerCase() !== "post" : false;
|
|
1187
|
+
},
|
|
1188
|
+
message: 'The "enctype" attribute only has effect when method is "post".'
|
|
1189
|
+
}
|
|
1190
|
+
],
|
|
1191
|
+
button: [
|
|
1192
|
+
{
|
|
1193
|
+
attr: "formaction",
|
|
1194
|
+
when: (adapter) => {
|
|
1195
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1196
|
+
return false;
|
|
1197
|
+
}
|
|
1198
|
+
const type = getAttrValue(adapter, "type") || "submit";
|
|
1199
|
+
return type !== "submit";
|
|
1200
|
+
},
|
|
1201
|
+
message: 'The "formaction" attribute only works with type="submit".'
|
|
1202
|
+
},
|
|
1203
|
+
{
|
|
1204
|
+
attr: "formmethod",
|
|
1205
|
+
when: (adapter) => {
|
|
1206
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1207
|
+
return false;
|
|
1208
|
+
}
|
|
1209
|
+
const type = getAttrValue(adapter, "type") || "submit";
|
|
1210
|
+
return type !== "submit";
|
|
1211
|
+
},
|
|
1212
|
+
message: 'The "formmethod" attribute only works with type="submit".'
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
attr: "formenctype",
|
|
1216
|
+
when: (adapter) => {
|
|
1217
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1218
|
+
return false;
|
|
1219
|
+
}
|
|
1220
|
+
const type = getAttrValue(adapter, "type") || "submit";
|
|
1221
|
+
return type !== "submit";
|
|
1222
|
+
},
|
|
1223
|
+
message: 'The "formenctype" attribute only works with type="submit".'
|
|
1224
|
+
},
|
|
1225
|
+
{
|
|
1226
|
+
attr: "formnovalidate",
|
|
1227
|
+
when: (adapter) => {
|
|
1228
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1229
|
+
return false;
|
|
1230
|
+
}
|
|
1231
|
+
const type = getAttrValue(adapter, "type") || "submit";
|
|
1232
|
+
return type !== "submit";
|
|
1233
|
+
},
|
|
1234
|
+
message: 'The "formnovalidate" attribute only works with type="submit".'
|
|
1235
|
+
},
|
|
1236
|
+
{
|
|
1237
|
+
attr: "formtarget",
|
|
1238
|
+
when: (adapter) => {
|
|
1239
|
+
if (isTemplateValueAttr(adapter, "type")) {
|
|
1240
|
+
return false;
|
|
1241
|
+
}
|
|
1242
|
+
const type = getAttrValue(adapter, "type") || "submit";
|
|
1243
|
+
return type !== "submit";
|
|
1244
|
+
},
|
|
1245
|
+
message: 'The "formtarget" attribute only works with type="submit".'
|
|
1246
|
+
}
|
|
1247
|
+
],
|
|
1248
|
+
area: [
|
|
1249
|
+
{
|
|
1250
|
+
attr: "download",
|
|
1251
|
+
when: (adapter) => !hasAttr(adapter, "href"),
|
|
1252
|
+
message: 'The "download" attribute has no effect without an "href".'
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
attr: "ping",
|
|
1256
|
+
when: (adapter) => !hasAttr(adapter, "href"),
|
|
1257
|
+
message: 'The "ping" attribute has no effect without an "href".'
|
|
1258
|
+
},
|
|
1259
|
+
{
|
|
1260
|
+
attr: "target",
|
|
1261
|
+
when: (adapter) => !hasAttr(adapter, "href"),
|
|
1262
|
+
message: 'The "target" attribute has no effect without an "href".'
|
|
1263
|
+
}
|
|
1264
|
+
],
|
|
1265
|
+
img: [
|
|
1266
|
+
{
|
|
1267
|
+
attr: "usemap",
|
|
1268
|
+
when: (adapter) => hasAttr(adapter, "ismap"),
|
|
1269
|
+
message: 'The "usemap" and "ismap" attributes cannot be used together.'
|
|
1270
|
+
}
|
|
1271
|
+
]
|
|
1272
|
+
};
|
|
1273
|
+
return {
|
|
1274
|
+
/**
|
|
1275
|
+
* @param {ElementNodeAdapter<
|
|
1276
|
+
* ElementNode,
|
|
1277
|
+
* AttributeKeyNode,
|
|
1278
|
+
* AttributeValueNode
|
|
1279
|
+
* >} adapter
|
|
1280
|
+
* @returns {NoIneffectiveAttrsResult<AttributeKeyNode>}
|
|
1281
|
+
*/
|
|
1282
|
+
checkAttributes(adapter) {
|
|
1283
|
+
const elementName = adapter.getTagName();
|
|
1284
|
+
const tagCheckers = checkersByTag[elementName];
|
|
1285
|
+
if (!tagCheckers) {
|
|
1286
|
+
return [];
|
|
1287
|
+
}
|
|
1288
|
+
const result = [];
|
|
1289
|
+
for (const check of tagCheckers) {
|
|
1290
|
+
for (const attribute of adapter.getAttributes()) {
|
|
1291
|
+
const attrKeyValue = attribute.key.value();
|
|
1292
|
+
const attrValueValue = attribute.value.value();
|
|
1293
|
+
if (attribute.value.isExpression() || attrValueValue === null || attrKeyValue !== check.attr) {
|
|
1294
|
+
continue;
|
|
1295
|
+
}
|
|
1296
|
+
if (check.when(adapter)) {
|
|
1297
|
+
result.push({
|
|
1298
|
+
node: attribute.key.node(),
|
|
1299
|
+
messageId: NO_INEFFECTIVE_ATTRS_MESSAGE_IDS.ineffective,
|
|
1300
|
+
data: {
|
|
1301
|
+
message: check.message
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
return result;
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
// lib/rules/no-obsolete-tags.js
|
|
1313
|
+
var OBSOLETE_TAGS = [
|
|
1314
|
+
"applet",
|
|
1315
|
+
"acronym",
|
|
1316
|
+
"bgsound",
|
|
1317
|
+
"dir",
|
|
1318
|
+
"frame",
|
|
1319
|
+
"frameset",
|
|
1320
|
+
"noframes",
|
|
1321
|
+
"isindex",
|
|
1322
|
+
"keygen",
|
|
1323
|
+
"listing",
|
|
1324
|
+
"menuitem",
|
|
1325
|
+
"nextid",
|
|
1326
|
+
"noembed",
|
|
1327
|
+
"plaintext",
|
|
1328
|
+
"rb",
|
|
1329
|
+
"rtc",
|
|
1330
|
+
"strike",
|
|
1331
|
+
"xmp",
|
|
1332
|
+
"basefont",
|
|
1333
|
+
"big",
|
|
1334
|
+
"blink",
|
|
1335
|
+
"center",
|
|
1336
|
+
"font",
|
|
1337
|
+
"marquee",
|
|
1338
|
+
"multicol",
|
|
1339
|
+
"nobr",
|
|
1340
|
+
"spacer",
|
|
1341
|
+
"tt"
|
|
1342
|
+
];
|
|
1343
|
+
var OBSOLETE_TAGS_SET = new Set(OBSOLETE_TAGS);
|
|
1344
|
+
var NO_OBSOLETE_TAGS_MESSAGE_IDS = {
|
|
1345
|
+
unexpected: "unexpected"
|
|
1346
|
+
};
|
|
1347
|
+
function noObsoleteTags() {
|
|
1348
|
+
return {
|
|
1349
|
+
/**
|
|
1350
|
+
* @param {ElementNodeAdapter<
|
|
1351
|
+
* ElementNode,
|
|
1352
|
+
* AttributeKeyNode,
|
|
1353
|
+
* AttributeValueNode
|
|
1354
|
+
* >} adapter
|
|
1355
|
+
* @returns {NoObsoleteTagsResult<ElementNode>}
|
|
1356
|
+
*/
|
|
1357
|
+
checkElement(adapter) {
|
|
1358
|
+
const tagName = adapter.getTagName();
|
|
1359
|
+
if (OBSOLETE_TAGS_SET.has(tagName)) {
|
|
1360
|
+
return [
|
|
1361
|
+
{
|
|
1362
|
+
messageId: NO_OBSOLETE_TAGS_MESSAGE_IDS.unexpected,
|
|
1363
|
+
node: adapter.node(),
|
|
1364
|
+
data: {
|
|
1365
|
+
tag: tagName
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
];
|
|
1369
|
+
}
|
|
1370
|
+
return [];
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
// lib/utils/obsolete-attrs.js
|
|
1376
|
+
var OBSOLETE_ATTRS = {
|
|
1377
|
+
charset: [
|
|
1378
|
+
{
|
|
1379
|
+
elements: ["a", "link"],
|
|
1380
|
+
suggestion: "Use an HTTP `Content-Type` header on the linked resource instead."
|
|
1381
|
+
},
|
|
1382
|
+
{
|
|
1383
|
+
elements: ["script"],
|
|
1384
|
+
suggestion: "It is redundant to specify it on the script element since it inherits from the document."
|
|
1385
|
+
}
|
|
1386
|
+
],
|
|
1387
|
+
coords: [
|
|
1388
|
+
{
|
|
1389
|
+
elements: ["a"],
|
|
1390
|
+
suggestion: "Use area instead of a for image maps."
|
|
1391
|
+
}
|
|
1392
|
+
],
|
|
1393
|
+
shape: [
|
|
1394
|
+
{
|
|
1395
|
+
elements: ["a"],
|
|
1396
|
+
suggestion: "Use area instead of a for image maps."
|
|
1397
|
+
}
|
|
1398
|
+
],
|
|
1399
|
+
methods: [
|
|
1400
|
+
{
|
|
1401
|
+
elements: ["a", "link"],
|
|
1402
|
+
suggestion: "Use the HTTP OPTIONS feature instead."
|
|
1403
|
+
}
|
|
1404
|
+
],
|
|
1405
|
+
name: [
|
|
1406
|
+
{
|
|
1407
|
+
elements: ["a", "embed", "img", "option"],
|
|
1408
|
+
suggestion: "Use the id attribute instead."
|
|
1409
|
+
}
|
|
1410
|
+
],
|
|
1411
|
+
rev: [
|
|
1412
|
+
{
|
|
1413
|
+
elements: ["a", "link"],
|
|
1414
|
+
suggestion: 'Use the rel attribute instead, with an opposite term. (For example, instead of rev="made", use rel="author".)'
|
|
1415
|
+
}
|
|
1416
|
+
],
|
|
1417
|
+
urn: [
|
|
1418
|
+
{
|
|
1419
|
+
elements: ["a", "link"],
|
|
1420
|
+
suggestion: "Specify the preferred persistent identifier using the href attribute instead."
|
|
1421
|
+
}
|
|
1422
|
+
],
|
|
1423
|
+
accept: [
|
|
1424
|
+
{
|
|
1425
|
+
elements: ["form"],
|
|
1426
|
+
suggestion: "Use the accept attribute directly on the input elements instead."
|
|
1427
|
+
}
|
|
1428
|
+
],
|
|
1429
|
+
hreflang: [
|
|
1430
|
+
{
|
|
1431
|
+
elements: ["area"],
|
|
1432
|
+
suggestion: "These attributes do not do anything useful, and for historical reasons there are no corresponding IDL attributes on area elements. Omit them altogether."
|
|
1433
|
+
}
|
|
1434
|
+
],
|
|
1435
|
+
type: [
|
|
1436
|
+
{
|
|
1437
|
+
elements: ["area"],
|
|
1438
|
+
suggestion: "These attributes do not do anything useful, and for historical reasons there are no corresponding IDL attributes on area elements. Omit them altogether."
|
|
1439
|
+
},
|
|
1440
|
+
{
|
|
1441
|
+
elements: ["li"],
|
|
1442
|
+
suggestion: "Use CSS instead."
|
|
1443
|
+
},
|
|
1444
|
+
{
|
|
1445
|
+
elements: ["menu"],
|
|
1446
|
+
suggestion: "To implement a custom context menu, use script to handle the contextmenu event. For toolbar menus, omit the attribute."
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
elements: ["style"],
|
|
1450
|
+
suggestion: "Omit the attribute for CSS; for data blocks, use script as the container instead of style."
|
|
1451
|
+
},
|
|
1452
|
+
{
|
|
1453
|
+
elements: ["ul"],
|
|
1454
|
+
suggestion: "Use CSS instead."
|
|
1455
|
+
}
|
|
1456
|
+
],
|
|
1457
|
+
nohref: [
|
|
1458
|
+
{
|
|
1459
|
+
elements: ["area"],
|
|
1460
|
+
suggestion: "Omitting the href attribute is sufficient; the nohref attribute is unnecessary. Omit it altogether."
|
|
1461
|
+
}
|
|
1462
|
+
],
|
|
1463
|
+
profile: [
|
|
1464
|
+
{
|
|
1465
|
+
elements: ["head"],
|
|
1466
|
+
suggestion: "Unnecessary. Omit it altogether."
|
|
1467
|
+
}
|
|
1468
|
+
],
|
|
1469
|
+
manifest: [
|
|
1470
|
+
{
|
|
1471
|
+
elements: ["html"],
|
|
1472
|
+
suggestion: "Use service workers instead."
|
|
1473
|
+
}
|
|
1474
|
+
],
|
|
1475
|
+
version: [
|
|
1476
|
+
{
|
|
1477
|
+
elements: ["html"],
|
|
1478
|
+
suggestion: "Unnecessary. Omit it altogether."
|
|
1479
|
+
}
|
|
1480
|
+
],
|
|
1481
|
+
ismap: [
|
|
1482
|
+
{
|
|
1483
|
+
elements: ["input"],
|
|
1484
|
+
suggestion: "Unnecessary. Omit it altogether. All input elements with a type attribute in the Image Button state are processed as server-side image maps."
|
|
1485
|
+
}
|
|
1486
|
+
],
|
|
1487
|
+
usemap: [
|
|
1488
|
+
{
|
|
1489
|
+
elements: ["input", "object"],
|
|
1490
|
+
suggestion: "Use the img element for image maps."
|
|
1491
|
+
}
|
|
1492
|
+
],
|
|
1493
|
+
longdesc: [
|
|
1494
|
+
{
|
|
1495
|
+
elements: ["iframe", "img"],
|
|
1496
|
+
suggestion: "Use a regular a element to link to the description, or (in the case of images) use an image map to provide a link from the image to the image's description."
|
|
1497
|
+
}
|
|
1498
|
+
],
|
|
1499
|
+
lowsrc: [
|
|
1500
|
+
{
|
|
1501
|
+
elements: ["img"],
|
|
1502
|
+
suggestion: "Use a progressive JPEG image (given in the src attribute), instead of using two separate images."
|
|
1503
|
+
}
|
|
1504
|
+
],
|
|
1505
|
+
target: [
|
|
1506
|
+
{
|
|
1507
|
+
elements: ["link"],
|
|
1508
|
+
suggestion: "Unnecessary. Omit it altogether."
|
|
1509
|
+
}
|
|
1510
|
+
],
|
|
1511
|
+
label: [
|
|
1512
|
+
{
|
|
1513
|
+
elements: ["menu"],
|
|
1514
|
+
suggestion: "To implement a custom context menu, use script to handle the contextmenu event."
|
|
1515
|
+
}
|
|
1516
|
+
],
|
|
1517
|
+
contextmenu: [
|
|
1518
|
+
{
|
|
1519
|
+
elements: ["*"],
|
|
1520
|
+
suggestion: "To implement a custom context menu, use script to handle the contextmenu event."
|
|
1521
|
+
}
|
|
1522
|
+
],
|
|
1523
|
+
onshow: [
|
|
1524
|
+
{
|
|
1525
|
+
elements: ["*"],
|
|
1526
|
+
suggestion: "To implement a custom context menu, use script to handle the contextmenu event."
|
|
1527
|
+
}
|
|
1528
|
+
],
|
|
1529
|
+
scheme: [
|
|
1530
|
+
{
|
|
1531
|
+
elements: ["meta"],
|
|
1532
|
+
suggestion: "Use only one scheme per field, or make the scheme declaration part of the value."
|
|
1533
|
+
}
|
|
1534
|
+
],
|
|
1535
|
+
archive: [
|
|
1536
|
+
{
|
|
1537
|
+
elements: ["object"],
|
|
1538
|
+
suggestion: "Use the data and type attributes to invoke plugins."
|
|
1539
|
+
}
|
|
1540
|
+
],
|
|
1541
|
+
classid: [
|
|
1542
|
+
{
|
|
1543
|
+
elements: ["object"],
|
|
1544
|
+
suggestion: "Use the data and type attributes to invoke plugins."
|
|
1545
|
+
}
|
|
1546
|
+
],
|
|
1547
|
+
code: [
|
|
1548
|
+
{
|
|
1549
|
+
elements: ["object"],
|
|
1550
|
+
suggestion: "Use the data and type attributes to invoke plugins."
|
|
1551
|
+
}
|
|
1552
|
+
],
|
|
1553
|
+
codebase: [
|
|
1554
|
+
{
|
|
1555
|
+
elements: ["object"],
|
|
1556
|
+
suggestion: "Use the data and type attributes to invoke plugins."
|
|
1557
|
+
}
|
|
1558
|
+
],
|
|
1559
|
+
codetype: [
|
|
1560
|
+
{
|
|
1561
|
+
elements: ["object"],
|
|
1562
|
+
suggestion: "Use the data and type attributes to invoke plugins."
|
|
1563
|
+
}
|
|
1564
|
+
],
|
|
1565
|
+
declare: [
|
|
1566
|
+
{
|
|
1567
|
+
elements: ["object"],
|
|
1568
|
+
suggestion: "Repeat the object element completely each time the resource is to be reused."
|
|
1569
|
+
}
|
|
1570
|
+
],
|
|
1571
|
+
standby: [
|
|
1572
|
+
{
|
|
1573
|
+
elements: ["object"],
|
|
1574
|
+
suggestion: "Optimize the linked resource so that it loads quickly or, at least, incrementally."
|
|
1575
|
+
}
|
|
1576
|
+
],
|
|
1577
|
+
typemustmatch: [
|
|
1578
|
+
{
|
|
1579
|
+
elements: ["object"],
|
|
1580
|
+
suggestion: "Avoid using object elements with untrusted resources."
|
|
1581
|
+
}
|
|
1582
|
+
],
|
|
1583
|
+
language: [
|
|
1584
|
+
{
|
|
1585
|
+
elements: ["script"],
|
|
1586
|
+
suggestion: "Omit the attribute for JavaScript; for data blocks, use the type attribute instead."
|
|
1587
|
+
}
|
|
1588
|
+
],
|
|
1589
|
+
event: [
|
|
1590
|
+
{
|
|
1591
|
+
elements: ["script"],
|
|
1592
|
+
suggestion: "Use DOM events mechanisms to register event listeners."
|
|
1593
|
+
}
|
|
1594
|
+
],
|
|
1595
|
+
for: [
|
|
1596
|
+
{
|
|
1597
|
+
elements: ["script"],
|
|
1598
|
+
suggestion: "Use DOM events mechanisms to register event listeners."
|
|
1599
|
+
}
|
|
1600
|
+
],
|
|
1601
|
+
datapagesize: [
|
|
1602
|
+
{
|
|
1603
|
+
elements: ["table"],
|
|
1604
|
+
suggestion: "Unnecessary. Omit it altogether."
|
|
1605
|
+
}
|
|
1606
|
+
],
|
|
1607
|
+
summary: [
|
|
1608
|
+
{
|
|
1609
|
+
elements: ["table"],
|
|
1610
|
+
suggestion: "Use one of the techniques for describing tables given in the table section instead."
|
|
1611
|
+
}
|
|
1612
|
+
],
|
|
1613
|
+
abbr: [
|
|
1614
|
+
{
|
|
1615
|
+
elements: ["td"],
|
|
1616
|
+
suggestion: "Use text that begins in an unambiguous and terse manner, and include any more elaborate text after that. The title attribute can also be useful in including more detailed text, so that the cell's contents can be made terse. If it's a heading, use th (which has an abbr attribute)."
|
|
1617
|
+
}
|
|
1618
|
+
],
|
|
1619
|
+
axis: [
|
|
1620
|
+
{
|
|
1621
|
+
elements: ["td", "th"],
|
|
1622
|
+
suggestion: "Use the scope attribute on the relevant th."
|
|
1623
|
+
}
|
|
1624
|
+
],
|
|
1625
|
+
scope: [
|
|
1626
|
+
{
|
|
1627
|
+
elements: ["td"],
|
|
1628
|
+
suggestion: "Use th elements for heading cells."
|
|
1629
|
+
}
|
|
1630
|
+
],
|
|
1631
|
+
datasrc: [
|
|
1632
|
+
{
|
|
1633
|
+
elements: [
|
|
1634
|
+
"a",
|
|
1635
|
+
"button",
|
|
1636
|
+
"div",
|
|
1637
|
+
"frame",
|
|
1638
|
+
"iframe",
|
|
1639
|
+
"img",
|
|
1640
|
+
"input",
|
|
1641
|
+
"label",
|
|
1642
|
+
"legend",
|
|
1643
|
+
"marquee",
|
|
1644
|
+
"object",
|
|
1645
|
+
"option",
|
|
1646
|
+
"select",
|
|
1647
|
+
"span",
|
|
1648
|
+
"table",
|
|
1649
|
+
"textarea"
|
|
1650
|
+
],
|
|
1651
|
+
suggestion: "Use script and a mechanism such as XMLHttpRequest to populate the page dynamically."
|
|
1652
|
+
}
|
|
1653
|
+
],
|
|
1654
|
+
datafld: [
|
|
1655
|
+
{
|
|
1656
|
+
elements: [
|
|
1657
|
+
"a",
|
|
1658
|
+
"button",
|
|
1659
|
+
"div",
|
|
1660
|
+
"fieldset",
|
|
1661
|
+
"frame",
|
|
1662
|
+
"iframe",
|
|
1663
|
+
"img",
|
|
1664
|
+
"input",
|
|
1665
|
+
"label",
|
|
1666
|
+
"legend",
|
|
1667
|
+
"marquee",
|
|
1668
|
+
"object",
|
|
1669
|
+
"select",
|
|
1670
|
+
"span",
|
|
1671
|
+
"textarea"
|
|
1672
|
+
],
|
|
1673
|
+
suggestion: "Use script and a mechanism such as XMLHttpRequest to populate the page dynamically."
|
|
1674
|
+
}
|
|
1675
|
+
],
|
|
1676
|
+
dataformatas: [
|
|
1677
|
+
{
|
|
1678
|
+
elements: [
|
|
1679
|
+
"button",
|
|
1680
|
+
"div",
|
|
1681
|
+
"input",
|
|
1682
|
+
"label",
|
|
1683
|
+
"legend",
|
|
1684
|
+
"marquee",
|
|
1685
|
+
"object",
|
|
1686
|
+
"option",
|
|
1687
|
+
"select",
|
|
1688
|
+
"span",
|
|
1689
|
+
"table"
|
|
1690
|
+
],
|
|
1691
|
+
suggestion: "Use script and a mechanism such as XMLHttpRequest to populate the page dynamically."
|
|
1692
|
+
}
|
|
1693
|
+
],
|
|
1694
|
+
dropzone: [
|
|
1695
|
+
{
|
|
1696
|
+
elements: ["*"],
|
|
1697
|
+
suggestion: "Use script to handle the dragenter and dragover events instead."
|
|
1698
|
+
}
|
|
1699
|
+
],
|
|
1700
|
+
alink: [
|
|
1701
|
+
{
|
|
1702
|
+
elements: ["body"],
|
|
1703
|
+
suggestion: "Use CSS instead."
|
|
1704
|
+
}
|
|
1705
|
+
],
|
|
1706
|
+
bgcolor: [
|
|
1707
|
+
{
|
|
1708
|
+
elements: ["body", "table", "td", "th", "tr"],
|
|
1709
|
+
suggestion: "Use CSS instead."
|
|
1710
|
+
}
|
|
1711
|
+
],
|
|
1712
|
+
bottommargin: [
|
|
1713
|
+
{
|
|
1714
|
+
elements: ["body"],
|
|
1715
|
+
suggestion: "Use CSS instead."
|
|
1716
|
+
}
|
|
1717
|
+
],
|
|
1718
|
+
leftmargin: [
|
|
1719
|
+
{
|
|
1720
|
+
elements: ["body"],
|
|
1721
|
+
suggestion: "Use CSS instead."
|
|
1722
|
+
}
|
|
1723
|
+
],
|
|
1724
|
+
link: [
|
|
1725
|
+
{
|
|
1726
|
+
elements: ["body"],
|
|
1727
|
+
suggestion: "Use CSS instead."
|
|
1728
|
+
}
|
|
1729
|
+
],
|
|
1730
|
+
marginheight: [
|
|
1731
|
+
{
|
|
1732
|
+
elements: ["body", "iframe"],
|
|
1733
|
+
suggestion: "Use CSS instead."
|
|
1734
|
+
}
|
|
1735
|
+
],
|
|
1736
|
+
marginwidth: [
|
|
1737
|
+
{
|
|
1738
|
+
elements: ["body", "iframe"],
|
|
1739
|
+
suggestion: "Use CSS instead."
|
|
1740
|
+
}
|
|
1741
|
+
],
|
|
1742
|
+
rightmargin: [
|
|
1743
|
+
{
|
|
1744
|
+
elements: ["body"],
|
|
1745
|
+
suggestion: "Use CSS instead."
|
|
1746
|
+
}
|
|
1747
|
+
],
|
|
1748
|
+
text: [
|
|
1749
|
+
{
|
|
1750
|
+
elements: ["body"],
|
|
1751
|
+
suggestion: "Use CSS instead."
|
|
1752
|
+
}
|
|
1753
|
+
],
|
|
1754
|
+
topmargin: [
|
|
1755
|
+
{
|
|
1756
|
+
elements: ["body"],
|
|
1757
|
+
suggestion: "Use CSS instead."
|
|
1758
|
+
}
|
|
1759
|
+
],
|
|
1760
|
+
vlink: [
|
|
1761
|
+
{
|
|
1762
|
+
elements: ["body"],
|
|
1763
|
+
suggestion: "Use CSS instead."
|
|
1764
|
+
}
|
|
1765
|
+
],
|
|
1766
|
+
clear: [
|
|
1767
|
+
{
|
|
1768
|
+
elements: ["br"],
|
|
1769
|
+
suggestion: "Use CSS instead."
|
|
1770
|
+
}
|
|
1771
|
+
],
|
|
1772
|
+
align: [
|
|
1773
|
+
{
|
|
1774
|
+
elements: [
|
|
1775
|
+
"caption",
|
|
1776
|
+
"col",
|
|
1777
|
+
"div",
|
|
1778
|
+
"embed",
|
|
1779
|
+
"h1",
|
|
1780
|
+
"h2",
|
|
1781
|
+
"h3",
|
|
1782
|
+
"h4",
|
|
1783
|
+
"h5",
|
|
1784
|
+
"h6",
|
|
1785
|
+
"hr",
|
|
1786
|
+
"iframe",
|
|
1787
|
+
"input",
|
|
1788
|
+
"img",
|
|
1789
|
+
"legend",
|
|
1790
|
+
"object",
|
|
1791
|
+
"p",
|
|
1792
|
+
"table",
|
|
1793
|
+
"tbody",
|
|
1794
|
+
"thead",
|
|
1795
|
+
"tfoot",
|
|
1796
|
+
"td",
|
|
1797
|
+
"th",
|
|
1798
|
+
"tr"
|
|
1799
|
+
],
|
|
1800
|
+
suggestion: "Use CSS instead."
|
|
1801
|
+
}
|
|
1802
|
+
],
|
|
1803
|
+
char: [
|
|
1804
|
+
{
|
|
1805
|
+
elements: ["col", "tbody", "thead", "tfoot", "td", "th", "tr"],
|
|
1806
|
+
suggestion: "Use CSS instead."
|
|
1807
|
+
}
|
|
1808
|
+
],
|
|
1809
|
+
charoff: [
|
|
1810
|
+
{
|
|
1811
|
+
elements: ["col", "tbody", "thead", "tfoot", "td", "th", "tr"],
|
|
1812
|
+
suggestion: "Use CSS instead."
|
|
1813
|
+
}
|
|
1814
|
+
],
|
|
1815
|
+
valign: [
|
|
1816
|
+
{
|
|
1817
|
+
elements: ["col", "tbody", "thead", "tfoot", "td", "th", "tr"],
|
|
1818
|
+
suggestion: "Use CSS instead."
|
|
1819
|
+
}
|
|
1820
|
+
],
|
|
1821
|
+
width: [
|
|
1822
|
+
{
|
|
1823
|
+
elements: ["col", "hr", "pre", "table", "td", "th"],
|
|
1824
|
+
suggestion: "Use CSS instead."
|
|
1825
|
+
}
|
|
1826
|
+
],
|
|
1827
|
+
compact: [
|
|
1828
|
+
{
|
|
1829
|
+
elements: ["dl", "menu", "ol", "ul"],
|
|
1830
|
+
suggestion: "Use CSS instead."
|
|
1831
|
+
}
|
|
1832
|
+
],
|
|
1833
|
+
hspace: [
|
|
1834
|
+
{
|
|
1835
|
+
elements: ["embed", "iframe", "input", "img", "object"],
|
|
1836
|
+
suggestion: "Use CSS instead."
|
|
1837
|
+
}
|
|
1838
|
+
],
|
|
1839
|
+
vspace: [
|
|
1840
|
+
{
|
|
1841
|
+
elements: ["embed", "iframe", "input", "img", "object"],
|
|
1842
|
+
suggestion: "Use CSS instead."
|
|
1843
|
+
}
|
|
1844
|
+
],
|
|
1845
|
+
color: [
|
|
1846
|
+
{
|
|
1847
|
+
elements: ["hr"],
|
|
1848
|
+
suggestion: "Use CSS instead."
|
|
1849
|
+
}
|
|
1850
|
+
],
|
|
1851
|
+
noshade: [
|
|
1852
|
+
{
|
|
1853
|
+
elements: ["hr"],
|
|
1854
|
+
suggestion: "Use CSS instead."
|
|
1855
|
+
}
|
|
1856
|
+
],
|
|
1857
|
+
size: [
|
|
1858
|
+
{
|
|
1859
|
+
elements: ["hr"],
|
|
1860
|
+
suggestion: "Use CSS instead."
|
|
1861
|
+
}
|
|
1862
|
+
],
|
|
1863
|
+
allowtransparency: [
|
|
1864
|
+
{
|
|
1865
|
+
elements: ["iframe"],
|
|
1866
|
+
suggestion: "Use CSS instead."
|
|
1867
|
+
}
|
|
1868
|
+
],
|
|
1869
|
+
frameborder: [
|
|
1870
|
+
{
|
|
1871
|
+
elements: ["iframe"],
|
|
1872
|
+
suggestion: "Use CSS instead."
|
|
1873
|
+
}
|
|
1874
|
+
],
|
|
1875
|
+
framespacing: [
|
|
1876
|
+
{
|
|
1877
|
+
elements: ["iframe"],
|
|
1878
|
+
suggestion: "Use CSS instead."
|
|
1879
|
+
}
|
|
1880
|
+
],
|
|
1881
|
+
scrolling: [
|
|
1882
|
+
{
|
|
1883
|
+
elements: ["iframe"],
|
|
1884
|
+
suggestion: "Use CSS instead."
|
|
1885
|
+
}
|
|
1886
|
+
],
|
|
1887
|
+
border: [
|
|
1888
|
+
{
|
|
1889
|
+
elements: ["input", "img", "object", "table"],
|
|
1890
|
+
suggestion: "Use CSS instead."
|
|
1891
|
+
}
|
|
1892
|
+
],
|
|
1893
|
+
frame: [
|
|
1894
|
+
{
|
|
1895
|
+
elements: ["table"],
|
|
1896
|
+
suggestion: "Use CSS instead."
|
|
1897
|
+
}
|
|
1898
|
+
],
|
|
1899
|
+
bordercolor: [
|
|
1900
|
+
{
|
|
1901
|
+
elements: ["table"],
|
|
1902
|
+
suggestion: "Use CSS instead."
|
|
1903
|
+
}
|
|
1904
|
+
],
|
|
1905
|
+
cellpadding: [
|
|
1906
|
+
{
|
|
1907
|
+
elements: ["table"],
|
|
1908
|
+
suggestion: "Use CSS instead."
|
|
1909
|
+
}
|
|
1910
|
+
],
|
|
1911
|
+
cellspacing: [
|
|
1912
|
+
{
|
|
1913
|
+
elements: ["table"],
|
|
1914
|
+
suggestion: "Use CSS instead."
|
|
1915
|
+
}
|
|
1916
|
+
],
|
|
1917
|
+
height: [
|
|
1918
|
+
{
|
|
1919
|
+
elements: ["table", "thead", "tbody", "tfoot", "td", "th", "tr"],
|
|
1920
|
+
suggestion: "Use CSS instead."
|
|
1921
|
+
}
|
|
1922
|
+
],
|
|
1923
|
+
rules: [
|
|
1924
|
+
{
|
|
1925
|
+
elements: ["table"],
|
|
1926
|
+
suggestion: "Use CSS instead."
|
|
1927
|
+
}
|
|
1928
|
+
],
|
|
1929
|
+
nowrap: [
|
|
1930
|
+
{
|
|
1931
|
+
elements: ["td", "th"],
|
|
1932
|
+
suggestion: "Use CSS instead."
|
|
1933
|
+
}
|
|
1934
|
+
],
|
|
1935
|
+
background: [
|
|
1936
|
+
{
|
|
1937
|
+
elements: ["body", "table", "thead", "tbody", "tfoot", "tr", "td", "th"],
|
|
1938
|
+
suggestion: "Use CSS instead."
|
|
1939
|
+
}
|
|
1940
|
+
]
|
|
1941
|
+
};
|
|
1942
|
+
|
|
1943
|
+
// lib/rules/no-obsolete-attrs.js
|
|
1944
|
+
var NO_OBSOLETE_ATTRS_MESSAGE_IDS = {
|
|
1945
|
+
obsolete: "obsolete"
|
|
1946
|
+
};
|
|
1947
|
+
function noObsoleteAttrs() {
|
|
1948
|
+
return {
|
|
1949
|
+
/**
|
|
1950
|
+
* @param {ElementNodeAdapter<
|
|
1951
|
+
* ElementNode,
|
|
1952
|
+
* AttributeKeyNode,
|
|
1953
|
+
* AttributeValueNode
|
|
1954
|
+
* >} adapter
|
|
1955
|
+
* @returns {NoObsoleteAttrsResult<AttributeKeyNode>}
|
|
1956
|
+
*/
|
|
1957
|
+
checkAttributes(adapter) {
|
|
1958
|
+
const elementName = adapter.getTagName();
|
|
1959
|
+
const result = [];
|
|
1960
|
+
for (const attribute of adapter.getAttributes()) {
|
|
1961
|
+
const attrKeyValue = attribute.key.value();
|
|
1962
|
+
const attrValueValue = attribute.value.value();
|
|
1963
|
+
if (attribute.key.isExpression() || attrKeyValue === null || attrValueValue === null) {
|
|
1964
|
+
continue;
|
|
1965
|
+
}
|
|
1966
|
+
const attrName = attrKeyValue.toLowerCase();
|
|
1967
|
+
if (OBSOLETE_ATTRS[attrName]) {
|
|
1968
|
+
const obsoleteConfigs = OBSOLETE_ATTRS[attrName];
|
|
1969
|
+
for (const config of obsoleteConfigs) {
|
|
1970
|
+
if (config.elements.includes("*") || config.elements.includes(elementName)) {
|
|
1971
|
+
result.push({
|
|
1972
|
+
node: attribute.key.node(),
|
|
1973
|
+
messageId: NO_OBSOLETE_ATTRS_MESSAGE_IDS.obsolete,
|
|
1974
|
+
data: {
|
|
1975
|
+
attr: attrName,
|
|
1976
|
+
element: elementName,
|
|
1977
|
+
suggestion: config.suggestion
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
break;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
return result;
|
|
1986
|
+
}
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
export {
|
|
1990
|
+
NO_INEFFECTIVE_ATTRS_MESSAGE_IDS,
|
|
1991
|
+
NO_INVALID_ATTR_VALUE_MESSAGE_IDS,
|
|
1992
|
+
NO_OBSOLETE_ATTRS_MESSAGE_IDS,
|
|
1993
|
+
NO_OBSOLETE_TAGS_MESSAGE_IDS,
|
|
1994
|
+
USE_BASELINE_MESSAGE_IDS,
|
|
1995
|
+
noIneffectiveAttrs,
|
|
1996
|
+
noInvalidAttrValue,
|
|
1997
|
+
noObsoleteAttrs,
|
|
1998
|
+
noObsoleteTags,
|
|
1999
|
+
useBaseline
|
|
2000
|
+
};
|
|
2001
|
+
//# sourceMappingURL=index.mjs.map
|