A modular CLI tool for transforming and cleaning up CSS files. Supports nesting selectors, merging duplicates, and consolidating media queries.
node scripts/cleanupCSS/index.js [command] <file.css>Or via npm:
npm run cleanupCSS -- [command] <file.css>| Command | Description |
|---|---|
info |
Output basic info about the CSS file (default when no command specified) |
nest-selectors |
Transform flat selectors to nested structure |
combine |
Merge duplicate selectors into a single nested structure |
mergeMQ |
Merge duplicate media queries; preserve document order (each block at first occurrence) |
pipeline |
Run all transforms sequentially: nest-selectors → combine → mergeMQ |
pipeline-dir |
Run full pipeline on every .css file in a directory (recursive) |
node scripts/cleanupCSS/index.js express/code/blocks/ax-columns/ax-columns.cssnode scripts/cleanupCSS/index.js nest-selectors express/code/blocks/ax-columns/ax-columns.cssOutput is written to {filename}_cleanedup.css (e.g. ax-columns_cleanedup.css).
Recommended: Use the pipeline command to run all transforms in one go. This is the convenience command that runs each transform in sequence, piping each step's output into the next:
# Via node
node scripts/cleanupCSS/index.js pipeline express/code/blocks/ax-columns/ax-columns.css
# Via npm
npm run cleanupCSS -- pipeline express/code/blocks/ax-columns/ax-columns.cssThis runs nest-selectors → combine → mergeMQ and writes the final result to ax-columns_cleanedup.css.
Use pipeline-dir with a folder path to find every .css file under that folder (and subfolders) and run the full pipeline on each. Output files are written next to each source as {filename}_cleanedup.css. Files named *_cleanedup.css are skipped so the tool does not reprocess its own output.
# Via node
node scripts/cleanupCSS/index.js pipeline-dir ./styles
# Via npm
npm run cleanupCSS -- pipeline-dir ./stylesEach command writes to {filename}_cleanedup.css. Running steps manually will create nested _cleanedup filenames (e.g. file_cleanedup_cleanedup.css). For a full cleanup run, use the pipeline command instead.
scripts/cleanupCSS/
├── index.js # CLI entry point, command dispatch
├── README.md # This file
├── lib/ # Shared utilities
│ ├── parse-css.js # CSS parsing
│ ├── selectors.js # Selector parsing & nesting logic
│ ├── combine-tree.js # Selector tree for combine transform
│ ├── media-query.js # Media query sort keys
│ ├── find-css.js # Recursive CSS file finder for pipeline-dir
│ └── output.js # Output path helpers
└── commands/ # Command implementations
├── info.js
├── nest-selectors.js
├── combine.js
└── mergeMQ.js
Converts flat CSS selectors to nested form using &:
.section .ax-columns→.section { & .ax-columns { } }- Handles multiple classes, pseudos, and combinators
Merges duplicate selectors within each "segment" of the file:
- Splits the file into segments by document order (alternating runs of rules and at-rules)
- Merges duplicate selectors only within each run of rules, so rules that originally appeared after a media query still override that media query
- Multiple
.section { }blocks in the same segment become one with all rules nested inside
- Merges duplicate
@mediarules with the same condition - Preserves document order: each merged block is emitted at the position of its first occurrence (avoids cascade bugs where rules that override media would otherwise be reordered)