@atlaskit/eslint-plugin-design-system
Version:
The essential plugin for use with the Atlassian Design System.
158 lines (155 loc) • 7.97 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _eslintCodemodUtils = require("eslint-codemod-utils");
var _jsxElementHelper = require("../../ast-nodes/jsx-element-helper");
var _createLintRule = require("../utils/create-lint-rule");
var _getAffectedPackageConfig = require("../utils/get-affected-package-config");
var _getFormImportLocalNames = require("../utils/get-form-import-local-names");
var _affectedAtlaskitPackages = require("./affected-atlaskit-packages");
var _affectedHtmlElements = require("./affected-html-elements");
var ATLASKIT_FIELD_IMPORT = 'Field';
var rule = (0, _createLintRule.createLintRule)({
meta: {
name: 'no-placeholder',
type: 'problem',
docs: {
description: 'Placeholders should not be used. If information should be given to the user about the proper type or formatting of a value, this should be included using a helper message that is associated to the input instead.',
recommended: true,
severity: 'warn'
},
messages: {
noPlaceholder: 'Placeholders should not be used. Use separate information to help users associated using `aria-describedby` instead.',
noPlaceholderOnSimpleField: 'Placeholders should not be used. Use the `helperMessage` prop instead.',
noPlaceholderOnComplexField: 'Placeholders should not be used. Use the `HelperMessage` component instead.'
}
},
create: function create(context) {
var hasFieldImport = false;
var fieldLocalName = null;
var localComponentNames = [];
return {
ImportDeclaration: function ImportDeclaration(node) {
var source = node.source.value;
var affectedPackage = (0, _getAffectedPackageConfig.getAffectedPackageConfig)(source, _affectedAtlaskitPackages.AFFECTED_ATLASKIT_PACKAGES);
// Ignore non-atlaskit input/form packages
if (!affectedPackage && source !== _getFormImportLocalNames.FORM_PACKAGE && source !== "".concat(_getFormImportLocalNames.FORM_PACKAGE, "/field")) {
return;
}
if (!node.specifiers.length) {
return;
}
var defaultImport = node.specifiers.filter(function (spec) {
return spec.type === 'ImportDefaultSpecifier';
});
var namedImport = node.specifiers.filter(function (spec) {
return spec.type === 'ImportSpecifier';
});
if (source === _getFormImportLocalNames.FORM_PACKAGE || source === "".concat(_getFormImportLocalNames.FORM_PACKAGE, "/field")) {
var _formImports$ATLASKIT, _formImports$ATLASKIT2;
var formImports = (0, _getFormImportLocalNames.getFormImportLocalNames)(node);
var matchedFieldImport = (_formImports$ATLASKIT = (_formImports$ATLASKIT2 = formImports[ATLASKIT_FIELD_IMPORT]) === null || _formImports$ATLASKIT2 === void 0 ? void 0 : _formImports$ATLASKIT2[0]) !== null && _formImports$ATLASKIT !== void 0 ? _formImports$ATLASKIT : null;
if (matchedFieldImport) {
hasFieldImport = true;
fieldLocalName = matchedFieldImport;
}
} else {
var _affectedPackage$impo;
var importNames = (_affectedPackage$impo = affectedPackage === null || affectedPackage === void 0 ? void 0 : affectedPackage.importNames) !== null && _affectedPackage$impo !== void 0 ? _affectedPackage$impo : [];
var usesDefaultImport = importNames.includes('default');
var possibleNamedImports = importNames.filter(function (importName) {
return importName !== 'default';
});
if (usesDefaultImport && defaultImport.length && defaultImport[0].local) {
localComponentNames.push(defaultImport[0].local.name);
// or if popup and using a named import
} else if (possibleNamedImports.length >= 1 && namedImport.length) {
namedImport.forEach(function (imp) {
if (imp.type === 'ImportSpecifier' && 'name' in imp.imported && possibleNamedImports.includes(imp.imported.name)) {
localComponentNames.push(imp.local.name);
}
});
}
}
},
JSXElement: function JSXElement(node) {
if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
return false;
}
var elName = _jsxElementHelper.JSXElementHelper.getName(node);
if (!elName) {
return false;
}
// If it is one of the affected native HTML elements
if (_affectedHtmlElements.AFFECTED_HTML_ELEMENTS.includes(elName)) {
// if has a placeholder attribute
var hasPlaceholderAttribute = node.openingElement.attributes.find(function (attr) {
return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute') && attr.name.name === 'placeholder';
});
if (hasPlaceholderAttribute) {
return context.report({
node: node.openingElement,
messageId: 'noPlaceholder'
});
}
// Else, it is a React component
} else {
// if none of the affected packages is imported, return
if (localComponentNames.length === 0) {
return;
}
// if component name is not in the list, exit
if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier') || !localComponentNames.includes(node.openingElement.name.name)) {
return;
}
if (hasFieldImport && fieldLocalName) {
var _node = node;
var hasParentField = false;
var fieldType = 'Complex';
// If node is a Field element or if
while ((0, _eslintCodemodUtils.isNodeOfType)(_node, 'JSXElement') && (0, _eslintCodemodUtils.isNodeOfType)(_node.openingElement.name, 'JSXIdentifier') && !hasParentField) {
var name = _node.openingElement.name.name;
hasParentField = hasParentField || name === fieldLocalName;
_node = _node.parent;
// Skip up until a JSXElement or JSXAttribute is reached
if ((0, _eslintCodemodUtils.isNodeOfType)(_node, 'JSXFragment') || (0, _eslintCodemodUtils.isNodeOfType)(_node, 'ArrowFunctionExpression') || (0, _eslintCodemodUtils.isNodeOfType)(_node, 'JSXExpressionContainer') || (0, _eslintCodemodUtils.isNodeOfType)(_node, 'JSXAttribute')) {
while (_node && !(0, _eslintCodemodUtils.isNodeOfType)(_node, 'JSXElement') && !(0, _eslintCodemodUtils.isNodeOfType)(_node, 'Program')) {
if ((0, _eslintCodemodUtils.isNodeOfType)(_node, 'JSXAttribute')) {
fieldType = 'Simple';
}
_node = _node.parent;
}
}
}
if (hasParentField) {
// if has a placeholder attribute
var _hasPlaceholderAttribute = node.openingElement.attributes.find(function (attr) {
return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute') && attr.name.name === 'placeholder';
});
if (_hasPlaceholderAttribute) {
return context.report({
node: node.openingElement,
messageId: "noPlaceholderOn".concat(fieldType, "Field")
});
}
}
} else {
// if has a placeholder attribute
var _hasPlaceholderAttribute2 = node.openingElement.attributes.find(function (attr) {
return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute') && attr.name.name === 'placeholder';
});
if (_hasPlaceholderAttribute2) {
return context.report({
node: node.openingElement,
messageId: 'noPlaceholder'
});
}
}
}
}
};
}
});
var _default = exports.default = rule;