Skip to content

Commit 29ee2a0

Browse files
Speed up build ~40% and add snapshot test suite (v1.6.0)
Replace the @extend-based comma-compression pass with a precomputed grouped-selector built during IR construction, cutting a full build from ~4.8s to ~2.8s with functionally equivalent output. Move per-utility registration to a flat shallow-merged registry instead of deep-merging the entire config in all 173 utility files. Add a snapshot test harness (npm test / test:update) with fixtures, a CSS normalizer for equivalence checks, README docs, and Cursor rules covering the utility schema and engine/test workflow. Rebuild dist and bump to v1.6.0. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent b33efc4 commit 29ee2a0

194 files changed

Lines changed: 115618 additions & 1514 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/rules/uniform-engine.mdc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
description: UniformCSS engine architecture and test workflow
3+
globs: uniform/_index.scss,uniform/core/**/*.scss
4+
alwaysApply: false
5+
---
6+
7+
# Engine: config → IR → emitters
8+
9+
`uniform/_index.scss` is a small compiler:
10+
11+
1. Utility files register into `core.$utilities` (a flat registry).
12+
2. `tree-constructor` lowers config into an intermediate map of class entries
13+
(`selector`, `grouped-selector`, `properties`, `category`, `parent`,
14+
`pseudo`, `screen`).
15+
3. Emitters consume that IR for `css`, `json`, `headless`, and `apply()`.
16+
17+
## Do not reintroduce @extend for comma-compression
18+
19+
Compressed output uses the precomputed `grouped-selector` (base selector +
20+
all its pseudo selectors, comma-joined) built during construction. This
21+
replaced the old `@extend` pass and is ~40% faster. Emit one rule per base
22+
class; skip `category: pseudo` entries. Never add `@extend` back.
23+
24+
## Always run snapshot tests after engine changes
25+
26+
```sh
27+
npm test # byte-exact diff of fixtures vs test/__snapshots__/
28+
npm run test:update # refresh snapshots after an INTENTIONAL output change
29+
```
30+
31+
- For compressed output, byte order may legitimately change. Verify functional
32+
equivalence with `node test/normalize.js <a.css> <b.css>` (expands comma
33+
groups and compares selector→declaration sets) BEFORE updating snapshots.
34+
- `nocompress`, `json`, and `apply` fixtures must stay byte-identical unless
35+
you intentionally changed those paths.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
description: How to add or edit a UniformCSS utility
3+
globs: uniform/utilities/**/*.scss
4+
alwaysApply: false
5+
---
6+
7+
# Utility files are declarative config, not CSS
8+
9+
Each utility file defines a single utility as a config map and registers it
10+
into the shared registry. It must NOT emit any CSS itself — the engine in
11+
`uniform/_index.scss` reads the registry and generates everything.
12+
13+
## Required shape
14+
15+
```scss
16+
@use "uniform/core";
17+
@use "sass:map";
18+
19+
$config: (
20+
utilities: (
21+
align-content: (
22+
important: false,
23+
shorthand: align-content, // class prefix; null = use variant key alone
24+
responsive: true,
25+
responsive-pseudos: false,
26+
extra-selector: null,
27+
properties: (align-content),
28+
static-properties: (), // always-emitted props (e.g. CSS vars)
29+
variants: ( center: center, start: flex-start ),
30+
pseudos: (none) // or e.g. (hover, group-hover, focus)
31+
)
32+
)
33+
);
34+
35+
// Always register via this exact line — shallow merge into the registry.
36+
core.$utilities: map.merge(core.$utilities, map.get($config, utilities));
37+
```
38+
39+
- Do NOT use `map.deep-merge(core.$all-config, $config)` (the old, quadratic pattern).
40+
- Utility names are unique top-level keys, so a shallow `map.merge` is correct.
41+
- After adding a utility, also `@use` it in `uniform/_index.scss`.

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,32 @@ Add Uniform as a Sass module to your `main.scss` project. Follow these steps to
132132
);
133133
```
134134

135+
## Development & Testing
136+
137+
Uniform compiles a config map into an intermediate representation and then emits
138+
CSS, JSON, or headless output. To guard that pipeline, the repo ships a snapshot
139+
test harness that compiles a set of fixtures and diffs them against committed
140+
baselines.
141+
142+
```sh
143+
# Compile fixtures and diff against test/__snapshots__/
144+
npm test
145+
146+
# Refresh baselines after an intentional output change
147+
npm run test:update
148+
```
149+
150+
Fixtures live in `test/fixtures/` and cover the default build, the
151+
non-compressed path, JSON output, a heavily customized config, and the
152+
`apply()` mixin. Because comma-compressed output can change selector order
153+
without changing meaning, `test/normalize.js` expands comma groups and compares
154+
`selector → declaration` sets so you can confirm two stylesheets are
155+
functionally equivalent before updating a snapshot:
156+
157+
```sh
158+
node test/normalize.js test/__snapshots__/default.css test/__out__/default.css
159+
```
160+
135161
## Community
136162

137163
If you're ever stuck, need help, or wish to have a general discussion about this project, please get involved with the following community channels.

0 commit comments

Comments
 (0)