@pathscale/rsbuild-plugin-ui-css-purge 0.9.5 → 0.9.6

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
@@ -1,145 +1,145 @@
1
- # @pathscale/rsbuild-plugin-ui-css-purge
2
-
3
- Database-first CSS purge for `@pathscale/ui` consumers. It scans consumer JSX with SWC, cross-references a versioned component purge database, and removes only selectors whose ownership and unused state are known.
4
-
5
- Runs as a postbuild step under Bun.
6
-
7
- ## How It Works
8
-
9
- The purge operates in two phases across two repositories.
10
-
11
- **Lib side (`@pathscale/ui`):** Components ship `*.classes.ts` files that describe component-owned classes by slot and prop. The manifest generator also scans colocated component CSS for selectors, data/aria attributes, CSS variable references, keyframes, and component dependencies. It writes a versioned `purge-manifest.json` database:
12
-
13
- ```ts
14
- interface PurgeDatabaseV2 {
15
- version: 2;
16
- components: Record<string, ComponentPurgeRecord>;
17
- shared: {
18
- selectors: { selector: string; components: string[] }[];
19
- cssVars: Record<string, { declaredBy: string[]; referencedBy: string[] }>;
20
- keyframes: Record<string, { declaredBy: string[]; referencedBy: string[] }>;
21
- };
22
- }
23
- ```
24
-
25
- **Consumer side:** After `rsbuild build`, the CLI scans source files for canonical `@pathscale/ui` usage, including aliases, deep imports, namespace imports, compound JSX such as `Modal.Root`, re-exports, spreads, and dynamic props. It builds usage facts and applies the database conservatively.
26
-
27
- ## Purge Rules
28
-
29
- | Rule | Behavior |
30
- | --- | --- |
31
- | Unused known component | Selectors owned only by that component can be removed. |
32
- | Used component, unused prop variant | Selectors requiring that known unused class can be removed. |
33
- | Runtime data/aria state | Kept when the owning used component selector is kept. |
34
- | Unknown ownership | Kept by default. |
35
- | Theme, reset, app selectors | Kept unless they are fully known unused component selectors. |
36
- | CSS vars and keyframes | Removed only after selector purge proves they are unreferenced. |
37
-
38
- The selector walk uses PostCSS. Lightning CSS is used for final minification.
39
-
40
- ## Installation
41
-
42
- ```bash
43
- bun add -d @pathscale/rsbuild-plugin-ui-css-purge
44
- ```
45
-
46
- ## Usage
47
-
48
- ### Consumer Project
49
-
50
- Add the postbuild purge after `rsbuild build`:
51
-
52
- ```json
53
- {
54
- "scripts": {
55
- "build": "rsbuild build && bunx rsbuild-plugin-ui-css-purge --dist dist --src src --manifest node_modules/@pathscale/ui/dist/purge-manifest.json"
56
- }
57
- }
58
- ```
59
-
60
- Options:
61
-
62
- | Flag | Default | Description |
63
- | --- | --- | --- |
64
- | `--manifest` | required | Path to `purge-manifest.json`. |
65
- | `--dist` | `./dist` | Directory containing built CSS files. |
66
- | `--src` | `./src` | Consumer source directory to scan for JSX usage. |
67
-
68
- ### Lib-Side Manifest Generation
69
-
70
- Run from `@pathscale/ui` as a build step:
71
-
72
- ```json
73
- {
74
- "scripts": {
75
- "prebuild": "bunx generate-manifest src/components --out dist/purge-manifest.json"
76
- }
77
- }
78
- ```
79
-
80
- This scans all `*.classes.ts` files and colocated component CSS files.
81
-
82
- ## The `*.classes.ts` Convention
83
-
84
- Every component should export a `CLASSES` object that names all component-owned classes. Tailwind utilities are filtered out so the manifest tracks ownership of durable component selectors, not generic utility classes.
85
-
86
- ```ts
87
- // button.classes.ts
88
- export const CLASSES = {
89
- base: "button inline-flex items-center",
90
- variant: {
91
- primary: "button--primary",
92
- secondary: "button--secondary",
93
- },
94
- size: {
95
- sm: "button--sm",
96
- md: "button--md",
97
- },
98
- flag: {
99
- disabled: "button--disabled",
100
- },
101
- attrs: {
102
- open: { "data-open": "true" },
103
- },
104
- } as const;
105
- ```
106
-
107
- Compound components use a nested shape:
108
-
109
- ```ts
110
- export const CLASSES = {
111
- Root: { base: "modal" },
112
- Panel: { base: "modal__panel" },
113
- } as const;
114
- ```
115
-
116
- ## Programmatic API
117
-
118
- ```ts
119
- import {
120
- buildSafelists,
121
- purgeCssWithDatabase,
122
- scanConsumerSource,
123
- } from "@pathscale/rsbuild-plugin-ui-css-purge";
124
-
125
- const usages = await scanConsumerSource("/path/to/consumer/src");
126
- const manifest = JSON.parse(await Bun.file("purge-manifest.json").text());
127
- const safelists = buildSafelists(usages, manifest);
128
- const result = purgeCssWithDatabase(css, manifest, safelists);
129
-
130
- console.log(result.report);
131
- ```
132
-
133
- ## Development
134
-
135
- ```bash
136
- bun install
137
- bun run test
138
- bun run build
139
- bun run lint
140
- bun run format
141
- ```
142
-
143
- ## License
144
-
145
- MIT
1
+ # @pathscale/rsbuild-plugin-ui-css-purge
2
+
3
+ Database-first CSS purge for `@pathscale/ui` consumers. It scans consumer JSX with SWC, cross-references a versioned component purge database, and removes only selectors whose ownership and unused state are known.
4
+
5
+ Runs as a postbuild step under Bun.
6
+
7
+ ## How It Works
8
+
9
+ The purge operates in two phases across two repositories.
10
+
11
+ **Lib side (`@pathscale/ui`):** Components ship `*.classes.ts` files that describe component-owned classes by slot and prop. The manifest generator also scans colocated component CSS for selectors, data/aria attributes, CSS variable references, keyframes, and component dependencies. It writes a versioned `purge-manifest.json` database:
12
+
13
+ ```ts
14
+ interface PurgeDatabaseV2 {
15
+ version: 2;
16
+ components: Record<string, ComponentPurgeRecord>;
17
+ shared: {
18
+ selectors: { selector: string; components: string[] }[];
19
+ cssVars: Record<string, { declaredBy: string[]; referencedBy: string[] }>;
20
+ keyframes: Record<string, { declaredBy: string[]; referencedBy: string[] }>;
21
+ };
22
+ }
23
+ ```
24
+
25
+ **Consumer side:** After `rsbuild build`, the CLI scans source files for canonical `@pathscale/ui` usage, including aliases, deep imports, namespace imports, compound JSX such as `Modal.Root`, re-exports, spreads, and dynamic props. It builds usage facts and applies the database conservatively.
26
+
27
+ ## Purge Rules
28
+
29
+ | Rule | Behavior |
30
+ | --- | --- |
31
+ | Unused known component | Selectors owned only by that component can be removed. |
32
+ | Used component, unused prop variant | Selectors requiring that known unused class can be removed. |
33
+ | Runtime data/aria state | Kept when the owning used component selector is kept. |
34
+ | Unknown ownership | Kept by default. |
35
+ | Theme, reset, app selectors | Kept unless they are fully known unused component selectors. |
36
+ | CSS vars and keyframes | Removed only after selector purge proves they are unreferenced. |
37
+
38
+ The selector walk uses PostCSS. Lightning CSS is used for final minification.
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ bun add -d @pathscale/rsbuild-plugin-ui-css-purge
44
+ ```
45
+
46
+ ## Usage
47
+
48
+ ### Consumer Project
49
+
50
+ Add the postbuild purge after `rsbuild build`:
51
+
52
+ ```json
53
+ {
54
+ "scripts": {
55
+ "build": "rsbuild build && bunx rsbuild-plugin-ui-css-purge --dist dist --src src --manifest node_modules/@pathscale/ui/dist/purge-manifest.json"
56
+ }
57
+ }
58
+ ```
59
+
60
+ Options:
61
+
62
+ | Flag | Default | Description |
63
+ | --- | --- | --- |
64
+ | `--manifest` | required | Path to `purge-manifest.json`. |
65
+ | `--dist` | `./dist` | Directory containing built CSS files. |
66
+ | `--src` | `./src` | Consumer source directory to scan for JSX usage. |
67
+
68
+ ### Lib-Side Manifest Generation
69
+
70
+ Run from `@pathscale/ui` as a build step:
71
+
72
+ ```json
73
+ {
74
+ "scripts": {
75
+ "prebuild": "bunx generate-manifest src/components --out dist/purge-manifest.json"
76
+ }
77
+ }
78
+ ```
79
+
80
+ This scans all `*.classes.ts` files and colocated component CSS files.
81
+
82
+ ## The `*.classes.ts` Convention
83
+
84
+ Every component should export a `CLASSES` object that names all component-owned classes. Tailwind utilities are filtered out so the manifest tracks ownership of durable component selectors, not generic utility classes.
85
+
86
+ ```ts
87
+ // button.classes.ts
88
+ export const CLASSES = {
89
+ base: "button inline-flex items-center",
90
+ variant: {
91
+ primary: "button--primary",
92
+ secondary: "button--secondary",
93
+ },
94
+ size: {
95
+ sm: "button--sm",
96
+ md: "button--md",
97
+ },
98
+ flag: {
99
+ disabled: "button--disabled",
100
+ },
101
+ attrs: {
102
+ open: { "data-open": "true" },
103
+ },
104
+ } as const;
105
+ ```
106
+
107
+ Compound components use a nested shape:
108
+
109
+ ```ts
110
+ export const CLASSES = {
111
+ Root: { base: "modal" },
112
+ Panel: { base: "modal__panel" },
113
+ } as const;
114
+ ```
115
+
116
+ ## Programmatic API
117
+
118
+ ```ts
119
+ import {
120
+ buildSafelists,
121
+ purgeCssWithDatabase,
122
+ scanConsumerSource,
123
+ } from "@pathscale/rsbuild-plugin-ui-css-purge";
124
+
125
+ const usages = await scanConsumerSource("/path/to/consumer/src");
126
+ const manifest = JSON.parse(await Bun.file("purge-manifest.json").text());
127
+ const safelists = buildSafelists(usages, manifest);
128
+ const result = purgeCssWithDatabase(css, manifest, safelists);
129
+
130
+ console.log(result.report);
131
+ ```
132
+
133
+ ## Development
134
+
135
+ ```bash
136
+ bun install
137
+ bun run test
138
+ bun run build
139
+ bun run lint
140
+ bun run format
141
+ ```
142
+
143
+ ## License
144
+
145
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { cleanUnusedVars, cleanUnusedVarsWithReport, normalizePurgeDatabase, purgeCssWithDatabase, } from "./postbuild-purge";
2
- export { extractUIImports, extractJSXUsages, buildSafelists, scanConsumerSource, } from "./scan-consumer";
3
2
  export type { ComponentManifest, ComponentPurgeRecord, PropUsage, PurgeDatabaseV2, PurgeManifest, Safelists, } from "./scan-consumer";
3
+ export { buildSafelists, extractJSXUsages, extractUIImports, scanConsumerSource, } from "./scan-consumer";