domflax 0.1.0 → 0.1.1

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.
Files changed (39) hide show
  1. package/README.md +159 -0
  2. package/dist/{chunk-4HHISSMR.js → chunk-DNHOGPYV.js} +2675 -1503
  3. package/dist/chunk-DNHOGPYV.js.map +1 -0
  4. package/dist/{chunk-ZJ2S36GY.js → chunk-DOQEBGWB.js} +33 -20
  5. package/dist/chunk-DOQEBGWB.js.map +1 -0
  6. package/dist/{chunk-77SLHRN6.js → chunk-DWLB7FRR.js} +341 -176
  7. package/dist/chunk-DWLB7FRR.js.map +1 -0
  8. package/dist/cli.cjs +2169 -760
  9. package/dist/cli.cjs.map +1 -1
  10. package/dist/cli.js +183 -91
  11. package/dist/cli.js.map +1 -1
  12. package/dist/index.cjs +3021 -1699
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +477 -54
  15. package/dist/index.d.ts +477 -54
  16. package/dist/index.js +49 -3
  17. package/dist/pattern-CV607P87.d.ts +547 -0
  18. package/dist/pattern-F5xBtIE-.d.cts +547 -0
  19. package/dist/pattern-kit.cjs +60 -39
  20. package/dist/pattern-kit.cjs.map +1 -1
  21. package/dist/pattern-kit.d.cts +3 -18
  22. package/dist/pattern-kit.d.ts +3 -18
  23. package/dist/pattern-kit.js +3 -1
  24. package/dist/pattern-kit.js.map +1 -1
  25. package/dist/{types-BQ7l6dVe.d.ts → resolve-ops-DIwEelH-.d.cts} +26 -251
  26. package/dist/{types-BQ7l6dVe.d.cts → resolve-ops-DIwEelH-.d.ts} +26 -251
  27. package/dist/verify.d.cts +1 -1
  28. package/dist/verify.d.ts +1 -1
  29. package/dist/webpack-loader.cjs +2975 -1699
  30. package/dist/webpack-loader.cjs.map +1 -1
  31. package/dist/webpack-loader.d.cts +2 -2
  32. package/dist/webpack-loader.d.ts +2 -2
  33. package/dist/webpack-loader.js +3 -3
  34. package/package.json +3 -6
  35. package/dist/chunk-4HHISSMR.js.map +0 -1
  36. package/dist/chunk-77SLHRN6.js.map +0 -1
  37. package/dist/chunk-ZJ2S36GY.js.map +0 -1
  38. package/dist/pattern-CX6iBzTD.d.ts +0 -237
  39. package/dist/pattern-P4FIKAUB.d.cts +0 -237
