@tenphi/eslint-plugin-tasty 0.1.0 → 0.2.1
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.
- package/dist/{config.mjs → config.js} +3 -3
- package/dist/config.js.map +1 -0
- package/dist/{configs.d.mts → configs.d.ts} +1 -1
- package/dist/{configs.mjs → configs.js} +1 -1
- package/dist/configs.js.map +1 -0
- package/dist/{constants.mjs → constants.js} +1 -1
- package/dist/constants.js.map +1 -0
- package/dist/{context.mjs → context.js} +3 -3
- package/dist/context.js.map +1 -0
- package/dist/{create-rule.mjs → create-rule.js} +1 -1
- package/dist/create-rule.js.map +1 -0
- package/dist/{index.d.mts → index.d.ts} +3 -3
- package/dist/{index.mjs → index.js} +29 -29
- package/dist/index.js.map +1 -0
- package/dist/{parser.mjs → parser.js} +3 -3
- package/dist/parser.js.map +1 -0
- package/dist/{property-expectations.mjs → property-expectations.js} +1 -1
- package/dist/property-expectations.js.map +1 -0
- package/dist/rules/{consistent-token-usage.mjs → consistent-token-usage.js} +4 -4
- package/dist/rules/consistent-token-usage.js.map +1 -0
- package/dist/rules/{known-property.mjs → known-property.js} +5 -5
- package/dist/rules/known-property.js.map +1 -0
- package/dist/rules/{no-duplicate-state.mjs → no-duplicate-state.js} +4 -4
- package/dist/rules/no-duplicate-state.js.map +1 -0
- package/dist/rules/{no-important.mjs → no-important.js} +4 -4
- package/dist/rules/no-important.js.map +1 -0
- package/dist/rules/{no-nested-selector.mjs → no-nested-selector.js} +4 -4
- package/dist/rules/no-nested-selector.js.map +1 -0
- package/dist/rules/{no-nested-state-map.mjs → no-nested-state-map.js} +4 -4
- package/dist/rules/no-nested-state-map.js.map +1 -0
- package/dist/rules/{no-raw-color-values.mjs → no-raw-color-values.js} +4 -4
- package/dist/rules/no-raw-color-values.js.map +1 -0
- package/dist/rules/{no-runtime-styles-mutation.mjs → no-runtime-styles-mutation.js} +4 -4
- package/dist/rules/no-runtime-styles-mutation.js.map +1 -0
- package/dist/rules/{no-styles-prop.mjs → no-styles-prop.js} +2 -2
- package/dist/rules/no-styles-prop.js.map +1 -0
- package/dist/rules/{no-unknown-state-alias.mjs → no-unknown-state-alias.js} +4 -4
- package/dist/rules/no-unknown-state-alias.js.map +1 -0
- package/dist/rules/{prefer-shorthand-property.mjs → prefer-shorthand-property.js} +5 -5
- package/dist/rules/prefer-shorthand-property.js.map +1 -0
- package/dist/rules/{require-default-state.mjs → require-default-state.js} +4 -4
- package/dist/rules/require-default-state.js.map +1 -0
- package/dist/rules/{static-no-dynamic-values.mjs → static-no-dynamic-values.js} +4 -4
- package/dist/rules/static-no-dynamic-values.js.map +1 -0
- package/dist/rules/{static-valid-selector.mjs → static-valid-selector.js} +4 -4
- package/dist/rules/static-valid-selector.js.map +1 -0
- package/dist/rules/{valid-boolean-property.mjs → valid-boolean-property.js} +5 -5
- package/dist/rules/valid-boolean-property.js.map +1 -0
- package/dist/rules/{valid-color-token.mjs → valid-color-token.js} +4 -4
- package/dist/rules/valid-color-token.js.map +1 -0
- package/dist/rules/{valid-custom-property.mjs → valid-custom-property.js} +4 -4
- package/dist/rules/valid-custom-property.js.map +1 -0
- package/dist/rules/{valid-custom-unit.mjs → valid-custom-unit.js} +4 -4
- package/dist/rules/valid-custom-unit.js.map +1 -0
- package/dist/rules/{valid-directional-modifier.mjs → valid-directional-modifier.js} +5 -5
- package/dist/rules/valid-directional-modifier.js.map +1 -0
- package/dist/rules/{valid-preset.mjs → valid-preset.js} +5 -5
- package/dist/rules/valid-preset.js.map +1 -0
- package/dist/rules/{valid-radius-shape.mjs → valid-radius-shape.js} +5 -5
- package/dist/rules/valid-radius-shape.js.map +1 -0
- package/dist/rules/{valid-recipe.mjs → valid-recipe.js} +6 -6
- package/dist/rules/valid-recipe.js.map +1 -0
- package/dist/rules/valid-state-key.js +142 -0
- package/dist/rules/valid-state-key.js.map +1 -0
- package/dist/rules/{valid-styles-structure.mjs → valid-styles-structure.js} +4 -4
- package/dist/rules/valid-styles-structure.js.map +1 -0
- package/dist/rules/{valid-sub-element.mjs → valid-sub-element.js} +4 -4
- package/dist/rules/valid-sub-element.js.map +1 -0
- package/dist/rules/{valid-transition.mjs → valid-transition.js} +5 -5
- package/dist/rules/valid-transition.js.map +1 -0
- package/dist/rules/{valid-value.mjs → valid-value.js} +6 -6
- package/dist/rules/valid-value.js.map +1 -0
- package/dist/{types.d.mts → types.d.ts} +1 -1
- package/dist/{utils.mjs → utils.js} +3 -40
- package/dist/utils.js.map +1 -0
- package/package.json +17 -24
- package/dist/config.mjs.map +0 -1
- package/dist/configs.mjs.map +0 -1
- package/dist/constants.mjs.map +0 -1
- package/dist/context.mjs.map +0 -1
- package/dist/create-rule.mjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/parser.mjs.map +0 -1
- package/dist/property-expectations.mjs.map +0 -1
- package/dist/rules/consistent-token-usage.mjs.map +0 -1
- package/dist/rules/known-property.mjs.map +0 -1
- package/dist/rules/no-duplicate-state.mjs.map +0 -1
- package/dist/rules/no-important.mjs.map +0 -1
- package/dist/rules/no-nested-selector.mjs.map +0 -1
- package/dist/rules/no-nested-state-map.mjs.map +0 -1
- package/dist/rules/no-raw-color-values.mjs.map +0 -1
- package/dist/rules/no-runtime-styles-mutation.mjs.map +0 -1
- package/dist/rules/no-styles-prop.mjs.map +0 -1
- package/dist/rules/no-unknown-state-alias.mjs.map +0 -1
- package/dist/rules/prefer-shorthand-property.mjs.map +0 -1
- package/dist/rules/require-default-state.mjs.map +0 -1
- package/dist/rules/static-no-dynamic-values.mjs.map +0 -1
- package/dist/rules/static-valid-selector.mjs.map +0 -1
- package/dist/rules/valid-boolean-property.mjs.map +0 -1
- package/dist/rules/valid-color-token.mjs.map +0 -1
- package/dist/rules/valid-custom-property.mjs.map +0 -1
- package/dist/rules/valid-custom-unit.mjs.map +0 -1
- package/dist/rules/valid-directional-modifier.mjs.map +0 -1
- package/dist/rules/valid-preset.mjs.map +0 -1
- package/dist/rules/valid-radius-shape.mjs.map +0 -1
- package/dist/rules/valid-recipe.mjs.map +0 -1
- package/dist/rules/valid-state-key.mjs +0 -71
- package/dist/rules/valid-state-key.mjs.map +0 -1
- package/dist/rules/valid-styles-structure.mjs.map +0 -1
- package/dist/rules/valid-sub-element.mjs.map +0 -1
- package/dist/rules/valid-transition.mjs.map +0 -1
- package/dist/rules/valid-value.mjs.map +0 -1
- package/dist/utils.mjs.map +0 -1
- /package/dist/_virtual/_rolldown/{runtime.mjs → runtime.js} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __require } from "./_virtual/_rolldown/runtime.
|
|
2
|
-
import { DEFAULT_IMPORT_SOURCES } from "./constants.
|
|
1
|
+
import { __require } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { DEFAULT_IMPORT_SOURCES } from "./constants.js";
|
|
3
3
|
import { existsSync, readFileSync, statSync } from "fs";
|
|
4
4
|
import { dirname, join, resolve } from "path";
|
|
5
5
|
|
|
@@ -115,4 +115,4 @@ function loadConfig(filePath) {
|
|
|
115
115
|
|
|
116
116
|
//#endregion
|
|
117
117
|
export { loadConfig };
|
|
118
|
-
//# sourceMappingURL=config.
|
|
118
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync } from 'fs';\nimport { dirname, join, resolve } from 'path';\nimport type { ResolvedConfig, TastyValidationConfig } from './types.js';\nimport { DEFAULT_IMPORT_SOURCES } from './constants.js';\n\nconst CONFIG_FILENAMES = [\n 'tasty.config.ts',\n 'tasty.config.js',\n 'tasty.config.mjs',\n 'tasty.config.json',\n];\n\ninterface CachedConfig {\n config: ResolvedConfig;\n mtimes: Map<string, number>;\n}\n\nlet cachedConfig: CachedConfig | null = null;\n\nfunction findProjectRoot(startDir: string): string | null {\n let dir = startDir;\n while (dir !== dirname(dir)) {\n if (existsSync(join(dir, 'package.json'))) {\n return dir;\n }\n dir = dirname(dir);\n }\n return null;\n}\n\nfunction findConfigFile(projectRoot: string): string | null {\n for (const name of CONFIG_FILENAMES) {\n const path = join(projectRoot, name);\n if (existsSync(path)) {\n return path;\n }\n }\n return null;\n}\n\nfunction loadRawConfig(configPath: string): TastyValidationConfig {\n const content = readFileSync(configPath, 'utf-8');\n\n if (configPath.endsWith('.json')) {\n return JSON.parse(content) as TastyValidationConfig;\n }\n\n // For TS/JS files, extract JSON-like config or use a simple parser.\n // In a real implementation, we'd use jiti or tsx to load TS configs.\n // For now, attempt JSON parse of the default export pattern.\n const jsonMatch = content.match(\n /export\\s+default\\s+({[\\s\\S]*?})\\s*(?:;|\\n|$)/,\n );\n if (jsonMatch) {\n try {\n const fn = new Function(`return (${jsonMatch[1]})`);\n return fn() as TastyValidationConfig;\n } catch {\n // fall through\n }\n }\n\n return {};\n}\n\nfunction mergeConfigs(\n parent: TastyValidationConfig,\n child: TastyValidationConfig,\n): TastyValidationConfig {\n const result: TastyValidationConfig = { ...parent };\n\n const arrayKeys = [\n 'tokens',\n 'units',\n 'funcs',\n 'states',\n 'presets',\n 'recipes',\n 'styles',\n 'importSources',\n ] as const;\n\n for (const key of arrayKeys) {\n const childVal = child[key];\n if (childVal === undefined) continue;\n\n if (childVal === false) {\n (result as Record<string, unknown>)[key] = false;\n continue;\n }\n\n const parentVal = parent[key];\n if (Array.isArray(parentVal) && Array.isArray(childVal)) {\n (result as Record<string, unknown>)[key] = [\n ...new Set([...parentVal, ...childVal]),\n ];\n } else {\n (result as Record<string, unknown>)[key] = childVal;\n }\n }\n\n return result;\n}\n\nfunction resolveConfigChain(\n configPath: string,\n visited = new Set<string>(),\n): TastyValidationConfig {\n const absPath = resolve(configPath);\n if (visited.has(absPath)) return {};\n visited.add(absPath);\n\n const config = loadRawConfig(absPath);\n\n if (!config.extends) return config;\n\n let parentPath: string;\n if (config.extends.startsWith('.') || config.extends.startsWith('/')) {\n parentPath = resolve(dirname(absPath), config.extends);\n } else {\n try {\n parentPath = require.resolve(config.extends);\n } catch {\n return config;\n }\n }\n\n const parentConfig = resolveConfigChain(parentPath, visited);\n return mergeConfigs(parentConfig, config);\n}\n\nfunction toResolved(config: TastyValidationConfig): ResolvedConfig {\n return {\n tokens: config.tokens ?? [],\n units: config.units ?? [],\n funcs: config.funcs ?? [],\n states: config.states ?? [],\n presets: config.presets ?? [],\n recipes: config.recipes ?? [],\n styles: config.styles ?? [],\n importSources: config.importSources ?? DEFAULT_IMPORT_SOURCES,\n };\n}\n\nconst DEFAULT_CONFIG: ResolvedConfig = {\n tokens: [],\n units: [],\n funcs: [],\n states: [],\n presets: [],\n recipes: [],\n styles: [],\n importSources: DEFAULT_IMPORT_SOURCES,\n};\n\nexport function loadConfig(filePath: string): ResolvedConfig {\n const projectRoot = findProjectRoot(dirname(resolve(filePath)));\n if (!projectRoot) return DEFAULT_CONFIG;\n\n const configFile = findConfigFile(projectRoot);\n if (!configFile) return DEFAULT_CONFIG;\n\n const currentMtime = statSync(configFile).mtimeMs;\n\n if (cachedConfig) {\n const cachedMtime = cachedConfig.mtimes.get(configFile);\n if (cachedMtime === currentMtime) {\n return cachedConfig.config;\n }\n }\n\n const rawConfig = resolveConfigChain(configFile);\n const resolved = toResolved(rawConfig);\n\n cachedConfig = {\n config: resolved,\n mtimes: new Map([[configFile, currentMtime]]),\n };\n\n return resolved;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configs.js","names":[],"sources":["../src/configs.ts"],"sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\n\nexport const recommended: TSESLint.SharedConfig.RulesRecord = {\n 'tasty/known-property': 'warn',\n 'tasty/valid-value': 'error',\n 'tasty/valid-color-token': 'error',\n 'tasty/valid-custom-unit': 'error',\n 'tasty/valid-boolean-property': 'error',\n 'tasty/valid-state-key': 'error',\n 'tasty/valid-styles-structure': 'error',\n 'tasty/no-nested-state-map': 'error',\n 'tasty/no-important': 'error',\n 'tasty/valid-sub-element': 'error',\n 'tasty/valid-directional-modifier': 'error',\n 'tasty/valid-radius-shape': 'error',\n 'tasty/no-nested-selector': 'warn',\n 'tasty/static-no-dynamic-values': 'error',\n 'tasty/static-valid-selector': 'error',\n};\n\nexport const strict: TSESLint.SharedConfig.RulesRecord = {\n ...recommended,\n 'tasty/prefer-shorthand-property': 'warn',\n 'tasty/valid-preset': 'error',\n 'tasty/valid-recipe': 'error',\n 'tasty/valid-transition': 'warn',\n 'tasty/valid-custom-property': 'warn',\n 'tasty/no-unknown-state-alias': 'warn',\n 'tasty/no-duplicate-state': 'warn',\n 'tasty/no-styles-prop': 'warn',\n 'tasty/no-raw-color-values': 'warn',\n 'tasty/consistent-token-usage': 'warn',\n 'tasty/no-runtime-styles-mutation': 'warn',\n};\n"],"mappings":";AAEA,MAAa,cAAiD;CAC5D,wBAAwB;CACxB,qBAAqB;CACrB,2BAA2B;CAC3B,2BAA2B;CAC3B,gCAAgC;CAChC,yBAAyB;CACzB,gCAAgC;CAChC,6BAA6B;CAC7B,sBAAsB;CACtB,2BAA2B;CAC3B,oCAAoC;CACpC,4BAA4B;CAC5B,4BAA4B;CAC5B,kCAAkC;CAClC,+BAA+B;CAChC;AAED,MAAa,SAA4C;CACvD,GAAG;CACH,mCAAmC;CACnC,sBAAsB;CACtB,sBAAsB;CACtB,0BAA0B;CAC1B,+BAA+B;CAC/B,gCAAgC;CAChC,4BAA4B;CAC5B,wBAAwB;CACxB,6BAA6B;CAC7B,gCAAgC;CAChC,oCAAoC;CACrC"}
|
|
@@ -697,4 +697,4 @@ const BUILT_IN_STATE_PREFIXES = new Set([
|
|
|
697
697
|
|
|
698
698
|
//#endregion
|
|
699
699
|
export { BOOLEAN_TRUE_PROPERTIES, BUILT_IN_STATE_PREFIXES, BUILT_IN_UNITS, CSS_UNITS, DEFAULT_IMPORT_SOURCES, DIRECTIONAL_MODIFIERS, KNOWN_CSS_PROPERTIES, KNOWN_TASTY_PROPERTIES, PRESET_MODIFIERS, RADIUS_SHAPES, SEMANTIC_TRANSITIONS, SHORTHAND_MAPPING, SPECIAL_STYLE_KEYS };
|
|
700
|
-
//# sourceMappingURL=constants.
|
|
700
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Built-in tasty style properties that are always valid as style keys.\n */\nexport const KNOWN_TASTY_PROPERTIES = new Set([\n 'display',\n 'font',\n 'preset',\n 'hide',\n 'whiteSpace',\n 'opacity',\n 'transition',\n 'gridArea',\n 'order',\n 'gridColumn',\n 'gridRow',\n 'placeSelf',\n 'alignSelf',\n 'justifySelf',\n 'zIndex',\n 'margin',\n 'inset',\n 'position',\n 'padding',\n 'paddingInline',\n 'paddingBlock',\n 'overflow',\n 'scrollbar',\n 'textAlign',\n 'border',\n 'radius',\n 'shadow',\n 'outline',\n 'color',\n 'fill',\n 'fade',\n 'image',\n 'textTransform',\n 'fontWeight',\n 'fontStyle',\n 'width',\n 'height',\n 'flexBasis',\n 'flexGrow',\n 'flexShrink',\n 'flex',\n 'flow',\n 'placeItems',\n 'placeContent',\n 'alignItems',\n 'alignContent',\n 'justifyItems',\n 'justifyContent',\n 'align',\n 'justify',\n 'gap',\n 'columnGap',\n 'rowGap',\n 'gridColumns',\n 'gridRows',\n 'gridTemplate',\n 'gridAreas',\n 'recipe',\n 'textOverflow',\n 'textDecoration',\n 'animation',\n 'cursor',\n 'pointerEvents',\n 'userSelect',\n 'transform',\n 'transformOrigin',\n 'filter',\n 'backdropFilter',\n 'mixBlendMode',\n 'objectFit',\n 'objectPosition',\n 'resize',\n 'appearance',\n 'listStyle',\n 'listStyleType',\n 'content',\n 'boxSizing',\n 'verticalAlign',\n 'wordBreak',\n 'overflowWrap',\n 'hyphens',\n 'tabSize',\n 'direction',\n 'unicodeBidi',\n 'writingMode',\n 'lineClamp',\n 'aspectRatio',\n 'contain',\n 'containerType',\n 'containerName',\n 'willChange',\n 'isolation',\n 'touchAction',\n 'scrollBehavior',\n 'scrollSnapType',\n 'scrollSnapAlign',\n 'caretColor',\n 'accentColor',\n 'colorScheme',\n]);\n\n/**\n * Special top-level keys that are valid but not regular style properties.\n */\nexport const SPECIAL_STYLE_KEYS = new Set(['@keyframes', '@properties']);\n\n/**\n * CSS property names (common subset for validation).\n * When a key is camelCase and matches a known CSS property, it's valid.\n */\nexport const KNOWN_CSS_PROPERTIES = new Set([\n 'all',\n 'animation',\n 'animationDelay',\n 'animationDirection',\n 'animationDuration',\n 'animationFillMode',\n 'animationIterationCount',\n 'animationName',\n 'animationPlayState',\n 'animationTimingFunction',\n 'appearance',\n 'aspectRatio',\n 'backdropFilter',\n 'backfaceVisibility',\n 'background',\n 'backgroundAttachment',\n 'backgroundBlendMode',\n 'backgroundClip',\n 'backgroundColor',\n 'backgroundImage',\n 'backgroundOrigin',\n 'backgroundPosition',\n 'backgroundRepeat',\n 'backgroundSize',\n 'blockSize',\n 'border',\n 'borderBlock',\n 'borderBlockColor',\n 'borderBlockEnd',\n 'borderBlockEndColor',\n 'borderBlockEndStyle',\n 'borderBlockEndWidth',\n 'borderBlockStart',\n 'borderBlockStartColor',\n 'borderBlockStartStyle',\n 'borderBlockStartWidth',\n 'borderBlockStyle',\n 'borderBlockWidth',\n 'borderBottom',\n 'borderBottomColor',\n 'borderBottomLeftRadius',\n 'borderBottomRightRadius',\n 'borderBottomStyle',\n 'borderBottomWidth',\n 'borderCollapse',\n 'borderColor',\n 'borderImage',\n 'borderInline',\n 'borderInlineColor',\n 'borderInlineEnd',\n 'borderInlineStart',\n 'borderInlineStyle',\n 'borderInlineWidth',\n 'borderLeft',\n 'borderLeftColor',\n 'borderLeftStyle',\n 'borderLeftWidth',\n 'borderRadius',\n 'borderRight',\n 'borderRightColor',\n 'borderRightStyle',\n 'borderRightWidth',\n 'borderSpacing',\n 'borderStyle',\n 'borderTop',\n 'borderTopColor',\n 'borderTopLeftRadius',\n 'borderTopRightRadius',\n 'borderTopStyle',\n 'borderTopWidth',\n 'borderWidth',\n 'bottom',\n 'boxDecorationBreak',\n 'boxShadow',\n 'boxSizing',\n 'breakAfter',\n 'breakBefore',\n 'breakInside',\n 'captionSide',\n 'caretColor',\n 'clear',\n 'clip',\n 'clipPath',\n 'color',\n 'colorScheme',\n 'columnCount',\n 'columnFill',\n 'columnGap',\n 'columnRule',\n 'columnRuleColor',\n 'columnRuleStyle',\n 'columnRuleWidth',\n 'columnSpan',\n 'columnWidth',\n 'columns',\n 'contain',\n 'containerName',\n 'containerType',\n 'content',\n 'contentVisibility',\n 'counterIncrement',\n 'counterReset',\n 'counterSet',\n 'cursor',\n 'direction',\n 'display',\n 'emptyCells',\n 'filter',\n 'flex',\n 'flexBasis',\n 'flexDirection',\n 'flexFlow',\n 'flexGrow',\n 'flexShrink',\n 'flexWrap',\n 'float',\n 'font',\n 'fontFamily',\n 'fontFeatureSettings',\n 'fontKerning',\n 'fontOpticalSizing',\n 'fontSize',\n 'fontSizeAdjust',\n 'fontStretch',\n 'fontStyle',\n 'fontSynthesis',\n 'fontVariant',\n 'fontVariantAlternates',\n 'fontVariantCaps',\n 'fontVariantEastAsian',\n 'fontVariantLigatures',\n 'fontVariantNumeric',\n 'fontVariantPosition',\n 'fontWeight',\n 'gap',\n 'grid',\n 'gridArea',\n 'gridAutoColumns',\n 'gridAutoFlow',\n 'gridAutoRows',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowStart',\n 'gridTemplate',\n 'gridTemplateAreas',\n 'gridTemplateColumns',\n 'gridTemplateRows',\n 'height',\n 'hyphens',\n 'imageRendering',\n 'inlineSize',\n 'inset',\n 'insetBlock',\n 'insetBlockEnd',\n 'insetBlockStart',\n 'insetInline',\n 'insetInlineEnd',\n 'insetInlineStart',\n 'isolation',\n 'justifyContent',\n 'justifyItems',\n 'justifySelf',\n 'left',\n 'letterSpacing',\n 'lineBreak',\n 'lineHeight',\n 'listStyle',\n 'listStyleImage',\n 'listStylePosition',\n 'listStyleType',\n 'margin',\n 'marginBlock',\n 'marginBlockEnd',\n 'marginBlockStart',\n 'marginBottom',\n 'marginInline',\n 'marginInlineEnd',\n 'marginInlineStart',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'maskImage',\n 'maxBlockSize',\n 'maxHeight',\n 'maxInlineSize',\n 'maxWidth',\n 'minBlockSize',\n 'minHeight',\n 'minInlineSize',\n 'minWidth',\n 'mixBlendMode',\n 'objectFit',\n 'objectPosition',\n 'opacity',\n 'order',\n 'orphans',\n 'outline',\n 'outlineColor',\n 'outlineOffset',\n 'outlineStyle',\n 'outlineWidth',\n 'overflow',\n 'overflowAnchor',\n 'overflowWrap',\n 'overflowX',\n 'overflowY',\n 'overscrollBehavior',\n 'padding',\n 'paddingBlock',\n 'paddingBlockEnd',\n 'paddingBlockStart',\n 'paddingBottom',\n 'paddingInline',\n 'paddingInlineEnd',\n 'paddingInlineStart',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'perspective',\n 'perspectiveOrigin',\n 'placeContent',\n 'placeItems',\n 'placeSelf',\n 'pointerEvents',\n 'position',\n 'quotes',\n 'resize',\n 'right',\n 'rotate',\n 'rowGap',\n 'scale',\n 'scrollBehavior',\n 'scrollMargin',\n 'scrollPadding',\n 'scrollSnapAlign',\n 'scrollSnapStop',\n 'scrollSnapType',\n 'scrollbarColor',\n 'scrollbarGutter',\n 'scrollbarWidth',\n 'shapeOutside',\n 'tabSize',\n 'tableLayout',\n 'textAlign',\n 'textAlignLast',\n 'textCombineUpright',\n 'textDecoration',\n 'textDecorationColor',\n 'textDecorationLine',\n 'textDecorationSkipInk',\n 'textDecorationStyle',\n 'textDecorationThickness',\n 'textEmphasis',\n 'textIndent',\n 'textOrientation',\n 'textOverflow',\n 'textRendering',\n 'textShadow',\n 'textTransform',\n 'textUnderlineOffset',\n 'textUnderlinePosition',\n 'textWrap',\n 'top',\n 'touchAction',\n 'transform',\n 'transformOrigin',\n 'transformStyle',\n 'transition',\n 'transitionDelay',\n 'transitionDuration',\n 'transitionProperty',\n 'transitionTimingFunction',\n 'translate',\n 'unicodeBidi',\n 'userSelect',\n 'verticalAlign',\n 'visibility',\n 'whiteSpace',\n 'widows',\n 'width',\n 'willChange',\n 'wordBreak',\n 'wordSpacing',\n 'writingMode',\n 'zIndex',\n]);\n\n/**\n * Built-in custom units recognized by the tasty parser.\n */\nexport const BUILT_IN_UNITS = new Set([\n 'x',\n 'r',\n 'cr',\n 'bw',\n 'ow',\n 'fs',\n 'lh',\n 'sf',\n]);\n\n/**\n * Standard CSS units (always valid).\n */\nexport const CSS_UNITS = new Set([\n 'px',\n 'em',\n 'rem',\n '%',\n 'vw',\n 'vh',\n 'vmin',\n 'vmax',\n 'ch',\n 'ex',\n 'cm',\n 'mm',\n 'in',\n 'pt',\n 'pc',\n 'fr',\n 'deg',\n 'rad',\n 'turn',\n 'grad',\n 's',\n 'ms',\n 'dpi',\n 'dpcm',\n 'dppx',\n 'svw',\n 'svh',\n 'lvw',\n 'lvh',\n 'dvw',\n 'dvh',\n 'cqw',\n 'cqh',\n 'cqi',\n 'cqb',\n 'cqmin',\n 'cqmax',\n 'cap',\n 'ic',\n 'rlh',\n 'vi',\n 'vb',\n]);\n\n/**\n * Properties that accept `true` as a value (means \"use default\").\n */\nexport const BOOLEAN_TRUE_PROPERTIES = new Set([\n 'border',\n 'radius',\n 'padding',\n 'gap',\n 'fill',\n 'color',\n 'outline',\n 'width',\n 'height',\n 'hide',\n 'preset',\n 'font',\n 'scrollbar',\n]);\n\n/**\n * Directional modifiers and which properties accept them.\n */\nexport const DIRECTIONAL_MODIFIERS: Record<string, Set<string>> = {\n border: new Set(['top', 'right', 'bottom', 'left']),\n radius: new Set([\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n ]),\n padding: new Set(['top', 'right', 'bottom', 'left']),\n margin: new Set(['top', 'right', 'bottom', 'left']),\n fade: new Set(['top', 'right', 'bottom', 'left']),\n};\n\n/**\n * Valid radius shape keywords.\n */\nexport const RADIUS_SHAPES = new Set(['round', 'ellipse', 'leaf', 'backleaf']);\n\n/**\n * Known semantic transition names.\n */\nexport const SEMANTIC_TRANSITIONS = new Set([\n 'fade',\n 'fill',\n 'border',\n 'radius',\n 'shadow',\n 'preset',\n 'gap',\n 'theme',\n 'color',\n 'outline',\n 'dimension',\n 'flow',\n 'inset',\n]);\n\n/**\n * Mapping of native CSS properties to tasty shorthand alternatives.\n */\nexport const SHORTHAND_MAPPING: Record<\n string,\n { property: string; hint: string }\n> = {\n backgroundColor: { property: 'fill', hint: \"fill: '...'\" },\n borderColor: { property: 'border', hint: \"border: '...'\" },\n borderWidth: { property: 'border', hint: \"border: '...'\" },\n borderStyle: { property: 'border', hint: \"border: '...'\" },\n borderTop: { property: 'border', hint: \"border: '... top'\" },\n borderRight: { property: 'border', hint: \"border: '... right'\" },\n borderBottom: { property: 'border', hint: \"border: '... bottom'\" },\n borderLeft: { property: 'border', hint: \"border: '... left'\" },\n borderRadius: { property: 'radius', hint: \"radius: '...'\" },\n maxWidth: { property: 'width', hint: \"width: 'max ...'\" },\n minWidth: { property: 'width', hint: \"width: 'min ...'\" },\n maxHeight: { property: 'height', hint: \"height: 'max ...'\" },\n minHeight: { property: 'height', hint: \"height: 'min ...'\" },\n flexDirection: { property: 'flow', hint: \"flow: '...'\" },\n flexWrap: { property: 'flow', hint: \"flow: '...'\" },\n flexFlow: { property: 'flow', hint: \"flow: '...'\" },\n gridAutoFlow: { property: 'flow', hint: \"flow: '...'\" },\n outlineOffset: { property: 'outline', hint: \"outline: '... / offset'\" },\n paddingTop: { property: 'padding', hint: \"padding: '... top'\" },\n paddingRight: { property: 'padding', hint: \"padding: '... right'\" },\n paddingBottom: { property: 'padding', hint: \"padding: '... bottom'\" },\n paddingLeft: { property: 'padding', hint: \"padding: '... left'\" },\n marginTop: { property: 'margin', hint: \"margin: '... top'\" },\n marginRight: { property: 'margin', hint: \"margin: '... right'\" },\n marginBottom: { property: 'margin', hint: \"margin: '... bottom'\" },\n marginLeft: { property: 'margin', hint: \"margin: '... left'\" },\n fontSize: { property: 'preset', hint: \"preset: '...'\" },\n fontWeight: {\n property: 'preset',\n hint: \"preset: '... strong' (with strong modifier)\",\n },\n lineHeight: {\n property: 'preset',\n hint: \"preset: '... tight' (with tight modifier)\",\n },\n boxShadow: { property: 'shadow', hint: \"shadow: '...'\" },\n};\n\n/**\n * Known preset modifiers.\n */\nexport const PRESET_MODIFIERS = new Set(['strong', 'italic', 'tight']);\n\n/**\n * Default import sources for tasty.\n */\nexport const DEFAULT_IMPORT_SOURCES = ['@tenphi/tasty', '@tenphi/tasty/static'];\n\n/**\n * Built-in state prefixes that are always valid (not aliases).\n */\nexport const BUILT_IN_STATE_PREFIXES = new Set([\n '@media',\n '@root',\n '@own',\n '@supports',\n '@starting',\n '@keyframes',\n '@properties',\n]);\n\n/**\n * Known CSS pseudo-classes.\n */\nexport const KNOWN_PSEUDO_CLASSES = new Set([\n ':hover',\n ':focus',\n ':focus-visible',\n ':focus-within',\n ':active',\n ':visited',\n ':link',\n ':checked',\n ':disabled',\n ':enabled',\n ':empty',\n ':first-child',\n ':last-child',\n ':first-of-type',\n ':last-of-type',\n ':only-child',\n ':only-of-type',\n ':root',\n ':target',\n ':valid',\n ':invalid',\n ':required',\n ':optional',\n ':read-only',\n ':read-write',\n ':placeholder-shown',\n ':autofill',\n ':default',\n ':indeterminate',\n ':in-range',\n ':out-of-range',\n ':any-link',\n ':local-link',\n ':is',\n ':not',\n ':where',\n ':has',\n ':nth-child',\n ':nth-last-child',\n ':nth-of-type',\n ':nth-last-of-type',\n '::before',\n '::after',\n '::placeholder',\n '::selection',\n '::first-line',\n '::first-letter',\n '::marker',\n '::backdrop',\n]);\n"],"mappings":";;;;AAGA,MAAa,yBAAyB,IAAI,IAAI;CAC5C;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;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,qBAAqB,IAAI,IAAI,CAAC,cAAc,cAAc,CAAC;;;;;AAMxE,MAAa,uBAAuB,IAAI,IAAI;CAC1C;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;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;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;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,iBAAiB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,YAAY,IAAI,IAAI;CAC/B;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;;;;AAKF,MAAa,0BAA0B,IAAI,IAAI;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,wBAAqD;CAChE,QAAQ,IAAI,IAAI;EAAC;EAAO;EAAS;EAAU;EAAO,CAAC;CACnD,QAAQ,IAAI,IAAI;EACd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CACF,SAAS,IAAI,IAAI;EAAC;EAAO;EAAS;EAAU;EAAO,CAAC;CACpD,QAAQ,IAAI,IAAI;EAAC;EAAO;EAAS;EAAU;EAAO,CAAC;CACnD,MAAM,IAAI,IAAI;EAAC;EAAO;EAAS;EAAU;EAAO,CAAC;CAClD;;;;AAKD,MAAa,gBAAgB,IAAI,IAAI;CAAC;CAAS;CAAW;CAAQ;CAAW,CAAC;;;;AAK9E,MAAa,uBAAuB,IAAI,IAAI;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,oBAGT;CACF,iBAAiB;EAAE,UAAU;EAAQ,MAAM;EAAe;CAC1D,aAAa;EAAE,UAAU;EAAU,MAAM;EAAiB;CAC1D,aAAa;EAAE,UAAU;EAAU,MAAM;EAAiB;CAC1D,aAAa;EAAE,UAAU;EAAU,MAAM;EAAiB;CAC1D,WAAW;EAAE,UAAU;EAAU,MAAM;EAAqB;CAC5D,aAAa;EAAE,UAAU;EAAU,MAAM;EAAuB;CAChE,cAAc;EAAE,UAAU;EAAU,MAAM;EAAwB;CAClE,YAAY;EAAE,UAAU;EAAU,MAAM;EAAsB;CAC9D,cAAc;EAAE,UAAU;EAAU,MAAM;EAAiB;CAC3D,UAAU;EAAE,UAAU;EAAS,MAAM;EAAoB;CACzD,UAAU;EAAE,UAAU;EAAS,MAAM;EAAoB;CACzD,WAAW;EAAE,UAAU;EAAU,MAAM;EAAqB;CAC5D,WAAW;EAAE,UAAU;EAAU,MAAM;EAAqB;CAC5D,eAAe;EAAE,UAAU;EAAQ,MAAM;EAAe;CACxD,UAAU;EAAE,UAAU;EAAQ,MAAM;EAAe;CACnD,UAAU;EAAE,UAAU;EAAQ,MAAM;EAAe;CACnD,cAAc;EAAE,UAAU;EAAQ,MAAM;EAAe;CACvD,eAAe;EAAE,UAAU;EAAW,MAAM;EAA2B;CACvE,YAAY;EAAE,UAAU;EAAW,MAAM;EAAsB;CAC/D,cAAc;EAAE,UAAU;EAAW,MAAM;EAAwB;CACnE,eAAe;EAAE,UAAU;EAAW,MAAM;EAAyB;CACrE,aAAa;EAAE,UAAU;EAAW,MAAM;EAAuB;CACjE,WAAW;EAAE,UAAU;EAAU,MAAM;EAAqB;CAC5D,aAAa;EAAE,UAAU;EAAU,MAAM;EAAuB;CAChE,cAAc;EAAE,UAAU;EAAU,MAAM;EAAwB;CAClE,YAAY;EAAE,UAAU;EAAU,MAAM;EAAsB;CAC9D,UAAU;EAAE,UAAU;EAAU,MAAM;EAAiB;CACvD,YAAY;EACV,UAAU;EACV,MAAM;EACP;CACD,YAAY;EACV,UAAU;EACV,MAAM;EACP;CACD,WAAW;EAAE,UAAU;EAAU,MAAM;EAAiB;CACzD;;;;AAKD,MAAa,mBAAmB,IAAI,IAAI;CAAC;CAAU;CAAU;CAAQ,CAAC;;;;AAKtE,MAAa,yBAAyB,CAAC,iBAAiB,uBAAuB;;;;AAK/E,MAAa,0BAA0B,IAAI,IAAI;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_IMPORT_SOURCES } from "./constants.
|
|
2
|
-
import { loadConfig } from "./config.
|
|
1
|
+
import { DEFAULT_IMPORT_SOURCES } from "./constants.js";
|
|
2
|
+
import { loadConfig } from "./config.js";
|
|
3
3
|
|
|
4
4
|
//#region src/context.ts
|
|
5
5
|
const TASTY_FUNCTION_NAMES = new Set([
|
|
@@ -177,4 +177,4 @@ var TastyContext = class {
|
|
|
177
177
|
|
|
178
178
|
//#endregion
|
|
179
179
|
export { TastyContext };
|
|
180
|
-
//# sourceMappingURL=context.
|
|
180
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +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 } from './types.js';\nimport { loadConfig } from './config.js';\nimport { DEFAULT_IMPORT_SOURCES } from './constants.js';\n\nexport interface TastyImport {\n localName: string;\n importedName: string;\n source: string;\n}\n\nconst TASTY_FUNCTION_NAMES = new Set([\n 'tasty',\n 'tastyStatic',\n 'useStyles',\n 'useGlobalStyles',\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 importSources: Set<string>;\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 }\n\n trackImport(node: TSESTree.ImportDeclaration): void {\n const source = node.source.value;\n if (!this.importSources.has(source)) return;\n\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportSpecifier') {\n const importedName =\n specifier.imported.type === 'Identifier'\n ? specifier.imported.name\n : specifier.imported.value;\n if (TASTY_FUNCTION_NAMES.has(importedName)) {\n this.imports.set(specifier.local.name, {\n localName: specifier.local.name,\n importedName,\n source,\n });\n }\n }\n }\n }\n\n getImport(localName: string): TastyImport | undefined {\n return this.imports.get(localName);\n }\n\n isTastyCall(node: TSESTree.CallExpression): TastyImport | undefined {\n if (node.callee.type !== 'Identifier') return undefined;\n return this.imports.get(node.callee.name);\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 getStyleContext(node: TSESTree.Node): {\n type: 'tasty' | 'tastyStatic' | 'useStyles' | 'useGlobalStyles';\n isStaticCall: boolean;\n isSelectorMode: boolean;\n isExtending: boolean;\n } | null {\n let current: TSESTree.Node | undefined = node;\n\n while (current) {\n if (current.type === 'CallExpression') {\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 };\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 };\n }\n }\n\n return null;\n }\n\n current = current.parent;\n }\n\n return null;\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 optionsArg =\n args.length >= 2 && args[0].type !== 'ObjectExpression'\n ? args[1]\n : 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: args.length >= 2 && args[0].type !== 'ObjectExpression',\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 };\n }\n\n return null;\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 };\n }\n\n // tastyStatic(base, { ... }) or tastyStatic('selector', { ... })\n if (args.length === 2 && args[1] === targetNode) {\n const isSelectorMode = args[0].type === 'Literal';\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode,\n isExtending: !isSelectorMode,\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.key.type === 'Identifier' &&\n prop.key.name === 'styles' &&\n 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.key.type === 'Identifier' &&\n prop.key.name === 'variants' &&\n prop.value.type === 'ObjectExpression'\n ) {\n for (const variantProp of prop.value.properties) {\n if (\n variantProp.type === 'Property' &&\n variantProp.value === targetNode\n ) {\n return true;\n }\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 key = parentProperty.key;\n if (key.type !== 'Identifier') return false;\n\n // If the key starts with uppercase, it's a sub-element, not a state map\n if (/^[A-Z]/.test(key.name)) return false;\n\n // Special keys are not state maps\n if (key.name === '@keyframes' || key.name === '@properties') return false;\n\n // If the object has keys that look like state expressions, it's a state map\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, @properties).\n */\n isSpecialKey(key: string): boolean {\n return key.startsWith('@');\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-rule.js","names":[],"sources":["../src/create-rule.ts"],"sourcesContent":["import { ESLintUtils } from '@typescript-eslint/utils';\n\nexport const createRule = ESLintUtils.RuleCreator(\n (name) =>\n `https://github.com/tenphi/eslint-plugin-tasty/blob/main/docs/rules/${name}.md`,\n);\n"],"mappings":";;;AAEA,MAAa,aAAa,YAAY,aACnC,SACC,sEAAsE,KAAK,KAC9E"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { recommended, strict } from "./configs.
|
|
2
|
-
import { ResolvedConfig, TastyValidationConfig } from "./types.
|
|
1
|
+
import { recommended, strict } from "./configs.js";
|
|
2
|
+
import { ResolvedConfig, TastyValidationConfig } from "./types.js";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
5
|
declare const plugin: any;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { type ResolvedConfig, type TastyValidationConfig, plugin as default, recommended, strict };
|
|
8
|
-
//# sourceMappingURL=index.d.
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import known_property_default from "./rules/known-property.
|
|
2
|
-
import valid_value_default from "./rules/valid-value.
|
|
3
|
-
import valid_color_token_default from "./rules/valid-color-token.
|
|
4
|
-
import valid_custom_unit_default from "./rules/valid-custom-unit.
|
|
5
|
-
import valid_state_key_default from "./rules/valid-state-key.
|
|
6
|
-
import valid_styles_structure_default from "./rules/valid-styles-structure.
|
|
7
|
-
import no_nested_selector_default from "./rules/no-nested-selector.
|
|
8
|
-
import valid_custom_property_default from "./rules/valid-custom-property.
|
|
9
|
-
import valid_preset_default from "./rules/valid-preset.
|
|
10
|
-
import valid_recipe_default from "./rules/valid-recipe.
|
|
11
|
-
import valid_boolean_property_default from "./rules/valid-boolean-property.
|
|
12
|
-
import valid_directional_modifier_default from "./rules/valid-directional-modifier.
|
|
13
|
-
import valid_radius_shape_default from "./rules/valid-radius-shape.
|
|
14
|
-
import no_important_default from "./rules/no-important.
|
|
15
|
-
import valid_sub_element_default from "./rules/valid-sub-element.
|
|
16
|
-
import no_nested_state_map_default from "./rules/no-nested-state-map.
|
|
17
|
-
import static_no_dynamic_values_default from "./rules/static-no-dynamic-values.
|
|
18
|
-
import static_valid_selector_default from "./rules/static-valid-selector.
|
|
19
|
-
import prefer_shorthand_property_default from "./rules/prefer-shorthand-property.
|
|
20
|
-
import valid_transition_default from "./rules/valid-transition.
|
|
21
|
-
import require_default_state_default from "./rules/require-default-state.
|
|
22
|
-
import no_duplicate_state_default from "./rules/no-duplicate-state.
|
|
23
|
-
import no_unknown_state_alias_default from "./rules/no-unknown-state-alias.
|
|
24
|
-
import no_raw_color_values_default from "./rules/no-raw-color-values.
|
|
25
|
-
import no_styles_prop_default from "./rules/no-styles-prop.
|
|
26
|
-
import consistent_token_usage_default from "./rules/consistent-token-usage.
|
|
27
|
-
import no_runtime_styles_mutation_default from "./rules/no-runtime-styles-mutation.
|
|
28
|
-
import { recommended, strict } from "./configs.
|
|
1
|
+
import known_property_default from "./rules/known-property.js";
|
|
2
|
+
import valid_value_default from "./rules/valid-value.js";
|
|
3
|
+
import valid_color_token_default from "./rules/valid-color-token.js";
|
|
4
|
+
import valid_custom_unit_default from "./rules/valid-custom-unit.js";
|
|
5
|
+
import valid_state_key_default from "./rules/valid-state-key.js";
|
|
6
|
+
import valid_styles_structure_default from "./rules/valid-styles-structure.js";
|
|
7
|
+
import no_nested_selector_default from "./rules/no-nested-selector.js";
|
|
8
|
+
import valid_custom_property_default from "./rules/valid-custom-property.js";
|
|
9
|
+
import valid_preset_default from "./rules/valid-preset.js";
|
|
10
|
+
import valid_recipe_default from "./rules/valid-recipe.js";
|
|
11
|
+
import valid_boolean_property_default from "./rules/valid-boolean-property.js";
|
|
12
|
+
import valid_directional_modifier_default from "./rules/valid-directional-modifier.js";
|
|
13
|
+
import valid_radius_shape_default from "./rules/valid-radius-shape.js";
|
|
14
|
+
import no_important_default from "./rules/no-important.js";
|
|
15
|
+
import valid_sub_element_default from "./rules/valid-sub-element.js";
|
|
16
|
+
import no_nested_state_map_default from "./rules/no-nested-state-map.js";
|
|
17
|
+
import static_no_dynamic_values_default from "./rules/static-no-dynamic-values.js";
|
|
18
|
+
import static_valid_selector_default from "./rules/static-valid-selector.js";
|
|
19
|
+
import prefer_shorthand_property_default from "./rules/prefer-shorthand-property.js";
|
|
20
|
+
import valid_transition_default from "./rules/valid-transition.js";
|
|
21
|
+
import require_default_state_default from "./rules/require-default-state.js";
|
|
22
|
+
import no_duplicate_state_default from "./rules/no-duplicate-state.js";
|
|
23
|
+
import no_unknown_state_alias_default from "./rules/no-unknown-state-alias.js";
|
|
24
|
+
import no_raw_color_values_default from "./rules/no-raw-color-values.js";
|
|
25
|
+
import no_styles_prop_default from "./rules/no-styles-prop.js";
|
|
26
|
+
import consistent_token_usage_default from "./rules/consistent-token-usage.js";
|
|
27
|
+
import no_runtime_styles_mutation_default from "./rules/no-runtime-styles-mutation.js";
|
|
28
|
+
import { recommended, strict } from "./configs.js";
|
|
29
29
|
|
|
30
30
|
//#region src/index.ts
|
|
31
31
|
const plugin = {
|
|
@@ -80,4 +80,4 @@ const plugin = {
|
|
|
80
80
|
|
|
81
81
|
//#endregion
|
|
82
82
|
export { plugin as default, recommended, strict };
|
|
83
|
-
//# sourceMappingURL=index.
|
|
83
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["rules.knownProperty","rules.validValue","rules.validColorToken","rules.validCustomUnit","rules.validStateKey","rules.validStylesStructure","rules.noNestedSelector","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.noDuplicateState","rules.noUnknownStateAlias","rules.noRawColorValues","rules.noStylesProp","rules.consistentTokenUsage","rules.noRuntimeStylesMutation"],"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';\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 '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-duplicate-state': rules.noDuplicateState,\n 'no-unknown-state-alias': rules.noUnknownStateAlias,\n 'no-raw-color-values': rules.noRawColorValues,\n 'no-styles-prop': rules.noStylesProp,\n 'consistent-token-usage': rules.consistentTokenUsage,\n 'no-runtime-styles-mutation': rules.noRuntimeStylesMutation,\n};\n\nconst plugin = {\n meta: {\n name: '@tenphi/eslint-plugin-tasty',\n version: '0.1.0',\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 { TastyValidationConfig, ResolvedConfig } from './types.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,MAAM,SAAS;CACb,MAAM;EACJ,MAAM;EACN,SAAS;EACV;CACD,OAnCsE;EACtE,kBAAkBA;EAClB,eAAeC;EACf,qBAAqBC;EACrB,qBAAqBC;EACrB,mBAAmBC;EACnB,0BAA0BC;EAC1B,sBAAsBC;EACtB,yBAAyBC;EACzB,gBAAgBC;EAChB,gBAAgBC;EAChB,0BAA0BC;EAC1B,8BAA8BC;EAC9B,sBAAsBC;EACtB,gBAAgBC;EAChB,qBAAqBC;EACrB,uBAAuBC;EACvB,4BAA4BC;EAC5B,yBAAyBC;EACzB,6BAA6BC;EAC7B,oBAAoBC;EACpB,yBAAyBC;EACzB,sBAAsBC;EACtB,0BAA0BC;EAC1B,uBAAuBC;EACvB,kBAAkBC;EAClB,0BAA0BC;EAC1B,8BAA8BC;EAC/B;CAQC,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,5 +1,5 @@
|
|
|
1
|
-
import { BUILT_IN_UNITS } from "./constants.
|
|
2
|
-
import { StyleParser } from "@tenphi/tasty/
|
|
1
|
+
import { BUILT_IN_UNITS } from "./constants.js";
|
|
2
|
+
import { StyleParser } from "@tenphi/tasty/core";
|
|
3
3
|
|
|
4
4
|
//#region src/parser.ts
|
|
5
5
|
const BUILT_IN_UNIT_STUBS = {
|
|
@@ -43,4 +43,4 @@ function getParser(config) {
|
|
|
43
43
|
|
|
44
44
|
//#endregion
|
|
45
45
|
export { getParser };
|
|
46
|
-
//# sourceMappingURL=parser.
|
|
46
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","names":[],"sources":["../src/parser.ts"],"sourcesContent":["import { StyleParser } from '@tenphi/tasty/core';\nimport type { ParserOptions } from '@tenphi/tasty/core';\nimport type { ResolvedConfig } from './types.js';\nimport { BUILT_IN_UNITS } from './constants.js';\n\nconst BUILT_IN_UNIT_STUBS: Record<string, string> = {\n x: 'var(--gap)',\n r: 'var(--radius)',\n cr: 'var(--card-radius)',\n bw: 'var(--border-width)',\n ow: 'var(--outline-width)',\n fs: 'var(--font-size)',\n lh: 'var(--line-height)',\n sf: 'var(--scale-factor)',\n};\n\nlet cachedParser: { parser: StyleParser; configKey: string } | null = null;\n\nfunction configKey(config: ResolvedConfig): string {\n const units = config.units === false ? 'false' : JSON.stringify(config.units);\n const funcs = config.funcs === false ? 'false' : JSON.stringify(config.funcs);\n return `${units}|${funcs}`;\n}\n\n/**\n * Build a StyleParser from the ESLint plugin config.\n * Unit handlers are stubs (they produce placeholder CSS) because we only\n * care about bucket classification, not actual CSS output.\n */\nexport function getParser(config: ResolvedConfig): StyleParser {\n const key = configKey(config);\n if (cachedParser && cachedParser.configKey === key) {\n return cachedParser.parser;\n }\n\n const units: Record<string, string> = { ...BUILT_IN_UNIT_STUBS };\n\n if (Array.isArray(config.units)) {\n for (const u of config.units) {\n if (!units[u]) {\n units[u] = `var(--${u})`;\n }\n }\n } else if (config.units !== false) {\n for (const u of BUILT_IN_UNITS) {\n units[u] = BUILT_IN_UNIT_STUBS[u] ?? `var(--${u})`;\n }\n }\n\n const funcs: ParserOptions['funcs'] = {};\n if (Array.isArray(config.funcs)) {\n for (const f of config.funcs) {\n funcs[f] = (groups) => groups.map((g) => g.output).join(', ');\n }\n }\n\n const opts: ParserOptions = {\n units: config.units === false ? undefined : units,\n funcs: Object.keys(funcs).length > 0 ? funcs : undefined,\n };\n\n const parser = new StyleParser(opts);\n\n cachedParser = { parser, configKey: key };\n return parser;\n}\n"],"mappings":";;;;AAKA,MAAM,sBAA8C;CAClD,GAAG;CACH,GAAG;CACH,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,IAAI,eAAkE;AAEtE,SAAS,UAAU,QAAgC;AAGjD,QAAO,GAFO,OAAO,UAAU,QAAQ,UAAU,KAAK,UAAU,OAAO,MAAM,CAE7D,GADF,OAAO,UAAU,QAAQ,UAAU,KAAK,UAAU,OAAO,MAAM;;;;;;;AAS/E,SAAgB,UAAU,QAAqC;CAC7D,MAAM,MAAM,UAAU,OAAO;AAC7B,KAAI,gBAAgB,aAAa,cAAc,IAC7C,QAAO,aAAa;CAGtB,MAAM,QAAgC,EAAE,GAAG,qBAAqB;AAEhE,KAAI,MAAM,QAAQ,OAAO,MAAM,EAC7B;OAAK,MAAM,KAAK,OAAO,MACrB,KAAI,CAAC,MAAM,GACT,OAAM,KAAK,SAAS,EAAE;YAGjB,OAAO,UAAU,MAC1B,MAAK,MAAM,KAAK,eACd,OAAM,KAAK,oBAAoB,MAAM,SAAS,EAAE;CAIpD,MAAM,QAAgC,EAAE;AACxC,KAAI,MAAM,QAAQ,OAAO,MAAM,CAC7B,MAAK,MAAM,KAAK,OAAO,MACrB,OAAM,MAAM,WAAW,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,KAAK,KAAK;CASjE,MAAM,SAAS,IAAI,YALS;EAC1B,OAAO,OAAO,UAAU,QAAQ,SAAY;EAC5C,OAAO,OAAO,KAAK,MAAM,CAAC,SAAS,IAAI,QAAQ;EAChD,CAEmC;AAEpC,gBAAe;EAAE;EAAQ,WAAW;EAAK;AACzC,QAAO"}
|
|
@@ -0,0 +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'];\nconst RADIUS_DIRECTIONAL_MODS = [\n ...DIRECTIONAL_MODS,\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\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'];\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\nexport const PROPERTY_EXPECTATIONS: Record<string, PropertyExpectation> = {\n fill: COLOR_ONLY,\n color: COLOR_ONLY,\n caretColor: COLOR_ONLY,\n accentColor: COLOR_ONLY,\n shadow: COLOR_ONLY,\n\n border: {\n acceptsColor: true,\n acceptsMods: [...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: DIRECTIONAL_MODS },\n paddingInline: VALUE_ONLY,\n paddingBlock: VALUE_ONLY,\n margin: { acceptsColor: false, acceptsMods: DIRECTIONAL_MODS },\n fade: { acceptsColor: false, acceptsMods: DIRECTIONAL_MODS },\n inset: { acceptsColor: false, acceptsMods: DIRECTIONAL_MODS },\n\n width: { acceptsColor: false, acceptsMods: DIMENSION_MODS },\n height: { 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: {\n acceptsColor: false,\n acceptsMods: [\n 'block',\n 'inline',\n 'inline-block',\n 'flex',\n 'inline-flex',\n 'grid',\n 'inline-grid',\n 'none',\n 'contents',\n 'table',\n 'table-row',\n 'table-cell',\n 'list-item',\n ],\n },\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":";AAsBA,MAAM,mBAAmB;CAAC;CAAO;CAAS;CAAU;CAAO;AAC3D,MAAM,0BAA0B;CAC9B,GAAG;CACH;CACA;CACA;CACA;CACD;AACD,MAAM,oBAAoB;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,iBAAiB,CAAC,OAAO,MAAM;AACrC,MAAM,YAAY;CAChB;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,gBAAgB;CACpB;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,gBAAgB;CAAC;CAAU;CAAY;CAAY;CAAS;CAAS;AAE3E,MAAM,aAAkC;CACtC,cAAc;CACd,aAAa;CACd;AAED,MAAM,aAAkC;CACtC,cAAc;CACd,aAAa;CACd;AAED,MAAM,cAAmC;CACvC,cAAc;CACd,aAAa;CACd;AAED,MAAa,wBAA6D;CACxE,MAAM;CACN,OAAO;CACP,YAAY;CACZ,aAAa;CACb,QAAQ;CAER,QAAQ;EACN,cAAc;EACd,aAAa,CAAC,GAAG,kBAAkB,GAAG,kBAAkB;EACzD;CACD,SAAS;EACP,cAAc;EACd,aAAa;EACd;CAED,QAAQ;EACN,cAAc;EACd,aAAa;GACX,GAAG;GACH;GACA;GACA;GACA;GACD;EACF;CAED,SAAS;EAAE,cAAc;EAAO,aAAa;EAAkB;CAC/D,eAAe;CACf,cAAc;CACd,QAAQ;EAAE,cAAc;EAAO,aAAa;EAAkB;CAC9D,MAAM;EAAE,cAAc;EAAO,aAAa;EAAkB;CAC5D,OAAO;EAAE,cAAc;EAAO,aAAa;EAAkB;CAE7D,OAAO;EAAE,cAAc;EAAO,aAAa;EAAgB;CAC3D,QAAQ;EAAE,cAAc;EAAO,aAAa;EAAgB;CAE5D,KAAK;CACL,WAAW;CACX,QAAQ;CACR,WAAW;CACX,UAAU;CACV,YAAY;CACZ,MAAM;CACN,OAAO;CACP,QAAQ;CACR,SAAS;CACT,aAAa;CACb,WAAW;CACX,SAAS;CAET,MAAM;EAAE,cAAc;EAAO,aAAa;EAAW;CACrD,SAAS;EACP,cAAc;EACd,aAAa;GACX;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACF;CACD,UAAU;EAAE,cAAc;EAAO,aAAa;EAAe;CAC7D,UAAU;EAAE,cAAc;EAAO,aAAa;EAAe;CAC9D;;;;;AAMD,SAAgB,eAAe,UAAuC;AACpE,QAAO,sBAAsB,aAAa"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { getKeyName, getStringValue } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { getKeyName, getStringValue } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/consistent-token-usage.ts
|
|
6
6
|
const PX_TO_UNIT = {
|
|
@@ -85,4 +85,4 @@ var consistent_token_usage_default = createRule({
|
|
|
85
85
|
|
|
86
86
|
//#endregion
|
|
87
87
|
export { consistent_token_usage_default as default };
|
|
88
|
-
//# sourceMappingURL=consistent-token-usage.
|
|
88
|
+
//# sourceMappingURL=consistent-token-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-token-usage.js","names":[],"sources":["../../src/rules/consistent-token-usage.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getKeyName, getStringValue } from '../utils.js';\n\ntype MessageIds = 'preferToken';\n\nconst PX_TO_UNIT: Record<string, string> = {\n '8px': '1x',\n '16px': '2x',\n '24px': '3x',\n '32px': '4x',\n '40px': '5x',\n '48px': '6x',\n '56px': '7x',\n '64px': '8x',\n};\n\nexport default createRule<[], MessageIds>({\n name: 'consistent-token-usage',\n meta: {\n type: 'suggestion',\n docs: {\n description:\n 'Suggest using design tokens and custom units instead of raw CSS values',\n },\n messages: {\n preferToken: \"Consider using '{{suggestion}}' instead of '{{raw}}'.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n function checkValue(\n property: string,\n value: string,\n node: TSESTree.Node,\n ): void {\n const trimmed = value.trim();\n\n // Check pixel values that map to gap multiples\n if (trimmed in PX_TO_UNIT) {\n context.report({\n node,\n messageId: 'preferToken',\n data: { suggestion: PX_TO_UNIT[trimmed], raw: trimmed },\n });\n return;\n }\n\n // Check 6px in radius context\n if (property === 'radius' && trimmed === '6px') {\n context.report({\n node,\n messageId: 'preferToken',\n data: { suggestion: '1r', raw: '6px' },\n });\n return;\n }\n\n // Check 1px in border context\n if (property === 'border' && trimmed.includes('1px')) {\n context.report({\n node,\n messageId: 'preferToken',\n data: { suggestion: '1bw', raw: '1px' },\n });\n }\n }\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) continue;\n\n const key = getKeyName(prop.key);\n if (key === null) continue;\n\n const str = getStringValue(prop.value);\n if (str) {\n checkValue(key, str, prop.value);\n continue;\n }\n\n if (prop.value.type === 'ObjectExpression') {\n for (const stateProp of prop.value.properties) {\n if (stateProp.type !== 'Property') continue;\n const stateStr = getStringValue(stateProp.value);\n if (stateStr) {\n checkValue(key, stateStr, stateProp.value);\n }\n }\n }\n }\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,MAAM,aAAqC;CACzC,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACT;AAED,qCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,0EACH;EACD,UAAU,EACR,aAAa,yDACd;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,WACP,UACA,OACA,MACM;GACN,MAAM,UAAU,MAAM,MAAM;AAG5B,OAAI,WAAW,YAAY;AACzB,YAAQ,OAAO;KACb;KACA,WAAW;KACX,MAAM;MAAE,YAAY,WAAW;MAAU,KAAK;MAAS;KACxD,CAAC;AACF;;AAIF,OAAI,aAAa,YAAY,YAAY,OAAO;AAC9C,YAAQ,OAAO;KACb;KACA,WAAW;KACX,MAAM;MAAE,YAAY;MAAM,KAAK;MAAO;KACvC,CAAC;AACF;;AAIF,OAAI,aAAa,YAAY,QAAQ,SAAS,MAAM,CAClD,SAAQ,OAAO;IACb;IACA,WAAW;IACX,MAAM;KAAE,YAAY;KAAO,KAAK;KAAO;IACxC,CAAC;;AAIN,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,cAAc,KAAK,SAAU;KAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,SAAI,QAAQ,KAAM;KAElB,MAAM,MAAM,eAAe,KAAK,MAAM;AACtC,SAAI,KAAK;AACP,iBAAW,KAAK,KAAK,KAAK,MAAM;AAChC;;AAGF,SAAI,KAAK,MAAM,SAAS,mBACtB,MAAK,MAAM,aAAa,KAAK,MAAM,YAAY;AAC7C,UAAI,UAAU,SAAS,WAAY;MACnC,MAAM,WAAW,eAAe,UAAU,MAAM;AAChD,UAAI,SACF,YAAW,KAAK,UAAU,UAAU,MAAM;;;;GAMrD;;CAEJ,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { KNOWN_CSS_PROPERTIES, KNOWN_TASTY_PROPERTIES, SHORTHAND_MAPPING, SPECIAL_STYLE_KEYS } from "../constants.
|
|
3
|
-
import { TastyContext } from "../context.
|
|
4
|
-
import { getKeyName } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { KNOWN_CSS_PROPERTIES, KNOWN_TASTY_PROPERTIES, SHORTHAND_MAPPING, SPECIAL_STYLE_KEYS } from "../constants.js";
|
|
3
|
+
import { TastyContext } from "../context.js";
|
|
4
|
+
import { getKeyName } from "../utils.js";
|
|
5
5
|
|
|
6
6
|
//#region src/rules/known-property.ts
|
|
7
7
|
var known_property_default = createRule({
|
|
@@ -52,4 +52,4 @@ var known_property_default = createRule({
|
|
|
52
52
|
|
|
53
53
|
//#endregion
|
|
54
54
|
export { known_property_default as default };
|
|
55
|
-
//# sourceMappingURL=known-property.
|
|
55
|
+
//# sourceMappingURL=known-property.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"known-property.js","names":[],"sources":["../../src/rules/known-property.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getKeyName } from '../utils.js';\nimport {\n KNOWN_TASTY_PROPERTIES,\n KNOWN_CSS_PROPERTIES,\n SPECIAL_STYLE_KEYS,\n SHORTHAND_MAPPING,\n} from '../constants.js';\n\ntype MessageIds = 'unknownProperty';\n\nexport default createRule<[], MessageIds>({\n name: 'known-property',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Warn when a style property name is not recognized as a valid tasty or CSS property',\n },\n messages: {\n unknownProperty: \"Unknown style property '{{name}}'.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) continue;\n\n const key = getKeyName(prop.key);\n if (key === null) continue;\n\n // Sub-element keys (uppercase start)\n if (/^[A-Z]/.test(key)) continue;\n\n // Nested selectors (handled by no-nested-selector)\n if (key.startsWith('&')) continue;\n\n // Special @ keys\n if (key.startsWith('@')) continue;\n\n // Custom CSS property definitions\n if (key.startsWith('$')) continue;\n\n // Color token definitions\n if (key.startsWith('#')) continue;\n\n // Known tasty property\n if (KNOWN_TASTY_PROPERTIES.has(key)) continue;\n\n // Known CSS property\n if (KNOWN_CSS_PROPERTIES.has(key)) continue;\n\n // Special style keys\n if (SPECIAL_STYLE_KEYS.has(key)) continue;\n\n // Shorthand mappings (reported by prefer-shorthand-property)\n if (key in SHORTHAND_MAPPING) continue;\n\n // Custom styles from config\n if (ctx.config.styles.includes(key)) continue;\n\n // Check if the parent is a state map — state keys are not properties\n if (\n prop.value.type === 'ObjectExpression' &&\n node.parent?.type === 'Property'\n ) {\n const parentProp = node.parent as TSESTree.Property;\n if (!parentProp.computed && ctx.isStateMap(node, parentProp)) {\n continue;\n }\n }\n\n context.report({\n node: prop.key,\n messageId: 'unknownProperty',\n data: { name: key },\n });\n }\n },\n };\n },\n});\n"],"mappings":";;;;;;AAaA,6BAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,sFACH;EACD,UAAU,EACR,iBAAiB,sCAClB;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;AAErC,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,cAAc,KAAK,SAAU;KAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,SAAI,QAAQ,KAAM;AAGlB,SAAI,SAAS,KAAK,IAAI,CAAE;AAGxB,SAAI,IAAI,WAAW,IAAI,CAAE;AAGzB,SAAI,IAAI,WAAW,IAAI,CAAE;AAGzB,SAAI,IAAI,WAAW,IAAI,CAAE;AAGzB,SAAI,IAAI,WAAW,IAAI,CAAE;AAGzB,SAAI,uBAAuB,IAAI,IAAI,CAAE;AAGrC,SAAI,qBAAqB,IAAI,IAAI,CAAE;AAGnC,SAAI,mBAAmB,IAAI,IAAI,CAAE;AAGjC,SAAI,OAAO,kBAAmB;AAG9B,SAAI,IAAI,OAAO,OAAO,SAAS,IAAI,CAAE;AAGrC,SACE,KAAK,MAAM,SAAS,sBACpB,KAAK,QAAQ,SAAS,YACtB;MACA,MAAM,aAAa,KAAK;AACxB,UAAI,CAAC,WAAW,YAAY,IAAI,WAAW,MAAM,WAAW,CAC1D;;AAIJ,aAAQ,OAAO;MACb,MAAM,KAAK;MACX,WAAW;MACX,MAAM,EAAE,MAAM,KAAK;MACpB,CAAC;;;GAGP;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { getKeyName, getStringValue } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { getKeyName, getStringValue } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/no-duplicate-state.ts
|
|
6
6
|
var no_duplicate_state_default = createRule({
|
|
@@ -48,4 +48,4 @@ var no_duplicate_state_default = createRule({
|
|
|
48
48
|
|
|
49
49
|
//#endregion
|
|
50
50
|
export { no_duplicate_state_default as default };
|
|
51
|
-
//# sourceMappingURL=no-duplicate-state.
|
|
51
|
+
//# sourceMappingURL=no-duplicate-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-duplicate-state.js","names":[],"sources":["../../src/rules/no-duplicate-state.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getKeyName, getStringValue } from '../utils.js';\n\ntype MessageIds = 'duplicateState';\n\nexport default createRule<[], MessageIds>({\n name: 'no-duplicate-state',\n meta: {\n type: 'suggestion',\n docs: {\n description:\n 'Warn when the same state key appears more than once in a style mapping',\n },\n messages: {\n duplicateState: \"Duplicate state key '{{key}}'.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n function checkDuplicates(obj: TSESTree.ObjectExpression): void {\n const seen = new Map<string, TSESTree.Node>();\n\n for (const prop of obj.properties) {\n if (prop.type !== 'Property') continue;\n\n const key = !prop.computed\n ? getKeyName(prop.key)\n : getStringValue(prop.key);\n\n if (key === null) continue;\n\n if (seen.has(key)) {\n context.report({\n node: prop.key,\n messageId: 'duplicateState',\n data: { key },\n });\n } else {\n seen.set(key, prop.key);\n }\n }\n }\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) continue;\n\n const key = getKeyName(prop.key);\n if (key === null) continue;\n\n // Skip sub-elements and special keys\n if (/^[A-Z@&]/.test(key)) continue;\n\n // Check state map objects for duplicates\n if (prop.value.type === 'ObjectExpression') {\n checkDuplicates(prop.value);\n }\n }\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,iCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,0EACH;EACD,UAAU,EACR,gBAAgB,kCACjB;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,gBAAgB,KAAsC;GAC7D,MAAM,uBAAO,IAAI,KAA4B;AAE7C,QAAK,MAAM,QAAQ,IAAI,YAAY;AACjC,QAAI,KAAK,SAAS,WAAY;IAE9B,MAAM,MAAM,CAAC,KAAK,WACd,WAAW,KAAK,IAAI,GACpB,eAAe,KAAK,IAAI;AAE5B,QAAI,QAAQ,KAAM;AAElB,QAAI,KAAK,IAAI,IAAI,CACf,SAAQ,OAAO;KACb,MAAM,KAAK;KACX,WAAW;KACX,MAAM,EAAE,KAAK;KACd,CAAC;QAEF,MAAK,IAAI,KAAK,KAAK,IAAI;;;AAK7B,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,cAAc,KAAK,SAAU;KAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,SAAI,QAAQ,KAAM;AAGlB,SAAI,WAAW,KAAK,IAAI,CAAE;AAG1B,SAAI,KAAK,MAAM,SAAS,mBACtB,iBAAgB,KAAK,MAAM;;;GAIlC;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { getStringValue } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { getStringValue } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/no-important.ts
|
|
6
6
|
var no_important_default = createRule({
|
|
@@ -41,4 +41,4 @@ var no_important_default = createRule({
|
|
|
41
41
|
|
|
42
42
|
//#endregion
|
|
43
43
|
export { no_important_default as default };
|
|
44
|
-
//# sourceMappingURL=no-important.
|
|
44
|
+
//# sourceMappingURL=no-important.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-important.js","names":[],"sources":["../../src/rules/no-important.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getStringValue } from '../utils.js';\n\ntype MessageIds = 'noImportant';\n\nexport default createRule<[], MessageIds>({\n name: 'no-important',\n meta: {\n type: 'problem',\n docs: {\n description: 'Disallow !important in tasty style values',\n },\n messages: {\n noImportant:\n 'Do not use !important in tasty styles. The tasty system manages specificity via doubled selectors and state ordering.',\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n function checkNode(node: TSESTree.Node): void {\n const str = getStringValue(node);\n if (str && str.includes('!important')) {\n context.report({ node, messageId: 'noImportant' });\n }\n }\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property') continue;\n\n checkNode(prop.value);\n\n if (prop.value.type === 'ObjectExpression') {\n for (const stateProp of prop.value.properties) {\n if (stateProp.type === 'Property') {\n checkNode(stateProp.value);\n }\n }\n }\n }\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,2BAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aAAa,6CACd;EACD,UAAU,EACR,aACE,yHACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,UAAU,MAA2B;GAC5C,MAAM,MAAM,eAAe,KAAK;AAChC,OAAI,OAAO,IAAI,SAAS,aAAa,CACnC,SAAQ,OAAO;IAAE;IAAM,WAAW;IAAe,CAAC;;AAItD,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,WAAY;AAE9B,eAAU,KAAK,MAAM;AAErB,SAAI,KAAK,MAAM,SAAS,oBACtB;WAAK,MAAM,aAAa,KAAK,MAAM,WACjC,KAAI,UAAU,SAAS,WACrB,WAAU,UAAU,MAAM;;;;GAMrC;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { getKeyName } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { getKeyName } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/no-nested-selector.ts
|
|
6
6
|
var no_nested_selector_default = createRule({
|
|
@@ -37,4 +37,4 @@ var no_nested_selector_default = createRule({
|
|
|
37
37
|
|
|
38
38
|
//#endregion
|
|
39
39
|
export { no_nested_selector_default as default };
|
|
40
|
-
//# sourceMappingURL=no-nested-selector.
|
|
40
|
+
//# sourceMappingURL=no-nested-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-nested-selector.js","names":[],"sources":["../../src/rules/no-nested-selector.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getKeyName } from '../utils.js';\n\ntype MessageIds = 'noNestedSelector';\n\nexport default createRule<[], MessageIds>({\n name: 'no-nested-selector',\n meta: {\n type: 'suggestion',\n docs: {\n description:\n 'Discourage &-prefixed nested selectors in favor of sub-element styling',\n },\n messages: {\n noNestedSelector:\n \"Avoid nested selectors ('{{key}}'). Use sub-element styling with capitalized keys and data-element attributes instead.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) continue;\n\n const key = getKeyName(prop.key);\n if (key === null) continue;\n\n if (key.startsWith('&')) {\n context.report({\n node: prop.key,\n messageId: 'noNestedSelector',\n data: { key },\n });\n }\n }\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,iCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,0EACH;EACD,UAAU,EACR,kBACE,0HACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;AAErC,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,cAAc,KAAK,SAAU;KAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,SAAI,QAAQ,KAAM;AAElB,SAAI,IAAI,WAAW,IAAI,CACrB,SAAQ,OAAO;MACb,MAAM,KAAK;MACX,WAAW;MACX,MAAM,EAAE,KAAK;MACd,CAAC;;;GAIT;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { getKeyName } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { getKeyName } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/no-nested-state-map.ts
|
|
6
6
|
var no_nested_state_map_default = createRule({
|
|
@@ -41,4 +41,4 @@ var no_nested_state_map_default = createRule({
|
|
|
41
41
|
|
|
42
42
|
//#endregion
|
|
43
43
|
export { no_nested_state_map_default as default };
|
|
44
|
-
//# sourceMappingURL=no-nested-state-map.
|
|
44
|
+
//# sourceMappingURL=no-nested-state-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-nested-state-map.js","names":[],"sources":["../../src/rules/no-nested-state-map.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getKeyName } from '../utils.js';\n\ntype MessageIds = 'nestedStateMap';\n\nexport default createRule<[], MessageIds>({\n name: 'no-nested-state-map',\n meta: {\n type: 'problem',\n docs: {\n description: 'Prevent state mapping objects inside state mapping objects',\n },\n messages: {\n nestedStateMap:\n \"Nested state maps are not allowed. Use combined state keys instead (e.g., 'hovered & pressed').\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) continue;\n\n const key = getKeyName(prop.key);\n if (key === null) continue;\n\n // Skip sub-elements and special keys\n if (/^[A-Z@&]/.test(key)) continue;\n\n // If value is an object (state map), check for nested objects\n if (prop.value.type !== 'ObjectExpression') continue;\n\n for (const stateProp of prop.value.properties) {\n if (stateProp.type !== 'Property') continue;\n\n if (stateProp.value.type === 'ObjectExpression') {\n context.report({\n node: stateProp.value,\n messageId: 'nestedStateMap',\n });\n }\n }\n }\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,kCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aAAa,8DACd;EACD,UAAU,EACR,gBACE,mGACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;AAErC,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,cAAc,KAAK,SAAU;KAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,SAAI,QAAQ,KAAM;AAGlB,SAAI,WAAW,KAAK,IAAI,CAAE;AAG1B,SAAI,KAAK,MAAM,SAAS,mBAAoB;AAE5C,UAAK,MAAM,aAAa,KAAK,MAAM,YAAY;AAC7C,UAAI,UAAU,SAAS,WAAY;AAEnC,UAAI,UAAU,MAAM,SAAS,mBAC3B,SAAQ,OAAO;OACb,MAAM,UAAU;OAChB,WAAW;OACZ,CAAC;;;;GAKX;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { getStringValue } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { getStringValue } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/no-raw-color-values.ts
|
|
6
6
|
const HEX_COLOR_REGEX = /#([0-9a-fA-F]{3,8})\b/g;
|
|
@@ -81,4 +81,4 @@ var no_raw_color_values_default = createRule({
|
|
|
81
81
|
|
|
82
82
|
//#endregion
|
|
83
83
|
export { no_raw_color_values_default as default };
|
|
84
|
-
//# sourceMappingURL=no-raw-color-values.
|
|
84
|
+
//# sourceMappingURL=no-raw-color-values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-raw-color-values.js","names":[],"sources":["../../src/rules/no-raw-color-values.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getStringValue } from '../utils.js';\n\ntype MessageIds = 'rawHexColor' | 'rawColorFunction';\n\nconst HEX_COLOR_REGEX = /#([0-9a-fA-F]{3,8})\\b/g;\nconst COLOR_FUNC_REGEX = /\\b(rgb|rgba|hsl|hsla)\\s*\\(/gi;\n\nexport default createRule<[], MessageIds>({\n name: 'no-raw-color-values',\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Suggest using color tokens instead of raw hex/rgb values',\n },\n messages: {\n rawHexColor: \"Use a color token instead of raw hex color '{{value}}'.\",\n rawColorFunction: 'Use a color token instead of raw {{func}}() color.',\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n function isInTokenDefinition(node: TSESTree.Node): boolean {\n // Check if this is inside a :root or token-defining context\n let current: TSESTree.Node | undefined = node;\n while (current) {\n if (current.type === 'CallExpression') {\n const imp = ctx.isTastyCall(current);\n if (imp && imp.importedName === 'tastyStatic') {\n const firstArg = current.arguments[0];\n const selectorStr = getStringValue(firstArg);\n if (selectorStr === ':root') return true;\n }\n break;\n }\n current = current.parent;\n }\n return false;\n }\n\n function checkValue(value: string, node: TSESTree.Node): void {\n if (isInTokenDefinition(node)) return;\n\n // Check hex colors\n HEX_COLOR_REGEX.lastIndex = 0;\n let match;\n while ((match = HEX_COLOR_REGEX.exec(value)) !== null) {\n const hex = match[1];\n if ([3, 4, 6, 8].includes(hex.length)) {\n context.report({\n node,\n messageId: 'rawHexColor',\n data: { value: match[0] },\n });\n }\n }\n\n // Check color functions\n COLOR_FUNC_REGEX.lastIndex = 0;\n while ((match = COLOR_FUNC_REGEX.exec(value)) !== null) {\n context.report({\n node,\n messageId: 'rawColorFunction',\n data: { func: match[1] },\n });\n }\n }\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property') continue;\n\n const str = getStringValue(prop.value);\n if (str) checkValue(str, prop.value);\n\n if (prop.value.type === 'ObjectExpression') {\n for (const stateProp of prop.value.properties) {\n if (stateProp.type !== 'Property') continue;\n const stateStr = getStringValue(stateProp.value);\n if (stateStr) checkValue(stateStr, stateProp.value);\n }\n }\n }\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AAEzB,kCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aAAa,4DACd;EACD,UAAU;GACR,aAAa;GACb,kBAAkB;GACnB;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,oBAAoB,MAA8B;GAEzD,IAAI,UAAqC;AACzC,UAAO,SAAS;AACd,QAAI,QAAQ,SAAS,kBAAkB;KACrC,MAAM,MAAM,IAAI,YAAY,QAAQ;AACpC,SAAI,OAAO,IAAI,iBAAiB,eAAe;MAC7C,MAAM,WAAW,QAAQ,UAAU;AAEnC,UADoB,eAAe,SAAS,KACxB,QAAS,QAAO;;AAEtC;;AAEF,cAAU,QAAQ;;AAEpB,UAAO;;EAGT,SAAS,WAAW,OAAe,MAA2B;AAC5D,OAAI,oBAAoB,KAAK,CAAE;AAG/B,mBAAgB,YAAY;GAC5B,IAAI;AACJ,WAAQ,QAAQ,gBAAgB,KAAK,MAAM,MAAM,MAAM;IACrD,MAAM,MAAM,MAAM;AAClB,QAAI;KAAC;KAAG;KAAG;KAAG;KAAE,CAAC,SAAS,IAAI,OAAO,CACnC,SAAQ,OAAO;KACb;KACA,WAAW;KACX,MAAM,EAAE,OAAO,MAAM,IAAI;KAC1B,CAAC;;AAKN,oBAAiB,YAAY;AAC7B,WAAQ,QAAQ,iBAAiB,KAAK,MAAM,MAAM,KAChD,SAAQ,OAAO;IACb;IACA,WAAW;IACX,MAAM,EAAE,MAAM,MAAM,IAAI;IACzB,CAAC;;AAIN,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,WAAY;KAE9B,MAAM,MAAM,eAAe,KAAK,MAAM;AACtC,SAAI,IAAK,YAAW,KAAK,KAAK,MAAM;AAEpC,SAAI,KAAK,MAAM,SAAS,mBACtB,MAAK,MAAM,aAAa,KAAK,MAAM,YAAY;AAC7C,UAAI,UAAU,SAAS,WAAY;MACnC,MAAM,WAAW,eAAe,UAAU,MAAM;AAChD,UAAI,SAAU,YAAW,UAAU,UAAU,MAAM;;;;GAK5D;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { isStaticValue } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { isStaticValue } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/no-runtime-styles-mutation.ts
|
|
6
6
|
var no_runtime_styles_mutation_default = createRule({
|
|
@@ -49,4 +49,4 @@ var no_runtime_styles_mutation_default = createRule({
|
|
|
49
49
|
|
|
50
50
|
//#endregion
|
|
51
51
|
export { no_runtime_styles_mutation_default as default };
|
|
52
|
-
//# sourceMappingURL=no-runtime-styles-mutation.
|
|
52
|
+
//# sourceMappingURL=no-runtime-styles-mutation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-runtime-styles-mutation.js","names":[],"sources":["../../src/rules/no-runtime-styles-mutation.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { isStaticValue } from '../utils.js';\n\ntype MessageIds = 'dynamicStyleValue';\n\nexport default createRule<[], MessageIds>({\n name: 'no-runtime-styles-mutation',\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Warn when style objects contain runtime-computed values',\n },\n messages: {\n dynamicStyleValue:\n 'Style values should be static. Use modifiers (mods prop), tokens, or CSS custom properties for dynamic behavior.',\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n function checkProperties(node: TSESTree.ObjectExpression): void {\n for (const prop of node.properties) {\n if (prop.type === 'SpreadElement') {\n context.report({ node: prop, messageId: 'dynamicStyleValue' });\n continue;\n }\n\n if (prop.type !== 'Property') continue;\n\n // Skip sub-elements (they contain nested style objects)\n if (\n !prop.computed &&\n prop.key.type === 'Identifier' &&\n /^[A-Z]/.test(prop.key.name)\n ) {\n if (prop.value.type === 'ObjectExpression') {\n checkProperties(prop.value);\n }\n continue;\n }\n\n // Skip @keyframes and @properties\n if (\n !prop.computed &&\n prop.key.type === 'Identifier' &&\n prop.key.name.startsWith('@')\n ) {\n continue;\n }\n\n if (!isStaticValue(prop.value)) {\n context.report({\n node: prop.value,\n messageId: 'dynamicStyleValue',\n });\n }\n }\n }\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n checkProperties(node);\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,yCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aAAa,2DACd;EACD,UAAU,EACR,mBACE,oHACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,gBAAgB,MAAuC;AAC9D,QAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,QAAI,KAAK,SAAS,iBAAiB;AACjC,aAAQ,OAAO;MAAE,MAAM;MAAM,WAAW;MAAqB,CAAC;AAC9D;;AAGF,QAAI,KAAK,SAAS,WAAY;AAG9B,QACE,CAAC,KAAK,YACN,KAAK,IAAI,SAAS,gBAClB,SAAS,KAAK,KAAK,IAAI,KAAK,EAC5B;AACA,SAAI,KAAK,MAAM,SAAS,mBACtB,iBAAgB,KAAK,MAAM;AAE7B;;AAIF,QACE,CAAC,KAAK,YACN,KAAK,IAAI,SAAS,gBAClB,KAAK,IAAI,KAAK,WAAW,IAAI,CAE7B;AAGF,QAAI,CAAC,cAAc,KAAK,MAAM,CAC5B,SAAQ,OAAO;KACb,MAAM,KAAK;KACX,WAAW;KACZ,CAAC;;;AAKR,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAC9B,oBAAgB,KAAK;;GAExB;;CAEJ,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/no-styles-prop.ts
|
|
4
4
|
var no_styles_prop_default = createRule({
|
|
@@ -22,4 +22,4 @@ var no_styles_prop_default = createRule({
|
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
24
|
export { no_styles_prop_default as default };
|
|
25
|
-
//# sourceMappingURL=no-styles-prop.
|
|
25
|
+
//# sourceMappingURL=no-styles-prop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-styles-prop.js","names":[],"sources":["../../src/rules/no-styles-prop.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\n\ntype MessageIds = 'noStylesProp';\n\nexport default createRule<[], MessageIds>({\n name: 'no-styles-prop',\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Discourage using the styles prop directly on components',\n },\n messages: {\n noStylesProp:\n \"Avoid using 'styles' prop directly. Create a styled wrapper with tasty(Component, { styles: ... }) instead.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n JSXAttribute(node: TSESTree.JSXAttribute) {\n if (\n node.name.type === 'JSXIdentifier' &&\n node.name.name === 'styles' &&\n node.value?.type === 'JSXExpressionContainer' &&\n node.value.expression.type === 'ObjectExpression'\n ) {\n context.report({\n node,\n messageId: 'noStylesProp',\n });\n }\n },\n };\n },\n});\n"],"mappings":";;;AAKA,6BAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aAAa,2DACd;EACD,UAAU,EACR,cACE,+GACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;AACd,SAAO,EACL,aAAa,MAA6B;AACxC,OACE,KAAK,KAAK,SAAS,mBACnB,KAAK,KAAK,SAAS,YACnB,KAAK,OAAO,SAAS,4BACrB,KAAK,MAAM,WAAW,SAAS,mBAE/B,SAAQ,OAAO;IACb;IACA,WAAW;IACZ,CAAC;KAGP;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRule } from "../create-rule.
|
|
2
|
-
import { TastyContext } from "../context.
|
|
3
|
-
import { getKeyName, getStringValue, isKnownStateAlias } from "../utils.
|
|
1
|
+
import { createRule } from "../create-rule.js";
|
|
2
|
+
import { TastyContext } from "../context.js";
|
|
3
|
+
import { getKeyName, getStringValue, isKnownStateAlias } from "../utils.js";
|
|
4
4
|
|
|
5
5
|
//#region src/rules/no-unknown-state-alias.ts
|
|
6
6
|
var no_unknown_state_alias_default = createRule({
|
|
@@ -46,4 +46,4 @@ var no_unknown_state_alias_default = createRule({
|
|
|
46
46
|
|
|
47
47
|
//#endregion
|
|
48
48
|
export { no_unknown_state_alias_default as default };
|
|
49
|
-
//# sourceMappingURL=no-unknown-state-alias.
|
|
49
|
+
//# sourceMappingURL=no-unknown-state-alias.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-unknown-state-alias.js","names":[],"sources":["../../src/rules/no-unknown-state-alias.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext } from '../context.js';\nimport { getKeyName, getStringValue, isKnownStateAlias } from '../utils.js';\n\ntype MessageIds = 'unknownAlias';\n\nexport default createRule<[], MessageIds>({\n name: 'no-unknown-state-alias',\n meta: {\n type: 'suggestion',\n docs: {\n description:\n \"Warn when a @name state alias is used that isn't in the config\",\n },\n messages: {\n unknownAlias: \"Unknown state alias '{{alias}}'.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n function checkStateKeys(obj: TSESTree.ObjectExpression): void {\n for (const prop of obj.properties) {\n if (prop.type !== 'Property') continue;\n\n const key = !prop.computed\n ? getKeyName(prop.key)\n : getStringValue(prop.key);\n if (key === null || !key.startsWith('@')) continue;\n\n if (!isKnownStateAlias(key, ctx.config)) {\n context.report({\n node: prop.key,\n messageId: 'unknownAlias',\n data: { alias: key },\n });\n }\n }\n }\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n\n 'CallExpression ObjectExpression'(node: TSESTree.ObjectExpression) {\n if (!ctx.isStyleObject(node)) return;\n\n // Skip if no states configured\n if (ctx.config.states.length === 0) return;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) continue;\n\n // Skip sub-elements and special keys\n const key = getKeyName(prop.key);\n if (key === null || /^[A-Z@&]/.test(key)) continue;\n\n // Check state map objects for unknown aliases\n if (prop.value.type === 'ObjectExpression') {\n checkStateKeys(prop.value);\n }\n }\n },\n };\n },\n});\n"],"mappings":";;;;;AAOA,qCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,kEACH;EACD,UAAU,EACR,cAAc,oCACf;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,eAAe,KAAsC;AAC5D,QAAK,MAAM,QAAQ,IAAI,YAAY;AACjC,QAAI,KAAK,SAAS,WAAY;IAE9B,MAAM,MAAM,CAAC,KAAK,WACd,WAAW,KAAK,IAAI,GACpB,eAAe,KAAK,IAAI;AAC5B,QAAI,QAAQ,QAAQ,CAAC,IAAI,WAAW,IAAI,CAAE;AAE1C,QAAI,CAAC,kBAAkB,KAAK,IAAI,OAAO,CACrC,SAAQ,OAAO;KACb,MAAM,KAAK;KACX,WAAW;KACX,MAAM,EAAE,OAAO,KAAK;KACrB,CAAC;;;AAKR,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAGvB,kCAAkC,MAAiC;AACjE,QAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAG9B,QAAI,IAAI,OAAO,OAAO,WAAW,EAAG;AAEpC,SAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,SAAI,KAAK,SAAS,cAAc,KAAK,SAAU;KAG/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,SAAI,QAAQ,QAAQ,WAAW,KAAK,IAAI,CAAE;AAG1C,SAAI,KAAK,MAAM,SAAS,mBACtB,gBAAe,KAAK,MAAM;;;GAIjC;;CAEJ,CAAC"}
|