@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 +145 -145
- package/dist/index.d.ts +1 -1
- package/dist/index.js +18 -32
- package/dist/postbuild-purge.d.ts +1 -1
- package/dist/postbuild-purge.js +18 -32
- package/dist/scan-consumer.d.ts +2 -2
- package/package.json +15 -11
- package/src/generate-manifest.ts +239 -37
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";
|