@atlaskit/eslint-plugin-design-system
Version:
The essential plugin for use with the Atlassian Design System.
84 lines (83 loc) • 3.97 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 elementsAccessibleNameProps = ['title', 'titleId'];
var rule = (0, _createLintRule.createLintRule)({
meta: {
name: 'use-menu-section-title',
type: 'suggestion',
docs: {
description: 'Encourages makers to provide accessible title for Atlassian Design System Menu Section component.',
recommended: true,
severity: 'warn'
},
messages: {
missingTitleProp: 'Missing accessible title. If there is no visible content to associate use `title` prop, otherwise pass id of element to `titleId` prop to be associated as label.',
titlePropShouldHaveContents: 'Define the string that labels the interactive element.',
titleIdShouldHaveValue: '`titleId` should reference the id of the element that defines the accessible name.',
noBothPropsUsage: 'Do not include both `titleId` and `title` properties. Use `titleId` if the label text is available in the DOM to reference it, otherwise use `title` to provide accessible name explicitly.'
},
hasSuggestions: true
},
create: function create(context) {
var contextLocalIdentifier = [];
return {
ImportDeclaration: function ImportDeclaration(node) {
var _node$specifiers;
var menuSectionIdentifier = (_node$specifiers = node.specifiers) === null || _node$specifiers === void 0 ? void 0 : _node$specifiers.filter(function (spec) {
if (node.source.value === '@atlaskit/menu') {
var _spec$imported;
return spec.type === 'ImportSpecifier' && 'name' in spec.imported && ((_spec$imported = spec.imported) === null || _spec$imported === void 0 ? void 0 : _spec$imported.name) === 'Section';
}
if (node.source.value === '@atlaskit/menu/section') {
return spec.type === 'ImportDefaultSpecifier';
}
});
if (menuSectionIdentifier !== null && menuSectionIdentifier !== void 0 && menuSectionIdentifier.length) {
var local = menuSectionIdentifier[0].local;
contextLocalIdentifier.push(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 (contextLocalIdentifier.includes(name)) {
var componentLabelProps = node.openingElement.attributes.filter(function (attr) {
return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute') && (0, _eslintCodemodUtils.isNodeOfType)(attr.name, 'JSXIdentifier') && elementsAccessibleNameProps.includes(attr.name.name);
});
if (componentLabelProps.length === 1) {
var prop = componentLabelProps[0];
if ('value' in prop && prop.value) {
if ((0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'Literal') && !prop.value.value || (0, _eslintCodemodUtils.isNodeOfType)(prop.value, 'JSXExpressionContainer') && !prop.value.expression) {
context.report({
node: prop,
messageId: prop.name.name === 'title' ? 'titlePropShouldHaveContents' : 'titleIdShouldHaveValue'
});
}
}
} else if (componentLabelProps.length > 1) {
context.report({
node: node.openingElement,
messageId: 'noBothPropsUsage'
});
} else {
context.report({
node: node.openingElement,
messageId: 'missingTitleProp'
});
}
}
}
};
}
});
var _default = exports.default = rule;