UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

153 lines (147 loc) 5.51 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RULE_NAME = void 0; Object.defineProperty(exports, "addProp", { enumerable: true, get: function get() { return _addProp.addProp; } }); exports.default = void 0; Object.defineProperty(exports, "setPropToTrue", { enumerable: true, get: function get() { return _setPropToTrue.setPropToTrue; } }); var _eslintCodemodUtils = require("eslint-codemod-utils"); var _createLintRule = require("../utils/create-lint-rule"); var _addProp = require("./add-prop"); var _setPropToTrue = require("./set-prop-to-true"); // eslint-disable-next-line import/no-extraneous-dependencies var RULE_NAME = exports.RULE_NAME = 'use-should-render-to-parent'; var PROP_NAME = 'shouldRenderToParent'; var message = "Setting the `".concat(PROP_NAME, "` prop to anything other than `true` causes accessibility issues. Only set to `false` as a last resort."); var supportedImports = [{ source: '@atlaskit/popup', allowsDefaultImport: true, namedImport: 'Popup' }, { source: '@atlaskit/popup/popup', namedImport: 'Popup' }, { source: '@atlaskit/dropdown-menu', allowsDefaultImport: true }, { source: '@atlaskit/dropdown-menu/dropdown-menu', allowsDefaultImport: true }, { source: '@atlassian/entry-points/dropdown-trigger', namedImport: 'DropdownTrigger' }, { source: '@atlassian/entry-points/popup-trigger', namedImport: 'PopupTrigger' }]; var rule = (0, _createLintRule.createLintRule)({ meta: { name: RULE_NAME, type: 'suggestion', docs: { description: "Encourages makers to use the `".concat(PROP_NAME, "` where possible in Atlassian Design System `Popup` and `DropdownMenu` components."), recommended: true, severity: 'warn' }, messages: { missingShouldRenderToParentProp: "The default value of `".concat(PROP_NAME, "` is `false`. ").concat(message), falseShouldRenderToParentProp: message }, hasSuggestions: true }, create: function create(context) { var componentLocalNames = new Set(); return { ImportDeclaration: function ImportDeclaration(node) { var source = node.source.value; if (typeof source !== 'string') { return; } var supportedImport = supportedImports.find(function (component) { return component.source === source; }); if (!supportedImport) { return; } if (!node.specifiers.length) { return; } var defaultImport = node.specifiers.filter(function (spec) { return spec.type === 'ImportDefaultSpecifier'; }); var namedImports = node.specifiers.filter(function (spec) { return spec.type === 'ImportSpecifier'; }); if (defaultImport.length && defaultImport[0].local && supportedImport.allowsDefaultImport) { componentLocalNames.add(defaultImport[0].local.name); } if (!namedImports.length) { return; } // Iterate through all of them, only one should ever be found namedImports.forEach(function (namedImport) { if (namedImport.type === 'ImportSpecifier' && 'name' in namedImport.imported && namedImport.imported.name === supportedImport.namedImport) { componentLocalNames.add(namedImport.local.name); } }); }, JSXElement: function JSXElement(node) { if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) { return; } if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier')) { return; } var name = node.openingElement.name.name; if (componentLocalNames.has(name)) { var prop = node.openingElement.attributes.find(function (attr) { return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute') && (0, _eslintCodemodUtils.isNodeOfType)(attr.name, 'JSXIdentifier') && attr.name.name === PROP_NAME; }); // If the prop does not exist, throw if (!prop) { return context.report({ node: node.openingElement.name, messageId: 'missingShouldRenderToParentProp', suggest: [{ desc: _addProp.addProp, fix: function fix(fixer) { return [fixer.insertTextAfter(node.openingElement.name, " ".concat(PROP_NAME))]; } }] }); } // If the prop is a boolean attribute with no value (set to `true`), // it's valid if (!('value' in prop) || prop.value === null) { return; } // If the prop has a falsy literal value or a falsy value in an // expression container, throw if ((0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'Literal') && !prop.value.value || (0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'JSXExpressionContainer') && prop.value.expression.type === 'Literal' && !prop.value.expression.value) { return context.report({ node: prop, messageId: 'falseShouldRenderToParentProp', suggest: [{ desc: _setPropToTrue.setPropToTrue, fix: function fix(fixer) { return [fixer.replaceText(prop, PROP_NAME)]; } }] }); } } } }; } }); var _default = exports.default = rule;