domflax 0.1.4 → 0.2.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/README.md +47 -29
- package/dist/{chunk-EVENAJYI.js → chunk-EYQXQQQH.js} +3 -3
- package/dist/{chunk-3Z5ZWLXX.js → chunk-FPT4EJ6Q.js} +805 -1612
- package/dist/chunk-FPT4EJ6Q.js.map +1 -0
- package/dist/{chunk-5FWENSD2.js → chunk-JBM3MJRM.js} +149 -10
- package/dist/chunk-JBM3MJRM.js.map +1 -0
- package/dist/{chunk-H5KTGI3A.js → chunk-TTJEXWAC.js} +172 -5
- package/dist/chunk-TTJEXWAC.js.map +1 -0
- package/dist/cli.cjs +1032 -1640
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +30 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1116 -1627
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +226 -485
- package/dist/index.d.ts +226 -485
- package/dist/index.js +16 -36
- package/dist/{pattern-CP9_HpVK.d.cts → pattern-DotR_dHs.d.cts} +1 -1
- package/dist/pattern-kit.cjs +60 -1
- package/dist/pattern-kit.cjs.map +1 -1
- package/dist/pattern-kit.d.cts +2 -2
- package/dist/pattern-kit.d.ts +2 -2
- package/dist/pattern-kit.js +1 -1
- package/dist/{pattern-CYgsv-jO.d.ts → pattern-urm5uuwj.d.ts} +1 -1
- package/dist/{resolve-ops-Ci7LgYHC.d.ts → resolve-ops-D8aQina5.d.cts} +11 -0
- package/dist/{resolve-ops-Ci7LgYHC.d.cts → resolve-ops-D8aQina5.d.ts} +11 -0
- package/dist/verify.d.cts +1 -1
- package/dist/verify.d.ts +1 -1
- package/dist/webpack-loader.cjs +1014 -1578
- package/dist/webpack-loader.cjs.map +1 -1
- package/dist/webpack-loader.d.cts +8 -2
- package/dist/webpack-loader.d.ts +8 -2
- package/dist/webpack-loader.js +7 -4
- package/dist/webpack-loader.js.map +1 -1
- package/dist/worker.cjs +983 -1601
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-3Z5ZWLXX.js.map +0 -1
- package/dist/chunk-5FWENSD2.js.map +0 -1
- package/dist/chunk-H5KTGI3A.js.map +0 -1
- /package/dist/{chunk-EVENAJYI.js.map → chunk-EYQXQQQH.js.map} +0 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
`domflax` analyzes your JSX **and HTML** at build time and rewrites it to a smaller equivalent:
|
|
6
6
|
|
|
7
|
-
1. **Compress** —
|
|
7
|
+
1. **Compress** — a general engine rewrites each element's classes to the **shortest set that produces the same computed style** (`px-4 py-4 mt-2 mb-2` → `p-4 my-2`, `h-10 w-10` → `size-10`). One algorithm across **Tailwind v3, Tailwind v4, and custom CSS** — no per-utility patterns.
|
|
8
8
|
2. **Flatten** — removes wrapper elements that are *provably inert* (they add no layout and paint nothing).
|
|
9
9
|
|
|
10
10
|
Matching happens on **computed styles**, not raw class names — so the rules work across Tailwind, custom CSS, and (later) other providers, and a Tailwind class and an equivalent custom class compress the same way.
|
|
@@ -27,7 +27,7 @@ It rewrites only the **static shape** of your markup. Dynamic class lists (`clas
|
|
|
27
27
|
- **Flattening is conservative.** A wrapper is removed only when removal is *provably* render-neutral — it establishes no layout context and has no style to reproduce on its child. A `flex`/`grid` **centering** wrapper is removed only when its parent is statically `display:grid` (so `place-self:center` is provably equivalent — Chromium-verified); a flex/block/unknown parent leaves it preserved. It never drops a style it can't reproduce, and never touches a wrapper a CSS selector depends on (`.list > .item h3`).
|
|
28
28
|
- domflax runs as a **purely static** source transform. It never launches a browser, so builds stay fast and deterministic.
|
|
29
29
|
|
|
30
|
-
> **Status: v0.
|
|
30
|
+
> **Status: v0.2.0.** Optimizes real `.jsx`/`.tsx` **and `.html`** — component-return, inside `.map()`/expressions, and whole static-HTML sites — via Vite, Next.js (webpack), and the CLI. **Compression is one general engine** that emits the shortest class set reproducing each element's computed style, uniformly across **Tailwind v3, Tailwind v4, and custom CSS** (it re-resolves the result and verifies it's identical before emitting). **Flattening** is a lean set of provably-safe structural patterns (inert wrappers + grid-parent centering). **Static-only — never launches a browser** during a build; a Tailwind project it can't resolve is left untouched, never broken. The CLI batches large sites across CPU cores (`--max-memory`, never OOM) and auto-detects each HTML page's own `<link>` stylesheets; the Vite/Next plugins print a build-end optimization summary. APIs may change before 1.0.
|
|
31
31
|
|
|
32
32
|
## Install
|
|
33
33
|
|
|
@@ -67,9 +67,21 @@ module.exports = {
|
|
|
67
67
|
|
|
68
68
|
> domflax runs as a **source transform** on your `.jsx`/`.tsx` files via the bundler — it never touches a framework's shipped `index.html`. Use `next build` (webpack); **Turbopack is not supported yet** (it doesn't accept arbitrary webpack loaders).
|
|
69
69
|
|
|
70
|
+
At the end of the build both plugins print a one-box summary of what domflax did:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
▲ domflax
|
|
74
|
+
────────────────────────────────
|
|
75
|
+
files optimized 42
|
|
76
|
+
DOM nodes removed 318
|
|
77
|
+
classes compressed 1,204
|
|
78
|
+
size saved 18.7 KB
|
|
79
|
+
────────────────────────────────
|
|
80
|
+
```
|
|
81
|
+
|
|
70
82
|
### Tailwind (auto-detected)
|
|
71
83
|
|
|
72
|
-
When `tailwindcss` is present, `provider: 'auto'` resolves classes through
|
|
84
|
+
When `tailwindcss` is present, `provider: 'auto'` resolves classes through your project's real Tailwind engine — **Tailwind v3 and v4 are both supported** — and emits the shortest equivalent classes back. `tailwindcss` is an optional peer, loaded from your project only when used. A Tailwind version domflax can't resolve is left untouched (never broken).
|
|
73
85
|
|
|
74
86
|
### Custom CSS files
|
|
75
87
|
|
|
@@ -100,6 +112,7 @@ npx domflax ./src --out ./domflax-out
|
|
|
100
112
|
| `--max-memory <MB>` | Cap total RAM — and thus worker parallelism. Default ≈ 70% of free RAM; low values run slower but never OOM. |
|
|
101
113
|
| `--concurrency <N>` | Cap worker count (memory always wins). |
|
|
102
114
|
| `--dry-run` | Preview changes, write nothing. |
|
|
115
|
+
| `--details` | Print per-file optimization stats (nodes / classes / bytes). |
|
|
103
116
|
| `--dangerously-overwrite-source` | Allow in-place source rewrite (needs clean git). |
|
|
104
117
|
|
|
105
118
|
### HTML & static sites
|
|
@@ -117,26 +130,33 @@ npx domflax ./dist --provider custom --out ./dist-optimized
|
|
|
117
130
|
|
|
118
131
|
## Writing a pattern
|
|
119
132
|
|
|
120
|
-
|
|
133
|
+
Compression is a general engine — there are **no per-utility compress patterns**. Patterns are for **flattening**: each is a single declarative file whose definition and tests live in one `definePattern` call, auto-discovered, with no manual registration:
|
|
121
134
|
|
|
122
135
|
```ts
|
|
123
|
-
import { definePattern } from 'domflax/pattern-kit'
|
|
136
|
+
import { definePattern, not, hasDynamicClasses } from 'domflax/pattern-kit'
|
|
124
137
|
|
|
125
138
|
export default definePattern({
|
|
126
|
-
name: '
|
|
127
|
-
category: '
|
|
128
|
-
safety:
|
|
129
|
-
doc: { summary: '
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
name: 'display-contents-wrapper',
|
|
140
|
+
category: 'flatten/wrapper/display-contents-wrapper',
|
|
141
|
+
safety: 2,
|
|
142
|
+
doc: { summary: 'A display:contents wrapper generates no box — unwrap it into its sole child.' },
|
|
143
|
+
match: {
|
|
144
|
+
tag: 'div',
|
|
145
|
+
style: { display: 'contents' },
|
|
146
|
+
onlyChild: 'element',
|
|
147
|
+
paintsNothing: true,
|
|
148
|
+
where: [not(hasDynamicClasses)],
|
|
149
|
+
},
|
|
150
|
+
rewrite: { flattenInto: 'child' },
|
|
132
151
|
test: {
|
|
133
|
-
cases: [{ before: '<div className="
|
|
134
|
-
|
|
152
|
+
cases: [{ before: '<div className="contents"><a className="text-blue-500">L</a></div>',
|
|
153
|
+
after: '<a className="text-blue-500">L</a>' }],
|
|
154
|
+
noMatch: ['<div className="contents" ref={r}><a>L</a></div>'],
|
|
135
155
|
},
|
|
136
156
|
})
|
|
137
157
|
```
|
|
138
158
|
|
|
139
|
-
Drop the file under `src/library/**` as `*.pattern.ts` and it's **auto-discovered**. The generic harness runs
|
|
159
|
+
Drop the file under `src/library/**` as `*.pattern.ts` and it's **auto-discovered**. The generic harness runs its `test` cases through the *real* transform, plus an automatic invariant suite (purity, opacity-barrier safety, id-preservation, fixpoint termination). Every `flatten/*` pattern auto-receives the opacity + selector-safety guards, and the conservative safety gate only commits a removal it can *prove* is render-neutral — so a pattern can never produce unsafe output.
|
|
140
160
|
|
|
141
161
|
## Advanced entry points
|
|
142
162
|
|
|
@@ -153,21 +173,19 @@ Runnable examples live in [`examples/`](./examples): `vite-react-tailwind`, `vit
|
|
|
153
173
|
|
|
154
174
|
## Roadmap
|
|
155
175
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
- [ ] `domflax/runtime` — optimize dynamic HTML strings before `innerHTML`
|
|
170
|
-
- [ ] `templatize` (plain-HTML cloneNode)
|
|
176
|
+
Done so far: monorepo + single bundled package · core IR/pass engine with surgical codegen · declarative `definePattern` + auto-discovery · the general compress **engine** (Tailwind v3 + v4 + custom CSS) · Tailwind v4 support + fail-safe · selector-safety & residual-skip · compression across dynamic content and inside `.map()` rows · Vite + Next.js adapters with a build-end summary · HTML frontend with per-page `<link>` CSS auto-detection · grid-parent centering flatten (Chromium-verified) · memory-bounded parallel CLI.
|
|
177
|
+
|
|
178
|
+
Where it's going — each release adds the engine capability that unlocks its next validated pattern batch (full details in [`docs/ROADMAP.md`](./docs/ROADMAP.md)):
|
|
179
|
+
|
|
180
|
+
| Version | Theme | Patterns |
|
|
181
|
+
| --- | --- | --- |
|
|
182
|
+
| **0.3.0** | **Reach** — `cn()`/template-literal static extraction, arbitrary-value + variant-aware compression, deeper static layout reasoning (margin-collapse, item sizing) | ~25 |
|
|
183
|
+
| **0.4.0** | **Verified tier** — opt-in render-verified flattening for static HTML (real pages, pixel-identical or rejected); unlocks animation-wrapper class-transfer, multi-child unwraps, merges | ~60 |
|
|
184
|
+
| **0.5.0** | **More frontends** — Astro static + Vue SFC frontends, Turbopack, Bootstrap/other providers for the compress engine | ~100 |
|
|
185
|
+
| **0.6.0** | **Perf & ecosystem** — incremental/watch caching, `domflax/runtime`, `templatize` (cloneNode), community `domflax-pattern-*` packages | ~140 |
|
|
186
|
+
| **1.0.0** | **Stable** — frozen API, semver guarantees, docs site, published benchmarks | **200+** |
|
|
187
|
+
|
|
188
|
+
Every pattern that ships must *uniquely fire on real code* and be proven render-neutral (statically or via the verified tier) — the count grows from new capability surface, never from padding.
|
|
171
189
|
|
|
172
190
|
## License
|
|
173
191
|
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
createJsxBackend,
|
|
7
7
|
createJsxFrontend,
|
|
8
8
|
createTailwindResolver
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FPT4EJ6Q.js";
|
|
10
10
|
import {
|
|
11
11
|
buildSelectorIndex,
|
|
12
12
|
createSyntheticSink,
|
|
13
13
|
normalizer,
|
|
14
14
|
runPasses,
|
|
15
15
|
syncClassesFromComputed
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-TTJEXWAC.js";
|
|
17
17
|
import {
|
|
18
18
|
init_esm_shims
|
|
19
19
|
} from "./chunk-U5GOONKV.js";
|
|
@@ -333,4 +333,4 @@ export {
|
|
|
333
333
|
destinationFor,
|
|
334
334
|
createTransform
|
|
335
335
|
};
|
|
336
|
-
//# sourceMappingURL=chunk-
|
|
336
|
+
//# sourceMappingURL=chunk-EYQXQQQH.js.map
|