UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

80 lines (79 loc) 3.27 kB
import { isNodeOfType } from 'eslint-codemod-utils'; import { createLintRule } from '../utils/create-lint-rule'; var rule = createLintRule({ meta: { name: 'no-margin', type: 'problem', docs: { recommended: false, severity: 'warn', description: 'Disallow using the margin CSS property.' }, messages: { noMargin: 'The use of `margin` is considered dangerous as it breaks the component model. Prefer a primitive spacing component or the application of `gap` via CSS Flexbox or Grid to achieve the same result and control the layout from the parent.' } }, create: function create(context) { return { // CSSObjectExpression and StyledObjectExpression // const cssObjectExpression = css({ margin: '4px' }) // const styledObjectExpression = styled.div({margin: '8px'}) 'CallExpression[callee.name=css] > ObjectExpression, CallExpression[callee.object.name=styled] > ObjectExpression': function CallExpressionCalleeNameCss__ObjectExpression_CallExpressionCalleeObjectNameStyled__ObjectExpression(parentNode) { if (!isNodeOfType(parentNode, 'ObjectExpression')) { return; } var _findObjectStyles = function findObjectStyles(node) { if (!isNodeOfType(node, 'Property')) { return; } if (isNodeOfType(node.value, 'ObjectExpression')) { return node.value.properties.forEach(_findObjectStyles); } if (!isNodeOfType(node.key, 'Identifier')) { return; } if (node.key.name.includes('margin')) { context.report({ node: node, messageId: 'noMargin' }); } return; }; parentNode.properties.forEach(_findObjectStyles); }, // CSSTemplateLiteral and StyledTemplateLiteral // const cssTemplateLiteral = css`color: red; margin: 12px`; // const styledTemplateLiteral = styled.p`color: red; margin: 8px`; 'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyled(node) { if (node.type !== 'TaggedTemplateExpression') { return; } var combinedString = node.quasi.quasis.map(function (q) { return q.value.raw; }).join(''); /** * Attempts to remove all non-essential words & characters from a style block. * Including selectors and queries * Adapted from ensure-design-token-usage */ var cssProperties = combinedString.split('\n').filter(function (line) { return !line.trim().startsWith('@'); }).join('\n').replace(/\n/g, '').split(/;|(?<!\$){|(?<!\${.+?)}/) // don't split on template literal expressions i.e. `${...}` .map(function (el) { return el.trim() || ''; }).filter(Boolean); cssProperties.forEach(function (style) { var prop = style.split(':')[0]; if (prop.includes('margin')) { context.report({ node: node, messageId: 'noMargin' }); } }); } }; } }); export default rule;