@tenphi/eslint-plugin-tasty 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -101,7 +101,8 @@ export default {
101
101
  | `tasty/prefer-auto-calc` | warn | `calc(...)` instead of Tasty auto-calc `(...)` |
102
102
  | `tasty/prefer-custom-property-syntax` | warn | `var(--prop)` / `$x-color` / `transparent` / `currentColor` instead of `$prop` / `#color` / `#clear` / `#current` |
103
103
  | `tasty/prefer-hide` | warn | `display: 'none'` instead of `hide: true` |
104
- | `tasty/prefer-directional-shorthand` | warn | 4-value `margin`/`padding` with zero placeholders instead of directional form |
104
+ | `tasty/prefer-directional-shorthand` | warn | 4-value `margin`/`padding`/`inset` with placeholder sides instead of directional form |
105
+ | `tasty/prefer-longhand-property` | error | Lossy `flex` shorthand instead of `flexGrow` / `flexShrink` / `flexBasis` |
105
106
 
106
107
  ### Strict (includes all recommended rules)
107
108
 
package/dist/configs.js CHANGED
@@ -27,7 +27,8 @@ const recommended = {
27
27
  "tasty/prefer-auto-calc": "warn",
28
28
  "tasty/prefer-custom-property-syntax": "warn",
29
29
  "tasty/prefer-hide": "warn",
30
- "tasty/prefer-directional-shorthand": "warn"
30
+ "tasty/prefer-directional-shorthand": "warn",
31
+ "tasty/prefer-longhand-property": "error"
31
32
  };
32
33
  const strict = {
33
34
  ...recommended,
@@ -1 +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': 'error',\n 'tasty/static-no-dynamic-values': 'error',\n 'tasty/static-valid-selector': 'error',\n 'tasty/valid-preset': 'error',\n 'tasty/valid-recipe': 'error',\n 'tasty/valid-transition': 'warn',\n 'tasty/require-default-state': 'error',\n 'tasty/no-own-at-root': 'warn',\n 'tasty/valid-default-state-order': 'warn',\n 'tasty/prefer-shorthand-property': 'warn',\n 'tasty/no-raw-color-values': 'warn',\n 'tasty/consistent-token-usage': 'warn',\n 'tasty/prefer-auto-calc': 'warn',\n 'tasty/prefer-custom-property-syntax': 'warn',\n 'tasty/prefer-hide': 'warn',\n 'tasty/prefer-directional-shorthand': 'warn',\n};\n\nexport const strict: TSESLint.SharedConfig.RulesRecord = {\n ...recommended,\n 'tasty/valid-custom-property': 'warn',\n 'tasty/no-unknown-state-alias': 'warn',\n 'tasty/no-styles-prop': 'warn',\n 'tasty/no-runtime-styles-mutation': 'warn',\n 'tasty/valid-state-definition': '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;CAC/B,sBAAsB;CACtB,sBAAsB;CACtB,0BAA0B;CAC1B,+BAA+B;CAC/B,wBAAwB;CACxB,mCAAmC;CACnC,mCAAmC;CACnC,6BAA6B;CAC7B,gCAAgC;CAChC,0BAA0B;CAC1B,uCAAuC;CACvC,qBAAqB;CACrB,sCAAsC;CACvC;AAED,MAAa,SAA4C;CACvD,GAAG;CACH,+BAA+B;CAC/B,gCAAgC;CAChC,wBAAwB;CACxB,oCAAoC;CACpC,gCAAgC;CACjC"}
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': 'error',\n 'tasty/static-no-dynamic-values': 'error',\n 'tasty/static-valid-selector': 'error',\n 'tasty/valid-preset': 'error',\n 'tasty/valid-recipe': 'error',\n 'tasty/valid-transition': 'warn',\n 'tasty/require-default-state': 'error',\n 'tasty/no-own-at-root': 'warn',\n 'tasty/valid-default-state-order': 'warn',\n 'tasty/prefer-shorthand-property': 'warn',\n 'tasty/no-raw-color-values': 'warn',\n 'tasty/consistent-token-usage': 'warn',\n 'tasty/prefer-auto-calc': 'warn',\n 'tasty/prefer-custom-property-syntax': 'warn',\n 'tasty/prefer-hide': 'warn',\n 'tasty/prefer-directional-shorthand': 'warn',\n 'tasty/prefer-longhand-property': 'error',\n};\n\nexport const strict: TSESLint.SharedConfig.RulesRecord = {\n ...recommended,\n 'tasty/valid-custom-property': 'warn',\n 'tasty/no-unknown-state-alias': 'warn',\n 'tasty/no-styles-prop': 'warn',\n 'tasty/no-runtime-styles-mutation': 'warn',\n 'tasty/valid-state-definition': '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;CAC/B,sBAAsB;CACtB,sBAAsB;CACtB,0BAA0B;CAC1B,+BAA+B;CAC/B,wBAAwB;CACxB,mCAAmC;CACnC,mCAAmC;CACnC,6BAA6B;CAC7B,gCAAgC;CAChC,0BAA0B;CAC1B,uCAAuC;CACvC,qBAAqB;CACrB,sCAAsC;CACtC,kCAAkC;CACnC;AAED,MAAa,SAA4C;CACvD,GAAG;CACH,+BAA+B;CAC/B,gCAAgC;CAChC,wBAAwB;CACxB,oCAAoC;CACpC,gCAAgC;CACjC"}
package/dist/constants.js CHANGED
@@ -578,6 +578,30 @@ const DIRECTIONAL_MODIFIERS = {
578
578
  ])
579
579
  };
580
580
  /**
581
+ * Properties whose 4-value box syntax round-trips losslessly to a directional
582
+ * shorthand, mapped to the *identity* token that marks an unset side.
583
+ *
584
+ * The identity is per-property because it is the CSS initial value of the
585
+ * longhand, not always `0`:
586
+ * - `margin` / `padding` — initial is `0`, so zero tokens are placeholders.
587
+ * - `inset` — initial is `auto`. A `0` here is a REAL offset that the
588
+ * directional shorthand would silently drop, so `auto` is the placeholder.
589
+ *
590
+ * Deliberately excluded because the rewrite is *not* equivalent:
591
+ * - `radius` — the four positions are corners, and a directional modifier
592
+ * addresses a corner pair (`radius: '4px bottom'` rounds both bottom
593
+ * corners), so a single-corner value has no directional equivalent.
594
+ * - `border` — four tokens parse as one border value (width/style/color),
595
+ * not as a box, so there are no per-side placeholders to collapse.
596
+ * - `fade` — each side becomes its own gradient group; collapsing changes the
597
+ * emitted `mask` layers.
598
+ */
599
+ const DIRECTIONAL_BOX_IDENTITY = {
600
+ margin: "0",
601
+ padding: "0",
602
+ inset: "auto"
603
+ };
604
+ /**
581
605
  * Valid radius shape keywords.
582
606
  */
