@tenphi/eslint-plugin-tasty
v1.0.5
Published
ESLint plugin for validating tasty() and tastyStatic() style objects
Maintainers
Readme
@tenphi/eslint-plugin-tasty
ESLint plugin for validating tasty(), tastyStatic(), useStyles(), useGlobalStyles(), and related APIs from @tenphi/tasty.
Catch typos, invalid syntax, and enforce best practices in your tasty style objects at lint time.
Targets @tenphi/tasty v3. v1 of this plugin validates the v3 style DSL: kebab-case at-rule keys (@property, @font-face, @counter-style, @function), $$name(...) CSS-function calls, and one value per directional group. The v2 at-rule spellings are reported with an auto-fix, so eslint --fix handles most of the upgrade. For tasty v2, pin @tenphi/eslint-plugin-tasty@^0.11.
Installation
pnpm add -D @tenphi/eslint-plugin-tastyUsage
ESLint Flat Config (ESLint 9+)
// eslint.config.js
import tasty from '@tenphi/eslint-plugin-tasty';
export default [
tasty.configs.recommended,
// your other configs...
];For stricter checks:
import tasty from '@tenphi/eslint-plugin-tasty';
export default [
tasty.configs.strict,
];Manual Rule Configuration
import tasty from '@tenphi/eslint-plugin-tasty';
export default [
{
plugins: { tasty },
rules: {
'tasty/known-property': 'warn',
'tasty/valid-value': 'error',
'tasty/valid-color-token': 'error',
// ...
},
},
];Project Configuration
Create a tasty.config.ts (or .js, .json) at your project root to configure validation:
// tasty.config.ts
export default {
tokens: ['#primary', '#danger', '#surface', '$spacing', '$gap'],
units: ['cols'],
functions: ['double', 'okhsl'],
states: ['@mobile', '@tablet', '@dark'],
presets: ['h1', 'h2', 'h3', 't1', 't2', 't3'],
recipes: ['card', 'elevated', 'reset'],
styles: ['glaze'],
importSources: ['@my-org/design-system'],
ownedSources: ['@my-org/*'],
};Every list defaults to "don't check": omit tokens and token existence is not
validated, set tokens: false to disable the check even though a parent config
sets it. importSources matters when you re-export tasty() from your own
module — the plugin only recognizes tasty({ styles }) when the call comes from a
tracked import, so a local barrel needs listing here.
ownedSources answers a different question: which base components you can edit.
When a rule's advice is "change the component you are extending", it stays quiet
over a base imported from someone else's package. Components declared in the same
file and relative, absolute, ~, # or @/ imports count as yours already —
list a scope here only for a design system you publish from your own monorepo
(* matches any run of characters).
functionswas calledfuncsbefore v1. The old spelling is still read as a deprecated alias.
Rules
Recommended
| Rule | Severity | Description |
|------|----------|-------------|
| tasty/known-property | warn | Unknown style property names (checked against the full MDN/W3C CSS property set) |
| tasty/valid-value | error | Malformed style values (unbalanced parens, !important) |
| tasty/valid-color-token | error | Invalid color token syntax or unknown tokens |
| tasty/valid-custom-unit | error | Unknown custom units |
| tasty/valid-boolean-property | error | true on properties that don't support it |
| tasty/valid-state-key | error | Invalid state key syntax in style mappings (including misuse of the _ fallback floor) |
| tasty/valid-styles-structure | error | Invalid styles object structure, and the v2 at-rule key spellings (auto-fixable) |
| tasty/no-nested-state-map | error | Nested state maps (not supported) |
| tasty/no-important | error | !important usage (breaks tasty specificity) |
| tasty/valid-sub-element | error | Sub-element values must be style objects |
| tasty/valid-directional-modifier | error | Directional modifiers on wrong properties, and more than one value in a group that names directions |
| tasty/valid-radius-shape | error | Unknown radius shape keywords |
| tasty/valid-preset | error | Unknown preset names |
| tasty/valid-recipe | error | Unknown recipe names |
| tasty/valid-transition | warn | Unknown transition property names |
| tasty/no-nested-selector | warn | &-prefixed nested selectors (use sub-elements) |
| tasty/static-no-dynamic-values | error | Dynamic values in tastyStatic() |
| tasty/static-valid-selector | error | Invalid selector in tastyStatic(selector, ...) |
| tasty/require-default-state | error | Missing default ('') or fallback floor (_) key in state mappings (skipped for extending calls) |
| tasty/no-own-at-root | warn | @own() used at root level where it is redundant |
| tasty/valid-default-state-order | warn | Misplaced default ('') or redundant '' when only _ is present |
| tasty/prefer-shorthand-property | warn | Use Tasty shorthand instead of native CSS properties (backgroundColor → fill, etc.). In an extension layer the rewrite is report-only and points at a token in the base component, and over a base you cannot edit it is skipped (see ownedSources) |
| tasty/no-raw-color-values | warn | Raw hex/rgb/okhsl/okhst/oklch/named colors instead of #color tokens |
| tasty/consistent-token-usage | warn | Raw px values when custom units or tokens exist |
| tasty/prefer-auto-calc | warn | calc(...) instead of Tasty auto-calc (...) |
| tasty/prefer-custom-property-syntax | warn | var(--prop) / $x-color / transparent / currentColor instead of $prop / #color / #clear / #current |
| tasty/prefer-hide | warn | display: 'none' instead of hide: true |
| tasty/prefer-directional-shorthand | warn | 4-value margin/padding/inset/radius/fade/border with placeholder positions instead of directional form |
| tasty/prefer-longhand-property | error | Lossy flex shorthand instead of flexGrow / flexShrink / flexBasis |
Strict (includes all recommended rules)
| Rule | Severity | Description |
|------|----------|-------------|
| tasty/valid-custom-property | warn | Unknown $name custom properties |
| tasty/valid-state-definition | warn | Invalid state definition values in configure() or tasty.config |
| tasty/no-unknown-state-alias | warn | Unknown @name state aliases |
| tasty/no-styles-prop | warn | Direct styles prop usage |
| tasty/no-runtime-styles-mutation | warn | Dynamic values in style objects |
License
MIT
