@atlaskit/eslint-plugin-design-system
Version:
The essential plugin for use with the Atlassian Design System.
92 lines (86 loc) • 4.48 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import { isNodeOfType } from 'eslint-codemod-utils';
import { createLintRule } from '../utils/create-lint-rule';
import { getFormImportLocalNames } from '../utils/get-form-import-local-names';
var rule = createLintRule({
meta: {
name: 'use-field-message-wrapper',
type: 'suggestion',
hasSuggestions: true,
docs: {
description: 'Encourage use of message wrapper component when using form message components.',
recommended: true,
severity: 'warn'
},
messages: {
useMessageWrapper: "All ADS form messaging components within a field should be wrapped by the `MessageWrapper` component from the form package. Consider also using the [simplified field implementation](https://atlassian.design/components/form/examples#simple-implementation-1) to handle styling and accessible messaging directly."
}
},
create: function create(context) {
var fieldImport;
var messageWrapperImport;
var messageImports = [];
return {
ImportDeclaration: function ImportDeclaration(node) {
var _formImports$Field$, _formImports$Field, _formImports$MessageW, _formImports$MessageW2, _formImports$ErrorMes, _formImports$HelperMe, _formImports$ValidMes;
var 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;
messageWrapperImport = (_formImports$MessageW = (_formImports$MessageW2 = formImports.MessageWrapper) === null || _formImports$MessageW2 === void 0 ? void 0 : _formImports$MessageW2[0]) !== null && _formImports$MessageW !== void 0 ? _formImports$MessageW : messageWrapperImport;
messageImports.push.apply(messageImports, _toConsumableArray((_formImports$ErrorMes = formImports.ErrorMessage) !== null && _formImports$ErrorMes !== void 0 ? _formImports$ErrorMes : []).concat(_toConsumableArray((_formImports$HelperMe = formImports.HelperMessage) !== null && _formImports$HelperMe !== void 0 ? _formImports$HelperMe : []), _toConsumableArray((_formImports$ValidMes = formImports.ValidMessage) !== null && _formImports$ValidMes !== void 0 ? _formImports$ValidMes : [])));
},
JSXElement: function JSXElement(node) {
if (!isNodeOfType(node, 'JSXElement')) {
return;
}
if (!isNodeOfType(node.openingElement.name, 'JSXIdentifier')) {
return;
}
var name = node.openingElement.name.name;
// if it's not a message component, skip
if (messageImports.length === 0 || !messageImports.includes(name)) {
return;
}
// if no field import exists, skip. It needs to be within our field
if (!fieldImport) {
return;
}
// If no message wrapper import exists, then it's definitely an error
if (!messageWrapperImport) {
return context.report({
node: node,
messageId: 'useMessageWrapper'
});
}
// check for if field and message wrapper are parents
var _node = node;
var hasParentField = false;
var hasParentMessageWrapper = false;
while (isNodeOfType(_node, 'JSXElement') && isNodeOfType(_node.openingElement.name, 'JSXIdentifier') && !hasParentField) {
var _name = _node.openingElement.name.name;
hasParentField = hasParentField || _name === fieldImport;
hasParentMessageWrapper = hasParentMessageWrapper || _name === messageWrapperImport;
_node = _node.parent;
// Skip up until a JSXElement is reached
if (isNodeOfType(_node, 'JSXFragment') || isNodeOfType(_node, 'ArrowFunctionExpression') || isNodeOfType(_node, 'JSXExpressionContainer')) {
while (_node && !isNodeOfType(_node, 'JSXElement') && !isNodeOfType(_node, 'Program')) {
_node = _node.parent;
}
}
}
// if not field, skip because this doesn't matter
if (!hasParentField) {
return;
}
// if it has a message wrapper, skip
if (hasParentMessageWrapper) {
return;
}
context.report({
node: node,
messageId: 'useMessageWrapper'
});
}
};
}
});
export default rule;