@atlaskit/eslint-plugin-design-system
Version:
The essential plugin for use with the Atlassian Design System.
122 lines (121 loc) • 5.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _eslintCodemodUtils = require("eslint-codemod-utils");
var _createLintRule = require("../utils/create-lint-rule");
var MODAL_DIALOG_IMPORT_SOURCES = new Set(['@atlaskit/modal-dialog', '@atlaskit/modal-dialog/modal-dialog']);
/**
* Modal entry-point triggers forward modal dialog props via `modalProps`.
* Do not flag top-level `label` on these components — IconButton-based triggers
* use `label` for the trigger button itself.
*/
var MODAL_ENTRY_POINT_TRIGGERS = [{
source: '@atlassian/entry-points/modal-trigger',
namedImport: 'ModalTrigger'
}, {
source: '@atlassian/entry-points/modal-button-trigger',
namedImport: 'ModalButtonTrigger'
}, {
source: '@atlassian/entry-points/modal-dropdown-item-trigger',
namedImport: 'ModalDropdownItemTrigger'
}, {
source: '@atlassian/entry-points/modal-icon-button-trigger',
namedImport: 'ModalIconButtonTrigger'
}, {
source: '@atlassian/entry-points/full-screen-modal-trigger',
namedImport: 'FullScreenModalTrigger'
}];
var hasLabelInObjectExpression = function hasLabelInObjectExpression(expression) {
if (!(0, _eslintCodemodUtils.isNodeOfType)(expression, 'ObjectExpression')) {
return false;
}
return expression.properties.some(function (property) {
if (!(0, _eslintCodemodUtils.isNodeOfType)(property, 'Property') || property.computed) {
return false;
}
if ((0, _eslintCodemodUtils.isNodeOfType)(property.key, 'Identifier')) {
return property.key.name === 'label';
}
return (0, _eslintCodemodUtils.isNodeOfType)(property.key, 'Literal') && property.key.value === 'label';
});
};
var rule = (0, _createLintRule.createLintRule)({
meta: {
name: 'no-modal-label',
type: 'suggestion',
docs: {
description: 'Disallows usage of the `label` prop on Atlassian Design System modal dialog and modal entry-point triggers.',
recommended: true,
severity: 'error'
},
messages: {
noModalLabel: 'Do not use the `label` prop on modal dialog. Use the `ModalTitle` component within the `ModalHeader`, or the `titleId` prop from `useModal()` on your heading element instead.'
}
},
create: function create(context) {
var modalDefaultImports = new Set();
var modalEntryPointTriggerImports = new Set();
return {
ImportDeclaration: function ImportDeclaration(node) {
var source = String(node.source.value);
if (MODAL_DIALOG_IMPORT_SOURCES.has(source)) {
node.specifiers.forEach(function (specifier) {
if ((0, _eslintCodemodUtils.isNodeOfType)(specifier, 'ImportDefaultSpecifier')) {
modalDefaultImports.add(specifier.local.name);
}
});
return;
}
var supportedImport = MODAL_ENTRY_POINT_TRIGGERS.find(function (component) {
return component.source === source;
});
if (!supportedImport) {
return;
}
node.specifiers.forEach(function (specifier) {
if ((0, _eslintCodemodUtils.isNodeOfType)(specifier, 'ImportSpecifier') && (0, _eslintCodemodUtils.isNodeOfType)(specifier.imported, 'Identifier') && specifier.imported.name === supportedImport.namedImport) {
modalEntryPointTriggerImports.add(specifier.local.name);
}
});
},
JSXOpeningElement: function JSXOpeningElement(node) {
if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXOpeningElement')) {
return;
}
if (!(0, _eslintCodemodUtils.isNodeOfType)(node.name, 'JSXIdentifier')) {
return;
}
var componentName = node.name.name;
if (modalDefaultImports.has(componentName)) {
var labelProp = node.attributes.find(function (attribute) {
return (0, _eslintCodemodUtils.isNodeOfType)(attribute, 'JSXAttribute') && (0, _eslintCodemodUtils.isNodeOfType)(attribute.name, 'JSXIdentifier') && attribute.name.name === 'label';
});
if (!labelProp) {
return;
}
context.report({
node: node,
messageId: 'noModalLabel'
});
return;
}
if (!modalEntryPointTriggerImports.has(componentName)) {
return;
}
var modalPropsAttribute = node.attributes.find(function (attribute) {
return (0, _eslintCodemodUtils.isNodeOfType)(attribute, 'JSXAttribute') && (0, _eslintCodemodUtils.isNodeOfType)(attribute.name, 'JSXIdentifier') && attribute.name.name === 'modalProps';
});
if (!modalPropsAttribute || !(0, _eslintCodemodUtils.isNodeOfType)(modalPropsAttribute, 'JSXAttribute') || !modalPropsAttribute.value || !(0, _eslintCodemodUtils.isNodeOfType)(modalPropsAttribute.value, 'JSXExpressionContainer') || !hasLabelInObjectExpression(modalPropsAttribute.value.expression)) {
return;
}
context.report({
node: node,
messageId: 'noModalLabel'
});
}
};
}
});
var _default = exports.default = rule;