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/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { e as IRDocument, d as RewriteOp, I as IRNodeId, h as StyleResolver, g as SelectorIndex, f as SafetyLevel, l as PassPhase, r as RewriteFactory, i as Diagnostic, c as StyleNormalizer, R as RewriteOpDraft, j as SyntheticSink } from './resolve-ops-
|
|
2
|
-
export { A as AttrMap, Q as AttrValue, y as Backref, B as BackrefTable, T as Brand, w as ClassList, U as ClassListForm, W as ClassSegment, X as ClassToken, Y as CommentSpec, u as ConditionKey, C as CssProperty, Z as CssValue, _ as DeclSignature, o as DeepReadonly, D as DiagnosticCode, $ as DistributiveOmit, E as ElementLike, a0 as ElementSpec, a1 as EmitContext, a2 as EmitResult, a3 as ExprKind, a4 as ExprRecord, H as ExprRef, K as ExprRegistry, a5 as ExprSpec, F as FileKind, a6 as FragmentSpec, G as FrontendKind, z as IRComment, p as IRElement, J as IRExpr, L as IRFragment, v as IRNamespace, q as IRNode, a7 as IRNodeBase, a8 as IRNodeKind, O as IRText, M as IdAllocator, a9 as InheritedPropertyTable, x as InlineStyle, N as NodeLike, n as NodeMeta, aa as NodeRefSpec, b as NodeSpec, ab as OpOrigin, ac as OpaqueReason, ad as OpaqueToken, m as PassCategory, ae as PassTraceEntry, P as PatternName, af as Position, s as Reporter, ag as ResolveInput, ah as ResolveResult, ai as ResolverDiagnostic, aj as SelectorUsage, ak as Severity, al as SourceFile, am as SourceFileId, k as SourceSpan, an as StyleBlock, t as StyleCondition, a as StyleConflictPolicy, ao as StyleDecl,
|
|
3
|
-
import { y as ApplyResult, z as RewriteGroup, B as ApplyContext, C as MatchContext, E as FixpointConfig, H as HaltReason, G as Pass, I as PassManager, J as Pattern, K as PhaseRunResult, L as Pipeline, A as AuthoredPattern, N as Captures, O as EncodedSourceMap } from './pattern-
|
|
4
|
-
export { Q as AppliedOp, S as BASE_CONDITION, U as BASE_CONDITION_KEY, V as Backend, W as BackendContext, X as CodegenResult, Y as EditPlan, Z as ElementInit, _ as FlattenGate, $ as Frontend, a0 as FrontendConfig, a1 as FrontendParseContext, a2 as MatchResult, a3 as MutableBackrefTable, a4 as OpValidationIssue, a5 as ParentLayoutContext, a6 as ParseResult, a7 as PatternDoc, a8 as PipelineConfig, a9 as PipelineInput, aa as PipelineOutput, ab as PipelineStats, ac as PreconditionSketch, ad as ReindentSpec, ae as RewriteContext, af as SkippedOpGroup, ag as StructuralInverse, ah as StylePredicate, ai as TextEdit, aj as TreeShapeSketch, ak as childIds, al as conditionKey, am as createBackrefTable, an as createComment, ao as createDocument, ap as createElement, aq as createExpr, ar as createExprRegistry, as as createFragment, at as createIdAllocator, au as createText, av as defaultMeta, aw as elementIds, ax as emptyAttrMap, ay as emptyClassList, az as emptyInlineStyle, l as emptyStyleMap, aA as getElement, aB as getNode, aC as walk } from './pattern-
|
|
1
|
+
import { e as IRDocument, d as RewriteOp, I as IRNodeId, h as StyleResolver, g as SelectorIndex, f as SafetyLevel, l as PassPhase, r as RewriteFactory, i as Diagnostic, c as StyleNormalizer, R as RewriteOpDraft, j as SyntheticSink, S as StyleMap } from './resolve-ops-D8aQina5.cjs';
|
|
2
|
+
export { A as AttrMap, Q as AttrValue, y as Backref, B as BackrefTable, T as Brand, w as ClassList, U as ClassListForm, W as ClassSegment, X as ClassToken, Y as CommentSpec, u as ConditionKey, C as CssProperty, Z as CssValue, _ as DeclSignature, o as DeepReadonly, D as DiagnosticCode, $ as DistributiveOmit, E as ElementLike, a0 as ElementSpec, a1 as EmitContext, a2 as EmitResult, a3 as ExprKind, a4 as ExprRecord, H as ExprRef, K as ExprRegistry, a5 as ExprSpec, F as FileKind, a6 as FragmentSpec, G as FrontendKind, z as IRComment, p as IRElement, J as IRExpr, L as IRFragment, v as IRNamespace, q as IRNode, a7 as IRNodeBase, a8 as IRNodeKind, O as IRText, M as IdAllocator, a9 as InheritedPropertyTable, x as InlineStyle, N as NodeLike, n as NodeMeta, aa as NodeRefSpec, b as NodeSpec, ab as OpOrigin, ac as OpaqueReason, ad as OpaqueToken, m as PassCategory, ae as PassTraceEntry, P as PatternName, af as Position, s as Reporter, ag as ResolveInput, ah as ResolveResult, ai as ResolverDiagnostic, aj as SelectorUsage, ak as Severity, al as SourceFile, am as SourceFileId, k as SourceSpan, an as StyleBlock, t as StyleCondition, a as StyleConflictPolicy, ao as StyleDecl, ap as StyleOrigin, aq as SyntheticClass, ar as TextSpec, as as VisitContext, at as VisitSignal, V as Visitor } from './resolve-ops-D8aQina5.cjs';
|
|
3
|
+
import { y as ApplyResult, z as RewriteGroup, B as ApplyContext, C as MatchContext, E as FixpointConfig, H as HaltReason, G as Pass, I as PassManager, J as Pattern, K as PhaseRunResult, L as Pipeline, A as AuthoredPattern, N as Captures, O as EncodedSourceMap } from './pattern-DotR_dHs.cjs';
|
|
4
|
+
export { Q as AppliedOp, S as BASE_CONDITION, U as BASE_CONDITION_KEY, V as Backend, W as BackendContext, X as CodegenResult, Y as EditPlan, Z as ElementInit, _ as FlattenGate, $ as Frontend, a0 as FrontendConfig, a1 as FrontendParseContext, a2 as MatchResult, a3 as MutableBackrefTable, a4 as OpValidationIssue, a5 as ParentLayoutContext, a6 as ParseResult, a7 as PatternDoc, a8 as PipelineConfig, a9 as PipelineInput, aa as PipelineOutput, ab as PipelineStats, ac as PreconditionSketch, ad as ReindentSpec, ae as RewriteContext, af as SkippedOpGroup, ag as StructuralInverse, ah as StylePredicate, ai as TextEdit, aj as TreeShapeSketch, ak as childIds, al as conditionKey, am as createBackrefTable, an as createComment, ao as createDocument, ap as createElement, aq as createExpr, ar as createExprRegistry, as as createFragment, at as createIdAllocator, au as createText, av as defaultMeta, aw as elementIds, ax as emptyAttrMap, ay as emptyClassList, az as emptyInlineStyle, l as emptyStyleMap, aA as getElement, aB as getNode, aC as walk } from './pattern-DotR_dHs.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @domflax/core — applier runtime helpers (shared by the per-op handlers in `./apply`).
|
|
@@ -237,65 +237,121 @@ declare function createPipeline(): Pipeline;
|
|
|
237
237
|
*/
|
|
238
238
|
|
|
239
239
|
/**
|
|
240
|
-
* Fold
|
|
241
|
-
*
|
|
240
|
+
* Fold each rewritable element's computed style back into the MINIMAL static class-token set — the
|
|
241
|
+
* general compress engine (see module docs + {@link import('./compress-engine')}). Mutates `doc`.
|
|
242
|
+
*
|
|
243
|
+
* TWO kinds of element are processed, and their guarantees differ:
|
|
244
|
+
*
|
|
245
|
+
* • STYLE-DIRTY — a pass rewrote this element's own computed style (a flatten fold / merge). Its
|
|
246
|
+
* computed CHANGED, so its classes MUST be re-derived to represent the new style (which may
|
|
247
|
+
* legitimately need MORE tokens than before). Handled exactly as it always was.
|
|
248
|
+
*
|
|
249
|
+
* • COMPRESS-ONLY — no pass touched it; we run the exact-cover engine purely to SHORTEN its class
|
|
250
|
+
* string (`px-4 py-4 → p-4`, drop a redundant class, pick a custom class that covers the same
|
|
251
|
+
* style, …). This is a pure class-string rewrite that must NEVER change the render or GROW the
|
|
252
|
+
* output, so it carries two extra hard backstops below: the rewritten set must re-resolve to the
|
|
253
|
+
* element's exact computed style, and it must not be longer than the original. A structural
|
|
254
|
+
* bystander with no compression opportunity therefore keeps its `class` attribute byte-for-byte.
|
|
242
255
|
*/
|
|
243
256
|
declare function syncClassesFromComputed(doc: IRDocument, resolver: StyleResolver, norm: StyleNormalizer): void;
|
|
244
257
|
|
|
245
258
|
/**
|
|
246
|
-
* @domflax/
|
|
259
|
+
* @domflax/core — the general COMPRESS ENGINE: a minimal-string exact-cover solver.
|
|
247
260
|
*
|
|
248
|
-
*
|
|
261
|
+
* ## What it replaces
|
|
249
262
|
*
|
|
250
|
-
*
|
|
263
|
+
* The hand-written compress patterns (padding/margin/inset/size/gap/place/border/overflow/…-shorthand
|
|
264
|
+
* and dedupe-classes) each recognised ONE shorthand shape and folded it. This module subsumes them
|
|
265
|
+
* ALL with a SINGLE, provider-uniform algorithm: given an element's target computed style, find the
|
|
266
|
+
* class set that reproduces it EXACTLY with the SHORTEST total `class="…"` string, searching the whole
|
|
267
|
+
* vocabulary (every Tailwind utility AND the project's custom-CSS classes at once).
|
|
251
268
|
*
|
|
252
|
-
*
|
|
253
|
-
* they were direct children of the element's parent. A `display:contents` wrapper with a single
|
|
254
|
-
* element child is therefore already a layout passthrough: it contributes nothing to flow, paint
|
|
255
|
-
* (a contents box paints nothing), formatting, stacking, or containing-block resolution. Removing it
|
|
256
|
-
* and hoisting the child produces a tree that is layout-identical — the wrapper's only remaining
|
|
257
|
-
* effect was inheritance, which is preserved by folding inheritable declarations onto the child first.
|
|
269
|
+
* ## The algorithm (per element, per style-condition — all folded into one solve)
|
|
258
270
|
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
271
|
+
* Given a normalized target StyleMap `U`:
|
|
272
|
+
* 1. UNIVERSE = the set of `(conditionKey, property, value, important)` tuples in `U`
|
|
273
|
+
* (a `tupleKey` per {@link tupleKey}).
|
|
274
|
+
* 2. CANDIDATES = the vocabulary classes whose FULL normalized-longhand declaration set is a SUBSET
|
|
275
|
+
* of `U` (never introduces a declaration `U` does not already contain). The caller feeds the
|
|
276
|
+
* vocabulary; the element's own droppable tokens are part of it, guaranteeing feasibility and the
|
|
277
|
+
* "never worse than the original" property.
|
|
278
|
+
* 3. COST(class) = token length + 1 (the token plus its joining space) — so minimizing total cost
|
|
279
|
+
* minimizes the rendered `class="…"` byte length exactly.
|
|
280
|
+
* 4. MIN-COST EXACT COVER via bitmask DP over `U`'s tuples: `dp[coveredMask]` = least cost reaching
|
|
281
|
+
* that coverage; each transition adds one candidate's mask. Because every candidate AGREES with
|
|
282
|
+
* `U` on every tuple it sets, ANY full cover reproduces `U` at the tuple level.
|
|
283
|
+
* 5. `|U|` is BOUNDED ({@link DEFAULT_MAX_UNIVERSE}); a larger condition-block returns `null` so the
|
|
284
|
+
* caller falls back to its greedy emit for that element.
|
|
264
285
|
*
|
|
265
|
-
* (
|
|
266
|
-
* `
|
|
267
|
-
*
|
|
286
|
+
* The **correctness backstop** (re-resolve the chosen set and assert it equals `U` exactly) lives in
|
|
287
|
+
* each resolver's `emit` — it owns the forward `resolve`, and running the check there keeps this core
|
|
288
|
+
* helper pure and provider-agnostic. A chosen set that fails the backstop is discarded and the greedy
|
|
289
|
+
* emit is used instead, so a set that does not reproduce `U` is NEVER emitted.
|
|
268
290
|
*/
|
|
291
|
+
|
|
269
292
|
/**
|
|
270
|
-
*
|
|
271
|
-
*
|
|
293
|
+
* The canonical key for one normalized declaration under one style condition: the atomic unit both the
|
|
294
|
+
* target universe and every vocabulary class are expressed in. Equal keys ⇔ the SAME declaration.
|
|
272
295
|
*/
|
|
273
|
-
declare
|
|
274
|
-
|
|
296
|
+
declare function tupleKey(condition: string, property: string, value: string, important: boolean): string;
|
|
275
297
|
/**
|
|
276
|
-
* @
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
298
|
+
* Flatten a StyleMap into its set of {@link tupleKey}s (normalizing first). This is how BOTH the target
|
|
299
|
+
* universe and each vocabulary class's declarations are lowered, so a class's tuples can be tested for
|
|
300
|
+
* subset-membership in the universe by plain string equality.
|
|
301
|
+
*/
|
|
302
|
+
declare function styleMapTuples(map: StyleMap, norm: StyleNormalizer): string[];
|
|
303
|
+
/** One vocabulary entry: a class token and the {@link tupleKey}s its full declaration set produces. */
|
|
304
|
+
interface CoverClass {
|
|
305
|
+
readonly token: string;
|
|
306
|
+
readonly tuples: readonly string[];
|
|
307
|
+
}
|
|
308
|
+
interface MinCoverOptions {
|
|
309
|
+
/** Upper bound on `|U|`; above it the DP is skipped (`null`) so the caller uses its greedy emit. */
|
|
310
|
+
readonly maxUniverse?: number;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* The largest universe the bitmask DP will solve. 20 tuples ⇒ a `2^20` (~1M) DP table, comfortably
|
|
314
|
+
* fast and bounded in memory; a heavier element (rare) falls back to the resolver's greedy emit.
|
|
315
|
+
*/
|
|
316
|
+
declare const DEFAULT_MAX_UNIVERSE = 20;
|
|
317
|
+
/**
|
|
318
|
+
* Solve the minimal-string exact cover of `universe` using `vocabulary`.
|
|
283
319
|
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
* be unwrapped into its sole child.
|
|
320
|
+
* Returns the chosen class tokens (sorted, de-duplicated) whose union reproduces `universe` EXACTLY at
|
|
321
|
+
* least total string cost, or `null` when there is no exact cover OR the universe exceeds the bound (in
|
|
322
|
+
* both cases the caller falls back to its greedy emit). An empty universe yields `[]`.
|
|
288
323
|
*
|
|
289
|
-
*
|
|
290
|
-
* guards (ref/handlers/dynamic-children/raw-html/combinator/reparent-impact) are applied
|
|
291
|
-
* automatically for every `flatten/*` pattern; the `where` predicates below add the LAYOUT-neutrality
|
|
292
|
-
* requirements specific to this pattern (no non-block display, no box/formatting/stacking context, no
|
|
293
|
-
* containing block, no custom-property coupling, no structural-pseudo targeting).
|
|
324
|
+
* Pure and provider-agnostic: the caller performs the re-resolve correctness backstop.
|
|
294
325
|
*/
|
|
326
|
+
declare function minStringCover(universe: readonly string[], vocabulary: Iterable<CoverClass>, options?: MinCoverOptions): readonly string[] | null;
|
|
327
|
+
|
|
295
328
|
/**
|
|
296
|
-
*
|
|
329
|
+
* domflax — build-end optimization SUMMARY.
|
|
330
|
+
*
|
|
331
|
+
* A tiny, dependency-free formatter shared by the Vite and webpack/Next adapters. Each adapter
|
|
332
|
+
* accumulates {@link FileStatDelta} numbers across the build into a {@link Totals}, then prints ONE
|
|
333
|
+
* boxed {@link renderSummary} block at build end — so the user sees the aggregate payoff without any
|
|
334
|
+
* per-file spam in between.
|
|
335
|
+
*
|
|
336
|
+
* ```
|
|
337
|
+
* ▲ domflax
|
|
338
|
+
* ────────────────────────────────
|
|
339
|
+
* files optimized 42
|
|
340
|
+
* DOM nodes removed 318
|
|
341
|
+
* classes compressed 1,204
|
|
342
|
+
* size saved 18.7 KB
|
|
343
|
+
* ────────────────────────────────
|
|
344
|
+
* ```
|
|
297
345
|
*/
|
|
298
|
-
|
|
346
|
+
/** Per-file optimization delta (from a single {@link Domflax.transform}). */
|
|
347
|
+
interface FileStatDelta {
|
|
348
|
+
/** DOM/IR nodes removed by provably-safe flattens. */
|
|
349
|
+
readonly nodesRemoved: number;
|
|
350
|
+
/** Class tokens eliminated by semantic compression. */
|
|
351
|
+
readonly classesSaved: number;
|
|
352
|
+
/** Bytes saved = original byte length − output byte length (may be negative in edge cases). */
|
|
353
|
+
readonly bytesSaved: number;
|
|
354
|
+
}
|
|
299
355
|
|
|
300
356
|
/**
|
|
301
357
|
* @domflax/patterns — flatten pattern: `flex-center-wrapper`.
|
|
@@ -320,108 +376,6 @@ declare const emptyStyleDiv: AuthoredPattern<Captures>;
|
|
|
320
376
|
*/
|
|
321
377
|
declare const flexCenterWrapper: AuthoredPattern<Captures>;
|
|
322
378
|
|
|
323
|
-
/**
|
|
324
|
-
* @domflax/patterns — flatten pattern: `inline-flex-center-wrapper`.
|
|
325
|
-
*
|
|
326
|
-
* Collapses the inline-flex flavour of the "centering wrapper" idiom
|
|
327
|
-
*
|
|
328
|
-
* <div style="display:inline-flex; align-items:center; justify-content:center"><Child/></div>
|
|
329
|
-
*
|
|
330
|
-
* into its sole child, pushing the centering intent down onto the child as `place-self: center`.
|
|
331
|
-
* Like its block-level `flex-center-wrapper` sibling the wrapper only exists to center one element;
|
|
332
|
-
* once `place-self:center` lives on the child the wrapper is pure structural noise and can go.
|
|
333
|
-
*
|
|
334
|
-
* Authored with the declarative {@link definePattern} API: the match is the inline-flex-centering
|
|
335
|
-
* computed-style signature on a single-element-child `<div>` that paints nothing of its own; the
|
|
336
|
-
* recipe folds inheritable styles onto the child, grants it `place-self:center`, then unwraps the
|
|
337
|
-
* wrapper (id-preserving). The opacity-barrier + selector-safety guards are applied automatically by
|
|
338
|
-
* the `definePattern` factory for every `flatten/*` pattern.
|
|
339
|
-
*/
|
|
340
|
-
/**
|
|
341
|
-
* Flatten an inline-flex-centering `<div>` wrapper into its sole element child, granting the child
|
|
342
|
-
* `place-self:center`.
|
|
343
|
-
*/
|
|
344
|
-
declare const inlineFlexCenterWrapper: AuthoredPattern<Captures>;
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* @domflax/patterns — flatten pattern: `nested-flex-merge`.
|
|
348
|
-
*
|
|
349
|
-
* Collapses a redundant nesting of two flex containers
|
|
350
|
-
*
|
|
351
|
-
* <div style="display:flex; align-items:center; gap:8px">
|
|
352
|
-
* <div style="display:flex; flex-direction:column"> … </div>
|
|
353
|
-
* </div>
|
|
354
|
-
*
|
|
355
|
-
* where the OUTER flex container's sole element child is ITSELF a flex container, into a single
|
|
356
|
-
* flex container that carries the union of both elements' flex declarations. The outer wrapper's
|
|
357
|
-
* box is then structural noise (it paints nothing and only establishes a flex context that the
|
|
358
|
-
* merged child now also establishes), so it is removed.
|
|
359
|
-
*
|
|
360
|
-
* Authored with the declarative {@link pattern} API: the match is a flex `<div>` with a single
|
|
361
|
-
* element child painting nothing of its own (auto-guarded against opacity barriers / combinator
|
|
362
|
-
* targeting like every `flatten/*` pattern). The value-relational reasoning — the child must also
|
|
363
|
-
* be a (non-combinator) flex container, the wrapper must carry only transferable flex/inheritable
|
|
364
|
-
* declarations, and the two must not conflict on any shared flex property — lives in the `rewrite`
|
|
365
|
-
* op-draft factory escape hatch, which folds inherited styles, transfers the wrapper's flex
|
|
366
|
-
* declarations onto the child (target-wins), then unwraps the wrapper.
|
|
367
|
-
*/
|
|
368
|
-
/**
|
|
369
|
-
* Flatten a flex container whose sole child is a compatible flex container into a single container.
|
|
370
|
-
*/
|
|
371
|
-
declare const nestedFlexMerge: AuthoredPattern<Captures>;
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* @domflax/patterns — flatten pattern: `nested-grid-merge`.
|
|
375
|
-
*
|
|
376
|
-
* Collapses a redundant nesting of two grid containers
|
|
377
|
-
*
|
|
378
|
-
* <div style="display:grid; gap:8px">
|
|
379
|
-
* <div style="display:grid; grid-template-columns:1fr 1fr"> … </div>
|
|
380
|
-
* </div>
|
|
381
|
-
*
|
|
382
|
-
* where the OUTER grid container's sole element child is ITSELF a grid container, into a single grid
|
|
383
|
-
* container carrying the union of both elements' grid declarations. The outer wrapper's box is then
|
|
384
|
-
* structural noise (it paints nothing and only establishes a grid context the merged child now also
|
|
385
|
-
* establishes), so it is removed.
|
|
386
|
-
*
|
|
387
|
-
* This is the grid analogue of `nested-flex-merge`. The declarative match is a grid `<div>` with a
|
|
388
|
-
* single element child painting nothing of its own (auto-guarded against opacity barriers / combinator
|
|
389
|
-
* targeting like every `flatten/*` pattern). The value-relational reasoning — the child must also be a
|
|
390
|
-
* (non-combinator) grid container, the wrapper must carry only transferable grid/inheritable
|
|
391
|
-
* declarations, and the two must not conflict on any shared grid property — lives in the `rewrite`
|
|
392
|
-
* op-draft factory escape hatch, which folds inherited styles, transfers the wrapper's grid
|
|
393
|
-
* declarations onto the child (target-wins), then unwraps the wrapper.
|
|
394
|
-
*/
|
|
395
|
-
/**
|
|
396
|
-
* Flatten a grid container whose sole child is a compatible grid container into a single container.
|
|
397
|
-
*/
|
|
398
|
-
declare const nestedGridMerge: AuthoredPattern<Captures>;
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* @domflax/patterns — flatten pattern: `passthrough-wrapper`.
|
|
402
|
-
*
|
|
403
|
-
* Collapses a purely-structural wrapper that exists for no reason at all:
|
|
404
|
-
*
|
|
405
|
-
* <div><Child/></div>
|
|
406
|
-
*
|
|
407
|
-
* The wrapper paints nothing, establishes no box / formatting / stacking context, carries no
|
|
408
|
-
* attributes beyond an (optional) inert class, holds exactly one element child, and is free of every
|
|
409
|
-
* opacity barrier (ref / event-handlers / dynamic children / dangerous html / spread / component).
|
|
410
|
-
* Such a `<div>` is pure DOM noise: removing it and hoisting the child is invisible to both paint
|
|
411
|
-
* and layout.
|
|
412
|
-
*
|
|
413
|
-
* Authored with the declarative {@link definePattern} API. The opacity-barrier + selector-safety
|
|
414
|
-
* guards (ref/handlers/dynamic-children/raw-html/combinator/reparent-impact) are applied
|
|
415
|
-
* automatically for every `flatten/*` pattern; the `where` predicates add the passthrough-specific
|
|
416
|
-
* requirements (no box/formatting/stacking context, no own attrs, no dynamic/spread classes, not a
|
|
417
|
-
* component, not a structural-pseudo subject).
|
|
418
|
-
*/
|
|
419
|
-
/**
|
|
420
|
-
* Flatten a do-nothing `<div>` wrapper into its sole element child, folding any inheritable styles
|
|
421
|
-
* down first so inherited values survive the box removal.
|
|
422
|
-
*/
|
|
423
|
-
declare const passthroughWrapper: AuthoredPattern<Captures>;
|
|
424
|
-
|
|
425
379
|
/**
|
|
426
380
|
* @domflax/patterns — flatten pattern: `redundant-fragment`.
|
|
427
381
|
*
|
|
@@ -447,378 +401,167 @@ declare const passthroughWrapper: AuthoredPattern<Captures>;
|
|
|
447
401
|
declare const redundantFragment: AuthoredPattern<Captures>;
|
|
448
402
|
|
|
449
403
|
/**
|
|
450
|
-
* @domflax/patterns — flatten pattern: `
|
|
404
|
+
* @domflax/patterns — flatten pattern: `grid-center-wrapper`.
|
|
451
405
|
*
|
|
452
|
-
* Collapses
|
|
406
|
+
* Collapses the grid flavour of the "centering wrapper" idiom
|
|
453
407
|
*
|
|
454
|
-
* <
|
|
408
|
+
* <div style="display:grid; align-items:center; justify-content:center"><Child/></div>
|
|
455
409
|
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
* hoisting the child leaves both paint and layout untouched (the surviving child folds the inheritable
|
|
460
|
-
* declarations the span carried).
|
|
410
|
+
* into its sole child, pushing the centering intent down onto the child as `place-self:center`. This is
|
|
411
|
+
* the grid analogue of `flex-center-wrapper`: the wrapper only exists to center one element, and once
|
|
412
|
+
* `place-self:center` lives on the child the wrapper is pure structural noise.
|
|
461
413
|
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
* component, not a structural-pseudo subject).
|
|
467
|
-
*/
|
|
468
|
-
/**
|
|
469
|
-
* Flatten a do-nothing inline `<span>` wrapper into its sole element child, folding any inheritable
|
|
470
|
-
* styles down first so inherited values survive the box removal.
|
|
471
|
-
*/
|
|
472
|
-
declare const redundantInlineWrapper: AuthoredPattern<Captures>;
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* @domflax/patterns — compress pattern: `border-radius-shorthand`.
|
|
476
|
-
*
|
|
477
|
-
* Collapses an element whose four corner radii are expressed as separate longhand declarations and
|
|
478
|
-
* are ALL EQUAL into the single CSS `border-radius` shorthand:
|
|
479
|
-
*
|
|
480
|
-
* border-top-left-radius:0.5rem; border-top-right-radius:0.5rem;
|
|
481
|
-
* border-bottom-right-radius:0.5rem; border-bottom-left-radius:0.5rem
|
|
482
|
-
* ⇒ border-radius:0.5rem (Tailwind `rounded-lg`)
|
|
483
|
-
*
|
|
484
|
-
* The IR's computed StyleMap keeps each corner as its own longhand (Tailwind's `rounded-tl-*` /
|
|
485
|
-
* `rounded-tr-*` / … each resolve to one corner property). This pass runs the collapse in reverse on
|
|
486
|
-
* the computed map ONLY when all four corners share one value — the single case that maps cleanly to
|
|
487
|
-
* a single Tailwind utility (the CSS 2-value `border-radius` form is DIAGONAL, which has no clean
|
|
488
|
-
* `rounded-*` edge utility, so per-corner differences are intentionally left alone). Rebuilding the
|
|
489
|
-
* map with one `border-radius` decl lets the minimizing reverse-emit pick the single `rounded-*`
|
|
490
|
-
* token covering all four corners instead of two edge tokens.
|
|
491
|
-
*
|
|
492
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
493
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
494
|
-
* HTML never blocks a class-only rewrite); the
|
|
495
|
-
* `rewriteClasses` recipe rebuilds the class StyleMap, declining (`null`) unless the four corners are
|
|
496
|
-
* present, concrete, equal, and share an `!important` flag.
|
|
497
|
-
*/
|
|
498
|
-
/** Fold four equal corner radii into the single `border-radius` shorthand. */
|
|
499
|
-
declare const borderRadiusShorthand: AuthoredPattern<Captures>;
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* @domflax/patterns — compress pattern: `border-shorthand`.
|
|
503
|
-
*
|
|
504
|
-
* Collapses an element whose four border-side WIDTHS are expressed as separate longhand declarations
|
|
505
|
-
* back into the shortest equivalent `border-width` shorthand:
|
|
506
|
-
*
|
|
507
|
-
* border-top-width:2px; border-right-width:2px; border-bottom-width:2px; border-left-width:2px
|
|
508
|
-
* ⇒ border-width:2px (Tailwind `border-2`)
|
|
509
|
-
*
|
|
510
|
-
* border-top-width:2px; border-bottom-width:2px; border-left-width:4px; border-right-width:4px
|
|
511
|
-
* ⇒ border-width:2px 4px (Tailwind `border-y-2 border-x-4`)
|
|
512
|
-
*
|
|
513
|
-
* Tailwind's per-side / per-axis width utilities (`border-t-*`, `border-x-*`, …) each resolve to the
|
|
514
|
-
* matching `border-*-width` longhand(s); the shared normalizer keeps them longhand. This pass runs
|
|
515
|
-
* the expansion in reverse on the computed map ONLY when the four widths fold cleanly into a 1- or
|
|
516
|
-
* 2-value form — i.e. `top===bottom` AND `left===right`. Rebuilding the map with one `border-width`
|
|
517
|
-
* shorthand lets the minimizing reverse-emit pick the single/paired utility (`border-2`, or
|
|
518
|
-
* `border-x-* border-y-*`) instead of four per-side tokens. Only WIDTH is folded — border style and
|
|
519
|
-
* color are independent longhands the resolver carries separately, so this never disturbs them.
|
|
520
|
-
*
|
|
521
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
522
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
523
|
-
* HTML never blocks a class-only rewrite); the `rewriteClasses`
|
|
524
|
-
* recipe rebuilds the class StyleMap, declining (`null`) unless the four widths fold cleanly.
|
|
525
|
-
*/
|
|
526
|
-
/** Compress an element's four equal/paired border-width longhands into the shortest shorthand. */
|
|
527
|
-
declare const borderShorthand: AuthoredPattern<Captures>;
|
|
528
|
-
|
|
529
|
-
/**
|
|
530
|
-
* @domflax/patterns — compress pattern: `dedupe-classes`.
|
|
531
|
-
*
|
|
532
|
-
* Removes duplicate / fully-overridden class tokens that resolve to the same property where a
|
|
533
|
-
* LATER token wins, leaving the minimal set of tokens with an IDENTICAL computed style. The
|
|
534
|
-
* canonical case:
|
|
535
|
-
*
|
|
536
|
-
* <p class="text-sm text-lg">…</p> → <p class="text-lg">…</p>
|
|
537
|
-
*
|
|
538
|
-
* Both `text-sm` and `text-lg` set `font-size`; resolution already made `text-lg` win, so the
|
|
539
|
-
* computed `font-size` is `text-lg`'s value and `text-sm` contributes NOTHING to the final
|
|
540
|
-
* computed style. The earlier token is pure noise and can be dropped without changing a pixel.
|
|
541
|
-
*
|
|
542
|
-
* How redundancy is detected (purely from the already-resolved, normalized computed StyleMap):
|
|
543
|
-
* • every declaration carries provenance — `origin` (the winning token) and `shadowed`
|
|
544
|
-
* (the tokens it overrode);
|
|
545
|
-
* • a class token is FULLY OVERRIDDEN iff it appears in some declaration's `shadowed` list but
|
|
546
|
-
* is NOT the winning `origin` of any declaration across ANY style condition. Such a token can
|
|
547
|
-
* be deleted with zero effect on the computed style.
|
|
548
|
-
*
|
|
549
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
550
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
551
|
-
* HTML never blocks a class-only rewrite); the `dropClasses` recipe returns the set of
|
|
552
|
-
* fully-overridden, resolver-droppable tokens to delete (their `shadowed` provenance is pruned
|
|
553
|
-
* automatically before the minimal class StyleMap is re-installed).
|
|
554
|
-
*/
|
|
555
|
-
/**
|
|
556
|
-
* Collapse a class list to the minimal token set that yields an identical computed style, by
|
|
557
|
-
* dropping tokens whose declarations are fully overridden by later tokens.
|
|
558
|
-
*/
|
|
559
|
-
declare const dedupeClasses: AuthoredPattern<Captures>;
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* @domflax/patterns — compress pattern: `gap-shorthand`.
|
|
563
|
-
*
|
|
564
|
-
* Collapses an element whose grid/flex gutters are expressed as two equal axis longhands back into
|
|
565
|
-
* the single `gap` shorthand:
|
|
566
|
-
*
|
|
567
|
-
* row-gap:16px; column-gap:16px ⇒ gap:16px (Tailwind `gap-x-4 gap-y-4` → `gap-4`)
|
|
568
|
-
*
|
|
569
|
-
* The IR's computed StyleMap is canonically LONGHAND (the shared normalizer expands the `gap`
|
|
570
|
-
* shorthand into `row-gap` + `column-gap` at parse time). This pass runs the expansion in reverse on
|
|
571
|
-
* the computed map ONLY when both axes carry the SAME value and `!important` flag — i.e. when the two
|
|
572
|
-
* gutters genuinely fold into a single-value `gap`. When the axes differ it declines, leaving the two
|
|
573
|
-
* longhands verbatim (an asymmetric gutter has no equivalent single-value shorthand).
|
|
574
|
-
*
|
|
575
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
576
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
577
|
-
* HTML never blocks a class-only rewrite); the
|
|
578
|
-
* `rewriteClasses` recipe rebuilds the class StyleMap, declining (`null`) unless the two axis gaps
|
|
579
|
-
* are present, equal, and share an `!important` flag.
|
|
580
|
-
*/
|
|
581
|
-
/** Fold an equal `row-gap`/`column-gap` pair into the single `gap` shorthand. */
|
|
582
|
-
declare const gapShorthand: AuthoredPattern<Captures>;
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* @domflax/patterns — compress pattern: `inset-shorthand`.
|
|
414
|
+
* Authored with the declarative {@link definePattern} API: the match is the grid-centering computed-style
|
|
415
|
+
* signature on a single-element-child `<div>` that paints nothing of its own; the recipe folds
|
|
416
|
+
* inheritable styles onto the child, grants it `place-self:center`, then unwraps the wrapper. The
|
|
417
|
+
* opacity-barrier + selector-safety guards are auto-applied for every `flatten/*` pattern.
|
|
586
418
|
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
* • top == bottom (a matching pair) → `inset-block: <v>` (Tailwind `inset-y-*`)
|
|
592
|
-
* • left == right (a matching pair) → `inset-inline: <v>` (Tailwind `inset-x-*`)
|
|
593
|
-
*
|
|
594
|
-
* The two axis collapses are independent: an element whose `top == bottom` but `left != right`
|
|
595
|
-
* collapses only the block axis and keeps the `left`/`right` longhands verbatim. When nothing
|
|
596
|
-
* collapses (all four distinct, or fewer than a full pair present) the pattern declines.
|
|
597
|
-
*
|
|
598
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
599
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
600
|
-
* HTML never blocks a class-only rewrite); the `rewriteClasses` recipe rebuilds the class
|
|
601
|
-
* StyleMap, declining (`null`) unless at least one inset axis collapses.
|
|
419
|
+
* Genuinely additive under the conservative gate: unlike a plain passthrough (which the gate REVERTS on
|
|
420
|
+
* a grid wrapper because grid establishes a formatting context), the compensating `place-self:center`
|
|
421
|
+
* makes the flatten `provably-safe` — but ONLY when the child's NEW parent is a statically-known grid
|
|
422
|
+
* that lets the wrapper fill its area (the ONE context where the child's `justify-self` is honored).
|
|
602
423
|
*/
|
|
603
424
|
/**
|
|
604
|
-
*
|
|
605
|
-
*
|
|
425
|
+
* Flatten a grid-centering `<div>` wrapper into its sole element child, granting the child
|
|
426
|
+
* `place-self:center`.
|
|
606
427
|
*/
|
|
607
|
-
declare const
|
|
428
|
+
declare const gridCenterWrapper: AuthoredPattern<Captures>;
|
|
608
429
|
|
|
609
430
|
/**
|
|
610
|
-
* @domflax/patterns —
|
|
611
|
-
*
|
|
612
|
-
* Collapses the four explicit margin longhands
|
|
431
|
+
* @domflax/patterns — flatten pattern: `display-contents-wrapper`.
|
|
613
432
|
*
|
|
614
|
-
*
|
|
433
|
+
* Collapses a wrapper that has explicitly opted OUT of generating a box:
|
|
615
434
|
*
|
|
616
|
-
*
|
|
617
|
-
* `padding-shorthand`, covering the `m` / `mx` / `my` collapse), choosing the shortest legal
|
|
618
|
-
* 1–4-value form:
|
|
435
|
+
* <div style="display:contents"><Child/></div> → <Child/>
|
|
619
436
|
*
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
437
|
+
* `display:contents` makes an element generate NO box of its own — its children render exactly as if
|
|
438
|
+
* they were direct children of the element's parent. A `display:contents` wrapper with a single
|
|
439
|
+
* element child is therefore already a layout passthrough: it contributes nothing to flow, paint
|
|
440
|
+
* (a contents box paints nothing), formatting, stacking, or containing-block resolution. Removing it
|
|
441
|
+
* and hoisting the child produces a tree that is layout-identical — the wrapper's only remaining
|
|
442
|
+
* effect was inheritance, which is preserved by folding inheritable declarations onto the child first.
|
|
624
443
|
*
|
|
625
|
-
*
|
|
626
|
-
*
|
|
444
|
+
* This is the safest possible wrapper-elimination: the box being removed provably did not exist.
|
|
445
|
+
* The opacity-barrier + selector-safety guards (ref/handlers/dynamic-children/raw-html/combinator/
|
|
446
|
+
* reparent-impact) are auto-applied for every `flatten/*` pattern; the `where` predicates add the
|
|
447
|
+
* passthrough-specific requirements (no own attrs / dynamic-or-spread classes, no `var()` coupling,
|
|
448
|
+
* not a component, not a structural-pseudo subject).
|
|
627
449
|
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
630
|
-
*
|
|
631
|
-
* StyleMap, declining (`null`) unless all four margin longhands are present with a uniform
|
|
632
|
-
* (non-)`!important` flag.
|
|
450
|
+
* (Chosen as the safe variant of the size-hoisting "full-size passthrough" idea: hoisting an explicit
|
|
451
|
+
* `width/height:100%` onto a child is only sound when the child is block-level and unsized, which is
|
|
452
|
+
* not knowable from the wrapper alone — whereas a `display:contents` box is a passthrough by definition.)
|
|
633
453
|
*/
|
|
634
454
|
/**
|
|
635
|
-
*
|
|
455
|
+
* Flatten a `display:contents` wrapper (a box that generates no box) into its sole element child,
|
|
456
|
+
* folding any inheritable styles down first so inherited values survive the removal.
|
|
636
457
|
*/
|
|
637
|
-
declare const
|
|
458
|
+
declare const displayContentsWrapper: AuthoredPattern<Captures>;
|
|
638
459
|
|
|
639
460
|
/**
|
|
640
|
-
* @domflax/patterns —
|
|
461
|
+
* @domflax/patterns — flatten pattern: `empty-style-div`.
|
|
641
462
|
*
|
|
642
|
-
* Collapses
|
|
643
|
-
*
|
|
463
|
+
* Collapses the most common piece of structural noise of all: a `<div>` whose ONLY role is to wrap
|
|
464
|
+
* a single child while contributing nothing to layout or paint —
|
|
644
465
|
*
|
|
645
|
-
*
|
|
646
|
-
*
|
|
466
|
+
* <div><Child/></div> (no styles at all)
|
|
467
|
+
* <div style="display:block"><Child/></div> (the default; still a no-op box)
|
|
647
468
|
*
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
* overflow-y`) has no single-keyword `overflow` equivalent and is declined.
|
|
469
|
+
* Such a div is layout-neutral: it is a plain block box with no own visual style, establishes no
|
|
470
|
+
* box / formatting / stacking context, is not a containing block, and declares no custom properties
|
|
471
|
+
* a descendant might read. Its box is therefore indistinguishable from "not being there", so it can
|
|
472
|
+
* be unwrapped into its sole child.
|
|
653
473
|
*
|
|
654
|
-
* Authored with the declarative {@link
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
474
|
+
* Authored with the declarative {@link definePattern} API. The opacity-barrier + selector-safety
|
|
475
|
+
* guards (ref/handlers/dynamic-children/raw-html/combinator/reparent-impact) are applied
|
|
476
|
+
* automatically for every `flatten/*` pattern; the `where` predicates below add the LAYOUT-neutrality
|
|
477
|
+
* requirements specific to this pattern (no non-block display, no box/formatting/stacking context, no
|
|
478
|
+
* containing block, no custom-property coupling, no structural-pseudo targeting).
|
|
659
479
|
*/
|
|
660
|
-
/** Fold an equal `overflow-x`/`overflow-y` pair into the single `overflow` shorthand. */
|
|
661
|
-
declare const overflowShorthand: AuthoredPattern<Captures>;
|
|
662
|
-
|
|
663
480
|
/**
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
* Collapses an element whose two overscroll-behavior axes are expressed as separate longhand
|
|
667
|
-
* declarations and are EQUAL into the single CSS `overscroll-behavior` shorthand:
|
|
668
|
-
*
|
|
669
|
-
* overscroll-behavior-x:contain; overscroll-behavior-y:contain
|
|
670
|
-
* ⇒ overscroll-behavior:contain (Tailwind `overscroll-x-contain overscroll-y-contain` → `overscroll-contain`)
|
|
671
|
-
*
|
|
672
|
-
* Tailwind's `overscroll-x-*` / `overscroll-y-*` utilities each resolve to the matching
|
|
673
|
-
* `overscroll-behavior-{x,y}` axis longhand, and the shared normalizer keeps `overscroll-behavior`
|
|
674
|
-
* un-expanded (it is NOT one of the box/gap shorthands the normalizer splits). So only the equal-axis
|
|
675
|
-
* form maps cleanly to a single `overscroll-*` utility. This pass runs the collapse in reverse on the
|
|
676
|
-
* computed map ONLY when both axes carry the SAME value and `!important` flag, replacing them with one
|
|
677
|
-
* `overscroll-behavior` decl so the minimizing reverse-emit can pick a single `overscroll-*` token
|
|
678
|
-
* instead of two axis tokens. When the axes differ it declines, leaving the two longhands verbatim.
|
|
679
|
-
*
|
|
680
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
681
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
682
|
-
* HTML never blocks a class-only rewrite); the
|
|
683
|
-
* `rewriteClasses` recipe rebuilds the class StyleMap, declining (`null`) unless both axes are
|
|
684
|
-
* present, concrete, equal, and share an `!important` flag.
|
|
481
|
+
* Flatten a layout-neutral, style-free `<div>` wrapper into its sole element child.
|
|
685
482
|
*/
|
|
686
|
-
|
|
687
|
-
declare const overscrollBehaviorShorthand: AuthoredPattern<Captures>;
|
|
483
|
+
declare const emptyStyleDiv: AuthoredPattern<Captures>;
|
|
688
484
|
|
|
689
485
|
/**
|
|
690
|
-
* @domflax/patterns —
|
|
486
|
+
* @domflax/patterns — flatten pattern: `inherited-only-wrapper`.
|
|
691
487
|
*
|
|
692
|
-
* Collapses
|
|
693
|
-
*
|
|
488
|
+
* Collapses a paint-free wrapper whose ONLY own declarations are INHERITED properties
|
|
489
|
+
* (`text-align`, `color`, `font-*`, `line-height`, `letter-spacing`, `white-space`, …):
|
|
694
490
|
*
|
|
695
|
-
*
|
|
696
|
-
* ⇒ padding:16px (Tailwind `p-4`)
|
|
491
|
+
* <div style="text-align:center"><Child/></div> → <Child style="text-align:center"/>
|
|
697
492
|
*
|
|
698
|
-
*
|
|
699
|
-
*
|
|
493
|
+
* An inherited property on a wrapper reaches its descendants purely through inheritance, so folding it
|
|
494
|
+
* onto the sole child and removing the box is render-identical — the child (and everything below it)
|
|
495
|
+
* still sees the same inherited value. The wrapper carries nothing NON-inherited (no padding, margin,
|
|
496
|
+
* sizing, border, background, layout), so its box contributes nothing to flow or paint.
|
|
700
497
|
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
704
|
-
*
|
|
705
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
706
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
707
|
-
* HTML never blocks a class-only rewrite); the `rewriteClasses`
|
|
708
|
-
* recipe rebuilds the class StyleMap, declining (`null`) unless the four sides fold cleanly.
|
|
498
|
+
* Distinct from `passthrough-wrapper` in INTENT: it recognizes the common "styling wrapper" idiom —
|
|
499
|
+
* a box that exists only to set an inherited text/font property on a subtree — and pushes that intent
|
|
500
|
+
* down onto the child. `foldInheritedStyles` (auto-applied by the flatten recipe) performs the fold;
|
|
501
|
+
* the `where` predicate restricts the match to wrappers whose entire own style is inheritable.
|
|
709
502
|
*/
|
|
710
503
|
/**
|
|
711
|
-
*
|
|
504
|
+
* Flatten a wrapper whose only own style is inherited into its sole element child (folding the
|
|
505
|
+
* inherited declarations down first so the subtree keeps the same inherited values).
|
|
712
506
|
*/
|
|
713
|
-
declare const
|
|
507
|
+
declare const inheritedOnlyWrapper: AuthoredPattern<Captures>;
|
|
714
508
|
|
|
715
509
|
/**
|
|
716
|
-
* @domflax/patterns —
|
|
510
|
+
* @domflax/patterns — flatten pattern: `passthrough-wrapper`.
|
|
717
511
|
*
|
|
718
|
-
*
|
|
719
|
-
* shorthands whenever the two axes of a pair agree:
|
|
512
|
+
* Collapses a purely-structural wrapper that exists for no reason at all:
|
|
720
513
|
*
|
|
721
|
-
*
|
|
722
|
-
* • align-content == justify-content → `place-content: <v>` (Tailwind `content-* justify-*`)
|
|
514
|
+
* <div><Child/></div>
|
|
723
515
|
*
|
|
724
|
-
* The
|
|
725
|
-
*
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
*
|
|
516
|
+
* The wrapper paints nothing, establishes no box / formatting / stacking context, carries no
|
|
517
|
+
* attributes beyond an (optional) inert class, holds exactly one element child, and is free of every
|
|
518
|
+
* opacity barrier (ref / event-handlers / dynamic children / dangerous html / spread / component).
|
|
519
|
+
* Such a `<div>` is pure DOM noise: removing it and hoisting the child is invisible to both paint
|
|
520
|
+
* and layout.
|
|
729
521
|
*
|
|
730
|
-
* Authored with the declarative {@link
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
*
|
|
734
|
-
*
|
|
522
|
+
* Authored with the declarative {@link definePattern} API. The opacity-barrier + selector-safety
|
|
523
|
+
* guards (ref/handlers/dynamic-children/raw-html/combinator/reparent-impact) are applied
|
|
524
|
+
* automatically for every `flatten/*` pattern; the `where` predicates add the passthrough-specific
|
|
525
|
+
* requirements (no box/formatting/stacking context, no own attrs, no dynamic/spread classes, not a
|
|
526
|
+
* component, not a structural-pseudo subject).
|
|
735
527
|
*/
|
|
736
|
-
/** Fold matching align/justify pairs into the `place-items` / `place-content` shorthands. */
|
|
737
|
-
declare const placeShorthand: AuthoredPattern<Captures>;
|
|
738
|
-
|
|
739
528
|
/**
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
* Collapses an element whose four scroll-margin sides are expressed as separate longhand
|
|
743
|
-
* declarations and are ALL EQUAL into the single CSS `scroll-margin` shorthand:
|
|
744
|
-
*
|
|
745
|
-
* scroll-margin-top:1rem; scroll-margin-right:1rem;
|
|
746
|
-
* scroll-margin-bottom:1rem; scroll-margin-left:1rem
|
|
747
|
-
* ⇒ scroll-margin:1rem (Tailwind `scroll-m-4`)
|
|
748
|
-
*
|
|
749
|
-
* Tailwind's `scroll-mt-*` / `scroll-mx-*` / … utilities each resolve to the matching
|
|
750
|
-
* `scroll-margin-*` longhand(s), and the shared normalizer keeps `scroll-margin` un-expanded (it is
|
|
751
|
-
* NOT one of the box shorthands the normalizer splits). So only the all-equal (1-value) form maps
|
|
752
|
-
* cleanly to a single `scroll-m-*` utility — the 2-value (`scroll-mx`/`scroll-my`) shape is left to
|
|
753
|
-
* the resolver's own reverse-emit. This pass runs the collapse in reverse on the computed map ONLY
|
|
754
|
-
* when all four sides share one value, replacing them with one `scroll-margin` decl so the minimizing
|
|
755
|
-
* reverse-emit can pick a single `scroll-m-*` token instead of two axis tokens.
|
|
756
|
-
*
|
|
757
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
758
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
759
|
-
* HTML never blocks a class-only rewrite); the
|
|
760
|
-
* `rewriteClasses` recipe rebuilds the class StyleMap, declining (`null`) unless the four sides are
|
|
761
|
-
* present, concrete, equal, and share an `!important` flag.
|
|
529
|
+
* Flatten a do-nothing `<div>` wrapper into its sole element child, folding any inheritable styles
|
|
530
|
+
* down first so inherited values survive the box removal.
|
|
762
531
|
*/
|
|
763
|
-
|
|
764
|
-
declare const scrollMarginShorthand: AuthoredPattern<Captures>;
|
|
532
|
+
declare const passthroughWrapper: AuthoredPattern<Captures>;
|
|
765
533
|
|
|
766
534
|
/**
|
|
767
|
-
* @domflax/patterns —
|
|
535
|
+
* @domflax/patterns — flatten pattern: `redundant-inline-wrapper`.
|
|
768
536
|
*
|
|
769
|
-
* Collapses
|
|
770
|
-
* declarations and are ALL EQUAL into the single CSS `scroll-padding` shorthand:
|
|
537
|
+
* Collapses a purely-structural INLINE wrapper:
|
|
771
538
|
*
|
|
772
|
-
*
|
|
773
|
-
* scroll-padding-bottom:1rem; scroll-padding-left:1rem
|
|
774
|
-
* ⇒ scroll-padding:1rem (Tailwind `scroll-p-4`)
|
|
539
|
+
* <span><Child/></span> (display:inline, no own style)
|
|
775
540
|
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
* the
|
|
781
|
-
* when all four sides share one value, replacing them with one `scroll-padding` decl so the minimizing
|
|
782
|
-
* reverse-emit can pick a single `scroll-p-*` token instead of two axis tokens.
|
|
541
|
+
* An inline `<span>` that paints nothing, establishes no box / formatting / stacking context, carries
|
|
542
|
+
* no attributes beyond an (optional) inert class, declares no custom properties, and holds exactly one
|
|
543
|
+
* element child is pure inline noise. An empty inline box merely wraps its child's box; removing it and
|
|
544
|
+
* hoisting the child leaves both paint and layout untouched (the surviving child folds the inheritable
|
|
545
|
+
* declarations the span carried).
|
|
783
546
|
*
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
*
|
|
547
|
+
* This is the inline sibling of `passthrough-wrapper` (which targets `<div>`): the same opacity-barrier
|
|
548
|
+
* + selector-safety guards are auto-applied by the `pattern()` factory for every `flatten/*` pattern;
|
|
549
|
+
* the `where` predicates add the inline-passthrough requirements (display must be the inline default,
|
|
550
|
+
* no box/formatting/stacking context or var coupling, no own attrs / dynamic-or-spread classes, not a
|
|
551
|
+
* component, not a structural-pseudo subject).
|
|
789
552
|
*/
|
|
790
|
-
/** Fold four equal scroll-padding sides into the single `scroll-padding` shorthand. */
|
|
791
|
-
declare const scrollPaddingShorthand: AuthoredPattern<Captures>;
|
|
792
|
-
|
|
793
553
|
/**
|
|
794
|
-
*
|
|
795
|
-
*
|
|
796
|
-
* Collapses an element whose computed `width` and `height` are EQUAL into the single Tailwind
|
|
797
|
-
* `size-*` utility:
|
|
798
|
-
*
|
|
799
|
-
* <div style="width:1rem; height:1rem"/> → <div class="size-4"/>
|
|
800
|
-
*
|
|
801
|
-
* At the IR level we work over the normalized computed StyleMap (CSS longhands), so the pattern
|
|
802
|
-
* recognizes the `width === height` shape in the BASE condition and rebuilds the element's class
|
|
803
|
-
* StyleMap with a single `size` declaration (the resolver reverse-emits the concrete `size-*` token
|
|
804
|
-
* at codegen). Both longhands are removed and replaced by the merged `size` decl, so the rewrite is
|
|
805
|
-
* idempotent — once collapsed there is no `width`+`height` pair left to re-match.
|
|
806
|
-
*
|
|
807
|
-
* Authored with the declarative {@link pattern} API: `definePattern` auto-applies the compress safety guards — a dynamic or opaque class list
|
|
808
|
-
* and combinator-subject selectors are excluded (a ref / event handler / dynamic child / dangerous
|
|
809
|
-
* HTML never blocks a class-only rewrite); the
|
|
810
|
-
* `rewriteClasses` recipe rebuilds the class StyleMap, returning `null` (decline) unless the BASE
|
|
811
|
-
* width/height are equal, concrete, and share an `!important` flag.
|
|
554
|
+
* Flatten a do-nothing inline `<span>` wrapper into its sole element child, folding any inheritable
|
|
555
|
+
* styles down first so inherited values survive the box removal.
|
|
812
556
|
*/
|
|
813
|
-
|
|
814
|
-
declare const sizeShorthand: AuthoredPattern<Captures>;
|
|
557
|
+
declare const redundantInlineWrapper: AuthoredPattern<Captures>;
|
|
815
558
|
|
|
816
559
|
/**
|
|
817
560
|
* AUTO-GENERATED by `scripts/gen-registry.mjs` — DO NOT EDIT BY HAND.
|
|
818
561
|
*
|
|
819
562
|
* Regenerate with `npm run generate` (also runs automatically before build/typecheck/test).
|
|
820
|
-
* Patterns are discovered by the `*.pattern.ts` file convention
|
|
821
|
-
*
|
|
563
|
+
* Patterns are discovered by the recursive `*.pattern.ts` file convention (organized into DOMAIN
|
|
564
|
+
* folders under `src/library/`); the array below is sorted flatten-before-compress.
|
|
822
565
|
*/
|
|
823
566
|
|
|
824
567
|
/** Every built-in pattern, in registration order (flatten patterns before compress). */
|
|
@@ -866,6 +609,12 @@ interface ResolvedDomflaxOptions {
|
|
|
866
609
|
interface DomflaxTransformResult {
|
|
867
610
|
readonly code: string;
|
|
868
611
|
readonly map: EncodedSourceMap | null;
|
|
612
|
+
/**
|
|
613
|
+
* Per-file optimization delta (nodes removed / classes saved / bytes saved). Zeroed for
|
|
614
|
+
* unsupported or unchanged files. Consumed by the build adapters to accumulate the build-end
|
|
615
|
+
* {@link renderSummary summary}.
|
|
616
|
+
*/
|
|
617
|
+
readonly stats: FileStatDelta;
|
|
869
618
|
}
|
|
870
619
|
/**
|
|
871
620
|
* A configured domflax engine. Holds the wired core {@link Pipeline}, the passthrough
|
|
@@ -897,6 +646,12 @@ interface DomflaxVitePlugin {
|
|
|
897
646
|
readonly enforce: 'pre';
|
|
898
647
|
/** Vite's per-file source hook. Fully synchronous and browser-free. */
|
|
899
648
|
transform(code: string, id: string): DomflaxTransformResult | null;
|
|
649
|
+
/** Vite build-start hook — resets the per-build summary accumulator (watch/serve safe). */
|
|
650
|
+
buildStart(): void;
|
|
651
|
+
/** Vite build-end hook — prints the aggregate {@link renderSummary} once (if anything changed). */
|
|
652
|
+
buildEnd(): void;
|
|
653
|
+
/** Vite close-bundle hook — prints the summary as a backstop if `buildEnd` did not fire. */
|
|
654
|
+
closeBundle(): void;
|
|
900
655
|
}
|
|
901
656
|
/**
|
|
902
657
|
* Vite adapter. Returns a real Vite `Plugin` (`enforce: 'pre'`) whose `transform` runs the domflax
|
|
@@ -917,6 +672,12 @@ interface DomflaxWebpackModuleHost {
|
|
|
917
672
|
module?: {
|
|
918
673
|
rules?: unknown[];
|
|
919
674
|
};
|
|
675
|
+
/** webpack's plugin list (present on both a real `Compiler.options` and Next's bare config). */
|
|
676
|
+
plugins?: unknown[];
|
|
677
|
+
}
|
|
678
|
+
/** A tappable webpack hook (only the `tap` arm domflax uses). */
|
|
679
|
+
interface DomflaxWebpackHook {
|
|
680
|
+
tap(name: string, fn: (arg: unknown) => void): void;
|
|
920
681
|
}
|
|
921
682
|
/**
|
|
922
683
|
* Minimal webpack-compiler shape. Declared locally so this adapter does NOT depend on `webpack`'s
|
|
@@ -928,6 +689,10 @@ interface DomflaxWebpackModuleHost {
|
|
|
928
689
|
*/
|
|
929
690
|
interface DomflaxWebpackCompiler extends DomflaxWebpackModuleHost {
|
|
930
691
|
options?: DomflaxWebpackModuleHost;
|
|
692
|
+
/** Present only on a REAL webpack `Compiler` (not on Next's bare config). Used for the summary. */
|
|
693
|
+
hooks?: {
|
|
694
|
+
done?: DomflaxWebpackHook;
|
|
695
|
+
};
|
|
931
696
|
}
|
|
932
697
|
/**
|
|
933
698
|
* Minimal webpack-plugin shape. `apply(compiler)` is the webpack plugin entry point.
|
|
@@ -936,30 +701,6 @@ interface DomflaxWebpackPlugin {
|
|
|
936
701
|
readonly name: string;
|
|
937
702
|
apply(compiler: DomflaxWebpackCompiler): void;
|
|
938
703
|
}
|
|
939
|
-
/**
|
|
940
|
-
* webpack adapter (also the Next.js path). Returns a plugin whose `apply(compiler)` injects a
|
|
941
|
-
* pre-enforced `module.rule` that invokes the domflax {@link ./webpack-loader loader} on every
|
|
942
|
-
* `.jsx`/`.tsx` module. The loader runs the SAME lazy engine as {@link createDomflax} (no eager
|
|
943
|
-
* Tailwind/postcss load).
|
|
944
|
-
*
|
|
945
|
-
* Next.js wiring (`next.config.js`) — Next exposes the underlying webpack config via `webpack(config)`:
|
|
946
|
-
* ```js
|
|
947
|
-
* // next.config.js
|
|
948
|
-
* const domflax = require('domflax');
|
|
949
|
-
* module.exports = {
|
|
950
|
-
* webpack(config) {
|
|
951
|
-
* domflax.webpack({ provider: 'tailwind' }).apply(config);
|
|
952
|
-
* return config;
|
|
953
|
-
* },
|
|
954
|
-
* };
|
|
955
|
-
* ```
|
|
956
|
-
* `apply(compiler)` is intentionally duck-typed on `compiler.options.module.rules`, so it accepts
|
|
957
|
-
* both a real webpack `Compiler` and the bare `config` object Next.js hands you.
|
|
958
|
-
*
|
|
959
|
-
* Caveat: this targets the webpack builder only. **Turbopack is not yet supported** — it does not
|
|
960
|
-
* accept arbitrary webpack loaders, so the `next.config.js` wiring above is a no-op under
|
|
961
|
-
* `next dev --turbopack`. Run domflax through the webpack builder until Turbopack exposes a loader API.
|
|
962
|
-
*/
|
|
963
704
|
declare function webpack(options?: DomflaxOptions): DomflaxWebpackPlugin;
|
|
964
705
|
/**
|
|
965
706
|
* The default-export namespace. Exposes the build adapters and the programmatic factory as an OBJECT
|
|
@@ -975,4 +716,4 @@ interface DomflaxDefault {
|
|
|
975
716
|
/** Default export: an object exposing `vite`, `webpack`, and the programmatic `createDomflax`. */
|
|
976
717
|
declare const domflax: DomflaxDefault;
|
|
977
718
|
|
|
978
|
-
export { ApplyContext, type ApplyOutcome, ApplyResult, Captures, DEFAULT_FIXPOINT, Diagnostic, type Domflax, type DomflaxDefault, type DomflaxOptions, type DomflaxProvider, type DomflaxTransformResult, type DomflaxVitePlugin, type DomflaxWebpackCompiler, type DomflaxWebpackPlugin, EncodedSourceMap, FixpointConfig, type FlattenClass, type FlattenClassification, type FlattenVerdict, HaltReason, IRDocument, IRNodeId, MatchContext, PHASE_ORDER, Pass, PassManager, PassPhase, Pattern, type PhaseLoopState, PhaseRunResult, Pipeline, type ResolvedDomflaxOptions, RewriteFactory, RewriteGroup, RewriteOp, RewriteOpDraft, type RunState, SafetyLevel, SelectorIndex, StyleNormalizer, StyleResolver, SyntheticSink, applyGroups, applyOps,
|
|
719
|
+
export { ApplyContext, type ApplyOutcome, ApplyResult, Captures, type CoverClass, DEFAULT_FIXPOINT, DEFAULT_MAX_UNIVERSE, Diagnostic, type Domflax, type DomflaxDefault, type DomflaxOptions, type DomflaxProvider, type DomflaxTransformResult, type DomflaxVitePlugin, type DomflaxWebpackCompiler, type DomflaxWebpackPlugin, EncodedSourceMap, FixpointConfig, type FlattenClass, type FlattenClassification, type FlattenVerdict, HaltReason, IRDocument, IRNodeId, MatchContext, type MinCoverOptions, PHASE_ORDER, Pass, PassManager, PassPhase, Pattern, type PhaseLoopState, PhaseRunResult, Pipeline, type ResolvedDomflaxOptions, RewriteFactory, RewriteGroup, RewriteOp, RewriteOpDraft, type RunState, SafetyLevel, SelectorIndex, StyleMap, StyleNormalizer, StyleResolver, SyntheticSink, applyGroups, applyOps, buildMatchContext, buildSelectorIndex, builtinPatterns, classifyFlattenOps, cloneDocument, createDomflax, createNullResolver, createNullSelectorIndex, createPassManager, createPipeline, createRewriteFactory, createSyntheticSink, domflax as default, displayContentsWrapper, docFingerprint, emptyStyleDiv, evaluateElement, finalizePhase, flattenVerdict, flattenWouldDropStyle, flexCenterWrapper, gridCenterWrapper, inheritedOnlyWrapper, minStringCover, passthroughWrapper, patternsForPhase, redundantFragment, redundantInlineWrapper, revertDiagnostic, runPasses, stampOrigin, styleMapTuples, syncClassesFromComputed, tupleKey, vite, webpack };
|