pasika 0.4.2 → 0.5.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
@@ -16,6 +16,7 @@ docs/
16
16
  scripts/
17
17
  registry.json # requirement → enforcement, keyed by content hash
18
18
  coverage.ts # reconciles the docs against the registry
19
+ dogfood.ts # lints sibling repos with the built presets
19
20
  utils/ # doc parsing, classification, registry IO
20
21
  types/ # registry schema
21
22
  constants/
@@ -81,6 +82,21 @@ npx tsx scripts/coverage.ts --classify 041b665bd7 --note "no check can compare a
81
82
 
82
83
  The script refuses a hash no requirement has, a `ref` naming a rule that does not exist, and a classification without a note — so a mismatch cannot reach the registry by hand. Re-running it on an already-recorded requirement replaces the earlier entry. All of it reads and writes `scripts/registry.json`.
83
84
 
85
+ ## Dogfooding
86
+
87
+ `npm run dogfood` lints an arbitrary repository with pasika's built presets, without modifying the target. It exists to find flaws in pasika itself by running it against sibling repos — it does not fix the target. Run `npm run build` first, then point it at a repo:
88
+
89
+ ```bash
90
+ npm run build
91
+ npm run dogfood -- ../some/repo # nextjsApp preset (default)
92
+ npm run dogfood -- ../some/repo --preset=typescriptApp
93
+ npm run dogfood -- ../some/repo --pasika-only # tally only pasika/* rules
94
+ npm run dogfood -- ../some/repo --rule=css-entry-point --findings
95
+ npm run dogfood -- ../some/repo --json # machine-readable report
96
+ ```
97
+
98
+ The script writes a temporary standalone `eslint.config.mjs` that imports the preset from this repo's `dist`, so it exercises exactly the config a consuming repository would write. The exit code reports whether the run succeeded; the target's problem count is informational (printed as `Exit code would be`). A missing `dist` build or an unknown flag exits non-zero.
99
+
84
100
  ## ESLint ruleset
85
101
 
86
102
  ### With Zirka (recommended)
