UNPKG

eslint-plugin-svelte

Version:
111 lines (110 loc) 3.74 kB
import { createRule } from '../utils/index.js'; import { findAttribute, findShorthandAttribute, findBindDirective, getStaticAttributeValue } from '../utils/ast-utils.js'; export default createRule('button-has-type', { meta: { docs: { description: 'disallow usage of button without an explicit type attribute', category: 'Best Practices', recommended: false }, schema: [ { type: 'object', properties: { button: { type: 'boolean' }, submit: { type: 'boolean' }, reset: { type: 'boolean' } }, additionalProperties: false } ], messages: { missingTypeAttribute: 'Missing an explicit type attribute for button.', invalidTypeAttribute: '{{value}} is an invalid value for button type attribute.', forbiddenTypeAttribute: '{{value}} is a forbidden value for button type attribute.', emptyTypeAttribute: 'A value must be set for button type attribute.' }, type: 'suggestion' // "problem", }, create(context) { const configuration = { button: true, submit: true, reset: true, ...(context.options[0] ?? {}) }; /** * Checks whether given text is known button type */ function isButtonType(type) { return type === 'button' || type === 'submit' || type === 'reset'; } /** * Report */ function report(node, messageId, data = {}) { context.report({ node, messageId, data }); } /** * Validate attribute */ function validateAttribute(attribute) { if (attribute.value.length === 0) { report(attribute, 'emptyTypeAttribute'); return; } const strValue = getStaticAttributeValue(attribute); if (strValue == null) { return; } if (!isButtonType(strValue)) { report(attribute, 'invalidTypeAttribute', { value: strValue }); } else if (!configuration[strValue]) { report(attribute, 'forbiddenTypeAttribute', { value: strValue }); } } /** * @param {VDirective} directive */ function validateDirective(directive) { if (!directive.expression) { report(directive, 'emptyTypeAttribute'); } } return { "SvelteElement[name.name='button'] > SvelteStartTag"(node) { const typeAttr = findAttribute(node, 'type'); if (typeAttr) { validateAttribute(typeAttr); return; } const typeDir = findBindDirective(node, 'type'); if (typeDir) { validateDirective(typeDir); return; } const typeShortAttr = findShorthandAttribute(node, 'type'); if (typeShortAttr) { return; } for (const attr of node.attributes) { if (attr.type === 'SvelteSpreadAttribute') { return; } } report(node, 'missingTypeAttribute'); } }; } });