{"_id":"@cascivo/eslint-plugin","_rev":"4-f0c729bc6786fe2d45c02a4ae2ccb539","name":"@cascivo/eslint-plugin","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@cascivo/eslint-plugin","version":"0.1.0","keywords":["cascivo","design-system","eslint","eslint-plugin","react"],"author":"urbanisierung","license":"MIT","_id":"@cascivo/eslint-plugin@0.1.0","maintainers":[{"name":"urbanisierung","email":"adam.urban@gmail.com"}],"homepage":"https://github.com/cascivo/cascivo/tree/main/packages/eslint-plugin#readme","bugs":"https://github.com/cascivo/cascivo/issues","dist":{"shasum":"b24ea5ceae544b2d8afd7b805f8be4adbd62a490","tarball":"https://registry.npmjs.org/@cascivo/eslint-plugin/-/eslint-plugin-0.1.0.tgz","fileCount":8,"integrity":"sha512-qnY+kCMylJ2L3uP33Lbi8g3LFnWN4V/gHiIuHF9SlgpsUuslIwm3PP+YJeHuRb69vBRZS5PWEZcnqGlYNMiioQ==","signatures":[{"sig":"MEYCIQC3UoIh4BKa/F+KibBNiipZTZe8fQd4/8ve4JffeFh7jQIhAJyGgBwyzE0a3Oa2I4vMPoMgvgZ4ou5dfmswDsLIBQey","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23698},"type":"module","exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"node --test src/*.test.js","build":"echo 'eslint-plugin: plain ESM, no build'"},"_npmUser":{"name":"urbanisierung","email":"adam.urban@gmail.com"},"repository":{"url":"git+https://github.com/cascivo/cascivo.git","type":"git","directory":"packages/eslint-plugin"},"description":"ESLint rule that turns cascivo's near-miss prop names into an actionable message — the wrong guess, the prop that exists, and why","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"eslint":"10.8.0"},"peerDependencies":{"eslint":">=9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin_0.1.0_1787749740675_0.12157063058728146","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@cascivo/eslint-plugin","version":"0.1.1","keywords":["cascivo","design-system","eslint","eslint-plugin","react"],"author":"urbanisierung","license":"MIT","_id":"@cascivo/eslint-plugin@0.1.1","maintainers":[{"name":"urbanisierung","email":"adam.urban@gmail.com"}],"homepage":"https://github.com/cascivo/cascivo/tree/main/packages/eslint-plugin#readme","bugs":"https://github.com/cascivo/cascivo/issues","dist":{"shasum":"d19e609e9af52dc1b79b425b49696b51032aeffa","tarball":"https://registry.npmjs.org/@cascivo/eslint-plugin/-/eslint-plugin-0.1.1.tgz","fileCount":8,"integrity":"sha512-gqyt/y+9g+OLlHWSg2/Hfc6puNHn2AupHiL7K9GMQsrioiIBbBKtaU8uy6k1JyfmQ5GtMDUKnbwIirCGaAtOSA==","signatures":[{"sig":"MEQCIAVb/8L1Y6rPu+AtaNbW6ZWy56iRqzNCt61uJdYwt4soAiARtQNOFk9oLg5sE1XItk6eEcUnBDydYi2gQoS21kzmrw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cascivo%2feslint-plugin@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":23698},"type":"module","exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"node --test src/*.test.js","build":"echo 'eslint-plugin: plain ESM, no build'"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:345409fa-1d5c-46d1-ae05-f0812bbd38fe"}},"repository":{"url":"git+https://github.com/cascivo/cascivo.git","type":"git","directory":"packages/eslint-plugin"},"description":"ESLint rule that turns cascivo's near-miss prop names into an actionable message — the wrong guess, the prop that exists, and why","directories":{},"_nodeVersion":"22.23.2","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"eslint":"10.8.0"},"peerDependencies":{"eslint":">=9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin_0.1.1_1787751435776_0.17059916169265454","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cascivo/eslint-plugin","version":"0.2.0","keywords":["cascivo","design-system","eslint","eslint-plugin","react"],"author":"urbanisierung","license":"MIT","_id":"@cascivo/eslint-plugin@0.2.0","maintainers":[{"name":"urbanisierung","email":"adam.urban@gmail.com"}],"homepage":"https://github.com/cascivo/cascivo/tree/main/packages/eslint-plugin#readme","bugs":"https://github.com/cascivo/cascivo/issues","dist":{"shasum":"8e9711d2abde0e1513c23593e5e4f6aab230e9df","tarball":"https://registry.npmjs.org/@cascivo/eslint-plugin/-/eslint-plugin-0.2.0.tgz","fileCount":10,"integrity":"sha512-LqjKJV7eCY71nVwKv4FfdZ9HXcpz4tn4nQJ5COpGLcnIrrAHmf4mOtJzBAQF36djA969Vudjs6b/gknMRTGbKw==","signatures":[{"sig":"MEUCIEOhswjQIHMU99iwBRSchUvkwd+7qx7IQ7DkugDVtSpuAiEAiO9iBGgbX2RzdQXwzXR9VF7rH4LUArRoA+uU6FaEXcQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cascivo%2feslint-plugin@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":44180},"type":"module","exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./package.json":"./package.json"},"private":false,"scripts":{"test":"node --test src/*.test.js","build":"echo 'eslint-plugin: plain ESM, no build'"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:345409fa-1d5c-46d1-ae05-f0812bbd38fe"}},"repository":{"url":"git+https://github.com/cascivo/cascivo.git","type":"git","directory":"packages/eslint-plugin"},"description":"ESLint rule that turns cascivo's near-miss prop names into an actionable message — the wrong guess, the prop that exists, and why","directories":{},"_nodeVersion":"22.23.2","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"eslint":"10.8.0","@typescript-eslint/parser":"8.66.0"},"peerDependencies":{"eslint":">=9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin_0.2.0_1788882561186_0.09539929671263869","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"_id":"@cascivo/eslint-plugin@0.2.1","bugs":"https://github.com/cascivo/cascivo/issues","dist":{"shasum":"9907375c7d2bc4c0d3dea3d82663b3c07355e8ac","tarball":"https://registry.npmjs.org/@cascivo/eslint-plugin/-/eslint-plugin-0.2.1.tgz","fileCount":10,"integrity":"sha512-dlA9d87yF2TOTkFQYa1Qf8FSE00vGJAIEf1wy9pxAnnZbKbuykXG6nw14vFOR2g1BeStirEZeFeoklMkFILQPw==","signatures":[{"sig":"MEUCIQDGhthDuyUFR/0HikZ0G2eZxCulvapgLJ5pEAZnapmKegIgC9Z4RL5msqNf/IYDx2RynFjfXEFOcjtD4/e7B6SSELE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICYs+P+2eP7iZPmZmSjrc82hEbehBU3oq+oz1HQzTtFVAiBrvSWekby2NzGYw47ThwXHcVDrIfL7UzMor74CGZQlxQ=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cascivo%2feslint-plugin@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":44308},"name":"@cascivo/eslint-plugin","type":"module","author":"urbanisierung","exports":{".":{"types":"./src/index.d.ts","default":"./src/index.js"},"./package.json":"./package.json"},"license":"MIT","private":false,"scripts":{"test":"node --test src/*.test.js","build":"echo 'eslint-plugin: plain ESM, no build'"},"version":"0.2.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:345409fa-1d5c-46d1-ae05-f0812bbd38fe"}},"homepage":"https://github.com/cascivo/cascivo/tree/main/packages/eslint-plugin#readme","keywords":["cascivo","design-system","eslint","eslint-plugin","react"],"repository":{"url":"git+https://github.com/cascivo/cascivo.git","type":"git","directory":"packages/eslint-plugin"},"description":"ESLint rule that turns cascivo's near-miss prop names into an actionable message — the wrong guess, the prop that exists, and why","directories":{},"maintainers":[{"name":"urbanisierung","email":"adam.urban@gmail.com"}],"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"eslint":"10.8.0","@typescript-eslint/parser":"8.66.0"},"peerDependencies":{"eslint":">=9.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/eslint-plugin_0.2.1_1789570776343_0.7097773727801167"}}},"time":{"created":"2026-08-26T13:09:00.477Z","modified":"2026-09-16T14:59:36.773Z","0.1.0":"2026-08-26T13:09:00.821Z","0.1.1":"2026-08-26T13:37:15.900Z","0.2.0":"2026-09-08T15:49:21.324Z","0.2.1":"2026-09-16T14:59:36.454Z"},"bugs":"https://github.com/cascivo/cascivo/issues","author":"urbanisierung","license":"MIT","homepage":"https://github.com/cascivo/cascivo/tree/main/packages/eslint-plugin#readme","keywords":["cascivo","design-system","eslint","eslint-plugin","react"],"repository":{"url":"git+https://github.com/cascivo/cascivo.git","type":"git","directory":"packages/eslint-plugin"},"description":"ESLint rule that turns cascivo's near-miss prop names into an actionable message — the wrong guess, the prop that exists, and why","maintainers":[{"name":"urbanisierung","email":"adam.urban@gmail.com"}],"readme":"<!-- generated by scripts/readme/generate.ts — edit readme.body.md, not this file -->\n\n<div align=\"center\">\n  <a href=\"https://cascivo.com\"><img src=\"https://cascivo.com/logo-mark-img-accent.svg\" width=\"72\" height=\"72\" alt=\"cascivo logo\"></a>\n  <h1>@cascivo/eslint-plugin</h1>\n  <p><strong>ESLint rule that turns cascivo's near-miss prop names into an actionable message — the wrong guess, the prop that exists, and why</strong></p>\n\n[![npm](https://img.shields.io/npm/v/%40cascivo%2Feslint-plugin?style=flat-square&color=0079bf)](https://www.npmjs.com/package/@cascivo/eslint-plugin)\n[![downloads](https://img.shields.io/npm/dm/%40cascivo%2Feslint-plugin?style=flat-square&color=0079bf)](https://www.npmjs.com/package/@cascivo/eslint-plugin)\n[![license](https://img.shields.io/npm/l/%40cascivo%2Feslint-plugin?style=flat-square&color=0079bf)](https://github.com/cascivo/cascivo/blob/main/LICENSE)\n![types](https://img.shields.io/badge/types-included-0079bf?style=flat-square&logo=typescript&logoColor=white)\n\n[npm](https://www.npmjs.com/package/@cascivo/eslint-plugin) · [cascivo.com](https://cascivo.com) · [Docs](https://cascivo.com/docs) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/cascivo/cascivo)\n\n</div>\n\n---\n\nTwo ESLint rules:\n\n- **`cascivo/prop-vocabulary`** — reports the prop names an adopter is likely to guess wrong, and answers with the prop that exists and why.\n- **`cascivo/token-values`** — reports a `--cascivo-*` custom property that does not exist, and names the one that does.\n\nYou probably do not need to install this directly — [`@cascivo/eslint-config`](../eslint-config) depends on it and enables both rules at `warn`.\n\n## Why it exists\n\nA 2026-08-21 adopter report put it precisely:\n\n> A fresh adopter's success is currently load-bearing on the docs staying this good — the API itself still has the sharp edges. **The docs are doing work the API should eventually do itself.**\n\nMost of that work moved into the type system: `label` and `ariaLabel` both compile now, `Switch` is exported, `Field` takes `hint`. What is left is the class TypeScript structurally cannot help with. `<Text tone=\"subtle\">` is a correct type error whose message —\n\n```\nProperty 'tone' does not exist on type 'TextProps'.\n```\n\n— names the mistake and teaches nothing, so you go looking for the docs anyway. That is the dependency the report flagged. TypeScript has no mechanism for a custom message on an unknown prop; a runtime warning cannot tell a typo from a legitimate DOM passthrough and arrives after the build you are fixing. A lint rule is the one layer that can carry the sentence:\n\n```\n`Text` has no `tone` prop — it is `muted`. `tone` is the catalog's SEVERITY vocabulary\n(Status, Badge, Timeline, SideNav). Text emphasis is the boolean `muted`.\n```\n\n## What it catches\n\n| You wrote                                      | It says                                                    | Autofix                     |\n| ---------------------------------------------- | ---------------------------------------------------------- | --------------------------- |\n| `<Text tone=\"subtle\">`                         | the prop is `muted`; `tone` is the severity vocabulary     | —                           |\n| `<Flex gap=\"4\">`                               | `gap` takes a number                                       | ✅ → `gap={4}`              |\n| `<Flex justify=\"between\">` with no `direction` | `Flex` is vertical by default, unlike CSS/Chakra/MUI/Radix | —                           |\n| `const { theme } = useTheme()`                 | it returns a tuple                                         | —                           |\n| `import { Dialog } from '@cascivo/react'`      | `Dialog` is `Modal`                                        | ✅ (unaliased imports only) |\n| `<DataTable items={…}>`                        | it takes `rows` — the one component that does              | —                           |\n\n## `cascivo/token-values` — the name that does not exist\n\n`prop-vocabulary` exists because a correct TypeScript error teaches nothing. This rule exists because there is **no error at all**.\n\nCSS silently drops an unknown custom property. `--cascivo-color-acent: red` does not warn, does not fail the build, does not appear in DevTools, and does not throw. It has no effect, and the hunt for the cause starts in the component. React makes it worse: `CSSProperties` has no index signature for `--*` keys, so every custom property in a `style` prop reaches the DOM through a cast you wrote — and a cast launders a typo by definition.\n\n```\n`--cascivo-color-acent` is not a cascivo token — CSS drops an unknown custom property\nsilently, so this has no effect. Did you mean `--cascivo-color-accent`?\n```\n\nIt also finds names written with the words in the wrong order, which plain edit distance never does:\n\n| You wrote                                                      | It says                                                                      |\n| -------------------------------------------------------------- | ---------------------------------------------------------------------------- |\n| `--cascivo-color-acent`                                        | did you mean `--cascivo-color-accent`                                        |\n| `--cascivo-text-color`                                         | did you mean `--cascivo-color-text` (`--cascivo-text-*` is the _size_ scale) |\n| `color: 'var(--cascivo-color-txt)'`                            | same check, inside a `var()` reference                                       |\n| `background: '#3b82f6'` where exactly one token has that value | use `var(--cascivo-…)` so it follows the theme                               |\n\nThe name set is generated by `scripts/style-contract/generate.ts` from the same catalog the docs site and `cascivo audit --ai` read, so the three cannot disagree. `cascivo audit --ai` reports the same class at **error** — it also scans your CSS, which a lint rule cannot.\n\nYour own custom properties are none of its business: only the `--cascivo-` namespace is checked.\n\n## Install\n\n```sh\npnpm add -D @cascivo/eslint-config   # brings this plugin with it\n```\n\n```js\n// eslint.config.js\nimport cascivo from '@cascivo/eslint-config'\n\nexport default [...yourConfig, ...cascivo] // spread LAST — flat config is last-wins\n```\n\nOr wire the rule up yourself:\n\n```js\nimport cascivoPlugin from '@cascivo/eslint-plugin'\n\nexport default [\n  {\n    plugins: { cascivo: cascivoPlugin },\n    rules: { 'cascivo/prop-vocabulary': 'warn' },\n  },\n]\n```\n\n## `warn`, not `error`\n\nDeliberate. A lint rule that fails your build over a naming opinion gets the whole config deleted — and that takes `react-hooks/immutability` with it, which is what `@cascivo/eslint-config` exists for. Raise it to `error` yourself if you want it enforced.\n\n## Adding a case\n\nEvery case lives in `near-misses.json`, from which `scripts/eslint-vocabulary/generate.ts` emits the data the rule reads. Each row is validated against `registry.json` at generation time: the prop it recommends must exist on that component, and the prop it warns about must not. A rename on either side fails `pnpm regen` rather than shipping a rule that teaches the wrong thing with the authority of a fix list.\n\nSo the next friction report costs a row in a JSON file, not a paragraph in a guide.\n\n## Install\n\n```sh\npnpm add @cascivo/eslint-plugin\n```\n\n---\n\n[cascivo.com](https://cascivo.com) · [Docs](https://cascivo.com/docs) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/cascivo/cascivo) · AI agents: read [`llms.txt`](https://cascivo.com/llms.txt) (install steps + component index, plain text) or use [`@cascivo/mcp`](https://github.com/cascivo/cascivo/tree/main/packages/mcp) and [`registry.json`](https://github.com/cascivo/cascivo/blob/main/registry.json) · MIT\n\n<div align=\"center\"><a href=\"https://cascivo.com\"><img src=\"https://cascivo.com/logo-mark-img.svg\" width=\"28\" height=\"28\" alt=\"cascivo\"></a></div>\n","readmeFilename":""}