@rolandjlevy/css-ghost 1.2.0 → 1.3.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 +14 -0
- package/README.md +34 -0
- package/index.d.ts +108 -0
- package/package.json +21 -4
- package/src/index.js +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to `@rolandjlevy/css-ghost` are documented here.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## [1.3.0] — 2026-10-17
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Programmatic API** (`src/index.js`) — `scan()` and `generateReport()` are now exposed as the package's public entry point via the `exports` field. Other tools and build plugins can now depend on css-ghost directly.
|
|
12
|
+
- **TypeScript types** (`index.d.ts`) — hand-authored declarations for `ScanResult`, `OrphanedItem`, `GhostTrail`, and `ReportTotals`; no `@types/` package needed.
|
|
13
|
+
- **GitHub Actions CI** (`.github/workflows/ci.yml`) — runs the smoke test suite on Node 18, 20 and 22 on every push and pull request.
|
|
14
|
+
- **Smoke test runner** (`test/run.js`) — `npm test` now runs `scan()` against all 13 fixture directories and asserts result shapes; 13/13 pass.
|
|
15
|
+
- **README badges** — npm version, monthly downloads, CI status, Node version and licence badge at the top of the README.
|
|
16
|
+
- **Programmatic API docs** — new README section with install instructions, usage example, and TypeScript note.
|
|
17
|
+
- **Keywords expanded** — added `vite`, `webpack`, `postcss`, `css-variables`, `vanilla-extract`, `orphaned-selectors` for better npm discovery.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
7
21
|
## [1.2.0] — 2026-10-17
|
|
8
22
|
|
|
9
23
|
### Fixed
|
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# 👻 css-ghost
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@rolandjlevy/css-ghost)
|
|
4
|
+
[](https://www.npmjs.com/package/@rolandjlevy/css-ghost)
|
|
5
|
+
[](https://github.com/rolandjlevy/css-ghost/actions/workflows/ci.yml)
|
|
6
|
+
[](https://nodejs.org/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
3
9
|
Find and remove unused CSS selectors and orphaned CSS custom properties — selectors defined in your style files but never referenced in your components, across React, Vue, Svelte, SCSS, and CSS Modules
|
|
4
10
|
|
|
5
11
|
## What it does
|
|
@@ -158,6 +164,34 @@ css-ghost ./src --ai # with AI summary
|
|
|
158
164
|
css-ghost ./src --output ./reports/audit.md
|
|
159
165
|
```
|
|
160
166
|
|
|
167
|
+
## Programmatic API
|
|
168
|
+
|
|
169
|
+
Use css-ghost as a library inside your own build tools, Vite plugins, or scripts:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npm install @rolandjlevy/css-ghost
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
import { scan, generateReport } from '@rolandjlevy/css-ghost';
|
|
177
|
+
import { resolve } from 'path';
|
|
178
|
+
|
|
179
|
+
// Scan one or more directories
|
|
180
|
+
const results = scan([resolve(process.cwd(), 'src')]);
|
|
181
|
+
|
|
182
|
+
// Optional: write a Markdown report and get the orphan totals
|
|
183
|
+
const { totalAllOrphans } = generateReport(results, 'orphan-report.md');
|
|
184
|
+
|
|
185
|
+
// Use in CI: fail the build if any orphans are found
|
|
186
|
+
if (totalAllOrphans > 0) process.exit(1);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
TypeScript types are included — no `@types/` package needed.
|
|
190
|
+
|
|
191
|
+
**`scan(dirs: string[])`** — returns a `ScanResult[]` array, one entry per style file. Each entry includes `filePath`, `orphaned` selectors, `orphanedVars` (CSS custom properties), `hasDynamic` flag, and more.
|
|
192
|
+
|
|
193
|
+
**`generateReport(results, outputPath?, aiSummary?)`** — writes a Markdown report and prints a colour summary to the terminal. Returns `{ totalOrphaned, totalVarsOrphaned, totalAllOrphans }`.
|
|
194
|
+
|
|
161
195
|
## Using with npm scripts
|
|
162
196
|
|
|
163
197
|
```json
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript declarations for @rolandjlevy/css-ghost
|
|
3
|
+
* Import from the package root to get `scan` and `generateReport`.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** A single orphaned class selector or CSS variable. */
|
|
7
|
+
export interface OrphanedItem {
|
|
8
|
+
/** The selector name (without leading `.`) or CSS variable name (with `--` prefix). */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Line number in the source style file. */
|
|
11
|
+
line: number;
|
|
12
|
+
/** The raw CSS rule text, if available. */
|
|
13
|
+
rule?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Git blame info for a single orphaned item (--ghost-trail mode). */
|
|
17
|
+
export interface GhostTrail {
|
|
18
|
+
/** Short commit hash. */
|
|
19
|
+
hash: string;
|
|
20
|
+
/** Commit author name. */
|
|
21
|
+
author: string;
|
|
22
|
+
/** Human-readable date/time of the commit. */
|
|
23
|
+
when: string;
|
|
24
|
+
/** Commit subject line. */
|
|
25
|
+
subject: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Per-file result returned by `scan()`.
|
|
30
|
+
* One entry per style file processed.
|
|
31
|
+
*/
|
|
32
|
+
export interface ScanResult {
|
|
33
|
+
/** Absolute path to the style file. */
|
|
34
|
+
filePath: string;
|
|
35
|
+
/** Total number of class selectors defined in the file. */
|
|
36
|
+
total: number;
|
|
37
|
+
/** Class selectors that are defined but never referenced in component files. */
|
|
38
|
+
orphaned: OrphanedItem[];
|
|
39
|
+
/** CSS custom properties (`--foo`) defined but never used via `var()`. */
|
|
40
|
+
orphanedVars: OrphanedItem[];
|
|
41
|
+
/** Total number of CSS custom properties defined in the file. */
|
|
42
|
+
totalVars: number;
|
|
43
|
+
/**
|
|
44
|
+
* `true` when the co-located component files use dynamic class access
|
|
45
|
+
* (`styles[variable]`, template literals) — results may be incomplete.
|
|
46
|
+
*/
|
|
47
|
+
hasDynamic: boolean;
|
|
48
|
+
/** Absolute paths of component files that contain dynamic class references. */
|
|
49
|
+
dynamicFiles: string[];
|
|
50
|
+
/**
|
|
51
|
+
* Ghost-trail git blame data for orphaned selectors, keyed by selector name.
|
|
52
|
+
* Only present when `--ghost-trail` is active or you call the git module directly.
|
|
53
|
+
*/
|
|
54
|
+
trails?: Record<string, GhostTrail>;
|
|
55
|
+
/**
|
|
56
|
+
* Ghost-trail git blame data for orphaned CSS variables, keyed by variable name.
|
|
57
|
+
* Only present when `--ghost-trail` is active or you call the git module directly.
|
|
58
|
+
*/
|
|
59
|
+
varTrails?: Record<string, GhostTrail>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Totals returned by `generateReport()`. Useful for CI / strict-mode checks. */
|
|
63
|
+
export interface ReportTotals {
|
|
64
|
+
/** Number of orphaned class selectors across all scanned files. */
|
|
65
|
+
totalOrphaned: number;
|
|
66
|
+
/** Number of orphaned CSS variables across all scanned files. */
|
|
67
|
+
totalVarsOrphaned: number;
|
|
68
|
+
/** Sum of `totalOrphaned` and `totalVarsOrphaned`. */
|
|
69
|
+
totalAllOrphans: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Scan one or more directories for orphaned CSS selectors and CSS custom properties.
|
|
74
|
+
*
|
|
75
|
+
* @param dirs - Absolute paths to the directories you want to scan.
|
|
76
|
+
* @returns An array of per-file results — one entry per style file found.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* import { scan } from '@rolandjlevy/css-ghost';
|
|
80
|
+
* import { resolve } from 'path';
|
|
81
|
+
*
|
|
82
|
+
* const results = scan([resolve(process.cwd(), 'src')]);
|
|
83
|
+
* const totalOrphans = results.reduce((n, r) => n + r.orphaned.length + r.orphanedVars.length, 0);
|
|
84
|
+
* console.log(`Found ${totalOrphans} orphan(s).`);
|
|
85
|
+
*/
|
|
86
|
+
export function scan(dirs: string[]): ScanResult[];
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Generate a Markdown report file and print a summary to stdout.
|
|
90
|
+
*
|
|
91
|
+
* @param results - Output from `scan()`.
|
|
92
|
+
* @param outputPath - Where to write the `.md` report. Defaults to `'orphan-report.md'`.
|
|
93
|
+
* @param aiSummary - Optional AI-generated summary string to embed in the report.
|
|
94
|
+
* @returns Totals you can use for CI gates or `--strict` mode.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* import { scan, generateReport } from '@rolandjlevy/css-ghost';
|
|
98
|
+
* import { resolve } from 'path';
|
|
99
|
+
*
|
|
100
|
+
* const results = scan([resolve(process.cwd(), 'src')]);
|
|
101
|
+
* const { totalAllOrphans } = generateReport(results, 'orphan-report.md');
|
|
102
|
+
* if (totalAllOrphans > 0) process.exit(1);
|
|
103
|
+
*/
|
|
104
|
+
export function generateReport(
|
|
105
|
+
results: ScanResult[],
|
|
106
|
+
outputPath?: string,
|
|
107
|
+
aiSummary?: string | null
|
|
108
|
+
): ReportTotals;
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rolandjlevy/css-ghost",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Find and remove unused CSS selectors and orphaned CSS custom properties — a CLI linter and auditor for React, Vue, Svelte, SCSS, and CSS Modules",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./src/index.js",
|
|
10
|
+
"types": "./index.d.ts",
|
|
6
11
|
"bin": {
|
|
7
12
|
"css-ghost": "bin/css-ghost.js"
|
|
8
13
|
},
|
|
@@ -12,11 +17,13 @@
|
|
|
12
17
|
"scan:trail": "node bin/css-ghost.js ./test --ghost-trail",
|
|
13
18
|
"delete": "node bin/css-ghost.js ./test --delete",
|
|
14
19
|
"delete:yes": "node bin/css-ghost.js ./test --delete --yes",
|
|
15
|
-
"setup": "node bin/css-ghost.js --setup"
|
|
20
|
+
"setup": "node bin/css-ghost.js --setup",
|
|
21
|
+
"test": "node test/run.js"
|
|
16
22
|
},
|
|
17
23
|
"files": [
|
|
18
24
|
"bin",
|
|
19
25
|
"src",
|
|
26
|
+
"index.d.ts",
|
|
20
27
|
"README.md",
|
|
21
28
|
"CHANGELOG.md",
|
|
22
29
|
"LICENSE"
|
|
@@ -25,6 +32,7 @@
|
|
|
25
32
|
"css",
|
|
26
33
|
"unused",
|
|
27
34
|
"orphan",
|
|
35
|
+
"orphaned-selectors",
|
|
28
36
|
"selectors",
|
|
29
37
|
"dead-code",
|
|
30
38
|
"cleanup",
|
|
@@ -33,20 +41,29 @@
|
|
|
33
41
|
"audit",
|
|
34
42
|
"tree-shaking",
|
|
35
43
|
"custom-properties",
|
|
44
|
+
"css-variables",
|
|
36
45
|
"react",
|
|
37
46
|
"vue",
|
|
38
47
|
"svelte",
|
|
39
48
|
"scss",
|
|
40
49
|
"css-modules",
|
|
41
|
-
"purgecss"
|
|
50
|
+
"purgecss",
|
|
51
|
+
"vite",
|
|
52
|
+
"webpack",
|
|
53
|
+
"postcss",
|
|
54
|
+
"vanilla-extract",
|
|
55
|
+
"style-audit"
|
|
42
56
|
],
|
|
43
57
|
"author": "Roland Levy",
|
|
44
58
|
"license": "MIT",
|
|
45
59
|
"repository": {
|
|
46
60
|
"type": "git",
|
|
47
|
-
"url": "https://github.com/rolandjlevy/css-ghost.git"
|
|
61
|
+
"url": "git+https://github.com/rolandjlevy/css-ghost.git"
|
|
48
62
|
},
|
|
49
63
|
"homepage": "https://github.com/rolandjlevy/css-ghost#readme",
|
|
64
|
+
"bugs": {
|
|
65
|
+
"url": "https://github.com/rolandjlevy/css-ghost/issues"
|
|
66
|
+
},
|
|
50
67
|
"engines": {
|
|
51
68
|
"node": ">=18"
|
|
52
69
|
},
|
package/src/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rolandjlevy/css-ghost — Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* Use this when integrating css-ghost into build tools, scripts, or plugins
|
|
5
|
+
* rather than running it as a CLI.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { scan, generateReport } from '@rolandjlevy/css-ghost';
|
|
9
|
+
*
|
|
10
|
+
* const results = scan(['/absolute/path/to/src']);
|
|
11
|
+
* const { totalAllOrphans } = generateReport(results, 'orphan-report.md');
|
|
12
|
+
* if (totalAllOrphans > 0) process.exit(1);
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export { scan } from './scanner.js';
|
|
16
|
+
export { generateReport } from './reporter.js';
|