@konvert7/klint 0.24.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -97,6 +97,7 @@ klint is for rules that are too project-specific or context-heavy for a formatte
97
97
  | Layer boundaries | `src/components/**` must not import from `src/data/**` |
98
98
  | Singleton ownership | `process.env.API_KEY` may only appear in `src/lib/auth.ts` |
99
99
  | Forbidden patterns | `console.log(` is blocked inside hook libraries |
100
+ | Raw JSX elements | `<button>` is blocked outside `src/components/ui/**` |
100
101
  | Type-aware mistakes | Promise-returning calls cannot be silently discarded |
101
102
  | Repository policy | Custom `klint.rules.ts` rules run with the same severity/config system |
102
103
 
@@ -273,6 +274,18 @@ arch:
273
274
  message: "Libraries should return or throw, not terminate the process"
274
275
  ```
275
276
 
277
+ Block raw JSX/HTML elements with `jsx-element` to push consumers onto design-system primitives. It is AST-matched on intrinsic (lowercase) tag names, so it is robust to whitespace, attributes, and lookalikes like `<buttonGroup>`:
278
+
279
+ ```yaml
280
+ arch:
281
+ forbidden:
282
+ - jsx-element: ["button", "input", "label"]
283
+ in: ["src/app/**/*.tsx", "src/components/**/*.tsx", "!src/components/ui/**"]
284
+ message: "Use the design-system primitives in @/components/ui/* instead of raw HTML elements"
285
+ ```
286
+
287
+ `jsx-element` matches intrinsic HTML elements only — not custom components like `<Button>`. Use `arch.imports` to restrict those.
288
+
276
289
  ### Singleton Locations
277
290
 
278
291
  Enforce that a pattern appears only in one designated file:
@@ -286,6 +299,17 @@ arch:
286
299
  message: "Use the auth module"
287
300
  ```
288
301
 
302
+ `singleton` accepts `jsx-element` too — pin a raw element to the one primitive file that is allowed to render it:
303
+
304
+ ```yaml
305
+ arch:
306
+ singleton:
307
+ - jsx-element: "button"
308
+ only: "src/components/ui/button.tsx"
309
+ in: ["src/**/*.tsx"]
310
+ message: "Raw <button> belongs only to the Button primitive"
311
+ ```
312
+
289
313
  ### Python Architecture Checks
290
314
 
291
315
  The Rust engine can apply architecture rules to Python projects:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konvert7/klint",
3
- "version": "0.24.0",
3
+ "version": "0.24.1",
4
4
  "description": "Architecture-as-Code linter for TypeScript. Enforce layer boundaries, import rules, and singleton patterns in YAML.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -64,10 +64,10 @@
64
64
  "zod": "^4.4.3"
65
65
  },
