@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,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
* @import {
|
|
2
|
+
* @import {Tag} from "@html-eslint/types"
|
|
3
|
+
* @import {RuleModule} from "../types"
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -16,9 +16,7 @@ const INPUT_TAGS = new Set(["input", "textarea", "select"]);
|
|
|
16
16
|
|
|
17
17
|
const LABEL_ATTRIBUTES = new Set(["id", "aria-labelledby", "aria-label"]);
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
* @type {RuleModule<[]>}
|
|
21
|
-
*/
|
|
19
|
+
/** @type {RuleModule<[]>} */
|
|
22
20
|
module.exports = {
|
|
23
21
|
meta: {
|
|
24
22
|
type: "code",
|
|
@@ -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");
|
|
@@ -12,9 +10,7 @@ const MESSAGE_IDS = {
|
|
|
12
10
|
EMPTY: "empty",
|
|
13
11
|
};
|
|
14
12
|
|
|
15
|
-
/**
|
|
16
|
-
* @type {RuleModule<[]>}
|
|
17
|
-
*/
|
|
13
|
+
/** @type {RuleModule<[]>} */
|
|
18
14
|
module.exports = {
|
|
19
15
|
meta: {
|
|
20
16
|
type: "code",
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {RuleModule} from "../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {RuleModule} from "../types" */
|
|
4
2
|
|
|
5
3
|
const { NODE_TYPES } = require("@html-eslint/parser");
|
|
6
4
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -12,9 +10,7 @@ const MESSAGE_IDS = {
|
|
|
12
10
|
|
|
13
11
|
const VALID_CONTAINERS = ["ul", "ol", "menu"];
|
|
14
12
|
|
|
15
|
-
/**
|
|
16
|
-
* @type {RuleModule<[]>}
|
|
17
|
-
*/
|
|
13
|
+
/** @type {RuleModule<[]>} */
|
|
18
14
|
module.exports = {
|
|
19
15
|
meta: {
|
|
20
16
|
type: "code",
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* Tag
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
9
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -21,9 +24,7 @@ function isMetaCharset(node) {
|
|
|
21
24
|
return isTag(node) && node.name === "meta" && !!findAttr(node, "charset");
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
/**
|
|
25
|
-
* @type {RuleModule<[]>}
|
|
26
|
-
*/
|
|
27
|
+
/** @type {RuleModule<[]>} */
|
|
27
28
|
module.exports = {
|
|
28
29
|
meta: {
|
|
29
30
|
type: "code",
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* Tag
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
4
7
|
*/
|
|
5
8
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
9
|
const { filter } = require("./utils/array");
|
|
@@ -20,9 +23,7 @@ function isMetaTagNode(node) {
|
|
|
20
23
|
return isTag(node) && node.name === "meta";
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
/**
|
|
24
|
-
* @type {RuleModule<[]>}
|
|
25
|
-
*/
|
|
26
|
+
/** @type {RuleModule<[]>} */
|
|
26
27
|
module.exports = {
|
|
27
28
|
meta: {
|
|
28
29
|
type: "code",
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* Tag
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
9
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -29,9 +32,7 @@ function isMetaViewport(node) {
|
|
|
29
32
|
return false;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
/**
|
|
33
|
-
* @type {RuleModule<[]>}
|
|
34
|
-
*/
|
|
35
|
+
/** @type {RuleModule<[]>} */
|
|
35
36
|
module.exports = {
|
|
36
37
|
meta: {
|
|
37
38
|
type: "code",
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* Tag
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {RuleModule} from "../types"
|
|
4
7
|
* @typedef {string[]} Option
|
|
5
8
|
*/
|
|
6
9
|
|
|
@@ -32,9 +35,7 @@ function normalize(properties) {
|
|
|
32
35
|
});
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
/**
|
|
36
|
-
* @type {RuleModule<[Option]>}
|
|
37
|
-
*/
|
|
38
|
+
/** @type {RuleModule<[Option]>} */
|
|
38
39
|
module.exports = {
|
|
39
40
|
meta: {
|
|
40
41
|
type: "code",
|
|
@@ -65,9 +66,7 @@ module.exports = {
|
|
|
65
66
|
},
|
|
66
67
|
|
|
67
68
|
create(context) {
|
|
68
|
-
/**
|
|
69
|
-
* @type {string[]}
|
|
70
|
-
*/
|
|
69
|
+
/** @type {string[]} */
|
|
71
70
|
const requiredProperties = normalize(
|
|
72
71
|
(context.options && context.options[0]) || DEFAULT_REQUIRED_PROPERTIES
|
|
73
72
|
);
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* Tag,
|
|
5
|
+
* Text
|
|
6
|
+
* } from "@html-eslint/types"
|
|
7
|
+
* @import {RuleModule} from "../types"
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
const { RULE_CATEGORY } = require("../constants");
|
|
@@ -29,9 +33,7 @@ function isNonEmptyText(node) {
|
|
|
29
33
|
return isText(node) && node.value.trim().length > 0;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
/**
|
|
33
|
-
* @type {RuleModule<[]>}
|
|
34
|
-
*/
|
|
36
|
+
/** @type {RuleModule<[]>} */
|
|
35
37
|
module.exports = {
|
|
36
38
|
meta: {
|
|
37
39
|
type: "code",
|
package/lib/rules/sort-attrs.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {Attribute} from "@html-eslint/types"
|
|
3
|
-
* @import {
|
|
4
|
-
*
|
|
2
|
+
* @import {Attribute} from "@html-eslint/types"
|
|
3
|
+
* @import {
|
|
4
|
+
* RuleFixer,
|
|
5
|
+
* RuleModule
|
|
6
|
+
* } from "../types"
|
|
5
7
|
* @typedef {Object} Option
|
|
6
|
-
* @property {
|
|
8
|
+
* @property {(string | { pattern: string })[]} [Option.priority]
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
const { hasTemplate } = require("./utils/node");
|
|
@@ -16,9 +18,7 @@ const MESSAGE_IDS = {
|
|
|
16
18
|
UNSORTED: "unsorted",
|
|
17
19
|
};
|
|
18
20
|
|
|
19
|
-
/**
|
|
20
|
-
* @type {RuleModule<[Option]>}
|
|
21
|
-
*/
|
|
21
|
+
/** @type {RuleModule<[Option]>} */
|
|
22
22
|
module.exports = {
|
|
23
23
|
meta: {
|
|
24
24
|
type: "code",
|
|
@@ -69,9 +69,7 @@ module.exports = {
|
|
|
69
69
|
const option = context.options[0] || {
|
|
70
70
|
priority: ["id", "type", "class", "style"],
|
|
71
71
|
};
|
|
72
|
-
/**
|
|
73
|
-
* @type {Array<string | {pattern: string, regex: RegExp}>}
|
|
74
|
-
*/
|
|
72
|
+
/** @type {(string | { pattern: string; regex: RegExp })[]} */
|
|
75
73
|
const priority = (option.priority || []).map((item) => {
|
|
76
74
|
if (item && typeof item === "object" && "pattern" in item) {
|
|
77
75
|
return {
|
|
@@ -84,7 +82,7 @@ module.exports = {
|
|
|
84
82
|
|
|
85
83
|
/**
|
|
86
84
|
* @param {string} attrName
|
|
87
|
-
* @param {string | {pattern: string
|
|
85
|
+
* @param {string | { pattern: string; regex: RegExp }} priorityItem
|
|
88
86
|
* @returns {boolean}
|
|
89
87
|
*/
|
|
90
88
|
function matchesPriority(attrName, priorityItem) {
|
|
@@ -117,7 +115,7 @@ module.exports = {
|
|
|
117
115
|
/**
|
|
118
116
|
* @param {Attribute} attrA
|
|
119
117
|
* @param {Attribute} attrB
|
|
120
|
-
* @
|
|
118
|
+
* @returns {number}
|
|
121
119
|
*/
|
|
122
120
|
function compare(attrA, attrB) {
|
|
123
121
|
const keyA = attrA.key.value;
|
|
@@ -185,12 +183,10 @@ module.exports = {
|
|
|
185
183
|
|
|
186
184
|
/**
|
|
187
185
|
* @param {Attribute[]} attributes
|
|
188
|
-
* @
|
|
186
|
+
* @returns {Attribute[][]}
|
|
189
187
|
*/
|
|
190
188
|
function groupAttributes(attributes) {
|
|
191
|
-
/**
|
|
192
|
-
* @type {Attribute[][]}
|
|
193
|
-
*/
|
|
189
|
+
/** @type {Attribute[][]} */
|
|
194
190
|
const attributesList = [];
|
|
195
191
|
let index = 0;
|
|
196
192
|
|
|
@@ -207,9 +203,7 @@ module.exports = {
|
|
|
207
203
|
return attributesList;
|
|
208
204
|
}
|
|
209
205
|
|
|
210
|
-
/**
|
|
211
|
-
* @param {Attribute[]} unsorted
|
|
212
|
-
*/
|
|
206
|
+
/** @param {Attribute[]} unsorted */
|
|
213
207
|
function checkSorting(unsorted) {
|
|
214
208
|
if (unsorted.length <= 1) {
|
|
215
209
|
return;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* Attribute,
|
|
4
|
+
* ScriptTag,
|
|
5
|
+
* StyleTag,
|
|
6
|
+
* Tag
|
|
7
|
+
* } from "@html-eslint/types"
|
|
8
|
+
* @import {RuleModule} from "../types"
|
|
4
9
|
* @typedef {Object} Option
|
|
5
10
|
* @property {"widely" | "newly" | number} Option.available
|
|
6
11
|
*/
|
|
@@ -21,9 +26,7 @@ const MESSAGE_IDS = {
|
|
|
21
26
|
NOT_BASELINE_GLOBAL_ATTRIBUTE: "notBaselineGlobalAttribute",
|
|
22
27
|
};
|
|
23
28
|
|
|
24
|
-
/**
|
|
25
|
-
* @type {RuleModule<[Option]>}
|
|
26
|
-
*/
|
|
29
|
+
/** @type {RuleModule<[Option]>} */
|
|
27
30
|
module.exports = {
|
|
28
31
|
meta: {
|
|
29
32
|
type: "code",
|
|
@@ -178,7 +181,6 @@ module.exports = {
|
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
/**
|
|
181
|
-
*
|
|
182
184
|
* @param {string} element
|
|
183
185
|
* @param {string} key
|
|
184
186
|
* @param {string} value
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is auto-generated. (yarn run baseline)
|
|
3
|
-
*/
|
|
1
|
+
/** This file is auto-generated. (yarn run baseline) */
|
|
4
2
|
const BASELINE_HIGH = 10;
|
|
5
3
|
const BASELINE_LOW = 5;
|
|
6
4
|
const BASELINE_FALSE = 0;
|
|
@@ -70,9 +68,9 @@ const elements = new Map([
|
|
|
70
68
|
["body", "10:2015"],
|
|
71
69
|
["br", "10:2015"],
|
|
72
70
|
["button", "10:2015"],
|
|
73
|
-
["button.command", "
|
|
74
|
-
["button.command.request-close", "
|
|
75
|
-
["button.commandfor", "
|
|
71
|
+
["button.command", "5:2025"],
|
|
72
|
+
["button.command.request-close", "5:2025"],
|
|
73
|
+
["button.commandfor", "5:2025"],
|
|
76
74
|
["button.disabled", "10:2015"],
|
|
77
75
|
["button.form", "10:2017"],
|
|
78
76
|
["button.formaction", "10:2015"],
|
|
@@ -7,8 +7,10 @@ const CAMEL_CASE_REGEX = /^[a-z][a-zA-Z0-9]+$/;
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
/**
|
|
9
9
|
* Checks a given name follows `kebab-case` or not.
|
|
10
|
-
*
|
|
11
|
-
* @
|
|
10
|
+
*
|
|
11
|
+
* @param {string} name Name to check
|
|
12
|
+
* @returns {boolean} `true` if a name follows `kebab-case`, otherwise
|
|
13
|
+
* `false`.
|
|
12
14
|
*/
|
|
13
15
|
isKebabCase(name) {
|
|
14
16
|
return KEBAB_CASE_REGEX.test(name);
|
|
@@ -16,8 +18,10 @@ module.exports = {
|
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Checks a given name follows `snake_case` or not.
|
|
19
|
-
*
|
|
20
|
-
* @
|
|
21
|
+
*
|
|
22
|
+
* @param {string} name Name to check
|
|
23
|
+
* @returns {boolean} `true` if a name follows `snake_case`, otherwise
|
|
24
|
+
* `false`.
|
|
21
25
|
*/
|
|
22
26
|
isSnakeCase(name) {
|
|
23
27
|
return SNAKE_CASE_REGEX.test(name);
|
|
@@ -25,8 +29,10 @@ module.exports = {
|
|
|
25
29
|
|
|
26
30
|
/**
|
|
27
31
|
* Checks a given name follows `PascalCase` or not.
|
|
28
|
-
*
|
|
29
|
-
* @
|
|
32
|
+
*
|
|
33
|
+
* @param {string} name Name to check
|
|
34
|
+
* @returns {boolean} `true` if a name follows `PascalCase`, otherwise
|
|
35
|
+
* `false`.
|
|
30
36
|
*/
|
|
31
37
|
isPascalCase(name) {
|
|
32
38
|
return PASCAL_CASE_REGEX.test(name);
|
|
@@ -34,7 +40,8 @@ module.exports = {
|
|
|
34
40
|
|
|
35
41
|
/**
|
|
36
42
|
* Checks a given name follows `camelCase` or not.
|
|
37
|
-
*
|
|
43
|
+
*
|
|
44
|
+
* @param {string} name Name to check
|
|
38
45
|
* @returns {boolean} `true` if a name follows `camelCase`, otherwise `false`.
|
|
39
46
|
*/
|
|
40
47
|
isCamelCase(name) {
|
package/lib/rules/utils/node.js
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* AnyNode,
|
|
4
|
+
* AnyToken,
|
|
5
|
+
* Attribute,
|
|
6
|
+
* AttributeKey,
|
|
7
|
+
* AttributeValue,
|
|
8
|
+
* CloseTemplate,
|
|
9
|
+
* Comment,
|
|
10
|
+
* CommentContent,
|
|
11
|
+
* OpenTemplate,
|
|
12
|
+
* ScriptTag,
|
|
13
|
+
* StyleTag,
|
|
14
|
+
* Tag,
|
|
15
|
+
* Text
|
|
16
|
+
* } from "@html-eslint/types"
|
|
17
|
+
* @import {AST} from "eslint"
|
|
18
|
+
* @import {
|
|
19
|
+
* BaseNode,
|
|
20
|
+
* Line
|
|
21
|
+
* } from "../../types"
|
|
5
22
|
*/
|
|
6
23
|
|
|
7
24
|
const { NODE_TYPES } = require("@html-eslint/parser");
|
|
@@ -30,6 +47,7 @@ function hasAttr(node, attrName) {
|
|
|
30
47
|
|
|
31
48
|
/**
|
|
32
49
|
* Checks whether a node's attributes is empty or not.
|
|
50
|
+
*
|
|
33
51
|
* @param {Tag | ScriptTag | StyleTag} node
|
|
34
52
|
* @returns {boolean}
|
|
35
53
|
*/
|
|
@@ -39,15 +57,16 @@ function isAttributesEmpty(node) {
|
|
|
39
57
|
|
|
40
58
|
/**
|
|
41
59
|
* Checks whether a node's all tokens are on the same line or not.
|
|
60
|
+
*
|
|
42
61
|
* @param {AnyNode} node A node to check
|
|
43
|
-
* @returns {boolean} `true` if a node's tokens are on the same line, otherwise
|
|
62
|
+
* @returns {boolean} `true` if a node's tokens are on the same line, otherwise
|
|
63
|
+
* `false`.
|
|
44
64
|
*/
|
|
45
65
|
function isNodeTokensOnSameLine(node) {
|
|
46
66
|
return node.loc.start.line === node.loc.end.line;
|
|
47
67
|
}
|
|
48
68
|
|
|
49
69
|
/**
|
|
50
|
-
*
|
|
51
70
|
* @param {AST.Range} rangeA
|
|
52
71
|
* @param {AST.Range} rangeB
|
|
53
72
|
* @returns {boolean}
|
|
@@ -57,7 +76,7 @@ function isRangesOverlap(rangeA, rangeB) {
|
|
|
57
76
|
}
|
|
58
77
|
|
|
59
78
|
/**
|
|
60
|
-
* @param {(Text | CommentContent)[
|
|
79
|
+
* @param {(Text | CommentContent)["parts"]} parts
|
|
61
80
|
* @param {AST.Range} range
|
|
62
81
|
* @returns {boolean}
|
|
63
82
|
*/
|
|
@@ -76,7 +95,6 @@ function hasTemplate(node) {
|
|
|
76
95
|
}
|
|
77
96
|
|
|
78
97
|
/**
|
|
79
|
-
*
|
|
80
98
|
* @param {Text | CommentContent} node
|
|
81
99
|
* @returns {Line[]}
|
|
82
100
|
*/
|
|
@@ -84,27 +102,45 @@ function splitToLineNodes(node) {
|
|
|
84
102
|
let start = node.range[0];
|
|
85
103
|
let line = node.loc.start.line;
|
|
86
104
|
const startCol = node.loc.start.column;
|
|
87
|
-
/**
|
|
88
|
-
* @type {Line[]}
|
|
89
|
-
*/
|
|
105
|
+
/** @type {Line[]} */
|
|
90
106
|
const lineNodes = [];
|
|
91
107
|
const parts = node.parts || [];
|
|
108
|
+
|
|
92
109
|
/**
|
|
93
|
-
*
|
|
94
110
|
* @param {AST.Range} range
|
|
111
|
+
* @returns {{
|
|
112
|
+
* isOverlapTemplate: boolean;
|
|
113
|
+
* hasOpenTemplate: boolean;
|
|
114
|
+
* hasCloseTemplate: boolean;
|
|
115
|
+
* }}
|
|
95
116
|
*/
|
|
96
|
-
function
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
)
|
|
117
|
+
function getTemplateInfo(range) {
|
|
118
|
+
let isOverlapTemplate = false;
|
|
119
|
+
let hasOpenTemplate = false;
|
|
120
|
+
let hasCloseTemplate = false;
|
|
121
|
+
for (const part of parts) {
|
|
122
|
+
if (part.type === NODE_TYPES.Template) {
|
|
123
|
+
if (isRangesOverlap(part.range, range)) {
|
|
124
|
+
isOverlapTemplate = true;
|
|
125
|
+
}
|
|
126
|
+
if (part.open && isRangesOverlap(part.open.range, range)) {
|
|
127
|
+
hasOpenTemplate = true;
|
|
128
|
+
}
|
|
129
|
+
if (part.close && isRangesOverlap(part.close.range, range)) {
|
|
130
|
+
hasCloseTemplate = true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
isOverlapTemplate,
|
|
136
|
+
hasCloseTemplate,
|
|
137
|
+
hasOpenTemplate,
|
|
138
|
+
};
|
|
101
139
|
}
|
|
102
140
|
|
|
103
141
|
node.value.split("\n").forEach((value, index) => {
|
|
104
142
|
const columnStart = index === 0 ? startCol : 0;
|
|
105
|
-
/**
|
|
106
|
-
* @type {AST.Range}
|
|
107
|
-
*/
|
|
143
|
+
/** @type {AST.Range} */
|
|
108
144
|
const range = [start, start + value.length];
|
|
109
145
|
const loc = {
|
|
110
146
|
start: {
|
|
@@ -116,15 +152,13 @@ function splitToLineNodes(node) {
|
|
|
116
152
|
column: columnStart + value.length,
|
|
117
153
|
},
|
|
118
154
|
};
|
|
119
|
-
/**
|
|
120
|
-
* @type {Line}
|
|
121
|
-
*/
|
|
155
|
+
/** @type {Line} */
|
|
122
156
|
const lineNode = {
|
|
123
157
|
type: "Line",
|
|
124
158
|
value,
|
|
125
159
|
range,
|
|
126
160
|
loc,
|
|
127
|
-
|
|
161
|
+
...getTemplateInfo(range),
|
|
128
162
|
};
|
|
129
163
|
|
|
130
164
|
start += value.length + 1;
|
|
@@ -138,9 +172,10 @@ function splitToLineNodes(node) {
|
|
|
138
172
|
|
|
139
173
|
/**
|
|
140
174
|
* Get location between two nodes.
|
|
141
|
-
*
|
|
142
|
-
* @param {{loc: AST.SourceLocation}}
|
|
143
|
-
* @
|
|
175
|
+
*
|
|
176
|
+
* @param {{ loc: AST.SourceLocation }} before A node placed in before
|
|
177
|
+
* @param {{ loc: AST.SourceLocation }} after A node placed in after
|
|
178
|
+
* @returns {AST.SourceLocation} Location between two nodes.
|
|
144
179
|
*/
|
|
145
180
|
function getLocBetween(before, after) {
|
|
146
181
|
return {
|
|
@@ -230,9 +265,8 @@ function findParent(node, predicate) {
|
|
|
230
265
|
}
|
|
231
266
|
|
|
232
267
|
/**
|
|
233
|
-
*
|
|
234
268
|
* @param {AnyToken[]} tokens
|
|
235
|
-
* @returns {(
|
|
269
|
+
* @returns {(CommentContent | Text)["parts"][number][]}
|
|
236
270
|
*/
|
|
237
271
|
function getTemplateTokens(tokens) {
|
|
238
272
|
return (
|
|
@@ -258,7 +292,7 @@ function getNameOf(node) {
|
|
|
258
292
|
if (isStyle(node)) {
|
|
259
293
|
return "style";
|
|
260
294
|
}
|
|
261
|
-
return node.name;
|
|
295
|
+
return node.name.toLowerCase();
|
|
262
296
|
}
|
|
263
297
|
|
|
264
298
|
module.exports = {
|
package/lib/rules/utils/rule.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
3
|
-
*
|
|
2
|
+
* @import {
|
|
3
|
+
* TaggedTemplateExpression,
|
|
4
|
+
* TemplateLiteral
|
|
5
|
+
* } from "@html-eslint/types"
|
|
6
|
+
* @import {
|
|
7
|
+
* Context,
|
|
8
|
+
* HTMLSettings,
|
|
9
|
+
* MaybeHTMLSettings
|
|
10
|
+
* } from "../../types"
|
|
4
11
|
*/
|
|
5
12
|
|
|
6
13
|
const { getSourceCode } = require("../utils/source-code");
|
|
@@ -54,7 +61,6 @@ function shouldCheckTaggedTemplateExpression(node, context) {
|
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
/**
|
|
57
|
-
*
|
|
58
64
|
* @param {TemplateLiteral} node
|
|
59
65
|
* @param {Context<any[]>} context
|
|
60
66
|
* @returns {boolean}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @import {Context} from "../../types";
|
|
3
|
-
*/
|
|
1
|
+
/** @import {Context} from "../../types" */
|
|
4
2
|
|
|
5
|
-
/**
|
|
6
|
-
* @param {Context<any[]>} context
|
|
7
|
-
*/
|
|
3
|
+
/** @param {Context<any[]>} context */
|
|
8
4
|
function getSourceCode(context) {
|
|
9
5
|
return context.sourceCode || context.getSourceCode();
|
|
10
6
|
}
|
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {TemplateLiteral} from "@html-eslint/types";
|
|
3
|
-
* @import {DocumentNode, AnyToken} from "es-html-parser";
|
|
4
|
-
* @import {SourceCode} from "eslint";
|
|
5
2
|
* @import {TemplateHTMLVisitor} from "@html-eslint/template-parser"
|
|
3
|
+
* @import {TemplateLiteral} from "@html-eslint/types"
|
|
4
|
+
* @import {
|
|
5
|
+
* AnyToken,
|
|
6
|
+
* DocumentNode
|
|
7
|
+
* } from "es-html-parser"
|
|
8
|
+
* @import {SourceCode} from "eslint"
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
11
|
const { parse, traverse } = require("@html-eslint/template-parser");
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
|
-
* Cache for parsed template literals to avoid re-parsing the same template
|
|
12
|
-
* Uses WeakMap for automatic garbage collection when nodes are
|
|
13
|
-
*
|
|
14
|
+
* Cache for parsed template literals to avoid re-parsing the same template
|
|
15
|
+
* multiple times. Uses WeakMap for automatic garbage collection when nodes are
|
|
16
|
+
* no longer referenced.
|
|
17
|
+
*
|
|
18
|
+
* @type {WeakMap<
|
|
19
|
+
* TemplateLiteral,
|
|
20
|
+
* { ast: any; html: string; tokens: any[] }
|
|
21
|
+
* >}
|
|
14
22
|
*/
|
|
15
23
|
const templateCache = new WeakMap();
|
|
16
24
|
|
|
17
25
|
/**
|
|
18
26
|
* Get or create cached parse result for a template literal.
|
|
27
|
+
*
|
|
19
28
|
* @param {TemplateLiteral} node
|
|
20
29
|
* @param {SourceCode} sourceCode
|
|
21
30
|
* @param {TemplateHTMLVisitor} [visitor]
|
|
22
|
-
* @returns {{ast: DocumentNode
|
|
31
|
+
* @returns {{ ast: DocumentNode; html: string; tokens: AnyToken[] }}
|
|
23
32
|
*/
|
|
24
33
|
function parseTemplateLiteral(node, sourceCode, visitor) {
|
|
25
34
|
// Check if we already have a cached result for this node
|