@html-eslint/eslint-plugin 0.28.0-alpha.0 → 0.28.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/lib/rules/attrs-newline.js +4 -5
- package/lib/rules/element-newline.js +22 -25
- package/lib/rules/id-naming-convention.js +63 -22
- package/lib/rules/indent.js +11 -4
- package/lib/rules/lowercase.js +4 -5
- package/lib/rules/no-abstract-roles.js +23 -19
- package/lib/rules/no-accesskey-attrs.js +18 -14
- package/lib/rules/no-aria-hidden-body.js +18 -12
- package/lib/rules/no-duplicate-attrs.js +27 -23
- package/lib/rules/no-duplicate-id.js +62 -21
- package/lib/rules/no-extra-spacing-attrs.js +104 -100
- package/lib/rules/no-extra-spacing-text.js +66 -26
- package/lib/rules/no-inline-styles.js +3 -25
- package/lib/rules/no-multiple-empty-lines.js +94 -42
- package/lib/rules/no-multiple-h1.js +1 -1
- package/lib/rules/no-obsolete-tags.js +3 -2
- package/lib/rules/no-positive-tabindex.js +24 -18
- package/lib/rules/no-restricted-attr-values.js +51 -47
- package/lib/rules/no-restricted-attrs.js +50 -45
- package/lib/rules/no-script-style-type.js +3 -2
- package/lib/rules/no-skip-heading-levels.js +1 -1
- package/lib/rules/no-target-blank.js +7 -2
- package/lib/rules/no-trailing-spaces.js +95 -39
- package/lib/rules/quotes.js +12 -8
- package/lib/rules/require-attrs.js +28 -20
- package/lib/rules/require-button-type.js +7 -3
- package/lib/rules/require-closing-tags.js +3 -2
- package/lib/rules/require-frame-title.js +3 -2
- package/lib/rules/require-img-alt.js +3 -2
- package/lib/rules/require-lang.js +3 -2
- package/lib/rules/require-li-container.js +1 -1
- package/lib/rules/require-meta-charset.js +5 -9
- package/lib/rules/require-meta-description.js +5 -5
- package/lib/rules/require-meta-viewport.js +5 -5
- package/lib/rules/require-open-graph-protocol.js +5 -5
- package/lib/rules/require-title.js +8 -7
- package/lib/rules/sort-attrs.js +5 -3
- package/lib/rules/utils/node.js +226 -68
- package/lib/rules/utils/visitors.js +52 -0
- package/lib/types.d.ts +15 -19
- package/package.json +9 -6
- package/types/configs/recommended.d.ts +1 -1
- package/types/constants/rule-category.d.ts +4 -4
- package/types/index.d.ts.map +1 -1
- package/types/rules/attrs-newline.d.ts +7 -4
- package/types/rules/attrs-newline.d.ts.map +1 -1
- package/types/rules/element-newline.d.ts +13 -11
- package/types/rules/element-newline.d.ts.map +1 -1
- package/types/rules/id-naming-convention.d.ts +7 -4
- package/types/rules/id-naming-convention.d.ts.map +1 -1
- package/types/rules/indent.d.ts +10 -7
- package/types/rules/indent.d.ts.map +1 -1
- package/types/rules/lowercase.d.ts +8 -4
- package/types/rules/lowercase.d.ts.map +1 -1
- package/types/rules/no-abstract-roles.d.ts +7 -4
- package/types/rules/no-abstract-roles.d.ts.map +1 -1
- package/types/rules/no-accesskey-attrs.d.ts +7 -4
- package/types/rules/no-accesskey-attrs.d.ts.map +1 -1
- package/types/rules/no-aria-hidden-body.d.ts +4 -1
- package/types/rules/no-aria-hidden-body.d.ts.map +1 -1
- package/types/rules/no-duplicate-attrs.d.ts +7 -4
- package/types/rules/no-duplicate-attrs.d.ts.map +1 -1
- package/types/rules/no-duplicate-id.d.ts +8 -4
- package/types/rules/no-duplicate-id.d.ts.map +1 -1
- package/types/rules/no-extra-spacing-attrs.d.ts +15 -12
- package/types/rules/no-extra-spacing-attrs.d.ts.map +1 -1
- package/types/rules/no-extra-spacing-text.d.ts +11 -5
- package/types/rules/no-extra-spacing-text.d.ts.map +1 -1
- package/types/rules/no-inline-styles.d.ts +5 -2
- package/types/rules/no-inline-styles.d.ts.map +1 -1
- package/types/rules/no-multiple-empty-lines.d.ts +8 -2
- package/types/rules/no-multiple-empty-lines.d.ts.map +1 -1
- package/types/rules/no-multiple-h1.d.ts +5 -2
- package/types/rules/no-multiple-h1.d.ts.map +1 -1
- package/types/rules/no-non-scalable-viewport.d.ts +4 -1
- package/types/rules/no-non-scalable-viewport.d.ts.map +1 -1
- package/types/rules/no-obsolete-tags.d.ts +4 -1
- package/types/rules/no-obsolete-tags.d.ts.map +1 -1
- package/types/rules/no-positive-tabindex.d.ts +7 -4
- package/types/rules/no-positive-tabindex.d.ts.map +1 -1
- package/types/rules/no-restricted-attr-values.d.ts +9 -6
- package/types/rules/no-restricted-attr-values.d.ts.map +1 -1
- package/types/rules/no-restricted-attrs.d.ts +9 -6
- package/types/rules/no-restricted-attrs.d.ts.map +1 -1
- package/types/rules/no-script-style-type.d.ts +7 -4
- package/types/rules/no-script-style-type.d.ts.map +1 -1
- package/types/rules/no-skip-heading-levels.d.ts +5 -2
- package/types/rules/no-skip-heading-levels.d.ts.map +1 -1
- package/types/rules/no-target-blank.d.ts +4 -1
- package/types/rules/no-target-blank.d.ts.map +1 -1
- package/types/rules/no-trailing-spaces.d.ts +6 -1
- package/types/rules/no-trailing-spaces.d.ts.map +1 -1
- package/types/rules/quotes.d.ts +9 -6
- package/types/rules/quotes.d.ts.map +1 -1
- package/types/rules/require-attrs.d.ts +7 -4
- package/types/rules/require-attrs.d.ts.map +1 -1
- package/types/rules/require-button-type.d.ts +4 -1
- package/types/rules/require-button-type.d.ts.map +1 -1
- package/types/rules/require-closing-tags.d.ts +5 -2
- package/types/rules/require-closing-tags.d.ts.map +1 -1
- package/types/rules/require-doctype.d.ts +4 -1
- package/types/rules/require-doctype.d.ts.map +1 -1
- package/types/rules/require-frame-title.d.ts +4 -1
- package/types/rules/require-frame-title.d.ts.map +1 -1
- package/types/rules/require-img-alt.d.ts +5 -2
- package/types/rules/require-img-alt.d.ts.map +1 -1
- package/types/rules/require-lang.d.ts +4 -1
- package/types/rules/require-lang.d.ts.map +1 -1
- package/types/rules/require-li-container.d.ts +4 -1
- package/types/rules/require-li-container.d.ts.map +1 -1
- package/types/rules/require-meta-charset.d.ts +6 -2
- package/types/rules/require-meta-charset.d.ts.map +1 -1
- package/types/rules/require-meta-description.d.ts +6 -2
- package/types/rules/require-meta-description.d.ts.map +1 -1
- package/types/rules/require-meta-viewport.d.ts +6 -2
- package/types/rules/require-meta-viewport.d.ts.map +1 -1
- package/types/rules/require-open-graph-protocol.d.ts +6 -2
- package/types/rules/require-open-graph-protocol.d.ts.map +1 -1
- package/types/rules/require-title.d.ts +7 -3
- package/types/rules/require-title.d.ts.map +1 -1
- package/types/rules/sort-attrs.d.ts +7 -4
- package/types/rules/sort-attrs.d.ts.map +1 -1
- package/types/rules/utils/array.d.ts.map +1 -1
- package/types/rules/utils/naming.d.ts.map +1 -1
- package/types/rules/utils/node.d.ts +65 -12
- package/types/rules/utils/node.d.ts.map +1 -1
- package/types/rules/utils/visitors.d.ts +10 -0
- package/types/rules/utils/visitors.d.ts.map +1 -0
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const { RULE_CATEGORY } = require("../constants");
|
|
11
|
+
const { createVisitors } = require("./utils/visitors");
|
|
11
12
|
|
|
12
13
|
const MESSAGE_IDS = {
|
|
13
14
|
RESTRICTED: "restricted",
|
|
@@ -64,54 +65,57 @@ module.exports = {
|
|
|
64
65
|
*/
|
|
65
66
|
const options = context.options;
|
|
66
67
|
const checkers = options.map((option) => new PatternChecker(option));
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
...result,
|
|
110
|
-
data: { attrValuePatterns: attr.value.value },
|
|
111
|
-
});
|
|
68
|
+
/**
|
|
69
|
+
* @param {TagNode | StyleTagNode | ScriptTagNode} node
|
|
70
|
+
*/
|
|
71
|
+
function check(node) {
|
|
72
|
+
node.attributes.forEach((attr) => {
|
|
73
|
+
if (
|
|
74
|
+
!attr.key ||
|
|
75
|
+
!attr.key.value ||
|
|
76
|
+
!attr.value ||
|
|
77
|
+
typeof attr.value.value !== "string"
|
|
78
|
+
) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const matched = checkers.find(
|
|
83
|
+
(checker) =>
|
|
84
|
+
attr.value && checker.test(attr.key.value, attr.value.value)
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
if (!matched) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @type {{node: AttributeNode, message: string, messageId?: string}}
|
|
93
|
+
*/
|
|
94
|
+
const result = {
|
|
95
|
+
node: attr,
|
|
96
|
+
message: "",
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const customMessage = matched.getMessage();
|
|
100
|
+
|
|
101
|
+
if (customMessage) {
|
|
102
|
+
result.message = customMessage;
|
|
103
|
+
} else {
|
|
104
|
+
result.messageId = MESSAGE_IDS.RESTRICTED;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
context.report({
|
|
108
|
+
...result,
|
|
109
|
+
data: { attrValuePatterns: attr.value.value },
|
|
112
110
|
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return createVisitors(context, {
|
|
115
|
+
Tag: check,
|
|
116
|
+
StyleTag: check,
|
|
117
|
+
ScriptTag: check,
|
|
118
|
+
});
|
|
115
119
|
},
|
|
116
120
|
};
|
|
117
121
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
const { NODE_TYPES } = require("@html-eslint/parser");
|
|
11
11
|
const { RULE_CATEGORY } = require("../constants");
|
|
12
|
+
const { createVisitors } = require("./utils/visitors");
|
|
12
13
|
|
|
13
14
|
const MESSAGE_IDS = {
|
|
14
15
|
RESTRICTED: "restricted",
|
|
@@ -65,52 +66,56 @@ module.exports = {
|
|
|
65
66
|
const options = context.options;
|
|
66
67
|
const checkers = options.map((option) => new PatternChecker(option));
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
node.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
data: { attr: attr.key.value },
|
|
110
|
-
});
|
|
69
|
+
/**
|
|
70
|
+
* @param {TagNode | StyleTagNode | ScriptTagNode} node
|
|
71
|
+
*/
|
|
72
|
+
function check(node) {
|
|
73
|
+
const tagName =
|
|
74
|
+
node.type === NODE_TYPES.Tag
|
|
75
|
+
? node.name
|
|
76
|
+
: node.type === NODE_TYPES.ScriptTag
|
|
77
|
+
? "script"
|
|
78
|
+
: "style";
|
|
79
|
+
node.attributes.forEach((attr) => {
|
|
80
|
+
if (!attr.key || !attr.key.value) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const matched = checkers.find((checker) =>
|
|
84
|
+
checker.test(tagName, attr.key.value)
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
if (!matched) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @type {{node: AttributeNode, message: string, messageId?: string}}
|
|
93
|
+
*/
|
|
94
|
+
const result = {
|
|
95
|
+
node: attr,
|
|
96
|
+
message: "",
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const customMessage = matched.getMessage();
|
|
100
|
+
|
|
101
|
+
if (customMessage) {
|
|
102
|
+
result.message = customMessage;
|
|
103
|
+
} else {
|
|
104
|
+
result.messageId = MESSAGE_IDS.RESTRICTED;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
context.report({
|
|
108
|
+
...result,
|
|
109
|
+
data: { attr: attr.key.value },
|
|
111
110
|
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return createVisitors(context, {
|
|
115
|
+
Tag: check,
|
|
116
|
+
StyleTag: check,
|
|
117
|
+
ScriptTag: check,
|
|
118
|
+
});
|
|
114
119
|
},
|
|
115
120
|
};
|
|
116
121
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const { RULE_CATEGORY } = require("../constants");
|
|
9
9
|
const { findAttr } = require("./utils/node");
|
|
10
|
+
const { createVisitors } = require("./utils/visitors");
|
|
10
11
|
|
|
11
12
|
const MESSAGE_IDS = {
|
|
12
13
|
UNNECESSARY: "unnecessary",
|
|
@@ -56,7 +57,7 @@ module.exports = {
|
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
return {
|
|
60
|
+
return createVisitors(context, {
|
|
60
61
|
ScriptTag(node) {
|
|
61
62
|
check(node, "text/javascript");
|
|
62
63
|
},
|
|
@@ -71,6 +72,6 @@ module.exports = {
|
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
},
|
|
74
|
-
};
|
|
75
|
+
});
|
|
75
76
|
},
|
|
76
77
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
6
|
const { findAttr } = require("./utils/node");
|
|
7
|
+
const { createVisitors } = require("./utils/visitors");
|
|
7
8
|
|
|
8
9
|
const MESSAGE_IDS = {
|
|
9
10
|
MISSING: "missing",
|
|
@@ -38,7 +39,7 @@ module.exports = {
|
|
|
38
39
|
function isExternalLink(link) {
|
|
39
40
|
return /^(?:\w+:|\/\/)/.test(link);
|
|
40
41
|
}
|
|
41
|
-
return {
|
|
42
|
+
return createVisitors(context, {
|
|
42
43
|
Tag(node) {
|
|
43
44
|
if (node.name !== "a") {
|
|
44
45
|
return;
|
|
@@ -49,6 +50,10 @@ module.exports = {
|
|
|
49
50
|
const href = findAttr(node, "href");
|
|
50
51
|
if (href && href.value && isExternalLink(href.value.value)) {
|
|
51
52
|
const rel = findAttr(node, "rel");
|
|
53
|
+
if (rel && rel.value && rel.value.templates.length) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
52
57
|
if (!rel || !rel.value || !rel.value.value.includes("noreferrer")) {
|
|
53
58
|
context.report({
|
|
54
59
|
node: target,
|
|
@@ -58,6 +63,6 @@ module.exports = {
|
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
65
|
},
|
|
61
|
-
};
|
|
66
|
+
});
|
|
62
67
|
},
|
|
63
68
|
};
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @typedef { import("../types").RuleModule } RuleModule
|
|
3
|
+
* @typedef { import("es-html-parser").CommentContentNode } CommentContentNode
|
|
4
|
+
* @typedef { import("es-html-parser").TextNode } TextNode
|
|
3
5
|
*/
|
|
4
6
|
|
|
7
|
+
const { parse } = require("@html-eslint/template-parser");
|
|
5
8
|
const { RULE_CATEGORY } = require("../constants");
|
|
9
|
+
const {
|
|
10
|
+
getTemplateTokens,
|
|
11
|
+
codeToLines,
|
|
12
|
+
isRangesOverlap,
|
|
13
|
+
} = require("./utils/node");
|
|
14
|
+
const {
|
|
15
|
+
shouldCheckTaggedTemplateExpression,
|
|
16
|
+
shouldCheckTemplateLiteral,
|
|
17
|
+
} = require("./utils/settings");
|
|
18
|
+
const { getSourceCode } = require("./utils/source-code");
|
|
6
19
|
|
|
7
20
|
const MESSAGE_IDS = {
|
|
8
21
|
TRAILING_SPACE: "trailingSpace",
|
|
@@ -27,48 +40,91 @@ module.exports = {
|
|
|
27
40
|
},
|
|
28
41
|
|
|
29
42
|
create(context) {
|
|
30
|
-
const sourceCode =
|
|
31
|
-
|
|
43
|
+
const sourceCode = getSourceCode(context);
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} source
|
|
46
|
+
* @param {string[]} lines
|
|
47
|
+
* @param {number} rangeOffset
|
|
48
|
+
* @param {((CommentContentNode | TextNode)['templates'][number])[]} tokens
|
|
49
|
+
*/
|
|
50
|
+
function check(source, lines, rangeOffset, tokens) {
|
|
51
|
+
let rangeIndex = rangeOffset;
|
|
52
|
+
const lineBreaks = source.match(/\r\n|[\r\n\u2028\u2029]/gu);
|
|
53
|
+
lines.forEach((line, index) => {
|
|
54
|
+
const lineNumber = index + 1;
|
|
55
|
+
const match = line.match(/[ \t\u00a0\u2000-\u200b\u3000]+$/);
|
|
56
|
+
const lineBreakLength =
|
|
57
|
+
lineBreaks && lineBreaks[index] ? lineBreaks[index].length : 1;
|
|
58
|
+
const lineLength = line.length + lineBreakLength;
|
|
32
59
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
},
|
|
52
|
-
end: {
|
|
53
|
-
line: lineNumber,
|
|
54
|
-
column: lineLength - lineBreakLength,
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
context.report({
|
|
59
|
-
messageId: MESSAGE_IDS.TRAILING_SPACE,
|
|
60
|
-
loc,
|
|
61
|
-
fix(fixer) {
|
|
62
|
-
return fixer.removeRange([
|
|
63
|
-
rangeIndex + loc.start.column,
|
|
64
|
-
rangeIndex + loc.end.column,
|
|
65
|
-
]);
|
|
66
|
-
},
|
|
67
|
-
});
|
|
60
|
+
if (match) {
|
|
61
|
+
if (typeof match.index === "number" && match.index > 0) {
|
|
62
|
+
const loc = {
|
|
63
|
+
start: {
|
|
64
|
+
line: lineNumber,
|
|
65
|
+
column: match.index,
|
|
66
|
+
},
|
|
67
|
+
end: {
|
|
68
|
+
line: lineNumber,
|
|
69
|
+
column: lineLength - lineBreakLength,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
const start = sourceCode.getIndexFromLoc(loc.start);
|
|
73
|
+
const end = sourceCode.getIndexFromLoc(loc.end);
|
|
74
|
+
if (
|
|
75
|
+
tokens.some((token) => isRangesOverlap(token.range, [start, end]))
|
|
76
|
+
) {
|
|
77
|
+
return;
|
|
68
78
|
}
|
|
79
|
+
context.report({
|
|
80
|
+
messageId: MESSAGE_IDS.TRAILING_SPACE,
|
|
81
|
+
loc,
|
|
82
|
+
fix(fixer) {
|
|
83
|
+
return fixer.removeRange([
|
|
84
|
+
rangeIndex + loc.start.column,
|
|
85
|
+
rangeIndex + loc.end.column,
|
|
86
|
+
]);
|
|
87
|
+
},
|
|
88
|
+
});
|
|
69
89
|
}
|
|
70
|
-
|
|
71
|
-
|
|
90
|
+
}
|
|
91
|
+
rangeIndex += lineLength;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
Document() {
|
|
97
|
+
check(sourceCode.getText(), sourceCode.getLines(), 0, []);
|
|
98
|
+
},
|
|
99
|
+
TaggedTemplateExpression(node) {
|
|
100
|
+
if (shouldCheckTaggedTemplateExpression(node, context)) {
|
|
101
|
+
const { html, tokens } = parse(
|
|
102
|
+
node.quasi,
|
|
103
|
+
getSourceCode(context),
|
|
104
|
+
{}
|
|
105
|
+
);
|
|
106
|
+
const lines = codeToLines(html);
|
|
107
|
+
check(
|
|
108
|
+
html,
|
|
109
|
+
lines,
|
|
110
|
+
// @ts-ignore
|
|
111
|
+
node.quasi.range[0] + 1,
|
|
112
|
+
getTemplateTokens(tokens)
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
TemplateLiteral(node) {
|
|
117
|
+
if (shouldCheckTemplateLiteral(node, context)) {
|
|
118
|
+
const { html, tokens } = parse(node, getSourceCode(context), {});
|
|
119
|
+
const lines = codeToLines(html);
|
|
120
|
+
check(
|
|
121
|
+
html,
|
|
122
|
+
lines,
|
|
123
|
+
// @ts-ignore
|
|
124
|
+
node.range[0] + 1,
|
|
125
|
+
getTemplateTokens(tokens)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
72
128
|
},
|
|
73
129
|
};
|
|
74
130
|
},
|
package/lib/rules/quotes.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
const { RULE_CATEGORY } = require("../constants");
|
|
11
|
+
const { createVisitors } = require("./utils/visitors");
|
|
11
12
|
|
|
12
13
|
const MESSAGE_IDS = {
|
|
13
14
|
UNEXPECTED: "unexpected",
|
|
@@ -131,14 +132,17 @@ module.exports = {
|
|
|
131
132
|
});
|
|
132
133
|
}
|
|
133
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* @param {TagNode | ScriptTagNode | StyleTagNode} node
|
|
137
|
+
*/
|
|
138
|
+
function check(node) {
|
|
139
|
+
node.attributes.forEach((attr) => checkQuotes(attr));
|
|
140
|
+
}
|
|
134
141
|
|
|
135
|
-
return {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
node.attributes.forEach((attr) => checkQuotes(attr));
|
|
141
|
-
},
|
|
142
|
-
};
|
|
142
|
+
return createVisitors(context, {
|
|
143
|
+
Tag: check,
|
|
144
|
+
ScriptTag: check,
|
|
145
|
+
StyleTag: check,
|
|
146
|
+
});
|
|
143
147
|
},
|
|
144
148
|
};
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const { NODE_TYPES } = require("@html-eslint/parser");
|
|
9
9
|
const { RULE_CATEGORY } = require("../constants");
|
|
10
|
+
const { createVisitors } = require("./utils/visitors");
|
|
10
11
|
|
|
11
12
|
const MESSAGE_IDS = {
|
|
12
13
|
MISSING: "missing",
|
|
@@ -103,25 +104,32 @@ module.exports = {
|
|
|
103
104
|
});
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
107
|
+
/**
|
|
108
|
+
* @param {StyleTagNode | ScriptTagNode} node
|
|
109
|
+
*/
|
|
110
|
+
function checkStyleOrScript(node) {
|
|
111
|
+
const tagName = node.type === NODE_TYPES.StyleTag ? "style" : "script";
|
|
112
|
+
if (!tagOptionsMap.has(tagName)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
check(node, tagName);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {TagNode} node
|
|
120
|
+
*/
|
|
121
|
+
function checkTag(node) {
|
|
122
|
+
const tagName = node.name.toLowerCase();
|
|
123
|
+
if (!tagOptionsMap.has(tagName)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
check(node, tagName);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return createVisitors(context, {
|
|
130
|
+
StyleTag: checkStyleOrScript,
|
|
131
|
+
ScriptTag: checkStyleOrScript,
|
|
132
|
+
Tag: checkTag,
|
|
133
|
+
});
|
|
126
134
|
},
|
|
127
135
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
6
|
const { findAttr } = require("./utils/node");
|
|
7
|
+
const { createVisitors } = require("./utils/visitors");
|
|
7
8
|
|
|
8
9
|
const MESSAGE_IDS = {
|
|
9
10
|
MISSING: "missing",
|
|
@@ -35,7 +36,7 @@ module.exports = {
|
|
|
35
36
|
},
|
|
36
37
|
|
|
37
38
|
create(context) {
|
|
38
|
-
return {
|
|
39
|
+
return createVisitors(context, {
|
|
39
40
|
Tag(node) {
|
|
40
41
|
if (node.name !== "button") {
|
|
41
42
|
return;
|
|
@@ -46,7 +47,10 @@ module.exports = {
|
|
|
46
47
|
node: node.openStart,
|
|
47
48
|
messageId: MESSAGE_IDS.MISSING,
|
|
48
49
|
});
|
|
49
|
-
} else if (
|
|
50
|
+
} else if (
|
|
51
|
+
!VALID_BUTTON_TYPES_SET.has(typeAttr.value.value) &&
|
|
52
|
+
!typeAttr.value.templates.length
|
|
53
|
+
) {
|
|
50
54
|
context.report({
|
|
51
55
|
node: typeAttr,
|
|
52
56
|
messageId: MESSAGE_IDS.INVALID,
|
|
@@ -56,6 +60,6 @@ module.exports = {
|
|
|
56
60
|
});
|
|
57
61
|
}
|
|
58
62
|
},
|
|
59
|
-
};
|
|
63
|
+
});
|
|
60
64
|
},
|
|
61
65
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { RULE_CATEGORY, VOID_ELEMENTS } = require("../constants");
|
|
7
|
+
const { createVisitors } = require("./utils/visitors");
|
|
7
8
|
|
|
8
9
|
const VOID_ELEMENTS_SET = new Set(VOID_ELEMENTS);
|
|
9
10
|
|
|
@@ -125,7 +126,7 @@ module.exports = {
|
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
return {
|
|
129
|
+
return createVisitors(context, {
|
|
129
130
|
Tag(node) {
|
|
130
131
|
const isVoidElement = VOID_ELEMENTS_SET.has(node.name);
|
|
131
132
|
const isSelfClosingCustomElement = !!selfClosingCustomPatterns.some(
|
|
@@ -156,6 +157,6 @@ module.exports = {
|
|
|
156
157
|
foreignContext.pop();
|
|
157
158
|
}
|
|
158
159
|
},
|
|
159
|
-
};
|
|
160
|
+
});
|
|
160
161
|
},
|
|
161
162
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
6
|
const { findAttr } = require("./utils/node");
|
|
7
|
+
const { createVisitors } = require("./utils/visitors");
|
|
7
8
|
|
|
8
9
|
const MESSAGE_IDS = {
|
|
9
10
|
MISSING: "missing",
|
|
@@ -32,7 +33,7 @@ module.exports = {
|
|
|
32
33
|
},
|
|
33
34
|
|
|
34
35
|
create(context) {
|
|
35
|
-
return {
|
|
36
|
+
return createVisitors(context, {
|
|
36
37
|
Tag(node) {
|
|
37
38
|
if (node.name !== "frame" && node.name !== "iframe") {
|
|
38
39
|
return;
|
|
@@ -51,6 +52,6 @@ module.exports = {
|
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
},
|
|
54
|
-
};
|
|
55
|
+
});
|
|
55
56
|
},
|
|
56
57
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { RULE_CATEGORY } = require("../constants");
|
|
7
|
+
const { createVisitors } = require("./utils/visitors");
|
|
7
8
|
|
|
8
9
|
const MESSAGE_IDS = {
|
|
9
10
|
MISSING_ALT: "missingAlt",
|
|
@@ -48,7 +49,7 @@ module.exports = {
|
|
|
48
49
|
context.options[0].substitute) ||
|
|
49
50
|
[];
|
|
50
51
|
|
|
51
|
-
return {
|
|
52
|
+
return createVisitors(context, {
|
|
52
53
|
Tag(node) {
|
|
53
54
|
if (node.name !== "img") {
|
|
54
55
|
return;
|
|
@@ -66,7 +67,7 @@ module.exports = {
|
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
69
|
},
|
|
69
|
-
};
|
|
70
|
+
});
|
|
70
71
|
},
|
|
71
72
|
};
|
|
72
73
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { RULE_CATEGORY } = require("../constants");
|
|
6
6
|
const { findAttr } = require("./utils/node");
|
|
7
|
+
const { createVisitors } = require("./utils/visitors");
|
|
7
8
|
|
|
8
9
|
const MESSAGE_IDS = {
|
|
9
10
|
MISSING: "missing",
|
|
@@ -32,7 +33,7 @@ module.exports = {
|
|
|
32
33
|
},
|
|
33
34
|
|
|
34
35
|
create(context) {
|
|
35
|
-
return {
|
|
36
|
+
return createVisitors(context, {
|
|
36
37
|
Tag(node) {
|
|
37
38
|
if (node.name !== "html") {
|
|
38
39
|
return;
|
|
@@ -56,6 +57,6 @@ module.exports = {
|
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
},
|
|
59
|
-
};
|
|
60
|
+
});
|
|
60
61
|
},
|
|
61
62
|
};
|