@html-eslint/eslint-plugin 0.50.0 → 0.51.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/index.js
CHANGED
|
@@ -53,6 +53,7 @@ const noInvalidEntity = require("./no-invalid-entity");
|
|
|
53
53
|
const noDuplicateInHead = require("./no-duplicate-in-head");
|
|
54
54
|
const noIneffectiveAttrs = require("./no-ineffective-attrs");
|
|
55
55
|
const noRestrictedTags = require("./no-restricted-tags");
|
|
56
|
+
const noWhitespaceOnlyChildren = require("./no-whitespace-only-children");
|
|
56
57
|
// import new rule here ↑
|
|
57
58
|
// DO NOT REMOVE THIS COMMENT
|
|
58
59
|
|
|
@@ -112,6 +113,7 @@ const rules = {
|
|
|
112
113
|
"no-duplicate-in-head": noDuplicateInHead,
|
|
113
114
|
"no-ineffective-attrs": noIneffectiveAttrs,
|
|
114
115
|
"no-restricted-tags": noRestrictedTags,
|
|
116
|
+
"no-whitespace-only-children": noWhitespaceOnlyChildren,
|
|
115
117
|
// export new rule here ↑
|
|
116
118
|
// DO NOT REMOVE THIS COMMENT
|
|
117
119
|
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import {Tag, Text} from "@html-eslint/types";
|
|
3
|
+
* @import {RuleModule} from "../types";
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { RULE_CATEGORY } = require("../constants");
|
|
7
|
+
const { isText, isComment, getLocBetween } = require("./utils/node");
|
|
8
|
+
const { createVisitors } = require("./utils/visitors");
|
|
9
|
+
const { getRuleUrl } = require("./utils/rule");
|
|
10
|
+
|
|
11
|
+
const MESSAGE_IDS = {
|
|
12
|
+
WHITESPACE_ONLY_CHILDREN: "whitespaceOnlyChildren",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {Tag} node
|
|
17
|
+
*/
|
|
18
|
+
function hasOnlyWhitespaceChildren(node) {
|
|
19
|
+
if (!node.children || node.children.length === 0) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (node.children.every((child) => isComment(child))) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
for (const child of node.children) {
|
|
28
|
+
if (isComment(child)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (isText(child)) {
|
|
32
|
+
// Check if text contains any non-whitespace characters
|
|
33
|
+
if (child.value && child.value.trim().length > 0) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @type {RuleModule<[{tagPatterns?: string[]}]>}
|
|
46
|
+
*/
|
|
47
|
+
module.exports = {
|
|
48
|
+
meta: {
|
|
49
|
+
type: "code",
|
|
50
|
+
docs: {
|
|
51
|
+
description: "Disallow tags with only whitespace children.",
|
|
52
|
+
recommended: false,
|
|
53
|
+
category: RULE_CATEGORY.BEST_PRACTICE,
|
|
54
|
+
url: getRuleUrl("no-whitespace-only-children"),
|
|
55
|
+
},
|
|
56
|
+
fixable: "whitespace",
|
|
57
|
+
schema: [
|
|
58
|
+
{
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
tagPatterns: {
|
|
62
|
+
type: "array",
|
|
63
|
+
items: {
|
|
64
|
+
type: "string",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
additionalProperties: false,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
messages: {
|
|
72
|
+
[MESSAGE_IDS.WHITESPACE_ONLY_CHILDREN]:
|
|
73
|
+
"Tag should not have only whitespace children.",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
create(context) {
|
|
77
|
+
const options = context.options[0] || {};
|
|
78
|
+
const tagPatterns = (options.tagPatterns || []).map(
|
|
79
|
+
(pattern) => new RegExp(pattern, "u")
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return createVisitors(context, {
|
|
83
|
+
Tag(node) {
|
|
84
|
+
if (!node.close) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (tagPatterns.length <= 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const tagName = node.name.toLowerCase();
|
|
92
|
+
|
|
93
|
+
// If tagPatterns is specified, check if tag name matches any pattern
|
|
94
|
+
const matches = tagPatterns.some((pattern) => pattern.test(tagName));
|
|
95
|
+
if (!matches) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (hasOnlyWhitespaceChildren(node)) {
|
|
100
|
+
const loc = getLocBetween(node.openEnd, node.close);
|
|
101
|
+
context.report({
|
|
102
|
+
loc,
|
|
103
|
+
messageId: MESSAGE_IDS.WHITESPACE_ONLY_CHILDREN,
|
|
104
|
+
fix(fixer) {
|
|
105
|
+
return node.children
|
|
106
|
+
.filter((child) => isText(child))
|
|
107
|
+
.map((child) => fixer.removeRange(child.range));
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@html-eslint/eslint-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "ESLint plugin for HTML",
|
|
6
6
|
"author": "yeonjuan",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@eslint/plugin-kit": "^0.4.1",
|
|
43
|
-
"@html-eslint/parser": "^0.
|
|
44
|
-
"@html-eslint/template-parser": "^0.
|
|
45
|
-
"@html-eslint/template-syntax-parser": "^0.
|
|
46
|
-
"@html-eslint/types": "^0.
|
|
43
|
+
"@html-eslint/parser": "^0.51.0",
|
|
44
|
+
"@html-eslint/template-parser": "^0.51.0",
|
|
45
|
+
"@html-eslint/template-syntax-parser": "^0.51.0",
|
|
46
|
+
"@html-eslint/types": "^0.51.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"eslint": "^8.0.0 || ^9.0.0"
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"engines": {
|
|
60
60
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "fcf6a16bcd2d74ca1b3037d0729a30a852dff494"
|
|
63
63
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-whitespace-only-children.d.ts","sourceRoot":"","sources":["../../lib/rules/no-whitespace-only-children.js"],"names":[],"mappings":"wBA4CU,WAAW,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CAAC;;gCA1CnB,UAAU"}
|