package/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # domflax
2
+
3
+ > Compile-time DOM flattener and semantic CSS compressor — fewer DOM nodes, smaller class sets, **identical rendered UI**.
4
+
5
+ `domflax` analyzes your JSX at build time and rewrites it to a smaller equivalent:
6
+
7
+ 1. **Compress** — collapses verbose class sets into their shortest equivalents (`px-4 py-4 mt-2 mb-2` → `p-4 my-2`, `h-10 w-10` → `size-10`).
8
+ 2. **Flatten** — removes wrapper elements that are *provably inert* (they add no layout and paint nothing).
9
+
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.
11
+
12
+ ```tsx
13
+ // before
14
+ <div className="contents">
15
+ <div className="px-4 py-4 mt-2 mb-2" onClick={save}>{title}</div>
16
+ </div>
17
+
18
+ // after — the inert wrapper is gone, classes are minimized, behavior is identical
19
+ <div className="p-4 my-2" onClick={save}>{title}</div>
20
+ ```
21
+
22
+ It rewrites only the **static shape** of your markup. Dynamic class lists (`className={cn(...)}`), components, and `dangerouslySetInnerHTML` are opaque and preserved; `async`/data-fetching code is untouched.
23
+
24
+ **Safety model — conservative by default, no browser involved.**
25
+
26
+ - **Compression is always safe.** It only re-serializes an element's *own* class list, so a `ref`, an event handler, a `{dynamic}` child, or `dangerouslySetInnerHTML` never blocks it — only a *dynamic* className (or a class a CSS selector depends on) is left alone.
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. It never drops a style it can't reproduce, and never touches a wrapper a CSS selector depends on (`.list > .item h3`).
28
+ - domflax runs as a **purely static** source transform. It never launches a browser, so builds stay fast and deterministic.
29
+
30
+ > **Status: v0.1.1.** Works end-to-end on real `.jsx`/`.tsx` — in component-return position **and inside `.map()` / expressions (list rows)** — via Vite, Next.js (webpack), and the CLI, with Tailwind and custom-CSS providers. 22 patterns. Wrappers that establish a layout context (e.g. `flex`/`grid` centering) are **conservatively preserved** — proving those render-identical needs context a static pass can't see; recovering them safely is on the Roadmap. APIs may change before 1.0.
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ npm install -D domflax
36
+ ```
37
+
38
+ One install, one package. `pattern-kit` and `verify` are subpaths of `domflax` — there are no separate packages to add.
39
+
40
+ ## Usage
41
+
42
+ ### Vite
43
+
44
+ ```ts
45
+ // vite.config.ts
46
+ import { defineConfig } from 'vite'
47
+ import domflax from 'domflax'
48
+
49
+ export default defineConfig({
50
+ plugins: [domflax.vite({ provider: 'auto' })],
51
+ })
52
+ ```
53
+
54
+ ### Next.js (webpack)
55
+
56
+ ```js
57
+ // next.config.js
58
+ const domflax = require('domflax')
59
+
60
+ module.exports = {
61
+ webpack(config) {
62
+ domflax.webpack({ provider: 'tailwind' }).apply(config)
63
+ return config
64
+ },
65
+ }
66
+ ```
67
+
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
+
70
+ ### Tailwind (auto-detected)
71
+
72
+ When `tailwindcss` is present, `provider: 'auto'` resolves classes through the real Tailwind engine and emits the shortest equivalent Tailwind classes back. `tailwindcss` is an optional peer, loaded from your project only when used.
73
+
74
+ ### Custom CSS files
75
+
76
+ No Tailwind? Point domflax at your stylesheets; it parses them (PostCSS) for forward (class → style) and reverse (style → class) resolution, and reads their selectors for safety.
77
+
78
+ ```ts
79
+ domflax.vite({ provider: 'custom', cssFiles: ['./src/styles/main.css'] })
80
+ ```
81
+
82
+ ## CLI
83
+
84
+ domflax also runs standalone — point it at a folder or files. Run it with no arguments for an interactive wizard.
85
+
86
+ ```bash
87
+ npx domflax # interactive wizard (arrow keys, multiselect)
88
+ npx domflax ./src --dry-run # preview diffs, write nothing
89
+ npx domflax ./src --out ./domflax-out
90
+ ```
91
+
92
+ **Source is never overwritten by default.** Output goes to `--out` (or `./domflax-out`), or in place only inside disposable build dirs (`dist/`, `build/`). Rewriting source in place requires the explicit `--dangerously-overwrite-source` flag *and* a clean git tree. The wizard never runs in CI / non-TTY.
93
+
94
+ | Flag | Description |
95
+ | --- | --- |
96
+ | `<path>` | Folder (auto-scanned) or glob of files. |
97
+ | `--out <dir>` | Write optimized output here (mirrors input structure). |
98
+ | `--provider <name>` | `auto` (default), `tailwind`, or `custom`. |
99
+ | `--css <files...>` | Stylesheets when `--provider custom`. |
100
+ | `--dry-run` | Preview changes, write nothing. |
101
+ | `--dangerously-overwrite-source` | Allow in-place source rewrite (needs clean git). |
102
+
103
+ ## Writing a pattern
104
+
105
+ Patterns are how domflax knows what's safe to rewrite. Each is a **single declarative file** — the definition and its tests live in one `definePattern` call, with no separate test file and no manual registration:
106
+
107
+ ```ts
108
+ import { definePattern } from 'domflax/pattern-kit'
109
+
110
+ export default definePattern({
111
+ name: 'padding-shorthand',
112
+ category: 'compress/padding-shorthand',
113
+ safety: 1,
114
+ doc: { summary: 'Equal/paired padding longhands collapse to the shortest shorthand.' },
115
+ // a compress recipe rewrites only the element's own class list (declines with null otherwise)
116
+ rewrite: { rewriteClasses: (computed) => foldPadding(computed) },
117
+ test: {
118
+ cases: [{ before: '<div className="px-4 py-4">{x}</div>', after: '<div className="p-4">{x}</div>' }],
119
+ noMatch: ['<div className="pt-2 pr-4 pb-8 pl-4">box</div>'],
120
+ },
121
+ })
122
+ ```
123
+
124
+ Drop the file under `src/library/**` as `*.pattern.ts` and it's **auto-discovered**. The generic harness runs every pattern's `test` cases through the *real* transform, plus an automatic invariant suite (purity, opacity-barrier safety, id-preservation, fixpoint termination) — so a new pattern is wired, tested, and proven sound with zero boilerplate. Flatten patterns auto-receive the opacity + selector-safety guards; compress patterns are gated only on dynamic / selector-bound classes.
125
+
126
+ ## Advanced entry points
127
+
128
+ ```ts
129
+ import { definePattern } from 'domflax/pattern-kit' // author custom patterns
130
+ import { verifyEquivalence } from 'domflax/verify' // optional, standalone equivalence checker
131
+ ```
132
+
133
+ The transform itself is static and never launches a browser. `domflax/verify` is a **separate, opt-in tool** that renders before/after in headless Chromium (via Playwright, an optional peer) and diffs pixels + box geometry + computed styles — handy for vetting patterns, *not* part of your build.
134
+
135
+ ## Examples
136
+
137
+ Runnable examples live in [`examples/`](./examples): `vite-react-tailwind`, `vite-custom-css` (custom provider + selector-safety), and `next-tailwind`.
138
+
139
+ ## Roadmap
140
+
141
+ - [x] Monorepo + single bundled package
142
+ - [x] Core engine (IR, pass manager, surgical full-module codegen)
143
+ - [x] Declarative `definePattern({ …, test })` + auto-discovery; 22 flatten/compress patterns
144
+ - [x] Real Tailwind engine + custom-CSS resolvers
145
+ - [x] CSS selector-safety + residual-skip (don't break `div div h1`; never drop un-reproducible styles)
146
+ - [x] Compression across dynamic content (refs / handlers / `{expr}` children)
147
+ - [x] Optimize JSX inside `.map()` / expressions (list rows)
148
+ - [x] Vite + Next.js (webpack) adapters + CLI (folders, wizard, output-safety)
149
+ - [x] Standalone equivalence verifier (Playwright, opt-in)
150
+ - [ ] Context-aware (or opt-in-verified) flatten for `flex`/`grid` centering wrappers
151
+ - [ ] HTML frontend (plain `.html` / Astro static)
152
+ - [ ] `domflax/runtime` — optimize dynamic HTML strings before `innerHTML`
153
+ - [ ] More providers; `templatize` (plain-HTML cloneNode)
154
+
155
+ ## License
156
+
157
+ See [LICENSE](./LICENSE) (Domflax Software License 1.0). The `domflax/runtime`, `domflax/cli`, and pattern-library components are additionally available under the MIT License per the Runtime Exception.
158
+
159
+ © Krishnesh Mishra