UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

143 lines (137 loc) 5.66 kB
import { createIsFromImportSourceFor } from '../../common/is-from-import-source'; import { createLintRule } from '../utils/create-lint-rule'; import { errorBoundary } from '../utils/error-boundary'; import { getCssMapKey } from './get-css-map-key'; import { getIconSize } from './get-icon-size'; import { getSpacingAttribute } from './get-spacing-attribute'; import { getStaticAttributeValue } from './get-static-attribute-value'; import { hasSpreadProps } from './has-spread-props'; import { SPACING_TO_PADDING } from './spacing-to-padding'; import { upsertCssMapImport } from './upsert-css-map-import'; import { upsertCssMapVariable } from './upsert-css-map-variable'; import { upsertFlexImport } from './upsert-flex-import'; import { upsertTokenImport } from './upsert-token-import'; var CSSMAP_VARIABLE_NAME = 'iconSpacingStyles'; var rule = createLintRule({ meta: { name: 'no-icon-spacing-prop', hasSuggestions: true, type: 'suggestion', docs: { description: 'Disallows usage of the deprecated spacing prop on new icons. Use Flex with cssMap for spacing instead.', recommended: true, severity: 'warn' }, messages: { noSpacingProp: "The `spacing` prop on icon component '{{iconName}}' is deprecated. Wrap the icon in a `<Flex xcss={iconSpacingStyles.spaceXXX}>` using `cssMap` from `@atlaskit/css` instead.", noSpacingPropManual: "The `spacing` prop on icon component '{{iconName}}' is deprecated but cannot be auto-fixed ({{reason}}). Manually wrap the icon in a `<Flex xcss={...}>` using `cssMap` from `@atlaskit/css`.", suggestRemoveSpacing: 'Remove the `spacing` prop.', suggestWrapInFlex: 'Wrap in `<Flex xcss={{{cssMapVarName}}.{{cssMapKey}}}>` and remove the `spacing` prop.' } }, create: function create(context) { var isNewIcon = createIsFromImportSourceFor(/^@(atlaskit\/icon|atlaskit\/icon-lab)\/core\//); return errorBoundary({ JSXElement: function JSXElement(node) { var _SPACING_TO_PADDING$s; if (!isNewIcon(node)) { return; } var spacingAttr = getSpacingAttribute(node); if (!spacingAttr) { return; } var iconName = node.openingElement.name.type === 'JSXIdentifier' ? node.openingElement.name.name : 'Unknown'; var spacingValue = getStaticAttributeValue(spacingAttr); var hasSpread = hasSpreadProps(node); if (!spacingValue || hasSpread) { var reason = hasSpread ? 'spread props present' : 'dynamic spacing value'; context.report({ node: node.openingElement, messageId: 'noSpacingPropManual', data: { iconName: iconName, reason: reason } }); return; } if (spacingValue === 'none') { context.report({ node: node.openingElement, messageId: 'noSpacingProp', data: { iconName: iconName }, suggest: [{ messageId: 'suggestRemoveSpacing', fix: function fix(fixer) { return fixer.remove(spacingAttr); } }] }); return; } var size = getIconSize(node); if (!size || !((_SPACING_TO_PADDING$s = SPACING_TO_PADDING[size]) !== null && _SPACING_TO_PADDING$s !== void 0 && _SPACING_TO_PADDING$s[spacingValue])) { context.report({ node: node.openingElement, messageId: 'noSpacingPropManual', data: { iconName: iconName, reason: "unknown size '".concat(size, "' or spacing '").concat(spacingValue, "'") } }); return; } var paddingToken = SPACING_TO_PADDING[size][spacingValue]; var cssMapKey = getCssMapKey(paddingToken); context.report({ node: node.openingElement, messageId: 'noSpacingProp', data: { iconName: iconName }, suggest: [{ messageId: 'suggestWrapInFlex', data: { cssMapVarName: CSSMAP_VARIABLE_NAME, cssMapKey: cssMapKey }, fix: function fix(fixer) { var fixes = []; // 1. Remove spacing prop fixes.push(fixer.remove(spacingAttr)); // 2. Wrap in Flex with cssMap reference fixes.push(fixer.insertTextBefore(node, "<Flex xcss={".concat(CSSMAP_VARIABLE_NAME, ".").concat(cssMapKey, "}>"))); fixes.push(fixer.insertTextAfter(node, "</Flex>")); // 3. Insert/update cssMap variable after last import var cssMapFix = upsertCssMapVariable(context, fixer, paddingToken); if (cssMapFix) { fixes.push(cssMapFix); } // 4. Add/update @atlaskit/css import (cssMap) var cssFix = upsertCssMapImport(context, fixer); if (cssFix) { fixes.push(cssFix); } // 5. Add Flex to @atlaskit/primitives/compiled var flexFix = upsertFlexImport(context, fixer); if (flexFix) { fixes.push(flexFix); } // 6. Add token from @atlaskit/tokens var tokenFix = upsertTokenImport(context, fixer); if (tokenFix) { fixes.push(tokenFix); } return fixes; } }] }); }, ImportDeclaration: isNewIcon.importDeclarationHook }); } }); export default rule;