UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

175 lines (173 loc) 7.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _eslintCodemodUtils = require("eslint-codemod-utils"); var _contextCompat = require("@atlaskit/eslint-utils/context-compat"); var _createLintRule = require("../utils/create-lint-rule"); var _isCssInJsObjectNode = require("../utils/is-css-in-js-object-node"); var _isCssInJsTemplateNode = require("../utils/is-css-in-js-template-node"); var _countMatchingKeyValues = require("./count-matching-key-values"); var _fixJsx = _interopRequireDefault(require("./fix-jsx")); var _fixVanilla = _interopRequireDefault(require("./fix-vanilla")); var _getObjectLikeness = require("./get-object-likeness"); var _makeTemplateLiteralIntoEntries = require("./make-template-literal-into-entries"); var THEME_IMPORT_NAMES = ['visuallyHidden', 'assistive']; var rule = (0, _createLintRule.createLintRule)({ meta: { name: 'use-visually-hidden', type: 'suggestion', fixable: 'code', docs: { description: 'Enforce usage of the visually hidden component.', recommended: true, severity: 'error' }, messages: { noDeprecatedUsage: 'Using the export `{{local}}` from `{{import}}` as a mixin is discouraged. Please use `@atlaskit/visually-hidden` instead.', noDeprecated: 'The export `{{local}}` from `{{import}}` is deprecated. Please use `@atlaskit/visually-hidden` instead.', suggestion: 'This CSS closely matches the implementation of a visually hidden element. You should consider using the `@atlaskit/visually-hidden` component instead.' } }, create: function create(context) { var source = (0, _contextCompat.getSourceCode)(context); return { ImportDeclaration: function ImportDeclaration(node) { var isThemeNode = (0, _eslintCodemodUtils.hasImportDeclaration)(node, '@atlaskit/theme') || (0, _eslintCodemodUtils.hasImportDeclaration)(node, '@atlaskit/theme/constants'); if (!isThemeNode) { return; } var visuallyHiddenOrAssistive = node.specifiers.filter(function (specifier) { return specifier.type === 'ImportSpecifier'; }).find(function (specifier) { return 'name' in specifier.imported && THEME_IMPORT_NAMES.includes(specifier.imported.name); }); if (!visuallyHiddenOrAssistive) { return; } (0, _contextCompat.getDeclaredVariables)(context, visuallyHiddenOrAssistive).forEach(function (someNode) { someNode.references.map(function (innerNode) { return innerNode.identifier; }).forEach(function (idNode) { // @ts-ignore JSX is not typed correctly in eslint if ((idNode === null || idNode === void 0 ? void 0 : idNode.parent.type) === 'JSXExpressionContainer') { context.report({ node: idNode.parent, messageId: 'noDeprecatedUsage', data: { import: "".concat(node.source.value), local: visuallyHiddenOrAssistive.local.name }, fix: (0, _fixJsx.default)(source, idNode) }); // this is either a styled usage OR mixin usage in a styled usage } else if (idNode.parent.type === 'CallExpression') { if ((0, _isCssInJsObjectNode.isCssInJsObjectNode)(idNode.parent) || (0, _isCssInJsTemplateNode.isCssInJsTemplateNode)(idNode.parent)) { context.report({ node: idNode.parent, messageId: 'noDeprecatedUsage', data: { import: "".concat(node.source.value), local: visuallyHiddenOrAssistive.local.name }, fix: (0, _fixVanilla.default)(source, idNode.parent) }); } if (idNode.parent.callee === idNode) { context.report({ node: idNode.parent, messageId: 'noDeprecatedUsage', data: { import: "".concat(node.source.value), local: visuallyHiddenOrAssistive.local.name }, fix: (0, _fixVanilla.default)(source, (0, _eslintCodemodUtils.closestOfType)(idNode.parent, 'TaggedTemplateExpression')) }); } } }); }); return context.report({ node: visuallyHiddenOrAssistive, messageId: 'noDeprecated', data: { import: "".concat(node.source.value), local: visuallyHiddenOrAssistive.local.name } }); }, CallExpression: function CallExpression(node) { var _node$arguments$; if (node.type !== 'CallExpression') { return; } if (!(node.callee.type === 'MemberExpression' || node.callee.type === 'Identifier')) { return; } var isStyled = (0, _isCssInJsObjectNode.isCssInJsObjectNode)(node); if (node.callee.type === 'MemberExpression' && node.callee.object.type === 'Identifier' && node.callee.object.name !== 'styled') { return; } if (node.callee.type === 'Identifier' && node.callee.name !== 'css') { return; } // This is an object style (probably) if (node.arguments && ((_node$arguments$ = node.arguments[0]) === null || _node$arguments$ === void 0 ? void 0 : _node$arguments$.type) === 'ObjectExpression') { var matchingScore = (0, _getObjectLikeness.getObjectLikeness)(node.arguments[0]); if (matchingScore > 0.8) { return context.report({ node: node.parent, messageId: 'suggestion', fix: isStyled ? (0, _fixVanilla.default)(source, node) : undefined }); } } return null; }, ObjectExpression: function ObjectExpression(node) { if (node.parent.type === 'CallExpression') { return; } var matchingScore = (0, _getObjectLikeness.getObjectLikeness)(node); if (matchingScore > 0.8) { return context.report({ node: node, messageId: 'suggestion' }); } }, 'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyled(node) { if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'TaggedTemplateExpression')) { return; } var templateString = node.quasi.quasis.map(function (q) { return q.value.raw; }).join(''); var styleEntries = (0, _makeTemplateLiteralIntoEntries.makeTemplateLiteralIntoEntries)(templateString); if (!styleEntries) { return; } var count = (0, _countMatchingKeyValues.countMatchingKeyValues)(styleEntries.map(function (_ref) { var _ref2 = (0, _slicedToArray2.default)(_ref, 2), key = _ref2[0], value = _ref2[1]; return { key: key, value: value }; })); if (count > 0.8) { return context.report({ node: node, messageId: 'suggestion', fix: node.tag.type !== 'Identifier' ? (0, _fixVanilla.default)(source, node) : undefined }); } } }; } }); var _default = exports.default = rule;