diff --git a/docs/rules.md b/docs/rules.md
index 068f62d2..faf6c911 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -14,6 +14,7 @@
| [no-duplicate-class](rules/no-duplicate-class) | Disallow duplicate class names | 🔧 |
| [no-duplicate-id](rules/no-duplicate-id) | Disallow duplicate id attributes | ⭐ |
| [no-duplicate-in-head](rules/no-duplicate-in-head) | Disallow duplicate tags in `
` | |
+| [no-ineffective-attrs](rules/no-ineffective-attrs) | Disallow HTML attributes that have no effect in their context | |
| [no-inline-styles](rules/no-inline-styles) | Disallow using inline style | |
| [no-invalid-entity](rules/no-invalid-entity) | Disallows the use of invalid HTML entities | |
| [no-nested-interactive](rules/no-nested-interactive) | Disallows nested interactive elements | |
diff --git a/docs/rules/require-attrs.md b/docs/rules/require-attrs.md
index bb1bbb4c..b1b43eb2 100644
--- a/docs/rules/require-attrs.md
+++ b/docs/rules/require-attrs.md
@@ -22,7 +22,7 @@ module.exports = {
### Options
-This rule takes an array of objects which has tag name with attribute name.
+This rule takes an array of option objects:
```js
module.exports = {
@@ -31,38 +31,83 @@ module.exports = {
"error",
{
tag: "img",
- attr: "alt", // Enforce to use img with alt attribute.
+ attr: "alt",
},
{
tag: "svg",
- attr: "viewBox" // Enforce to use svg and viewBox attributes with "0 0 100 100" value.
- value: "0 0 100 100"
+ attr: "viewBox",
+ value: "0 0 100 100",
},
],
},
};
```
-Examples of **incorrect** code for this rule with the option below:
-
-```json
-{
- "tag": "img",
- "attr": "alt"
-},
-{
- "tag": "svg",
- "attr": "viewBox",
- "value": "0 0 100 100"
-}
+#### tag
+
+- Type: `string`
+- **Required**
+
+The HTML tag name to check for the specified attribute.
+
+#### attr
+
+- Type: `string`
+- **Required**
+
+The attribute name that must be present on the specified tag.
+
+#### value
+
+- Type: `string`
+- _Optional_
+
+The expected value for the attribute. If specified, the attribute must have this exact value.
+
+#### message
+
+- Type: `string`
+- _Optional_
+
+Custom error message to display when the rule is violated. If not provided, a default message will be used.
+
+```js
+module.exports = {
+ rules: {
+ "@html-eslint/require-attrs": [
+ "error",
+ {
+ tag: "img",
+ attr: "alt",
+ message: "Images must have alternative text for accessibility",
+ },
+ ],
+ },
+};
```
-```html,incorrect
-
+Examples of **incorrect** code for this rule:
+
+```html
+
+
+
+
+
+
+
+
```
-Examples of **correct** code for this rule with the option above:
+Examples of **correct** code for this rule:
+
+```html
+
+
+
+
+
-```html,correct
-
+
+
```
diff --git a/packages/eslint-plugin/lib/rules/require-attrs.js b/packages/eslint-plugin/lib/rules/require-attrs.js
index 914bc003..cab47fc3 100644
--- a/packages/eslint-plugin/lib/rules/require-attrs.js
+++ b/packages/eslint-plugin/lib/rules/require-attrs.js
@@ -6,6 +6,7 @@
* @property {string} tag
* @property {string} attr
* @property {string} [value]
+ * @property {string} [message]
*
*/
@@ -41,6 +42,7 @@ module.exports = {
tag: { type: "string" },
attr: { type: "string" },
value: { type: "string" },
+ message: { type: "string" },
},
required: ["tag", "attr"],
additionalProperties: false,
@@ -59,7 +61,7 @@ module.exports = {
*/
const options = context.options || [];
/**
- * @type {Map}
+ * @type {Map}
*/
const tagOptionsMap = new Map();
@@ -90,7 +92,9 @@ module.exports = {
);
if (!attr) {
context.report({
- messageId: MESSAGE_IDS.MISSING,
+ ...(option.message
+ ? { message: option.message }
+ : { messageId: MESSAGE_IDS.MISSING }),
node,
data: {
attr: attrName,
@@ -111,7 +115,9 @@ module.exports = {
(!attr.value || attr.value.value !== option.value)
) {
context.report({
- messageId: MESSAGE_IDS.UNEXPECTED,
+ ...(option.message
+ ? { message: option.message }
+ : { messageId: MESSAGE_IDS.UNEXPECTED }),
node: attr,
data: {
attr: attrName,
diff --git a/packages/eslint-plugin/tests/rules/require-attrs.test.js b/packages/eslint-plugin/tests/rules/require-attrs.test.js
index 568bc232..e2e9c406 100644
--- a/packages/eslint-plugin/tests/rules/require-attrs.test.js
+++ b/packages/eslint-plugin/tests/rules/require-attrs.test.js
@@ -310,6 +310,44 @@ ruleTester.run("require-attrs", rule, {
},
],
},
+ // Test custom message option
+ {
+ code: `
`,
+ options: [
+ {
+ tag: "img",
+ attr: "alt",
+ message: "Image must have alt text for accessibility",
+ },
+ ],
+ errors: [
+ {
+ line: 1,
+ column: 1,
+ message: "Image must have alt text for accessibility",
+ },
+ ],
+ },
+ {
+ code: ``,
+ options: [
+ {
+ tag: "svg",
+ attr: "viewBox",
+ value: "0 0 100 100",
+ message: "SVG viewBox must be '0 0 100 100'",
+ },
+ ],
+ output: ``,
+ errors: [
+ {
+ line: 1,
+ column: 6,
+ endColumn: 21,
+ message: "SVG viewBox must be '0 0 100 100'",
+ },
+ ],
+ },
],
});
@@ -354,5 +392,23 @@ templateRuleTester.run("[template] require-attrs", rule, {
},
],
},
+ // Test custom message option in template
+ {
+ code: "html``",
+ options: [
+ {
+ tag: "div",
+ attr: "role",
+ message: "Div elements should have a role attribute",
+ },
+ ],
+ errors: [
+ {
+ line: 1,
+ column: 6,
+ message: "Div elements should have a role attribute",
+ },
+ ],
+ },
],
});