UNPKG

@atlaskit/eslint-plugin-ui-styling-standard

Version:

The eslint plugin to enforce and educate on Atlassian's UI Styling Standard

208 lines (207 loc) • 10.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _contextCompat = require("@atlaskit/eslint-utils/context-compat"); var _isSupportedImport = require("@atlaskit/eslint-utils/is-supported-import"); var _createRule = require("../utils/create-rule"); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } var isTypographyImportSpecifier = function isTypographyImportSpecifier(def) { var _def$parent, _def$parent2, _def$parent3; return def.node.type === 'ImportSpecifier' && def.node.imported.type === 'Identifier' && ((_def$parent = def.parent) === null || _def$parent === void 0 ? void 0 : _def$parent.type) === 'ImportDeclaration' && (def.node.imported.name === 'typography' && ((_def$parent2 = def.parent) === null || _def$parent2 === void 0 ? void 0 : _def$parent2.source.value) === '@atlaskit/theme' || ((_def$parent3 = def.parent) === null || _def$parent3 === void 0 ? void 0 : _def$parent3.source.value) === '@atlaskit/theme/typography'); }; var isElevationImportSpecifier = function isElevationImportSpecifier(def) { var _def$parent4, _def$parent5, _def$parent6; return def.node.type === 'ImportSpecifier' && def.node.imported.type === 'Identifier' && ((_def$parent4 = def.parent) === null || _def$parent4 === void 0 ? void 0 : _def$parent4.type) === 'ImportDeclaration' && (def.node.imported.name === 'elevation' && ((_def$parent5 = def.parent) === null || _def$parent5 === void 0 ? void 0 : _def$parent5.source.value) === '@atlaskit/theme' || ((_def$parent6 = def.parent) === null || _def$parent6 === void 0 ? void 0 : _def$parent6.source.value) === '@atlaskit/theme/elevation'); }; var isSkeletonShimmerImportSpecifier = function isSkeletonShimmerImportSpecifier(def) { var _def$parent7, _def$parent8, _def$parent9; return def.node.type === 'ImportSpecifier' && def.node.imported.type === 'Identifier' && ((_def$parent7 = def.parent) === null || _def$parent7 === void 0 ? void 0 : _def$parent7.type) === 'ImportDeclaration' && def.node.imported.name === 'skeletonShimmer' && typeof ((_def$parent8 = def.parent) === null || _def$parent8 === void 0 ? void 0 : _def$parent8.source.value) === 'string' && ((_def$parent9 = def.parent) === null || _def$parent9 === void 0 || (_def$parent9 = _def$parent9.source.value) === null || _def$parent9 === void 0 ? void 0 : _def$parent9.startsWith('@atlaskit/theme')); }; var bannedImportChecks = [{ messageId: 'usingTypography', isBanned: isTypographyImportSpecifier }, { messageId: 'usingElevation', isBanned: isElevationImportSpecifier }, { messageId: 'usingSkeletonShimmer', isBanned: isSkeletonShimmerImportSpecifier }]; function isAstNode(value) { return (0, _typeof2.default)(value) === 'object' && value !== null && 'type' in value && typeof value.type === 'string'; } function hasBannedThemeImport(sourceCode) { var _iterator = _createForOfIteratorHelper(sourceCode.ast.body), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var statement = _step.value; if (statement.type !== 'ImportDeclaration' || typeof statement.source.value !== 'string') { continue; } var source = statement.source.value; if (!source.startsWith('@atlaskit/theme')) { continue; } var _iterator2 = _createForOfIteratorHelper(statement.specifiers), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var specifier = _step2.value; if (specifier.type !== 'ImportSpecifier' || specifier.imported.type !== 'Identifier') { continue; } var name = specifier.imported.name; if (source === '@atlaskit/theme/typography' || source === '@atlaskit/theme/elevation') { return true; } if (source === '@atlaskit/theme' && (name === 'typography' || name === 'elevation')) { return true; } if (name === 'skeletonShimmer') { return true; } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return false; } function visitIdentifiers(node, visit) { if (node.type === 'Identifier' && 'name' in node && typeof node.name === 'string') { visit(node); } for (var _i = 0, _Object$keys = Object.keys(node); _i < _Object$keys.length; _i++) { var key = _Object$keys[_i]; if (key === 'parent') { continue; } var value = node[key]; if (Array.isArray(value)) { var _iterator3 = _createForOfIteratorHelper(value), _step3; try { for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { var child = _step3.value; if (isAstNode(child)) { visitIdentifiers(child, visit); } } } catch (err) { _iterator3.e(err); } finally { _iterator3.f(); } } else if (isAstNode(value)) { visitIdentifiers(value, visit); } } } function findReferencedVariable(scope, identifier) { var current = scope; while (current) { var variable = current.set.get(identifier.name); if (variable !== null && variable !== void 0 && variable.references.some(function (reference) { return reference.identifier === identifier; })) { return variable; } current = current.upper; } return undefined; } var rule = (0, _createRule.createLintRule)({ meta: { name: 'atlaskit-theme', docs: { description: 'Ban certain usages of `@atlaskit/theme` that `@compiled/react` does not understand', removeFromPresets: true }, messages: { usingTypography: 'Typography does not work with Compiled. Please utilise alternatives like Heading or tokens instead and see https://atlassian.design/components/eslint-plugin-ui-styling-standard/atlaskit-theme/usage', usingElevation: 'Elevation does not work with Compiled. Please use a token with a fallback instead and see https://atlassian.design/components/eslint-plugin-ui-styling-standard/atlaskit-theme/usage', usingSkeletonShimmer: 'Skeleton Shimmer does not work with Compiled. Please use an SVG skeleton instead and see https://atlassian.design/components/eslint-plugin-ui-styling-standard/atlaskit-theme/usage' }, schema: [], type: 'problem' }, create: function create(context) { var sourceCode = (0, _contextCompat.getSourceCode)(context); if (!hasBannedThemeImport(sourceCode)) { return {}; } var importSources = (0, _isSupportedImport.getImportSources)(context); var reported = new WeakSet(); var reportBannedIdentifier = function reportBannedIdentifier(identifier, scope) { if (identifier.name === 'fontFallback' || reported.has(identifier)) { return; } var variable = findReferencedVariable(scope, identifier); if (!variable) { return; } var didReport = false; for (var _i2 = 0, _bannedImportChecks = bannedImportChecks; _i2 < _bannedImportChecks.length; _i2++) { var _bannedImportChecks$_ = _bannedImportChecks[_i2], messageId = _bannedImportChecks$_.messageId, isBanned = _bannedImportChecks$_.isBanned; if (variable.defs.some(isBanned)) { context.report({ messageId: messageId, node: identifier }); didReport = true; } } if (didReport) { reported.add(identifier); } }; var lintCompiledInvocation = function lintCompiledInvocation(node) { if (node.type !== 'CallExpression' && node.type !== 'TaggedTemplateExpression') { return; } var calleeOrTag = node.type === 'CallExpression' ? node.callee : node.tag; var scope = (0, _contextCompat.getScope)(context, node); if (!(0, _isSupportedImport.isCompiled)(calleeOrTag, scope.references, importSources)) { return; } var roots = node.type === 'CallExpression' ? node.arguments : node.quasi.expressions; var _iterator4 = _createForOfIteratorHelper(roots), _step4; try { for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) { var root = _step4.value; if (isAstNode(root)) { visitIdentifiers(root, function (identifier) { return reportBannedIdentifier(identifier, scope); }); } } } catch (err) { _iterator4.e(err); } finally { _iterator4.f(); } }; return { CallExpression: lintCompiledInvocation, TaggedTemplateExpression: lintCompiledInvocation }; } }); var _default = exports.default = rule;