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