stylelint-plugin-rhythmguard 1.4.2 → 1.6.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/CHANGELOG.md CHANGED
@@ -6,6 +6,14 @@ The format follows Keep a Changelog principles and semantic versioning.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.6.0] - 2026-05-19
10
+
11
+ ### Added
12
+
13
+ - `rhythmguard audit` now reports design-system drift across CSS declarations and Tailwind arbitrary spacing class strings.
14
+ - Added `--format markdown` / `--markdown` audit output for PR-ready design-system health reports.
15
+ - Audit JSON now includes format version, CSS findings, Tailwind class-string findings, scan counts, top affected files, and summary totals while preserving existing top-level count fields.
16
+
9
17
  ## [1.4.2] - 2026-02-21
10
18
 
11
19
  ### Changed
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/petrilahdelma/stylelint-plugin-rhythmguard/main/assets/rhythmguard-banner.svg" width="100%" alt="Rhythmguard banner in Geist Pixel" />
2
+ <img src="https://raw.githubusercontent.com/petrilahdelma/stylelint-plugin-rhythmguard/main/assets/rhythmguard-banner.svg?v=3" width="100%" alt="Rhythmguard banner showing spacing scale ruler and lint output" />
3
3
  </p>
4
4
 
5
5
  # stylelint-plugin-rhythmguard
6
6
 
7
- High-precision spacing governance for CSS and design systems.
7
+ Token governance for CSS and Tailwind. Enforce spacing scales, require design tokens, and catch arbitrary values before they ship.
8
8
 
