@html-eslint/eslint-plugin 0.51.0 → 0.52.1
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/lib/configs/recommended.js +8 -2
- package/lib/index.js +2 -6
- package/lib/languages/html-language.js +23 -15
- package/lib/languages/html-source-code.js +34 -26
- package/lib/languages/html-traversal-step.js +6 -10
- package/lib/rules/attrs-newline.js +15 -11
- package/lib/rules/class-spacing.js +148 -0
- package/lib/rules/element-newline.js +18 -21
- package/lib/rules/id-naming-convention.js +15 -12
- package/lib/rules/indent/indent-level.js +10 -17
- package/lib/rules/indent/indent.js +51 -56
- package/lib/rules/index.js +5 -1
- package/lib/rules/lowercase.js +11 -23
- package/lib/rules/max-element-depth.js +8 -10
- package/lib/rules/no-abstract-roles.js +8 -8
- package/lib/rules/no-accesskey-attrs.js +8 -8
- package/lib/rules/no-aria-hidden-body.js +2 -6
- package/lib/rules/no-aria-hidden-on-focusable.js +4 -5
- package/lib/rules/no-duplicate-attrs.js +12 -8
- package/lib/rules/no-duplicate-class.js +8 -14
- package/lib/rules/no-duplicate-id.js +9 -15
- package/lib/rules/no-duplicate-in-head.js +10 -17
- package/lib/rules/no-empty-headings.js +7 -8
- package/lib/rules/no-extra-spacing-attrs.js +13 -8
- package/lib/rules/no-extra-spacing-text.js +11 -14
- package/lib/rules/no-heading-inside-button.js +2 -6
- package/lib/rules/no-ineffective-attrs.js +14 -15
- package/lib/rules/no-inline-styles.js +2 -6
- package/lib/rules/no-invalid-entity.js +4 -8
- package/lib/rules/no-invalid-role.js +3 -10
- package/lib/rules/no-multiple-empty-lines.js +7 -7
- package/lib/rules/no-multiple-h1.js +4 -8
- package/lib/rules/no-nested-interactive.js +5 -9
- package/lib/rules/no-non-scalable-viewport.js +2 -6
- package/lib/rules/no-obsolete-attrs.js +83 -0
- package/lib/rules/no-obsolete-tags.js +2 -6
- package/lib/rules/no-positive-tabindex.js +8 -8
- package/lib/rules/no-restricted-attr-values.js +18 -21
- package/lib/rules/no-restricted-attrs.js +18 -22
- package/lib/rules/no-restricted-tags.js +17 -20
- package/lib/rules/no-script-style-type.js +7 -6
- package/lib/rules/no-skip-heading-levels.js +4 -8
- package/lib/rules/no-target-blank.js +3 -6
- package/lib/rules/no-trailing-spaces.js +7 -6
- package/lib/rules/no-whitespace-only-children.js +7 -8
- package/lib/rules/prefer-https.js +11 -14
- package/lib/rules/quotes.js +13 -16
- package/lib/rules/require-attrs.js +18 -17
- package/lib/rules/require-button-type.js +6 -5
- package/lib/rules/require-closing-tags.js +9 -12
- package/lib/rules/require-doctype.js +2 -6
- package/lib/rules/require-explicit-size.js +2 -5
- package/lib/rules/require-form-method.js +2 -6
- package/lib/rules/require-frame-title.js +2 -6
- package/lib/rules/require-img-alt.js +3 -6
- package/lib/rules/require-input-label.js +3 -5
- package/lib/rules/require-lang.js +2 -6
- package/lib/rules/require-li-container.js +2 -6
- package/lib/rules/require-meta-charset.js +6 -5
- package/lib/rules/require-meta-description.js +6 -5
- package/lib/rules/require-meta-viewport.js +6 -5
- package/lib/rules/require-open-graph-protocol.js +7 -8
- package/lib/rules/require-title.js +7 -5
- package/lib/rules/sort-attrs.js +13 -19
- package/lib/rules/use-baseline.js +8 -6
- package/lib/rules/utils/baseline.js +4 -6
- package/lib/rules/utils/naming.js +14 -7
- package/lib/rules/utils/node.js +63 -29
- package/lib/rules/utils/rule.js +1 -4
- package/lib/rules/utils/settings.js +9 -3
- package/lib/rules/utils/source-code.js +2 -6
- package/lib/rules/utils/template-literal.js +16 -7
- package/lib/rules/utils/visitors.js +4 -1
- package/lib/specs/index.js +5 -0
- package/lib/specs/obsolete-attrs.js +604 -0
- package/lib/types/ast.ts +5 -2
- package/package.json +6 -6
- package/types/configs/recommended.d.ts +2 -1
- package/types/configs/recommended.d.ts.map +1 -1
- package/types/index.d.ts +2 -6
- package/types/index.d.ts.map +1 -1
- package/types/languages/html-language.d.ts +12 -10
- package/types/languages/html-language.d.ts.map +1 -1
- package/types/languages/html-source-code.d.ts +13 -6
- package/types/languages/html-source-code.d.ts.map +1 -1
- package/types/languages/html-traversal-step.d.ts +5 -5
- package/types/languages/html-traversal-step.d.ts.map +1 -1
- package/types/rules/attrs-newline.d.ts +1 -1
- package/types/rules/attrs-newline.d.ts.map +1 -1
- package/types/rules/class-spacing.d.ts +4 -0
- package/types/rules/class-spacing.d.ts.map +1 -0
- package/types/rules/element-newline.d.ts +3 -3
- package/types/rules/element-newline.d.ts.map +1 -1
- package/types/rules/id-naming-convention.d.ts.map +1 -1
- package/types/rules/indent/indent-level.d.ts +10 -17
- package/types/rules/indent/indent-level.d.ts.map +1 -1
- package/types/rules/indent/indent.d.ts.map +1 -1
- package/types/rules/lowercase.d.ts.map +1 -1
- package/types/rules/max-element-depth.d.ts.map +1 -1
- package/types/rules/no-abstract-roles.d.ts.map +1 -1
- package/types/rules/no-accesskey-attrs.d.ts.map +1 -1
- package/types/rules/no-aria-hidden-body.d.ts.map +1 -1
- package/types/rules/no-aria-hidden-on-focusable.d.ts.map +1 -1
- package/types/rules/no-duplicate-attrs.d.ts.map +1 -1
- package/types/rules/no-duplicate-class.d.ts.map +1 -1
- package/types/rules/no-duplicate-id.d.ts.map +1 -1
- package/types/rules/no-duplicate-in-head.d.ts.map +1 -1
- package/types/rules/no-empty-headings.d.ts.map +1 -1
- package/types/rules/no-extra-spacing-attrs.d.ts.map +1 -1
- package/types/rules/no-extra-spacing-text.d.ts.map +1 -1
- package/types/rules/no-heading-inside-button.d.ts.map +1 -1
- package/types/rules/no-ineffective-attrs.d.ts.map +1 -1
- package/types/rules/no-inline-styles.d.ts.map +1 -1
- package/types/rules/no-invalid-entity.d.ts.map +1 -1
- package/types/rules/no-invalid-role.d.ts.map +1 -1
- package/types/rules/no-multiple-empty-lines.d.ts.map +1 -1
- package/types/rules/no-multiple-h1.d.ts.map +1 -1
- package/types/rules/no-nested-interactive.d.ts.map +1 -1
- package/types/rules/no-non-scalable-viewport.d.ts.map +1 -1
- package/types/rules/no-obsolete-attrs.d.ts +4 -0
- package/types/rules/no-obsolete-attrs.d.ts.map +1 -0
- package/types/rules/no-obsolete-tags.d.ts.map +1 -1
- package/types/rules/no-positive-tabindex.d.ts.map +1 -1
- package/types/rules/no-restricted-attr-values.d.ts.map +1 -1
- package/types/rules/no-restricted-attrs.d.ts.map +1 -1
- package/types/rules/no-restricted-tags.d.ts.map +1 -1
- package/types/rules/no-script-style-type.d.ts.map +1 -1
- package/types/rules/no-skip-heading-levels.d.ts.map +1 -1
- package/types/rules/no-target-blank.d.ts.map +1 -1
- package/types/rules/no-trailing-spaces.d.ts.map +1 -1
- package/types/rules/no-whitespace-only-children.d.ts.map +1 -1
- package/types/rules/prefer-https.d.ts.map +1 -1
- package/types/rules/quotes.d.ts.map +1 -1
- package/types/rules/require-attrs.d.ts.map +1 -1
- package/types/rules/require-button-type.d.ts.map +1 -1
- package/types/rules/require-closing-tags.d.ts.map +1 -1
- package/types/rules/require-doctype.d.ts.map +1 -1
- package/types/rules/require-explicit-size.d.ts.map +1 -1
- package/types/rules/require-form-method.d.ts.map +1 -1
- package/types/rules/require-frame-title.d.ts.map +1 -1
- package/types/rules/require-img-alt.d.ts.map +1 -1
- package/types/rules/require-input-label.d.ts.map +1 -1
- package/types/rules/require-lang.d.ts.map +1 -1
- package/types/rules/require-li-container.d.ts.map +1 -1
- package/types/rules/require-meta-charset.d.ts.map +1 -1
- package/types/rules/require-meta-description.d.ts.map +1 -1
- package/types/rules/require-meta-viewport.d.ts.map +1 -1
- package/types/rules/require-open-graph-protocol.d.ts.map +1 -1
- package/types/rules/require-title.d.ts.map +1 -1
- package/types/rules/sort-attrs.d.ts.map +1 -1
- package/types/rules/use-baseline.d.ts.map +1 -1
- package/types/rules/utils/baseline.d.ts +1 -3
- package/types/rules/utils/baseline.d.ts.map +1 -1
- package/types/rules/utils/naming.d.ts +14 -7
- package/types/rules/utils/naming.d.ts.map +1 -1
- package/types/rules/utils/node.d.ts +11 -10
- package/types/rules/utils/node.d.ts.map +1 -1
- package/types/rules/utils/rule.d.ts +1 -4
- package/types/rules/utils/rule.d.ts.map +1 -1
- package/types/rules/utils/settings.d.ts +0 -1
- package/types/rules/utils/settings.d.ts.map +1 -1
- package/types/rules/utils/source-code.d.ts +2 -6
- package/types/rules/utils/source-code.d.ts.map +1 -1
- package/types/rules/utils/template-literal.d.ts +2 -1
- package/types/rules/utils/template-literal.d.ts.map +1 -1
- package/types/rules/utils/visitors.d.ts.map +1 -1
- package/types/specs/index.d.ts +3 -0
- package/types/specs/index.d.ts.map +1 -0
- package/types/specs/obsolete-attrs.d.ts +19 -0
- package/types/specs/obsolete-attrs.d.ts.map +1 -0
- package/types/types/ast.d.ts +5 -2
- package/types/types/ast.d.ts.map +1 -1
|
@@ -1,20 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* CloseTemplate,
|
|
5
|
+
* OpenTemplate,
|
|
6
|
+
* ScriptTag,
|
|
7
|
+
* StyleTag,
|
|
8
|
+
* Tag,
|
|
9
|
+
* TemplateLiteral,
|
|
10
|
+
* TemplateText,
|
|
11
|
+
* Text
|
|
12
|
+
* } from "@html-eslint/types"
|
|
13
|
+
* @import {AST} from "eslint"
|
|
14
|
+
* @import {
|
|
15
|
+
* Context,
|
|
16
|
+
* Line,
|
|
17
|
+
* RuleListener,
|
|
18
|
+
* RuleModule
|
|
19
|
+
* } from "../../types"
|
|
6
20
|
* @typedef {AnyNode | Line} AnyNodeOrLine
|
|
21
|
+
*
|
|
7
22
|
* @typedef {Object} IndentType
|
|
8
23
|
* @property {"tab"} TAB
|
|
9
24
|
* @property {"space"} SPACE
|
|
25
|
+
*
|
|
10
26
|
* @typedef {Object} MessageId
|
|
11
27
|
* @property {"wrongIndent"} WRONG_INDENT
|
|
28
|
+
*
|
|
12
29
|
* @typedef {Object} IndentOptionInfo
|
|
13
30
|
* @property {IndentType["TAB"] | IndentType["SPACE"]} indentType
|
|
14
31
|
* @property {number} indentSize
|
|
15
32
|
* @property {string} indentChar
|
|
16
33
|
*
|
|
17
34
|
* @typedef {"tab" | number} Option1
|
|
35
|
+
*
|
|
18
36
|
* @typedef {Object} Option2
|
|
19
37
|
* @property {number} [Option2.Attribute]
|
|
20
38
|
* @property {Record<string, number>} [Option2.tagChildrenIndent]
|
|
@@ -29,7 +47,6 @@ const {
|
|
|
29
47
|
splitToLineNodes,
|
|
30
48
|
isLine,
|
|
31
49
|
isTag,
|
|
32
|
-
hasTemplate,
|
|
33
50
|
isScript,
|
|
34
51
|
isStyle,
|
|
35
52
|
isText,
|
|
@@ -54,9 +71,7 @@ const INDENT_TYPES = {
|
|
|
54
71
|
|
|
55
72
|
const IGNORING_NODES = ["pre", "xmp"];
|
|
56
73
|
|
|
57
|
-
/**
|
|
58
|
-
* @type {RuleModule<[Option1, Option2]>}
|
|
59
|
-
*/
|
|
74
|
+
/** @type {RuleModule<[Option1, Option2]>} */
|
|
60
75
|
module.exports = {
|
|
61
76
|
meta: {
|
|
62
77
|
type: "code",
|
|
@@ -127,7 +142,7 @@ module.exports = {
|
|
|
127
142
|
|
|
128
143
|
/**
|
|
129
144
|
* @param {Tag | ScriptTag | StyleTag | Text} node
|
|
130
|
-
* @
|
|
145
|
+
* @returns {number}
|
|
131
146
|
*/
|
|
132
147
|
function getTagIncreasingLevel(node) {
|
|
133
148
|
if (
|
|
@@ -149,7 +164,7 @@ module.exports = {
|
|
|
149
164
|
|
|
150
165
|
/**
|
|
151
166
|
* @param {AnyNode} node
|
|
152
|
-
* @
|
|
167
|
+
* @returns {number}
|
|
153
168
|
*/
|
|
154
169
|
function getIncreasingLevel(node) {
|
|
155
170
|
if (isLine(node)) {
|
|
@@ -189,7 +204,6 @@ module.exports = {
|
|
|
189
204
|
}
|
|
190
205
|
|
|
191
206
|
/**
|
|
192
|
-
*
|
|
193
207
|
* @param {TemplateLiteral} node
|
|
194
208
|
* @returns {number}
|
|
195
209
|
*/
|
|
@@ -222,7 +236,11 @@ module.exports = {
|
|
|
222
236
|
let parentIgnoringChildCount = 0;
|
|
223
237
|
|
|
224
238
|
/**
|
|
225
|
-
* @param {AnyNode
|
|
239
|
+
* @param {AnyNode
|
|
240
|
+
* | Line
|
|
241
|
+
* | TemplateText
|
|
242
|
+
* | OpenTemplate
|
|
243
|
+
* | CloseTemplate} node
|
|
226
244
|
* @returns {string}
|
|
227
245
|
*/
|
|
228
246
|
function getActualIndent(node) {
|
|
@@ -237,9 +255,7 @@ module.exports = {
|
|
|
237
255
|
return line.slice(0, column);
|
|
238
256
|
}
|
|
239
257
|
|
|
240
|
-
/**
|
|
241
|
-
* @returns {string}
|
|
242
|
-
*/
|
|
258
|
+
/** @returns {string} */
|
|
243
259
|
function getExpectedIndent() {
|
|
244
260
|
let base = "";
|
|
245
261
|
if (indentType === "space") {
|
|
@@ -284,7 +300,11 @@ module.exports = {
|
|
|
284
300
|
}
|
|
285
301
|
|
|
286
302
|
/**
|
|
287
|
-
* @param {AnyNode
|
|
303
|
+
* @param {AnyNode
|
|
304
|
+
* | Line
|
|
305
|
+
* | TemplateText
|
|
306
|
+
* | OpenTemplate
|
|
307
|
+
* | CloseTemplate} node
|
|
288
308
|
*/
|
|
289
309
|
function checkIndent(node) {
|
|
290
310
|
if (parentIgnoringChildCount > 0) {
|
|
@@ -309,9 +329,7 @@ module.exports = {
|
|
|
309
329
|
}
|
|
310
330
|
}
|
|
311
331
|
|
|
312
|
-
/**
|
|
313
|
-
* @type {RuleListener}
|
|
314
|
-
*/
|
|
332
|
+
/** @type {RuleListener} */
|
|
315
333
|
const commentVisitor = {
|
|
316
334
|
Comment(node) {
|
|
317
335
|
indentLevel.indent(node);
|
|
@@ -319,22 +337,13 @@ module.exports = {
|
|
|
319
337
|
CommentOpen: checkIndent,
|
|
320
338
|
CommentContent(node) {
|
|
321
339
|
indentLevel.indent(node);
|
|
322
|
-
if (hasTemplate(node)) {
|
|
323
|
-
node.parts.forEach((part) => {
|
|
324
|
-
if (part.type !== NODE_TYPES.Part) {
|
|
325
|
-
if (part.open) {
|
|
326
|
-
checkIndent(part.open);
|
|
327
|
-
}
|
|
328
|
-
if (part.close) {
|
|
329
|
-
checkIndent(part.close);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
|
|
335
340
|
const lineNodes = splitToLineNodes(node);
|
|
336
341
|
lineNodes.forEach((lineNode) => {
|
|
337
|
-
if (
|
|
342
|
+
if (
|
|
343
|
+
lineNode.isOverlapTemplate &&
|
|
344
|
+
!lineNode.hasCloseTemplate &&
|
|
345
|
+
!lineNode.hasOpenTemplate
|
|
346
|
+
) {
|
|
338
347
|
return;
|
|
339
348
|
}
|
|
340
349
|
if (lineNode.value.trim().length) {
|
|
@@ -351,9 +360,7 @@ module.exports = {
|
|
|
351
360
|
},
|
|
352
361
|
};
|
|
353
362
|
|
|
354
|
-
/**
|
|
355
|
-
* @type {RuleListener}
|
|
356
|
-
*/
|
|
363
|
+
/** @type {RuleListener} */
|
|
357
364
|
const visitor = {
|
|
358
365
|
Tag(node) {
|
|
359
366
|
if (IGNORING_NODES.includes(node.name)) {
|
|
@@ -401,23 +408,13 @@ module.exports = {
|
|
|
401
408
|
},
|
|
402
409
|
Text(node) {
|
|
403
410
|
indentLevel.indent(node);
|
|
404
|
-
if (hasTemplate(node)) {
|
|
405
|
-
node.parts.forEach((part) => {
|
|
406
|
-
if (part.type !== NODE_TYPES.Part) {
|
|
407
|
-
if (part.open) {
|
|
408
|
-
checkIndent(part.open);
|
|
409
|
-
}
|
|
410
|
-
if (part.close) {
|
|
411
|
-
checkIndent(part.close);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
|
|
417
411
|
const lineNodes = splitToLineNodes(node);
|
|
418
|
-
|
|
419
412
|
lineNodes.forEach((lineNode) => {
|
|
420
|
-
if (
|
|
413
|
+
if (
|
|
414
|
+
lineNode.isOverlapTemplate &&
|
|
415
|
+
!lineNode.hasCloseTemplate &&
|
|
416
|
+
!lineNode.hasOpenTemplate
|
|
417
|
+
) {
|
|
421
418
|
return;
|
|
422
419
|
}
|
|
423
420
|
if (lineNode.value.trim().length) {
|
|
@@ -464,7 +461,7 @@ module.exports = {
|
|
|
464
461
|
/**
|
|
465
462
|
* @param {AnyNodeOrLine | TemplateText | OpenTemplate | CloseTemplate} node
|
|
466
463
|
* @param {string} actualIndent
|
|
467
|
-
* @
|
|
464
|
+
* @returns {{ range: AST.Range; loc: AST.SourceLocation }}
|
|
468
465
|
*/
|
|
469
466
|
function getIndentNodeToReport(node, actualIndent) {
|
|
470
467
|
let rangeStart = node.range[0];
|
|
@@ -498,13 +495,11 @@ function countLeftPadding(str) {
|
|
|
498
495
|
|
|
499
496
|
/**
|
|
500
497
|
* @param {Context<any[]>} context
|
|
501
|
-
* @
|
|
498
|
+
* @returns {IndentOptionInfo}
|
|
502
499
|
*/
|
|
503
500
|
function getIndentOptionInfo(context) {
|
|
504
501
|
const options = context.options;
|
|
505
|
-
/**
|
|
506
|
-
* @type {IndentType['SPACE'] | IndentType['TAB']}
|
|
507
|
-
*/
|
|
502
|
+
/** @type {IndentType["SPACE"] | IndentType["TAB"]} */
|
|
508
503
|
let indentType = INDENT_TYPES.SPACE;
|
|
509
504
|
let indentSize = 4;
|
|
510
505
|
if (options.length) {
|
package/lib/rules/index.js
CHANGED
|
@@ -54,6 +54,8 @@ const noDuplicateInHead = require("./no-duplicate-in-head");
|
|
|
54
54
|
const noIneffectiveAttrs = require("./no-ineffective-attrs");
|
|
55
55
|
const noRestrictedTags = require("./no-restricted-tags");
|
|
56
56
|
const noWhitespaceOnlyChildren = require("./no-whitespace-only-children");
|
|
57
|
+
const noObsoleteAttrs = require("./no-obsolete-attrs");
|
|
58
|
+
const classSpacing = require("./class-spacing");
|
|
57
59
|
// import new rule here ↑
|
|
58
60
|
// DO NOT REMOVE THIS COMMENT
|
|
59
61
|
|
|
@@ -114,11 +116,13 @@ const rules = {
|
|
|
114
116
|
"no-ineffective-attrs": noIneffectiveAttrs,
|
|
115
117
|
"no-restricted-tags": noRestrictedTags,
|
|
116
118
|
"no-whitespace-only-children": noWhitespaceOnlyChildren,
|
|
119
|
+
"no-obsolete-attrs": noObsoleteAttrs,
|
|
120
|
+
"class-spacing": classSpacing,
|
|
117
121
|
// export new rule here ↑
|
|
118
122
|
// DO NOT REMOVE THIS COMMENT
|
|
119
123
|
};
|
|
120
124
|
|
|
121
125
|
module.exports =
|
|
122
|
-
/** @type {Record<string, import(
|
|
126
|
+
/** @type {Record<string, import("@eslint/core").RuleDefinition>} */ (
|
|
123
127
|
/** @type {unknown} */ (rules)
|
|
124
128
|
);
|
package/lib/rules/lowercase.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @import {
|
|
3
|
-
* Tag,
|
|
4
|
-
* StyleTag,
|
|
5
|
-
* ScriptTag,
|
|
6
3
|
* Doctype,
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* ScriptTag,
|
|
5
|
+
* StyleTag,
|
|
6
|
+
* Tag
|
|
7
|
+
* } from "@html-eslint/types"
|
|
8
|
+
* @import {RuleModule} from "../types"
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -18,9 +18,7 @@ const MESSAGE_IDS = {
|
|
|
18
18
|
UNEXPECTED: "unexpected",
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
/**
|
|
22
|
-
* @type {RuleModule<[]>}
|
|
23
|
-
*/
|
|
21
|
+
/** @type {RuleModule<[]>} */
|
|
24
22
|
module.exports = {
|
|
25
23
|
meta: {
|
|
26
24
|
type: "suggestion",
|
|
@@ -41,14 +39,10 @@ module.exports = {
|
|
|
41
39
|
|
|
42
40
|
create(context) {
|
|
43
41
|
const allowedAttrKeySet = new Set(SVG_CAMEL_CASE_ATTRIBUTES);
|
|
44
|
-
/**
|
|
45
|
-
* @type {Tag[]}
|
|
46
|
-
*/
|
|
42
|
+
/** @type {Tag[]} */
|
|
47
43
|
const svgStack = [];
|
|
48
44
|
|
|
49
|
-
/**
|
|
50
|
-
* @param {Tag} node
|
|
51
|
-
*/
|
|
45
|
+
/** @param {Tag} node */
|
|
52
46
|
function enterSvg(node) {
|
|
53
47
|
svgStack.push(node);
|
|
54
48
|
}
|
|
@@ -65,18 +59,14 @@ module.exports = {
|
|
|
65
59
|
return !!svgStack.length && allowedAttrKeySet.has(key);
|
|
66
60
|
}
|
|
67
61
|
|
|
68
|
-
/**
|
|
69
|
-
* @param {Tag | StyleTag | ScriptTag} node
|
|
70
|
-
*/
|
|
62
|
+
/** @param {Tag | StyleTag | ScriptTag} node */
|
|
71
63
|
function nameOf(node) {
|
|
72
64
|
if (isScript(node)) return "script";
|
|
73
65
|
if (isStyle(node)) return "style";
|
|
74
66
|
return node.name;
|
|
75
67
|
}
|
|
76
68
|
|
|
77
|
-
/**
|
|
78
|
-
* @param {Tag | StyleTag | ScriptTag} node
|
|
79
|
-
*/
|
|
69
|
+
/** @param {Tag | StyleTag | ScriptTag} node */
|
|
80
70
|
function check(node) {
|
|
81
71
|
const raw = node.openStart.value.slice(1);
|
|
82
72
|
const name = nameOf(node);
|
|
@@ -133,9 +123,7 @@ module.exports = {
|
|
|
133
123
|
}
|
|
134
124
|
}
|
|
135
125
|
|
|
136
|
-
/**
|
|
137
|
-
* @param {Doctype} doctype
|
|
138
|
-
*/
|
|
126
|
+
/** @param {Doctype} doctype */
|
|
139
127
|
function checkDoctype(doctype) {
|
|
140
128
|
if (doctype.open.value !== doctype.open.value.toLowerCase()) {
|
|
141
129
|
context.report({
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* ScriptTag,
|
|
4
|
+
* StyleTag,
|
|
5
|
+
* Tag
|
|
6
|
+
* } from "@html-eslint/types"
|
|
7
|
+
* @import {RuleModule} from "../types"
|
|
5
8
|
* @typedef {Object} Option
|
|
6
9
|
* @property {number} [Option.max]
|
|
7
10
|
*/
|
|
@@ -14,9 +17,7 @@ const MESSAGE_IDS = {
|
|
|
14
17
|
MAX_DEPTH_EXCEEDED: "maxDepthExceeded",
|
|
15
18
|
};
|
|
16
19
|
|
|
17
|
-
/**
|
|
18
|
-
* @type {RuleModule<[Option]>}
|
|
19
|
-
*/
|
|
20
|
+
/** @type {RuleModule<[Option]>} */
|
|
20
21
|
module.exports = {
|
|
21
22
|
meta: {
|
|
22
23
|
type: "code",
|
|
@@ -63,10 +64,7 @@ module.exports = {
|
|
|
63
64
|
depth = 0;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
/**
|
|
67
|
-
*
|
|
68
|
-
* @param {Tag | ScriptTag | StyleTag} node
|
|
69
|
-
*/
|
|
67
|
+
/** @param {Tag | ScriptTag | StyleTag} node */
|
|
70
68
|
function increaseDepth(node) {
|
|
71
69
|
depth++;
|
|
72
70
|
if (depth > maxDepth) {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* ScriptTag,
|
|
4
|
+
* StyleTag,
|
|
5
|
+
* Tag
|
|
6
|
+
* } from "@html-eslint/types"
|
|
7
|
+
* @import {RuleModule} from "../types"
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -27,9 +31,7 @@ const ABSTRACT_ROLE_SET = new Set([
|
|
|
27
31
|
"window",
|
|
28
32
|
]);
|
|
29
33
|
|
|
30
|
-
/**
|
|
31
|
-
* @type {RuleModule<[]>}
|
|
32
|
-
*/
|
|
34
|
+
/** @type {RuleModule<[]>} */
|
|
33
35
|
module.exports = {
|
|
34
36
|
meta: {
|
|
35
37
|
type: "code",
|
|
@@ -49,9 +51,7 @@ module.exports = {
|
|
|
49
51
|
},
|
|
50
52
|
|
|
51
53
|
create(context) {
|
|
52
|
-
/**
|
|
53
|
-
* @param {Tag | ScriptTag | StyleTag} node
|
|
54
|
-
*/
|
|
54
|
+
/** @param {Tag | ScriptTag | StyleTag} node */
|
|
55
55
|
function check(node) {
|
|
56
56
|
const roleAttr = findAttr(node, "role");
|
|
57
57
|
if (
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* ScriptTag,
|
|
4
|
+
* StyleTag,
|
|
5
|
+
* Tag
|
|
6
|
+
* } from "@html-eslint/types"
|
|
7
|
+
* @import {RuleModule} from "../types"
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -12,9 +16,7 @@ const MESSAGE_IDS = {
|
|
|
12
16
|
UNEXPECTED: "unexpected",
|
|
13
17
|
};
|
|
14
18
|
|
|
15
|
-
/**
|
|
16
|
-
* @type {RuleModule<[]>}
|
|
17
|
-
*/
|
|
19
|
+
/** @type {RuleModule<[]>} */
|
|
18
20
|
module.exports = {
|
|
19
21
|
meta: {
|
|
20
22
|
type: "code",
|
|
@@ -34,9 +36,7 @@ module.exports = {
|
|
|
34
36
|
},
|
|
35
37
|
|
|
36
38
|
create(context) {
|
|
37
|
-
/**
|
|
38
|
-
* @param {Tag | ScriptTag | StyleTag} node
|
|
39
|
-
*/
|
|
39
|
+
/** @param {Tag | ScriptTag | StyleTag} node */
|
|
40
40
|
function check(node) {
|
|
41
41
|
const accessKeyAttr = findAttr(node, "accesskey");
|
|
42
42
|
if (accessKeyAttr) {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {RuleModule} from "../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {RuleModule} from "../types" */
|
|
4
2
|
|
|
5
3
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
4
|
const { findAttr } = require("./utils/node");
|
|
@@ -11,9 +9,7 @@ const MESSAGE_IDS = {
|
|
|
11
9
|
UNEXPECTED: "unexpected",
|
|
12
10
|
};
|
|
13
11
|
|
|
14
|
-
/**
|
|
15
|
-
* @type {RuleModule<[]>}
|
|
16
|
-
*/
|
|
12
|
+
/** @type {RuleModule<[]>} */
|
|
17
13
|
module.exports = {
|
|
18
14
|
meta: {
|
|
19
15
|
type: "code",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {Tag} from "@html-eslint/types"
|
|
3
|
-
* @import {RuleModule} from "../types"
|
|
2
|
+
* @import {Tag} from "@html-eslint/types"
|
|
3
|
+
* @import {RuleModule} from "../types"
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -27,9 +27,7 @@ const FOCUSABLE_ELEMENTS = new Set([
|
|
|
27
27
|
"summary",
|
|
28
28
|
]);
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* @type {RuleModule<[]>}
|
|
32
|
-
*/
|
|
30
|
+
/** @type {RuleModule<[]>} */
|
|
33
31
|
module.exports = {
|
|
34
32
|
meta: {
|
|
35
33
|
type: "code",
|
|
@@ -52,6 +50,7 @@ module.exports = {
|
|
|
52
50
|
create(context) {
|
|
53
51
|
/**
|
|
54
52
|
* Checks if an element is focusable
|
|
53
|
+
*
|
|
55
54
|
* @param {Tag} node
|
|
56
55
|
* @returns {boolean}
|
|
57
56
|
*/
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* Attribute,
|
|
4
|
+
* ScriptTag,
|
|
5
|
+
* StyleTag,
|
|
6
|
+
* Tag
|
|
7
|
+
* } from "@html-eslint/types"
|
|
8
|
+
* @import {
|
|
9
|
+
* RuleModule,
|
|
10
|
+
* SuggestionReportDescriptor
|
|
11
|
+
* } from "../types"
|
|
4
12
|
*/
|
|
5
13
|
|
|
6
14
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -13,9 +21,7 @@ const MESSAGE_IDS = {
|
|
|
13
21
|
REMOVE_ATTR: "removeAttr",
|
|
14
22
|
};
|
|
15
23
|
|
|
16
|
-
/**
|
|
17
|
-
* @type {RuleModule<[]>}
|
|
18
|
-
*/
|
|
24
|
+
/** @type {RuleModule<[]>} */
|
|
19
25
|
module.exports = {
|
|
20
26
|
meta: {
|
|
21
27
|
type: "code",
|
|
@@ -55,9 +61,7 @@ module.exports = {
|
|
|
55
61
|
];
|
|
56
62
|
}
|
|
57
63
|
|
|
58
|
-
/**
|
|
59
|
-
* @param {Tag | StyleTag | ScriptTag} node
|
|
60
|
-
*/
|
|
64
|
+
/** @param {Tag | StyleTag | ScriptTag} node */
|
|
61
65
|
function check(node) {
|
|
62
66
|
if (Array.isArray(node.attributes)) {
|
|
63
67
|
const attrsSet = new Set();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {AttributeValue} from "@html-eslint/types"
|
|
3
|
-
* @import {RuleModule} from "../types"
|
|
2
|
+
* @import {AttributeValue} from "@html-eslint/types"
|
|
3
|
+
* @import {RuleModule} from "../types"
|
|
4
4
|
* @typedef {Object} ClassInfo
|
|
5
5
|
* @property {string} name
|
|
6
|
-
* @property {import("@html-eslint/types").AnyNode[
|
|
7
|
-
* @property {import("@html-eslint/types").AnyNode[
|
|
6
|
+
* @property {import("@html-eslint/types").AnyNode["loc"]} loc
|
|
7
|
+
* @property {import("@html-eslint/types").AnyNode["range"]} range
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const { NODE_TYPES } = require("@html-eslint/parser");
|
|
@@ -16,9 +16,7 @@ const MESSAGE_IDS = {
|
|
|
16
16
|
DUPLICATE_CLASS: "duplicateClass",
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
* @type {RuleModule<[]>}
|
|
21
|
-
*/
|
|
19
|
+
/** @type {RuleModule<[]>} */
|
|
22
20
|
module.exports = {
|
|
23
21
|
meta: {
|
|
24
22
|
type: "code",
|
|
@@ -38,17 +36,13 @@ module.exports = {
|
|
|
38
36
|
create(context) {
|
|
39
37
|
/**
|
|
40
38
|
* @param {AttributeValue} value
|
|
41
|
-
* @returns {{value: string
|
|
39
|
+
* @returns {{ value: string; pos: number }[]}
|
|
42
40
|
*/
|
|
43
41
|
function splitClassAndSpaces(value) {
|
|
44
|
-
/**
|
|
45
|
-
* @type {{value: string, pos: number}[]}
|
|
46
|
-
*/
|
|
42
|
+
/** @type {{ value: string; pos: number }[]} */
|
|
47
43
|
const result = [];
|
|
48
44
|
const regex = /(\s+|\S+)/g;
|
|
49
|
-
/**
|
|
50
|
-
* @type {RegExpExecArray | null}
|
|
51
|
-
*/
|
|
45
|
+
/** @type {RegExpExecArray | null} */
|
|
52
46
|
let match = null;
|
|
53
47
|
|
|
54
48
|
while ((match = regex.exec(value.value)) !== null) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AttributeValue,
|
|
4
|
+
* Tag
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
9
|
const { parseTemplateLiteral } = require("./utils/template-literal");
|
|
@@ -17,9 +20,7 @@ const MESSAGE_IDS = {
|
|
|
17
20
|
DUPLICATE_ID: "duplicateId",
|
|
18
21
|
};
|
|
19
22
|
|
|
20
|
-
/**
|
|
21
|
-
* @type {RuleModule<[]>}
|
|
22
|
-
*/
|
|
23
|
+
/** @type {RuleModule<[]>} */
|
|
23
24
|
module.exports = {
|
|
24
25
|
meta: {
|
|
25
26
|
type: "code",
|
|
@@ -40,13 +41,9 @@ module.exports = {
|
|
|
40
41
|
|
|
41
42
|
create(context) {
|
|
42
43
|
const htmlIdAttrsMap = new Map();
|
|
43
|
-
/**
|
|
44
|
-
* @param {Map<string, AttributeValue[]>} map
|
|
45
|
-
*/
|
|
44
|
+
/** @param {Map<string, AttributeValue[]>} map */
|
|
46
45
|
function createTagVisitor(map) {
|
|
47
|
-
/**
|
|
48
|
-
* @param {Tag} node
|
|
49
|
-
*/
|
|
46
|
+
/** @param {Tag} node */
|
|
50
47
|
return function (node) {
|
|
51
48
|
if (!node.attributes || node.attributes.length <= 0) {
|
|
52
49
|
return;
|
|
@@ -64,10 +61,7 @@ module.exports = {
|
|
|
64
61
|
};
|
|
65
62
|
}
|
|
66
63
|
|
|
67
|
-
/**
|
|
68
|
-
*
|
|
69
|
-
* @param {Map<string, AttributeValue[]>} map
|
|
70
|
-
*/
|
|
64
|
+
/** @param {Map<string, AttributeValue[]>} map */
|
|
71
65
|
function report(map) {
|
|
72
66
|
map.forEach((attrs) => {
|
|
73
67
|
if (Array.isArray(attrs) && attrs.length > 1) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {Tag} from "@html-eslint/types"
|
|
3
|
-
* @import {RuleModule} from "../types"
|
|
2
|
+
* @import {Tag} from "@html-eslint/types"
|
|
3
|
+
* @import {RuleModule} from "../types"
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { parseTemplateLiteral } = require("./utils/template-literal");
|
|
@@ -18,8 +18,9 @@ const MESSAGE_IDS = {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* Returns a formatted string representing a tag's key detail.
|
|
22
|
-
*
|
|
21
|
+
* Returns a formatted string representing a tag's key detail. E.g.,
|
|
22
|
+
* meta[charset=UTF-8], meta[name=viewport], link[rel=canonical]
|
|
23
|
+
*
|
|
23
24
|
* @param {Tag} node
|
|
24
25
|
* @returns {string | null}
|
|
25
26
|
*/
|
|
@@ -58,9 +59,7 @@ function getTrackingKey(node) {
|
|
|
58
59
|
return null;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
/**
|
|
62
|
-
* @type {RuleModule<[]>}
|
|
63
|
-
*/
|
|
62
|
+
/** @type {RuleModule<[]>} */
|
|
64
63
|
module.exports = {
|
|
65
64
|
meta: {
|
|
66
65
|
type: "code",
|
|
@@ -83,13 +82,11 @@ module.exports = {
|
|
|
83
82
|
|
|
84
83
|
/**
|
|
85
84
|
* @param {Map<string, Tag[]>} map
|
|
86
|
-
* @param {{count: number}|null} headCountRef
|
|
85
|
+
* @param {{ count: number } | null} headCountRef
|
|
87
86
|
*/
|
|
88
87
|
function createTagVisitor(map, headCountRef = null) {
|
|
89
88
|
return {
|
|
90
|
-
/**
|
|
91
|
-
* @param {Tag} node
|
|
92
|
-
*/
|
|
89
|
+
/** @param {Tag} node */
|
|
93
90
|
Tag(node) {
|
|
94
91
|
const tagName = node.name.toLowerCase();
|
|
95
92
|
|
|
@@ -119,9 +116,7 @@ module.exports = {
|
|
|
119
116
|
}
|
|
120
117
|
},
|
|
121
118
|
|
|
122
|
-
/**
|
|
123
|
-
* @param {Tag} node
|
|
124
|
-
*/
|
|
119
|
+
/** @param {Tag} node */
|
|
125
120
|
"Tag:exit"(node) {
|
|
126
121
|
const tagName = node.name.toLowerCase();
|
|
127
122
|
if (tagName === "head") {
|
|
@@ -135,9 +130,7 @@ module.exports = {
|
|
|
135
130
|
};
|
|
136
131
|
}
|
|
137
132
|
|
|
138
|
-
/**
|
|
139
|
-
* @param {Map<string, Tag[]>} map
|
|
140
|
-
*/
|
|
133
|
+
/** @param {Map<string, Tag[]>} map */
|
|
141
134
|
function report(map) {
|
|
142
135
|
map.forEach((tags, tagKey) => {
|
|
143
136
|
if (Array.isArray(tags) && tags.length > 1) {
|