UNPKG

@atlaskit/eslint-plugin-design-system

Version:

The essential plugin for use with the Atlassian Design System.

101 lines (96 loc) 4.35 kB
import { isNodeOfType } from 'eslint-codemod-utils'; import { createLintRule } from '../utils/create-lint-rule'; import { getFormImportLocalNames } from '../utils/get-form-import-local-names'; export const convertField = 'Convert field to simple field'; const rule = createLintRule({ meta: { name: 'use-simple-field', type: 'suggestion', hasSuggestions: true, docs: { description: 'Encourage use of simple field for better developer experience and accessibility.', recommended: true, severity: 'warn' }, messages: { useSimpleField: 'The simplified field implementation can be used here.' } }, create(context) { let fieldImport; let messageImports = []; return { ImportDeclaration(node) { var _formImports$Field$, _formImports$Field, _formImports$ErrorMes, _formImports$HelperMe, _formImports$ValidMes; const formImports = getFormImportLocalNames(node); fieldImport = (_formImports$Field$ = (_formImports$Field = formImports.Field) === null || _formImports$Field === void 0 ? void 0 : _formImports$Field[0]) !== null && _formImports$Field$ !== void 0 ? _formImports$Field$ : fieldImport; messageImports.push(...((_formImports$ErrorMes = formImports.ErrorMessage) !== null && _formImports$ErrorMes !== void 0 ? _formImports$ErrorMes : []), ...((_formImports$HelperMe = formImports.HelperMessage) !== null && _formImports$HelperMe !== void 0 ? _formImports$HelperMe : []), ...((_formImports$ValidMes = formImports.ValidMessage) !== null && _formImports$ValidMes !== void 0 ? _formImports$ValidMes : [])); }, JSXElement(node) { if (!isNodeOfType(node, 'JSXElement')) { return; } if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) { return; } // if no field import exists, skip if (!fieldImport) { return; } // if component is not field, skip if (node.openingElement.name.name !== fieldImport) { return; } // if message imports exist, skip because we can't really dig around // inside the field to see if they exist because of memory constraints if (messageImports.length > 0) { return; } // if component exists as a prop, skip because it's already simple const attributes = node.openingElement.attributes; const componentAttr = attributes.find(attr => isNodeOfType(attr, 'JSXAttribute') && isNodeOfType(attr.name, 'JSXIdentifier') && attr.name.name === 'component'); if (componentAttr) { return; } // if children is not a render prop, skip const renderProps = node.children.find(child => isNodeOfType(child, 'JSXExpressionContainer')); if (!renderProps) { return; } const renderPropExpression = renderProps.expression; // If not an arrow func, ignore if (!isNodeOfType(renderPropExpression, 'ArrowFunctionExpression')) { return; } const renderPropParams = renderPropExpression.params; // if it is not an object pattern, skip if (!isNodeOfType(renderPropParams[0], 'ObjectPattern')) { return; } // if component uses more than just fieldProps in render props, skip const renderPropArgProperties = renderPropParams[0].properties; const fieldPropsProp = renderPropArgProperties.find(property => isNodeOfType(property, 'Property') && isNodeOfType(property.key, 'Identifier') && property.key.name === 'fieldProps'); if (renderPropArgProperties.length > 1 || !fieldPropsProp) { return; } const lastProp = attributes.slice(-1)[0] || node.openingElement.name; const sourceCode = context.sourceCode; const renderPropsText = sourceCode.getText(renderProps); context.report({ node: node, messageId: 'useSimpleField', suggest: [{ desc: convertField, fix: fixer => { const fixes = []; fixes.push(fixer.insertTextAfter(lastProp, ` component=${renderPropsText} `)); fixes.push(fixer.remove(renderProps)); return fixes; } }] }); } }; } }); export default rule;