@atlaskit/eslint-plugin-design-system
Version:
The essential plugin for use with the Atlassian Design System.
69 lines • 2.89 kB
JavaScript
import { isNodeOfType } from 'eslint-codemod-utils';
import { getSourceCode } from '@atlaskit/eslint-utils/context-compat';
import { createLintRule } from '../utils/create-lint-rule';
import { getModuleOfIdentifier } from '../utils/get-module-of-identifier';
import { getJSXElementName } from '../utils/jsx';
var unsafeOverrides = ['css', 'className', 'theme', 'cssFn', 'styles'];
var rule = createLintRule({
meta: {
docs: {
recommended: true,
// This should be an error but for now we're rolling it out as warn so we can actually get it into codebases.
severity: 'warn',
description: 'Discourage usage of unsafe style overrides used against the Atlassian Design System.'
},
name: 'no-unsafe-style-overrides',
messages: {
noUnsafeStyledOverride: 'Wrapping {{componentName}} in a styled component encourages unsafe style overrides which cause friction and incidents when its internals change.',
noUnsafeOverrides: 'The {{propName}} prop encourages unsafe style overrides which cause friction and incidents when {{componentName}} internals change.'
}
},
create: function create(context) {
return {
CallExpression: function CallExpression(node) {
if (node.callee.type !== 'Identifier' || !node.callee.name.toLowerCase().includes('styled')) {
// Ignore functions that don't look like styled().
return;
}
var firstArgument = node.arguments[0];
if (!firstArgument || firstArgument.type !== 'Identifier') {
return;
}
var moduleName = getModuleOfIdentifier(getSourceCode(context), firstArgument.name);
if (!moduleName || !moduleName.moduleName.startsWith('@atlaskit')) {
// Ignore styled calls with non-atlaskit components.
return;
}
context.report({
node: firstArgument,
messageId: 'noUnsafeStyledOverride',
data: {
componentName: moduleName.importName
}
});
},
JSXAttribute: function JSXAttribute(node) {
if (!isNodeOfType(node, 'JSXAttribute') || !(node.parent && isNodeOfType(node.parent, 'JSXOpeningElement'))) {
return;
}
var elementName = getJSXElementName(node.parent);
var moduleName = getModuleOfIdentifier(getSourceCode(context), elementName);
if (!moduleName || !moduleName.moduleName.startsWith('@atlaskit')) {
return;
}
var propName = typeof node.name.name === 'string' ? node.name.name : node.name.name.name;
if (unsafeOverrides.includes(propName)) {
context.report({
node: node,
messageId: 'noUnsafeOverrides',
data: {
propName: propName,
componentName: moduleName.importName
}
});
}
}
};
}
});
export default rule;