@atlaskit/eslint-plugin-design-system
Version:
The essential plugin for use with the Atlassian Design System.
175 lines (173 loc) • 7.7 kB
JavaScript
"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;