markswift 0.0.0-stage → 2.0.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/CHANGELOG.md +234 -0
- package/LICENSE +21 -0
- package/README.md +592 -2
- package/dist/cli-jdrbzqfa.js +2975 -0
- package/dist/cli-qchh0m4d.js +14041 -0
- package/dist/cli.js +637 -0
- package/dist/compiler/index.js +20 -0
- package/dist/index.js +22 -0
- package/dist/types/analysis/alignment.d.ts +12 -0
- package/dist/types/analysis/bands.d.ts +53 -0
- package/dist/types/analysis/breakpoints.d.ts +22 -0
- package/dist/types/analysis/class-hints.d.ts +21 -0
- package/dist/types/analysis/context.d.ts +49 -0
- package/dist/types/analysis/controls.d.ts +97 -0
- package/dist/types/analysis/flex-row.d.ts +14 -0
- package/dist/types/analysis/flex-sizing.d.ts +5 -0
- package/dist/types/analysis/flow-layout.d.ts +18 -0
- package/dist/types/analysis/generated.d.ts +16 -0
- package/dist/types/analysis/geometry.d.ts +50 -0
- package/dist/types/analysis/grid-tracks.d.ts +44 -0
- package/dist/types/analysis/grid.d.ts +5 -0
- package/dist/types/analysis/infer.d.ts +18 -0
- package/dist/types/analysis/invisible.d.ts +6 -0
- package/dist/types/analysis/layers.d.ts +15 -0
- package/dist/types/analysis/measured-layout.d.ts +6 -0
- package/dist/types/analysis/motion.d.ts +29 -0
- package/dist/types/analysis/naming.d.ts +6 -0
- package/dist/types/analysis/node-base.d.ts +13 -0
- package/dist/types/analysis/size-constraints.d.ts +5 -0
- package/dist/types/analysis/sizing.d.ts +24 -0
- package/dist/types/analysis/style-background.d.ts +24 -0
- package/dist/types/analysis/style-border.d.ts +7 -0
- package/dist/types/analysis/style-effects.d.ts +4 -0
- package/dist/types/analysis/style.d.ts +9 -0
- package/dist/types/analysis/svg/attributes.d.ts +10 -0
- package/dist/types/analysis/svg/build.d.ts +6 -0
- package/dist/types/analysis/svg/context.d.ts +31 -0
- package/dist/types/analysis/svg/geometry.d.ts +11 -0
- package/dist/types/analysis/svg/gradients.d.ts +6 -0
- package/dist/types/analysis/svg/markup.d.ts +23 -0
- package/dist/types/analysis/svg/text.d.ts +7 -0
- package/dist/types/analysis/svg/transforms.d.ts +19 -0
- package/dist/types/analysis/svg/traversal.d.ts +4 -0
- package/dist/types/analysis/table-borders.d.ts +19 -0
- package/dist/types/analysis/table.d.ts +36 -0
- package/dist/types/analysis/text-layout.d.ts +65 -0
- package/dist/types/analysis/text-runs.d.ts +30 -0
- package/dist/types/analysis/text.d.ts +9 -0
- package/dist/types/analysis/tooltips.d.ts +16 -0
- package/dist/types/analysis/typography.d.ts +21 -0
- package/dist/types/analysis/wrapping.d.ts +5 -0
- package/dist/types/api/bands.d.ts +58 -0
- package/dist/types/api/build.d.ts +51 -0
- package/dist/types/api/convert.d.ts +13 -0
- package/dist/types/api/types.d.ts +69 -0
- package/dist/types/browser/capture.d.ts +89 -0
- package/dist/types/browser/conditions.d.ts +25 -0
- package/dist/types/browser/fonts.d.ts +34 -0
- package/dist/types/browser/images.d.ts +3 -0
- package/dist/types/browser/layers.d.ts +132 -0
- package/dist/types/browser/motion.d.ts +44 -0
- package/dist/types/browser/settle.d.ts +27 -0
- package/dist/types/browser/sizing.d.ts +10 -0
- package/dist/types/browser/snapshot.d.ts +155 -0
- package/dist/types/browser/states.d.ts +36 -0
- package/dist/types/cli/args.d.ts +31 -0
- package/dist/types/cli/config.d.ts +78 -0
- package/dist/types/cli/css.d.ts +9 -0
- package/dist/types/cli/manifest.d.ts +20 -0
- package/dist/types/cli/output.d.ts +27 -0
- package/dist/types/cli/run.d.ts +4 -0
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/compiler/index.d.ts +91 -0
- package/dist/types/compiler/naming.d.ts +1 -0
- package/dist/types/css/background.d.ts +16 -0
- package/dist/types/css/blend.d.ts +9 -0
- package/dist/types/css/color.d.ts +14 -0
- package/dist/types/css/counter.d.ts +10 -0
- package/dist/types/css/easing.d.ts +4 -0
- package/dist/types/css/effects.d.ts +18 -0
- package/dist/types/css/grid.d.ts +29 -0
- package/dist/types/css/index.d.ts +15 -0
- package/dist/types/css/media.d.ts +16 -0
- package/dist/types/css/paint.d.ts +33 -0
- package/dist/types/css/radius.d.ts +5 -0
- package/dist/types/css/raster.d.ts +10 -0
- package/dist/types/css/shadows.d.ts +3 -0
- package/dist/types/css/syntax.d.ts +12 -0
- package/dist/types/css/transforms.d.ts +45 -0
- package/dist/types/css/typography.d.ts +8 -0
- package/dist/types/fonts/converter.d.ts +16 -0
- package/dist/types/fonts/metadata.d.ts +6 -0
- package/dist/types/fonts/package.d.ts +12 -0
- package/dist/types/fonts/registration.d.ts +13 -0
- package/dist/types/fonts/source.d.ts +14 -0
- package/dist/types/fonts/types.d.ts +28 -0
- package/dist/types/html/elements.d.ts +8 -0
- package/dist/types/html/index.d.ts +4 -0
- package/dist/types/html/inputs.d.ts +4 -0
- package/dist/types/html/policy.d.ts +3 -0
- package/dist/types/html/types.d.ts +12 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/input/identity.d.ts +3 -0
- package/dist/types/input/mime.d.ts +1 -0
- package/dist/types/input/root.d.ts +1 -0
- package/dist/types/input/server.d.ts +11 -0
- package/dist/types/input/source.d.ts +9 -0
- package/dist/types/input/types.d.ts +54 -0
- package/dist/types/model/fonts.d.ts +26 -0
- package/dist/types/model/interactive.d.ts +10 -0
- package/dist/types/model/layout.d.ts +528 -0
- package/dist/types/model/semantic.d.ts +984 -0
- package/dist/types/model/values.d.ts +125 -0
- package/dist/types/model/version.d.ts +4 -0
- package/dist/types/swift/borders.d.ts +13 -0
- package/dist/types/swift/components.d.ts +115 -0
- package/dist/types/swift/context.d.ts +184 -0
- package/dist/types/swift/control-state.d.ts +19 -0
- package/dist/types/swift/controls.d.ts +62 -0
- package/dist/types/swift/diagnostics.d.ts +3 -0
- package/dist/types/swift/effects.d.ts +23 -0
- package/dist/types/swift/emit.d.ts +6 -0
- package/dist/types/swift/format.d.ts +91 -0
- package/dist/types/swift/frames.d.ts +17 -0
- package/dist/types/swift/images.d.ts +25 -0
- package/dist/types/swift/layout.d.ts +5 -0
- package/dist/types/swift/measured-layout.d.ts +4 -0
- package/dist/types/swift/modifiers.d.ts +30 -0
- package/dist/types/swift/motion.d.ts +20 -0
- package/dist/types/swift/nodes.d.ts +4 -0
- package/dist/types/swift/paint.d.ts +22 -0
- package/dist/types/swift/runtime.d.ts +6 -0
- package/dist/types/swift/shadows.d.ts +7 -0
- package/dist/types/swift/states.d.ts +3 -0
- package/dist/types/swift/svg.d.ts +14 -0
- package/dist/types/swift/text-box.d.ts +12 -0
- package/dist/types/swift/text.d.ts +3 -0
- package/dist/types/swift/tokens/emit.d.ts +26 -0
- package/dist/types/swift/tokens/extract.d.ts +21 -0
- package/dist/types/swift/tokens/naming.d.ts +22 -0
- package/dist/types/swift/tokens/slots.d.ts +18 -0
- package/dist/types/swift/tokens/types.d.ts +77 -0
- package/dist/types/swift/tokens.d.ts +6 -0
- package/dist/types/swift/traversal.d.ts +2 -0
- package/dist/types/swift/wrapping.d.ts +4 -0
- package/package.json +66 -4
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Shared SVG traversal data contracts. */
|
|
2
|
+
import { type BundledFamilies } from "../../model/fonts.ts";
|
|
3
|
+
import { type LayoutNode, type Rect } from "../../model/layout.ts";
|
|
4
|
+
import { type Diagnostic, type SvgPath, type SvgText } from "../../model/semantic.ts";
|
|
5
|
+
/** Affine matrix in SVG order `[a, b, c, d, e, f]`. */
|
|
6
|
+
export type SvgMatrix = [number, number, number, number, number, number];
|
|
7
|
+
export interface SvgScope {
|
|
8
|
+
/** Inherited presentation attributes, nearest ancestor wins. */
|
|
9
|
+
attrs: Record<string, string>;
|
|
10
|
+
/** Accumulated transform from the viewBox down to this element. */
|
|
11
|
+
ctm: SvgMatrix;
|
|
12
|
+
/** Product of ancestor `opacity` values. */
|
|
13
|
+
opacity: number;
|
|
14
|
+
/** Computed `color` of the nearest `<use>`: instanced content resolves `currentColor` against it. */
|
|
15
|
+
useColor?: string;
|
|
16
|
+
/** `<use>` nesting depth (cycle guard). */
|
|
17
|
+
depth: number;
|
|
18
|
+
/** Inherited from an ancestor group (<g clip-path|mask>): applied to every shape below that has none of its own. */
|
|
19
|
+
clip?: SvgPath["clip"];
|
|
20
|
+
/** Inherited from an ancestor group (<g clip-path|mask>): applied to every shape below that has none of its own. */
|
|
21
|
+
mask?: SvgPath[];
|
|
22
|
+
}
|
|
23
|
+
export interface SvgContext {
|
|
24
|
+
bundledFamilies: BundledFamilies;
|
|
25
|
+
ids: Record<string, LayoutNode>;
|
|
26
|
+
diagnostics: Diagnostic[];
|
|
27
|
+
vb: [number, number, number, number];
|
|
28
|
+
frame: Rect;
|
|
29
|
+
paths: SvgPath[];
|
|
30
|
+
texts: SvgText[];
|
|
31
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Exact SVG path bounds and circular stroke geometry. */
|
|
2
|
+
import { type PathSegment, type SvgPath } from "../../model/semantic.ts";
|
|
3
|
+
import { type Rect } from "../../model/layout.ts";
|
|
4
|
+
import { type SvgMatrix } from "./context.ts";
|
|
5
|
+
export declare function ringOf(circle: {
|
|
6
|
+
cx: number;
|
|
7
|
+
cy: number;
|
|
8
|
+
r: number;
|
|
9
|
+
}, dash: number[], phase: number, ctm: SvgMatrix, vb: [number, number, number, number]): SvgPath["ring"] | undefined;
|
|
10
|
+
/** Bounding box of the path's geometry (exact for lines and Bézier curves). */
|
|
11
|
+
export declare function pathBounds(path: PathSegment[]): Rect;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Resolve SVG gradient paint servers and inherited stops. */
|
|
2
|
+
import { type Rect } from "../../model/layout.ts";
|
|
3
|
+
import { type SvgGradient } from "../../model/semantic.ts";
|
|
4
|
+
import { type SvgContext } from "./context.ts";
|
|
5
|
+
/** `url(#id)` → gradient in user units, or undefined (reported) when the id is not a gradient. */
|
|
6
|
+
export declare function gradientOf(raw: string, bbox: Rect, ctx: SvgContext): SvgGradient | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Parse standalone SVG markup into layout data before SVG analysis. */
|
|
2
|
+
import { type Rect } from "../../model/layout.ts";
|
|
3
|
+
import { type SvgNode } from "../../model/semantic.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Standalone SVG markup (a `data:image/svg+xml` URL, an inline asset) → SvgNode drawn in
|
|
6
|
+
* `frame`. Attributes only — there is no computed style — so `currentColor`, CSS classes
|
|
7
|
+
* and `<style>` rules inside the markup are not resolved. Undefined when the root is not an
|
|
8
|
+
* `<svg>` or no viewBox can be derived (neither `viewBox` nor width/height).
|
|
9
|
+
*/
|
|
10
|
+
export declare function svgFromMarkup(markup: string, frame: Rect): SvgNode | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* A `data:image/svg+xml` URL → its vector (drawn in a zero frame; the emitter sizes it) and CSS
|
|
13
|
+
* natural size; `undefined` for any other URL. The payload is parsed once for both. The natural
|
|
14
|
+
* size is px `width`/`height`; one of them alone takes the other from the viewBox ratio. With
|
|
15
|
+
* neither (or `%`) the image has a ratio but no size: the caller fits the viewBox into its area.
|
|
16
|
+
*/
|
|
17
|
+
export declare function svgFromDataUrl(url: string): {
|
|
18
|
+
vector?: SvgNode;
|
|
19
|
+
intrinsic?: {
|
|
20
|
+
w: number;
|
|
21
|
+
h: number;
|
|
22
|
+
};
|
|
23
|
+
} | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Resolve SVG labels and measured text placement. */
|
|
2
|
+
import { type LayoutNode } from "../../model/layout.ts";
|
|
3
|
+
import { type SvgScope, type SvgContext } from "./context.ts";
|
|
4
|
+
export declare function collectText(el: LayoutNode, scope: SvgScope, pos: {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}, ctx: SvgContext): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** SVG affine transforms and path transformation. */
|
|
2
|
+
import { type LayoutNode } from "../../model/layout.ts";
|
|
3
|
+
import { type Diagnostic, type PathSegment } from "../../model/semantic.ts";
|
|
4
|
+
import { type SvgMatrix } from "./context.ts";
|
|
5
|
+
export declare const IDENTITY: SvgMatrix;
|
|
6
|
+
export declare function multiply(m: SvgMatrix, n: SvgMatrix): SvgMatrix;
|
|
7
|
+
export declare function isIdentity(m: SvgMatrix): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The element's own transform: Chrome's computed `transform` (attribute and CSS alike, as a
|
|
10
|
+
* matrix) about its `transform-origin`, in user units. Falls back to the attribute when the
|
|
11
|
+
* snapshot carries no computed value.
|
|
12
|
+
*/
|
|
13
|
+
export declare function ownTransform(c: LayoutNode, diagnostics: Diagnostic[]): SvgMatrix;
|
|
14
|
+
/** SVG transform list (`rotate(30 50 40) translate(…)`) → matrix; svgpath parses the list, three probe points recover it. */
|
|
15
|
+
export declare function transformAttr(attr: string | undefined): SvgMatrix;
|
|
16
|
+
export declare function bake(d: string, ctm: SvgMatrix): string;
|
|
17
|
+
/** Path data → absolute segments, shorthands and arcs expanded: the IR's one path normalisation. */
|
|
18
|
+
export declare function segments(d: string): PathSegment[];
|
|
19
|
+
export declare function apply(m: SvgMatrix, x: number, y: number): [number, number];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Traverse SVG groups, instances and shapes with recursive clipping and masks. */
|
|
2
|
+
import { type LayoutNode } from "../../model/layout.ts";
|
|
3
|
+
import { type SvgScope, type SvgContext } from "./context.ts";
|
|
4
|
+
export declare function visitChildren(el: LayoutNode, scope: SvgScope, ctx: SvgContext): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The collapsing border model (CSS 2.1 §17.6.2) over a captured table. Chrome resolves every grid
|
|
3
|
+
* line to one border (hidden wins, then the widest, then the stronger style, then cell > row >
|
|
4
|
+
* row group > table, then the box further up/left), paints it centred on the line and lays each
|
|
5
|
+
* cell out with half of it inside on every side; the table's box holds the outer halves. Each
|
|
6
|
+
* box paints only its own computed border, so the resolved line is rewritten into the boxes'
|
|
7
|
+
* styles instead: half of it on each side of the line. A line that is the same along a whole
|
|
8
|
+
* row is painted by the row (a hugging cell can be shorter than its row), and its cells keep
|
|
9
|
+
* the half as padding; any other line is painted by the cells.
|
|
10
|
+
*/
|
|
11
|
+
import type { LayoutNode } from "../model/layout.ts";
|
|
12
|
+
/** `table` with its collapsed borders rewritten into its own, its row groups', rows' and cells' styles. */
|
|
13
|
+
export declare function collapseTableBorders(table: LayoutNode): LayoutNode;
|
|
14
|
+
/**
|
|
15
|
+
* `empty-cells: hide` in the separated border model: an empty cell paints no background, border or shadow; its box
|
|
16
|
+
* keeps its place. Empty as Chrome decides it (probed): only collapsible whitespace inside — an empty `<span>` or
|
|
17
|
+
* ` ` still paints. Collapsed tables ignore the property.
|
|
18
|
+
*/
|
|
19
|
+
export declare function hideEmptyCells(table: LayoutNode): LayoutNode;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admission of a captured CSS table into `MarkswiftTable` (plan 049): its HTML-table-model slot grid, checked against
|
|
3
|
+
* the captured boxes, and the `table-layout: fixed` column solver the runtime mirrors.
|
|
4
|
+
*/
|
|
5
|
+
import type { LayoutNode } from "../model/layout.ts";
|
|
6
|
+
import type { GridPlacement, TableColumn } from "../model/semantic.ts";
|
|
7
|
+
type Slot = Pick<GridPlacement, "rowStart" | "colStart" | "rowSpan" | "colSpan">;
|
|
8
|
+
/** One slot-grid member of a captured table: its LayoutNode, its row (and row group), 1-based slot. */
|
|
9
|
+
export interface TableMember extends Slot {
|
|
10
|
+
node: LayoutNode;
|
|
11
|
+
parent: LayoutNode;
|
|
12
|
+
group?: LayoutNode;
|
|
13
|
+
}
|
|
14
|
+
export interface TableSlots {
|
|
15
|
+
widths: number[];
|
|
16
|
+
heights: number[];
|
|
17
|
+
hSpacing: number;
|
|
18
|
+
vSpacing: number;
|
|
19
|
+
collapse: boolean;
|
|
20
|
+
/** `table-layout: fixed` on a table with a non-`auto` Typed-OM width (CSS applies the fixed algorithm). */
|
|
21
|
+
fixedRequested: boolean;
|
|
22
|
+
/** The table's Typed-OM width is `<n>px` (read from `t`): the offered width is the captured one, scaling is exact. */
|
|
23
|
+
widthFixed: boolean;
|
|
24
|
+
fixed?: TableColumn[];
|
|
25
|
+
/** Painting row groups then rows (collapsed tables only), each spanning every column. */
|
|
26
|
+
bands: Array<Slot & {
|
|
27
|
+
node: LayoutNode;
|
|
28
|
+
}>;
|
|
29
|
+
/** Cells in DOM row-major order. */
|
|
30
|
+
cells: TableMember[];
|
|
31
|
+
}
|
|
32
|
+
/** Column widths for a content width; mirrors MarkswiftTable.columns (runtime/table.swift). */
|
|
33
|
+
export declare function solveTableColumns(width: number | undefined, widths: number[], spacing: number, fixed?: TableColumn[]): number[];
|
|
34
|
+
/** The table's slot grid when every captured box sits on it (0.5 px); undefined keeps the measured-rows path. */
|
|
35
|
+
export declare function tableSlots(t: LayoutNode): TableSlots | undefined;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** Inline gaps, fragments, line breaks and baseline placement. */
|
|
2
|
+
import { type LayoutNode, type Rect } from "../model/layout.ts";
|
|
3
|
+
import { type TextRun, type DiagnosticLevel } from "../model/semantic.ts";
|
|
4
|
+
import { type BundledFamilies } from "../model/fonts.ts";
|
|
5
|
+
import { type MeasuredTextRun } from "./context.ts";
|
|
6
|
+
/**
|
|
7
|
+
* The horizontal padding and border of an inline element is advance the browser inserted around
|
|
8
|
+
* its text, but a native run carries no box — so it becomes a run that paints nothing and only
|
|
9
|
+
* advances the line. Nested inline elements contribute one gap each, at the point where their
|
|
10
|
+
* first (or last) run sits, so `<a><code>x</code></a>` opens both boxes before the same glyph.
|
|
11
|
+
*/
|
|
12
|
+
export declare function withInlineGaps(built: MeasuredTextRun[], host: LayoutNode): TextRun[];
|
|
13
|
+
/**
|
|
14
|
+
* The collapsed space between two inline elements, as a run of the host's own text: its style,
|
|
15
|
+
* and a text node of its own so the browser's measured line boxes — which belong to the real
|
|
16
|
+
* text nodes — are not read twice.
|
|
17
|
+
*/
|
|
18
|
+
export declare function hostSpace(host: LayoutNode, families: BundledFamilies): MeasuredTextRun;
|
|
19
|
+
/** The inline elements from `host` (exclusive) down to `el` (inclusive), outermost first. */
|
|
20
|
+
export declare function inlineChain(host: LayoutNode, el: LayoutNode): LayoutNode[];
|
|
21
|
+
/**
|
|
22
|
+
* The boxes a wrapped inline element was painted in: one per line it spans. The measured text
|
|
23
|
+
* fragments inside it are the content areas, so each line's box is their union grown by the
|
|
24
|
+
* element's padding and border — vertically on every line, horizontally only where the box
|
|
25
|
+
* actually opens and closes (`box-decoration-break: slice`, the CSS default).
|
|
26
|
+
*/
|
|
27
|
+
export declare function inlineFragments(el: LayoutNode): Rect[];
|
|
28
|
+
/** Drops the whitespace `edge` matches from a run, keeping its source map aligned. */
|
|
29
|
+
export declare function trimRun(b: MeasuredTextRun, edge: RegExp): void;
|
|
30
|
+
/**
|
|
31
|
+
* Computed `unicode-bidi` as Unicode controls around each element's runs: SwiftUI has no
|
|
32
|
+
* per-run direction, and Core Text runs UAX #9 over the controls (LRI/RLI…PDI, LRO/RLO…PDF). The
|
|
33
|
+
* direction is the computed one, which Chrome already resolved for `dir=auto` from the content.
|
|
34
|
+
* Call after trimming and before `markLineBreaks`; the controls map to no source index.
|
|
35
|
+
*/
|
|
36
|
+
export declare function markBidi(built: MeasuredTextRun[], host: LayoutNode): void;
|
|
37
|
+
/** What closes each UAX #9 explicit opener (LRE/RLE/LRO/RLO, LRI/RLI/FSI): PDF, or PDI for an isolate. */
|
|
38
|
+
export declare const BIDI_CLOSER: Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* The bidi controls (`markBidi`) still open after `text`, outermost first. A PDI closes the innermost isolate and every
|
|
41
|
+
* embedding opened inside it; a PDF closes an embedding only inside the current isolate's scope; a "\n" is a
|
|
42
|
+
* paragraph separator and ends them all (UAX #9 X6a, X7, X8). Unmatched terminators do nothing.
|
|
43
|
+
*/
|
|
44
|
+
export declare function openBidi(text: string): string[];
|
|
45
|
+
/**
|
|
46
|
+
* The browser's line division, re-expressed as offsets into each run's laid-out text.
|
|
47
|
+
*
|
|
48
|
+
* A measured box is an inline *fragment*, not a line: Blink splits one at every collapsed
|
|
49
|
+
* whitespace run that came from a source newline, so several boxes routinely share a line.
|
|
50
|
+
* Fragments are grouped by their top edge; the first fragment of each line after the first is
|
|
51
|
+
* a break, and the first output character at or after its raw index is where it goes. Only
|
|
52
|
+
* fidelity bakes the breaks into the output; its emitter reports that.
|
|
53
|
+
*
|
|
54
|
+
* A wrap can also fall exactly at a run boundary (before an `<a>` or `<strong>`): that run's own
|
|
55
|
+
* boxes hold no break, and CDP omits `lines` for a single-line node. Its first baseline is then
|
|
56
|
+
* below the previous run's last one — baselines, because top edges differ on a shared line when
|
|
57
|
+
* font sizes do; a `vertical-align` shift is added back first, so call after `markBaselineShifts`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function markLineBreaks(built: MeasuredTextRun[]): void;
|
|
60
|
+
/**
|
|
61
|
+
* `vertical-align` on an inline run (`<sub>`, `<sup>`, `vertical-align: super`) as a baseline
|
|
62
|
+
* offset in px. The shift is measured against the nearest run on the same line that sits on the
|
|
63
|
+
* host's own baseline, so a UA-defined keyword needs no table.
|
|
64
|
+
*/
|
|
65
|
+
export declare function markBaselineShifts(built: MeasuredTextRun[], host: LayoutNode, note: (level: DiagnosticLevel, feature: string, message: string) => void): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Inline run collection, whitespace normalization and text decoration. */
|
|
2
|
+
import { type LayoutNode } from "../model/layout.ts";
|
|
3
|
+
import type { Color } from "../model/values.ts";
|
|
4
|
+
import { type TextDecoration } from "../model/semantic.ts";
|
|
5
|
+
import { type SourceTextRun } from "./context.ts";
|
|
6
|
+
/** Inline (non-atomic) element whose subtree is nothing but text (and a pseudo's captured images): merged into the parent's runs. */
|
|
7
|
+
export declare function isInlineText(c: LayoutNode): boolean;
|
|
8
|
+
export declare function collectRuns(el: LayoutNode, runs: SourceTextRun[]): void;
|
|
9
|
+
/** Split runs into groups separated by flow children (by document order → measured y/x proximity). */
|
|
10
|
+
export declare function groupRuns(host: LayoutNode, runs: SourceTextRun[]): SourceTextRun[][];
|
|
11
|
+
export declare function contains(a: LayoutNode, b: LayoutNode): boolean;
|
|
12
|
+
export type Collapse = "collapse" | "preserve" | "preserve-breaks";
|
|
13
|
+
/** Computed `white-space-collapse`; a hand-built tree without it gets the initial `collapse`. */
|
|
14
|
+
export declare function collapseOf(s: Record<string, string>): Collapse;
|
|
15
|
+
/**
|
|
16
|
+
* Whitespace as the browser laid it out — collapsed to single spaces, or kept (breaks only, or
|
|
17
|
+
* all) — plus a source map: `src[i]` is the index in `text` of the character that produced
|
|
18
|
+
* output character `i`, a collapsed run mapping to its first character. The map is what lets
|
|
19
|
+
* the browser's measured line division, which indexes the raw text, be re-expressed as offsets
|
|
20
|
+
* into the laid-out run text.
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizeWhitespace(text: string, mode: Collapse): {
|
|
23
|
+
text: string;
|
|
24
|
+
src: number[];
|
|
25
|
+
};
|
|
26
|
+
/** The colour glyphs paint in: `-webkit-text-fill-color` overrides `color`; black when neither parses. */
|
|
27
|
+
export declare function textColorOf(s: Record<string, string>): Color;
|
|
28
|
+
/** Concatenated text of an element's subtree, as the snapshot laid it out. */
|
|
29
|
+
export declare function textContent(el: LayoutNode | undefined): string;
|
|
30
|
+
export declare function decorationOf(s: Record<string, string>, color: Color): TextDecoration | undefined;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Construct semantic text nodes from measured inline runs. */
|
|
2
|
+
import { type LayoutNode } from "../model/layout.ts";
|
|
3
|
+
import { type TextNode } from "../model/semantic.ts";
|
|
4
|
+
import { type SourceTextRun, type InferenceContext } from "./context.ts";
|
|
5
|
+
/**
|
|
6
|
+
* @param leaf the host holds nothing but this text → its box is the CSS line box (text-node
|
|
7
|
+
* boxes from DOMSnapshot are glyph areas and overshoot tight line-heights).
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildText(host: LayoutNode, runs: SourceTextRun[], ctx: InferenceContext, leaf?: boolean): TextNode;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Tooltips (D-HOVER): `title` and captured tooltip layers become `SemBase.tooltip` — `.help` plus an accessibility hint, never drawn. */
|
|
2
|
+
import type { Layer, LayoutDoc, LayoutNode } from "../model/layout.ts";
|
|
3
|
+
import { type SemBase, type SemNode } from "../model/semantic.ts";
|
|
4
|
+
/** An element's `title` as tooltip text; an iframe's title is its name, not a tooltip. */
|
|
5
|
+
export declare function titleOf(n: LayoutNode): string;
|
|
6
|
+
/** Appends `text` to `base.tooltip` unless blank or already there; parts join with "; ". */
|
|
7
|
+
export declare function addTooltip(base: SemBase, text: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* A layer that only describes its trigger: tooltip content (`role=tooltip`, shadcn's `tooltip-content` slot), an
|
|
10
|
+
* `aria-describedby`/`interestfor` relation, or a hover layer of a shadcn tooltip trigger (`root` resolves the trigger;
|
|
11
|
+
* without it that last rule cannot fire). 060 skips these layers.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isTooltipLayer(layer: Layer, root?: LayoutNode): boolean;
|
|
14
|
+
/** Each tooltip layer's text becomes its trigger's `tooltip`: the `role=tooltip` element's (Radix pairs its visible
|
|
15
|
+
* content with a visually hidden copy that carries the role), else the whole layer's. */
|
|
16
|
+
export declare function applyTooltips(root: SemNode, doc: LayoutDoc): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Computed font selection with conversion-scoped bundled families. */
|
|
2
|
+
import { type BundledFamilies } from "../model/fonts.ts";
|
|
3
|
+
import { type FontSpec } from "../model/semantic.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Lower-case family name → the SwiftUI system design that carries it: the CSS generic families,
|
|
6
|
+
* the `ui-*` keywords, the Apple system stacks (`-apple-system`, `BlinkMacSystemFont`) and the
|
|
7
|
+
* concrete faces a design names next to a generic (`Menlo`, `Georgia`, …). `cursive`/`fantasy`
|
|
8
|
+
* have no system design and resolve to the default one, which `buildText` reports.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SYSTEM_DESIGNS: Record<string, "default" | "rounded" | "monospaced" | "serif">;
|
|
11
|
+
/**
|
|
12
|
+
* Font of a computed style: family, size, weight, line-height. The computed `font-family` is the
|
|
13
|
+
* authored list, not the family the browser picked, so it is walked in order and the first entry
|
|
14
|
+
* that resolves decides — a family the run bundled becomes `custom` (with `opsz` clamped into
|
|
15
|
+
* the axis range its file declares), a generic or an Apple system stack becomes the matching
|
|
16
|
+
* system design. An unresolvable list falls back to the default design, which `buildText`
|
|
17
|
+
* reports by name. `font-variation-settings` applies last and wins per axis (CSS Fonts 4 §7):
|
|
18
|
+
* `wght` → weight, `opsz` → opsz, other axes the bundled file declares (`wdth` also from
|
|
19
|
+
* `font-stretch`) → `axes`; a system family keeps `font-stretch`/`wdth` as `stretch`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function fontOf(s: Record<string, string>, families?: BundledFamilies): FontSpec;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Bounded native row reflow; unsupported flex algorithms retain captured positions. */
|
|
2
|
+
import type { LayoutNode } from "../model/layout.ts";
|
|
3
|
+
import { type Axis, type CrossAlign, type Distribution, type SemBase, type StackNode } from "../model/semantic.ts";
|
|
4
|
+
import type { AnalyzedChild } from "./context.ts";
|
|
5
|
+
export declare function buildWrapping(n: LayoutNode, base: SemBase, all: AnalyzedChild[], axis: Axis, align: CrossAlign, distribution: Distribution): StackNode;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** The browser captures of one conversion: per theme, and per width band. */
|
|
2
|
+
import type { Page } from "playwright-core";
|
|
3
|
+
import type { BrowserCapture, Capture } from "../browser/capture.ts";
|
|
4
|
+
import { type BandPlan } from "../compiler/index.ts";
|
|
5
|
+
import type { LayoutCondition, Theme } from "../model/layout.ts";
|
|
6
|
+
import type { ConvertOptions } from "./types.ts";
|
|
7
|
+
/** Throws unless `bp` is unset, `true` or `{ devices?, max? }` with positive integer sizes and an integer max ≥ 320. */
|
|
8
|
+
export declare function validateBreakpoints(bp: ConvertOptions["breakpoints"], prefix?: string): void;
|
|
9
|
+
/** The band plan of `bp` for a page whose first capture is `first` and reports `conditions`. */
|
|
10
|
+
export declare function planFor(bp: NonNullable<ConvertOptions["breakpoints"]>, conditions: LayoutCondition[], first: {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}): BandPlan;
|
|
14
|
+
/**
|
|
15
|
+
* Capture one page in its theme(s), each raced against `timedOut`. Adaptive: two captures in one browser session;
|
|
16
|
+
* the light one is emitted, the dark one pairs its colours. `layers`: also run the open-state pass on each theme
|
|
17
|
+
* (the primary one probes dismissal; dark copies it by layer id).
|
|
18
|
+
*/
|
|
19
|
+
export declare function captureThemes(renderer: BrowserCapture, req: {
|
|
20
|
+
name: string;
|
|
21
|
+
url: string;
|
|
22
|
+
html?: string;
|
|
23
|
+
label: string;
|
|
24
|
+
root: string;
|
|
25
|
+
theme: Theme | "adaptive";
|
|
26
|
+
css?: string;
|
|
27
|
+
darkClass?: string;
|
|
28
|
+
waitFor?: string;
|
|
29
|
+
prepare?: (page: Page) => Promise<void>;
|
|
30
|
+
viewport?: {
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
};
|
|
34
|
+
layers?: boolean;
|
|
35
|
+
breakpoints?: boolean;
|
|
36
|
+
}, timedOut: Promise<never>): Promise<{
|
|
37
|
+
primary: Capture;
|
|
38
|
+
dark?: Capture;
|
|
39
|
+
}>;
|
|
40
|
+
/** One capture of a breakpoint conversion; `extra`: a container-query capture (`BandPlan.extra`). */
|
|
41
|
+
export interface BandCapture {
|
|
42
|
+
primary: Capture;
|
|
43
|
+
dark?: Capture;
|
|
44
|
+
extra?: true;
|
|
45
|
+
}
|
|
46
|
+
/** The capture of every band of `plan`, reusing `first` for the band it belongs to, then its `extra` captures; one
|
|
47
|
+
* browser, in order, returned ascending by width (`extra: true` on the extras). Only band 0 runs the open-state pass
|
|
48
|
+
* (`req.layers`): its layers are applied once on the merged screen. */
|
|
49
|
+
export declare function captureBands(renderer: BrowserCapture, req: Parameters<typeof captureThemes>[1], first: {
|
|
50
|
+
viewport: {
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
53
|
+
};
|
|
54
|
+
captured: {
|
|
55
|
+
primary: Capture;
|
|
56
|
+
dark?: Capture;
|
|
57
|
+
};
|
|
58
|
+
}, plan: BandPlan, timedOut: Promise<never>): Promise<BandCapture[]>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type CompileResult, type EmitMode, type PaletteMap } from "../compiler/index.ts";
|
|
2
|
+
import type { Theme } from "../model/layout.ts";
|
|
3
|
+
import type { ConversionWarning } from "../model/semantic.ts";
|
|
4
|
+
import type { ConvertOptions } from "./types.ts";
|
|
5
|
+
export interface BuildComponent {
|
|
6
|
+
/** Swift view name, e.g. `AccordionView`. */
|
|
7
|
+
name: string;
|
|
8
|
+
/** `file`: path inside `serveRoot`; `url`: a running http(s) page. */
|
|
9
|
+
source: {
|
|
10
|
+
file: string;
|
|
11
|
+
} | {
|
|
12
|
+
url: string;
|
|
13
|
+
};
|
|
14
|
+
root?: string;
|
|
15
|
+
theme?: Theme | "adaptive";
|
|
16
|
+
darkClass?: string;
|
|
17
|
+
/** Already compiled CSS injected into the page. */
|
|
18
|
+
css?: string;
|
|
19
|
+
waitFor?: string;
|
|
20
|
+
mode?: EmitMode;
|
|
21
|
+
viewport?: {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
};
|
|
25
|
+
/** Capture every CSS width band and emit one view across them, as `convert`'s `breakpoints`. */
|
|
26
|
+
breakpoints?: ConvertOptions["breakpoints"];
|
|
27
|
+
}
|
|
28
|
+
export interface BuildOptions {
|
|
29
|
+
/** Swift package, product, target and module name. */
|
|
30
|
+
library: string;
|
|
31
|
+
components: BuildComponent[];
|
|
32
|
+
/** Directory served at http://127.0.0.1:<port>/ for every `file` source (relative URLs such as `../assets/x.woff2` resolve inside it). */
|
|
33
|
+
serveRoot?: string;
|
|
34
|
+
/** Whole-build deadline in ms. Default 600000. */
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
/** App colours for the library's `Palette` tokens; unmapped tokens and unused keys become warnings. */
|
|
37
|
+
palette?: PaletteMap;
|
|
38
|
+
}
|
|
39
|
+
export interface BuildResult {
|
|
40
|
+
/** Package files relative to the package root (`Package.swift`, `Sources/<library>/…`). */
|
|
41
|
+
files: Record<string, string>;
|
|
42
|
+
assets: Record<string, Uint8Array>;
|
|
43
|
+
/** Page and compile warnings carry `component`; font notes and config-level (`source: "build"`) ones may not. */
|
|
44
|
+
warnings: ConversionWarning[];
|
|
45
|
+
diagnostics: Record<string, CompileResult["diagnostics"]>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Capture every component in one browser session per viewport and emit ONE local SwiftPM package: a module-level
|
|
49
|
+
* `Palette`, one copy of each shape, font and image, one runtime, public views.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildLibrary(options: BuildOptions): Promise<BuildResult>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HtmlSource } from "../input/types.ts";
|
|
2
|
+
import type { FontFace } from "../model/layout.ts";
|
|
3
|
+
import type { ConvertOptions, ConversionResult } from "./types.ts";
|
|
4
|
+
/** Convert a document, fragment, HTML file or rendered URL through the same measured pipeline. */
|
|
5
|
+
export declare function convert(source: HtmlSource, options?: ConvertOptions): Promise<ConversionResult>;
|
|
6
|
+
/**
|
|
7
|
+
|
|
8
|
+
* Faces of several captures: the first list, plus faces only a later one declared. A face several
|
|
9
|
+
* declared is one face, loaded if any capture loaded it. Identical lists come back as the first.
|
|
10
|
+
*/
|
|
11
|
+
export declare function unionFaces(lists: FontFace[][]): FontFace[];
|
|
12
|
+
/** Convenience entry point for pasted HTML. */
|
|
13
|
+
export declare function convertHtml(html: string, options?: ConvertOptions): Promise<ConversionResult>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Page } from "playwright-core";
|
|
2
|
+
import type { CompileOptions, CompileResult } from "../compiler/index.ts";
|
|
3
|
+
import type { LayoutDoc, Theme } from "../model/layout.ts";
|
|
4
|
+
import type { ConversionWarning } from "../model/semantic.ts";
|
|
5
|
+
export type { HtmlSource } from "../input/types.ts";
|
|
6
|
+
export interface ConvertOptions extends Pick<CompileOptions, "name" | "mode" | "palette"> {
|
|
7
|
+
/** Already compiled CSS. Utility and CSS Modules selectors work exactly like normal CSS. */
|
|
8
|
+
css?: string;
|
|
9
|
+
root?: string;
|
|
10
|
+
/**
|
|
11
|
+
* `adaptive` (default) captures the page with `prefers-color-scheme: light`, then `dark`, and
|
|
12
|
+
* emits one view whose colours follow the colour scheme. `light`/`dark` capture one theme.
|
|
13
|
+
*/
|
|
14
|
+
theme?: Theme | "adaptive";
|
|
15
|
+
/** Class added to `<html>` for the dark capture, for class-based themes such as `.dark`. */
|
|
16
|
+
darkClass?: string;
|
|
17
|
+
viewport?: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Default true: when the capture contains a grid or flex row that a runtime Layout would reflow, a second capture
|
|
23
|
+
* at 320px (390px when the viewport is ≤ 320px) must agree, or the layout stays pinned.
|
|
24
|
+
*/
|
|
25
|
+
probe?: boolean;
|
|
26
|
+
dpr?: number;
|
|
27
|
+
/** Installed Playwright browser channel; defaults to chrome. */
|
|
28
|
+
browserChannel?: string;
|
|
29
|
+
/** For publicly submitted pasted markup: block page scripts and outbound resource requests. */
|
|
30
|
+
untrustedInput?: boolean;
|
|
31
|
+
/** Mounted selector to await before capture. */
|
|
32
|
+
waitFor?: string;
|
|
33
|
+
/** Optional application-specific setup, such as opening a menu; runs before every capture, including each open-state capture. */
|
|
34
|
+
prepare?: (page: Page) => Promise<void>;
|
|
35
|
+
/** Upper bound for the whole conversion (browser, network, font conversion), in ms. Default 120000. */
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Capture one layout per CSS width band (`@media` width thresholds) instead of one viewport. `true`: devices
|
|
39
|
+
* 390×844, 834×1210, 1210×834, 1376×1032 up to `max` (default 1376); a band without a device is captured at its
|
|
40
|
+
* lower bound with `viewport.height`; the configured `viewport` is the capture of its own band. Thresholds below
|
|
41
|
+
* 320 px or above `max`, and beyond six bands, are reported. The view emits every element whose authored inputs are
|
|
42
|
+
* equal in all bands once and switches the others at the CSS thresholds (`MarkswiftBands`, at the width offered to
|
|
43
|
+
* the view); a root that does not follow the viewport width keeps the first band's layout, with a warning. A query
|
|
44
|
+
* container (`container-type`) that is a stack or grid switches its content at the width offered to its content box
|
|
45
|
+
* on width `@container` queries; such pages add one capture at the top of each band, then capture each band but
|
|
46
|
+
* band 0 and the configured `viewport`'s at its lower bound, keeping its device as one more capture (within the six).
|
|
47
|
+
*/
|
|
48
|
+
breakpoints?: true | {
|
|
49
|
+
devices?: Array<{
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
}>;
|
|
53
|
+
max?: number;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export interface ConversionResult extends CompileResult {
|
|
57
|
+
/** Font packaging limitations, browser resource/page errors, viewport-dependent CSS and light/dark pairing limitations. */
|
|
58
|
+
warnings: ConversionWarning[];
|
|
59
|
+
/** The emitted capture: the light one for `adaptive`. */
|
|
60
|
+
layout: LayoutDoc;
|
|
61
|
+
/** The dark capture of an `adaptive` conversion. */
|
|
62
|
+
darkLayout?: LayoutDoc;
|
|
63
|
+
/** Every capture (`breakpoints`), ascending by width: one per width band plus, on pages with width `@container`
|
|
64
|
+
* queries, the extra captures of each band (its top, its device); `bands[0].layout` is `layout`. */
|
|
65
|
+
bands?: Array<{
|
|
66
|
+
layout: LayoutDoc;
|
|
67
|
+
darkLayout?: LayoutDoc;
|
|
68
|
+
}>;
|
|
69
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { type Layer, type LayoutDoc } from "../model/layout.ts";
|
|
2
|
+
import type { NodeIdentity, CaptureRequest, Trigger } from "../input/types.ts";
|
|
3
|
+
import type { ConversionWarning } from "../model/semantic.ts";
|
|
4
|
+
export interface Capture {
|
|
5
|
+
/** Resource failures, page errors and viewport-dependent CSS observed while preparing this capture. */
|
|
6
|
+
warnings: ConversionWarning[];
|
|
7
|
+
layout: LayoutDoc;
|
|
8
|
+
/** Set only when `CaptureRequest.screenshot` is true. */
|
|
9
|
+
png?: Uint8Array;
|
|
10
|
+
/**
|
|
11
|
+
* Bytes of every `@font-face` source that was not already inline, keyed by `file`: exactly
|
|
12
|
+
* the `LayoutDoc.fonts[].src[].file` value (`_fonts/<content hash>.<ext>`) that points at
|
|
13
|
+
* them. Packaging reads them from here; the conversion never writes them to disk. Identical
|
|
14
|
+
* faces collapse onto one entry.
|
|
15
|
+
*/
|
|
16
|
+
fontFiles: Array<{
|
|
17
|
+
file: string;
|
|
18
|
+
bytes: Uint8Array;
|
|
19
|
+
}>;
|
|
20
|
+
/** Rest captures: what the open-state pass activates (`browser/layers.ts`), in document order. */
|
|
21
|
+
triggers?: Trigger[];
|
|
22
|
+
/** `spec.open` captures whose trigger opened something: the layer, the open root size, and the trigger-subtree
|
|
23
|
+
* paint while open (LayoutNode id → delta). */
|
|
24
|
+
opened?: {
|
|
25
|
+
layer: Layer;
|
|
26
|
+
size: {
|
|
27
|
+
w: number;
|
|
28
|
+
h: number;
|
|
29
|
+
};
|
|
30
|
+
openPaint: Record<string, Record<string, string>>;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface CaptureOptions {
|
|
34
|
+
dpr: number;
|
|
35
|
+
viewport: {
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
};
|
|
39
|
+
channel?: string;
|
|
40
|
+
restricted?: boolean;
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
}
|
|
43
|
+
export declare class BrowserCapture {
|
|
44
|
+
private browser;
|
|
45
|
+
private context;
|
|
46
|
+
private stopping?;
|
|
47
|
+
private readonly opts;
|
|
48
|
+
constructor(opts: CaptureOptions);
|
|
49
|
+
start(): Promise<void>;
|
|
50
|
+
/** Version of the launched browser (e.g. `153.0.8010.12`). */
|
|
51
|
+
get version(): string;
|
|
52
|
+
/**
|
|
53
|
+
* Safe to call more than once and concurrently (the conversion deadline and its cleanup both
|
|
54
|
+
* call it): one close runs. Before `start` has a browser it does nothing, so a later call still closes it.
|
|
55
|
+
*/
|
|
56
|
+
stop(): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Capture one screen. `identity` names layout nodes; `source` is the
|
|
59
|
+
* LayoutDoc.source label. The page's `prefers-color-scheme` follows `spec.theme`.
|
|
60
|
+
*/
|
|
61
|
+
capture(spec: CaptureRequest, identity: NodeIdentity, source: string): Promise<Capture>;
|
|
62
|
+
/** Viewport, colour scheme, routes, navigation, `waitFor` and `prepare` of one capture request. */
|
|
63
|
+
private load;
|
|
64
|
+
/**
|
|
65
|
+
* Motion frame: the same page with every animation paused `frame.t` ms in (`reduced`: under
|
|
66
|
+
* `prefers-reduced-motion: reduce`, else `no-preference`), screenshotted at `clip` — the rest capture's root box.
|
|
67
|
+
* Throws when no animation was paused: the frame would silently be the settled look.
|
|
68
|
+
*/
|
|
69
|
+
captureFrame(spec: CaptureRequest, frame: {
|
|
70
|
+
t: number;
|
|
71
|
+
reduced: boolean;
|
|
72
|
+
}, clip: {
|
|
73
|
+
x: number;
|
|
74
|
+
y: number;
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
}): Promise<Uint8Array>;
|
|
78
|
+
/**
|
|
79
|
+
* `@open:<layer>@t:<ms>` enter frame (066): a fresh page opened like the `@open` capture (058's `openLayer`), the
|
|
80
|
+
* focus ring it took dropped, every animation paused `t` ms in under `no-preference`, screenshotted at `clip`.
|
|
81
|
+
* Throws when no animation was paused (as `captureFrame`).
|
|
82
|
+
*/
|
|
83
|
+
captureLayerFrame(spec: CaptureRequest, trigger: Trigger, t: number, clip: {
|
|
84
|
+
x: number;
|
|
85
|
+
y: number;
|
|
86
|
+
width: number;
|
|
87
|
+
height: number;
|
|
88
|
+
}): Promise<Uint8Array>;
|
|
89
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** CSS the capture resolved for one viewport and one validation state, reported instead of silently baked in. */
|
|
2
|
+
import type { Page } from "playwright-core";
|
|
3
|
+
import { type LayoutCondition, type LayoutNode } from "../model/layout.ts";
|
|
4
|
+
import type { ConversionWarning } from "../model/semantic.ts";
|
|
5
|
+
/** A size condition whose rules hit captured elements; `container`: the serial stamped on the query container. */
|
|
6
|
+
export interface FoundCondition {
|
|
7
|
+
kind: "media" | "container";
|
|
8
|
+
query: string;
|
|
9
|
+
matches?: boolean;
|
|
10
|
+
container?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Walks every readable stylesheet (nested rules included). For `@media`/`@container` rules with a
|
|
14
|
+
* size condition, collects the selectors inside that match the captured root or its descendants
|
|
15
|
+
* (whether or not the condition holds now) and stamps the matching elements with CONDITIONAL_MARK
|
|
16
|
+
* (their query container with CONTAINER_MARK); marks elements an author rule styles through
|
|
17
|
+
* `:valid`/`:invalid` with VALIDATION_MARK. Call before DOMSnapshot A so the marks land in `attrs`.
|
|
18
|
+
* `breakpoints`: the conversion reconstructs width media queries, so they are not reported as losses.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readConditionalRules(page: Page, selector: string, viewportWidth: number, breakpoints?: boolean): Promise<{
|
|
21
|
+
warnings: ConversionWarning[];
|
|
22
|
+
found: FoundCondition[];
|
|
23
|
+
}>;
|
|
24
|
+
/** Moves the stamped marks into `conditional` and resolves container entries to node ids and `matches`. */
|
|
25
|
+
export declare function applyConditionMarks(root: LayoutNode, found: FoundCondition[]): LayoutCondition[];
|