eslint-plugin-vuejs-accessibility
Version:
An eslint plugin for checking Vue.js files for accessibility
92 lines (91 loc) • 3.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("../utils");
function isLabelElement(node, { labelComponents = [] }) {
const allLabelComponents = labelComponents.concat("label");
return (0, utils_1.isMatchingElement)(node, allLabelComponents);
}
function hasNestedLabelElement(node, options) {
const { parent } = node;
if (isLabelElement(parent, options)) {
return true;
}
return (parent &&
parent.type === "VElement" &&
hasNestedLabelElement(parent, options));
}
/**
* Check if the form control at least has an "id" to be associated with a label
* Can't really check for the label with a matching "for" attribute, because
* checking every element in the file may lead to bad performance.
*/
function hasIdForLabelElement(node) {
const id = (0, utils_1.getElementAttributeValue)(node, "id");
return Boolean(id);
}
const rule = {
meta: {
type: "problem",
docs: {
url: (0, utils_1.makeDocsURL)("form-control-has-label")
},
messages: {
default: "Each form element must have a programmatically associated label element."
},
schema: [
{
type: "object",
properties: {
labelComponents: {
type: "array",
items: {
type: "string"
},
uniqueItems: true
},
controlComponents: {
type: "array",
items: {
type: "string"
},
uniqueItems: true
}
}
}
]
},
create(context) {
return (0, utils_1.defineTemplateBodyVisitor)(context, {
VElement(node) {
const options = context.options[0] || {};
const controlComponents = [
"input",
"textarea",
"select",
"meter",
"output",
"progress",
...(options.controlComponents || [])
];
const elementType = (0, utils_1.getElementType)(node);
if (!controlComponents.includes(elementType)) {
return;
}
if (elementType === "input") {
const type = (0, utils_1.getElementAttributeValue)(node, "type");
const types = ["hidden", "button", "image", "submit", "reset"];
if (!type || types.includes(type)) {
return;
}
}
if (!(0, utils_1.isAriaHidden)(node) &&
!(0, utils_1.hasAriaLabel)(node) &&
!hasNestedLabelElement(node, options) &&
!hasIdForLabelElement(node)) {
context.report({ node, messageId: "default" });
}
}
});
}
};
exports.default = rule;