UNPKG

eslint-plugin-styled-component-jsx-attributes

Version:

A simple plugin for enforcing the use of the id attribute on styled components.

146 lines (113 loc) 6.42 kB
"use strict"; var isStyledCallExpression = function isStyledCallExpression(node) { return node.tag.type === 'CallExpression'; }; var isStyledFunc = function isStyledFunc(node) { var _node$tag$callee; // Check for standard styled function call if (((_node$tag$callee = node.tag.callee) === null || _node$tag$callee === void 0 ? void 0 : _node$tag$callee.name) === 'styled') { return true; } // Check for prop forwarding syntax: styled('button', { shouldForwardProp: ... }) try { if (node.tag && node.tag.callee && node.tag.callee.name === 'styled' && node.tag.arguments && node.tag.arguments.length > 1 && node.tag.arguments[1] && node.tag.arguments[1].type === 'ObjectExpression') { return true; } } catch (e) {// Fail safely if any properties are undefined } return false; }; var isStyledFuncWithAttrs = function isStyledFuncWithAttrs(node) { var _node$tag$callee2, _node$tag$callee2$obj, _node$tag$callee2$obj2; return ((_node$tag$callee2 = node.tag.callee) === null || _node$tag$callee2 === void 0 ? void 0 : (_node$tag$callee2$obj = _node$tag$callee2.object) === null || _node$tag$callee2$obj === void 0 ? void 0 : (_node$tag$callee2$obj2 = _node$tag$callee2$obj.callee) === null || _node$tag$callee2$obj2 === void 0 ? void 0 : _node$tag$callee2$obj2.name) === 'styled'; }; var isPlainSTE = function isPlainSTE(node) { var _node$tag, _node$tag$object; return node.tag.type === 'MemberExpression' && ((_node$tag = node.tag) === null || _node$tag === void 0 ? void 0 : (_node$tag$object = _node$tag.object) === null || _node$tag$object === void 0 ? void 0 : _node$tag$object.name) === 'styled'; }; var isAttrs = function isAttrs(_ref) { var _tag$callee, _tag$callee$property; var tag = _ref.tag; return ((_tag$callee = tag.callee) === null || _tag$callee === void 0 ? void 0 : (_tag$callee$property = _tag$callee.property) === null || _tag$callee$property === void 0 ? void 0 : _tag$callee$property.name) === 'attrs'; }; var getAttrsType = function getAttrsType(node) { var _node$tag2, _node$tag2$arguments, _node$tag2$arguments$; var type = (_node$tag2 = node.tag) === null || _node$tag2 === void 0 ? void 0 : (_node$tag2$arguments = _node$tag2.arguments) === null || _node$tag2$arguments === void 0 ? void 0 : (_node$tag2$arguments$ = _node$tag2$arguments[0]) === null || _node$tag2$arguments$ === void 0 ? void 0 : _node$tag2$arguments$.type; return type === 'FunctionExpression' ? 'func' : type === 'ArrowFunctionExpression' ? 'arrow' : type === 'ObjectExpression' ? 'object' : ''; }; var _require = require('util'), inspect = _require.inspect; var _require2 = require('./constants'), __UNKNOWN_IDENTIFER__ = _require2.__UNKNOWN_IDENTIFER__; module.exports = function (styledComponentsDict, context, name) { return { TaggedTemplateExpression: function TaggedTemplateExpression(node) { var scName = node.parent.id && node.parent.id.name; if (!scName || scName === 'undefined') { var _node$parent$key, _node$parent$parent, _node$parent$parent$p, _node$parent$parent$p2; if (isPlainSTE(node) && ((_node$parent$key = node.parent.key) === null || _node$parent$key === void 0 ? void 0 : _node$parent$key.name) && ((_node$parent$parent = node.parent.parent) === null || _node$parent$parent === void 0 ? void 0 : (_node$parent$parent$p = _node$parent$parent.parent) === null || _node$parent$parent$p === void 0 ? void 0 : (_node$parent$parent$p2 = _node$parent$parent$p.id) === null || _node$parent$parent$p2 === void 0 ? void 0 : _node$parent$parent$p2.name)) { scName = "".concat(node.parent.parent.parent.id.name, ".").concat(node.parent.key.name); } else { return; } } var attrs = []; var tag = ''; var func = function func(inspectee) { return name.includes('anchor-is-valid') && context.report(node, inspect(inspectee || node)); }; // styled(Component)`` || styled.div.attrs(...)`` if (isStyledCallExpression(node)) { // styled(Component)`` if (isStyledFunc(node)) { try { // Handle prop forwarding syntax: styled('button', { shouldForwardProp: ... }) if (node.tag.arguments[0] && node.tag.arguments[0].type === 'Literal' && typeof node.tag.arguments[0].value === 'string') { // This is the styled('button', {...}) syntax with prop forwarding var newName = node.parent.id ? node.parent.id.name : 'UnknownStyledComponent'; var newTag = node.tag.arguments[0].value; styledComponentsDict[newName] = { name: newName, attrs: attrs, tag: newTag }; return; } // Handle regular styled(Component) syntax var ancestorScName = node.tag.arguments[0].name; //styled(motion.div) if (!ancestorScName) { var newName = node.parent.id ? node.parent.id.name : 'UnknownStyledComponent'; var newTag; // Try to extract tag from property if (node.tag.arguments[0].property && node.tag.arguments[0].property.name) { newTag = node.tag.arguments[0].property.name; } // If that fails, try to extract from object.property else if (node.tag.arguments[0].object && node.tag.arguments[0].object.property) { newTag = node.tag.arguments[0].object.property.name; } if (newTag && newName) { styledComponentsDict[newName] = { name: newName, attrs: attrs, tag: newTag }; } } else if (styledComponentsDict[ancestorScName]) { attrs = styledComponentsDict[ancestorScName].attrs; tag = styledComponentsDict[ancestorScName].tag; } } catch (err) {// Fail gracefully for any parsing errors } } // styled.div.attrs(...)`` || styled(Component).attrs(...)`` styledComponentsDict[scName] = { name: scName, attrs: attrs, tag: tag }; } // const A = styled.div`` if (isPlainSTE(node)) { tag = node.tag.property.name; styledComponentsDict[scName] = { name: scName, attrs: attrs, tag: tag }; } } }; };