66
66
  "optionalDependencies": {
67
- "@konvert7/klint-darwin-arm64": "0.24.0",
68
- "@konvert7/klint-darwin-x64": "0.24.0",
69
- "@konvert7/klint-linux-x64": "0.24.0",
70
- "@konvert7/klint-win32-x64": "0.24.0"
67
+ "@konvert7/klint-darwin-arm64": "0.24.1",
68
+ "@konvert7/klint-darwin-x64": "0.24.1",
69
+ "@konvert7/klint-linux-x64": "0.24.1",
70
+ "@konvert7/klint-win32-x64": "0.24.1"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@biomejs/biome": "2.4.7",
@@ -4,6 +4,19 @@ description: Add, modify, or explain klint architecture rules for this repo. Use
4
4
  argument-hint: <constraint to enforce>
5
5
  ---
6
6
 
7
+ ## Schema
8
+
9
+ The full, authoritative config schema lives in the repo and is the source of truth for every field below:
10
+
11
+ - YAML: <https://github.com/konvert7/klint/blob/main/klint.schema.yaml>
12
+ - JSON: <https://github.com/konvert7/klint/blob/main/klint.schema.json>
13
+
14
+ Wire it into `klint.yaml` for editor autocomplete and validation:
15
+
16
+ ```yaml
17
+ # yaml-language-server: $schema=./klint.schema.yaml
18
+ ```
19
+
7
20
  ## Workflow
8
21
 
9
22
  1. **Understand the constraint** — if scope is ambiguous, ask: which files/layers are involved? should it block or warn? are there legitimate exceptions?
@@ -19,8 +32,10 @@ argument-hint: <constraint to enforce>
19
32
  |---|---|
20
33
  | Layer X must not import from layer Y | `arch.imports` + `deny` |
21
34
  | Layer X may only import from Y and Z | `arch.imports` + `allow` |
22
- | Pattern P must only appear in one designated file | `arch.singleton` |
23
- | Pattern P must never appear inside a scoped layer | `arch.forbidden` |
35
+ | Pattern P must only appear in one designated file | `arch.singleton` + `pattern` |
36
+ | Pattern P must never appear inside a scoped layer | `arch.forbidden` + `pattern` |
37
+ | Raw HTML/JSX element must never appear in a scoped layer | `arch.forbidden` + `jsx-element` |
38
+ | Raw HTML/JSX element may only appear in one primitive file | `arch.singleton` + `jsx-element` |
24
39
 
25
40
  4. **Read `klint.yaml`** — check existing `arch.layers` and rules before adding anything. Add a new named layer to `arch.layers` if the file group doesn't exist yet.
26
41
 
@@ -69,29 +84,56 @@ arch:
69
84
  ```
70
85
 
71
86
  ### Singleton — one designated location
87
+
88
+ Pin a `pattern` (literal string) **or** a `jsx-element` (AST-matched tag) to exactly one file. Every other in-scope occurrence is a violation.
89
+
72
90
  ```yaml
73
91
  arch:
74
92
  singleton:
93
+ # pattern: literal string match — fires if it appears anywhere except `only`
75
94
  - pattern: "process.env.API_KEY"
76
95
  only: "src/lib/auth.ts"
77
- in: ["src/**"] # optional: limit scan scope (default: all files)
96
+ in: ["src/**"] # optional: limit scan scope (default: all files). string OR array
78
97
  message: "Use the auth module instead of reading API_KEY directly"
98
+ severity: error # optional — default error; use warn to record without blocking
99
+
100
+ # jsx-element: pin a raw element to its design-system primitive
101
+ - jsx-element: "button" # one tag, or a list: ["button", "input"]
102
+ only: "src/components/ui/button.tsx"
103
+ in: ["src/**/*.tsx"]
104
+ message: "Raw <button> belongs only to the Button primitive"
79
105
  ```
80
106
 
81
- `pattern` is a **literal string match**. It fires if the pattern appears in any in-scope file except the `only` file.
107
+ Required: `only` + `message`, plus one of `pattern` / `jsx-element` (not both in the same stanza).
82
108
 
83
109
  ### Forbidden — banned pattern in scope
110
+
111
+ Block a `pattern` (literal string) **or** a `jsx-element` (AST-matched tag) inside a scoped layer.
112
+
84
113
  ```yaml
85
114
  arch:
86
115
  forbidden:
116
+ # pattern: literal substring — no regex
87
117
  - pattern: "console.log("
88
- in: ["src/lib/**"]
118
+ in: ["src/lib/**"] # string OR array; supports ! negation
89
119
  message: "Use the logger — console.log leaks into the agent event stream"
120
+ severity: error # optional — default error; use warn to record without blocking
121
+
122
+ # jsx-element: forbid raw HTML elements outside the design system
123
+ - jsx-element: ["button", "input", "label"]
124
+ in: ["src/app/**/*.tsx", "src/components/**/*.tsx", "!src/components/ui/**"]
125
+ message: "Use the design-system primitives in @/components/ui/* instead of raw HTML elements"
90
126
  ```
91
127
 
128
+ Required: `in` + `message`, plus one of `pattern` / `jsx-element` (not both in the same stanza).
129
+
130
+ `jsx-element` matches intrinsic element names on the AST (opening and self-closing tags), so it is robust to whitespace, attributes, and naming collisions like `<buttonGroup>` — unlike a literal `pattern: "<button"` scan. It works on `.tsx`/`.jsx` files in both the TS and Rust engines.
131
+
92
132
  ## Pitfalls
93
133
 
94
134
  - `pattern` in `singleton` and `forbidden` is a **literal string** — will not catch `process.env["KEY"]` (bracket notation). Grep for both forms if both are possible.
135
+ - `jsx-element` matches **intrinsic** (lowercase HTML) tags only — `button`, `input`, `label`. It does not match custom React components like `<Button>`; to restrict those, use `arch.imports` against the component's module instead.
136
+ - A `forbidden`/`singleton` stanza takes either `pattern` or `jsx-element`, never both — split into two stanzas if you need both.
95
137
  - `only` in `singleton` is relative to the project root — use forward slashes on all platforms.
96
138
  - `severity: warn` records the violation but does not block the session. Use `error` (the default) to block.
97
139
  - Path aliases (`@/*`) resolve via `tsconfig.json` `compilerOptions.paths`, including `extends` chains.
@@ -19,16 +19,12 @@ class Klint < Formula
19
19
  version "${version}"
20
20
  license "MIT"
21
21
 
22
- on_macos do
23
- on_arm do
24
- url "https://github.com/konvert7/klint/releases/download/native-v${version}/klint-${version}-darwin-arm64.tar.gz"
25
- sha256 "${options.darwinArm64Sha}"
26
- end
27
-
28
- on_intel do
29
- url "https://github.com/konvert7/klint/releases/download/native-v${version}/klint-${version}-darwin-x64.tar.gz"
30
- sha256 "${options.darwinX64Sha}"
31
- end
22
+ if Hardware::CPU.arm?
23
+ url "https://github.com/konvert7/klint/releases/download/native-v${version}/klint-${version}-darwin-arm64.tar.gz"
24
+ sha256 "${options.darwinArm64Sha}"
25
+ else
26
+ url "https://github.com/konvert7/klint/releases/download/native-v${version}/klint-${version}-darwin-x64.tar.gz"
27
+ sha256 "${options.darwinX64Sha}"
32
28
  end
33
29
 
34
30
  def install