domflax 0.1.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/LICENSE +214 -0
- package/dist/chunk-4HHISSMR.js +2227 -0
- package/dist/chunk-4HHISSMR.js.map +1 -0
- package/dist/chunk-6WVVF6AD.js +55 -0
- package/dist/chunk-6WVVF6AD.js.map +1 -0
- package/dist/chunk-77SLHRN6.js +2047 -0
- package/dist/chunk-77SLHRN6.js.map +1 -0
- package/dist/chunk-ZJ2S36GY.js +175 -0
- package/dist/chunk-ZJ2S36GY.js.map +1 -0
- package/dist/cli.cjs +5207 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1310 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +4383 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +539 -0
- package/dist/index.d.ts +539 -0
- package/dist/index.js +110 -0
- package/dist/index.js.map +1 -0
- package/dist/pattern-CX6iBzTD.d.ts +237 -0
- package/dist/pattern-P4FIKAUB.d.cts +237 -0
- package/dist/pattern-kit.cjs +630 -0
- package/dist/pattern-kit.cjs.map +1 -0
- package/dist/pattern-kit.d.cts +80 -0
- package/dist/pattern-kit.d.ts +80 -0
- package/dist/pattern-kit.js +55 -0
- package/dist/pattern-kit.js.map +1 -0
- package/dist/types-BQ7l6dVe.d.cts +749 -0
- package/dist/types-BQ7l6dVe.d.ts +749 -0
- package/dist/verify.cjs +2747 -0
- package/dist/verify.cjs.map +1 -0
- package/dist/verify.d.cts +245 -0
- package/dist/verify.d.ts +245 -0
- package/dist/verify.js +2700 -0
- package/dist/verify.js.map +1 -0
- package/dist/webpack-loader.cjs +4149 -0
- package/dist/webpack-loader.cjs.map +1 -0
- package/dist/webpack-loader.d.cts +21 -0
- package/dist/webpack-loader.d.ts +21 -0
- package/dist/webpack-loader.js +30 -0
- package/dist/webpack-loader.js.map +1 -0
- package/package.json +99 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
import { n as IRDocument, J as ApplyResult, K as RewriteGroup, L as ApplyContext, O as RewriteOp, Q as FixpointConfig, T as StyleResolver, U as SelectorIndex, W as Pass, X as PassManager, x as RewriteFactory, Y as PhaseRunResult, Z as Pipeline, _ as SyntheticSink, c as StyleNormalizer, w as Captures, P as Pattern, v as SafetyLevel, $ as EncodedSourceMap } from './types-BQ7l6dVe.cjs';
|
|
2
|
+
export { a0 as AppliedOp, A as AttrMap, a1 as AttrValue, a2 as Backend, a3 as BackendContext, k as Backref, B as BackrefTable, a4 as Brand, g as ClassList, a5 as ClassListForm, a6 as ClassSegment, a7 as ClassToken, a8 as CodegenResult, a9 as CommentSpec, e as ConditionKey, C as CssProperty, aa as CssValue, ab as DeclSignature, ac as DeepReadonly, H as Diagnostic, ad as DiagnosticCode, ae as DistributiveOmit, af as EditPlan, E as ElementLike, ag as ElementSpec, ah as EmitContext, ai as EmitResult, aj as ExprKind, ak as ExprRecord, p as ExprRef, r as ExprRegistry, al as ExprSpec, am as FileKind, an as FragmentSpec, ao as Frontend, ap as FrontendConfig, F as FrontendKind, aq as FrontendParseContext, ar as HaltReason, m as IRComment, o as IRElement, q as IRExpr, s as IRFragment, f as IRNamespace, l as IRNode, as as IRNodeBase, I as IRNodeId, at as IRNodeKind, u as IRText, t as IdAllocator, au as InheritedPropertyTable, h as InlineStyle, M as MatchContext, y as MatchResult, N as NodeLike, j as NodeMeta, av as NodeRefSpec, b as NodeSpec, aw as OpOrigin, ax as OpValidationIssue, ay as OpaqueReason, az as OpaqueToken, aA as ParentLayoutContext, aB as ParseResult, z as PassCategory, aC as PassPhase, aD as PassTraceEntry, G as PatternDoc, aE as PatternName, aF as PipelineConfig, aG as PipelineInput, aH as PipelineOutput, aI as PipelineStats, aJ as Position, D as PreconditionSketch, aK as ReindentSpec, aL as Reporter, aM as ResolveInput, aN as ResolveResult, aO as ResolverDiagnostic, aP as RewriteContext, R as RewriteOpDraft, aQ as SelectorUsage, aR as Severity, aS as SkippedOpGroup, aT as SourceFile, aU as SourceFileId, i as SourceSpan, aV as StructuralInverse, aW as StyleBlock, d as StyleCondition, a as StyleConflictPolicy, aX as StyleDecl, S as StyleMap, aY as StyleOrigin, aZ as StylePredicate, a_ as SyntheticClass, a$ as TextEdit, b0 as TextSpec, b1 as TreeShapeSketch, b2 as VisitContext, b3 as VisitSignal, V as Visitor } from './types-BQ7l6dVe.cjs';
|
|
3
|
+
import { A as AuthoredPattern } from './pattern-P4FIKAUB.cjs';
|
|
4
|
+
export { B as BASE_CONDITION, u as BASE_CONDITION_KEY, v as ElementInit, w as MutableBackrefTable, x as childIds, y as conditionKey, z as createBackrefTable, C as createComment, G as createDocument, H as createElement, I as createExpr, J as createExprRegistry, K as createFragment, L as createIdAllocator, N as createText, O as defaultMeta, Q as elementIds, S as emptyAttrMap, T as emptyClassList, U as emptyInlineStyle, i as emptyStyleMap, V as getElement, W as getNode, X as walk } from './pattern-P4FIKAUB.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @domflax/core — the pure applier (the one trusted mutator).
|
|
8
|
+
*
|
|
9
|
+
* {@link applyOps} takes an {@link IRDocument} plus a flat list of {@link RewriteOp}s and returns
|
|
10
|
+
* a NEW, mutated document (the input document is left untouched — "pure" in the input-immutability
|
|
11
|
+
* sense). Every op is validated against the safety ceiling and node-local safety floor before it
|
|
12
|
+
* runs; rejected ops are collected into {@link ApplyResult.skipped} with {@link Diagnostic}s rather
|
|
13
|
+
* than throwing. Dependency-free: only the `./types` contract and `./builders` runtime helpers.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
interface ApplyOutcome {
|
|
17
|
+
/** The new document (the input doc is never mutated). */
|
|
18
|
+
readonly doc: IRDocument;
|
|
19
|
+
readonly result: ApplyResult;
|
|
20
|
+
}
|
|
21
|
+
/** Shallow-immutable clone: input doc and its node objects are never mutated. */
|
|
22
|
+
declare function cloneDocument(doc: IRDocument): IRDocument;
|
|
23
|
+
/**
|
|
24
|
+
* Apply a flat list of ops to a copy of `doc`. The input document is never mutated.
|
|
25
|
+
* Each op is independently validated; failing ops are skipped (collected in
|
|
26
|
+
* {@link ApplyResult.skipped}) instead of throwing.
|
|
27
|
+
*/
|
|
28
|
+
declare function applyOps(doc: IRDocument, ops: readonly RewriteOp[], ctx?: Partial<ApplyContext>): ApplyOutcome;
|
|
29
|
+
/**
|
|
30
|
+
* Apply pre-grouped ops (each {@link RewriteGroup} is committed atomically: if ANY op in the group
|
|
31
|
+
* fails validation, the whole group is skipped and none of its ops mutate the tree).
|
|
32
|
+
*/
|
|
33
|
+
declare function applyGroups(doc: IRDocument, groups: readonly RewriteGroup[], ctx?: Partial<ApplyContext>): ApplyOutcome;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @domflax/core — pass manager + supporting contexts.
|
|
37
|
+
*
|
|
38
|
+
* Runs {@link Pattern}s grouped by {@link PassCategory} in declared order, driving the `flatten`
|
|
39
|
+
* phase to a fixpoint under a max-iteration budget, and isolating per-node pattern errors into
|
|
40
|
+
* {@link Diagnostic}s (a thrown pattern never aborts the run — it becomes `DF_PATTERN_THREW`).
|
|
41
|
+
*
|
|
42
|
+
* Dependency-free: only the `./types` contract plus `./builders` + `./ops` runtime helpers.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
declare const DEFAULT_FIXPOINT: FixpointConfig;
|
|
46
|
+
/** A no-op resolver: owns nothing, resolves to empty styles. Useful as an injection default. */
|
|
47
|
+
declare function createNullResolver(): StyleResolver;
|
|
48
|
+
/** A SelectorIndex that reports zero CSS-targeting (no combinator/structural coupling). */
|
|
49
|
+
declare function createNullSelectorIndex(): SelectorIndex;
|
|
50
|
+
/**
|
|
51
|
+
* Build a real {@link SelectorIndex} from the active resolver.
|
|
52
|
+
*
|
|
53
|
+
* For a resolver that reports project COMPLEX selectors — anything with a combinator (`>`/`+`/`~`/
|
|
54
|
+
* descendant) or a structural pseudo, i.e. the custom-CSS resolver — every element whose static class
|
|
55
|
+
* participates in such a selector is flagged so the flatten/compress guards (`targetedByCombinator` /
|
|
56
|
+
* `affectsSelectorMatching`) fire and a wrapper a selector depends on is NOT flattened. An element is
|
|
57
|
+
* combinator-coupled when one of its classes is used as a descendant/child ancestor, as a sibling
|
|
58
|
+
* subject, or as a `:has()` argument; structural-coupled when used in `:nth-child(...)` etc.
|
|
59
|
+
*
|
|
60
|
+
* For a combinator-free resolver (Tailwind utilities — no `complexSelectors()`), this degrades to the
|
|
61
|
+
* null index so behaviour is unchanged.
|
|
62
|
+
*/
|
|
63
|
+
declare function buildSelectorIndex(doc: IRDocument, resolver: StyleResolver): SelectorIndex;
|
|
64
|
+
/** The pattern-kit factory: produces op DRAFTS and detached NodeSpecs without any allocation. */
|
|
65
|
+
declare function createRewriteFactory(): RewriteFactory;
|
|
66
|
+
/**
|
|
67
|
+
* Runs `passes` over `doc` to a per-phase fixpoint. This is the concrete entry the pipeline calls
|
|
68
|
+
* (the {@link PassManager} interface keeps passes on the call site; we accept them explicitly here
|
|
69
|
+
* so the manager stays stateless).
|
|
70
|
+
*/
|
|
71
|
+
declare function runPasses(doc: IRDocument, passes: readonly Pass[], ctx: ApplyContext, config?: FixpointConfig): {
|
|
72
|
+
readonly doc: IRDocument;
|
|
73
|
+
readonly results: readonly PhaseRunResult[];
|
|
74
|
+
};
|
|
75
|
+
/** A {@link PassManager} that runs the given passes (carried on the manager instance). */
|
|
76
|
+
declare function createPassManager(passes: readonly Pass[]): PassManager;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @domflax/core — the pure, single-file pipeline.
|
|
80
|
+
*
|
|
81
|
+
* Wires injected interfaces together: {@link Frontend} → resolve → {@link PassManager} →
|
|
82
|
+
* {@link Backend}. Core itself stays dependency-free; the resolver, frontend, and backend are all
|
|
83
|
+
* supplied by the caller, so no heavy third-party libs ever reach this package.
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
/** A minimal in-memory {@link SyntheticSink}: dedupes by className, drains in insertion order. */
|
|
87
|
+
declare function createSyntheticSink(): SyntheticSink;
|
|
88
|
+
/** Build the pure single-file {@link Pipeline}. */
|
|
89
|
+
declare function createPipeline(): Pipeline;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @domflax/core — the shared reverse-emit step (computed → className).
|
|
93
|
+
*
|
|
94
|
+
* The backend re-prints `className` from each element's {@link ClassList}, but the pass manager
|
|
95
|
+
* records optimized styles on `computed`. This module folds those optimized computed styles back
|
|
96
|
+
* into the element's static class tokens, and is the SINGLE source of truth shared by every
|
|
97
|
+
* orchestrator (the `domflax` meta package, `@domflax/cli`, and the pattern auto-test harness) so
|
|
98
|
+
* their pipelines cannot diverge.
|
|
99
|
+
*
|
|
100
|
+
* ## REPLACE, not append
|
|
101
|
+
*
|
|
102
|
+
* For every TOUCHED, rewritable (non-opaque, non-dynamic) element we ask the resolver for the
|
|
103
|
+
* MINIMAL class set reproducing the element's FULL computed style (`resolver.emit(el.computed)`),
|
|
104
|
+
* then REPLACE the element's static tokens with it — rather than appending. Replacing is what lets
|
|
105
|
+
* a compress pass actually shorten output: `px-4 py-4` collapses to `p-4`, equal `w/h` to `size-*`,
|
|
106
|
+
* the four insets to `inset-0`, and fully-overridden duplicates simply disappear.
|
|
107
|
+
*
|
|
108
|
+
* ## Droppability gate (never lose a load-bearing class)
|
|
109
|
+
*
|
|
110
|
+
* A token is only removed when `resolver.selectorUsage(token).droppable` is true — i.e. it is a
|
|
111
|
+
* plain, resolver-owned utility whose entire contribution is reproducible from `computed`. Tokens
|
|
112
|
+
* that are unknown to the resolver, opaque (combinator/at-rule utilities whose effect never folds
|
|
113
|
+
* onto the element's own box), variant-bound, or referenced by a custom-CSS selector are NOT
|
|
114
|
+
* droppable and are preserved verbatim. As a safety net, if `emit` produces nothing at all we leave
|
|
115
|
+
* the element's tokens untouched (a resolver that failed to load must never erase classes).
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Fold every TOUCHED, rewritable element's optimized computed style back into the MINIMAL static
|
|
120
|
+
* class-token set (see module docs). Mutates `doc` in place.
|
|
121
|
+
*/
|
|
122
|
+
declare function syncClassesFromComputed(doc: IRDocument, resolver: StyleResolver, norm: StyleNormalizer): void;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @domflax/patterns — flatten pattern: `empty-style-div`.
|
|
126
|
+
*
|
|
127
|
+
* Collapses the most common piece of structural noise of all: a `<div>` whose ONLY role is to wrap
|
|
128
|
+
* a single child while contributing nothing to layout or paint —
|
|
129
|
+
*
|
|
130
|
+
* <div><Child/></div> (no styles at all)
|
|
131
|
+
* <div style="display:block"><Child/></div> (the default; still a no-op box)
|
|
132
|
+
*
|
|
133
|
+
* Such a div is layout-neutral: it is a plain block box with no own visual style, establishes no
|
|
134
|
+
* box / formatting / stacking context, is not a containing block, and declares no custom properties
|
|
135
|
+
* a descendant might read. Its box is therefore indistinguishable from "not being there", so it can
|
|
136
|
+
* be unwrapped into its sole child.
|
|
137
|
+
*
|
|
138
|
+
* Authored with the declarative {@link pattern} API. The opacity-barrier + selector-safety guards
|
|
139
|
+
* (ref/handlers/dynamic-children/raw-html/combinator/reparent-impact) are applied automatically for
|
|
140
|
+
* every `flatten/*` pattern; the `where` predicates below add the LAYOUT-neutrality requirements
|
|
141
|
+
* specific to this pattern (no non-block display, no box/formatting/stacking context, no containing
|
|
142
|
+
* block, no custom-property coupling, no structural-pseudo targeting).
|
|
143
|
+
*/
|
|
144
|
+
/**
|
|
145
|
+
* Flatten a layout-neutral, style-free `<div>` wrapper into its sole element child.
|
|
146
|
+
*/
|
|
147
|
+
declare const emptyStyleDiv: AuthoredPattern<Captures>;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @domflax/patterns — flatten pattern: `flex-center-wrapper`.
|
|
151
|
+
*
|
|
152
|
+
* Collapses the ubiquitous "centering wrapper" idiom
|
|
153
|
+
*
|
|
154
|
+
* <div style="display:flex; align-items:center; justify-content:center"><Child/></div>
|
|
155
|
+
*
|
|
156
|
+
* into its sole child, pushing the centering intent down onto the child as `place-self: center`.
|
|
157
|
+
* The wrapper only exists to center one element; once `place-self:center` lives on the child the
|
|
158
|
+
* wrapper is pure structural noise and can go.
|
|
159
|
+
*
|
|
160
|
+
* Authored with the declarative {@link pattern} API: the match is the flex-centering computed-style
|
|
161
|
+
* signature on a single-element-child `<div>` that paints nothing of its own; the recipe folds
|
|
162
|
+
* inheritable styles onto the child, grants it `place-self:center`, then unwraps the wrapper
|
|
163
|
+
* (id-preserving). The opacity-barrier + selector-safety guards are applied automatically by the
|
|
164
|
+
* `pattern()` factory for every `flatten/*` pattern.
|
|
165
|
+
*/
|
|
166
|
+
/**
|
|
167
|
+
* Flatten a flex-centering `<div>` wrapper into its sole element child, granting the child
|
|
168
|
+
* `place-self:center`.
|
|
169
|
+
*/
|
|
170
|
+
declare const flexCenterWrapper: AuthoredPattern<Captures>;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @domflax/patterns — flatten pattern: `nested-flex-merge`.
|
|
174
|
+
*
|
|
175
|
+
* Collapses a redundant nesting of two flex containers
|
|
176
|
+
*
|
|
177
|
+
* <div style="display:flex; align-items:center; gap:8px">
|
|
178
|
+
* <div style="display:flex; flex-direction:column"> … </div>
|
|
179
|
+
* </div>
|
|
180
|
+
*
|
|
181
|
+
* where the OUTER flex container's sole element child is ITSELF a flex container, into a single
|
|
182
|
+
* flex container that carries the union of both elements' flex declarations. The outer wrapper's
|
|
183
|
+
* box is then structural noise (it paints nothing and only establishes a flex context that the
|
|
184
|
+
* merged child now also establishes), so it is removed.
|
|
185
|
+
*
|
|
186
|
+
* Authored with the declarative {@link pattern} API: the match is a flex `<div>` with a single
|
|
187
|
+
* element child painting nothing of its own (auto-guarded against opacity barriers / combinator
|
|
188
|
+
* targeting like every `flatten/*` pattern). The value-relational reasoning — the child must also
|
|
189
|
+
* be a (non-combinator) flex container, the wrapper must carry only transferable flex/inheritable
|
|
190
|
+
* declarations, and the two must not conflict on any shared flex property — lives in the `rewrite`
|
|
191
|
+
* op-draft factory escape hatch, which folds inherited styles, transfers the wrapper's flex
|
|
192
|
+
* declarations onto the child (target-wins), then unwraps the wrapper.
|
|
193
|
+
*/
|
|
194
|
+
/**
|
|
195
|
+
* Flatten a flex container whose sole child is a compatible flex container into a single container.
|
|
196
|
+
*/
|
|
197
|
+
declare const nestedFlexMerge: AuthoredPattern<Captures>;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @domflax/patterns — flatten pattern: `passthrough-wrapper`.
|
|
201
|
+
*
|
|
202
|
+
* Collapses a purely-structural wrapper that exists for no reason at all:
|
|
203
|
+
*
|
|
204
|
+
* <div><Child/></div>
|
|
205
|
+
*
|
|
206
|
+
* The wrapper paints nothing, establishes no box / formatting / stacking context, carries no
|
|
207
|
+
* attributes beyond an (optional) inert class, holds exactly one element child, and is free of every
|
|
208
|
+
* opacity barrier (ref / event-handlers / dynamic children / dangerous html / spread / component).
|
|
209
|
+
* Such a `<div>` is pure DOM noise: removing it and hoisting the child is invisible to both paint
|
|
210
|
+
* and layout.
|
|
211
|
+
*
|
|
212
|
+
* Authored with the declarative {@link pattern} API. The opacity-barrier + selector-safety guards
|
|
213
|
+
* (ref/handlers/dynamic-children/raw-html/combinator/reparent-impact) are applied automatically for
|
|
214
|
+
* every `flatten/*` pattern; the `where` predicates add the passthrough-specific requirements (no
|
|
215
|
+
* box/formatting/stacking context, no own attrs, no dynamic/spread classes, not a component, not a
|
|
216
|
+
* structural-pseudo subject).
|
|
217
|
+
*/
|
|
218
|
+
/**
|
|
219
|
+
* Flatten a do-nothing `<div>` wrapper into its sole element child, folding any inheritable styles
|
|
220
|
+
* down first so inherited values survive the box removal.
|
|
221
|
+
*/
|
|
222
|
+
declare const passthroughWrapper: AuthoredPattern<Captures>;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @domflax/patterns — flatten pattern: `redundant-fragment`.
|
|
226
|
+
*
|
|
227
|
+
* Collapses a fragment that wraps exactly one child
|
|
228
|
+
*
|
|
229
|
+
* <><Child/></> → <Child/>
|
|
230
|
+
*
|
|
231
|
+
* A fragment renders no box of its own, so a fragment whose sole purpose is to wrap a single node
|
|
232
|
+
* is pure structural noise: splicing the child up into the fragment's slot is invisible in both
|
|
233
|
+
* the rendered DOM and the project's CSS cascade.
|
|
234
|
+
*
|
|
235
|
+
* Anchoring: the pass manager only visits ELEMENT nodes (see core's `elementIds`), never fragments,
|
|
236
|
+
* so this pattern is anchored on the fragment's sole *element* child and removes the PARENT fragment.
|
|
237
|
+
* Because the match is PARENT-anchored (and reads a fragment's `meta`, which the element-only
|
|
238
|
+
* combinator vocabulary cannot inspect), it uses the declarative API's two escape hatches: a raw
|
|
239
|
+
* `match` predicate and a raw `rewrite` op-draft factory.
|
|
240
|
+
*/
|
|
241
|
+
/**
|
|
242
|
+
* Flatten a fragment that wraps exactly one child into that child.
|
|
243
|
+
*
|
|
244
|
+
* Safety level 1 (`safe`): a purely structural, style-free, selector-transparent cleanup.
|
|
245
|
+
*/
|
|
246
|
+
declare const redundantFragment: AuthoredPattern<Captures>;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @domflax/patterns — compress pattern: `dedupe-classes`.
|
|
250
|
+
*
|
|
251
|
+
* Removes duplicate / fully-overridden class tokens that resolve to the same property where a
|
|
252
|
+
* LATER token wins, leaving the minimal set of tokens with an IDENTICAL computed style. The
|
|
253
|
+
* canonical case:
|
|
254
|
+
*
|
|
255
|
+
* <p class="text-sm text-lg">…</p> → <p class="text-lg">…</p>
|
|
256
|
+
*
|
|
257
|
+
* Both `text-sm` and `text-lg` set `font-size`; resolution already made `text-lg` win, so the
|
|
258
|
+
* computed `font-size` is `text-lg`'s value and `text-sm` contributes NOTHING to the final
|
|
259
|
+
* computed style. The earlier token is pure noise and can be dropped without changing a pixel.
|
|
260
|
+
*
|
|
261
|
+
* How redundancy is detected (purely from the already-resolved, normalized computed StyleMap):
|
|
262
|
+
* • every declaration carries provenance — `origin` (the winning token) and `shadowed`
|
|
263
|
+
* (the tokens it overrode);
|
|
264
|
+
* • a class token is FULLY OVERRIDDEN iff it appears in some declaration's `shadowed` list but
|
|
265
|
+
* is NOT the winning `origin` of any declaration across ANY style condition. Such a token can
|
|
266
|
+
* be deleted with zero effect on the computed style.
|
|
267
|
+
*
|
|
268
|
+
* Authored with the declarative {@link pattern} API: the `where` guards exclude opacity barriers,
|
|
269
|
+
* dynamic/opaque class lists, and combinator subjects; the `dropClasses` recipe returns the set of
|
|
270
|
+
* fully-overridden, resolver-droppable tokens to delete (their `shadowed` provenance is pruned
|
|
271
|
+
* automatically before the minimal class StyleMap is re-installed).
|
|
272
|
+
*/
|
|
273
|
+
/**
|
|
274
|
+
* Collapse a class list to the minimal token set that yields an identical computed style, by
|
|
275
|
+
* dropping tokens whose declarations are fully overridden by later tokens.
|
|
276
|
+
*/
|
|
277
|
+
declare const dedupeClasses: AuthoredPattern<Captures>;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* @domflax/patterns — compress pattern: `inset-shorthand`.
|
|
281
|
+
*
|
|
282
|
+
* Recompacts the four physical inset longhands (`top`/`right`/`bottom`/`left`) on an element's
|
|
283
|
+
* computed style back into the tightest CSS shorthand the values allow:
|
|
284
|
+
*
|
|
285
|
+
* • all four equal → `inset: <v>`
|
|
286
|
+
* • top == bottom (a matching pair) → `inset-block: <v>` (Tailwind `inset-y-*`)
|
|
287
|
+
* • left == right (a matching pair) → `inset-inline: <v>` (Tailwind `inset-x-*`)
|
|
288
|
+
*
|
|
289
|
+
* The two axis collapses are independent: an element whose `top == bottom` but `left != right`
|
|
290
|
+
* collapses only the block axis and keeps the `left`/`right` longhands verbatim. When nothing
|
|
291
|
+
* collapses (all four distinct, or fewer than a full pair present) the pattern declines.
|
|
292
|
+
*
|
|
293
|
+
* Authored with the declarative {@link pattern} API: the `where` guards exclude opacity barriers,
|
|
294
|
+
* dynamic class lists, and combinator subjects; the `rewriteClasses` recipe rebuilds the class
|
|
295
|
+
* StyleMap, declining (`null`) unless at least one inset axis collapses.
|
|
296
|
+
*/
|
|
297
|
+
/**
|
|
298
|
+
* Collapse equal/paired physical inset longhands into the `inset` / `inset-block` / `inset-inline`
|
|
299
|
+
* shorthands on an element's computed style.
|
|
300
|
+
*/
|
|
301
|
+
declare const insetShorthand: AuthoredPattern<Captures>;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* @domflax/patterns — compress pattern: `margin-shorthand`.
|
|
305
|
+
*
|
|
306
|
+
* Collapses the four explicit margin longhands
|
|
307
|
+
*
|
|
308
|
+
* margin-top / margin-right / margin-bottom / margin-left
|
|
309
|
+
*
|
|
310
|
+
* back into a single CSS `margin` shorthand declaration on the SAME element (the margin analogue of
|
|
311
|
+
* `padding-shorthand`, covering the `m` / `mx` / `my` collapse), choosing the shortest legal
|
|
312
|
+
* 1–4-value form:
|
|
313
|
+
*
|
|
314
|
+
* • all four equal → `margin: <v>` (the `m` case)
|
|
315
|
+
* • top==bottom and left==right → `margin: <y> <x>` (the `my`/`mx` case)
|
|
316
|
+
* • left==right (top!=bottom) → `margin: <t> <x> <b>`
|
|
317
|
+
* • otherwise → `margin: <t> <r> <b> <l>`
|
|
318
|
+
*
|
|
319
|
+
* It is a pure representation change: the resolved box model is identical, only the declaration
|
|
320
|
+
* count shrinks from four to one, which the backend can then re-emit as a single shorthand utility.
|
|
321
|
+
*
|
|
322
|
+
* Authored with the declarative {@link pattern} API: the `where` guards exclude opacity barriers,
|
|
323
|
+
* dynamic class lists, and combinator subjects; the `rewriteClasses` recipe rebuilds the class
|
|
324
|
+
* StyleMap, declining (`null`) unless all four margin longhands are present with a uniform
|
|
325
|
+
* (non-)`!important` flag.
|
|
326
|
+
*/
|
|
327
|
+
/**
|
|
328
|
+
* Fold four margin longhands into one `margin` shorthand on the element's base style block.
|
|
329
|
+
*/
|
|
330
|
+
declare const marginShorthand: AuthoredPattern<Captures>;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* @domflax/patterns — compress pattern: `padding-shorthand`.
|
|
334
|
+
*
|
|
335
|
+
* Collapses an element whose four padding sides are expressed as separate longhand declarations
|
|
336
|
+
* back into the shortest equivalent shorthand:
|
|
337
|
+
*
|
|
338
|
+
* padding-top:16px; padding-right:16px; padding-bottom:16px; padding-left:16px
|
|
339
|
+
* ⇒ padding:16px (Tailwind `p-4`)
|
|
340
|
+
*
|
|
341
|
+
* padding-top:8px; padding-bottom:8px; padding-left:16px; padding-right:16px
|
|
342
|
+
* ⇒ padding:8px 16px (Tailwind `px-4 py-2`)
|
|
343
|
+
*
|
|
344
|
+
* The IR's computed StyleMap is canonically LONGHAND (the shared normalizer expands every box
|
|
345
|
+
* shorthand at parse time). This pass runs the expansion in reverse on the computed map ONLY when
|
|
346
|
+
* the four sides fold cleanly into a 1- or 2-value form — i.e. `top===bottom` AND `left===right`.
|
|
347
|
+
*
|
|
348
|
+
* Authored with the declarative {@link pattern} API: the `where` guards exclude opacity barriers,
|
|
349
|
+
* dynamic class lists, spread/component identity, and combinator subjects; the `rewriteClasses`
|
|
350
|
+
* recipe rebuilds the class StyleMap, declining (`null`) unless the four sides fold cleanly.
|
|
351
|
+
*/
|
|
352
|
+
/**
|
|
353
|
+
* Compress an element's four equal/paired padding longhands into the shortest `padding` shorthand.
|
|
354
|
+
*/
|
|
355
|
+
declare const paddingShorthand: AuthoredPattern<Captures>;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* @domflax/patterns — compress pattern: `size-shorthand`.
|
|
359
|
+
*
|
|
360
|
+
* Collapses an element whose computed `width` and `height` are EQUAL into the single Tailwind
|
|
361
|
+
* `size-*` utility:
|
|
362
|
+
*
|
|
363
|
+
* <div style="width:1rem; height:1rem"/> → <div class="size-4"/>
|
|
364
|
+
*
|
|
365
|
+
* At the IR level we work over the normalized computed StyleMap (CSS longhands), so the pattern
|
|
366
|
+
* recognizes the `width === height` shape in the BASE condition and rebuilds the element's class
|
|
367
|
+
* StyleMap with a single `size` declaration (the resolver reverse-emits the concrete `size-*` token
|
|
368
|
+
* at codegen). Both longhands are removed and replaced by the merged `size` decl, so the rewrite is
|
|
369
|
+
* idempotent — once collapsed there is no `width`+`height` pair left to re-match.
|
|
370
|
+
*
|
|
371
|
+
* Authored with the declarative {@link pattern} API: the `where` guards exclude opacity barriers,
|
|
372
|
+
* dynamic class lists, and combinator subjects (compress patterns get NO auto-guards); the
|
|
373
|
+
* `rewriteClasses` recipe rebuilds the class StyleMap, returning `null` (decline) unless the BASE
|
|
374
|
+
* width/height are equal, concrete, and share an `!important` flag.
|
|
375
|
+
*/
|
|
376
|
+
/** Fold equal `width`/`height` into the `size-*` utility. */
|
|
377
|
+
declare const sizeShorthand: AuthoredPattern<Captures>;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* AUTO-GENERATED by `scripts/gen-registry.mjs` — DO NOT EDIT BY HAND.
|
|
381
|
+
*
|
|
382
|
+
* Regenerate with `npm run generate` (also runs automatically before build/typecheck/test).
|
|
383
|
+
* Patterns are discovered by the `*.pattern.ts` file convention under `src/flatten` and
|
|
384
|
+
* `src/compress`; the array below is sorted flatten-before-compress.
|
|
385
|
+
*/
|
|
386
|
+
|
|
387
|
+
/** Every built-in pattern, in registration order (flatten patterns before compress). */
|
|
388
|
+
declare const builtinPatterns: readonly Pattern[];
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* domflax — public meta package.
|
|
392
|
+
*
|
|
393
|
+
* Re-exports the entire `@domflax/core` public API (types + reference runtime) and the built-in
|
|
394
|
+
* `@domflax/patterns` library, then layers thin, framework-agnostic build adapters on top
|
|
395
|
+
* (`vite()` / `webpack()`) plus a programmatic `createDomflax()` factory.
|
|
396
|
+
*
|
|
397
|
+
* Each adapter runs the SAME single-file engine as {@link createDomflax} (JSX/TSX frontend + lazy
|
|
398
|
+
* Tailwind/CSS resolver → core pass manager → reverse-emit → JSX backend). The adapters are
|
|
399
|
+
* structurally typed against their bundlers — they never hard-depend on `vite` or `webpack`.
|
|
400
|
+
*
|
|
401
|
+
* Future deps (intentionally NOT imported yet — they land in a later stage):
|
|
402
|
+
* - `@domflax/frontend-html` — HTML / Astro-static frontend feeding the pipeline.
|
|
403
|
+
* - `@domflax/backend-*` — additional surgical codegen backends.
|
|
404
|
+
*/
|
|
405
|
+
|
|
406
|
+
/** How class names resolve to computed styles. */
|
|
407
|
+
type DomflaxProvider = 'auto' | 'tailwind' | 'custom';
|
|
408
|
+
/** Public adapter/factory options (mirrors the documented `domflax({...})` surface). */
|
|
409
|
+
interface DomflaxOptions {
|
|
410
|
+
/** Resolution strategy. Defaults to `'auto'`. */
|
|
411
|
+
readonly provider?: DomflaxProvider;
|
|
412
|
+
/** Stylesheets to parse when `provider` is `'custom'`. */
|
|
413
|
+
readonly cssFiles?: readonly string[];
|
|
414
|
+
/** Preview changes without rewriting source. */
|
|
415
|
+
readonly dryRun?: boolean;
|
|
416
|
+
/** Optimization aggressiveness handed to the pass manager (0 lint … 3 aggressive). */
|
|
417
|
+
readonly safety?: SafetyLevel;
|
|
418
|
+
/** File globs/extensions the adapters should consider. Defaults to jsx/tsx/html. */
|
|
419
|
+
readonly include?: readonly string[];
|
|
420
|
+
}
|
|
421
|
+
/** Fully-resolved options with defaults applied. */
|
|
422
|
+
interface ResolvedDomflaxOptions {
|
|
423
|
+
readonly provider: DomflaxProvider;
|
|
424
|
+
readonly cssFiles: readonly string[];
|
|
425
|
+
readonly dryRun: boolean;
|
|
426
|
+
readonly safety: SafetyLevel;
|
|
427
|
+
readonly include: readonly string[];
|
|
428
|
+
}
|
|
429
|
+
/** Result of a single-file transform. `map` is null until codegen lands. */
|
|
430
|
+
interface DomflaxTransformResult {
|
|
431
|
+
readonly code: string;
|
|
432
|
+
readonly map: EncodedSourceMap | null;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* A configured domflax engine. Holds the wired core {@link Pipeline}, the passthrough
|
|
436
|
+
* {@link StyleResolver}, and the built-in {@link Pattern} set, and exposes a single-file
|
|
437
|
+
* `transform`.
|
|
438
|
+
*/
|
|
439
|
+
interface Domflax {
|
|
440
|
+
readonly options: ResolvedDomflaxOptions;
|
|
441
|
+
readonly pipeline: Pipeline;
|
|
442
|
+
readonly resolver: StyleResolver;
|
|
443
|
+
readonly patterns: readonly Pattern[];
|
|
444
|
+
/**
|
|
445
|
+
* Transform one file. For `.jsx`/`.tsx` this runs the full pipeline (parse → resolve → flatten →
|
|
446
|
+
* reverse-emit → print); every other (or unsupported) file is returned unchanged.
|
|
447
|
+
*/
|
|
448
|
+
transform(code: string, id: string): DomflaxTransformResult;
|
|
449
|
+
}
|
|
450
|
+
declare function createDomflax(options?: DomflaxOptions): Domflax;
|
|
451
|
+
/**
|
|
452
|
+
* Minimal Vite-plugin shape. Declared locally so this adapter does NOT depend on `vite`'s types
|
|
453
|
+
* (an optional, type-only peer). Structurally compatible with Vite's `Plugin` for the hooks domflax
|
|
454
|
+
* uses: `enforce: 'pre'` runs domflax before Vite's JSX→`createElement` transform, and `transform`
|
|
455
|
+
* is Vite's per-file source hook. Returning `null` is Vite's "no change" signal.
|
|
456
|
+
*/
|
|
457
|
+
interface DomflaxVitePlugin {
|
|
458
|
+
readonly name: string;
|
|
459
|
+
readonly enforce: 'pre';
|
|
460
|
+
transform(code: string, id: string): DomflaxTransformResult | null;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Vite adapter. Returns a real Vite `Plugin` (`enforce: 'pre'`) whose `transform` runs the domflax
|
|
464
|
+
* engine on `.jsx`/`.tsx` modules — strips any bundler query suffix (e.g. `App.tsx?used`) before
|
|
465
|
+
* matching, returns `{ code, map }` when the source changed, and `null` (Vite's unchanged signal)
|
|
466
|
+
* for unchanged sources and for any non-jsx/tsx module.
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```js
|
|
470
|
+
* // vite.config.js
|
|
471
|
+
* import domflax from 'domflax';
|
|
472
|
+
* export default { plugins: [domflax.vite({ provider: 'tailwind' })] };
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
475
|
+
declare function vite(options?: DomflaxOptions): DomflaxVitePlugin;
|
|
476
|
+
/** Anything carrying a `module.rules` array — both a webpack `Compiler.options` and Next's bare config. */
|
|
477
|
+
interface DomflaxWebpackModuleHost {
|
|
478
|
+
module?: {
|
|
479
|
+
rules?: unknown[];
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Minimal webpack-compiler shape. Declared locally so this adapter does NOT depend on `webpack`'s
|
|
484
|
+
* types. domflax only needs to push a rule onto the host's `module.rules`.
|
|
485
|
+
*
|
|
486
|
+
* `apply` accepts BOTH shapes: a real webpack `Compiler` (rules live under `compiler.options.module`)
|
|
487
|
+
* AND the bare `config` object Next.js hands you from `webpack(config)` (rules live directly under
|
|
488
|
+
* `config.module`). It duck-types `compiler.options ?? compiler` to find the right host.
|
|
489
|
+
*/
|
|
490
|
+
interface DomflaxWebpackCompiler extends DomflaxWebpackModuleHost {
|
|
491
|
+
options?: DomflaxWebpackModuleHost;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Minimal webpack-plugin shape. `apply(compiler)` is the webpack plugin entry point.
|
|
495
|
+
*/
|
|
496
|
+
interface DomflaxWebpackPlugin {
|
|
497
|
+
readonly name: string;
|
|
498
|
+
apply(compiler: DomflaxWebpackCompiler): void;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* webpack adapter (also the Next.js path). Returns a plugin whose `apply(compiler)` injects a
|
|
502
|
+
* pre-enforced `module.rule` that invokes the domflax {@link ./webpack-loader loader} on every
|
|
503
|
+
* `.jsx`/`.tsx` module. The loader runs the SAME lazy engine as {@link createDomflax} (no eager
|
|
504
|
+
* Tailwind/postcss load).
|
|
505
|
+
*
|
|
506
|
+
* Next.js wiring (`next.config.js`) — Next exposes the underlying webpack config via `webpack(config)`:
|
|
507
|
+
* ```js
|
|
508
|
+
* // next.config.js
|
|
509
|
+
* const domflax = require('domflax');
|
|
510
|
+
* module.exports = {
|
|
511
|
+
* webpack(config) {
|
|
512
|
+
* domflax.webpack({ provider: 'tailwind' }).apply(config);
|
|
513
|
+
* return config;
|
|
514
|
+
* },
|
|
515
|
+
* };
|
|
516
|
+
* ```
|
|
517
|
+
* `apply(compiler)` is intentionally duck-typed on `compiler.options.module.rules`, so it accepts
|
|
518
|
+
* both a real webpack `Compiler` and the bare `config` object Next.js hands you.
|
|
519
|
+
*
|
|
520
|
+
* Caveat: this targets the webpack builder only. **Turbopack is not yet supported** — it does not
|
|
521
|
+
* accept arbitrary webpack loaders, so the `next.config.js` wiring above is a no-op under
|
|
522
|
+
* `next dev --turbopack`. Run domflax through the webpack builder until Turbopack exposes a loader API.
|
|
523
|
+
*/
|
|
524
|
+
declare function webpack(options?: DomflaxOptions): DomflaxWebpackPlugin;
|
|
525
|
+
/**
|
|
526
|
+
* The default-export namespace. Exposes the build adapters and the programmatic factory as an OBJECT
|
|
527
|
+
* so the documented `import domflax from 'domflax'; domflax.vite()` / `domflax.webpack()` works (and a
|
|
528
|
+
* CommonJS `const domflax = require('domflax'); domflax.vite()` too). The named exports
|
|
529
|
+
* (`createDomflax`, `vite`, `webpack`, …) remain available for direct import.
|
|
530
|
+
*/
|
|
531
|
+
interface DomflaxDefault {
|
|
532
|
+
createDomflax(options?: DomflaxOptions): Domflax;
|
|
533
|
+
vite(options?: DomflaxOptions): DomflaxVitePlugin;
|
|
534
|
+
webpack(options?: DomflaxOptions): DomflaxWebpackPlugin;
|
|
535
|
+
}
|
|
536
|
+
/** Default export: an object exposing `vite`, `webpack`, and the programmatic `createDomflax`. */
|
|
537
|
+
declare const domflax: DomflaxDefault;
|
|
538
|
+
|
|
539
|
+
export { ApplyContext, type ApplyOutcome, ApplyResult, Captures, DEFAULT_FIXPOINT, type Domflax, type DomflaxDefault, type DomflaxOptions, type DomflaxProvider, type DomflaxTransformResult, type DomflaxVitePlugin, type DomflaxWebpackCompiler, type DomflaxWebpackPlugin, EncodedSourceMap, FixpointConfig, IRDocument, Pass, PassManager, Pattern, PhaseRunResult, Pipeline, type ResolvedDomflaxOptions, RewriteFactory, RewriteGroup, RewriteOp, SafetyLevel, SelectorIndex, StyleNormalizer, StyleResolver, SyntheticSink, applyGroups, applyOps, buildSelectorIndex, builtinPatterns, cloneDocument, createDomflax, createNullResolver, createNullSelectorIndex, createPassManager, createPipeline, createRewriteFactory, createSyntheticSink, dedupeClasses, domflax as default, emptyStyleDiv, flexCenterWrapper, insetShorthand, marginShorthand, nestedFlexMerge, paddingShorthand, passthroughWrapper, redundantFragment, runPasses, sizeShorthand, syncClassesFromComputed, vite, webpack };
|