@@ -99,7 +115,7 @@ const { eslintConfig } = styleguide({
99
115
  export default eslintConfig;
100
116
  ```
101
117
 
102
- For a plain TypeScript repository, enable `pasikaTypescriptApp` instead of `pasikaNextjsApp`. `zirka` composes the pasika ruleset over four file scopes: TS/TSX under `src/**`, `globals.css` and other stylesheets, `package.json`, and markdown — each with its own ESLint language.
118
+ For a plain TypeScript repository, enable `pasikaTypescriptApp` instead of `pasikaNextjsApp`; that preset covers the manifest, the zirka contract, and the docs only — the `src/**` source rules belong to the Next.js app preset. `zirka` composes the pasika ruleset over four file scopes: TS/TSX under `src/**`, `globals.css` and other stylesheets, `package.json`, and markdown — each with its own ESLint language.
103
119
 
104
120
  ### Without Zirka
105
121
 
@@ -110,9 +126,11 @@ import { typescriptApp } from "pasika/eslint";
110
126
  export default typescriptApp;
111
127
  ```
112
128
 
113
- `typescriptApp` is the plain-TypeScript-repository preset — the package.json manifest, the zirka configuration contract, the `src/**` TypeScript app source, and the docs. `nextjsApp` is the full framework preset: everything in `typescriptApp` plus the Next.js-stack manifest requirement, the Next.js app source rules, and the Tailwind stylesheet blocks. The granular rule objects (`tailwindRules`, `repoPackageJsonRules`, `documentationRules`) stay exported for manual wiring.
129
+ `typescriptApp` is the plain-TypeScript-repository preset — the package.json manifest, the zirka configuration contract, and the docs. It carries no `src/**` source block: source linting is the Next.js app's job. `nextjsApp` is the full framework preset: everything in `typescriptApp` plus the Next.js-stack manifest requirement, the `src/**` app source rules, and the Tailwind stylesheet blocks. The granular rule objects (`tailwindRules`, `repoPackageJsonRules`, `documentationRules`) stay exported for manual wiring.
130
+
131
+ The `src/**` blocks ship `@typescript-eslint/parser` themselves, so a standalone preset parses `.ts`/`.tsx` correctly on its own (`pasika` lists it as a runtime dependency).
114
132
 
115
- Because the preset blocks wire ESLint's language plugins, using them directly (without `zirka`) requires `@eslint/css`, `@eslint/json`, and `@eslint/markdown` to be installed in the consuming project — they are `peerDependencies` of `pasika`. A `zirka`-based setup gets them automatically.
133
+ Because the preset blocks also wire ESLint's language plugins, using them directly (without `zirka`) requires `@eslint/css`, `@eslint/json`, and `@eslint/markdown` to be installed in the consuming project — they are `peerDependencies` of `pasika`. A `zirka`-based setup gets them automatically.
116
134
 
117
135
  ### TS/TSX rules
118
136
 
@@ -164,19 +182,19 @@ Because the preset blocks wire ESLint's language plugins, using them directly (w
164
182
 
165
183
  Applied to `src/**/globals.css` (and other stylesheets) through `@eslint/css` with tolerant Tailwind v4 parsing.
166
184
 
167
- | Rule | Enforces |
168
- | --------------------------------- | ----------------------------------------------------------------------------- |
169
- | `pasika/theme-reset` | A `--*: initial` theme reset is present |
170
- | `pasika/root-variables` | `:root` defines the CSS custom properties |
171
- | `pasika/apply-usage` | `@layer base` uses `@apply` for declarations |
172
- | `pasika/base-layer-pair` | The base layer applies `base-canvas` and `base-ink` |
173
- | `pasika/stylesheet-ordering` | Imports → `@custom-variant` → `:root` → `@theme` → `@utility` → `@layer base` |
174
- | `pasika/css-variable-naming` | Background vars named `--<role>-canvas`, text vars `--<role>-ink` |
175
- | `pasika/custom-utility-apply` | `@utility` blocks use `@apply` |
176
- | `pasika/surface-utility` | Repeated canvas+ink combos become a named surface utility |
177
- | `pasika/theme-variable-namespace` | Utility class groups share a namespace prefix |
178
- | `pasika/global-css-location` | Global CSS lives in the correct entry point |
179
- | `pasika/unused-utility` | A custom `@utility` no source file references is reported as dead |
185
+ | Rule | Enforces |
186
+ | --------------------------------- | ----------------------------------------------------------------------------------------------------- |
187
+ | `pasika/theme-reset` | A `--*: initial` theme reset is present |
188
+ | `pasika/root-variables` | `:root` defines the CSS custom properties |
189
+ | `pasika/apply-usage` | `@layer base` uses `@apply` for declarations |
190
+ | `pasika/base-layer-pair` | The base layer applies `base-canvas` and `base-ink` |
191
+ | `pasika/stylesheet-ordering` | Imports → `@custom-variant` → `:root` → `@theme` → `@utility` → `@layer base` |
192
+ | `pasika/css-variable-naming` | Background vars named `--<role>-canvas`, text vars `--<role>-ink` |
193
+ | `pasika/custom-utility-apply` | `@utility` blocks use `@apply` |
194
+ | `pasika/surface-utility` | Repeated canvas+ink combos become a named surface utility |
195
+ | `pasika/theme-variable-namespace` | Utility class groups share a namespace prefix |
196
+ | `pasika/css-entry-point`| One global entry, imported by one module, project CSS only in a stylesheet the entry imports directly |
197
+ | `pasika/unused-utility` | A custom `@utility` no source file references is reported as dead |
180
198
 
181
199
  ### Package.json rules
182
200
 
@@ -197,7 +215,7 @@ Run `npx tsx scripts/coverage.ts --json` for the exact requirement each rule cov
197
215
 
198
216
  ### † Cross-file rules
199
217
 
200
- Where a component, hook, value, type, or style belongs depends on which files use it, so the rules marked † index the whole `src/` tree instead of looking at one file. Two consequences:
218
+ Where a component, hook, value, type, or style belongs depends on which files use it — and whether a stylesheet sits inside the global import graph depends on the whole `src/` tree — so the rules marked † index the whole `src/` tree instead of looking at one file. Two consequences:
201
219
 
202
220
  - **Do not pass `--cache`.** Move a file and the finding belongs to a _different_ file, whose cache entry is unchanged — so ESLint would replay a stale verdict. `repository-policy.md` requires lint commands to run without it.
203
221
  - The index is read from disk rather than from ESLint's file list, so a partial run such as `lint-staged` still judges against the true graph.
@@ -216,4 +234,5 @@ npm run typecheck
216
234
  npm run test
217
235
  npm run coverage
218
236
  npm run build
237
+ npm run dogfood -- ../some/repo # requires a build; see Dogfooding above
219
238
  ```
@@ -1,9 +1,9 @@
1
- import * as _eslint_markdown from '@eslint/markdown';
2
- import * as _eslint_css from '@eslint/css';
3
- import * as _eslint_json from '@eslint/json';
4
1
  import * as eslint from 'eslint';
5
2
  import { Rule, Linter } from 'eslint';
6
3
  import * as ESTree from 'estree';
4
+ import * as _eslint_markdown from '@eslint/markdown';
5
+ import * as _eslint_css from '@eslint/css';
6
+ import * as _eslint_json from '@eslint/json';
7
7
 
8
8
  /**
9
9
  * Local AST node types for the parser-specific shapes ESLint's ESTree types
@@ -110,7 +110,7 @@ declare const tailwindRules: {
110
110
  "custom-utility-apply": _eslint_css.CSSRuleDefinition;
111
111
  "surface-utility": _eslint_css.CSSRuleDefinition;
112
112
  "theme-variable-namespace": _eslint_css.CSSRuleDefinition;
113
- "global-css-location": _eslint_css.CSSRuleDefinition;
113
+ "css-entry-point": _eslint_css.CSSRuleDefinition;
114
114
  "global-stylesheet": _eslint_css.CSSRuleDefinition;
115
115
  "unused-utility": _eslint_css.CSSRuleDefinition;
116
116
  };
@@ -121,7 +121,7 @@ declare const repoPackageJsonRules: {
121
121
  "exact-version": _eslint_json.JSONRuleDefinition;
122
122
  };
123
123
  /** Package.json rules specific to a Next.js (or React) application. */
124
- declare const nextPackageJsonRules: {
124
+ declare const nextjsPackageJsonRules: {
125
125
  "nextjs-stack": _eslint_json.JSONRuleDefinition;
126
126
  };
127
127
 
@@ -133,63 +133,6 @@ declare const vulykRules: {
133
133
  "vulyk-docs": _eslint_json.JSONRuleDefinition;
134
134
  };
135
135
 
136
- /** Every source rule, merged so the Next.js preset applies them all. */
137
- declare const pasikaRules: {
138
- "component-placement": eslint.Rule.RuleModule;
139
- "application-structure": eslint.Rule.RuleModule;
140
- "data-testid-case": eslint.Rule.RuleModule;
141
- "jsx-hygiene": eslint.Rule.RuleModule;
142
- "interactive-component": eslint.Rule.RuleModule;
143
- "ui-state": eslint.Rule.RuleModule;
144
- "no-mixed-concerns": eslint.Rule.RuleModule;
145
- "no-arbitrary-tailwind": eslint.Rule.RuleModule;
146
- "unknown-utility": eslint.Rule.RuleModule;
147
- "enforce-cn-merge": {
148
- meta: {
149
- schema: never[];
150
- type: "problem";
151
- docs: {
152
- description: string;
153
- };
154
- };
155
- create(context: eslint.Rule.RuleContext): {
156
- JSXAttribute(node: JsxAttributeNode): void;
157
- };
158
- };
159
- "cn-helper": eslint.Rule.RuleModule;
160
- "enforce-cva-variant-props": eslint.Rule.RuleModule;
161
- "cva-appearance-props": eslint.Rule.RuleModule;
162
- "cva-boolean-variants": eslint.Rule.RuleModule;
163
- "cross-feature-import": eslint.Rule.RuleModule;
164
- "pure-function-extract": eslint.Rule.RuleModule;
165
- "hook-complexity": eslint.Rule.RuleModule;
166
- "locale-dotted-path": eslint.Rule.RuleModule;
167
- "locales-location": eslint.Rule.RuleModule;
168
- "hook-extraction": eslint.Rule.RuleModule;
169
- "component-nesting": eslint.Rule.RuleModule;
170
- "stay-flat": eslint.Rule.RuleModule;
171
- "locale-placement": eslint.Rule.RuleModule;
172
- "sole-state-owner": eslint.Rule.RuleModule;
173
- "locale-key-shape": eslint.Rule.RuleModule;
174
- "shared-style-dedup": eslint.Rule.RuleModule;
175
- "repeated-structure": eslint.Rule.RuleModule;
176
- "filename-case": eslint.Rule.RuleModule;
177
- "import-boundaries": eslint.Rule.RuleModule;
178
- "named-exports": eslint.Rule.RuleModule;
179
- "support-file-placement": eslint.Rule.RuleModule;
180
- "support-folder-shape": eslint.Rule.RuleModule;
181
- "import-through-index": eslint.Rule.RuleModule;
182
- "util-file-name": eslint.Rule.RuleModule;
183
- "no-util-barrel": eslint.Rule.RuleModule;
184
- "enforce-barrel-exports": eslint.Rule.RuleModule;
185
- "config-extraction": eslint.Rule.RuleModule;
186
- "value-extraction": eslint.Rule.RuleModule;
187
- "type-extraction": eslint.Rule.RuleModule;
188
- "zod-schema-validation": eslint.Rule.RuleModule;
189
- "source-under-src": eslint.Rule.RuleModule;
190
- "zirka-baseline": eslint.Rule.RuleModule;
191
- };
192
-
193
136
  /**
194
137
  * One plugin object every preset block references. ESLint only permits a
195
138
  * plugin name to be redefined across configs when the value is the same
@@ -213,7 +156,7 @@ declare const pasikaPlugin: {
213
156
  "custom-utility-apply": _eslint_css.CSSRuleDefinition;
214
157
  "surface-utility": _eslint_css.CSSRuleDefinition;
215
158
  "theme-variable-namespace": _eslint_css.CSSRuleDefinition;
216
- "global-css-location": _eslint_css.CSSRuleDefinition;
159
+ "css-entry-point": _eslint_css.CSSRuleDefinition;
217
160
  "global-stylesheet": _eslint_css.CSSRuleDefinition;
218
161
  "unused-utility": _eslint_css.CSSRuleDefinition;
219
162
  "doc-kind-suffix": _eslint_markdown.MarkdownRuleDefinition;
@@ -239,6 +182,21 @@ declare const pasikaPlugin: {
239
182
  "no-nested-how-to": _eslint_markdown.MarkdownRuleDefinition;
240
183
  "glossary-term-linking": _eslint_markdown.MarkdownRuleDefinition;
241
184
  "guide-mentions-documents": _eslint_markdown.MarkdownRuleDefinition;
185
+ "filename-case": eslint.Rule.RuleModule;
186
+ "import-boundaries": eslint.Rule.RuleModule;
187
+ "named-exports": eslint.Rule.RuleModule;
188
+ "support-file-placement": eslint.Rule.RuleModule;
189
+ "support-folder-shape": eslint.Rule.RuleModule;
190
+ "import-through-index": eslint.Rule.RuleModule;
191
+ "util-file-name": eslint.Rule.RuleModule;
192
+ "no-util-barrel": eslint.Rule.RuleModule;
193
+ "enforce-barrel-exports": eslint.Rule.RuleModule;
194
+ "config-extraction": eslint.Rule.RuleModule;
195
+ "value-extraction": eslint.Rule.RuleModule;
196
+ "type-extraction": eslint.Rule.RuleModule;
197
+ "zod-schema-validation": eslint.Rule.RuleModule;
198
+ "source-under-src": eslint.Rule.RuleModule;
199
+ "zirka-baseline": eslint.Rule.RuleModule;
242
200
  "component-placement": eslint.Rule.RuleModule;
243
201
  "application-structure": eslint.Rule.RuleModule;
244
202
  "data-testid-case": eslint.Rule.RuleModule;
@@ -277,21 +235,6 @@ declare const pasikaPlugin: {
277
235
  "locale-key-shape": eslint.Rule.RuleModule;
278
236
  "shared-style-dedup": eslint.Rule.RuleModule;
279
237
  "repeated-structure": eslint.Rule.RuleModule;
280
- "filename-case": eslint.Rule.RuleModule;
281
- "import-boundaries": eslint.Rule.RuleModule;
282
- "named-exports": eslint.Rule.RuleModule;
283
- "support-file-placement": eslint.Rule.RuleModule;
284
- "support-folder-shape": eslint.Rule.RuleModule;
285
- "import-through-index": eslint.Rule.RuleModule;
286
- "util-file-name": eslint.Rule.RuleModule;
287
- "no-util-barrel": eslint.Rule.RuleModule;
288
- "enforce-barrel-exports": eslint.Rule.RuleModule;
289
- "config-extraction": eslint.Rule.RuleModule;
290
- "value-extraction": eslint.Rule.RuleModule;
291
- "type-extraction": eslint.Rule.RuleModule;
292
- "zod-schema-validation": eslint.Rule.RuleModule;
293
- "source-under-src": eslint.Rule.RuleModule;
294
- "zirka-baseline": eslint.Rule.RuleModule;
295
238
  };
296
239
  };
297
240
  /** Every rule id, as they appear in configuration and in lint output. */
@@ -299,16 +242,17 @@ declare const allPasikaRuleIds: string[];
299
242
  /**
300
243
  * TypeScript app preset: the framework-agnostic baseline — the package.json
301
244
  * manifest (incl. husky hook and vulyk requirements), the zirka configuration
302
- * contract, the `src/**` TS/TSX source, and the documentation markdown rules.
303
- * Use this for a plain TypeScript repository.
245
+ * contract, and the documentation markdown rules. It carries no `src/**`
246
+ * source block: source linting is the Next.js app's job.
247
+ * Use this for a plain TypeScript repository that does not adopt the framework.
304
248
  */
305
249
  declare const typescriptApp: Linter.Config[];
306
250
  /**
307
251
  * Next.js app preset: the full adopted-to-the-framework stack. Anything in
308
252
  * `typescriptApp` plus the framework-only blocks — the Next.js-stack manifest
309
- * requirement, the Next.js app source rules, and the Tailwind stylesheet
253
+ * requirement, the `src/**` app source rules, and the Tailwind stylesheet
310
254
  * rules. `typescriptApp` is a strict subset of `nextjsApp`.
311
255
  */
312
256
  declare const nextjsApp: Linter.Config[];
313
257
 
314
- export { allPasikaRuleIds, documentationRules, huskyRules, nextPackageJsonRules, nextjsApp, pasikaPlugin, pasikaRules, repoPackageJsonRules, tailwindRules, typescriptApp, vulykRules };
258
+ export { allPasikaRuleIds, documentationRules, huskyRules, nextjsApp, nextjsPackageJsonRules, pasikaPlugin, repoPackageJsonRules, tailwindRules, typescriptApp, vulykRules };