UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

84 lines (83 loc) 3.97 kB
"use strict"; 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;