9
9
  [![CI](https://img.shields.io/github/actions/workflow/status/petrilahdelma/stylelint-plugin-rhythmguard/ci.yml?branch=main&label=ci)](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/actions/workflows/ci.yml)
10
10
  [![npm version](https://img.shields.io/npm/v/stylelint-plugin-rhythmguard.svg)](https://www.npmjs.com/package/stylelint-plugin-rhythmguard)
@@ -12,25 +12,48 @@ High-precision spacing governance for CSS and design systems.
12
12
  [![License: MIT](https://img.shields.io/badge/license-MIT-white.svg)](./LICENSE)
13
13
  [![Node](https://img.shields.io/badge/node-%3E%3D18.18-black.svg)](https://nodejs.org/)
14
14
 
15
- `stylelint-plugin-rhythmguard` enforces scale and token discipline across spacing, radius, typography, size, and translate motion offsets.
15
+ Rhythmguard enforces scale and token discipline across spacing, radius, typography, size, and motion offsets — in CSS declarations and Tailwind class strings.
16
16
 
17
- ## Demo
17
+ Built for teams that want:
18
18
 
19
- <p align="center">
20
- <a href="https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/assets/rhythmguard-campaign-60s.webm">
21
- <img src="https://raw.githubusercontent.com/petrilahdelma/stylelint-plugin-rhythmguard/main/assets/rhythmguard-campaign-60s.gif" width="100%" alt="Rhythmguard 60-second demo" />
22
- </a>
23
- </p>
19
+ - zero random spacing values in production
20
+ - token-first workflows with autofix migration
21
+ - Tailwind arbitrary value governance (`p-[13px]` `p-[12px]`)
22
+ - consistent layout rhythm across components and pages
24
23
 
25
- I built Rhythmguard after 20 years of watching teams ignore spacing scales and ship arbitrary pixel values everywhere.
24
+ ## Quick Start: Next.js + Tailwind
26
25
 
27
- It is built for teams that want:
26
+ ```bash
27
+ npm install --save-dev stylelint stylelint-plugin-rhythmguard
28
+ ```
29
+
30
+ **.stylelintrc.json:**
31
+
32
+ ```json
33
+ {
34
+ "extends": ["stylelint-plugin-rhythmguard/configs/tailwind"]
35
+ }
36
+ ```
37
+
38
+ **eslint.config.js** (for Tailwind class-string governance):
39
+
40
+ ```js
41
+ import rhythmguard from 'stylelint-plugin-rhythmguard/eslint';
42
+
43
+ export default [
44
+ {
45
+ plugins: { 'rhythmguard-tailwind': rhythmguard },
46
+ rules: {
47
+ 'rhythmguard-tailwind/tailwind-class-use-scale': [
48
+ 'error',
49
+ { scale: [0, 4, 8, 12, 16, 24, 32] }
50
+ ],
51
+ },
52
+ },
53
+ ];
54
+ ```
28
55
 
29
- - zero random spacing values in production CSS
30
- - consistent numeric scales for radius, typography, and sizing primitives
31
- - token-first spacing workflows
32
- - predictable autofix behavior for large migrations
33
- - consistent layout rhythm across web surfaces
56
+ This gives you spacing governance in both CSS files and JSX/TSX templates.
34
57
 
35
58
  ## Rule Matrix
36
59
 
@@ -44,6 +67,44 @@ It is built for teams that want:
44
67
  | `rhythmguard/prefer-token` | Enforces token usage over raw spacing literals | Yes, with `tokenMap` |
45
68
  | `rhythmguard/no-offscale-transform` | Enforces scale-aligned `translate*` motion offsets | Yes, nearest safe value |
46
69
 
70
+ ## Demo
71
+
72
+ <p align="center">
73
+ <a href="https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/assets/rhythmguard-campaign-60s.webm">
74
+ <img src="https://raw.githubusercontent.com/petrilahdelma/stylelint-plugin-rhythmguard/main/assets/rhythmguard-campaign-60s.gif" width="100%" alt="Rhythmguard 60-second demo" />
75
+ </a>
76
+ </p>
77
+
78
+ I built Rhythmguard after 20 years of watching teams ignore spacing scales and ship arbitrary pixel values everywhere.
79
+
80
+ ## Try It in Your Browser
81
+
82
+ **[petrilahdelma.github.io/stylelint-plugin-rhythmguard](https://petrilahdelma.github.io/stylelint-plugin-rhythmguard/)** — paste CSS, see violations and token opportunities live. No install, no config.
83
+
84
+ ## Audit Before You Enforce
85
+
86
+ Use the audit CLI to create a design-system drift report before turning rules into hard CI gates:
87
+
88
+ ```bash
89
+ npx rhythmguard audit ./src
90
+ npx rhythmguard audit ./src --format markdown
91
+ npx rhythmguard audit ./src --json
92
+ ```
93
+
94
+ The report covers authored CSS declarations and Tailwind arbitrary spacing values in common template/source files. Markdown output is PR-ready for UX developers, UX designers, and design-system owners:
95
+
96
+ ```md
97
+ # Rhythmguard Design-System Audit
98
+
99
+ | Metric | Value |
100
+ | --- | ---: |
101
+ | CSS files scanned | 47 |
102
+ | Template files scanned | 83 |
103
+ | Files with issues | 12 |
104
+ | Total findings | 52 |
105
+ | Scale cleanliness | 91% |
106
+ ```
107
+
47
108
  ## Installation
48
109
 
49
110
  ```bash
@@ -66,32 +127,32 @@ npm install --save-dev stylelint-plugin-rhythmguard
66
127
 
67
128
  ## Quick Start
68
129
 
69
- ### Recommended config
130
+ ### Tailwind config
70
131
 
71
132
  ```json
72
133
  {
73
- "extends": ["stylelint-plugin-rhythmguard/configs/recommended"]
134
+ "extends": ["stylelint-plugin-rhythmguard/configs/tailwind"]
74
135
  }
75
136
  ```
76
137
 
77
- ### Strict config
138
+ ### Recommended config
78
139
 
79
140
  ```json
80
141
  {
81
- "extends": ["stylelint-plugin-rhythmguard/configs/strict"]
142
+ "extends": ["stylelint-plugin-rhythmguard/configs/recommended"]
82
143
  }
83
144
  ```
84
145
 
85
- `strict` intentionally delegates transform translation enforcement to `rhythmguard/no-offscale-transform` to reduce overlapping warnings from `use-scale`.
86
-
87
- ### Tailwind config
146
+ ### Strict config
88
147
 
89
148
  ```json
90
149
  {
91
- "extends": ["stylelint-plugin-rhythmguard/configs/tailwind"]
150
+ "extends": ["stylelint-plugin-rhythmguard/configs/strict"]
92
151
  }
93
152
  ```
94
153
 
154
+ `strict` intentionally delegates transform translation enforcement to `rhythmguard/no-offscale-transform` to reduce overlapping warnings from `use-scale`.
155
+
95
156
  ### Expanded config
96
157
 
97
158
  ```json
@@ -122,18 +183,32 @@ npm install --save-dev stylelint-plugin-rhythmguard
122
183
 
123
184
  `migration` keeps on-scale numeric values temporarily while auto-building token mappings from CSS custom properties and optional Tailwind spacing config.
124
185
 
186
+ ### React / Next.js + Tailwind config
187
+
188
+ ```json
189
+ {
190
+ "extends": ["stylelint-plugin-rhythmguard/configs/react-tailwind"]
191
+ }
192
+ ```
193
+
194
+ `react-tailwind` extends the tailwind config with CSS Modules overrides (spacing + radius enforcement) and ignores Next.js build directories.
195
+
125
196
  Stable shared config entry points:
126
197
 
127
198
  - `stylelint-plugin-rhythmguard/configs/recommended`
128
199
  - `stylelint-plugin-rhythmguard/configs/strict`
129
200
  - `stylelint-plugin-rhythmguard/configs/tailwind`
201
+ - `stylelint-plugin-rhythmguard/configs/react-tailwind`
130
202
  - `stylelint-plugin-rhythmguard/configs/expanded`
131
203
  - `stylelint-plugin-rhythmguard/configs/logical`
132
204
  - `stylelint-plugin-rhythmguard/configs/migration`
133
205
 
206
+ Framework-specific setup for Vue, Lit, Astro, and SvelteKit: [`docs/FRAMEWORKS.md`](https://github.com/PetriLahdelma/stylelint-plugin-rhythmguard/blob/main/docs/FRAMEWORKS.md)
207
+
134
208
  ## Comparison and Migration Recipes
135
209
 
136
210
  - Side-by-side tool fit guide with migration snippets: [`docs/COMPARISON.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/COMPARISON.md)
211
+ - Audit 2.0 validation and roadmap: [`docs/AUDIT_2_VALIDATION.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/AUDIT_2_VALIDATION.md)
137
212
  - Real-world before/after excerpts from public repos: [`docs/ADOPTION_DIFFS.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/ADOPTION_DIFFS.md)
138
213
  - Distribution submissions to Stylelint discovery surfaces: [`docs/DISTRIBUTION.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/DISTRIBUTION.md)
139
214
 
@@ -409,7 +484,7 @@ Options:
409
484
  | `mathFunctionArguments` | `Record<mathFn, number[]>` | `{}` | Restricts linting to specific 1-based argument indexes per math function |
410
485
  | `ignoreMathFunctionArguments` | `Record<mathFn, number[]>` | `{}` | Excludes specific 1-based argument indexes per math function |
411
486
  | `tokenMap` | `Record<string,string>` | `{}` | Enables autofix from raw value to token |
412
- | `tokenMapFile` | `string` | `null` | JSON file path to merge additional token mappings |
487
+ | `tokenMapFile` | `string` | `null` | JSON file path to merge additional token mappings (supports flat, Style Dictionary, and W3C DTCG formats) |
413
488
  | `tokenMapFromCssCustomProperties` | `boolean` | `false` | Auto-builds mappings from matching custom property declarations in the same stylesheet |
414
489
  | `tokenMapFromTailwindSpacing` | `boolean` | `false` | Auto-builds mappings from `theme.spacing` and `theme.extend.spacing` in Tailwind config |
415
490
  | `tailwindConfigPath` | `string` | `null` | Path to Tailwind config used by `tokenMapFromTailwindSpacing` (`.js`, `.cjs`, `.mjs`) |
@@ -450,13 +525,19 @@ Rhythmguard works well in Tailwind projects, but it enforces what Stylelint can
450
525
  - CSS Modules (for example `*.module.css`)
451
526
  - declarations inside `@layer` blocks
452
527
 
453
- ### What Rhythmguard does not cover
528
+ ### Tailwind v4 @theme tokens
529
+
530
+ The `tailwind` config preset automatically extracts spacing tokens from Tailwind v4 `@theme` blocks and uses them for `prefer-token` enforcement. Raw values like `padding: 16px` are autofixed to `padding: var(--spacing-4)`.
531
+
532
+ See [`docs/TAILWIND.md`](https://github.com/PetriLahdelma/stylelint-plugin-rhythmguard/blob/main/docs/TAILWIND.md) for full setup.
533
+
534
+ ### What the Stylelint layer does not cover
454
535
 
455
536
  - Tailwind class strings in templates/JSX/TSX, for example:
456
537
  - `class="p-4 gap-2"`
457
538
  - `class="p-[13px] translate-y-[18px]"`
458
539
 
459
- Those are not Stylelint declaration nodes, so they are outside Stylelint rule scope.
540
+ Those are not Stylelint declaration nodes, so they are outside Stylelint rule scope. Use the ESLint companion rule below for scale-aware class-string enforcement.
460
541
 
461
542
  ### Companion ESLint layer for class strings
462
543
 
@@ -480,6 +561,18 @@ export default [
480
561
 
481
562
  This rule targets arbitrary spacing utilities such as `p-[13px]`, `gap-[18px]`, `translate-x-[10px]`, and autofixes to the nearest configured scale value.
482
563
 
564
+ #### Supported patterns
565
+
566
+ The rule checks every string literal in your code, so it works automatically with common utility functions:
567
+
568
+ - `cn("p-[13px]")` / `cn("p-[13px]", condition && "m-[7px]")`
569
+ - `clsx("p-[13px]", "gap-[18px]")`
570
+ - `twMerge("p-[13px]", otherClasses)`
571
+ - `cva("base", { variants: { size: { sm: "p-[5px]" } } })`
572
+ - `<div className={cn("p-[13px]")} />`
573
+
574
+ No extra config needed — if the string contains an arbitrary spacing value, it gets caught and autofixed.
575
+
483
576
  ### Recommended stack for full Tailwind enforcement
484
577
 
485
578
  Use both layers:
@@ -498,7 +591,7 @@ Suggested setup:
498
591
  Then pair with:
499
592
 
500
593
  - `stylelint-plugin-rhythmguard/eslint` for arbitrary spacing class-string scale enforcement.
501
- - `eslint-plugin-tailwindcss` for broader class-string linting and conventions.
594
+ - `eslint-plugin-tailwindcss` for broader class-string linting and conventions. If your policy is to ban every arbitrary value, enable its `tailwindcss/no-arbitrary-value` rule; use Rhythmguard when you want spacing-specific scale checks and nearest-value fixes.
502
595
  - `prettier-plugin-tailwindcss` for deterministic class ordering.
503
596
 
504
597
  Detailed setup reference: [`docs/TAILWIND.md`](https://github.com/PetriLahdelma/stylelint-plugin-rhythmguard/blob/main/docs/TAILWIND.md).
@@ -521,6 +614,35 @@ console.log(rhythmguard.presets.scales['rhythmic-4']);
521
614
  console.log(Object.keys(rhythmguard.eslint.rules));
522
615
  ```
523
616
 
617
+ ## Token File Formats
618
+
619
+ The `tokenMapFile` option supports multiple JSON formats:
620
+
621
+ **Flat token-to-value:**
622
+
623
+ ```json
624
+ { "--spacing-4": "16px", "--spacing-3": "12px" }
625
+ ```
626
+
627
+ **Style Dictionary:**
628
+
629
+ ```json
630
+ { "--spacing-4": { "value": "16px" } }
631
+ ```
632
+
633
+ **W3C DTCG (Design Token Community Group):**
634
+
635
+ ```json
636
+ {
637
+ "spacing": {
638
+ "4": { "$value": "16px", "$type": "dimension" },
639
+ "2": { "$value": "8px", "$type": "dimension" }
640
+ }
641
+ }
642
+ ```
643
+
644
+ Nested DTCG groups are walked recursively. The key path becomes the CSS variable name: `spacing.4` → `var(--spacing-4)`. Non-length values (colors, fonts) are ignored automatically.
645
+
524
646
  ## Autofix Philosophy
525
647
 
526
648
  Rhythmguard only applies deterministic fixes:
@@ -565,8 +687,6 @@ Detailed methodology and custom args are documented in [`docs/BENCHMARKING.md`](
565
687
  ## Article
566
688
 
567
689
  - Dev.to: [Enforcing your spacing standards with Rhythmguard](https://dev.to/petrilahdelma/enforcing-your-spacing-standards-with-rhythmguard-a-custom-stylelint-plugin-1ojj)
568
- - Original article update note (Feb 21, 2026): [`docs/DEVTO_ORIGINAL_UPDATE_NOTE_2026-02-21.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/DEVTO_ORIGINAL_UPDATE_NOTE_2026-02-21.md)
569
- - Continuation draft (ready to publish): [`docs/DEVTO_CONTINUATION_2026-02-21.md`](https://github.com/petrilahdelma/stylelint-plugin-rhythmguard/blob/main/docs/DEVTO_CONTINUATION_2026-02-21.md)
570
690
 
571
691
  ## Used by and Community Examples
572
692
 
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "stylelint-plugin-rhythmguard",
3
- "version": "1.4.2",
4
- "description": "Stylelint plugin for spacing scale, token enforcement, and Tailwind class-string governance",
3
+ "version": "1.6.0",
4
+ "description": "Token governance for CSS and Tailwind — enforce spacing scales, require design tokens, catch arbitrary values",
5
+ "bin": {
6
+ "rhythmguard": "src/cli/index.js"
7
+ },
5
8
  "keywords": [
6
9
  "stylelint",
7
10
  "stylelint-plugin",
@@ -46,6 +49,10 @@
46
49
  "require": "./src/configs/migration.js",
47
50
  "import": "./src/configs/migration.mjs"
48
51
  },
52
+ "./configs/react-tailwind": {
53
+ "require": "./src/configs/react-tailwind.js",
54
+ "import": "./src/configs/react-tailwind.mjs"
55
+ },
49
56
  "./presets": {
50
57
  "require": "./src/presets/index.js",
51
58
  "import": "./src/presets/index.mjs"
@@ -92,7 +99,7 @@
92
99
  },
93
100
  "repository": {
94
101
  "type": "git",
95
- "url": "git+https://github.com/petrilahdelma/stylelint-plugin-rhythmguard.git"
102
+ "url": "https://github.com/PetriLahdelma/stylelint-plugin-rhythmguard"
96
103
  },
97
104
  "homepage": "https://github.com/petrilahdelma/stylelint-plugin-rhythmguard#readme",
98
105
  "bugs": {