UNPKG

eslint-plugin-logical-properties

Version:
141 lines (140 loc) 7.12 kB
import { isValidProperty } from '../utils/isValidProperty.js'; import { directionalMappingTransformerFactory, } from './directionalMapping.js'; import { directionalShorthandTransformerFactory, } from './directionalShorthand.js'; import { MustDisablePropertyError } from '../utils/MustDisablePropertyError.js'; import { directionalShorthandMappingTransformerFactory, } from './directionalShorthandMapping.js'; import { directionalDisableTransformerFactory, } from './directionalDisable.js'; import { defaultFunctions, defaultJsxAttributes, defaultKeyframes, defaultResolvers, rulePrefix, } from '../constants.js'; import { directionalValueTransformerFactory, } from './directionalValue.js'; import { configSchema } from '../config.js'; import { propertyTraverseSet } from '../utils/propertyTraverse.js'; import { getValidPropertyName } from '../utils/getValidPropertyName.js'; const getOptional = (input, fallback) => ((input && input.length > 0) ? [...input] : [...fallback]); const isTargetJsxAttribute = (node, names) => (typeof node === 'object' && node !== null && 'type' in node && node.type === 'JSXAttribute' && 'name' in node && !!node.name && typeof node.name === 'object' && node.name !== null && 'type' in node.name && node.name.type === 'JSXIdentifier' && 'name' in node.name && typeof node.name.name === 'string' && names.includes(node.name.name) && 'value' in node && !!node.value && typeof node.value === 'object' && node.value !== null && 'type' in node.value && node.value.type === 'JSXExpressionContainer' && 'expression' in node.value && typeof node.value.expression === 'object' && node.value.expression !== null && 'type' in node.value.expression && node.value.expression.type === 'ObjectExpression'); export const transformDirectionalProperty = (node, context, config, resolvers) => { const { disabled = [], mappings = {}, shorthands = {}, shorthandPairMappings = {}, shorthandMappings = {}, values = {}, } = config; const toDisable = Array.isArray(disabled) ? disabled : [disabled]; const mappingsSources = Object.keys(mappings); const shorthandSources = Object.keys(shorthands); const shorthandPairMappingsSources = Object.keys(shorthandPairMappings); const shorthandMappingsSources = Object.keys(shorthandMappings); const valueSources = Object.keys(values); const transformerFactoryInput = { node, context, config, }; const directionalMappingTransformer = directionalMappingTransformerFactory(transformerFactoryInput); const directionalShorthandTransformer = directionalShorthandTransformerFactory(transformerFactoryInput); const directionalShorthandMappingTransformer = directionalShorthandMappingTransformerFactory(transformerFactoryInput); const directionalDisableTransformer = directionalDisableTransformerFactory(transformerFactoryInput); const directionalValueTransformer = directionalValueTransformerFactory(transformerFactoryInput); for (const property of node.properties) { if (isValidProperty(property)) { const propertyName = getValidPropertyName(property); try { if (mappingsSources.includes(propertyName)) { directionalMappingTransformer(property); } else if (shorthandSources.includes(propertyName) || shorthandPairMappingsSources.includes(propertyName)) { directionalShorthandTransformer(property); } else if (shorthandMappingsSources.includes(propertyName)) { directionalShorthandMappingTransformer(property); } else if (valueSources.includes(propertyName)) { directionalValueTransformer(property); } else if (toDisable.includes(propertyName)) { throw new MustDisablePropertyError(); } } catch (error) { if (error instanceof MustDisablePropertyError) { directionalDisableTransformer(property); } } } } const resolvedObjects = propertyTraverseSet(node, resolvers); for (const object of resolvedObjects) { transformDirectionalProperty(object, context, config, resolvers); } }; export const generateDirectionalRules = (config) => ({ meta: { type: 'problem', fixable: 'code', schema: [configSchema], }, create(context) { const [ruleOptions = {}] = context.options ?? []; const settings = (context.settings?.[rulePrefix] ?? {}); const options = ruleOptions; const nodeFunctionNames = getOptional(options.functions, getOptional(settings.functions, defaultFunctions)); const nodeKeyframesNames = getOptional(options.keyframes, getOptional(settings.keyframes, defaultKeyframes)); const nodeJsxAttributesNames = getOptional(options.jsxAttributes, getOptional(settings.jsxAttributes, defaultJsxAttributes)); const nodeResolvers = getOptional(options.resolvers, getOptional(settings.resolvers, defaultResolvers)); return { JSXAttribute(node) { if (isTargetJsxAttribute(node, nodeJsxAttributesNames)) { transformDirectionalProperty(node.value.expression, context, config, nodeResolvers); } }, CallExpression(node) { if (node.callee.type === 'Identifier' && nodeFunctionNames.includes(node.callee.name)) { for (const rules of node.arguments) { if (rules.type === 'ArrayExpression') { for (const ruleSet of rules.elements) { if (ruleSet?.type === 'ObjectExpression') { transformDirectionalProperty(ruleSet, context, config, []); } } } else if (rules.type === 'ObjectExpression') { transformDirectionalProperty(rules, context, config, nodeResolvers); } } } else if (node.callee.type === 'Identifier' && nodeKeyframesNames.includes(node.callee.name)) { for (const argument of node.arguments) { if (argument.type === 'ObjectExpression') { for (const property of argument.properties) { if (property.type === 'Property' && property.value.type === 'ObjectExpression') { transformDirectionalProperty(property.value, context, config, nodeResolvers); } } } } } }, }; }, });