UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

142 lines (139 loc) 6.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _eslintCodemodUtils = require("eslint-codemod-utils"); var _jsxElementHelper = require("../../ast-nodes/jsx-element-helper"); var _createLintRule = require("../utils/create-lint-rule"); var _getAffectedPackageConfig = require("../utils/get-affected-package-config"); var _affectedAtlaskitPackages = require("./affected-atlaskit-packages"); var _affectedHtmlElements = require("./affected-html-elements"); var _unwantedAtlaskitAttributes = require("./unwanted-atlaskit-attributes"); var _unwantedHtmlAttributes = require("./unwanted-html-attributes"); var isUnwantedHTMLAtrribute = function isUnwantedHTMLAtrribute(s) { var attrs = _unwantedHtmlAttributes.UNWANTED_HTML_ATTRIBUTES; return attrs.includes(s); }; var isUnwantedAtlaskitAtrribute = function isUnwantedAtlaskitAtrribute(s) { var attrs = _unwantedAtlaskitAttributes.UNWANTED_ATLASKIT_ATTRIBUTES; return attrs.includes(s); }; var isUnwantedAttribute = function isUnwantedAttribute(s) { return isUnwantedHTMLAtrribute(s) || isUnwantedAtlaskitAtrribute(s); }; var hasUnwantedAttributes = function hasUnwantedAttributes(node, type) { var attrNames = (0, _toConsumableArray2.default)(type === 'html' ? _unwantedHtmlAttributes.UNWANTED_HTML_ATTRIBUTES : _unwantedAtlaskitAttributes.UNWANTED_ATLASKIT_ATTRIBUTES); var unwantedAttrs = node.openingElement.attributes.filter(function (attr) { return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute'); }).map(function (attr) { return String(attr.name.name); }).filter(isUnwantedAttribute).filter(function (unwantedAttribute) { return attrNames.includes(unwantedAttribute); }); return unwantedAttrs; }; var rule = (0, _createLintRule.createLintRule)({ meta: { name: 'no-readonly-or-disabled-inputs', type: 'problem', docs: { description: 'Inputs should almost always be interactive. Disabled and read-only inputs can usually be replaced by a more user-friendly design pattern.', recommended: true, severity: 'warn' }, messages: { noDisabled: 'Inputs should almost always be interactive. Instead of disabling an input, consider removing it altogether, as it cannot be used anyway. Disabled inputs are much less accessible than a well labeled and described input with clear error, valid, and/or helper messages.', noReadOnly: 'Inputs should almost always be interactive. Instead of making an input read-only, consider making it normal text. Read-only inputs do the same thing as normal text but appear as interactive elements and add themselves to the tab-order, which can be confusing for users.' } }, create: function create(context) { var localComponentNames = []; return { ImportDeclaration: function ImportDeclaration(node) { var source = node.source.value; var affectedPackage = (0, _getAffectedPackageConfig.getAffectedPackageConfig)(source, _affectedAtlaskitPackages.AFFECTED_ATLASKIT_PACKAGES); // Ignore non-atlaskit input packages if (!affectedPackage) { return; } if (!node.specifiers.length) { return; } var defaultImport = node.specifiers.filter(function (spec) { return spec.type === 'ImportDefaultSpecifier'; }); var namedImport = node.specifiers.filter(function (spec) { return spec.type === 'ImportSpecifier'; }); var importNames = affectedPackage.importNames; var usesDefaultImport = importNames.includes('default'); var possibleNamedImports = importNames.filter(function (importName) { return importName !== 'default'; }); if (usesDefaultImport && defaultImport.length && defaultImport[0].local) { localComponentNames.push(defaultImport[0].local.name); } else if (possibleNamedImports.length >= 1 && namedImport.length) { namedImport.forEach(function (imp) { if (imp.type === 'ImportSpecifier' && 'name' in imp.imported && possibleNamedImports.includes(imp.imported.name)) { localComponentNames.push(imp.local.name); } }); } }, JSXElement: function JSXElement(node) { if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) { return false; } var elName = _jsxElementHelper.JSXElementHelper.getName(node); if (!elName) { return false; } var fixes = []; // If it is one of the affected native HTML elements if (_affectedHtmlElements.AFFECTED_HTML_ELEMENTS.includes(elName)) { var unwantedAttributes = hasUnwantedAttributes(node, 'html'); if (unwantedAttributes.includes('disabled')) { fixes.push(context.report({ node: node.openingElement, messageId: 'noDisabled' })); } if (unwantedAttributes.includes('readonly')) { fixes.push(context.report({ node: node.openingElement, messageId: 'noReadOnly' })); } // Else, it is a React component } else { // if none of the affected packages is imported, return if (localComponentNames.length === 0) { return; } // if component name is not in the list, exit if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier') || !localComponentNames.includes(node.openingElement.name.name)) { return; } var _unwantedAttributes = hasUnwantedAttributes(node, 'atlaskit'); if (_unwantedAttributes.includes('isDisabled')) { fixes.push(context.report({ node: node.openingElement, messageId: 'noDisabled' })); } if (_unwantedAttributes.includes('isReadOnly')) { fixes.push(context.report({ node: node.openingElement, messageId: 'noReadOnly' })); } } return fixes; } }; } }); var _default = exports.default = rule;