583
607
  const RADIUS_SHAPES = new Set([
@@ -761,18 +785,6 @@ const SHORTHAND_MAPPING = {
761
785
  property: "preset",
762
786
  hint: "preset: '...'"
763
787
  },
764
- flexGrow: {
765
- property: "flex",
766
- hint: "flex: '...'"
767
- },
768
- flexShrink: {
769
- property: "flex",
770
- hint: "flex: '...'"
771
- },
772
- flexBasis: {
773
- property: "flex",
774
- hint: "flex: '...'"
775
- },
776
788
  flexGap: {
777
789
  property: "gap",
778
790
  hint: "gap: '...'"
@@ -835,6 +847,25 @@ const SHORTHAND_MAPPING = {
835
847
  }
836
848
  };
837
849
  /**
850
+ * CSS shorthands whose *longhands* are the preferred Tasty form — the reverse
851
+ * of `SHORTHAND_MAPPING`.
852
+ *
853
+ * `flex` is lossy in a way the longhands are not: it resets the two components
854
+ * you did not write to values that are not their CSS initial. `flex: '0'`
855
+ * expands to `flex-grow: 0; flex-shrink: 1; flex-basis: 0%`, so it cannot
856
+ * express "do not shrink" (`flexShrink: 0`) at all, and it silently changes
857
+ * `flex-basis`. Writing the longhands keeps each component independent, which
858
+ * also lets them carry separate state maps.
859
+ */
860
+ const LONGHAND_MAPPING = { flex: {
861
+ longhands: [
862
+ "flexGrow",
863
+ "flexShrink",
864
+ "flexBasis"
865
+ ],
866
+ hint: "flexGrow / flexShrink / flexBasis"
867
+ } };
868
+ /**
838
869
  * CSS transition property names mapped to Tasty semantic transition names.
839
870
  */
840
871
  const TRANSITION_SEMANTIC_MAPPING = {
@@ -1144,5 +1175,5 @@ const COLOR_BEARING_PROPERTIES = new Set([
1144
1175
  ]);
1145
1176
 
1146
1177
  //#endregion
1147
- export { BOOLEAN_TRUE_PROPERTIES, BUILT_IN_STATE_PREFIXES, BUILT_IN_UNITS, COLOR_BEARING_PROPERTIES, CSS_UNITS, DEFAULT_IMPORT_SOURCES, DIRECTIONAL_MODIFIERS, KNOWN_CSS_PROPERTIES, KNOWN_PSEUDO_CLASSES, KNOWN_TASTY_PROPERTIES, NAMED_CSS_COLORS, PRESET_MODIFIERS, RADIUS_SHAPES, SEMANTIC_TRANSITIONS, SHORTHAND_MAPPING, SPECIAL_STYLE_KEYS, TRANSITION_SEMANTIC_MAPPING };
1178
+ export { BOOLEAN_TRUE_PROPERTIES, BUILT_IN_STATE_PREFIXES, BUILT_IN_UNITS, COLOR_BEARING_PROPERTIES, CSS_UNITS, DEFAULT_IMPORT_SOURCES, DIRECTIONAL_BOX_IDENTITY, DIRECTIONAL_MODIFIERS, KNOWN_CSS_PROPERTIES, KNOWN_PSEUDO_CLASSES, KNOWN_TASTY_PROPERTIES, LONGHAND_MAPPING, NAMED_CSS_COLORS, PRESET_MODIFIERS, RADIUS_SHAPES, SEMANTIC_TRANSITIONS, SHORTHAND_MAPPING, SPECIAL_STYLE_KEYS, TRANSITION_SEMANTIC_MAPPING };
1148
1179
  //# sourceMappingURL=constants.js.map
@@ -1 +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 'container',\n 'containerType',\n 'containerName',\n 'interpolateSize',\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([\n '@keyframes',\n '@properties',\n '@fontFace',\n '@counterStyle',\n]);\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 'clipRule',\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 'dominantBaseline',\n 'emptyCells',\n 'fillOpacity',\n 'fillRule',\n 'filter',\n 'flex',\n 'flexBasis',\n 'flexDirection',\n 'flexFlow',\n 'flexGrow',\n 'flexShrink',\n 'flexWrap',\n 'float',\n 'floodColor',\n 'floodOpacity',\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 'lightingColor',\n 'lineBreak',\n 'lineHeight',\n 'listStyle',\n 'listStyleImage',\n 'listStylePosition',\n 'listStyleType',\n 'marker',\n 'markerEnd',\n 'markerMid',\n 'markerStart',\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 'scrollMarginBlock',\n 'scrollMarginBlockEnd',\n 'scrollMarginBlockStart',\n 'scrollMarginBottom',\n 'scrollMarginInline',\n 'scrollMarginInlineEnd',\n 'scrollMarginInlineStart',\n 'scrollMarginLeft',\n 'scrollMarginRight',\n 'scrollMarginTop',\n 'scrollPadding',\n 'scrollPaddingBlock',\n 'scrollPaddingBlockEnd',\n 'scrollPaddingBlockStart',\n 'scrollPaddingBottom',\n 'scrollPaddingInline',\n 'scrollPaddingInlineEnd',\n 'scrollPaddingInlineStart',\n 'scrollPaddingLeft',\n 'scrollPaddingRight',\n 'scrollPaddingTop',\n 'scrollSnapAlign',\n 'scrollSnapStop',\n 'scrollSnapType',\n 'scrollbarColor',\n 'scrollbarGutter',\n 'scrollbarWidth',\n 'shapeOutside',\n 'shapeRendering',\n 'stopColor',\n 'stopOpacity',\n 'stroke',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeLinecap',\n 'strokeLinejoin',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'tableLayout',\n 'textAlign',\n 'textAlignLast',\n 'textAnchor',\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 'textSizeAdjust',\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(['x', 'r', 'cr', 'bw', 'ow', 'lh', 'sf']);\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 'margin',\n 'gap',\n 'fill',\n 'color',\n 'shadow',\n 'outline',\n 'inset',\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 inset: 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 'text',\n 'opacity',\n 'translate',\n 'rotate',\n 'scale',\n 'filter',\n 'image',\n 'background',\n 'width',\n 'height',\n 'zIndex',\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; safeFix?: boolean }\n> = {\n backgroundColor: { property: 'fill', hint: \"fill: '...'\", safeFix: true },\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: '...'\", safeFix: true },\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: 'name / strong' (with strong modifier)\",\n },\n lineHeight: {\n property: 'preset',\n hint: \"preset: 'name / tight' (with tight modifier)\",\n },\n boxShadow: { property: 'shadow', hint: \"shadow: '...'\" },\n backgroundImage: { property: 'image', hint: \"image: '...'\" },\n fontFamily: { property: 'font', hint: \"font: '...'\" },\n fontStyle: {\n property: 'preset',\n hint: \"preset: 'name / italic' (with italic modifier)\",\n },\n letterSpacing: { property: 'preset', hint: \"preset: '...'\" },\n textTransform: { property: 'preset', hint: \"preset: '...'\" },\n flexGrow: { property: 'flex', hint: \"flex: '...'\" },\n flexShrink: { property: 'flex', hint: \"flex: '...'\" },\n flexBasis: { property: 'flex', hint: \"flex: '...'\" },\n flexGap: { property: 'gap', hint: \"gap: '...'\" },\n scrollbarWidth: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarColor: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarGutter: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n gridTemplateColumns: {\n property: 'gridColumns',\n hint: \"gridColumns: '...'\",\n },\n gridTemplateRows: { property: 'gridRows', hint: \"gridRows: '...'\" },\n gridTemplateAreas: { property: 'gridAreas', hint: \"gridAreas: '...'\" },\n top: { property: 'inset', hint: \"inset: '... top'\" },\n right: { property: 'inset', hint: \"inset: '... right'\" },\n bottom: { property: 'inset', hint: \"inset: '... bottom'\" },\n left: { property: 'inset', hint: \"inset: '... left'\" },\n outlineColor: { property: 'outline', hint: \"outline: '...'\" },\n outlineWidth: { property: 'outline', hint: \"outline: '...'\" },\n outlineStyle: { property: 'outline', hint: \"outline: '...'\" },\n lineClamp: {\n property: 'textOverflow',\n hint: \"textOverflow: 'ellipsis / {lines}'\",\n },\n};\n\n/**\n * CSS transition property names mapped to Tasty semantic transition names.\n */\nexport const TRANSITION_SEMANTIC_MAPPING: Record<string, string> = {\n backgroundColor: 'fill',\n 'background-color': 'fill',\n backgroundImage: 'image',\n 'background-image': 'image',\n borderRadius: 'radius',\n 'border-radius': 'radius',\n borderColor: 'border',\n 'border-color': 'border',\n borderWidth: 'border',\n 'border-width': 'border',\n borderStyle: 'border',\n 'border-style': 'border',\n boxShadow: 'shadow',\n 'box-shadow': 'shadow',\n outlineColor: 'outline',\n 'outline-color': 'outline',\n outlineWidth: 'outline',\n 'outline-width': 'outline',\n outlineOffset: 'outline',\n 'outline-offset': 'outline',\n gridTemplateColumns: 'gridColumns',\n 'grid-template-columns': 'gridColumns',\n gridTemplateRows: 'gridRows',\n 'grid-template-rows': 'gridRows',\n flexDirection: 'flow',\n 'flex-direction': 'flow',\n gridAutoFlow: 'flow',\n 'grid-auto-flow': 'flow',\n fontSize: 'preset',\n 'font-size': 'preset',\n lineHeight: 'preset',\n 'line-height': 'preset',\n letterSpacing: 'preset',\n 'letter-spacing': 'preset',\n};\n\n/**\n * Known preset modifiers.\n */\nexport const PRESET_MODIFIERS = new Set([\n 'strong',\n 'bold',\n 'italic',\n 'icon',\n 'tight',\n]);\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 '@parent',\n '@own',\n '@supports',\n '@starting',\n '@keyframes',\n '@properties',\n '@fontFace',\n '@counterStyle',\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\n/**\n * CSS named colors (level 1–4) that should be replaced by `#color` tokens.\n * `transparent` and `currentcolor` are excluded — they have their own token\n * suggestions (`#clear`, `#current`) handled by `prefer-custom-property-syntax`.\n */\nexport const NAMED_CSS_COLORS = new Set<string>([\n 'aliceblue',\n 'antiquewhite',\n 'aqua',\n 'aquamarine',\n 'azure',\n 'beige',\n 'bisque',\n 'black',\n 'blanchedalmond',\n 'blue',\n 'blueviolet',\n 'brown',\n 'burlywood',\n 'cadetblue',\n 'chartreuse',\n 'chocolate',\n 'coral',\n 'cornflowerblue',\n 'cornsilk',\n 'crimson',\n 'cyan',\n 'darkblue',\n 'darkcyan',\n 'darkgoldenrod',\n 'darkgray',\n 'darkgreen',\n 'darkgrey',\n 'darkkhaki',\n 'darkmagenta',\n 'darkolivegreen',\n 'darkorange',\n 'darkorchid',\n 'darkred',\n 'darksalmon',\n 'darkseagreen',\n 'darkslateblue',\n 'darkslategray',\n 'darkslategrey',\n 'darkturquoise',\n 'darkviolet',\n 'deeppink',\n 'deepskyblue',\n 'dimgray',\n 'dimgrey',\n 'dodgerblue',\n 'firebrick',\n 'floralwhite',\n 'forestgreen',\n 'fuchsia',\n 'gainsboro',\n 'ghostwhite',\n 'gold',\n 'goldenrod',\n 'gray',\n 'green',\n 'greenyellow',\n 'grey',\n 'honeydew',\n 'hotpink',\n 'indianred',\n 'indigo',\n 'ivory',\n 'khaki',\n 'lavender',\n 'lavenderblush',\n 'lawngreen',\n 'lemonchiffon',\n 'lightblue',\n 'lightcoral',\n 'lightcyan',\n 'lightgoldenrodyellow',\n 'lightgray',\n 'lightgreen',\n 'lightgrey',\n 'lightpink',\n 'lightsalmon',\n 'lightseagreen',\n 'lightskyblue',\n 'lightslategray',\n 'lightslategrey',\n 'lightsteelblue',\n 'lightyellow',\n 'lime',\n 'limegreen',\n 'linen',\n 'magenta',\n 'maroon',\n 'mediumaquamarine',\n 'mediumblue',\n 'mediumorchid',\n 'mediumpurple',\n 'mediumseagreen',\n 'mediumslateblue',\n 'mediumspringgreen',\n 'mediumturquoise',\n 'mediumvioletred',\n 'midnightblue',\n 'mintcream',\n 'mistyrose',\n 'moccasin',\n 'navajowhite',\n 'navy',\n 'oldlace',\n 'olive',\n 'olivedrab',\n 'orange',\n 'orangered',\n 'orchid',\n 'palegoldenrod',\n 'palegreen',\n 'paleturquoise',\n 'palevioletred',\n 'papayawhip',\n 'peachpuff',\n 'peru',\n 'pink',\n 'plum',\n 'powderblue',\n 'purple',\n 'rebeccapurple',\n 'red',\n 'rosybrown',\n 'royalblue',\n 'saddlebrown',\n 'salmon',\n 'sandybrown',\n 'seagreen',\n 'seashell',\n 'sienna',\n 'silver',\n 'skyblue',\n 'slateblue',\n 'slategray',\n 'slategrey',\n 'snow',\n 'springgreen',\n 'steelblue',\n 'tan',\n 'teal',\n 'thistle',\n 'tomato',\n 'turquoise',\n 'violet',\n 'wheat',\n 'white',\n 'whitesmoke',\n 'yellow',\n 'yellowgreen',\n]);\n\n/**\n * Properties that accept color values. Used to scope named-color checks so\n * string properties like `content` or `cursor` don't false-positive.\n */\nexport const COLOR_BEARING_PROPERTIES = new Set<string>([\n // Tasty enhanced properties\n 'fill',\n 'color',\n 'caretColor',\n 'accentColor',\n 'shadow',\n 'border',\n 'outline',\n 'fade',\n // CSS background\n 'background',\n 'backgroundColor',\n // CSS border colors\n 'borderColor',\n 'borderTopColor',\n 'borderRightColor',\n 'borderBottomColor',\n 'borderLeftColor',\n // CSS shadows\n 'boxShadow',\n 'textShadow',\n // CSS text decoration\n 'textDecorationColor',\n // CSS outline / misc\n 'outlineColor',\n 'scrollbarColor',\n 'columnRuleColor',\n // SVG\n 'stroke',\n 'stopColor',\n 'floodColor',\n 'lightingColor',\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;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,qBAAqB,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACD,CAAC;;;;;AAMF,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;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;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;CAAC;CAAK;CAAK;CAAM;CAAM;CAAM;CAAM;CAAK,CAAC;;;;AAK/E,MAAa,Y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ACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;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;;;;;;AAOF,MAAa,mBAAmB,IAAI,IAAY;CAC9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;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;;;;;AAMF,MAAa,2BAA2B,IAAI,IAAY;CAEtD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CAEA;CACA;CACA;CAEA;CACA;CACA;CACA;CACD,CAAC"}
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 'container',\n 'containerType',\n 'containerName',\n 'interpolateSize',\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([\n '@keyframes',\n '@properties',\n '@fontFace',\n '@counterStyle',\n]);\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 'clipRule',\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 'dominantBaseline',\n 'emptyCells',\n 'fillOpacity',\n 'fillRule',\n 'filter',\n 'flex',\n 'flexBasis',\n 'flexDirection',\n 'flexFlow',\n 'flexGrow',\n 'flexShrink',\n 'flexWrap',\n 'float',\n 'floodColor',\n 'floodOpacity',\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 'lightingColor',\n 'lineBreak',\n 'lineHeight',\n 'listStyle',\n 'listStyleImage',\n 'listStylePosition',\n 'listStyleType',\n 'marker',\n 'markerEnd',\n 'markerMid',\n 'markerStart',\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 'scrollMarginBlock',\n 'scrollMarginBlockEnd',\n 'scrollMarginBlockStart',\n 'scrollMarginBottom',\n 'scrollMarginInline',\n 'scrollMarginInlineEnd',\n 'scrollMarginInlineStart',\n 'scrollMarginLeft',\n 'scrollMarginRight',\n 'scrollMarginTop',\n 'scrollPadding',\n 'scrollPaddingBlock',\n 'scrollPaddingBlockEnd',\n 'scrollPaddingBlockStart',\n 'scrollPaddingBottom',\n 'scrollPaddingInline',\n 'scrollPaddingInlineEnd',\n 'scrollPaddingInlineStart',\n 'scrollPaddingLeft',\n 'scrollPaddingRight',\n 'scrollPaddingTop',\n 'scrollSnapAlign',\n 'scrollSnapStop',\n 'scrollSnapType',\n 'scrollbarColor',\n 'scrollbarGutter',\n 'scrollbarWidth',\n 'shapeOutside',\n 'shapeRendering',\n 'stopColor',\n 'stopOpacity',\n 'stroke',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeLinecap',\n 'strokeLinejoin',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'tableLayout',\n 'textAlign',\n 'textAlignLast',\n 'textAnchor',\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 'textSizeAdjust',\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(['x', 'r', 'cr', 'bw', 'ow', 'lh', 'sf']);\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 'margin',\n 'gap',\n 'fill',\n 'color',\n 'shadow',\n 'outline',\n 'inset',\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 inset: new Set(['top', 'right', 'bottom', 'left']),\n};\n\n/**\n * Properties whose 4-value box syntax round-trips losslessly to a directional\n * shorthand, mapped to the *identity* token that marks an unset side.\n *\n * The identity is per-property because it is the CSS initial value of the\n * longhand, not always `0`:\n * - `margin` / `padding` — initial is `0`, so zero tokens are placeholders.\n * - `inset` — initial is `auto`. A `0` here is a REAL offset that the\n * directional shorthand would silently drop, so `auto` is the placeholder.\n *\n * Deliberately excluded because the rewrite is *not* equivalent:\n * - `radius` — the four positions are corners, and a directional modifier\n * addresses a corner pair (`radius: '4px bottom'` rounds both bottom\n * corners), so a single-corner value has no directional equivalent.\n * - `border` — four tokens parse as one border value (width/style/color),\n * not as a box, so there are no per-side placeholders to collapse.\n * - `fade` — each side becomes its own gradient group; collapsing changes the\n * emitted `mask` layers.\n */\nexport const DIRECTIONAL_BOX_IDENTITY: Record<string, string> = {\n margin: '0',\n padding: '0',\n inset: 'auto',\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 'text',\n 'opacity',\n 'translate',\n 'rotate',\n 'scale',\n 'filter',\n 'image',\n 'background',\n 'width',\n 'height',\n 'zIndex',\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; safeFix?: boolean }\n> = {\n backgroundColor: { property: 'fill', hint: \"fill: '...'\", safeFix: true },\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: '...'\", safeFix: true },\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: 'name / strong' (with strong modifier)\",\n },\n lineHeight: {\n property: 'preset',\n hint: \"preset: 'name / tight' (with tight modifier)\",\n },\n boxShadow: { property: 'shadow', hint: \"shadow: '...'\" },\n backgroundImage: { property: 'image', hint: \"image: '...'\" },\n fontFamily: { property: 'font', hint: \"font: '...'\" },\n fontStyle: {\n property: 'preset',\n hint: \"preset: 'name / italic' (with italic modifier)\",\n },\n letterSpacing: { property: 'preset', hint: \"preset: '...'\" },\n textTransform: { property: 'preset', hint: \"preset: '...'\" },\n flexGap: { property: 'gap', hint: \"gap: '...'\" },\n scrollbarWidth: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarColor: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarGutter: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n gridTemplateColumns: {\n property: 'gridColumns',\n hint: \"gridColumns: '...'\",\n },\n gridTemplateRows: { property: 'gridRows', hint: \"gridRows: '...'\" },\n gridTemplateAreas: { property: 'gridAreas', hint: \"gridAreas: '...'\" },\n top: { property: 'inset', hint: \"inset: '... top'\" },\n right: { property: 'inset', hint: \"inset: '... right'\" },\n bottom: { property: 'inset', hint: \"inset: '... bottom'\" },\n left: { property: 'inset', hint: \"inset: '... left'\" },\n outlineColor: { property: 'outline', hint: \"outline: '...'\" },\n outlineWidth: { property: 'outline', hint: \"outline: '...'\" },\n outlineStyle: { property: 'outline', hint: \"outline: '...'\" },\n lineClamp: {\n property: 'textOverflow',\n hint: \"textOverflow: 'ellipsis / {lines}'\",\n },\n};\n\n/**\n * CSS shorthands whose *longhands* are the preferred Tasty form — the reverse\n * of `SHORTHAND_MAPPING`.\n *\n * `flex` is lossy in a way the longhands are not: it resets the two components\n * you did not write to values that are not their CSS initial. `flex: '0'`\n * expands to `flex-grow: 0; flex-shrink: 1; flex-basis: 0%`, so it cannot\n * express \"do not shrink\" (`flexShrink: 0`) at all, and it silently changes\n * `flex-basis`. Writing the longhands keeps each component independent, which\n * also lets them carry separate state maps.\n */\nexport const LONGHAND_MAPPING: Record<\n string,\n { longhands: string[]; hint: string }\n> = {\n flex: {\n longhands: ['flexGrow', 'flexShrink', 'flexBasis'],\n hint: 'flexGrow / flexShrink / flexBasis',\n },\n};\n\n/**\n * CSS transition property names mapped to Tasty semantic transition names.\n */\nexport const TRANSITION_SEMANTIC_MAPPING: Record<string, string> = {\n backgroundColor: 'fill',\n 'background-color': 'fill',\n backgroundImage: 'image',\n 'background-image': 'image',\n borderRadius: 'radius',\n 'border-radius': 'radius',\n borderColor: 'border',\n 'border-color': 'border',\n borderWidth: 'border',\n 'border-width': 'border',\n borderStyle: 'border',\n 'border-style': 'border',\n boxShadow: 'shadow',\n 'box-shadow': 'shadow',\n outlineColor: 'outline',\n 'outline-color': 'outline',\n outlineWidth: 'outline',\n 'outline-width': 'outline',\n outlineOffset: 'outline',\n 'outline-offset': 'outline',\n gridTemplateColumns: 'gridColumns',\n 'grid-template-columns': 'gridColumns',\n gridTemplateRows: 'gridRows',\n 'grid-template-rows': 'gridRows',\n flexDirection: 'flow',\n 'flex-direction': 'flow',\n gridAutoFlow: 'flow',\n 'grid-auto-flow': 'flow',\n fontSize: 'preset',\n 'font-size': 'preset',\n lineHeight: 'preset',\n 'line-height': 'preset',\n letterSpacing: 'preset',\n 'letter-spacing': 'preset',\n};\n\n/**\n * Known preset modifiers.\n */\nexport const PRESET_MODIFIERS = new Set([\n 'strong',\n 'bold',\n 'italic',\n 'icon',\n 'tight',\n]);\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 '@parent',\n '@own',\n '@supports',\n '@starting',\n '@keyframes',\n '@properties',\n '@fontFace',\n '@counterStyle',\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\n/**\n * CSS named colors (level 1–4) that should be replaced by `#color` tokens.\n * `transparent` and `currentcolor` are excluded — they have their own token\n * suggestions (`#clear`, `#current`) handled by `prefer-custom-property-syntax`.\n */\nexport const NAMED_CSS_COLORS = new Set<string>([\n 'aliceblue',\n 'antiquewhite',\n 'aqua',\n 'aquamarine',\n 'azure',\n 'beige',\n 'bisque',\n 'black',\n 'blanchedalmond',\n 'blue',\n 'blueviolet',\n 'brown',\n 'burlywood',\n 'cadetblue',\n 'chartreuse',\n 'chocolate',\n 'coral',\n 'cornflowerblue',\n 'cornsilk',\n 'crimson',\n 'cyan',\n 'darkblue',\n 'darkcyan',\n 'darkgoldenrod',\n 'darkgray',\n 'darkgreen',\n 'darkgrey',\n 'darkkhaki',\n 'darkmagenta',\n 'darkolivegreen',\n 'darkorange',\n 'darkorchid',\n 'darkred',\n 'darksalmon',\n 'darkseagreen',\n 'darkslateblue',\n 'darkslategray',\n 'darkslategrey',\n 'darkturquoise',\n 'darkviolet',\n 'deeppink',\n 'deepskyblue',\n 'dimgray',\n 'dimgrey',\n 'dodgerblue',\n 'firebrick',\n 'floralwhite',\n 'forestgreen',\n 'fuchsia',\n 'gainsboro',\n 'ghostwhite',\n 'gold',\n 'goldenrod',\n 'gray',\n 'green',\n 'greenyellow',\n 'grey',\n 'honeydew',\n 'hotpink',\n 'indianred',\n 'indigo',\n 'ivory',\n 'khaki',\n 'lavender',\n 'lavenderblush',\n 'lawngreen',\n 'lemonchiffon',\n 'lightblue',\n 'lightcoral',\n 'lightcyan',\n 'lightgoldenrodyellow',\n 'lightgray',\n 'lightgreen',\n 'lightgrey',\n 'lightpink',\n 'lightsalmon',\n 'lightseagreen',\n 'lightskyblue',\n 'lightslategray',\n 'lightslategrey',\n 'lightsteelblue',\n 'lightyellow',\n 'lime',\n 'limegreen',\n 'linen',\n 'magenta',\n 'maroon',\n 'mediumaquamarine',\n 'mediumblue',\n 'mediumorchid',\n 'mediumpurple',\n 'mediumseagreen',\n 'mediumslateblue',\n 'mediumspringgreen',\n 'mediumturquoise',\n 'mediumvioletred',\n 'midnightblue',\n 'mintcream',\n 'mistyrose',\n 'moccasin',\n 'navajowhite',\n 'navy',\n 'oldlace',\n 'olive',\n 'olivedrab',\n 'orange',\n 'orangered',\n 'orchid',\n 'palegoldenrod',\n 'palegreen',\n 'paleturquoise',\n 'palevioletred',\n 'papayawhip',\n 'peachpuff',\n 'peru',\n 'pink',\n 'plum',\n 'powderblue',\n 'purple',\n 'rebeccapurple',\n 'red',\n 'rosybrown',\n 'royalblue',\n 'saddlebrown',\n 'salmon',\n 'sandybrown',\n 'seagreen',\n 'seashell',\n 'sienna',\n 'silver',\n 'skyblue',\n 'slateblue',\n 'slategray',\n 'slategrey',\n 'snow',\n 'springgreen',\n 'steelblue',\n 'tan',\n 'teal',\n 'thistle',\n 'tomato',\n 'turquoise',\n 'violet',\n 'wheat',\n 'white',\n 'whitesmoke',\n 'yellow',\n 'yellowgreen',\n]);\n\n/**\n * Properties that accept color values. Used to scope named-color checks so\n * string properties like `content` or `cursor` don't false-positive.\n */\nexport const COLOR_BEARING_PROPERTIES = new Set<string>([\n // Tasty enhanced properties\n 'fill',\n 'color',\n 'caretColor',\n 'accentColor',\n 'shadow',\n 'border',\n 'outline',\n 'fade',\n // CSS background\n 'background',\n 'backgroundColor',\n // CSS border colors\n 'borderColor',\n 'borderTopColor',\n 'borderRightColor',\n 'borderBottomColor',\n 'borderLeftColor',\n // CSS shadows\n 'boxShadow',\n 'textShadow',\n // CSS text decoration\n 'textDecorationColor',\n // CSS outline / misc\n 'outlineColor',\n 'scrollbarColor',\n 'columnRuleColor',\n // SVG\n 'stroke',\n 'stopColor',\n 'floodColor',\n 'lightingColor',\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;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,qBAAqB,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACD,CAAC;;;;;AAMF,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;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;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;CAAC;CAAK;CAAK;CAAM;CAAM;CAAM;CAAM;CAAK,CAAC;;;;AAK/E,MAAa,Y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;;;;AAKF,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;CACD,CAAC;;;;;;AAOF,MAAa,mBAAmB,IAAI,IAAY;CAC9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;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;;;;;AAMF,MAAa,2BAA2B,IAAI,IAAY;CAEtD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CAEA;CACA;CACA;CAEA;CACA;CACA;CACA;CACD,CAAC"}
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ import prefer_auto_calc_default from "./rules/prefer-auto-calc.js";
31
31
  import prefer_custom_property_syntax_default from "./rules/prefer-custom-property-syntax.js";
32
32
  import prefer_hide_default from "./rules/prefer-hide.js";
33
33
  import prefer_directional_shorthand_default from "./rules/prefer-directional-shorthand.js";
34
+ import prefer_longhand_property_default from "./rules/prefer-longhand-property.js";
34
35
  import { recommended, strict } from "./configs.js";
35
36
 
36
37
  //#region src/index.ts
@@ -72,7 +73,8 @@ const plugin = {
72
73
  "prefer-auto-calc": prefer_auto_calc_default,
73
74
  "prefer-custom-property-syntax": prefer_custom_property_syntax_default,
74
75
  "prefer-hide": prefer_hide_default,
75
- "prefer-directional-shorthand": prefer_directional_shorthand_default
76
+ "prefer-directional-shorthand": prefer_directional_shorthand_default,
77
+ "prefer-longhand-property": prefer_longhand_property_default
76
78
  },
77
79
  configs: {
78
80
  recommended: {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["rules.knownProperty","rules.validValue","rules.validColorToken","rules.validCustomUnit","rules.validStateKey","rules.validStylesStructure","rules.noNestedSelector","rules.validCustomProperty","rules.validPreset","rules.validRecipe","rules.validBooleanProperty","rules.validDirectionalModifier","rules.validRadiusShape","rules.noImportant","rules.validSubElement","rules.noNestedStateMap","rules.staticNoDynamicValues","rules.staticValidSelector","rules.preferShorthandProperty","rules.validTransition","rules.requireDefaultState","rules.noUnknownStateAlias","rules.noRawColorValues","rules.noStylesProp","rules.consistentTokenUsage","rules.noRuntimeStylesMutation","rules.validStateDefinition","rules.noOwnAtRoot","rules.validDefaultStateOrder","rules.preferAutoCalc","rules.preferCustomPropertySyntax","rules.preferHide","rules.preferDirectionalShorthand"],"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-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 'valid-state-definition': rules.validStateDefinition,\n 'no-own-at-root': rules.noOwnAtRoot,\n 'valid-default-state-order': rules.validDefaultStateOrder,\n 'prefer-auto-calc': rules.preferAutoCalc,\n 'prefer-custom-property-syntax': rules.preferCustomPropertySyntax,\n 'prefer-hide': rules.preferHide,\n 'prefer-directional-shorthand': rules.preferDirectionalShorthand,\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,MAAM,SAAS;CACb,MAAM;EACJ,MAAM;EACN,SAAS;EACV;CACD,OAzCsE;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,0BAA0BC;EAC1B,uBAAuBC;EACvB,kBAAkBC;EAClB,0BAA0BC;EAC1B,8BAA8BC;EAC9B,0BAA0BC;EAC1B,kBAAkBC;EAClB,6BAA6BC;EAC7B,oBAAoBC;EACpB,iCAAiCC;EACjC,eAAeC;EACf,gCAAgCC;EACjC;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
+ {"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.noUnknownStateAlias","rules.noRawColorValues","rules.noStylesProp","rules.consistentTokenUsage","rules.noRuntimeStylesMutation","rules.validStateDefinition","rules.noOwnAtRoot","rules.validDefaultStateOrder","rules.preferAutoCalc","rules.preferCustomPropertySyntax","rules.preferHide","rules.preferDirectionalShorthand","rules.preferLonghandProperty"],"sources":["../src/index.ts"],"sourcesContent":["import type { TSESLint } from '@typescript-eslint/utils';\nimport * as rules from './rules/index.js';\nimport { recommended, strict } from './configs.js';\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-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 'valid-state-definition': rules.validStateDefinition,\n 'no-own-at-root': rules.noOwnAtRoot,\n 'valid-default-state-order': rules.validDefaultStateOrder,\n 'prefer-auto-calc': rules.preferAutoCalc,\n 'prefer-custom-property-syntax': rules.preferCustomPropertySyntax,\n 'prefer-hide': rules.preferHide,\n 'prefer-directional-shorthand': rules.preferDirectionalShorthand,\n 'prefer-longhand-property': rules.preferLonghandProperty,\n};\n\nconst plugin = {\n meta: {\n name: '@tenphi/eslint-plugin-tasty',\n version: '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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,MAAM,SAAS;CACb,MAAM;EACJ,MAAM;EACN,SAAS;EACV;CACD,OA1CsE;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,0BAA0BC;EAC1B,uBAAuBC;EACvB,kBAAkBC;EAClB,0BAA0BC;EAC1B,8BAA8BC;EAC9B,0BAA0BC;EAC1B,kBAAkBC;EAClB,6BAA6BC;EAC7B,oBAAoBC;EACpB,iCAAiCC;EACjC,eAAeC;EACf,gCAAgCC;EAChC,4BAA4BC;EAC7B;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
1
  import { createRule } from "../create-rule.js";
2
- import { DIRECTIONAL_MODIFIERS } from "../constants.js";
2
+ import { DIRECTIONAL_BOX_IDENTITY } from "../constants.js";
3
3
  import { getKeyName, getStringValue } from "../utils.js";
4
4
  import { TastyContext, styleObjectListeners } from "../context.js";
5
5
  import { replaceStringValue } from "../fix-utils.js";
@@ -16,15 +16,23 @@ function isZeroLike(token) {
16
16
  if (trimmed === "0") return true;
17
17
  return /^0+(?:\.0+)?(?:px|em|rem|%|x|r|cr|bw|ow|lh|sf)?$/i.test(trimmed);
18
18
  }
19
- function suggestDirectional(value) {
19
+ /**
20
+ * Whether `token` is the placeholder value for an unset side, i.e. dropping it
21
+ * from the shorthand leaves the emitted CSS unchanged.
22
+ */
23
+ function isIdentity(token, identity) {
24
+ if (identity === "auto") return token.trim().toLowerCase() === "auto";
25
+ return isZeroLike(token);
26
+ }
27
+ function suggestDirectional(value, identity) {
20
28
  const tokens = value.trim().split(/\s+/);
21
29
  if (tokens.length !== 4) return null;
22
- const nonZero = tokens.map((token, index) => ({
30
+ const meaningful = tokens.map((token, index) => ({
23
31
  token,
24
32
  side: SIDES[index]
25
- })).filter(({ token }) => !isZeroLike(token));
26
- if (nonZero.length !== 1) return null;
27
- const { token, side } = nonZero[0];
33
+ })).filter(({ token }) => !isIdentity(token, identity));
34
+ if (meaningful.length !== 1) return null;
35
+ const { token, side } = meaningful[0];
28
36
  return `${token} ${side}`;
29
37
  }
30
38
  var prefer_directional_shorthand_default = createRule({
@@ -40,7 +48,7 @@ var prefer_directional_shorthand_default = createRule({
40
48
  create(context) {
41
49
  const ctx = new TastyContext(context);
42
50
  function checkValue(property, value, node) {
43
- const suggestion = suggestDirectional(value);
51
+ const suggestion = suggestDirectional(value, DIRECTIONAL_BOX_IDENTITY[property]);
44
52
  if (!suggestion) return;
45
53
  context.report({
46
54
  node,
@@ -61,7 +69,7 @@ var prefer_directional_shorthand_default = createRule({
61
69
  if (prop.type !== "Property" || prop.computed) continue;
62
70
  const key = getKeyName(prop.key);
63
71
  if (key === null) continue;
64
- if (!(key in DIRECTIONAL_MODIFIERS)) continue;
72
+ if (!(key in DIRECTIONAL_BOX_IDENTITY)) continue;
65
73
  const str = getStringValue(prop.value);
66
74
  if (str) {
67
75
  checkValue(key, str, prop.value);
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-directional-shorthand.js","names":[],"sources":["../../src/rules/prefer-directional-shorthand.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext, styleObjectListeners } from '../context.js';\nimport { getKeyName, getStringValue } from '../utils.js';\nimport { DIRECTIONAL_MODIFIERS } from '../constants.js';\nimport { replaceStringValue } from '../fix-utils.js';\n\ntype MessageIds = 'preferDirectionalShorthand';\n\nconst SIDES = ['top', 'right', 'bottom', 'left'] as const;\n\nfunction isZeroLike(token: string): boolean {\n const trimmed = token.trim();\n if (trimmed === '0') return true;\n return /^0+(?:\\.0+)?(?:px|em|rem|%|x|r|cr|bw|ow|lh|sf)?$/i.test(trimmed);\n}\n\nfunction suggestDirectional(value: string): string | null {\n const tokens = value.trim().split(/\\s+/);\n if (tokens.length !== 4) return null;\n\n const nonZero = tokens\n .map((token, index) => ({ token, side: SIDES[index] }))\n .filter(({ token }) => !isZeroLike(token));\n\n if (nonZero.length !== 1) return null;\n\n const { token, side } = nonZero[0];\n return `${token} ${side}`;\n}\n\nexport default createRule<[], MessageIds>({\n name: 'prefer-directional-shorthand',\n meta: {\n type: 'suggestion',\n fixable: 'code',\n docs: {\n description:\n 'Suggest Tasty directional shorthand instead of 4-value CSS box syntax with zero placeholders',\n },\n messages: {\n preferDirectionalShorthand:\n \"'{{property}}' value '{{raw}}' only sets one side. Use the directional shorthand '{{suggestion}}' (e.g. '1x bottom') instead.\",\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 suggestion = suggestDirectional(value);\n if (!suggestion) return;\n\n context.report({\n node,\n messageId: 'preferDirectionalShorthand',\n data: { property, raw: value, suggestion },\n fix(fixer) {\n return replaceStringValue(fixer, node, suggestion);\n },\n });\n }\n\n function handleStyleObject(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 if (!(key in DIRECTIONAL_MODIFIERS)) 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 return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n ...styleObjectListeners(handleStyleObject),\n };\n },\n});\n"],"mappings":";;;;;;;AASA,MAAM,QAAQ;CAAC;CAAO;CAAS;CAAU;CAAO;AAEhD,SAAS,WAAW,OAAwB;CAC1C,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,YAAY,IAAK,QAAO;AAC5B,QAAO,oDAAoD,KAAK,QAAQ;;AAG1E,SAAS,mBAAmB,OAA8B;CACxD,MAAM,SAAS,MAAM,MAAM,CAAC,MAAM,MAAM;AACxC,KAAI,OAAO,WAAW,EAAG,QAAO;CAEhC,MAAM,UAAU,OACb,KAAK,OAAO,WAAW;EAAE;EAAO,MAAM,MAAM;EAAQ,EAAE,CACtD,QAAQ,EAAE,YAAY,CAAC,WAAW,MAAM,CAAC;AAE5C,KAAI,QAAQ,WAAW,EAAG,QAAO;CAEjC,MAAM,EAAE,OAAO,SAAS,QAAQ;AAChC,QAAO,GAAG,MAAM,GAAG;;AAGrB,2CAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,SAAS;EACT,MAAM,EACJ,aACE,gGACH;EACD,UAAU,EACR,4BACE,iIACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,WACP,UACA,OACA,MACM;GACN,MAAM,aAAa,mBAAmB,MAAM;AAC5C,OAAI,CAAC,WAAY;AAEjB,WAAQ,OAAO;IACb;IACA,WAAW;IACX,MAAM;KAAE;KAAU,KAAK;KAAO;KAAY;IAC1C,IAAI,OAAO;AACT,YAAO,mBAAmB,OAAO,MAAM,WAAW;;IAErD,CAAC;;EAGJ,SAAS,kBAAkB,MAAiC;AAC1D,OAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,QAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,QAAI,KAAK,SAAS,cAAc,KAAK,SAAU;IAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,QAAI,QAAQ,KAAM;AAClB,QAAI,EAAE,OAAO,uBAAwB;IAErC,MAAM,MAAM,eAAe,KAAK,MAAM;AACtC,QAAI,KAAK;AACP,gBAAW,KAAK,KAAK,KAAK,MAAM;AAChC;;AAGF,QAAI,KAAK,MAAM,SAAS,mBACtB,MAAK,MAAM,aAAa,KAAK,MAAM,YAAY;AAC7C,SAAI,UAAU,SAAS,WAAY;KACnC,MAAM,WAAW,eAAe,UAAU,MAAM;AAChD,SAAI,SACF,YAAW,KAAK,UAAU,UAAU,MAAM;;;;AAOpD,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAEvB,GAAG,qBAAqB,kBAAkB;GAC3C;;CAEJ,CAAC"}
1
+ {"version":3,"file":"prefer-directional-shorthand.js","names":[],"sources":["../../src/rules/prefer-directional-shorthand.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext, styleObjectListeners } from '../context.js';\nimport { getKeyName, getStringValue } from '../utils.js';\nimport { DIRECTIONAL_BOX_IDENTITY } from '../constants.js';\nimport { replaceStringValue } from '../fix-utils.js';\n\ntype MessageIds = 'preferDirectionalShorthand';\n\nconst SIDES = ['top', 'right', 'bottom', 'left'] as const;\n\nfunction isZeroLike(token: string): boolean {\n const trimmed = token.trim();\n if (trimmed === '0') return true;\n return /^0+(?:\\.0+)?(?:px|em|rem|%|x|r|cr|bw|ow|lh|sf)?$/i.test(trimmed);\n}\n\n/**\n * Whether `token` is the placeholder value for an unset side, i.e. dropping it\n * from the shorthand leaves the emitted CSS unchanged.\n */\nfunction isIdentity(token: string, identity: string): boolean {\n if (identity === 'auto') return token.trim().toLowerCase() === 'auto';\n return isZeroLike(token);\n}\n\nfunction suggestDirectional(value: string, identity: string): string | null {\n const tokens = value.trim().split(/\\s+/);\n if (tokens.length !== 4) return null;\n\n const meaningful = tokens\n .map((token, index) => ({ token, side: SIDES[index] }))\n .filter(({ token }) => !isIdentity(token, identity));\n\n // Only collapse when exactly one side carries a real value — otherwise the\n // directional shorthand would drop the others.\n if (meaningful.length !== 1) return null;\n\n const { token, side } = meaningful[0];\n return `${token} ${side}`;\n}\n\nexport default createRule<[], MessageIds>({\n name: 'prefer-directional-shorthand',\n meta: {\n type: 'suggestion',\n fixable: 'code',\n docs: {\n description:\n 'Suggest Tasty directional shorthand instead of 4-value CSS box syntax with zero placeholders',\n },\n messages: {\n preferDirectionalShorthand:\n \"'{{property}}' value '{{raw}}' only sets one side. Use the directional shorthand '{{suggestion}}' (e.g. '1x bottom') instead.\",\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 suggestion = suggestDirectional(\n value,\n DIRECTIONAL_BOX_IDENTITY[property],\n );\n if (!suggestion) return;\n\n context.report({\n node,\n messageId: 'preferDirectionalShorthand',\n data: { property, raw: value, suggestion },\n fix(fixer) {\n return replaceStringValue(fixer, node, suggestion);\n },\n });\n }\n\n function handleStyleObject(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 if (!(key in DIRECTIONAL_BOX_IDENTITY)) 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 return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n ...styleObjectListeners(handleStyleObject),\n };\n },\n});\n"],"mappings":";;;;;;;AASA,MAAM,QAAQ;CAAC;CAAO;CAAS;CAAU;CAAO;AAEhD,SAAS,WAAW,OAAwB;CAC1C,MAAM,UAAU,MAAM,MAAM;AAC5B,KAAI,YAAY,IAAK,QAAO;AAC5B,QAAO,oDAAoD,KAAK,QAAQ;;;;;;AAO1E,SAAS,WAAW,OAAe,UAA2B;AAC5D,KAAI,aAAa,OAAQ,QAAO,MAAM,MAAM,CAAC,aAAa,KAAK;AAC/D,QAAO,WAAW,MAAM;;AAG1B,SAAS,mBAAmB,OAAe,UAAiC;CAC1E,MAAM,SAAS,MAAM,MAAM,CAAC,MAAM,MAAM;AACxC,KAAI,OAAO,WAAW,EAAG,QAAO;CAEhC,MAAM,aAAa,OAChB,KAAK,OAAO,WAAW;EAAE;EAAO,MAAM,MAAM;EAAQ,EAAE,CACtD,QAAQ,EAAE,YAAY,CAAC,WAAW,OAAO,SAAS,CAAC;AAItD,KAAI,WAAW,WAAW,EAAG,QAAO;CAEpC,MAAM,EAAE,OAAO,SAAS,WAAW;AACnC,QAAO,GAAG,MAAM,GAAG;;AAGrB,2CAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,SAAS;EACT,MAAM,EACJ,aACE,gGACH;EACD,UAAU,EACR,4BACE,iIACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,WACP,UACA,OACA,MACM;GACN,MAAM,aAAa,mBACjB,OACA,yBAAyB,UAC1B;AACD,OAAI,CAAC,WAAY;AAEjB,WAAQ,OAAO;IACb;IACA,WAAW;IACX,MAAM;KAAE;KAAU,KAAK;KAAO;KAAY;IAC1C,IAAI,OAAO;AACT,YAAO,mBAAmB,OAAO,MAAM,WAAW;;IAErD,CAAC;;EAGJ,SAAS,kBAAkB,MAAiC;AAC1D,OAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,QAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,QAAI,KAAK,SAAS,cAAc,KAAK,SAAU;IAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,QAAI,QAAQ,KAAM;AAClB,QAAI,EAAE,OAAO,0BAA2B;IAExC,MAAM,MAAM,eAAe,KAAK,MAAM;AACtC,QAAI,KAAK;AACP,gBAAW,KAAK,KAAK,KAAK,MAAM;AAChC;;AAGF,QAAI,KAAK,MAAM,SAAS,mBACtB,MAAK,MAAM,aAAa,KAAK,MAAM,YAAY;AAC7C,SAAI,UAAU,SAAS,WAAY;KACnC,MAAM,WAAW,eAAe,UAAU,MAAM;AAChD,SAAI,SACF,YAAW,KAAK,UAAU,UAAU,MAAM;;;;AAOpD,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAEvB,GAAG,qBAAqB,kBAAkB;GAC3C;;CAEJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { createRule } from "../create-rule.js";
2
+ import { LONGHAND_MAPPING } from "../constants.js";
3
+ import { getKeyName } from "../utils.js";
4
+ import { TastyContext, styleObjectListeners } from "../context.js";
5
+
6
+ //#region src/rules/prefer-longhand-property.ts
7
+ var prefer_longhand_property_default = createRule({
8
+ name: "prefer-longhand-property",
9
+ meta: {
10
+ type: "problem",
11
+ docs: { description: "Disallow lossy CSS shorthands whose longhands are the preferred Tasty form" },
12
+ messages: { preferLonghand: "'{{shorthand}}' resets the components you omit to non-initial values. Use {{alternative}} instead." },
13
+ schema: []
14
+ },
15
+ defaultOptions: [],
16
+ create(context) {
17
+ const ctx = new TastyContext(context);
18
+ function handleStyleObject(node) {
19
+ if (!ctx.isStyleObject(node)) return;
20
+ for (const prop of node.properties) {
21
+ if (prop.type !== "Property" || prop.computed) continue;
22
+ const key = getKeyName(prop.key);
23
+ if (key === null) continue;
24
+ const mapping = LONGHAND_MAPPING[key];
25
+ if (!mapping) continue;
26
+ context.report({
27
+ node: prop.key,
28
+ messageId: "preferLonghand",
29
+ data: {
30
+ shorthand: key,
31
+ alternative: mapping.hint
32
+ }
33
+ });
34
+ }
35
+ }
36
+ return {
37
+ ImportDeclaration(node) {
38
+ ctx.trackImport(node);
39
+ },
40
+ ...styleObjectListeners(handleStyleObject)
41
+ };
42
+ }
43
+ });
44
+
45
+ //#endregion
46
+ export { prefer_longhand_property_default as default };
47
+ //# sourceMappingURL=prefer-longhand-property.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-longhand-property.js","names":[],"sources":["../../src/rules/prefer-longhand-property.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport { createRule } from '../create-rule.js';\nimport { TastyContext, styleObjectListeners } from '../context.js';\nimport { getKeyName } from '../utils.js';\nimport { LONGHAND_MAPPING } from '../constants.js';\n\ntype MessageIds = 'preferLonghand';\n\nexport default createRule<[], MessageIds>({\n name: 'prefer-longhand-property',\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Disallow lossy CSS shorthands whose longhands are the preferred Tasty form',\n },\n messages: {\n preferLonghand:\n \"'{{shorthand}}' resets the components you omit to non-initial values. Use {{alternative}} instead.\",\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n const ctx = new TastyContext(context);\n\n function handleStyleObject(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 mapping = LONGHAND_MAPPING[key];\n if (!mapping) continue;\n\n // Report-only: splitting the shorthand requires knowing which of the\n // three components the author actually meant to set.\n context.report({\n node: prop.key,\n messageId: 'preferLonghand',\n data: { shorthand: key, alternative: mapping.hint },\n });\n }\n }\n\n return {\n ImportDeclaration(node) {\n ctx.trackImport(node);\n },\n ...styleObjectListeners(handleStyleObject),\n };\n },\n});\n"],"mappings":";;;;;;AAQA,uCAAe,WAA2B;CACxC,MAAM;CACN,MAAM;EACJ,MAAM;EACN,MAAM,EACJ,aACE,8EACH;EACD,UAAU,EACR,gBACE,sGACH;EACD,QAAQ,EAAE;EACX;CACD,gBAAgB,EAAE;CAClB,OAAO,SAAS;EACd,MAAM,MAAM,IAAI,aAAa,QAAQ;EAErC,SAAS,kBAAkB,MAAiC;AAC1D,OAAI,CAAC,IAAI,cAAc,KAAK,CAAE;AAE9B,QAAK,MAAM,QAAQ,KAAK,YAAY;AAClC,QAAI,KAAK,SAAS,cAAc,KAAK,SAAU;IAE/C,MAAM,MAAM,WAAW,KAAK,IAAI;AAChC,QAAI,QAAQ,KAAM;IAElB,MAAM,UAAU,iBAAiB;AACjC,QAAI,CAAC,QAAS;AAId,YAAQ,OAAO;KACb,MAAM,KAAK;KACX,WAAW;KACX,MAAM;MAAE,WAAW;MAAK,aAAa,QAAQ;MAAM;KACpD,CAAC;;;AAIN,SAAO;GACL,kBAAkB,MAAM;AACtB,QAAI,YAAY,KAAK;;GAEvB,GAAG,qBAAqB,kBAAkB;GAC3C;;CAEJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenphi/eslint-plugin-tasty",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "ESLint plugin for validating tasty() and tastyStatic() style objects",
5
5
  "type": "module",
6
6
  "exports": {