@tenphi/eslint-plugin-tasty 1.12.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport type { RuleContext } from '@typescript-eslint/utils/ts-eslint';\nimport type { ResolvedConfig, StyleFunctionConfig } from './types.js';\nimport { loadConfig } from './config.js';\nimport {\n DEFAULT_IMPORT_SOURCES,\n KNOWN_CSS_PROPERTIES,\n KNOWN_TASTY_PROPERTIES,\n SPECIAL_STYLE_KEYS,\n} from './constants.js';\nimport {\n collectLocalStateAliases,\n getKeyName,\n unwrapExpression,\n wildcardPattern,\n} from './utils.js';\nimport { finishJSXAnalysis, jsxPropKind } from './type-aware-jsx.js';\nimport { isModuleTastyComponent } from './module-components.js';\n\n/**\n * Every object is considered, then TastyContext gates it by its actual context.\n * Narrow ancestry selectors miss nested shared styles and wrapped JSX values.\n */\nexport const STYLE_OBJECT_SELECTORS = ['ObjectExpression'] as const;\n\n/** One listener per object; context recognition remains the caller's gate. */\nexport function styleObjectListeners(\n handler: (node: TSESTree.ObjectExpression) => void,\n): Record<string, (node: TSESTree.ObjectExpression) => void> {\n return { ObjectExpression: handler };\n}\n\nexport interface StyleContext {\n type: 'tasty' | 'tastyStatic' | 'useStyles' | 'useGlobalStyles';\n isStaticCall: boolean;\n isSelectorMode: boolean;\n isExtending: boolean;\n /**\n * Local name of the component this layer extends, when there is one and it is\n * an identifier. `null` covers every other case — a base definition, a\n * selector, or a layer whose base cannot be read off the AST — so a rule that\n * cares must treat `null` as \"unknown\", not as \"not extending\".\n */\n baseComponent: string | null;\n}\n\nexport interface TastyImport {\n localName: string;\n importedName: string;\n source: string;\n}\n\n/**\n * Whether a type annotation names tasty's `Styles` anywhere inside it.\n *\n * Walks the annotation rather than matching only the outermost reference, so a\n * wrapped tasty type (`Styles | undefined`, `Array<Styles>`) is recognised while\n * `CSSProperties` in the same positions is not. Maps of styles are told apart\n * first by `stylesAnnotationShape`. Deliberately name-based: the plugin has no type checker, and requiring one\n * would make every rule type-aware.\n */\nfunction referencesStylesType(node: TSESTree.TypeNode): boolean {\n const stack: TSESTree.Node[] = [node];\n\n while (stack.length) {\n const current = stack.pop()!;\n\n if (\n current.type === 'TSTypeReference' &&\n current.typeName.type === 'Identifier' &&\n /^Styles$/i.test(current.typeName.name)\n ) {\n return true;\n }\n\n for (const value of Object.values(\n current as unknown as Record<string, unknown>,\n )) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && 'type' in item) {\n stack.push(item as TSESTree.Node);\n }\n }\n } else if (value && typeof value === 'object' && 'type' in value) {\n // Skip `parent` — it points back up the tree and would loop forever.\n if (value !== (current as TSESTree.Node).parent) {\n stack.push(value as TSESTree.Node);\n }\n }\n }\n }\n\n return false;\n}\n\n/** Utility types whose result has the same shape as their argument. */\nconst SHAPE_PRESERVING_TYPES = new Set([\n 'Readonly',\n 'Partial',\n 'Required',\n 'NonNullable',\n]);\n\n/**\n * What a `Styles`-bearing annotation declares: `'styles'` for a style object,\n * `'map'` for an object whose *values* are style objects (`Record<K, Styles>`,\n * `{ [k: string]: Styles }`, `{ root: Styles }`), `null` when `Styles` does not\n * appear at all.\n *\n * The distinction matters for a map: its keys are variant or block names, so\n * checking the map itself as a style object reports every one of them as an\n * unknown property, while the style objects it holds go unchecked.\n */\nfunction stylesAnnotationShape(\n node: TSESTree.TypeNode,\n): 'styles' | 'map' | null {\n if (node.type === 'TSUnionType' || node.type === 'TSIntersectionType') {\n const shapes = node.types.map(stylesAnnotationShape);\n if (shapes.includes('styles')) return 'styles';\n return shapes.includes('map') ? 'map' : null;\n }\n\n if (node.type === 'TSTypeReference' && node.typeName.type === 'Identifier') {\n const name = node.typeName.name;\n const args = node.typeArguments?.params ?? [];\n\n if (/^Styles$/i.test(name)) return 'styles';\n if (name === 'Record' && args.length === 2) {\n if (stylesAnnotationShape(args[1]) === 'styles') return 'map';\n }\n if (SHAPE_PRESERVING_TYPES.has(name) && args.length === 1) {\n return stylesAnnotationShape(args[0]);\n }\n }\n\n if (node.type === 'TSTypeLiteral') {\n const holdsStyles = node.members.some(\n (member) =>\n (member.type === 'TSIndexSignature' ||\n member.type === 'TSPropertySignature') &&\n member.typeAnnotation !== undefined &&\n stylesAnnotationShape(member.typeAnnotation.typeAnnotation) ===\n 'styles',\n );\n if (holdsStyles) return 'map';\n }\n\n return referencesStylesType(node) ? 'styles' : null;\n}\n\n/**\n * Whether a key could plausibly be a tasty style key.\n *\n * Covers every top-level shape tasty accepts: a style property, a sub-element\n * (capitalised), an at-rule or state/custom-property/colour key (`@`, `&`, `$`,\n * `#`), and the default-state key.\n */\nfunction isPlausibleStyleKey(key: string): boolean {\n if (key === '' || key === '_') return true;\n if (/^[A-Z]/.test(key)) return true;\n if (/^[@&$#]/.test(key)) return true;\n if (SPECIAL_STYLE_KEYS.has(key)) return true;\n\n return KNOWN_TASTY_PROPERTIES.has(key) || KNOWN_CSS_PROPERTIES.has(key);\n}\n\n/**\n * Whether an object is a map of named CSS blocks rather than a tasty styles object.\n *\n * The shape is unmistakable — `{ table: {…}, th: {…}, td: {…} }`, `{ root: {…},\n * toolbar: {…} }` — and it is what a React inline-style map looks like when it\n * carries no type annotation to opt it out. Every key is a block name that is not a\n * style key, and every value is an object.\n *\n * Requiring *every* value to be an object literal is what keeps this from swallowing\n * the case it would hurt most: `const styles = { colour: 'red' }` has a string value,\n * so it is not treated as a block map and `known-property` still reports the typo.\n * Otherwise the rule that catches a misspelled property would be silenced by the\n * misspelling.\n */\nfunction isNamedCssBlockMap(node: TSESTree.ObjectExpression): boolean {\n if (node.properties.length === 0) return false;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) return false;\n\n const key = getKeyName(prop.key);\n\n if (key === null || isPlausibleStyleKey(key)) return false;\n if (prop.value.type !== 'ObjectExpression') return false;\n }\n\n return true;\n}\n\n/**\n * The outermost expression an object is the result of through conditional and\n * logical operators (and type wrappers): `cond ? { … } : null`, `cond && { … }`,\n * `styles ?? { … }`. Whatever position that expression takes, the object may\n * land in. The test of a conditional and the left of `&&` never become the\n * value, so they are not followed.\n */\nfunction conditionalFlowRoot(node: TSESTree.Node): TSESTree.Node {\n let current = node;\n // Matching unwraps type wrappers itself, so the root is the outermost\n // operator, not a wrapper around it.\n let root = node;\n while (current.parent) {\n const parent: TSESTree.Node = current.parent;\n if (\n (parent.type === 'TSAsExpression' ||\n parent.type === 'TSSatisfiesExpression' ||\n parent.type === 'TSNonNullExpression' ||\n parent.type === 'TSTypeAssertion') &&\n parent.expression === current\n ) {\n current = parent;\n } else if (\n (parent.type === 'ConditionalExpression' && parent.test !== current) ||\n (parent.type === 'LogicalExpression' &&\n (parent.right === current || parent.operator !== '&&'))\n ) {\n current = root = parent;\n } else {\n break;\n }\n }\n return root;\n}\n\n/**\n * The component a `styles` JSX prop overrides — `<Card styles={…} />` -> `Card`.\n * A namespaced tag (`<UI.Card />`) resolves to its root object, since that is the\n * name an import can be matched against.\n */\nfunction jsxStylesPropTarget(node: TSESTree.Node): string | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const container = wrapped.parent;\n if (container?.type !== 'JSXExpressionContainer') return null;\n\n const attribute = container.parent;\n if (attribute?.type !== 'JSXAttribute') return null;\n\n const element = attribute.parent;\n if (element?.type !== 'JSXOpeningElement') return null;\n\n let name: TSESTree.JSXTagNameExpression = element.name;\n while (name.type === 'JSXMemberExpression') name = name.object;\n\n return name.type === 'JSXIdentifier' ? name.name : null;\n}\n\n/**\n * The identifier a base-component argument resolves to — `tasty(UI.Card, {…})`\n * -> `UI`, which is what the import map is keyed by.\n *\n * Type assertions are stripped on the way down. Reading `Button as any` as an\n * unknown base would quietly promote an imported component to \"owned\", which is\n * the reading that produces a warning the author cannot act on.\n */\nfunction baseComponentName(node: TSESTree.Node): string | null {\n let current = unwrapExpression(node);\n\n while (current.type === 'MemberExpression') {\n current = unwrapExpression(current.object);\n }\n\n return current.type === 'Identifier' ? current.name : null;\n}\n\n/**\n * Whether `source` is inside this project. Relative and absolute specifiers are,\n * as are the conventional in-repo aliases (`~/`, `#internal`, `@/`) — `@` alone\n * is not, since `@scope/pkg` is a published package.\n */\nfunction isInRepoSource(source: string): boolean {\n return (\n source.startsWith('.') ||\n source.startsWith('/') ||\n source.startsWith('~') ||\n source.startsWith('#') ||\n source.startsWith('@/')\n );\n}\n\n/** `settings.tasty.mergeFunctions`: project helpers with `mergeStyles` semantics. */\nfunction readMergeFunctions(\n context: RuleContext<string, unknown[]>,\n): ReadonlySet<string> {\n const settings = context.settings?.tasty as\n | { mergeFunctions?: unknown }\n | undefined;\n const option = settings?.mergeFunctions;\n if (option === undefined) return new Set();\n if (\n !Array.isArray(option) ||\n option.some((name) => typeof name !== 'string')\n ) {\n throw new Error(\n 'tasty: mergeFunctions must be an array of function names.',\n );\n }\n return new Set(option);\n}\n\nconst TASTY_FUNCTION_NAMES = new Set([\n 'tasty',\n 'tastyStatic',\n 'useStyles',\n 'useGlobalStyles',\n 'mergeStyles',\n 'configure',\n]);\n\n/**\n * Context tracker for a single file's lint pass.\n * Tracks which imports come from tasty and provides\n * helpers to determine if a node is in a tasty style context.\n */\nexport class TastyContext {\n readonly config: ResolvedConfig;\n private imports = new Map<string, TastyImport>();\n private moduleSources = new Map<string, string>();\n private importSources: Set<string>;\n private mergeFunctions: ReadonlySet<string>;\n private relativeComponents = new Map<string, boolean>();\n private resolving = new Set<TSESTree.Node>();\n\n constructor(\n private context: RuleContext<string, unknown[]>,\n config?: ResolvedConfig,\n ) {\n this.config = config ?? loadConfig(context.filename);\n this.importSources = new Set([\n ...DEFAULT_IMPORT_SOURCES,\n ...this.config.importSources,\n ]);\n this.mergeFunctions = readMergeFunctions(context);\n }\n\n trackImport(node: TSESTree.ImportDeclaration): void {\n const source = node.source.value;\n\n // Every import is recorded, tasty or not. Where a *base component* comes\n // from is what tells a rule whether the file it would send the author to\n // edit is even theirs — see `isOwnedComponent`.\n for (const specifier of node.specifiers) {\n this.moduleSources.set(specifier.local.name, source);\n }\n\n if (!this.importSources.has(source) || node.importKind === 'type') return;\n\n for (const specifier of node.specifiers) {\n if (\n specifier.type === 'ImportSpecifier' &&\n specifier.importKind !== 'type'\n ) {\n const importedName =\n specifier.imported.type === 'Identifier'\n ? specifier.imported.name\n : specifier.imported.value;\n if (\n TASTY_FUNCTION_NAMES.has(importedName) ||\n Object.hasOwn(this.config.styleFunctions ?? {}, importedName)\n ) {\n this.imports.set(specifier.local.name, {\n localName: specifier.local.name,\n importedName,\n source,\n });\n }\n }\n }\n }\n\n isComponentJSXProp(node: TSESTree.JSXAttribute): boolean {\n return jsxPropKind(this.context, node) === 'component';\n }\n\n finishJSXAnalysis(): void {\n finishJSXAnalysis(this.context);\n }\n\n getImport(localName: string): TastyImport | undefined {\n return this.imports.get(localName);\n }\n\n /** The built-in and configured `importSources`. */\n get trackedSources(): ReadonlySet<string> {\n return this.importSources;\n }\n\n /**\n * Whether the base component an extension layer sits on top of lives in a file\n * this project can edit — so a rule can decide whether pointing the author at\n * the base's own definition is advice they can act on.\n *\n * A name that was never imported is declared in this very file, and an unknown\n * base (`null`) counts as owned as well: staying quiet is for a base that is\n * demonstrably someone else's, never for one the plugin merely failed to read.\n */\n isOwnedComponent(localName: string | null): boolean {\n if (localName === null) return true;\n\n const source = this.moduleSources.get(localName);\n if (source === undefined) return true;\n if (isInRepoSource(source)) return true;\n\n // `ownedSources` is optional on the public `ResolvedConfig`, so a config\n // built by a consumer rather than by `loadConfig` may not carry it.\n return (this.config.ownedSources ?? []).some((pattern) =>\n wildcardPattern(pattern).test(source),\n );\n }\n\n isTastyCall(node: TSESTree.CallExpression): TastyImport | undefined {\n const callee = unwrapExpression(node.callee);\n if (callee.type !== 'Identifier') return undefined;\n const imp = this.imports.get(callee.name);\n if (!imp) return undefined;\n\n // A parameter or local declaration can shadow the imported helper. Only\n // the import binding carries evidence that the call accepts Tasty styles.\n let scope = this.context.sourceCode.getScope(callee);\n while (scope) {\n const variable = scope.set.get(callee.name);\n if (variable) {\n return variable.defs.some((def) => def.type === 'ImportBinding')\n ? imp\n : undefined;\n }\n if (!scope.upper) break;\n scope = scope.upper;\n }\n return undefined;\n }\n\n /**\n * `mergeStyles(...)`, or a call to a project helper named in\n * `settings.tasty.mergeFunctions`. A helper matches by its imported name, so\n * an aliased import still counts, or by the name it is declared under in this\n * file; a parameter of the same name shadows it.\n */\n isMergeStylesCall(node: TSESTree.CallExpression): boolean {\n if (this.isTastyCall(node)?.importedName === 'mergeStyles') return true;\n if (this.mergeFunctions.size === 0) return false;\n\n const callee = unwrapExpression(node.callee);\n if (callee.type !== 'Identifier') return false;\n\n let scope = this.context.sourceCode.getScope(callee);\n while (scope) {\n const variable = scope.set.get(callee.name);\n if (variable) {\n return variable.defs.some((def) => {\n if (def.type === 'FunctionName' || def.type === 'Variable') {\n return this.mergeFunctions.has(callee.name);\n }\n if (\n def.type !== 'ImportBinding' ||\n def.parent.type !== 'ImportDeclaration' ||\n def.parent.importKind === 'type'\n ) {\n return false;\n }\n if (def.node.type === 'ImportDefaultSpecifier') {\n return this.mergeFunctions.has(callee.name);\n }\n if (def.node.type !== 'ImportSpecifier') return false;\n if (def.node.importKind === 'type') return false;\n const imported = def.node.imported;\n return this.mergeFunctions.has(\n imported.type === 'Identifier' ? imported.name : imported.value,\n );\n });\n }\n if (!scope.upper) break;\n scope = scope.upper;\n }\n // An undeclared global, such as an auto-imported helper.\n return this.mergeFunctions.has(callee.name);\n }\n\n /** Local factory results, const aliases, and configured component imports. */\n isTastyJSXComponent(node: TSESTree.Node, name: string): boolean {\n const visited = new Set<TSESTree.VariableDeclarator>();\n const resolve = (reference: TSESTree.Node, localName: string): boolean => {\n let scope = this.context.sourceCode.getScope(reference);\n while (scope) {\n const variable = scope.set.get(localName);\n if (variable) {\n return variable.defs.some((def) => {\n if (def.type === 'ImportBinding') {\n if (\n def.parent.type !== 'ImportDeclaration' ||\n def.parent.importKind === 'type' ||\n (def.node.type === 'ImportSpecifier' &&\n def.node.importKind === 'type')\n ) {\n return false;\n }\n const source = def.parent.source.value;\n if (this.importSources.has(source)) return true;\n return this.isRelativeTastyImport(source, def.node);\n }\n if (def.type !== 'Variable') return false;\n const declaration = def.node;\n if (\n declaration.id.type !== 'Identifier' ||\n declaration.parent.kind !== 'const' ||\n !declaration.init ||\n visited.has(declaration)\n )\n return false;\n visited.add(declaration);\n const init = unwrapExpression(declaration.init);\n if (init.type === 'Identifier') return resolve(init, init.name);\n if (init.type === 'MemberExpression' && !init.computed) {\n let member: TSESTree.Node = init;\n while (member.type === 'MemberExpression') {\n if (member.computed) return false;\n member = unwrapExpression(member.object);\n }\n const root = baseComponentName(init);\n return root !== null && resolve(init, root);\n }\n if (init.type !== 'CallExpression') return false;\n const imp = this.isTastyCall(init);\n return (\n imp?.importedName === 'tasty' ||\n (imp !== undefined &&\n this.config.styleFunctions?.[imp.importedName]?.kind ===\n 'options')\n );\n });\n }\n if (!scope.upper) break;\n scope = scope.upper;\n }\n return false;\n };\n return resolve(node, name);\n }\n\n /**\n * Whether a binding imported from a relative module names a Tasty component\n * declared there — `import { Panel } from './styled'`. A namespace import has\n * no single export to follow.\n */\n private isRelativeTastyImport(\n source: string,\n specifier: TSESTree.Node,\n ): boolean {\n if (\n specifier.type !== 'ImportSpecifier' &&\n specifier.type !== 'ImportDefaultSpecifier'\n ) {\n return false;\n }\n const exportName =\n specifier.type === 'ImportDefaultSpecifier'\n ? 'default'\n : specifier.imported.type === 'Identifier'\n ? specifier.imported.name\n : specifier.imported.value;\n const key = `${source}\\0${exportName}`;\n let result = this.relativeComponents.get(key);\n if (result === undefined) {\n result = isModuleTastyComponent(\n this.context.filename,\n source,\n exportName,\n {\n importSources: this.importSources,\n isComponentFactory: (name) =>\n name === 'tasty' ||\n this.config.styleFunctions?.[name]?.kind === 'options',\n },\n );\n this.relativeComponents.set(key, result);\n }\n return result;\n }\n\n /**\n * Determines whether an object expression is a tasty style object\n * by walking up the AST to find a recognized call expression.\n */\n isStyleObject(node: TSESTree.ObjectExpression): boolean {\n return this.getStyleContext(node) !== null;\n }\n\n private getSubElementParent(\n node: TSESTree.Node,\n ): TSESTree.ObjectExpression | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const parent = wrapped.parent;\n if (parent?.type !== 'Property' || parent.computed) return null;\n const key = getKeyName(parent.key);\n return key &&\n /^[A-Z]/.test(key) &&\n parent.parent.type === 'ObjectExpression'\n ? parent.parent\n : null;\n }\n\n /** Follow only sub-elements of recognized styles, never a variants container. */\n getRootStyleObject(\n node: TSESTree.ObjectExpression,\n ): TSESTree.ObjectExpression {\n let current = node;\n while (true) {\n const parent = this.getSubElementParent(current);\n if (!parent || !this.isStyleObject(parent)) return current;\n current = parent;\n }\n }\n\n /**\n * The `mergeStyles(...)` call, or configured merge helper call, this object\n * is a direct argument of, if any.\n */\n private getMergeStylesCall(\n node: TSESTree.ObjectExpression,\n ): TSESTree.CallExpression | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const call = wrapped.parent;\n return call?.type === 'CallExpression' &&\n call.arguments.includes(wrapped as TSESTree.CallExpressionArgument) &&\n this.isMergeStylesCall(call)\n ? call\n : null;\n }\n\n /**\n * Local `@name` state aliases visible to a style object, the way Tasty\n * resolves them: the object's own, then those of each enclosing sub-element\n * up to the root. A `mergeStyles(...)` argument stands for the merged object,\n * so every object argument of the call contributes, and a call that is a\n * sub-element value sees the aliases of the styles it sits in.\n */\n getLocalStateAliases(node: TSESTree.ObjectExpression): string[] {\n const aliases = new Set<string>();\n let current: TSESTree.ObjectExpression | null = node;\n\n while (current) {\n const call = this.getMergeStylesCall(current);\n const scope = call\n ? call.arguments\n .map((arg) => unwrapExpression(arg))\n .filter(\n (arg): arg is TSESTree.ObjectExpression =>\n arg.type === 'ObjectExpression',\n )\n : [current];\n for (const object of scope) {\n for (const alias of collectLocalStateAliases(object))\n aliases.add(alias);\n }\n\n const parent = this.getSubElementParent(call ?? current);\n current = parent && this.isStyleObject(parent) ? parent : null;\n }\n\n return [...aliases];\n }\n\n /**\n * Whether the style object this node belongs to is declared on its own — a\n * `const CELL_STYLES: Styles` or a value of a `Record<K, Styles>` — rather\n * than handed to a call or prop. Such styles can be spread anywhere,\n * including into a sub-element, so their root is not necessarily the\n * component's root.\n */\n isSharedStyleObject(node: TSESTree.ObjectExpression): boolean {\n const outermost = (inner: TSESTree.Node): TSESTree.Node => {\n let wrapped = inner;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === inner) {\n wrapped = wrapped.parent;\n }\n return wrapped;\n };\n\n let parent = outermost(this.getRootStyleObject(node)).parent;\n if (\n parent?.type === 'Property' &&\n parent.parent.type === 'ObjectExpression'\n ) {\n parent = outermost(parent.parent).parent;\n }\n return parent?.type === 'VariableDeclarator';\n }\n\n /** Include helper calls nested inside a real sub-element, but not variant names. */\n isInsideSubElement(node: TSESTree.Node): boolean {\n let current = node.parent;\n while (current) {\n if (current.type === 'Property' && !current.computed) {\n const key = getKeyName(current.key);\n if (\n key &&\n /^[A-Z]/.test(key) &&\n current.parent.type === 'ObjectExpression' &&\n this.isStyleObject(current.parent)\n ) {\n return true;\n }\n }\n current = current.parent;\n }\n return false;\n }\n\n /**\n * The style context of an object, or of any expression standing where a\n * style object goes. Besides objects written in place, this covers an object\n * that reaches a style position only through a conditional or logical\n * operator (`mergeStyles(cond ? { … } : null, styles)`), and one held in a\n * render-scope variable that is then passed on (`const local = { … }`,\n * `styles = { ...styles, … }`, then `styles={local}`): Tasty receives each of\n * them as styles all the same.\n */\n getStyleContext(node: TSESTree.Node): StyleContext | null {\n // A binding can lead back into the object being resolved (`a = { X: a }`).\n if (this.resolving.has(node)) return null;\n this.resolving.add(node);\n try {\n if (node.type === 'ObjectExpression') {\n const flow = conditionalFlowRoot(node);\n if (flow !== node) return this.getStyleContext(flow);\n }\n return (\n this.getDirectStyleContext(node) ?? this.getBindingStyleContext(node)\n );\n } finally {\n this.resolving.delete(node);\n }\n }\n\n /**\n * The context of a value held in a render-scope variable, taken from the\n * first place the variable is read as styles. Module-scope bindings are\n * shared values and are left to the declaration heuristics.\n */\n private getBindingStyleContext(node: TSESTree.Node): StyleContext | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const holder = wrapped.parent;\n let target: TSESTree.Identifier | null = null;\n if (\n holder?.type === 'VariableDeclarator' &&\n holder.init === wrapped &&\n holder.id.type === 'Identifier'\n ) {\n target = holder.id;\n } else if (\n holder?.type === 'AssignmentExpression' &&\n holder.operator === '=' &&\n holder.right === wrapped &&\n holder.left.type === 'Identifier'\n ) {\n target = holder.left;\n }\n if (!target) return null;\n\n let scope = this.context.sourceCode.getScope(target);\n while (!scope.set.has(target.name) && scope.upper) scope = scope.upper;\n const variable = scope.set.get(target.name);\n if (!variable || scope.type === 'module' || scope.type === 'global') {\n return null;\n }\n\n for (const reference of variable.references ?? []) {\n if (!reference.isRead() || reference.identifier === target) continue;\n const context = this.getStyleContext(reference.identifier);\n if (context) return context;\n }\n return null;\n }\n\n private getDirectStyleContext(node: TSESTree.Node): StyleContext | null {\n // Sub-element objects inherit their parent style object's context\n const parent = this.getSubElementParent(node);\n if (parent) {\n const inherited = this.getStyleContext(parent);\n if (inherited) return inherited;\n }\n\n // An object assigned to a `styles` key (or a `styles` JSX prop) is a style\n // object on its own terms — no enclosing tasty call or `styles`-ish variable\n // name required. Checked before the walk, which would otherwise climb past it\n // to an unrelated call or declaration and reject the whole thing.\n if (this.isStylesPropertyValue(node)) {\n // A `styles` prop is an override layer by construction: the component it\n // is handed to already carries its own styles and this object lands on\n // top of them. A Storybook `args.styles` is the same prop by another name,\n // but the component behind `args` is not on the AST path, so its base\n // stays unknown.\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: true,\n baseComponent: jsxStylesPropTarget(node),\n };\n }\n\n let current: TSESTree.Node | undefined = node;\n\n while (current) {\n if (current.type === 'CallExpression') {\n if (this.isMergeStylesCall(current)) {\n return this.getMergeStylesContext(current, node);\n }\n\n const imp = this.isTastyCall(current);\n if (!imp) return null;\n\n const name = imp.importedName;\n const isStaticCall = name === 'tastyStatic';\n\n if (name === 'tasty') {\n return this.getTastyCallContext(current, node);\n }\n\n if (name === 'tastyStatic') {\n return this.getTastyStaticCallContext(current, node);\n }\n\n if (name === 'useStyles') {\n if (current.arguments[0] === node) {\n return {\n type: 'useStyles',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n }\n\n if (name === 'useGlobalStyles') {\n if (current.arguments[1] === node) {\n return {\n type: 'useGlobalStyles',\n isStaticCall,\n isSelectorMode: true,\n isExtending: false,\n baseComponent: null,\n };\n }\n }\n\n // Built-in signatures always take precedence over configured ones.\n const custom = this.config.styleFunctions?.[name];\n if (!TASTY_FUNCTION_NAMES.has(name) && custom) {\n return this.getCustomCallContext(current, node, custom);\n }\n\n return null;\n }\n\n if (this.isStyleVariableDeclaration(current, node)) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n\n current = current.parent;\n }\n\n return null;\n }\n\n private isStyleVariableDeclaration(\n current: TSESTree.Node,\n targetNode: TSESTree.Node,\n ): boolean {\n if (\n current.type !== 'VariableDeclarator' ||\n current.id.type !== 'Identifier'\n ) {\n return false;\n }\n\n let init: TSESTree.Node | null | undefined = current.init;\n while (\n init?.type === 'TSAsExpression' ||\n init?.type === 'TSSatisfiesExpression' ||\n init?.type === 'TSTypeAssertion' ||\n init?.type === 'TSNonNullExpression'\n ) {\n init = (init as TSESTree.TSAsExpression).expression;\n }\n\n // An explicit type annotation is authoritative, in both directions, and is\n // read before anything about the name. The name heuristics below are a\n // guess; a declared type is the author stating what the object is, so it\n // wins — `const CARD_STYLES: Styles` is as much a style object as\n // `const cardStyles: Styles`.\n //\n // This matters because the rewrites these rules offer are only valid *inside*\n // tasty: `#purple.05` and `$font-sans` are correct tasty declarations and\n // meaningless as raw CSS. A `const styles: Record<string, CSSProperties>`\n // handed to React's `style={…}` was matched on name alone, so its plain CSS\n // longhands were reported as tasty violations — and `--fix` rewrote real\n // `var(--shadow-sm-color)` to `#shadow-sm`, which nothing resolves there, so\n // the browser dropped the declaration.\n const annotated = this.stylesTypeAnnotation(current);\n\n // A map of style objects: its values are checked, never the map itself.\n if (annotated === 'map') {\n return (\n init?.type === 'ObjectExpression' &&\n init.properties.some(\n (prop) =>\n prop.type === 'Property' &&\n unwrapExpression(prop.value) === targetNode,\n )\n );\n }\n\n if (init !== targetNode) return false;\n if (annotated !== null) return annotated === 'styles';\n\n const name = current.id.name;\n\n // Unannotated constants are shared values, not style objects by name alone.\n if (/^[A-Z][A-Z0-9_]*$/.test(name)) return false;\n\n // Only `styles` and `*Styles` count. The singular `style` is conventionally\n // a DOM inline-style object (`el.style`, `CSSProperties`, `setStyle(el, …)`)\n // holding raw CSS longhands, not tasty syntax — matching it reported those\n // longhands as tasty violations.\n if (name === 'styles' || name.endsWith('Styles')) {\n // The name is the weakest evidence there is, so let an unmistakable shape\n // overrule it. Without an annotation to go on, a map of named CSS blocks was\n // reported as tasty — `known-property` on every HTML tag name, each block read\n // as a state map — and `--fix` offered rewrites that are only valid inside\n // tasty.\n return !(\n targetNode.type === 'ObjectExpression' && isNamedCssBlockMap(targetNode)\n );\n }\n\n return false;\n }\n\n private getCustomCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n config: StyleFunctionConfig,\n ): StyleContext | null {\n const { argument, kind } = config;\n if (argument !== 'all' && (!Number.isInteger(argument) || argument < 0)) {\n return null;\n }\n // A preceding spread makes the runtime argument index unknown. Never apply\n // style rewrites to an object that might occupy a different parameter.\n if (\n argument !== 'all' &&\n call.arguments\n .slice(0, argument)\n .some((arg) => arg.type === 'SpreadElement')\n ) {\n return null;\n }\n\n const args =\n argument === 'all' ? call.arguments : [call.arguments[argument]];\n for (const arg of args) {\n if (!arg) continue;\n const value = unwrapExpression(arg);\n if (value.type !== 'ObjectExpression') continue;\n\n const isVariant =\n kind === 'options' && this.isInsideVariantsProperty(value, targetNode);\n const matches =\n kind === 'styles'\n ? value === targetNode\n : kind === 'options' &&\n (this.isInsideStylesProperty(value, targetNode) || isVariant);\n\n if (matches) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: !isVariant && (config.partial ?? false),\n baseComponent: null,\n };\n }\n }\n\n return null;\n }\n\n /**\n * Verdict from the declared type: `'styles'` the object is tasty, `'map'` its\n * values are, `false` explicitly neither, `null` when there is no annotation to\n * go on and the caller should fall back to the name.\n *\n * A `Styles` reference anywhere in the annotation counts, so wrappers like\n * `Styles | undefined` and `Record<string, Styles>` opt in — while\n * `CSSProperties`, `Record<string, CSSProperties>` and an inline literal of\n * them opt out.\n */\n private stylesTypeAnnotation(\n node: TSESTree.VariableDeclarator,\n ): 'styles' | 'map' | false | null {\n const annotation = node.id.typeAnnotation?.typeAnnotation;\n\n if (!annotation) return null;\n\n return stylesAnnotationShape(annotation) ?? false;\n }\n\n private getTastyCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tasty({ styles: { ... } }) or tasty(Component, { styles: { ... } })\n const isExtending =\n args.length >= 2 && unwrapExpression(args[0]).type !== 'ObjectExpression';\n const optionsArg = isExtending ? args[1] : args[0];\n\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideStylesProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending,\n baseComponent: isExtending ? baseComponentName(args[0]) : null,\n };\n }\n\n // Check if inside variants\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideVariantsProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n\n return null;\n }\n\n /**\n * Every object argument of `mergeStyles(base, ...overrides)` is a style\n * object. The first is the base; each later one is layered on top, where a\n * state map without `''` extends the one below it rather than replacing it.\n */\n private getMergeStylesContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ): StyleContext | null {\n const index = call.arguments.findIndex(\n (arg) => unwrapExpression(arg) === targetNode,\n );\n if (index === -1) return null;\n\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: index > 0,\n baseComponent: null,\n };\n }\n\n private getTastyStaticCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tastyStatic({ ... })\n if (args.length === 1 && args[0] === targetNode) {\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n\n // tastyStatic(base, { ... }) or tastyStatic('selector', { ... })\n if (args.length === 2 && args[1] === targetNode) {\n const isSelectorMode = unwrapExpression(args[0]).type === 'Literal';\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode,\n isExtending: !isSelectorMode,\n baseComponent: isSelectorMode ? null : baseComponentName(args[0]),\n };\n }\n\n return null;\n }\n\n private isInsideStylesProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n !prop.computed &&\n getKeyName(prop.key) === 'styles' &&\n unwrapExpression(prop.value) === targetNode\n ) {\n return true;\n }\n }\n return false;\n }\n\n private isInsideVariantsProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n !prop.computed &&\n getKeyName(prop.key) === 'variants'\n ) {\n const variants = unwrapExpression(prop.value);\n if (variants.type !== 'ObjectExpression') continue;\n for (const variantProp of variants.properties) {\n if (\n variantProp.type === 'Property' &&\n unwrapExpression(variantProp.value) === targetNode\n ) {\n return true;\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this object is a `styles` JSX prop value or a Storybook `args.styles`.\n *\n * Both are unambiguous enough to stand on their own without an import-tracked\n * call or a `styles`-ish variable name. A bare `styles` key elsewhere is not —\n * see the selector list for why.\n */\n isStylesPropertyValue(node: TSESTree.Node): boolean {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const parent = wrapped.parent;\n\n if (parent?.type === 'Property' && !parent.computed) {\n if (getKeyName(parent.key) !== 'styles') return false;\n\n // Only inside `args: { … }`.\n const argsObject = parent.parent;\n const argsProperty =\n argsObject?.type === 'ObjectExpression' ? argsObject.parent : undefined;\n\n return (\n argsProperty?.type === 'Property' &&\n !argsProperty.computed &&\n getKeyName(argsProperty.key) === 'args'\n );\n }\n\n if (parent?.type === 'JSXExpressionContainer') {\n const attribute = parent.parent;\n\n return (\n attribute?.type === 'JSXAttribute' &&\n attribute.name.type === 'JSXIdentifier' &&\n (attribute.name.name === 'styles' ||\n attribute.name.name.endsWith('Styles'))\n );\n }\n\n return false;\n }\n\n /**\n * Checks if a property value node is a state mapping object\n * (i.e., an object where keys are state expressions and values are style values).\n */\n isStateMap(\n node: TSESTree.ObjectExpression,\n parentProperty: TSESTree.Property,\n ): boolean {\n const keyName = getKeyName(parentProperty.key);\n if (keyName === null) return false;\n\n // If the key starts with uppercase, it's a sub-element, not a state map\n if (/^[A-Z]/.test(keyName)) return false;\n\n // Special keys are not state maps\n // At-rule blocks are not state maps — their object values are descriptor maps.\n if (SPECIAL_STYLE_KEYS.has(keyName)) return false;\n\n // If the object has keys that look like state expressions, it's a state map.\n // A lone `_` (the fallback floor) or `''` (the default) is enough — both are\n // already covered by the string-literal / identifier branches below.\n return node.properties.some((prop) => {\n if (prop.type !== 'Property') return false;\n if (prop.key.type === 'Literal' && prop.key.value === '') return true;\n if (prop.key.type === 'Identifier') return true;\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') {\n return true;\n }\n return false;\n });\n }\n\n /**\n * Checks if a key represents a sub-element (starts with uppercase).\n */\n isSubElementKey(key: string): boolean {\n return /^[A-Z]/.test(key);\n }\n\n /**\n * Checks if a key represents a nested selector (starts with &).\n */\n isNestedSelectorKey(key: string): boolean {\n return key.startsWith('&');\n }\n\n /**\n * Checks if a key is a custom CSS property definition ($name or $$name).\n */\n isCustomPropertyKey(key: string): boolean {\n return key.startsWith('$');\n }\n\n /**\n * Checks if a key is a color token definition (#name or ##name).\n */\n isColorTokenKey(key: string): boolean {\n return key.startsWith('#');\n }\n\n /**\n * Checks if a key is a special @ property (@keyframes, @property, ...).\n */\n isSpecialKey(key: string): boolean {\n return key.startsWith('@');\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport type { RuleContext, Scope } from '@typescript-eslint/utils/ts-eslint';\nimport type { ResolvedConfig, StyleFunctionConfig } from './types.js';\nimport { loadConfig } from './config.js';\nimport {\n DEFAULT_IMPORT_SOURCES,\n KNOWN_CSS_PROPERTIES,\n KNOWN_TASTY_PROPERTIES,\n SPECIAL_STYLE_KEYS,\n} from './constants.js';\nimport {\n collectLocalStateAliases,\n getKeyName,\n unwrapExpression,\n valueDefinition,\n wildcardPattern,\n} from './utils.js';\nimport {\n finishJSXAnalysis,\n isTypeAwareJSX,\n jsxPropKind,\n type PropKind,\n} from './type-aware-jsx.js';\nimport { isModuleTastyComponent } from './module-components.js';\n\n/**\n * Every object is considered, then TastyContext gates it by its actual context.\n * Narrow ancestry selectors miss nested shared styles and wrapped JSX values.\n */\nexport const STYLE_OBJECT_SELECTORS = ['ObjectExpression'] as const;\n\n/** One listener per object; context recognition remains the caller's gate. */\nexport function styleObjectListeners(\n handler: (node: TSESTree.ObjectExpression) => void,\n): Record<string, (node: TSESTree.ObjectExpression) => void> {\n return { ObjectExpression: handler };\n}\n\nexport interface StyleContext {\n type: 'tasty' | 'tastyStatic' | 'useStyles' | 'useGlobalStyles';\n isStaticCall: boolean;\n isSelectorMode: boolean;\n isExtending: boolean;\n /**\n * Local name of the component this layer extends, when there is one and it is\n * an identifier. `null` covers every other case — a base definition, a\n * selector, or a layer whose base cannot be read off the AST — so a rule that\n * cares must treat `null` as \"unknown\", not as \"not extending\".\n */\n baseComponent: string | null;\n}\n\nexport interface TastyImport {\n localName: string;\n importedName: string;\n source: string;\n}\n\n/**\n * Whether a type annotation names tasty's `Styles` anywhere inside it.\n *\n * Walks the annotation rather than matching only the outermost reference, so a\n * wrapped tasty type (`Styles | undefined`, `Array<Styles>`) is recognised while\n * `CSSProperties` in the same positions is not. Maps of styles are told apart\n * first by `stylesAnnotationShape`. Deliberately name-based: the plugin has no type checker, and requiring one\n * would make every rule type-aware.\n */\nfunction referencesStylesType(node: TSESTree.TypeNode): boolean {\n const stack: TSESTree.Node[] = [node];\n\n while (stack.length) {\n const current = stack.pop()!;\n\n if (\n current.type === 'TSTypeReference' &&\n current.typeName.type === 'Identifier' &&\n /^Styles$/i.test(current.typeName.name)\n ) {\n return true;\n }\n\n for (const value of Object.values(\n current as unknown as Record<string, unknown>,\n )) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && 'type' in item) {\n stack.push(item as TSESTree.Node);\n }\n }\n } else if (value && typeof value === 'object' && 'type' in value) {\n // Skip `parent` — it points back up the tree and would loop forever.\n if (value !== (current as TSESTree.Node).parent) {\n stack.push(value as TSESTree.Node);\n }\n }\n }\n }\n\n return false;\n}\n\n/** Utility types whose result has the same shape as their argument. */\nconst SHAPE_PRESERVING_TYPES = new Set([\n 'Readonly',\n 'Partial',\n 'Required',\n 'NonNullable',\n]);\n\n/**\n * What a `Styles`-bearing annotation declares: `'styles'` for a style object,\n * `'map'` for an object whose *values* are style objects (`Record<K, Styles>`,\n * `{ [k: string]: Styles }`, `{ root: Styles }`), `null` when `Styles` does not\n * appear at all.\n *\n * The distinction matters for a map: its keys are variant or block names, so\n * checking the map itself as a style object reports every one of them as an\n * unknown property, while the style objects it holds go unchecked.\n */\nfunction stylesAnnotationShape(\n node: TSESTree.TypeNode,\n): 'styles' | 'map' | null {\n if (node.type === 'TSUnionType' || node.type === 'TSIntersectionType') {\n const shapes = node.types.map(stylesAnnotationShape);\n if (shapes.includes('styles')) return 'styles';\n return shapes.includes('map') ? 'map' : null;\n }\n\n if (node.type === 'TSTypeReference' && node.typeName.type === 'Identifier') {\n const name = node.typeName.name;\n const args = node.typeArguments?.params ?? [];\n\n if (/^Styles$/i.test(name)) return 'styles';\n if (name === 'Record' && args.length === 2) {\n if (stylesAnnotationShape(args[1]) === 'styles') return 'map';\n }\n if (SHAPE_PRESERVING_TYPES.has(name) && args.length === 1) {\n return stylesAnnotationShape(args[0]);\n }\n }\n\n if (node.type === 'TSTypeLiteral') {\n const holdsStyles = node.members.some(\n (member) =>\n (member.type === 'TSIndexSignature' ||\n member.type === 'TSPropertySignature') &&\n member.typeAnnotation !== undefined &&\n stylesAnnotationShape(member.typeAnnotation.typeAnnotation) ===\n 'styles',\n );\n if (holdsStyles) return 'map';\n }\n\n return referencesStylesType(node) ? 'styles' : null;\n}\n\n/**\n * Whether a key could plausibly be a tasty style key.\n *\n * Covers every top-level shape tasty accepts: a style property, a sub-element\n * (capitalised), an at-rule or state/custom-property/colour key (`@`, `&`, `$`,\n * `#`), and the default-state key.\n */\nfunction isPlausibleStyleKey(key: string): boolean {\n if (key === '' || key === '_') return true;\n if (/^[A-Z]/.test(key)) return true;\n if (/^[@&$#]/.test(key)) return true;\n if (SPECIAL_STYLE_KEYS.has(key)) return true;\n\n return KNOWN_TASTY_PROPERTIES.has(key) || KNOWN_CSS_PROPERTIES.has(key);\n}\n\n/**\n * Whether an object is a map of named CSS blocks rather than a tasty styles object.\n *\n * The shape is unmistakable — `{ table: {…}, th: {…}, td: {…} }`, `{ root: {…},\n * toolbar: {…} }` — and it is what a React inline-style map looks like when it\n * carries no type annotation to opt it out. Every key is a block name that is not a\n * style key, and every value is an object.\n *\n * Requiring *every* value to be an object literal is what keeps this from swallowing\n * the case it would hurt most: `const styles = { colour: 'red' }` has a string value,\n * so it is not treated as a block map and `known-property` still reports the typo.\n * Otherwise the rule that catches a misspelled property would be silenced by the\n * misspelling.\n */\nfunction isNamedCssBlockMap(node: TSESTree.ObjectExpression): boolean {\n if (node.properties.length === 0) return false;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) return false;\n\n const key = getKeyName(prop.key);\n\n if (key === null || isPlausibleStyleKey(key)) return false;\n if (prop.value.type !== 'ObjectExpression') return false;\n }\n\n return true;\n}\n\n/**\n * The outermost expression an object is the result of through conditional and\n * logical operators (and type wrappers): `cond ? { … } : null`, `cond && { … }`,\n * `styles ?? { … }`. Whatever position that expression takes, the object may\n * land in. The test of a conditional and the left of `&&` never become the\n * value, so they are not followed.\n */\nfunction conditionalFlowRoot(node: TSESTree.Node): TSESTree.Node {\n let current = node;\n // Matching unwraps type wrappers itself, so the root is the outermost\n // operator, not a wrapper around it.\n let root = node;\n while (current.parent) {\n const parent: TSESTree.Node = current.parent;\n if (\n (parent.type === 'TSAsExpression' ||\n parent.type === 'TSSatisfiesExpression' ||\n parent.type === 'TSNonNullExpression' ||\n parent.type === 'TSTypeAssertion') &&\n parent.expression === current\n ) {\n current = parent;\n } else if (\n (parent.type === 'ConditionalExpression' && parent.test !== current) ||\n (parent.type === 'LogicalExpression' &&\n (parent.right === current || parent.operator !== '&&'))\n ) {\n current = root = parent;\n } else {\n break;\n }\n }\n return root;\n}\n\n/**\n * The component a `styles` JSX prop overrides — `<Card styles={…} />` -> `Card`.\n * A namespaced tag (`<UI.Card />`) resolves to its root object, since that is the\n * name an import can be matched against.\n */\nfunction jsxStylesPropTarget(node: TSESTree.Node): string | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const container = wrapped.parent;\n if (container?.type !== 'JSXExpressionContainer') return null;\n\n const attribute = container.parent;\n if (attribute?.type !== 'JSXAttribute') return null;\n\n const element = attribute.parent;\n if (element?.type !== 'JSXOpeningElement') return null;\n\n let name: TSESTree.JSXTagNameExpression = element.name;\n while (name.type === 'JSXMemberExpression') name = name.object;\n\n return name.type === 'JSXIdentifier' ? name.name : null;\n}\n\n/**\n * The identifier a base-component argument resolves to — `tasty(UI.Card, {…})`\n * -> `UI`, which is what the import map is keyed by.\n *\n * Type assertions are stripped on the way down. Reading `Button as any` as an\n * unknown base would quietly promote an imported component to \"owned\", which is\n * the reading that produces a warning the author cannot act on.\n */\nfunction baseComponentName(node: TSESTree.Node): string | null {\n let current = unwrapExpression(node);\n\n while (current.type === 'MemberExpression') {\n current = unwrapExpression(current.object);\n }\n\n return current.type === 'Identifier' ? current.name : null;\n}\n\n/**\n * Whether `source` is inside this project. Relative and absolute specifiers are,\n * as are the conventional in-repo aliases (`~/`, `#internal`, `@/`) — `@` alone\n * is not, since `@scope/pkg` is a published package.\n */\nfunction isInRepoSource(source: string): boolean {\n return (\n source.startsWith('.') ||\n source.startsWith('/') ||\n source.startsWith('~') ||\n source.startsWith('#') ||\n source.startsWith('@/')\n );\n}\n\n/**\n * A bare specifier and each path above it, down to its package:\n * `@scope/pkg/a/b` gives `@scope/pkg/a/b`, `@scope/pkg/a` and `@scope/pkg`. A\n * source entry naming any of them covers the specifier.\n */\nfunction specifierPaths(source: string): string[] {\n const parts = source.split('/');\n const packageLength = source.startsWith('@') ? 2 : 1;\n const paths: string[] = [];\n for (let length = parts.length; length >= packageLength; length--) {\n paths.push(parts.slice(0, length).join('/'));\n }\n return paths;\n}\n\n/** `settings.tasty.mergeFunctions`: project helpers with `mergeStyles` semantics. */\nfunction readMergeFunctions(\n context: RuleContext<string, unknown[]>,\n): ReadonlySet<string> {\n const settings = context.settings?.tasty as\n | { mergeFunctions?: unknown }\n | undefined;\n const option = settings?.mergeFunctions;\n if (option === undefined) return new Set();\n if (\n !Array.isArray(option) ||\n option.some((name) => typeof name !== 'string')\n ) {\n throw new Error(\n 'tasty: mergeFunctions must be an array of function names.',\n );\n }\n return new Set(option);\n}\n\nconst TASTY_FUNCTION_NAMES = new Set([\n 'tasty',\n 'tastyStatic',\n 'useStyles',\n 'useGlobalStyles',\n 'mergeStyles',\n 'configure',\n]);\n\n/**\n * Context tracker for a single file's lint pass.\n * Tracks which imports come from tasty and provides\n * helpers to determine if a node is in a tasty style context.\n */\nexport class TastyContext {\n readonly config: ResolvedConfig;\n private imports = new Map<string, TastyImport>();\n private moduleSources = new Map<string, string>();\n private importSources: Set<string>;\n private mergeFunctions: ReadonlySet<string>;\n private relativeComponents = new Map<string, boolean>();\n private resolving = new Set<TSESTree.Node>();\n private ownedPatterns: RegExp[] | undefined;\n private externalElements = new WeakMap<TSESTree.Node, boolean>();\n\n constructor(\n private context: RuleContext<string, unknown[]>,\n config?: ResolvedConfig,\n ) {\n this.config = config ?? loadConfig(context.filename);\n this.importSources = new Set([\n ...DEFAULT_IMPORT_SOURCES,\n ...this.config.importSources,\n ]);\n this.mergeFunctions = readMergeFunctions(context);\n }\n\n trackImport(node: TSESTree.ImportDeclaration): void {\n const source = node.source.value;\n\n // Every import is recorded, tasty or not. Where a *base component* comes\n // from is what tells a rule whether the file it would send the author to\n // edit is even theirs — see `isOwnedComponent`.\n for (const specifier of node.specifiers) {\n this.moduleSources.set(specifier.local.name, source);\n }\n\n if (!this.importSources.has(source) || node.importKind === 'type') return;\n\n for (const specifier of node.specifiers) {\n if (\n specifier.type === 'ImportSpecifier' &&\n specifier.importKind !== 'type'\n ) {\n const importedName =\n specifier.imported.type === 'Identifier'\n ? specifier.imported.name\n : specifier.imported.value;\n if (\n TASTY_FUNCTION_NAMES.has(importedName) ||\n Object.hasOwn(this.config.styleFunctions ?? {}, importedName)\n ) {\n this.imports.set(specifier.local.name, {\n localName: specifier.local.name,\n importedName,\n source,\n });\n }\n }\n }\n }\n\n isComponentJSXProp(node: TSESTree.JSXAttribute): boolean {\n return this.jsxPropKind(node) === 'component';\n }\n\n /** What `typeAwareJSX` makes of a JSX prop; `'unknown'` while it is off. */\n jsxPropKind(node: TSESTree.JSXAttribute): PropKind {\n return jsxPropKind(this.context, node);\n }\n\n /** Whether `settings.tasty.typeAwareJSX` classifies JSX props by their types. */\n get typeAwareJSX(): boolean {\n return isTypeAwareJSX(this.context);\n }\n\n finishJSXAnalysis(): void {\n finishJSXAnalysis(this.context);\n }\n\n getImport(localName: string): TastyImport | undefined {\n return this.imports.get(localName);\n }\n\n /** The built-in and configured `importSources`. */\n get trackedSources(): ReadonlySet<string> {\n return this.importSources;\n }\n\n /**\n * Whether the base component an extension layer sits on top of lives in a file\n * this project can edit — so a rule can decide whether pointing the author at\n * the base's own definition is advice they can act on.\n *\n * A name that was never imported is declared in this very file, and an unknown\n * base (`null`) counts as owned as well: staying quiet is for a base that is\n * demonstrably someone else's, never for one the plugin merely failed to read.\n */\n isOwnedComponent(localName: string | null): boolean {\n if (localName === null) return true;\n\n const source = this.moduleSources.get(localName);\n return source === undefined || this.isOwnedSource(source);\n }\n\n /** In-repo, or a package (or a subpath of one) listed in `ownedSources`. */\n private isOwnedSource(source: string): boolean {\n if (isInRepoSource(source)) return true;\n\n // `ownedSources` is optional on the public `ResolvedConfig`, so a config\n // built by a consumer rather than by `loadConfig` may not carry it.\n this.ownedPatterns ??= (this.config.ownedSources ?? []).map(\n wildcardPattern,\n );\n const patterns = this.ownedPatterns;\n return specifierPaths(source).some((path) =>\n patterns.some((pattern) => pattern.test(path)),\n );\n }\n\n /**\n * The definition a name resolves to through `const` aliases of an identifier\n * or a non-computed member chain (`const Scope = FocusScope`,\n * `const Item = UI.Item`): an import binding, or a declaration whose value is\n * something else. Null for an unbound or redeclared name, or an alias cycle; a\n * same-named type does not count as a redeclaration.\n */\n private resolveAlias(\n reference: TSESTree.Node,\n name: string,\n visited = new Set<TSESTree.Node>(),\n ): Scope.Definition | null {\n let scope: Scope.Scope | null = this.context.sourceCode.getScope(reference);\n while (scope && !scope.set.has(name)) scope = scope.upper;\n const def = scope && valueDefinition(scope.set.get(name)!);\n if (!def) return null;\n if (\n def.type !== 'Variable' ||\n def.parent.kind !== 'const' ||\n def.node.id.type !== 'Identifier' ||\n !def.node.init\n ) {\n return def;\n }\n\n const init = unwrapExpression(def.node.init);\n if (init.type !== 'Identifier' && init.type !== 'MemberExpression') {\n return def;\n }\n if (visited.has(def.node)) return null;\n visited.add(def.node);\n let root: TSESTree.Node = init;\n while (root.type === 'MemberExpression') {\n if (root.computed) return null;\n root = unwrapExpression(root.object);\n }\n return root.type === 'Identifier'\n ? this.resolveAlias(init, root.name, visited)\n : null;\n }\n\n /**\n * Whether a JSX element is a component from a package Tasty has no say over:\n * its tag, or the root object of a member tag, is imported from a bare\n * specifier that is neither an import source nor owned, such as `react-aria`'s\n * `FocusScope`. Either list covers a package's subpaths. Its props are its\n * own, so `<FocusScope contain />` carries no style value. `const` aliases are\n * followed; a component declared in the file, a factory call and a relative\n * or in-repo import are not external.\n */\n isExternalJSXElement(element: TSESTree.JSXOpeningElement): boolean {\n let external = this.externalElements.get(element);\n if (external === undefined) {\n let tag = element.name;\n while (tag.type === 'JSXMemberExpression') tag = tag.object;\n const def =\n tag.type === 'JSXIdentifier' ? this.resolveAlias(tag, tag.name) : null;\n external = false;\n if (\n def?.type === 'ImportBinding' &&\n def.parent.type === 'ImportDeclaration'\n ) {\n const source = def.parent.source.value;\n external =\n !this.isOwnedSource(source) &&\n !specifierPaths(source).some((path) => this.importSources.has(path));\n }\n this.externalElements.set(element, external);\n }\n return external;\n }\n\n isTastyCall(node: TSESTree.CallExpression): TastyImport | undefined {\n const callee = unwrapExpression(node.callee);\n if (callee.type !== 'Identifier') return undefined;\n const imp = this.imports.get(callee.name);\n if (!imp) return undefined;\n\n // A parameter or local declaration can shadow the imported helper. Only\n // the import binding carries evidence that the call accepts Tasty styles.\n let scope = this.context.sourceCode.getScope(callee);\n while (scope) {\n const variable = scope.set.get(callee.name);\n if (variable) {\n return variable.defs.some((def) => def.type === 'ImportBinding')\n ? imp\n : undefined;\n }\n if (!scope.upper) break;\n scope = scope.upper;\n }\n return undefined;\n }\n\n /**\n * `mergeStyles(...)`, or a call to a project helper named in\n * `settings.tasty.mergeFunctions`. A helper matches by its imported name, so\n * an aliased import still counts, or by the name it is declared under in this\n * file; a parameter of the same name shadows it.\n */\n isMergeStylesCall(node: TSESTree.CallExpression): boolean {\n if (this.isTastyCall(node)?.importedName === 'mergeStyles') return true;\n if (this.mergeFunctions.size === 0) return false;\n\n const callee = unwrapExpression(node.callee);\n if (callee.type !== 'Identifier') return false;\n\n let scope = this.context.sourceCode.getScope(callee);\n while (scope) {\n const variable = scope.set.get(callee.name);\n if (variable) {\n return variable.defs.some((def) => {\n if (def.type === 'FunctionName' || def.type === 'Variable') {\n return this.mergeFunctions.has(callee.name);\n }\n if (\n def.type !== 'ImportBinding' ||\n def.parent.type !== 'ImportDeclaration' ||\n def.parent.importKind === 'type'\n ) {\n return false;\n }\n if (def.node.type === 'ImportDefaultSpecifier') {\n return this.mergeFunctions.has(callee.name);\n }\n if (def.node.type !== 'ImportSpecifier') return false;\n if (def.node.importKind === 'type') return false;\n const imported = def.node.imported;\n return this.mergeFunctions.has(\n imported.type === 'Identifier' ? imported.name : imported.value,\n );\n });\n }\n if (!scope.upper) break;\n scope = scope.upper;\n }\n // An undeclared global, such as an auto-imported helper.\n return this.mergeFunctions.has(callee.name);\n }\n\n /** Local factory results, const aliases, and configured component imports. */\n isTastyJSXComponent(node: TSESTree.Node, name: string): boolean {\n const def = this.resolveAlias(node, name);\n if (def?.type === 'ImportBinding') {\n if (\n def.parent.type !== 'ImportDeclaration' ||\n def.parent.importKind === 'type' ||\n (def.node.type === 'ImportSpecifier' && def.node.importKind === 'type')\n ) {\n return false;\n }\n const source = def.parent.source.value;\n if (this.importSources.has(source)) return true;\n return this.isRelativeTastyImport(source, def.node);\n }\n if (\n def?.type !== 'Variable' ||\n def.parent.kind !== 'const' ||\n def.node.id.type !== 'Identifier' ||\n !def.node.init\n ) {\n return false;\n }\n const init = unwrapExpression(def.node.init);\n if (init.type !== 'CallExpression') return false;\n const imp = this.isTastyCall(init);\n return (\n imp?.importedName === 'tasty' ||\n (imp !== undefined &&\n this.config.styleFunctions?.[imp.importedName]?.kind === 'options')\n );\n }\n\n /**\n * Whether a binding imported from a relative module names a Tasty component\n * declared there — `import { Panel } from './styled'`. A namespace import has\n * no single export to follow.\n */\n private isRelativeTastyImport(\n source: string,\n specifier: TSESTree.Node,\n ): boolean {\n if (\n specifier.type !== 'ImportSpecifier' &&\n specifier.type !== 'ImportDefaultSpecifier'\n ) {\n return false;\n }\n const exportName =\n specifier.type === 'ImportDefaultSpecifier'\n ? 'default'\n : specifier.imported.type === 'Identifier'\n ? specifier.imported.name\n : specifier.imported.value;\n const key = `${source}\\0${exportName}`;\n let result = this.relativeComponents.get(key);\n if (result === undefined) {\n result = isModuleTastyComponent(\n this.context.filename,\n source,\n exportName,\n {\n importSources: this.importSources,\n isComponentFactory: (name) =>\n name === 'tasty' ||\n this.config.styleFunctions?.[name]?.kind === 'options',\n },\n );\n this.relativeComponents.set(key, result);\n }\n return result;\n }\n\n /**\n * Determines whether an object expression is a tasty style object\n * by walking up the AST to find a recognized call expression.\n */\n isStyleObject(node: TSESTree.ObjectExpression): boolean {\n return this.getStyleContext(node) !== null;\n }\n\n private getSubElementParent(\n node: TSESTree.Node,\n ): TSESTree.ObjectExpression | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const parent = wrapped.parent;\n if (parent?.type !== 'Property' || parent.computed) return null;\n const key = getKeyName(parent.key);\n return key &&\n /^[A-Z]/.test(key) &&\n parent.parent.type === 'ObjectExpression'\n ? parent.parent\n : null;\n }\n\n /** Follow only sub-elements of recognized styles, never a variants container. */\n getRootStyleObject(\n node: TSESTree.ObjectExpression,\n ): TSESTree.ObjectExpression {\n let current = node;\n while (true) {\n const parent = this.getSubElementParent(current);\n if (!parent || !this.isStyleObject(parent)) return current;\n current = parent;\n }\n }\n\n /**\n * The `mergeStyles(...)` call, or configured merge helper call, this object\n * is a direct argument of, if any.\n */\n private getMergeStylesCall(\n node: TSESTree.ObjectExpression,\n ): TSESTree.CallExpression | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const call = wrapped.parent;\n return call?.type === 'CallExpression' &&\n call.arguments.includes(wrapped as TSESTree.CallExpressionArgument) &&\n this.isMergeStylesCall(call)\n ? call\n : null;\n }\n\n /**\n * Local `@name` state aliases visible to a style object, the way Tasty\n * resolves them: the object's own, then those of each enclosing sub-element\n * up to the root. A `mergeStyles(...)` argument stands for the merged object,\n * so every object argument of the call contributes, and a call that is a\n * sub-element value sees the aliases of the styles it sits in.\n */\n getLocalStateAliases(node: TSESTree.ObjectExpression): string[] {\n const aliases = new Set<string>();\n let current: TSESTree.ObjectExpression | null = node;\n\n while (current) {\n const call = this.getMergeStylesCall(current);\n const scope = call\n ? call.arguments\n .map((arg) => unwrapExpression(arg))\n .filter(\n (arg): arg is TSESTree.ObjectExpression =>\n arg.type === 'ObjectExpression',\n )\n : [current];\n for (const object of scope) {\n for (const alias of collectLocalStateAliases(object))\n aliases.add(alias);\n }\n\n const parent = this.getSubElementParent(call ?? current);\n current = parent && this.isStyleObject(parent) ? parent : null;\n }\n\n return [...aliases];\n }\n\n /**\n * Whether the style object this node belongs to is declared on its own — a\n * `const CELL_STYLES: Styles` or a value of a `Record<K, Styles>` — rather\n * than handed to a call or prop. Such styles can be spread anywhere,\n * including into a sub-element, so their root is not necessarily the\n * component's root.\n */\n isSharedStyleObject(node: TSESTree.ObjectExpression): boolean {\n const outermost = (inner: TSESTree.Node): TSESTree.Node => {\n let wrapped = inner;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === inner) {\n wrapped = wrapped.parent;\n }\n return wrapped;\n };\n\n let parent = outermost(this.getRootStyleObject(node)).parent;\n if (\n parent?.type === 'Property' &&\n parent.parent.type === 'ObjectExpression'\n ) {\n parent = outermost(parent.parent).parent;\n }\n return parent?.type === 'VariableDeclarator';\n }\n\n /** Include helper calls nested inside a real sub-element, but not variant names. */\n isInsideSubElement(node: TSESTree.Node): boolean {\n let current = node.parent;\n while (current) {\n if (current.type === 'Property' && !current.computed) {\n const key = getKeyName(current.key);\n if (\n key &&\n /^[A-Z]/.test(key) &&\n current.parent.type === 'ObjectExpression' &&\n this.isStyleObject(current.parent)\n ) {\n return true;\n }\n }\n current = current.parent;\n }\n return false;\n }\n\n /**\n * The style context of an object, or of any expression standing where a\n * style object goes. Besides objects written in place, this covers an object\n * that reaches a style position only through a conditional or logical\n * operator (`mergeStyles(cond ? { … } : null, styles)`), and one held in a\n * render-scope variable that is then passed on (`const local = { … }`,\n * `styles = { ...styles, … }`, then `styles={local}`): Tasty receives each of\n * them as styles all the same.\n */\n getStyleContext(node: TSESTree.Node): StyleContext | null {\n // A binding can lead back into the object being resolved (`a = { X: a }`).\n if (this.resolving.has(node)) return null;\n this.resolving.add(node);\n try {\n if (node.type === 'ObjectExpression') {\n const flow = conditionalFlowRoot(node);\n if (flow !== node) return this.getStyleContext(flow);\n }\n return (\n this.getDirectStyleContext(node) ?? this.getBindingStyleContext(node)\n );\n } finally {\n this.resolving.delete(node);\n }\n }\n\n /**\n * The context of a value held in a render-scope variable, taken from the\n * first place the variable is read as styles. Module-scope bindings are\n * shared values and are left to the declaration heuristics.\n */\n private getBindingStyleContext(node: TSESTree.Node): StyleContext | null {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const holder = wrapped.parent;\n let target: TSESTree.Identifier | null = null;\n if (\n holder?.type === 'VariableDeclarator' &&\n holder.init === wrapped &&\n holder.id.type === 'Identifier'\n ) {\n target = holder.id;\n } else if (\n holder?.type === 'AssignmentExpression' &&\n holder.operator === '=' &&\n holder.right === wrapped &&\n holder.left.type === 'Identifier'\n ) {\n target = holder.left;\n }\n if (!target) return null;\n\n let scope = this.context.sourceCode.getScope(target);\n while (!scope.set.has(target.name) && scope.upper) scope = scope.upper;\n const variable = scope.set.get(target.name);\n if (!variable || scope.type === 'module' || scope.type === 'global') {\n return null;\n }\n\n for (const reference of variable.references ?? []) {\n if (!reference.isRead() || reference.identifier === target) continue;\n const context = this.getStyleContext(reference.identifier);\n if (context) return context;\n }\n return null;\n }\n\n private getDirectStyleContext(node: TSESTree.Node): StyleContext | null {\n // Sub-element objects inherit their parent style object's context\n const parent = this.getSubElementParent(node);\n if (parent) {\n const inherited = this.getStyleContext(parent);\n if (inherited) return inherited;\n }\n\n // An object assigned to a `styles` key (or a `styles` JSX prop) is a style\n // object on its own terms — no enclosing tasty call or `styles`-ish variable\n // name required. Checked before the walk, which would otherwise climb past it\n // to an unrelated call or declaration and reject the whole thing.\n if (this.isStylesPropertyValue(node)) {\n // A `styles` prop is an override layer by construction: the component it\n // is handed to already carries its own styles and this object lands on\n // top of them. A Storybook `args.styles` is the same prop by another name,\n // but the component behind `args` is not on the AST path, so its base\n // stays unknown.\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: true,\n baseComponent: jsxStylesPropTarget(node),\n };\n }\n\n let current: TSESTree.Node | undefined = node;\n\n while (current) {\n if (current.type === 'CallExpression') {\n if (this.isMergeStylesCall(current)) {\n return this.getMergeStylesContext(current, node);\n }\n\n const imp = this.isTastyCall(current);\n if (!imp) return null;\n\n const name = imp.importedName;\n const isStaticCall = name === 'tastyStatic';\n\n if (name === 'tasty') {\n return this.getTastyCallContext(current, node);\n }\n\n if (name === 'tastyStatic') {\n return this.getTastyStaticCallContext(current, node);\n }\n\n if (name === 'useStyles') {\n if (current.arguments[0] === node) {\n return {\n type: 'useStyles',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n }\n\n if (name === 'useGlobalStyles') {\n if (current.arguments[1] === node) {\n return {\n type: 'useGlobalStyles',\n isStaticCall,\n isSelectorMode: true,\n isExtending: false,\n baseComponent: null,\n };\n }\n }\n\n // Built-in signatures always take precedence over configured ones.\n const custom = this.config.styleFunctions?.[name];\n if (!TASTY_FUNCTION_NAMES.has(name) && custom) {\n return this.getCustomCallContext(current, node, custom);\n }\n\n return null;\n }\n\n if (this.isStyleVariableDeclaration(current, node)) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n\n current = current.parent;\n }\n\n return null;\n }\n\n private isStyleVariableDeclaration(\n current: TSESTree.Node,\n targetNode: TSESTree.Node,\n ): boolean {\n if (\n current.type !== 'VariableDeclarator' ||\n current.id.type !== 'Identifier'\n ) {\n return false;\n }\n\n let init: TSESTree.Node | null | undefined = current.init;\n while (\n init?.type === 'TSAsExpression' ||\n init?.type === 'TSSatisfiesExpression' ||\n init?.type === 'TSTypeAssertion' ||\n init?.type === 'TSNonNullExpression'\n ) {\n init = (init as TSESTree.TSAsExpression).expression;\n }\n\n // An explicit type annotation is authoritative, in both directions, and is\n // read before anything about the name. The name heuristics below are a\n // guess; a declared type is the author stating what the object is, so it\n // wins — `const CARD_STYLES: Styles` is as much a style object as\n // `const cardStyles: Styles`.\n //\n // This matters because the rewrites these rules offer are only valid *inside*\n // tasty: `#purple.05` and `$font-sans` are correct tasty declarations and\n // meaningless as raw CSS. A `const styles: Record<string, CSSProperties>`\n // handed to React's `style={…}` was matched on name alone, so its plain CSS\n // longhands were reported as tasty violations — and `--fix` rewrote real\n // `var(--shadow-sm-color)` to `#shadow-sm`, which nothing resolves there, so\n // the browser dropped the declaration.\n const annotated = this.stylesTypeAnnotation(current);\n\n // A map of style objects: its values are checked, never the map itself.\n if (annotated === 'map') {\n return (\n init?.type === 'ObjectExpression' &&\n init.properties.some(\n (prop) =>\n prop.type === 'Property' &&\n unwrapExpression(prop.value) === targetNode,\n )\n );\n }\n\n if (init !== targetNode) return false;\n if (annotated !== null) return annotated === 'styles';\n\n const name = current.id.name;\n\n // Unannotated constants are shared values, not style objects by name alone.\n if (/^[A-Z][A-Z0-9_]*$/.test(name)) return false;\n\n // Only `styles` and `*Styles` count. The singular `style` is conventionally\n // a DOM inline-style object (`el.style`, `CSSProperties`, `setStyle(el, …)`)\n // holding raw CSS longhands, not tasty syntax — matching it reported those\n // longhands as tasty violations.\n if (name === 'styles' || name.endsWith('Styles')) {\n // The name is the weakest evidence there is, so let an unmistakable shape\n // overrule it. Without an annotation to go on, a map of named CSS blocks was\n // reported as tasty — `known-property` on every HTML tag name, each block read\n // as a state map — and `--fix` offered rewrites that are only valid inside\n // tasty.\n return !(\n targetNode.type === 'ObjectExpression' && isNamedCssBlockMap(targetNode)\n );\n }\n\n return false;\n }\n\n private getCustomCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n config: StyleFunctionConfig,\n ): StyleContext | null {\n const { argument, kind } = config;\n if (argument !== 'all' && (!Number.isInteger(argument) || argument < 0)) {\n return null;\n }\n // A preceding spread makes the runtime argument index unknown. Never apply\n // style rewrites to an object that might occupy a different parameter.\n if (\n argument !== 'all' &&\n call.arguments\n .slice(0, argument)\n .some((arg) => arg.type === 'SpreadElement')\n ) {\n return null;\n }\n\n const args =\n argument === 'all' ? call.arguments : [call.arguments[argument]];\n for (const arg of args) {\n if (!arg) continue;\n const value = unwrapExpression(arg);\n if (value.type !== 'ObjectExpression') continue;\n\n const isVariant =\n kind === 'options' && this.isInsideVariantsProperty(value, targetNode);\n const matches =\n kind === 'styles'\n ? value === targetNode\n : kind === 'options' &&\n (this.isInsideStylesProperty(value, targetNode) || isVariant);\n\n if (matches) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: !isVariant && (config.partial ?? false),\n baseComponent: null,\n };\n }\n }\n\n return null;\n }\n\n /**\n * Verdict from the declared type: `'styles'` the object is tasty, `'map'` its\n * values are, `false` explicitly neither, `null` when there is no annotation to\n * go on and the caller should fall back to the name.\n *\n * A `Styles` reference anywhere in the annotation counts, so wrappers like\n * `Styles | undefined` and `Record<string, Styles>` opt in — while\n * `CSSProperties`, `Record<string, CSSProperties>` and an inline literal of\n * them opt out.\n */\n private stylesTypeAnnotation(\n node: TSESTree.VariableDeclarator,\n ): 'styles' | 'map' | false | null {\n const annotation = node.id.typeAnnotation?.typeAnnotation;\n\n if (!annotation) return null;\n\n return stylesAnnotationShape(annotation) ?? false;\n }\n\n private getTastyCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tasty({ styles: { ... } }) or tasty(Component, { styles: { ... } })\n const isExtending =\n args.length >= 2 && unwrapExpression(args[0]).type !== 'ObjectExpression';\n const optionsArg = isExtending ? args[1] : args[0];\n\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideStylesProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending,\n baseComponent: isExtending ? baseComponentName(args[0]) : null,\n };\n }\n\n // Check if inside variants\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideVariantsProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n\n return null;\n }\n\n /**\n * Every object argument of `mergeStyles(base, ...overrides)` is a style\n * object. The first is the base; each later one is layered on top, where a\n * state map without `''` extends the one below it rather than replacing it.\n */\n private getMergeStylesContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ): StyleContext | null {\n const index = call.arguments.findIndex(\n (arg) => unwrapExpression(arg) === targetNode,\n );\n if (index === -1) return null;\n\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: index > 0,\n baseComponent: null,\n };\n }\n\n private getTastyStaticCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tastyStatic({ ... })\n if (args.length === 1 && args[0] === targetNode) {\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode: false,\n isExtending: false,\n baseComponent: null,\n };\n }\n\n // tastyStatic(base, { ... }) or tastyStatic('selector', { ... })\n if (args.length === 2 && args[1] === targetNode) {\n const isSelectorMode = unwrapExpression(args[0]).type === 'Literal';\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode,\n isExtending: !isSelectorMode,\n baseComponent: isSelectorMode ? null : baseComponentName(args[0]),\n };\n }\n\n return null;\n }\n\n private isInsideStylesProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n !prop.computed &&\n getKeyName(prop.key) === 'styles' &&\n unwrapExpression(prop.value) === targetNode\n ) {\n return true;\n }\n }\n return false;\n }\n\n private isInsideVariantsProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n !prop.computed &&\n getKeyName(prop.key) === 'variants'\n ) {\n const variants = unwrapExpression(prop.value);\n if (variants.type !== 'ObjectExpression') continue;\n for (const variantProp of variants.properties) {\n if (\n variantProp.type === 'Property' &&\n unwrapExpression(variantProp.value) === targetNode\n ) {\n return true;\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this object is a `styles` JSX prop value or a Storybook `args.styles`.\n *\n * Both are unambiguous enough to stand on their own without an import-tracked\n * call or a `styles`-ish variable name. A bare `styles` key elsewhere is not —\n * see the selector list for why.\n */\n isStylesPropertyValue(node: TSESTree.Node): boolean {\n let wrapped: TSESTree.Node = node;\n while (wrapped.parent && unwrapExpression(wrapped.parent) === node) {\n wrapped = wrapped.parent;\n }\n const parent = wrapped.parent;\n\n if (parent?.type === 'Property' && !parent.computed) {\n if (getKeyName(parent.key) !== 'styles') return false;\n\n // Only inside `args: { … }`.\n const argsObject = parent.parent;\n const argsProperty =\n argsObject?.type === 'ObjectExpression' ? argsObject.parent : undefined;\n\n return (\n argsProperty?.type === 'Property' &&\n !argsProperty.computed &&\n getKeyName(argsProperty.key) === 'args'\n );\n }\n\n if (parent?.type === 'JSXExpressionContainer') {\n const attribute = parent.parent;\n\n return (\n attribute?.type === 'JSXAttribute' &&\n attribute.name.type === 'JSXIdentifier' &&\n (attribute.name.name === 'styles' ||\n attribute.name.name.endsWith('Styles'))\n );\n }\n\n return false;\n }\n\n /**\n * Checks if a property value node is a state mapping object\n * (i.e., an object where keys are state expressions and values are style values).\n */\n isStateMap(\n node: TSESTree.ObjectExpression,\n parentProperty: TSESTree.Property,\n ): boolean {\n const keyName = getKeyName(parentProperty.key);\n if (keyName === null) return false;\n\n // If the key starts with uppercase, it's a sub-element, not a state map\n if (/^[A-Z]/.test(keyName)) return false;\n\n // Special keys are not state maps\n // At-rule blocks are not state maps — their object values are descriptor maps.\n if (SPECIAL_STYLE_KEYS.has(keyName)) return false;\n\n // If the object has keys that look like state expressions, it's a state map.\n // A lone `_` (the fallback floor) or `''` (the default) is enough — both are\n // already covered by the string-literal / identifier branches below.\n return node.properties.some((prop) => {\n if (prop.type !== 'Property') return false;\n if (prop.key.type === 'Literal' && prop.key.value === '') return true;\n if (prop.key.type === 'Identifier') return true;\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') {\n return true;\n }\n return false;\n });\n }\n\n /**\n * Checks if a key represents a sub-element (starts with uppercase).\n */\n isSubElementKey(key: string): boolean {\n return /^[A-Z]/.test(key);\n }\n\n /**\n * Checks if a key represents a nested selector (starts with &).\n */\n isNestedSelectorKey(key: string): boolean {\n return key.startsWith('&');\n }\n\n /**\n * Checks if a key is a custom CSS property definition ($name or $$name).\n */\n isCustomPropertyKey(key: string): boolean {\n return key.startsWith('$');\n }\n\n /**\n * Checks if a key is a color token definition (#name or ##name).\n */\n isColorTokenKey(key: string): boolean {\n return key.startsWith('#');\n }\n\n /**\n * Checks if a key is a special @ property (@keyframes, @property, ...).\n */\n isSpecialKey(key: string): boolean {\n return key.startsWith('@');\n }\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { version } from "./version.js";
1
2
  import known_property_default from "./rules/known-property.js";
2
3
  import valid_value_default from "./rules/valid-value.js";
3
4
  import valid_color_token_default from "./rules/valid-color-token.js";
@@ -43,7 +44,6 @@ import prefer_hide_default from "./rules/prefer-hide.js";
43
44
  import prefer_directional_shorthand_default from "./rules/prefer-directional-shorthand.js";
44
45
  import prefer_longhand_property_default from "./rules/prefer-longhand-property.js";
45
46
  import { recommended, strict } from "./configs.js";
46
- import { createRequire } from "node:module";
47
47
 
48
48
  //#region src/index.ts
49
49
  const ruleMap = {
@@ -92,7 +92,6 @@ const ruleMap = {
92
92
  "prefer-directional-shorthand": prefer_directional_shorthand_default,
93
93
  "prefer-longhand-property": prefer_longhand_property_default
94
94
  };
95
- const { version } = createRequire(import.meta.url)("../package.json");
96
95
  const plugin = {
97
96
  meta: {
98
97
  name: "@tenphi/eslint-plugin-tasty",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["rules.knownProperty","rules.validValue","rules.validColorToken","rules.validCustomUnit","rules.validStateKey","rules.validStylesStructure","rules.noNestedSelector","rules.noStateInSelector","rules.preferElementSelector","rules.validCustomProperty","rules.validPreset","rules.validRecipe","rules.validBooleanProperty","rules.validDirectionalModifier","rules.validRadiusShape","rules.noImportant","rules.validSubElement","rules.noNestedStateMap","rules.staticNoDynamicValues","rules.staticValidSelector","rules.preferShorthandProperty","rules.validTransition","rules.requireDefaultState","rules.noUnknownStateAlias","rules.noRawColorValues","rules.noRawTransitionDuration","rules.noRawMotionDuration","rules.noStylesProp","rules.noStyleProp","rules.noClassNameProp","rules.noProtectedRestyle","rules.consistentTokenUsage","rules.noRuntimeStylesMutation","rules.noStyleSpread","rules.validStateDefinition","rules.noOwnAtRoot","rules.noIgnoredPseudoElementState","rules.validDefaultStateOrder","rules.preferAutoCalc","rules.preferStateNegation","rules.preferCustomPropertySyntax","rules.preferHide","rules.preferDirectionalShorthand","rules.preferLonghandProperty"],"sources":["../src/index.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport type { TSESLint } from '@typescript-eslint/utils';\nimport * as rules from './rules/index.js';\nimport { recommended, strict } from './configs.js';\n\nconst ruleMap: Record<string, TSESLint.RuleModule<string, unknown[]>> = {\n 'known-property': rules.knownProperty,\n 'valid-value': rules.validValue,\n 'valid-color-token': rules.validColorToken,\n 'valid-custom-unit': rules.validCustomUnit,\n 'valid-state-key': rules.validStateKey,\n 'valid-styles-structure': rules.validStylesStructure,\n 'no-nested-selector': rules.noNestedSelector,\n 'no-state-in-selector': rules.noStateInSelector,\n 'prefer-element-selector': rules.preferElementSelector,\n 'valid-custom-property': rules.validCustomProperty,\n 'valid-preset': rules.validPreset,\n 'valid-recipe': rules.validRecipe,\n 'valid-boolean-property': rules.validBooleanProperty,\n 'valid-directional-modifier': rules.validDirectionalModifier,\n 'valid-radius-shape': rules.validRadiusShape,\n 'no-important': rules.noImportant,\n 'valid-sub-element': rules.validSubElement,\n 'no-nested-state-map': rules.noNestedStateMap,\n 'static-no-dynamic-values': rules.staticNoDynamicValues,\n 'static-valid-selector': rules.staticValidSelector,\n 'prefer-shorthand-property': rules.preferShorthandProperty,\n 'valid-transition': rules.validTransition,\n 'require-default-state': rules.requireDefaultState,\n 'no-unknown-state-alias': rules.noUnknownStateAlias,\n 'no-raw-color-values': rules.noRawColorValues,\n 'no-raw-transition-duration': rules.noRawTransitionDuration,\n 'no-raw-motion-duration': rules.noRawMotionDuration,\n 'no-styles-prop': rules.noStylesProp,\n 'no-style-prop': rules.noStyleProp,\n 'no-classname-prop': rules.noClassNameProp,\n 'no-protected-restyle': rules.noProtectedRestyle,\n 'consistent-token-usage': rules.consistentTokenUsage,\n 'no-runtime-styles-mutation': rules.noRuntimeStylesMutation,\n 'no-style-spread': rules.noStyleSpread,\n 'valid-state-definition': rules.validStateDefinition,\n 'no-own-at-root': rules.noOwnAtRoot,\n 'no-ignored-pseudo-element-state': rules.noIgnoredPseudoElementState,\n 'valid-default-state-order': rules.validDefaultStateOrder,\n 'prefer-auto-calc': rules.preferAutoCalc,\n 'prefer-state-negation': rules.preferStateNegation,\n 'prefer-custom-property-syntax': rules.preferCustomPropertySyntax,\n 'prefer-hide': rules.preferHide,\n 'prefer-directional-shorthand': rules.preferDirectionalShorthand,\n 'prefer-longhand-property': rules.preferLonghandProperty,\n};\n\n// Read from package.json so `meta.version` cannot drift from the released\n// version, as the previous hardcoded literal had. `../package.json` resolves to\n// the package root from both `src/` and the unbundled `dist/`.\nconst { version } = createRequire(import.meta.url)('../package.json') as {\n version: string;\n};\n\nconst plugin = {\n meta: {\n name: '@tenphi/eslint-plugin-tasty',\n version,\n },\n rules: ruleMap,\n configs: {\n recommended: {\n plugins: {\n get tasty() {\n return plugin;\n },\n },\n rules: recommended,\n },\n strict: {\n plugins: {\n get tasty() {\n return plugin;\n },\n },\n rules: strict,\n },\n },\n} satisfies TSESLint.FlatConfig.Plugin & {\n configs: Record<string, TSESLint.FlatConfig.Config>;\n};\n\nexport default plugin;\n\nexport { recommended, strict } from './configs.js';\nexport type { TypeAwareJSXOptions } from './type-aware-jsx.js';\nexport type {\n TastyValidationConfig,\n ResolvedConfig,\n StyleFunctionConfig,\n ProtectedComponentConfig,\n} from './types.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAM,UAAkE;CACtE,kBAAkBA;CAClB,eAAeC;CACf,qBAAqBC;CACrB,qBAAqBC;CACrB,mBAAmBC;CACnB,0BAA0BC;CAC1B,sBAAsBC;CACtB,wBAAwBC;CACxB,2BAA2BC;CAC3B,yBAAyBC;CACzB,gBAAgBC;CAChB,gBAAgBC;CAChB,0BAA0BC;CAC1B,8BAA8BC;CAC9B,sBAAsBC;CACtB,gBAAgBC;CAChB,qBAAqBC;CACrB,uBAAuBC;CACvB,4BAA4BC;CAC5B,yBAAyBC;CACzB,6BAA6BC;CAC7B,oBAAoBC;CACpB,yBAAyBC;CACzB,0BAA0BC;CAC1B,uBAAuBC;CACvB,8BAA8BC;CAC9B,0BAA0BC;CAC1B,kBAAkBC;CAClB,iBAAiBC;CACjB,qBAAqBC;CACrB,wBAAwBC;CACxB,0BAA0BC;CAC1B,8BAA8BC;CAC9B,mBAAmBC;CACnB,0BAA0BC;CAC1B,kBAAkBC;CAClB,mCAAmCC;CACnC,6BAA6BC;CAC7B,oBAAoBC;CACpB,yBAAyBC;CACzB,iCAAiCC;CACjC,eAAeC;CACf,gCAAgCC;CAChC,4BAA4BC;CAC7B;AAKD,MAAM,EAAE,YAAY,cAAc,OAAO,KAAK,IAAI,CAAC,kBAAkB;AAIrE,MAAM,SAAS;CACb,MAAM;EACJ,MAAM;EACN;EACD;CACD,OAAO;CACP,SAAS;EACP,aAAa;GACX,SAAS,EACP,IAAI,QAAQ;AACV,WAAO;MAEV;GACD,OAAO;GACR;EACD,QAAQ;GACN,SAAS,EACP,IAAI,QAAQ;AACV,WAAO;MAEV;GACD,OAAO;GACR;EACF;CACF"}
1
+ {"version":3,"file":"index.js","names":["rules.knownProperty","rules.validValue","rules.validColorToken","rules.validCustomUnit","rules.validStateKey","rules.validStylesStructure","rules.noNestedSelector","rules.noStateInSelector","rules.preferElementSelector","rules.validCustomProperty","rules.validPreset","rules.validRecipe","rules.validBooleanProperty","rules.validDirectionalModifier","rules.validRadiusShape","rules.noImportant","rules.validSubElement","rules.noNestedStateMap","rules.staticNoDynamicValues","rules.staticValidSelector","rules.preferShorthandProperty","rules.validTransition","rules.requireDefaultState","rules.noUnknownStateAlias","rules.noRawColorValues","rules.noRawTransitionDuration","rules.noRawMotionDuration","rules.noStylesProp","rules.noStyleProp","rules.noClassNameProp","rules.noProtectedRestyle","rules.consistentTokenUsage","rules.noRuntimeStylesMutation","rules.noStyleSpread","rules.validStateDefinition","rules.noOwnAtRoot","rules.noIgnoredPseudoElementState","rules.validDefaultStateOrder","rules.preferAutoCalc","rules.preferStateNegation","rules.preferCustomPropertySyntax","rules.preferHide","rules.preferDirectionalShorthand","rules.preferLonghandProperty"],"sources":["../src/index.ts"],"sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport * as rules from './rules/index.js';\nimport { recommended, strict } from './configs.js';\nimport { version } from './version.js';\n\nconst ruleMap: Record<string, TSESLint.RuleModule<string, unknown[]>> = {\n 'known-property': rules.knownProperty,\n 'valid-value': rules.validValue,\n 'valid-color-token': rules.validColorToken,\n 'valid-custom-unit': rules.validCustomUnit,\n 'valid-state-key': rules.validStateKey,\n 'valid-styles-structure': rules.validStylesStructure,\n 'no-nested-selector': rules.noNestedSelector,\n 'no-state-in-selector': rules.noStateInSelector,\n 'prefer-element-selector': rules.preferElementSelector,\n 'valid-custom-property': rules.validCustomProperty,\n 'valid-preset': rules.validPreset,\n 'valid-recipe': rules.validRecipe,\n 'valid-boolean-property': rules.validBooleanProperty,\n 'valid-directional-modifier': rules.validDirectionalModifier,\n 'valid-radius-shape': rules.validRadiusShape,\n 'no-important': rules.noImportant,\n 'valid-sub-element': rules.validSubElement,\n 'no-nested-state-map': rules.noNestedStateMap,\n 'static-no-dynamic-values': rules.staticNoDynamicValues,\n 'static-valid-selector': rules.staticValidSelector,\n 'prefer-shorthand-property': rules.preferShorthandProperty,\n 'valid-transition': rules.validTransition,\n 'require-default-state': rules.requireDefaultState,\n 'no-unknown-state-alias': rules.noUnknownStateAlias,\n 'no-raw-color-values': rules.noRawColorValues,\n 'no-raw-transition-duration': rules.noRawTransitionDuration,\n 'no-raw-motion-duration': rules.noRawMotionDuration,\n 'no-styles-prop': rules.noStylesProp,\n 'no-style-prop': rules.noStyleProp,\n 'no-classname-prop': rules.noClassNameProp,\n 'no-protected-restyle': rules.noProtectedRestyle,\n 'consistent-token-usage': rules.consistentTokenUsage,\n 'no-runtime-styles-mutation': rules.noRuntimeStylesMutation,\n 'no-style-spread': rules.noStyleSpread,\n 'valid-state-definition': rules.validStateDefinition,\n 'no-own-at-root': rules.noOwnAtRoot,\n 'no-ignored-pseudo-element-state': rules.noIgnoredPseudoElementState,\n 'valid-default-state-order': rules.validDefaultStateOrder,\n 'prefer-auto-calc': rules.preferAutoCalc,\n 'prefer-state-negation': rules.preferStateNegation,\n 'prefer-custom-property-syntax': rules.preferCustomPropertySyntax,\n 'prefer-hide': rules.preferHide,\n 'prefer-directional-shorthand': rules.preferDirectionalShorthand,\n 'prefer-longhand-property': rules.preferLonghandProperty,\n};\n\nconst plugin = {\n meta: {\n name: '@tenphi/eslint-plugin-tasty',\n version,\n },\n rules: ruleMap,\n configs: {\n recommended: {\n plugins: {\n get tasty() {\n return plugin;\n },\n },\n rules: recommended,\n },\n strict: {\n plugins: {\n get tasty() {\n return plugin;\n },\n },\n rules: strict,\n },\n },\n} satisfies TSESLint.FlatConfig.Plugin & {\n configs: Record<string, TSESLint.FlatConfig.Config>;\n};\n\nexport default plugin;\n\nexport { recommended, strict } from './configs.js';\nexport type { TypeAwareJSXOptions } from './type-aware-jsx.js';\nexport type {\n TastyValidationConfig,\n ResolvedConfig,\n StyleFunctionConfig,\n ProtectedComponentConfig,\n} from './types.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAM,UAAkE;CACtE,kBAAkBA;CAClB,eAAeC;CACf,qBAAqBC;CACrB,qBAAqBC;CACrB,mBAAmBC;CACnB,0BAA0BC;CAC1B,sBAAsBC;CACtB,wBAAwBC;CACxB,2BAA2BC;CAC3B,yBAAyBC;CACzB,gBAAgBC;CAChB,gBAAgBC;CAChB,0BAA0BC;CAC1B,8BAA8BC;CAC9B,sBAAsBC;CACtB,gBAAgBC;CAChB,qBAAqBC;CACrB,uBAAuBC;CACvB,4BAA4BC;CAC5B,yBAAyBC;CACzB,6BAA6BC;CAC7B,oBAAoBC;CACpB,yBAAyBC;CACzB,0BAA0BC;CAC1B,uBAAuBC;CACvB,8BAA8BC;CAC9B,0BAA0BC;CAC1B,kBAAkBC;CAClB,iBAAiBC;CACjB,qBAAqBC;CACrB,wBAAwBC;CACxB,0BAA0BC;CAC1B,8BAA8BC;CAC9B,mBAAmBC;CACnB,0BAA0BC;CAC1B,kBAAkBC;CAClB,mCAAmCC;CACnC,6BAA6BC;CAC7B,oBAAoBC;CACpB,yBAAyBC;CACzB,iCAAiCC;CACjC,eAAeC;CACf,gCAAgCC;CAChC,4BAA4BC;CAC7B;AAED,MAAM,SAAS;CACb,MAAM;EACJ,MAAM;EACN;EACD;CACD,OAAO;CACP,SAAS;EACP,aAAa;GACX,SAAS,EACP,IAAI,QAAQ;AACV,WAAO;MAEV;GACD,OAAO;GACR;EACD,QAAQ;GACN,SAAS,EACP,IAAI,QAAQ;AACV,WAAO;MAEV;GACD,OAAO;GACR;EACF;CACF"}
@@ -5,6 +5,8 @@ import { checkBracketBalance, scanTokens } from "./utils.js";
5
5
  const RE_UNIT_NUM = /^[+-]?(?:\d*\.\d+|\d+)([a-z][a-z0-9]*)$/;
6
6
  const RE_NUMBER = /^[+-]?(?:\d*\.\d+|\d+)$/;
7
7
  const RE_CSS_UNIT_NUM = /^[+-]?(?:\d*\.\d+|\d+)([a-z%]+)$/;
8
+ /** An unspaced `<ratio>`, such as `16/10`. */
9
+ const RE_RATIO = /^(?:\d*\.\d+|\d+)\/(?:\d*\.\d+|\d+)$/;
8
10
  const COLOR_FUNCS = new Set([
9
11
  "rgb",
10
12
  "rgba",
@@ -479,6 +481,10 @@ function classifyToken(raw, offset, errors, opts) {
479
481
  value: parseFloat(token),
480
482
  raw: token
481
483
  };
484
+ if (RE_RATIO.test(token)) return {
485
+ type: "ratio",
486
+ raw: token
487
+ };
482
488
  if (token === "@inherit") return {
483
489
  type: "keyword",
484
490
  value: token
@@ -1 +1 @@
1
- {"version":3,"file":"value-parser.js","names":[],"sources":["../../src/parsers/value-parser.ts"],"sourcesContent":["import { scanTokens, checkBracketBalance } from './utils.js';\nimport {\n BUILT_IN_UNITS,\n CSS_UNITS,\n NAMED_CSS_COLORS,\n SYSTEM_COLORS,\n} from '../constants.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ValueToken =\n | { type: 'color-token'; name: string; opacity?: string; raw: string }\n | { type: 'color-ref'; name: string; raw: string }\n /** A CSS named color (`rebeccapurple`) or system color (`Canvas`). */\n | { type: 'color-keyword'; raw: string }\n | { type: 'custom-prop'; name: string; raw: string }\n | { type: 'custom-prop-ref'; name: string; raw: string }\n | { type: 'custom-unit'; value: number; unit: string; raw: string }\n | { type: 'css-unit'; value: number; unit: string; raw: string }\n | { type: 'number'; value: number; raw: string }\n | { type: 'keyword'; value: string }\n | { type: 'css-function'; name: string; args: string; raw: string }\n /**\n * A Tasty CSS `@function` call: `$$name(args)` (emits native `--name(args)`).\n * Distinct from `custom-prop-ref`, which is the bare `$$name` form that\n * `transition` uses to name a custom property.\n */\n | { type: 'tasty-function'; name: string; args: string; raw: string }\n | { type: 'string'; value: string; raw: string }\n | { type: 'important'; raw: string }\n | { type: 'group-expr'; inner: string; raw: string }\n | { type: 'unknown'; raw: string };\n\nexport interface ValueError {\n message: string;\n offset: number;\n length: number;\n raw?: string;\n}\n\nexport interface ValuePart {\n tokens: ValueToken[];\n}\n\nexport interface ValueGroup {\n parts: ValuePart[];\n}\n\nexport interface ValueParseResult {\n groups: ValueGroup[];\n errors: ValueError[];\n}\n\nexport interface ValueParserOptions {\n knownUnits?: Set<string> | string[];\n knownFuncs?: Set<string> | string[];\n skipUnitValidation?: boolean;\n skipFuncValidation?: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst RE_UNIT_NUM = /^[+-]?(?:\\d*\\.\\d+|\\d+)([a-z][a-z0-9]*)$/;\nconst RE_NUMBER = /^[+-]?(?:\\d*\\.\\d+|\\d+)$/;\nconst RE_CSS_UNIT_NUM = /^[+-]?(?:\\d*\\.\\d+|\\d+)([a-z%]+)$/;\n\nconst COLOR_FUNCS = new Set([\n 'rgb',\n 'rgba',\n 'hsl',\n 'hsla',\n 'hwb',\n 'lab',\n 'lch',\n 'oklab',\n 'oklch',\n 'color',\n 'device-cmyk',\n 'gray',\n 'color-mix',\n 'color-contrast',\n]);\n\nconst CSS_FUNCS = new Set([\n 'calc',\n 'calc-size',\n 'min',\n 'max',\n 'clamp',\n 'abs',\n 'sign',\n 'round',\n 'mod',\n 'rem',\n 'sin',\n 'cos',\n 'tan',\n 'asin',\n 'acos',\n 'atan',\n 'atan2',\n 'pow',\n 'sqrt',\n 'hypot',\n 'log',\n 'exp',\n 'var',\n 'env',\n 'attr',\n 'counter',\n 'counters',\n 'image-set',\n 'cross-fade',\n 'image',\n 'paint',\n 'element',\n 'linear-gradient',\n 'radial-gradient',\n 'conic-gradient',\n 'repeating-linear-gradient',\n 'repeating-radial-gradient',\n 'repeating-conic-gradient',\n 'url',\n 'fit-content',\n 'minmax',\n 'repeat',\n 'cubic-bezier',\n 'steps',\n 'linear',\n 'rotate',\n 'scale',\n 'translate',\n 'skew',\n 'matrix',\n 'perspective',\n 'rotate3d',\n 'rotateX',\n 'rotateY',\n 'rotateZ',\n 'scale3d',\n 'scaleX',\n 'scaleY',\n 'scaleZ',\n 'translate3d',\n 'translateX',\n 'translateY',\n 'translateZ',\n 'skewX',\n 'skewY',\n 'matrix3d',\n 'blur',\n 'brightness',\n 'contrast',\n 'drop-shadow',\n 'grayscale',\n 'hue-rotate',\n 'invert',\n 'opacity',\n 'saturate',\n 'sepia',\n 'polygon',\n 'circle',\n 'ellipse',\n 'inset',\n 'path',\n 'xywh',\n 'rect',\n 'ray',\n 'light-dark',\n 'anchor',\n 'anchor-size',\n 'scroll',\n 'view',\n 'symbols',\n]);\n\nconst VALUE_KEYWORDS = new Set([\n 'auto',\n 'none',\n 'normal',\n 'inherit',\n 'initial',\n 'unset',\n 'revert',\n 'revert-layer',\n 'max-content',\n 'min-content',\n 'fit-content',\n 'stretch',\n 'transparent',\n 'currentcolor',\n 'currentColor',\n // display\n 'block',\n 'inline',\n 'inline-block',\n 'flex',\n 'inline-flex',\n 'grid',\n 'inline-grid',\n 'contents',\n 'table',\n 'table-row',\n 'table-cell',\n 'list-item',\n 'flow-root',\n // position\n 'static',\n 'relative',\n 'absolute',\n 'fixed',\n 'sticky',\n // overflow\n 'visible',\n 'hidden',\n 'scroll',\n 'clip',\n 'overlay',\n // flex/align\n 'center',\n 'start',\n 'end',\n 'flex-start',\n 'flex-end',\n 'space-between',\n 'space-around',\n 'space-evenly',\n 'baseline',\n // flow\n 'row',\n 'column',\n 'row-reverse',\n 'column-reverse',\n 'wrap',\n 'nowrap',\n 'dense',\n // border\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'outset',\n // directional\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n // radius shapes\n 'round',\n 'ellipse',\n 'leaf',\n 'backleaf',\n // dimension modifiers\n 'min',\n 'max',\n // text\n 'bold',\n 'bolder',\n 'lighter',\n 'italic',\n 'oblique',\n 'uppercase',\n 'lowercase',\n 'capitalize',\n 'line-through',\n 'underline',\n 'overline',\n 'wavy',\n // cursor\n 'pointer',\n 'default',\n 'text',\n 'move',\n 'grab',\n 'grabbing',\n 'not-allowed',\n 'crosshair',\n 'wait',\n 'help',\n 'col-resize',\n 'row-resize',\n 'n-resize',\n 's-resize',\n 'e-resize',\n 'w-resize',\n 'ne-resize',\n 'nw-resize',\n 'se-resize',\n 'sw-resize',\n 'ew-resize',\n 'ns-resize',\n 'zoom-in',\n 'zoom-out',\n // misc\n 'cover',\n 'contain',\n 'fill',\n 'no-repeat',\n 'repeat-x',\n 'repeat-y',\n 'border-box',\n 'padding-box',\n 'content-box',\n 'break-word',\n 'break-all',\n 'keep-all',\n 'anywhere',\n 'pre',\n 'pre-wrap',\n 'pre-line',\n 'balance',\n 'smooth',\n 'horizontal',\n 'vertical',\n 'both',\n 'mandatory',\n 'proximity',\n // white-space\n 'collapse',\n 'preserve',\n 'preserve-breaks',\n 'break-spaces',\n // text-wrap\n 'pretty',\n 'stable',\n // will-change\n 'transform',\n 'opacity',\n // animation\n 'infinite',\n 'alternate',\n 'alternate-reverse',\n 'reverse',\n 'forwards',\n 'backwards',\n 'running',\n 'paused',\n 'ease',\n 'ease-in',\n 'ease-out',\n 'ease-in-out',\n 'step-start',\n 'step-end',\n // scrollbar\n 'thin',\n 'always',\n 'both-edges',\n // width/height\n 'fixed',\n // shadow\n 'inset',\n // textOverflow\n 'clip',\n // other\n 'ltr',\n 'rtl',\n 'embed',\n 'isolate',\n 'isolate-override',\n 'plaintext',\n 'horizontal-tb',\n 'vertical-rl',\n 'vertical-lr',\n 'sideways-rl',\n 'sideways-lr',\n 'monospace',\n 'serif',\n 'sans-serif',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'to',\n // misc\n 'strong',\n 'tight',\n 'icon',\n]);\n\n// ============================================================================\n// Classifier\n// ============================================================================\n\nfunction toSet(input?: Set<string> | string[]): Set<string> {\n if (!input) return new Set();\n return input instanceof Set ? input : new Set(input);\n}\n\nfunction classifyToken(\n raw: string,\n offset: number,\n errors: ValueError[],\n opts: ValueParserOptions,\n): ValueToken {\n const token = raw.trim();\n if (!token) return { type: 'keyword', value: '' };\n\n // Quoted strings\n if (\n (token.startsWith('\"') && token.endsWith('\"')) ||\n (token.startsWith(\"'\") && token.endsWith(\"'\"))\n ) {\n return { type: 'string', value: token.slice(1, -1), raw: token };\n }\n\n // !important\n if (token === '!important') {\n return { type: 'important', raw: token };\n }\n\n // Double prefix: $$name(...) is a Tasty `@function` call; bare $$name is the\n // custom-property reference `transition` uses. The call form must be checked\n // first, or the bare-name regex rejects `$$negative(10px)` outright.\n if (token.startsWith('$$') || token.startsWith('##')) {\n const call = classifyTastyFunctionCall(token, offset, errors);\n if (call) return call;\n }\n\n // Double prefix: $$name (custom property reference for transitions)\n if (token.startsWith('$$')) {\n const name = token.slice(2);\n if (/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n return { type: 'custom-prop-ref', name, raw: token };\n }\n errors.push({\n message: `Invalid custom property reference '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // Double prefix: ##name (color reference for transitions)\n if (token.startsWith('##')) {\n const name = token.slice(2);\n if (/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n return { type: 'color-ref', name, raw: token };\n }\n errors.push({\n message: `Invalid color reference '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // Custom property: $name\n if (token.startsWith('$')) {\n const name = token.slice(1);\n if (/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n return { type: 'custom-prop', name, raw: token };\n }\n errors.push({\n message: `Invalid custom property syntax '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // Color token: #name, #name.N, #name.$prop, or bare # (error)\n if (token.startsWith('#')) {\n if (token.length === 1) {\n errors.push({\n message: 'Empty color token name.',\n offset,\n length: 1,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n return classifyColorToken(token, offset, errors);\n }\n\n // Parenthesized expression: (expr) — fallback, auto-calc, etc.\n if (token.startsWith('(') && token.endsWith(')')) {\n return { type: 'group-expr', inner: token.slice(1, -1), raw: token };\n }\n\n // Function call: name(...)\n const openIdx = token.indexOf('(');\n if (openIdx > 0 && token.endsWith(')')) {\n const fname = token.slice(0, openIdx);\n const args = token.slice(openIdx + 1, -1);\n\n if (opts.skipFuncValidation) {\n return { type: 'css-function', name: fname, args, raw: token };\n }\n\n const knownFuncs = toSet(opts.knownFuncs);\n\n if (\n COLOR_FUNCS.has(fname) ||\n CSS_FUNCS.has(fname) ||\n knownFuncs.has(fname)\n ) {\n return { type: 'css-function', name: fname, args, raw: token };\n }\n\n // Unknown function — still return as css-function but flag it\n errors.push({\n message: `Unknown function '${fname}()'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'css-function', name: fname, args, raw: token };\n }\n\n // Unit number: 2x, 1.5r, 10px, 50%, 1fr\n const unitMatch = token.match(RE_UNIT_NUM);\n if (unitMatch) {\n const unit = unitMatch[1];\n const numVal = parseFloat(token.slice(0, -unit.length));\n\n if (opts.skipUnitValidation) {\n return { type: 'custom-unit', value: numVal, unit, raw: token };\n }\n\n const knownUnits = toSet(opts.knownUnits);\n\n if (BUILT_IN_UNITS.has(unit) || knownUnits.has(unit)) {\n return { type: 'custom-unit', value: numVal, unit, raw: token };\n }\n if (CSS_UNITS.has(unit)) {\n return { type: 'css-unit', value: numVal, unit, raw: token };\n }\n\n errors.push({\n message: `Unknown unit '${unit}' in '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // CSS unit with % (RE_UNIT_NUM doesn't match % since it expects alpha)\n const cssUnitMatch = token.match(RE_CSS_UNIT_NUM);\n if (cssUnitMatch) {\n const unit = cssUnitMatch[1];\n const numVal = parseFloat(token.slice(0, -unit.length));\n if (CSS_UNITS.has(unit)) {\n return { type: 'css-unit', value: numVal, unit, raw: token };\n }\n }\n\n // Plain number\n if (RE_NUMBER.test(token)) {\n return { type: 'number', value: parseFloat(token), raw: token };\n }\n\n // Tasty merge directive (@inherit)\n if (token === '@inherit') {\n return { type: 'keyword', value: token };\n }\n\n // Known keyword\n if (VALUE_KEYWORDS.has(token) || VALUE_KEYWORDS.has(token.toLowerCase())) {\n return { type: 'keyword', value: token };\n }\n\n // Color keyword: no token syntax, so the keyword itself is the color.\n // Matched case-insensitively, as CSS and Tasty match them.\n const lower = token.toLowerCase();\n if (NAMED_CSS_COLORS.has(lower) || SYSTEM_COLORS.has(lower)) {\n return { type: 'color-keyword', raw: token };\n }\n\n // CSS custom property function var(--name)\n if (token.startsWith('var(') && token.endsWith(')')) {\n return {\n type: 'css-function',\n name: 'var',\n args: token.slice(4, -1),\n raw: token,\n };\n }\n\n // Unknown token\n return { type: 'unknown', raw: token };\n}\n\n/**\n * Classify a `$$name(...)` / `##name(...)` Tasty `@function` call.\n *\n * Returns `null` when the token is not a call, so the caller falls through to the\n * bare `$$name` / `##name` reference handling that `transition` relies on.\n */\nfunction classifyTastyFunctionCall(\n token: string,\n offset: number,\n errors: ValueError[],\n): ValueToken | null {\n const openIdx = token.indexOf('(');\n\n if (openIdx <= 2 || !token.endsWith(')')) return null;\n\n const name = token.slice(2, openIdx);\n const args = token.slice(openIdx + 1, -1);\n\n if (!/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n errors.push({\n message: `Invalid function name in '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n return { type: 'tasty-function', name, args, raw: token };\n}\n\nfunction classifyColorToken(\n token: string,\n offset: number,\n errors: ValueError[],\n): ValueToken {\n const raw = token;\n\n // Strip leading #\n const name = token.slice(1);\n\n if (name.length === 0) {\n errors.push({\n message: 'Empty color token name.',\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n // Check for opacity suffix\n const dotIndex = name.indexOf('.');\n if (dotIndex !== -1) {\n const tokenName = name.slice(0, dotIndex);\n const opacitySuffix = name.slice(dotIndex + 1);\n\n if (tokenName.length === 0) {\n errors.push({\n message: 'Empty color token name before opacity.',\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n // Dynamic opacity from CSS custom property\n if (opacitySuffix.startsWith('$')) {\n return {\n type: 'color-token',\n name: tokenName,\n opacity: opacitySuffix,\n raw,\n };\n }\n\n if (opacitySuffix.length === 0) {\n errors.push({\n message: 'Trailing dot with no opacity value.',\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n // Tasty reads the digits as a decimal fraction (`.5` and `.50` are 50%,\n // `.150` is 15%), so any digit string is in range.\n if (!/^\\d+$/.test(opacitySuffix)) {\n errors.push({\n message: /^-\\d+$/.test(opacitySuffix)\n ? 'Opacity cannot be negative.'\n : `Invalid opacity value '${opacitySuffix}'.`,\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n return {\n type: 'color-token',\n name: tokenName,\n opacity: opacitySuffix,\n raw,\n };\n }\n\n return { type: 'color-token', name, raw };\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Parse a style value string into typed tokens organized by\n * comma-separated groups and slash-separated parts.\n */\nexport function parseValue(\n src: string,\n opts: ValueParserOptions = {},\n): ValueParseResult {\n const errors: ValueError[] = [];\n\n // Check bracket balance first\n const bracketError = checkBracketBalance(src);\n if (bracketError) {\n errors.push({\n message: bracketError.message,\n offset: bracketError.position,\n length: 1,\n });\n return { groups: [], errors };\n }\n\n const scanned = scanTokens(src);\n\n const groups: ValueGroup[] = [];\n let currentParts: ValuePart[] = [];\n let currentTokens: ValueToken[] = [];\n\n const endPart = () => {\n if (currentTokens.length > 0) {\n currentParts.push({ tokens: currentTokens });\n currentTokens = [];\n }\n };\n\n const endGroup = () => {\n endPart();\n if (currentParts.length > 0) {\n groups.push({ parts: currentParts });\n } else {\n groups.push({ parts: [{ tokens: [] }] });\n }\n currentParts = [];\n };\n\n for (const scanned_token of scanned) {\n if (scanned_token.value) {\n const classified = classifyToken(\n scanned_token.value,\n scanned_token.offset,\n errors,\n opts,\n );\n currentTokens.push(classified);\n }\n if (scanned_token.isSlash) endPart();\n if (scanned_token.isComma) endGroup();\n }\n\n // Push final group\n if (\n currentTokens.length > 0 ||\n currentParts.length > 0 ||\n groups.length === 0\n ) {\n endGroup();\n }\n\n return { groups, errors };\n}\n\n/**\n * Extract all tokens of a specific type from a parse result.\n */\nexport function extractTokensByType<T extends ValueToken['type']>(\n result: ValueParseResult,\n type: T,\n): Extract<ValueToken, { type: T }>[] {\n const tokens: Extract<ValueToken, { type: T }>[] = [];\n for (const group of result.groups) {\n for (const part of group.parts) {\n for (const token of part.tokens) {\n if (token.type === type) {\n tokens.push(token as Extract<ValueToken, { type: T }>);\n }\n }\n }\n }\n return tokens;\n}\n\n/**\n * Get a flat list of all tokens from a parse result.\n */\nexport function flattenTokens(result: ValueParseResult): ValueToken[] {\n const tokens: ValueToken[] = [];\n for (const group of result.groups) {\n for (const part of group.parts) {\n tokens.push(...part.tokens);\n }\n }\n return tokens;\n}\n"],"mappings":";;;;AAkEA,MAAM,cAAc;AACpB,MAAM,YAAY;AAClB,MAAM,kBAAkB;AAExB,MAAM,cAAc,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,YAAY,IAAI,IAAI;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;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"}
1
+ {"version":3,"file":"value-parser.js","names":[],"sources":["../../src/parsers/value-parser.ts"],"sourcesContent":["import { scanTokens, checkBracketBalance } from './utils.js';\nimport {\n BUILT_IN_UNITS,\n CSS_UNITS,\n NAMED_CSS_COLORS,\n SYSTEM_COLORS,\n} from '../constants.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ValueToken =\n | { type: 'color-token'; name: string; opacity?: string; raw: string }\n | { type: 'color-ref'; name: string; raw: string }\n /** A CSS named color (`rebeccapurple`) or system color (`Canvas`). */\n | { type: 'color-keyword'; raw: string }\n | { type: 'custom-prop'; name: string; raw: string }\n | { type: 'custom-prop-ref'; name: string; raw: string }\n | { type: 'custom-unit'; value: number; unit: string; raw: string }\n | { type: 'css-unit'; value: number; unit: string; raw: string }\n | { type: 'number'; value: number; raw: string }\n /** An unspaced `<ratio>`, such as `16/10`; the spaced form is two parts. */\n | { type: 'ratio'; raw: string }\n | { type: 'keyword'; value: string }\n | { type: 'css-function'; name: string; args: string; raw: string }\n /**\n * A Tasty CSS `@function` call: `$$name(args)` (emits native `--name(args)`).\n * Distinct from `custom-prop-ref`, which is the bare `$$name` form that\n * `transition` uses to name a custom property.\n */\n | { type: 'tasty-function'; name: string; args: string; raw: string }\n | { type: 'string'; value: string; raw: string }\n | { type: 'important'; raw: string }\n | { type: 'group-expr'; inner: string; raw: string }\n | { type: 'unknown'; raw: string };\n\nexport interface ValueError {\n message: string;\n offset: number;\n length: number;\n raw?: string;\n}\n\nexport interface ValuePart {\n tokens: ValueToken[];\n}\n\nexport interface ValueGroup {\n parts: ValuePart[];\n}\n\nexport interface ValueParseResult {\n groups: ValueGroup[];\n errors: ValueError[];\n}\n\nexport interface ValueParserOptions {\n knownUnits?: Set<string> | string[];\n knownFuncs?: Set<string> | string[];\n skipUnitValidation?: boolean;\n skipFuncValidation?: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst RE_UNIT_NUM = /^[+-]?(?:\\d*\\.\\d+|\\d+)([a-z][a-z0-9]*)$/;\nconst RE_NUMBER = /^[+-]?(?:\\d*\\.\\d+|\\d+)$/;\nconst RE_CSS_UNIT_NUM = /^[+-]?(?:\\d*\\.\\d+|\\d+)([a-z%]+)$/;\n/** An unspaced `<ratio>`, such as `16/10`. */\nconst RE_RATIO = /^(?:\\d*\\.\\d+|\\d+)\\/(?:\\d*\\.\\d+|\\d+)$/;\n\nconst COLOR_FUNCS = new Set([\n 'rgb',\n 'rgba',\n 'hsl',\n 'hsla',\n 'hwb',\n 'lab',\n 'lch',\n 'oklab',\n 'oklch',\n 'color',\n 'device-cmyk',\n 'gray',\n 'color-mix',\n 'color-contrast',\n]);\n\nconst CSS_FUNCS = new Set([\n 'calc',\n 'calc-size',\n 'min',\n 'max',\n 'clamp',\n 'abs',\n 'sign',\n 'round',\n 'mod',\n 'rem',\n 'sin',\n 'cos',\n 'tan',\n 'asin',\n 'acos',\n 'atan',\n 'atan2',\n 'pow',\n 'sqrt',\n 'hypot',\n 'log',\n 'exp',\n 'var',\n 'env',\n 'attr',\n 'counter',\n 'counters',\n 'image-set',\n 'cross-fade',\n 'image',\n 'paint',\n 'element',\n 'linear-gradient',\n 'radial-gradient',\n 'conic-gradient',\n 'repeating-linear-gradient',\n 'repeating-radial-gradient',\n 'repeating-conic-gradient',\n 'url',\n 'fit-content',\n 'minmax',\n 'repeat',\n 'cubic-bezier',\n 'steps',\n 'linear',\n 'rotate',\n 'scale',\n 'translate',\n 'skew',\n 'matrix',\n 'perspective',\n 'rotate3d',\n 'rotateX',\n 'rotateY',\n 'rotateZ',\n 'scale3d',\n 'scaleX',\n 'scaleY',\n 'scaleZ',\n 'translate3d',\n 'translateX',\n 'translateY',\n 'translateZ',\n 'skewX',\n 'skewY',\n 'matrix3d',\n 'blur',\n 'brightness',\n 'contrast',\n 'drop-shadow',\n 'grayscale',\n 'hue-rotate',\n 'invert',\n 'opacity',\n 'saturate',\n 'sepia',\n 'polygon',\n 'circle',\n 'ellipse',\n 'inset',\n 'path',\n 'xywh',\n 'rect',\n 'ray',\n 'light-dark',\n 'anchor',\n 'anchor-size',\n 'scroll',\n 'view',\n 'symbols',\n]);\n\nconst VALUE_KEYWORDS = new Set([\n 'auto',\n 'none',\n 'normal',\n 'inherit',\n 'initial',\n 'unset',\n 'revert',\n 'revert-layer',\n 'max-content',\n 'min-content',\n 'fit-content',\n 'stretch',\n 'transparent',\n 'currentcolor',\n 'currentColor',\n // display\n 'block',\n 'inline',\n 'inline-block',\n 'flex',\n 'inline-flex',\n 'grid',\n 'inline-grid',\n 'contents',\n 'table',\n 'table-row',\n 'table-cell',\n 'list-item',\n 'flow-root',\n // position\n 'static',\n 'relative',\n 'absolute',\n 'fixed',\n 'sticky',\n // overflow\n 'visible',\n 'hidden',\n 'scroll',\n 'clip',\n 'overlay',\n // flex/align\n 'center',\n 'start',\n 'end',\n 'flex-start',\n 'flex-end',\n 'space-between',\n 'space-around',\n 'space-evenly',\n 'baseline',\n // flow\n 'row',\n 'column',\n 'row-reverse',\n 'column-reverse',\n 'wrap',\n 'nowrap',\n 'dense',\n // border\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'outset',\n // directional\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n // radius shapes\n 'round',\n 'ellipse',\n 'leaf',\n 'backleaf',\n // dimension modifiers\n 'min',\n 'max',\n // text\n 'bold',\n 'bolder',\n 'lighter',\n 'italic',\n 'oblique',\n 'uppercase',\n 'lowercase',\n 'capitalize',\n 'line-through',\n 'underline',\n 'overline',\n 'wavy',\n // cursor\n 'pointer',\n 'default',\n 'text',\n 'move',\n 'grab',\n 'grabbing',\n 'not-allowed',\n 'crosshair',\n 'wait',\n 'help',\n 'col-resize',\n 'row-resize',\n 'n-resize',\n 's-resize',\n 'e-resize',\n 'w-resize',\n 'ne-resize',\n 'nw-resize',\n 'se-resize',\n 'sw-resize',\n 'ew-resize',\n 'ns-resize',\n 'zoom-in',\n 'zoom-out',\n // misc\n 'cover',\n 'contain',\n 'fill',\n 'no-repeat',\n 'repeat-x',\n 'repeat-y',\n 'border-box',\n 'padding-box',\n 'content-box',\n 'break-word',\n 'break-all',\n 'keep-all',\n 'anywhere',\n 'pre',\n 'pre-wrap',\n 'pre-line',\n 'balance',\n 'smooth',\n 'horizontal',\n 'vertical',\n 'both',\n 'mandatory',\n 'proximity',\n // white-space\n 'collapse',\n 'preserve',\n 'preserve-breaks',\n 'break-spaces',\n // text-wrap\n 'pretty',\n 'stable',\n // will-change\n 'transform',\n 'opacity',\n // animation\n 'infinite',\n 'alternate',\n 'alternate-reverse',\n 'reverse',\n 'forwards',\n 'backwards',\n 'running',\n 'paused',\n 'ease',\n 'ease-in',\n 'ease-out',\n 'ease-in-out',\n 'step-start',\n 'step-end',\n // scrollbar\n 'thin',\n 'always',\n 'both-edges',\n // width/height\n 'fixed',\n // shadow\n 'inset',\n // textOverflow\n 'clip',\n // other\n 'ltr',\n 'rtl',\n 'embed',\n 'isolate',\n 'isolate-override',\n 'plaintext',\n 'horizontal-tb',\n 'vertical-rl',\n 'vertical-lr',\n 'sideways-rl',\n 'sideways-lr',\n 'monospace',\n 'serif',\n 'sans-serif',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'to',\n // misc\n 'strong',\n 'tight',\n 'icon',\n]);\n\n// ============================================================================\n// Classifier\n// ============================================================================\n\nfunction toSet(input?: Set<string> | string[]): Set<string> {\n if (!input) return new Set();\n return input instanceof Set ? input : new Set(input);\n}\n\nfunction classifyToken(\n raw: string,\n offset: number,\n errors: ValueError[],\n opts: ValueParserOptions,\n): ValueToken {\n const token = raw.trim();\n if (!token) return { type: 'keyword', value: '' };\n\n // Quoted strings\n if (\n (token.startsWith('\"') && token.endsWith('\"')) ||\n (token.startsWith(\"'\") && token.endsWith(\"'\"))\n ) {\n return { type: 'string', value: token.slice(1, -1), raw: token };\n }\n\n // !important\n if (token === '!important') {\n return { type: 'important', raw: token };\n }\n\n // Double prefix: $$name(...) is a Tasty `@function` call; bare $$name is the\n // custom-property reference `transition` uses. The call form must be checked\n // first, or the bare-name regex rejects `$$negative(10px)` outright.\n if (token.startsWith('$$') || token.startsWith('##')) {\n const call = classifyTastyFunctionCall(token, offset, errors);\n if (call) return call;\n }\n\n // Double prefix: $$name (custom property reference for transitions)\n if (token.startsWith('$$')) {\n const name = token.slice(2);\n if (/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n return { type: 'custom-prop-ref', name, raw: token };\n }\n errors.push({\n message: `Invalid custom property reference '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // Double prefix: ##name (color reference for transitions)\n if (token.startsWith('##')) {\n const name = token.slice(2);\n if (/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n return { type: 'color-ref', name, raw: token };\n }\n errors.push({\n message: `Invalid color reference '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // Custom property: $name\n if (token.startsWith('$')) {\n const name = token.slice(1);\n if (/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n return { type: 'custom-prop', name, raw: token };\n }\n errors.push({\n message: `Invalid custom property syntax '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // Color token: #name, #name.N, #name.$prop, or bare # (error)\n if (token.startsWith('#')) {\n if (token.length === 1) {\n errors.push({\n message: 'Empty color token name.',\n offset,\n length: 1,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n return classifyColorToken(token, offset, errors);\n }\n\n // Parenthesized expression: (expr) — fallback, auto-calc, etc.\n if (token.startsWith('(') && token.endsWith(')')) {\n return { type: 'group-expr', inner: token.slice(1, -1), raw: token };\n }\n\n // Function call: name(...)\n const openIdx = token.indexOf('(');\n if (openIdx > 0 && token.endsWith(')')) {\n const fname = token.slice(0, openIdx);\n const args = token.slice(openIdx + 1, -1);\n\n if (opts.skipFuncValidation) {\n return { type: 'css-function', name: fname, args, raw: token };\n }\n\n const knownFuncs = toSet(opts.knownFuncs);\n\n if (\n COLOR_FUNCS.has(fname) ||\n CSS_FUNCS.has(fname) ||\n knownFuncs.has(fname)\n ) {\n return { type: 'css-function', name: fname, args, raw: token };\n }\n\n // Unknown function — still return as css-function but flag it\n errors.push({\n message: `Unknown function '${fname}()'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'css-function', name: fname, args, raw: token };\n }\n\n // Unit number: 2x, 1.5r, 10px, 50%, 1fr\n const unitMatch = token.match(RE_UNIT_NUM);\n if (unitMatch) {\n const unit = unitMatch[1];\n const numVal = parseFloat(token.slice(0, -unit.length));\n\n if (opts.skipUnitValidation) {\n return { type: 'custom-unit', value: numVal, unit, raw: token };\n }\n\n const knownUnits = toSet(opts.knownUnits);\n\n if (BUILT_IN_UNITS.has(unit) || knownUnits.has(unit)) {\n return { type: 'custom-unit', value: numVal, unit, raw: token };\n }\n if (CSS_UNITS.has(unit)) {\n return { type: 'css-unit', value: numVal, unit, raw: token };\n }\n\n errors.push({\n message: `Unknown unit '${unit}' in '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n // CSS unit with % (RE_UNIT_NUM doesn't match % since it expects alpha)\n const cssUnitMatch = token.match(RE_CSS_UNIT_NUM);\n if (cssUnitMatch) {\n const unit = cssUnitMatch[1];\n const numVal = parseFloat(token.slice(0, -unit.length));\n if (CSS_UNITS.has(unit)) {\n return { type: 'css-unit', value: numVal, unit, raw: token };\n }\n }\n\n // Plain number\n if (RE_NUMBER.test(token)) {\n return { type: 'number', value: parseFloat(token), raw: token };\n }\n\n // Unspaced ratio: 16/10\n if (RE_RATIO.test(token)) {\n return { type: 'ratio', raw: token };\n }\n\n // Tasty merge directive (@inherit)\n if (token === '@inherit') {\n return { type: 'keyword', value: token };\n }\n\n // Known keyword\n if (VALUE_KEYWORDS.has(token) || VALUE_KEYWORDS.has(token.toLowerCase())) {\n return { type: 'keyword', value: token };\n }\n\n // Color keyword: no token syntax, so the keyword itself is the color.\n // Matched case-insensitively, as CSS and Tasty match them.\n const lower = token.toLowerCase();\n if (NAMED_CSS_COLORS.has(lower) || SYSTEM_COLORS.has(lower)) {\n return { type: 'color-keyword', raw: token };\n }\n\n // CSS custom property function var(--name)\n if (token.startsWith('var(') && token.endsWith(')')) {\n return {\n type: 'css-function',\n name: 'var',\n args: token.slice(4, -1),\n raw: token,\n };\n }\n\n // Unknown token\n return { type: 'unknown', raw: token };\n}\n\n/**\n * Classify a `$$name(...)` / `##name(...)` Tasty `@function` call.\n *\n * Returns `null` when the token is not a call, so the caller falls through to the\n * bare `$$name` / `##name` reference handling that `transition` relies on.\n */\nfunction classifyTastyFunctionCall(\n token: string,\n offset: number,\n errors: ValueError[],\n): ValueToken | null {\n const openIdx = token.indexOf('(');\n\n if (openIdx <= 2 || !token.endsWith(')')) return null;\n\n const name = token.slice(2, openIdx);\n const args = token.slice(openIdx + 1, -1);\n\n if (!/^[a-z_][a-z0-9-_]*$/i.test(name)) {\n errors.push({\n message: `Invalid function name in '${token}'.`,\n offset,\n length: token.length,\n raw: token,\n });\n return { type: 'unknown', raw: token };\n }\n\n return { type: 'tasty-function', name, args, raw: token };\n}\n\nfunction classifyColorToken(\n token: string,\n offset: number,\n errors: ValueError[],\n): ValueToken {\n const raw = token;\n\n // Strip leading #\n const name = token.slice(1);\n\n if (name.length === 0) {\n errors.push({\n message: 'Empty color token name.',\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n // Check for opacity suffix\n const dotIndex = name.indexOf('.');\n if (dotIndex !== -1) {\n const tokenName = name.slice(0, dotIndex);\n const opacitySuffix = name.slice(dotIndex + 1);\n\n if (tokenName.length === 0) {\n errors.push({\n message: 'Empty color token name before opacity.',\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n // Dynamic opacity from CSS custom property\n if (opacitySuffix.startsWith('$')) {\n return {\n type: 'color-token',\n name: tokenName,\n opacity: opacitySuffix,\n raw,\n };\n }\n\n if (opacitySuffix.length === 0) {\n errors.push({\n message: 'Trailing dot with no opacity value.',\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n // Tasty reads the digits as a decimal fraction (`.5` and `.50` are 50%,\n // `.150` is 15%), so any digit string is in range.\n if (!/^\\d+$/.test(opacitySuffix)) {\n errors.push({\n message: /^-\\d+$/.test(opacitySuffix)\n ? 'Opacity cannot be negative.'\n : `Invalid opacity value '${opacitySuffix}'.`,\n offset,\n length: token.length,\n raw,\n });\n return { type: 'unknown', raw };\n }\n\n return {\n type: 'color-token',\n name: tokenName,\n opacity: opacitySuffix,\n raw,\n };\n }\n\n return { type: 'color-token', name, raw };\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Parse a style value string into typed tokens organized by\n * comma-separated groups and slash-separated parts.\n */\nexport function parseValue(\n src: string,\n opts: ValueParserOptions = {},\n): ValueParseResult {\n const errors: ValueError[] = [];\n\n // Check bracket balance first\n const bracketError = checkBracketBalance(src);\n if (bracketError) {\n errors.push({\n message: bracketError.message,\n offset: bracketError.position,\n length: 1,\n });\n return { groups: [], errors };\n }\n\n const scanned = scanTokens(src);\n\n const groups: ValueGroup[] = [];\n let currentParts: ValuePart[] = [];\n let currentTokens: ValueToken[] = [];\n\n const endPart = () => {\n if (currentTokens.length > 0) {\n currentParts.push({ tokens: currentTokens });\n currentTokens = [];\n }\n };\n\n const endGroup = () => {\n endPart();\n if (currentParts.length > 0) {\n groups.push({ parts: currentParts });\n } else {\n groups.push({ parts: [{ tokens: [] }] });\n }\n currentParts = [];\n };\n\n for (const scanned_token of scanned) {\n if (scanned_token.value) {\n const classified = classifyToken(\n scanned_token.value,\n scanned_token.offset,\n errors,\n opts,\n );\n currentTokens.push(classified);\n }\n if (scanned_token.isSlash) endPart();\n if (scanned_token.isComma) endGroup();\n }\n\n // Push final group\n if (\n currentTokens.length > 0 ||\n currentParts.length > 0 ||\n groups.length === 0\n ) {\n endGroup();\n }\n\n return { groups, errors };\n}\n\n/**\n * Extract all tokens of a specific type from a parse result.\n */\nexport function extractTokensByType<T extends ValueToken['type']>(\n result: ValueParseResult,\n type: T,\n): Extract<ValueToken, { type: T }>[] {\n const tokens: Extract<ValueToken, { type: T }>[] = [];\n for (const group of result.groups) {\n for (const part of group.parts) {\n for (const token of part.tokens) {\n if (token.type === type) {\n tokens.push(token as Extract<ValueToken, { type: T }>);\n }\n }\n }\n }\n return tokens;\n}\n\n/**\n * Get a flat list of all tokens from a parse result.\n */\nexport function flattenTokens(result: ValueParseResult): ValueToken[] {\n const tokens: ValueToken[] = [];\n for (const group of result.groups) {\n for (const part of group.parts) {\n tokens.push(...part.tokens);\n }\n }\n return tokens;\n}\n"],"mappings":";;;;AAoEA,MAAM,cAAc;AACpB,MAAM,YAAY;AAClB,MAAM,kBAAkB;;AAExB,MAAM,WAAW;AAEjB,MAAM,cAAc,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,YAAY,IAAI,IAAI;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAC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"}
@@ -115,7 +115,9 @@ const DISPLAY_MODS = [
115
115
  "inline-table",
116
116
  "inline-flex",
117
117
  "inline-grid",
118
- "inline-grid-lanes"
118
+ "inline-grid-lanes",
119
+ "-webkit-box",
120
+ "-webkit-inline-box"
119
121
  ];
120
122
  const PROPERTY_EXPECTATIONS = {
121
123
  fill: {
@@ -250,7 +252,10 @@ const PROPERTY_EXPECTATIONS = {
250
252
  order: VALUE_ONLY,
251
253
  zIndex: VALUE_ONLY,
252
254
  opacity: VALUE_ONLY,
253
- aspectRatio: VALUE_ONLY,
255
+ aspectRatio: {
256
+ ...VALUE_ONLY,
257
+ acceptsRatio: true
258
+ },
254
259
  lineClamp: VALUE_ONLY,
255
260
  tabSize: VALUE_ONLY,
256
261
  flow: {
@@ -1 +1 @@
1
- {"version":3,"file":"property-expectations.js","names":[],"sources":["../src/property-expectations.ts"],"sourcesContent":["/**\n * Per-property expectations for parser bucket validation.\n *\n * After parsing a value through StyleParser.process(), each group contains\n * `colors`, `values`, and `mods` arrays. This map defines what is expected\n * for each tasty property so we can flag unexpected tokens.\n *\n * - `acceptsColor`: whether Color bucket tokens are valid\n * - `acceptsMods`: whether Mod bucket tokens are valid, and if so which ones\n * - `false` = no mods accepted (any mod is an error)\n * - `true` = any mod accepted (pass-through)\n * - `string[]` = only these specific mods are accepted\n *\n * Properties NOT listed here default to PASSTHROUGH (accept everything).\n * Only add properties that have actual restrictions.\n */\n\nexport interface PropertyExpectation {\n acceptsColor: boolean;\n acceptsMods: boolean | string[];\n}\n\nconst DIRECTIONAL_MODS = ['top', 'right', 'bottom', 'left'];\n// Output modifier accepted by every box property (`padding`, `margin`,\n// `inset`, `border`, `radius`): emit the individual CSS longhands instead of\n// the shorthand, so children can selectively inherit a single side/corner.\nconst LONGHAND_MOD = 'longhand';\n// `inset` additionally accepts `dock`: pin one edge and span its full\n// length (tasty >= 2.10). Other directional properties do not.\nconst INSET_MODS = [...DIRECTIONAL_MODS, 'dock', LONGHAND_MOD];\nconst BOX_DIRECTIONAL_MODS = [...DIRECTIONAL_MODS, LONGHAND_MOD];\nconst RADIUS_DIRECTIONAL_MODS = [\n ...DIRECTIONAL_MODS,\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n LONGHAND_MOD,\n];\nconst BORDER_STYLE_MODS = [\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'inset',\n 'outset',\n 'none',\n 'hidden',\n];\nconst DIMENSION_MODS = ['min', 'max', 'fixed'];\n// The logical axis handlers take `start`/`end` in place of the four physical\n// sides, plus the same `longhand` output modifier — it emits the two native\n// start/end declarations instead of the axis shorthand.\nconst LOGICAL_EDGE_MODS = ['start', 'end', LONGHAND_MOD];\nconst FLOW_MODS = [\n 'row',\n 'column',\n 'wrap',\n 'nowrap',\n 'dense',\n 'row-reverse',\n 'column-reverse',\n];\nconst OVERFLOW_MODS = [\n 'visible',\n 'hidden',\n 'scroll',\n 'clip',\n 'auto',\n 'overlay',\n];\nconst POSITION_MODS = ['static', 'relative', 'absolute', 'fixed', 'sticky'];\n\nconst COLOR_ONLY: PropertyExpectation = {\n acceptsColor: true,\n acceptsMods: false,\n};\n\nconst VALUE_ONLY: PropertyExpectation = {\n acceptsColor: false,\n acceptsMods: false,\n};\n\nconst PASSTHROUGH: PropertyExpectation = {\n acceptsColor: true,\n acceptsMods: true,\n};\n\n/**\n * Every `display` keyword, one word at a time: values are checked word by\n * word, so the two-value syntax (`block flex`, `inline flow-root`,\n * `list-item block`) is covered by its outside, inside and `list-item` words.\n * `grid-lanes` is CSS Grid Level 3 masonry.\n */\nconst DISPLAY_MODS = [\n // <display-outside>\n 'block',\n 'inline',\n 'run-in',\n // <display-inside>\n 'flow',\n 'flow-root',\n 'table',\n 'flex',\n 'grid',\n 'grid-lanes',\n 'ruby',\n 'math',\n // <display-listitem>\n 'list-item',\n // <display-internal>\n 'table-row-group',\n 'table-header-group',\n 'table-footer-group',\n 'table-row',\n 'table-cell',\n 'table-column-group',\n 'table-column',\n 'table-caption',\n 'ruby-base',\n 'ruby-text',\n 'ruby-base-container',\n 'ruby-text-container',\n // <display-box>\n 'contents',\n 'none',\n // <display-legacy>\n 'inline-block',\n 'inline-table',\n 'inline-flex',\n 'inline-grid',\n 'inline-grid-lanes',\n];\n\nexport const PROPERTY_EXPECTATIONS: Record<string, PropertyExpectation> = {\n fill: { acceptsColor: true, acceptsMods: ['none', 'transparent'] },\n color: { acceptsColor: true, acceptsMods: ['none', 'transparent'] },\n caretColor: COLOR_ONLY,\n accentColor: COLOR_ONLY,\n shadow: { acceptsColor: true, acceptsMods: ['inset'] },\n\n border: {\n acceptsColor: true,\n acceptsMods: [...BOX_DIRECTIONAL_MODS, ...BORDER_STYLE_MODS],\n },\n outline: {\n acceptsColor: true,\n acceptsMods: BORDER_STYLE_MODS,\n },\n\n radius: {\n acceptsColor: false,\n acceptsMods: [\n ...RADIUS_DIRECTIONAL_MODS,\n 'round',\n 'ellipse',\n 'leaf',\n 'backleaf',\n ],\n },\n\n padding: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n margin: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n fade: { acceptsColor: true, acceptsMods: DIRECTIONAL_MODS },\n inset: { acceptsColor: false, acceptsMods: INSET_MODS },\n scrollMargin: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n scrollPadding: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n\n // Native logical CSS shorthands. Tasty v3.8 stopped reading these in its\n // physical handlers, so they are ordinary CSS declarations now: one or two\n // lengths through the normal value parser, no colours and no modifiers. The\n // enhanced `blockPadding` / `inlinePadding` below are what take modifiers.\n paddingInline: VALUE_ONLY,\n paddingBlock: VALUE_ONLY,\n\n width: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n height: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n\n // Enhanced logical styles. Each axis/category pair mirrors its physical\n // counterpart's vocabulary with `start`/`end` in place of the four sides.\n blockPadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlinePadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockInset: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineInset: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockScrollMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineScrollMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockScrollPadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineScrollPadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockBorder: {\n acceptsColor: true,\n acceptsMods: [...LOGICAL_EDGE_MODS, ...BORDER_STYLE_MODS],\n },\n inlineBorder: {\n acceptsColor: true,\n acceptsMods: [...LOGICAL_EDGE_MODS, ...BORDER_STYLE_MODS],\n },\n blockSize: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n inlineSize: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n\n gap: VALUE_ONLY,\n columnGap: VALUE_ONLY,\n rowGap: VALUE_ONLY,\n flexBasis: VALUE_ONLY,\n flexGrow: VALUE_ONLY,\n flexShrink: VALUE_ONLY,\n flex: VALUE_ONLY,\n order: VALUE_ONLY,\n zIndex: VALUE_ONLY,\n opacity: VALUE_ONLY,\n aspectRatio: VALUE_ONLY,\n lineClamp: VALUE_ONLY,\n tabSize: VALUE_ONLY,\n\n flow: { acceptsColor: false, acceptsMods: FLOW_MODS },\n display: { acceptsColor: false, acceptsMods: DISPLAY_MODS },\n overflow: { acceptsColor: false, acceptsMods: OVERFLOW_MODS },\n position: { acceptsColor: false, acceptsMods: POSITION_MODS },\n};\n\n/**\n * Get expectations for a property. Properties not in the map\n * are treated as passthrough (accept everything).\n */\nexport function getExpectation(property: string): PropertyExpectation {\n return PROPERTY_EXPECTATIONS[property] ?? PASSTHROUGH;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"property-expectations.js","names":[],"sources":["../src/property-expectations.ts"],"sourcesContent":["/**\n * Per-property expectations for parser bucket validation.\n *\n * After parsing a value through StyleParser.process(), each group contains\n * `colors`, `values`, and `mods` arrays. This map defines what is expected\n * for each tasty property so we can flag unexpected tokens.\n *\n * - `acceptsColor`: whether Color bucket tokens are valid\n * - `acceptsMods`: whether Mod bucket tokens are valid, and if so which ones\n * - `false` = no mods accepted (any mod is an error)\n * - `true` = any mod accepted (pass-through)\n * - `string[]` = only these specific mods are accepted\n *\n * Properties NOT listed here default to PASSTHROUGH (accept everything).\n * Only add properties that have actual restrictions.\n */\n\nexport interface PropertyExpectation {\n acceptsColor: boolean;\n acceptsMods: boolean | string[];\n /** Whether an unspaced `<ratio>` token (`16/10`) is a value here. */\n acceptsRatio?: boolean;\n}\n\nconst DIRECTIONAL_MODS = ['top', 'right', 'bottom', 'left'];\n// Output modifier accepted by every box property (`padding`, `margin`,\n// `inset`, `border`, `radius`): emit the individual CSS longhands instead of\n// the shorthand, so children can selectively inherit a single side/corner.\nconst LONGHAND_MOD = 'longhand';\n// `inset` additionally accepts `dock`: pin one edge and span its full\n// length (tasty >= 2.10). Other directional properties do not.\nconst INSET_MODS = [...DIRECTIONAL_MODS, 'dock', LONGHAND_MOD];\nconst BOX_DIRECTIONAL_MODS = [...DIRECTIONAL_MODS, LONGHAND_MOD];\nconst RADIUS_DIRECTIONAL_MODS = [\n ...DIRECTIONAL_MODS,\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n LONGHAND_MOD,\n];\nconst BORDER_STYLE_MODS = [\n 'solid',\n 'dashed',\n 'dotted',\n 'double',\n 'groove',\n 'ridge',\n 'inset',\n 'outset',\n 'none',\n 'hidden',\n];\nconst DIMENSION_MODS = ['min', 'max', 'fixed'];\n// The logical axis handlers take `start`/`end` in place of the four physical\n// sides, plus the same `longhand` output modifier — it emits the two native\n// start/end declarations instead of the axis shorthand.\nconst LOGICAL_EDGE_MODS = ['start', 'end', LONGHAND_MOD];\nconst FLOW_MODS = [\n 'row',\n 'column',\n 'wrap',\n 'nowrap',\n 'dense',\n 'row-reverse',\n 'column-reverse',\n];\nconst OVERFLOW_MODS = [\n 'visible',\n 'hidden',\n 'scroll',\n 'clip',\n 'auto',\n 'overlay',\n];\nconst POSITION_MODS = ['static', 'relative', 'absolute', 'fixed', 'sticky'];\n\nconst COLOR_ONLY: PropertyExpectation = {\n acceptsColor: true,\n acceptsMods: false,\n};\n\nconst VALUE_ONLY: PropertyExpectation = {\n acceptsColor: false,\n acceptsMods: false,\n};\n\nconst PASSTHROUGH: PropertyExpectation = {\n acceptsColor: true,\n acceptsMods: true,\n};\n\n/**\n * Every `display` keyword, one word at a time: values are checked word by\n * word, so the two-value syntax (`block flex`, `inline flow-root`,\n * `list-item block`) is covered by its outside, inside and `list-item` words.\n * `grid-lanes` is CSS Grid Level 3 masonry.\n */\nconst DISPLAY_MODS = [\n // <display-outside>\n 'block',\n 'inline',\n 'run-in',\n // <display-inside>\n 'flow',\n 'flow-root',\n 'table',\n 'flex',\n 'grid',\n 'grid-lanes',\n 'ruby',\n 'math',\n // <display-listitem>\n 'list-item',\n // <display-internal>\n 'table-row-group',\n 'table-header-group',\n 'table-footer-group',\n 'table-row',\n 'table-cell',\n 'table-column-group',\n 'table-column',\n 'table-caption',\n 'ruby-base',\n 'ruby-text',\n 'ruby-base-container',\n 'ruby-text-container',\n // <display-box>\n 'contents',\n 'none',\n // <display-legacy>\n 'inline-block',\n 'inline-table',\n 'inline-flex',\n 'inline-grid',\n 'inline-grid-lanes',\n // The old flexbox boxes, kept because `-webkit-line-clamp` only truncates\n // inside one.\n '-webkit-box',\n '-webkit-inline-box',\n];\n\nexport const PROPERTY_EXPECTATIONS: Record<string, PropertyExpectation> = {\n fill: { acceptsColor: true, acceptsMods: ['none', 'transparent'] },\n color: { acceptsColor: true, acceptsMods: ['none', 'transparent'] },\n caretColor: COLOR_ONLY,\n accentColor: COLOR_ONLY,\n shadow: { acceptsColor: true, acceptsMods: ['inset'] },\n\n border: {\n acceptsColor: true,\n acceptsMods: [...BOX_DIRECTIONAL_MODS, ...BORDER_STYLE_MODS],\n },\n outline: {\n acceptsColor: true,\n acceptsMods: BORDER_STYLE_MODS,\n },\n\n radius: {\n acceptsColor: false,\n acceptsMods: [\n ...RADIUS_DIRECTIONAL_MODS,\n 'round',\n 'ellipse',\n 'leaf',\n 'backleaf',\n ],\n },\n\n padding: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n margin: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n fade: { acceptsColor: true, acceptsMods: DIRECTIONAL_MODS },\n inset: { acceptsColor: false, acceptsMods: INSET_MODS },\n scrollMargin: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n scrollPadding: { acceptsColor: false, acceptsMods: BOX_DIRECTIONAL_MODS },\n\n // Native logical CSS shorthands. Tasty v3.8 stopped reading these in its\n // physical handlers, so they are ordinary CSS declarations now: one or two\n // lengths through the normal value parser, no colours and no modifiers. The\n // enhanced `blockPadding` / `inlinePadding` below are what take modifiers.\n paddingInline: VALUE_ONLY,\n paddingBlock: VALUE_ONLY,\n\n width: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n height: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n\n // Enhanced logical styles. Each axis/category pair mirrors its physical\n // counterpart's vocabulary with `start`/`end` in place of the four sides.\n blockPadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlinePadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockInset: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineInset: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockScrollMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineScrollMargin: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockScrollPadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n inlineScrollPadding: { acceptsColor: false, acceptsMods: LOGICAL_EDGE_MODS },\n blockBorder: {\n acceptsColor: true,\n acceptsMods: [...LOGICAL_EDGE_MODS, ...BORDER_STYLE_MODS],\n },\n inlineBorder: {\n acceptsColor: true,\n acceptsMods: [...LOGICAL_EDGE_MODS, ...BORDER_STYLE_MODS],\n },\n blockSize: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n inlineSize: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n\n gap: VALUE_ONLY,\n columnGap: VALUE_ONLY,\n rowGap: VALUE_ONLY,\n flexBasis: VALUE_ONLY,\n flexGrow: VALUE_ONLY,\n flexShrink: VALUE_ONLY,\n flex: VALUE_ONLY,\n order: VALUE_ONLY,\n zIndex: VALUE_ONLY,\n opacity: VALUE_ONLY,\n // `<ratio>` allows optional whitespace around the slash: `16/10`, `16 / 10`.\n aspectRatio: { ...VALUE_ONLY, acceptsRatio: true },\n lineClamp: VALUE_ONLY,\n tabSize: VALUE_ONLY,\n\n flow: { acceptsColor: false, acceptsMods: FLOW_MODS },\n display: { acceptsColor: false, acceptsMods: DISPLAY_MODS },\n overflow: { acceptsColor: false, acceptsMods: OVERFLOW_MODS },\n position: { acceptsColor: false, acceptsMods: POSITION_MODS },\n};\n\n/**\n * Get expectations for a property. Properties not in the map\n * are treated as passthrough (accept everything).\n */\nexport function getExpectation(property: string): PropertyExpectation {\n return PROPERTY_EXPECTATIONS[property] ?? PASSTHROUGH;\n}\n"],"mappings":"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"}