@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.
@@ -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.50.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.50.0",
44
- "@html-eslint/template-parser": "^0.50.0",
45
- "@html-eslint/template-syntax-parser": "^0.50.0",
46
- "@html-eslint/types": "^0.50.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": "68100e43c5da0e3edb3d288f428a18d729d981d3"
62
+ "gitHead": "fcf6a16bcd2d74ca1b3037d0729a30a852dff494"
63
63
  }
@@ -0,0 +1,6 @@
1
+ declare const _exports: RuleModule<[{
2
+ tagPatterns?: string[];
3
+ }]>;
4
+ export = _exports;
5
+ import type { RuleModule } from "../types";
6
+ //# sourceMappingURL=no-whitespace-only-children.d.ts.map
@@ -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"}