UNPKG

eslint-plugin-react-native-unistyles

Version:
281 lines (280 loc) 12.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.stylesASTHelpers = exports.StyleSheets = void 0; const utils_1 = require("@typescript-eslint/utils"); const generic_1 = require("./generic"); /** * StyleSheets represents the StyleSheets found in the source code. */ class StyleSheets { styleSheets = {}; /** * Add a StyleSheet to our StyleSheets collections. */ add(styleSheetName, properties) { this.styleSheets[styleSheetName] = properties; } /** * MarkAsUsed marks a rule as used in our source code by removing it from the * specified StyleSheet rules. * * @param fullyQualifiedName - The fully qualified name of the rule (e.g., 'styles.text') */ markAsUsed(fullyQualifiedName) { const nameSplit = fullyQualifiedName.split('.'); const styleSheetName = nameSplit[0]; const styleSheetProperty = nameSplit[1]; if (styleSheetName && this.styleSheets[styleSheetName]) { this.styleSheets[styleSheetName] = this.styleSheets[styleSheetName].filter((property) => { if (property.key.type === utils_1.AST_NODE_TYPES.Identifier) { return property.key.name !== styleSheetProperty; } if (property.key.type === utils_1.AST_NODE_TYPES.Literal) { return property.key.value?.toString() !== styleSheetProperty; } if (property.key.type === utils_1.AST_NODE_TYPES.TemplateLiteral) { const keyString = generic_1.genericUtils.getStringFromTemplateLiteral(property.key); return keyString !== styleSheetProperty; } return true; }); } } /** * GetUnusedReferences returns all collected StyleSheets and their unmarked rules. */ getUnusedReferences() { return this.styleSheets; } } exports.StyleSheets = StyleSheets; exports.stylesASTHelpers = { containsStyleSheetObject(node, objectNames) { if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { const callee = node.callee; if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) { const object = callee.object; if (object.type === utils_1.AST_NODE_TYPES.Identifier) { return objectNames.includes(object.name); } } } return false; }, containsCreateCall(node) { if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { const callee = node.callee; if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression) { // StyleSheet.create const property = callee.property; if (property.type === utils_1.AST_NODE_TYPES.Identifier) { return property.name === 'create'; } // StyleSheet["create"] if (property.type === utils_1.AST_NODE_TYPES.Literal) { return property.value === 'create'; } // StyleSheet[`create`] if (property.type === utils_1.AST_NODE_TYPES.TemplateLiteral) { const propertyName = generic_1.genericUtils.getStringFromTemplateLiteral(property); return propertyName === 'create'; } } } return false; }, isStyleSheetDeclaration(node) { const objectNames = ['StyleSheet']; // has StylesSheet indetifier const hasStyleSheetObject = exports.stylesASTHelpers.containsStyleSheetObject(node, objectNames); // calls create function StyleSheet.create const hasCreateCall = exports.stylesASTHelpers.containsCreateCall(node); return hasStyleSheetObject && hasCreateCall; }, getStyleSheetName(node) { const parent = node.parent; if (parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator) { if (parent.id.type === utils_1.AST_NODE_TYPES.Identifier) { return parent.id.name; } } return undefined; }, getStyleDeclarations(node) { if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { const firstArgument = node.arguments[0]; if (firstArgument?.type === utils_1.AST_NODE_TYPES.ObjectExpression || firstArgument?.type === utils_1.AST_NODE_TYPES.ObjectPattern) { const properties = firstArgument.properties; return properties.filter((property) => property.type === utils_1.AST_NODE_TYPES.Property); } if (firstArgument?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { const body = firstArgument.body; if (body?.type === utils_1.AST_NODE_TYPES.ObjectExpression || body?.type === utils_1.AST_NODE_TYPES.ObjectPattern) { const properties = body.properties; return properties.filter((property) => property.type === utils_1.AST_NODE_TYPES.Property); } if (body.type === utils_1.AST_NODE_TYPES.BlockStatement) { const statements = body.body; const returnStatement = statements.find((body) => body.type === utils_1.AST_NODE_TYPES.ReturnStatement); const argument = returnStatement?.argument; if (argument?.type === utils_1.AST_NODE_TYPES.ObjectExpression || argument?.type === utils_1.AST_NODE_TYPES.ObjectPattern) { const properties = argument.properties; return properties.filter((property) => property.type === utils_1.AST_NODE_TYPES.Property); } } } if (firstArgument?.type === utils_1.AST_NODE_TYPES.FunctionExpression) { const body = firstArgument.body; const statements = body.body; const returnStatement = statements.find((body) => body.type === utils_1.AST_NODE_TYPES.ReturnStatement); const argument = returnStatement?.argument; if (argument?.type === utils_1.AST_NODE_TYPES.ObjectExpression || argument?.type === utils_1.AST_NODE_TYPES.ObjectPattern) { const properties = argument.properties; return properties.filter((property) => property.type === utils_1.AST_NODE_TYPES.Property); } } } return []; }, getStyleDeclarationsChunks(node) { const getChunks = (properties) => { const result = []; let chunk = []; for (const property of properties) { if (property.type === utils_1.AST_NODE_TYPES.Property) { chunk.push(property); } else if (chunk.length) { result.push(chunk); chunk = []; } } if (chunk.length) { result.push(chunk); } return result; }; if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { const firstArgument = node.arguments[0]; // example StyleSheet.create( { ... } ) if (firstArgument?.type === utils_1.AST_NODE_TYPES.ObjectExpression) { const properties = firstArgument.properties; return getChunks(properties); } // example StyleSheet.create(() => ( { ... } )) // example StyleSheet.create(() => { return { ... } }) if (firstArgument?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { const body = firstArgument.body; // example StyleSheet.create(() => ( { ... } )) if (body?.type === utils_1.AST_NODE_TYPES.ObjectExpression) { const properties = body.properties; return getChunks(properties); } // example StyleSheet.create(() => { return { ... } }) if (body.type === utils_1.AST_NODE_TYPES.BlockStatement) { const statements = body.body; const returnStatement = statements.find((body) => body.type === utils_1.AST_NODE_TYPES.ReturnStatement); const argument = returnStatement?.argument; if (argument?.type === utils_1.AST_NODE_TYPES.ObjectExpression) { const properties = argument.properties; return getChunks(properties); } } } // example StyleSheet.create(function () { ... }) // example2 StyleSheet.create(function namedfunc() { ... }) if (firstArgument?.type === utils_1.AST_NODE_TYPES.FunctionExpression) { const body = firstArgument.body; const statements = body.body; const returnStatement = statements.find((body) => body.type === utils_1.AST_NODE_TYPES.ReturnStatement); const argument = returnStatement?.argument; if (argument?.type === utils_1.AST_NODE_TYPES.ObjectExpression) { const properties = argument.properties; return getChunks(properties); } } } return []; }, getPropertiesChunks(properties) { const result = []; let chunk = []; for (const property of properties) { if (property.type === utils_1.AST_NODE_TYPES.Property) { chunk.push(property); } else if (chunk.length) { result.push(chunk); chunk = []; } } if (chunk.length) { result.push(chunk); } return result; }, getExpressionIdentifier(node) { if (node) { switch (node.type) { case 'Identifier': return node.name; case 'Literal': return node.value?.toString() ?? ''; case 'TemplateLiteral': return generic_1.genericUtils.getStringFromTemplateLiteral(node) ?? ''; default: return ''; } } return ''; }, getStylePropertyIdentifier(node) { if (node.key) { return exports.stylesASTHelpers.getExpressionIdentifier(node.key); } return undefined; }, // example: styles.text & styles['text'] & styles[`text`] getPotentialStyleReferenceFromMemberExpression(node) { if (node.parent.type === utils_1.AST_NODE_TYPES.MemberExpression) return undefined; let objectName; if (node.object.type === utils_1.AST_NODE_TYPES.Identifier) { objectName = node.object.name; } if (node.object.type === utils_1.AST_NODE_TYPES.Literal) { objectName = node.object.value?.toString(); } if (node.object.type === utils_1.AST_NODE_TYPES.TemplateLiteral) { objectName = generic_1.genericUtils.getStringFromTemplateLiteral(node.object); } let propertyName; if (node.property.type === utils_1.AST_NODE_TYPES.Identifier) { propertyName = node.property.name; } if (node.property.type === utils_1.AST_NODE_TYPES.Literal) { propertyName = node.property.value?.toString(); } if (node.property.type === utils_1.AST_NODE_TYPES.TemplateLiteral) { propertyName = generic_1.genericUtils.getStringFromTemplateLiteral(node.property); } if (objectName && propertyName) { return `${objectName}.${propertyName}`; } return undefined; }, // example: margin vs marginTop isEitherShortHand(property1, property2) { const shorthands = ['margin', 'padding', 'border', 'flex']; if (shorthands.includes(property1)) { return property2.startsWith(property1); } if (shorthands.includes(property2)) { return property1.startsWith(property2); } return false; }, };