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.
Files changed (146) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/LICENSE +21 -0
  3. package/README.md +592 -2
  4. package/dist/cli-jdrbzqfa.js +2975 -0
  5. package/dist/cli-qchh0m4d.js +14041 -0
  6. package/dist/cli.js +637 -0
  7. package/dist/compiler/index.js +20 -0
  8. package/dist/index.js +22 -0
  9. package/dist/types/analysis/alignment.d.ts +12 -0
  10. package/dist/types/analysis/bands.d.ts +53 -0
  11. package/dist/types/analysis/breakpoints.d.ts +22 -0
  12. package/dist/types/analysis/class-hints.d.ts +21 -0
  13. package/dist/types/analysis/context.d.ts +49 -0
  14. package/dist/types/analysis/controls.d.ts +97 -0
  15. package/dist/types/analysis/flex-row.d.ts +14 -0
  16. package/dist/types/analysis/flex-sizing.d.ts +5 -0
  17. package/dist/types/analysis/flow-layout.d.ts +18 -0
  18. package/dist/types/analysis/generated.d.ts +16 -0
  19. package/dist/types/analysis/geometry.d.ts +50 -0
  20. package/dist/types/analysis/grid-tracks.d.ts +44 -0
  21. package/dist/types/analysis/grid.d.ts +5 -0
  22. package/dist/types/analysis/infer.d.ts +18 -0
  23. package/dist/types/analysis/invisible.d.ts +6 -0
  24. package/dist/types/analysis/layers.d.ts +15 -0
  25. package/dist/types/analysis/measured-layout.d.ts +6 -0
  26. package/dist/types/analysis/motion.d.ts +29 -0
  27. package/dist/types/analysis/naming.d.ts +6 -0
  28. package/dist/types/analysis/node-base.d.ts +13 -0
  29. package/dist/types/analysis/size-constraints.d.ts +5 -0
  30. package/dist/types/analysis/sizing.d.ts +24 -0
  31. package/dist/types/analysis/style-background.d.ts +24 -0
  32. package/dist/types/analysis/style-border.d.ts +7 -0
  33. package/dist/types/analysis/style-effects.d.ts +4 -0
  34. package/dist/types/analysis/style.d.ts +9 -0
  35. package/dist/types/analysis/svg/attributes.d.ts +10 -0
  36. package/dist/types/analysis/svg/build.d.ts +6 -0
  37. package/dist/types/analysis/svg/context.d.ts +31 -0
  38. package/dist/types/analysis/svg/geometry.d.ts +11 -0
  39. package/dist/types/analysis/svg/gradients.d.ts +6 -0
  40. package/dist/types/analysis/svg/markup.d.ts +23 -0
  41. package/dist/types/analysis/svg/text.d.ts +7 -0
  42. package/dist/types/analysis/svg/transforms.d.ts +19 -0
  43. package/dist/types/analysis/svg/traversal.d.ts +4 -0
  44. package/dist/types/analysis/table-borders.d.ts +19 -0
  45. package/dist/types/analysis/table.d.ts +36 -0
  46. package/dist/types/analysis/text-layout.d.ts +65 -0
  47. package/dist/types/analysis/text-runs.d.ts +30 -0
  48. package/dist/types/analysis/text.d.ts +9 -0
  49. package/dist/types/analysis/tooltips.d.ts +16 -0
  50. package/dist/types/analysis/typography.d.ts +21 -0
  51. package/dist/types/analysis/wrapping.d.ts +5 -0
  52. package/dist/types/api/bands.d.ts +58 -0
  53. package/dist/types/api/build.d.ts +51 -0
  54. package/dist/types/api/convert.d.ts +13 -0
  55. package/dist/types/api/types.d.ts +69 -0
  56. package/dist/types/browser/capture.d.ts +89 -0
  57. package/dist/types/browser/conditions.d.ts +25 -0
  58. package/dist/types/browser/fonts.d.ts +34 -0
  59. package/dist/types/browser/images.d.ts +3 -0
  60. package/dist/types/browser/layers.d.ts +132 -0
  61. package/dist/types/browser/motion.d.ts +44 -0
  62. package/dist/types/browser/settle.d.ts +27 -0
  63. package/dist/types/browser/sizing.d.ts +10 -0
  64. package/dist/types/browser/snapshot.d.ts +155 -0
  65. package/dist/types/browser/states.d.ts +36 -0
  66. package/dist/types/cli/args.d.ts +31 -0
  67. package/dist/types/cli/config.d.ts +78 -0
  68. package/dist/types/cli/css.d.ts +9 -0
  69. package/dist/types/cli/manifest.d.ts +20 -0
  70. package/dist/types/cli/output.d.ts +27 -0
  71. package/dist/types/cli/run.d.ts +4 -0
  72. package/dist/types/cli.d.ts +2 -0
  73. package/dist/types/compiler/index.d.ts +91 -0
  74. package/dist/types/compiler/naming.d.ts +1 -0
  75. package/dist/types/css/background.d.ts +16 -0
  76. package/dist/types/css/blend.d.ts +9 -0
  77. package/dist/types/css/color.d.ts +14 -0
  78. package/dist/types/css/counter.d.ts +10 -0
  79. package/dist/types/css/easing.d.ts +4 -0
  80. package/dist/types/css/effects.d.ts +18 -0
  81. package/dist/types/css/grid.d.ts +29 -0
  82. package/dist/types/css/index.d.ts +15 -0
  83. package/dist/types/css/media.d.ts +16 -0
  84. package/dist/types/css/paint.d.ts +33 -0
  85. package/dist/types/css/radius.d.ts +5 -0
  86. package/dist/types/css/raster.d.ts +10 -0
  87. package/dist/types/css/shadows.d.ts +3 -0
  88. package/dist/types/css/syntax.d.ts +12 -0
  89. package/dist/types/css/transforms.d.ts +45 -0
  90. package/dist/types/css/typography.d.ts +8 -0
  91. package/dist/types/fonts/converter.d.ts +16 -0
  92. package/dist/types/fonts/metadata.d.ts +6 -0
  93. package/dist/types/fonts/package.d.ts +12 -0
  94. package/dist/types/fonts/registration.d.ts +13 -0
  95. package/dist/types/fonts/source.d.ts +14 -0
  96. package/dist/types/fonts/types.d.ts +28 -0
  97. package/dist/types/html/elements.d.ts +8 -0
  98. package/dist/types/html/index.d.ts +4 -0
  99. package/dist/types/html/inputs.d.ts +4 -0
  100. package/dist/types/html/policy.d.ts +3 -0
  101. package/dist/types/html/types.d.ts +12 -0
  102. package/dist/types/index.d.ts +8 -0
  103. package/dist/types/input/identity.d.ts +3 -0
  104. package/dist/types/input/mime.d.ts +1 -0
  105. package/dist/types/input/root.d.ts +1 -0
  106. package/dist/types/input/server.d.ts +11 -0
  107. package/dist/types/input/source.d.ts +9 -0
  108. package/dist/types/input/types.d.ts +54 -0
  109. package/dist/types/model/fonts.d.ts +26 -0
  110. package/dist/types/model/interactive.d.ts +10 -0
  111. package/dist/types/model/layout.d.ts +528 -0
  112. package/dist/types/model/semantic.d.ts +984 -0
  113. package/dist/types/model/values.d.ts +125 -0
  114. package/dist/types/model/version.d.ts +4 -0
  115. package/dist/types/swift/borders.d.ts +13 -0
  116. package/dist/types/swift/components.d.ts +115 -0
  117. package/dist/types/swift/context.d.ts +184 -0
  118. package/dist/types/swift/control-state.d.ts +19 -0
  119. package/dist/types/swift/controls.d.ts +62 -0
  120. package/dist/types/swift/diagnostics.d.ts +3 -0
  121. package/dist/types/swift/effects.d.ts +23 -0
  122. package/dist/types/swift/emit.d.ts +6 -0
  123. package/dist/types/swift/format.d.ts +91 -0
  124. package/dist/types/swift/frames.d.ts +17 -0
  125. package/dist/types/swift/images.d.ts +25 -0
  126. package/dist/types/swift/layout.d.ts +5 -0
  127. package/dist/types/swift/measured-layout.d.ts +4 -0
  128. package/dist/types/swift/modifiers.d.ts +30 -0
  129. package/dist/types/swift/motion.d.ts +20 -0
  130. package/dist/types/swift/nodes.d.ts +4 -0
  131. package/dist/types/swift/paint.d.ts +22 -0
  132. package/dist/types/swift/runtime.d.ts +6 -0
  133. package/dist/types/swift/shadows.d.ts +7 -0
  134. package/dist/types/swift/states.d.ts +3 -0
  135. package/dist/types/swift/svg.d.ts +14 -0
  136. package/dist/types/swift/text-box.d.ts +12 -0
  137. package/dist/types/swift/text.d.ts +3 -0
  138. package/dist/types/swift/tokens/emit.d.ts +26 -0
  139. package/dist/types/swift/tokens/extract.d.ts +21 -0
  140. package/dist/types/swift/tokens/naming.d.ts +22 -0
  141. package/dist/types/swift/tokens/slots.d.ts +18 -0
  142. package/dist/types/swift/tokens/types.d.ts +77 -0
  143. package/dist/types/swift/tokens.d.ts +6 -0
  144. package/dist/types/swift/traversal.d.ts +2 -0
  145. package/dist/types/swift/wrapping.d.ts +4 -0
  146. package/package.json +66 -4
@@ -0,0 +1,91 @@
1
+ import { LayoutDoc } from "../model/layout.ts";
2
+ import { type EmitMode, type SwiftOutput } from "../swift/emit.ts";
3
+ import { type PaletteMap } from "../swift/tokens.ts";
4
+ import type { FaceMetrics, BundledFamily } from "../model/fonts.ts";
5
+ import type { ConversionWarning } from "../model/semantic.ts";
6
+ export type { Diagnostic, DiagnosticLevel, Confidence, ConversionWarning } from "../model/semantic.ts";
7
+ export interface CompileOptions {
8
+ /** Complete Swift type name, e.g. ProfileCard. ASCII identifiers starting with uppercase. */
9
+ name?: string;
10
+ mode?: EmitMode;
11
+ bundledFamilies?: Record<string, BundledFamily>;
12
+ fontMetrics?: Record<string, FaceMetrics>;
13
+ /**
14
+ * Dark capture of the same screen; `layout` must then be the light one. The view is emitted
15
+ * from the light layout and every colour that differs in dark becomes a `Color.markswift(light:dark:)` token.
16
+ */
17
+ dark?: LayoutDoc;
18
+ /**
19
+ * Capture of the same screen and theme at another viewport width. Admitted MarkswiftTracks/MarkswiftFlexRow nodes
20
+ * whose authored inputs do not reproduce the probe geometry within 1px fall back to pinned output with a diagnostic.
21
+ */
22
+ probe?: LayoutDoc;
23
+ /** Breakpoint conversion: captures of the same screen and theme at the other width bands, ascending by viewport
24
+ * width; `layout` is band 0. Their shared `conditions` define the band edges. A page with width `@container` queries
25
+ * may hold more than one capture per band (`BandPlan.extra`); the lowest of a band represents it. */
26
+ variants?: LayoutDoc[];
27
+ /** Dark captures of `variants`, same order; required when `dark` is set with `variants`. */
28
+ darkVariants?: LayoutDoc[];
29
+ /** Probe capture per variant (same order), as `probe` is for `layout`. */
30
+ variantProbes?: Array<LayoutDoc | undefined>;
31
+ /** @internal Pixel-identity check only: disables repeated-sibling extraction. */
32
+ extract?: boolean;
33
+ /** `public` for a generated library (plan 033's `build`); `convert` stays internal. Default `internal`. */
34
+ visibility?: "internal" | "public";
35
+ /** App colours for captured tokens (`--palette`); views keep referencing `Palette.x`. */
36
+ palette?: PaletteMap;
37
+ }
38
+ export interface CompileResult {
39
+ name: string;
40
+ code: string;
41
+ /** All Swift sources needed by this view, including shared runtime helpers. */
42
+ files: Record<string, string>;
43
+ diagnostics: SwiftOutput["report"];
44
+ /** Binary resources referenced by the generated Swift (relative bundle path → bytes), e.g. `Images/<hash>.png`. Add these resources to the iOS target. */
45
+ assets: Record<string, Uint8Array>;
46
+ /** Light/dark pairing limitations and palette-map gaps; empty for a single-theme compile without a map. */
47
+ warnings: ConversionWarning[];
48
+ /** App mode: layer id → the `init` label (`isMoreExpanded`, `isEditProfilePresented`) that shows it; absent when nothing opens. */
49
+ openStates?: Record<string, string>;
50
+ }
51
+ /** Compile a captured layout. Custom fonts must be packaged by the caller and passed explicitly. */
52
+ export declare function compileLayout(layout: LayoutDoc, options?: CompileOptions): CompileResult;
53
+ /** A runtime Layout (MarkswiftTracks, MarkswiftFlexRow) would reflow some node of `layout`: a probe capture can verify it. */
54
+ export declare function needsProbe(layout: LayoutDoc): boolean;
55
+ export { planBands, BAND_MIN, BAND_CAP, DEFAULT_BAND_DEVICES, type BandPlan } from "../analysis/bands.ts";
56
+ export interface LibraryComponent {
57
+ name: string;
58
+ layout: LayoutDoc;
59
+ dark?: LayoutDoc;
60
+ /** Breakpoint component: captures at the other width bands, as `CompileOptions.variants`. */
61
+ variants?: LayoutDoc[];
62
+ /** Dark captures of `variants`, as `CompileOptions.darkVariants`. */
63
+ darkVariants?: LayoutDoc[];
64
+ mode?: EmitMode;
65
+ }
66
+ export interface LibraryOptions extends Pick<CompileOptions, "bundledFamilies" | "fontMetrics" | "palette"> {
67
+ /** Library (Swift module) name; must differ from every component name. */
68
+ library: string;
69
+ /** Add `BundledFonts.register()` to every preview (the package bundles fonts). */
70
+ registerFonts?: boolean;
71
+ }
72
+ export interface LibraryResult {
73
+ /** Module sources, relative to `Sources/<library>/`. */
74
+ files: Record<string, string>;
75
+ assets: Record<string, Uint8Array>;
76
+ /** Per-component compile warnings, each with `component` set to the component name; palette-map warnings are library-wide. */
77
+ warnings: ConversionWarning[];
78
+ diagnostics: Record<string, CompileResult["diagnostics"]>;
79
+ }
80
+ /** Library and component names of one build: valid Swift types, unique ignoring case, none named like the library. */
81
+ export declare function validateLibrary(library: string, components: string[]): void;
82
+ /**
83
+ * Compile many captured components into the sources of one Swift module: one token set over every
84
+ * screen, so one name per light/dark value pair, emitted as a module-level `public enum Palette`
85
+ * (`MarkswiftPalette.swift`); shapes deduplicated into `MarkswiftShapes.swift`; one runtime;
86
+ * public views. Views reference bare `Palette.x`/`MarkswiftShape_x`, which resolve to these.
87
+ */
88
+ export declare function compileLayouts(components: LibraryComponent[], options: LibraryOptions): LibraryResult;
89
+ export type { LayoutDoc } from "../model/layout.ts";
90
+ export type { EmitMode } from "../swift/emit.ts";
91
+ export type { PaletteMap } from "../swift/tokens.ts";
@@ -0,0 +1 @@
1
+ export declare function validateName(name: string): void;
@@ -0,0 +1,16 @@
1
+ import type { BackgroundRepeat, BackgroundSize } from "../model/values.ts";
2
+ /** Computed `background-repeat` (first layer) → one of the four tile modes; `space`/`round` → `repeat`. */
3
+ export declare function parseBackgroundRepeat(s: string | undefined): BackgroundRepeat | undefined;
4
+ /**
5
+ * One `background-size` layer (first layer of a comma list) → px box, `cover`/`contain`,
6
+ * or undefined when it depends on the image's intrinsic size (`auto`) and `imgW`/`imgH`
7
+ * are not given. `auto` on one axis keeps the image aspect ratio.
8
+ */
9
+ export declare function parseBackgroundSize(s: string | undefined, boxW: number, boxH: number, imgW?: number, imgH?: number): BackgroundSize | undefined;
10
+ /**
11
+ * One `background-position` layer → `[x, y]` px offset of the image's top-left corner.
12
+ * Handles px, `%`, `calc()`, side keywords (`left center right top bottom`) and the
13
+ * 3/4-value `right 10px bottom 20px` form. Percentages and far-side offsets resolve
14
+ * against `box − image` when `imgW`/`imgH` are given, else against the box.
15
+ */
16
+ export declare function parseBackgroundPosition(s: string | undefined, boxW: number, boxH: number, imgW?: number, imgH?: number): [number, number];
@@ -0,0 +1,9 @@
1
+ import { type BlendMode } from "../model/values.ts";
2
+ /** One `<blend-mode>` keyword; `undefined` for anything outside the spec's list. */
3
+ export declare function parseBlendMode(s: string | undefined): BlendMode | undefined;
4
+ /**
5
+ * `background-blend-mode`: one keyword per background layer, in CSS layer order (top-most
6
+ * first), cycled by the caller when there are more layers than keywords. An unrecognised
7
+ * keyword yields `normal` so a layer is never silently dropped.
8
+ */
9
+ export declare function parseBlendModes(s: string | undefined): BlendMode[];
@@ -0,0 +1,14 @@
1
+ /** Pure color interpretation of browser-resolved CSS values. */
2
+ import type { Color } from "../model/values.ts";
3
+ export declare const TRANSPARENT: Color;
4
+ /** CSS named colours. Computed styles never use them, but attribute-only SVG markup (data: images) does. */
5
+ export declare const NAMED_COLORS: Record<string, string>;
6
+ /**
7
+ * Any CSS color Chrome serialises: `transparent`, `#hex` (3/4/6/8), legacy and modern
8
+ * `rgb()/rgba()`, `hsl()/hsla()`, `hwb()`, `lab()/lch()`, `oklab()/oklch()`, and
9
+ * `color(<space> …)` for the CSS Color 4 predefined spaces. Non-sRGB inputs are converted
10
+ * through XYZ D65, clipped to the sRGB gamut and rounded to 4 decimals. Unknown → undefined.
11
+ */
12
+ export declare function parseColor(s: string | undefined): Color | undefined;
13
+ /** Hue component in degrees (`deg`, `rad`, `grad`, `turn`, bare number, `none`). */
14
+ export declare function hue(t: string): number | undefined;
@@ -0,0 +1,10 @@
1
+ import type { CounterStyle } from "../model/semantic.ts";
2
+ /** `list-style-type` / `counter()` styles whose text Markswift can regenerate; Chrome's `*-latin` print as `*-alpha`. */
3
+ export declare const COUNTER_STYLES: Readonly<Record<string, CounterStyle>>;
4
+ /** A counter value as Chrome prints it; alphabetic below 1 and roman outside 1…3999 fall back to decimal. Mirror: `markswiftCounter` (runtime/counter.swift). */
5
+ export declare function counterText(value: number, style: CounterStyle): string;
6
+ /** The counter value at the start of `text` (after `prefix`), and the rest; undefined unless `counterText` reproduces it. */
7
+ export declare function parseCounter(text: string, style: CounterStyle, prefix?: string): {
8
+ value: number;
9
+ suffix: string;
10
+ } | undefined;
@@ -0,0 +1,4 @@
1
+ /** CSS easing functions (css-easing-2) → IR `Easing`. */
2
+ import type { Easing } from "../model/semantic.ts";
3
+ /** `ease`, `cubic-bezier(…)`, `steps(…)`, `linear(…)` → IR; undefined when it is not a valid easing function. */
4
+ export declare function parseEasing(s: string): Easing | undefined;
@@ -0,0 +1,18 @@
1
+ /** Pure effects interpretation of browser-resolved CSS values. */
2
+ import type { ClipShape, Filter } from "../model/semantic.ts";
3
+ /**
4
+ * Computed `filter` list → ordered entries. Chrome serialises amounts as bare numbers
5
+ * (`grayscale(1)`), lengths in px and angles in deg. `url()` and unknown functions land
6
+ * in `unsupported` (raw text) so the caller can note them.
7
+ */
8
+ export declare function parseFilters(s: string | undefined): {
9
+ filters: Filter[];
10
+ unsupported: string[];
11
+ };
12
+ /**
13
+ * Computed `clip-path` basic shape → px geometry inside a `w`×`h` box. Handles
14
+ * `circle(r at x y)`, `ellipse(rx ry at x y)`, `inset(t r b l round …)`, `polygon(…)`
15
+ * with px/%/`closest-side`/`farthest-side` and `at` keywords. `none`, `path()`, `url()`
16
+ * and reference boxes → undefined.
17
+ */
18
+ export declare function parseClipPath(s: string | undefined, w: number, h: number): ClipShape | undefined;
@@ -0,0 +1,29 @@
1
+ import type { GridRowTrack, GridTemplate } from "../model/semantic.ts";
2
+ /** Browser-resolved grid tracks; authored repeat/fr/subgrid values remain unresolved. */
3
+ export declare function resolvedGridTracks(value: string | undefined): number[] | undefined;
4
+ /** Authored Typed-OM template → tracks; undefined for anything MarkswiftTracks cannot reproduce. */
5
+ export declare function parseTrackTemplate(value: string | undefined): GridTemplate | undefined;
6
+ /** Authored `grid-template-rows` / computed `grid-auto-rows` → rows MarkswiftTracks sizes; undefined otherwise. */
7
+ export declare function parseRowTracks(value: string | undefined): GridRowTrack[] | undefined;
8
+ export interface GridArea {
9
+ colStart: number;
10
+ colEnd: number;
11
+ rowStart: number;
12
+ rowEnd: number;
13
+ }
14
+ /** Computed `grid-template-areas` → each named area's 1-based lines and the areas' row/column counts; `none` → empty. */
15
+ export declare function parseGridAreas(value: string | undefined): {
16
+ areas: Record<string, GridArea>;
17
+ rows: number;
18
+ columns: number;
19
+ } | undefined;
20
+ /**
21
+ * CSS grid §8.3 for one axis: computed start/end longhands → 1-based start line (absent = auto-placed) and span.
22
+ * `lines` = the explicit grid's line count on this axis (negative lines count back from it). Area names (also
23
+ * `<area>-start`/`<area>-end`) resolve through `areas`. Undefined for what MarkswiftTracks cannot place: named lines
24
+ * of the template, `span <name>`, `<n> <name>`, or a line before the grid's first.
25
+ */
26
+ export declare function gridSpan(start: string | undefined, end: string | undefined, areas: Record<string, GridArea>, axis: "col" | "row", lines: number): {
27
+ start?: number;
28
+ span: number;
29
+ } | undefined;
@@ -0,0 +1,15 @@
1
+ /** Public CSS parser surface; implementations are grouped by CSS responsibility. Code outside css/ imports from here. */
2
+ export { parseColor } from "./color.ts";
3
+ export { px, parseDeclared, splitTop, resolveLength, round2 } from "./syntax.ts";
4
+ export { parseBlendMode, parseBlendModes } from "./blend.ts";
5
+ export { contentAlt, cssUrls, paintWithin, parseBackgroundImage, resolvePaint } from "./paint.ts";
6
+ export { COUNTER_STYLES, counterText, parseCounter } from "./counter.ts";
7
+ export { parseShadows } from "./shadows.ts";
8
+ export { type TransformLoss, parseTransform, parseOrigin, cssTransform } from "./transforms.ts";
9
+ export { parseFilters, parseClipPath } from "./effects.ts";
10
+ export { parseBackgroundRepeat, parseBackgroundSize, parseBackgroundPosition } from "./background.ts";
11
+ export { rasterSize } from "./raster.ts";
12
+ export { fontWeight, fontFamilies, fontStretch, variationSettings } from "./typography.ts";
13
+ export { parseRadiusXY } from "./radius.ts";
14
+ export { type GridArea, gridSpan, parseGridAreas, parseRowTracks, parseTrackTemplate, resolvedGridTracks, } from "./grid.ts";
15
+ export { type WidthQuery, widthQuery, passes, matchesWidth, captureWidth, bandOf } from "./media.ts";
@@ -0,0 +1,16 @@
1
+ /** Width `@media`/`@container` conditions as band edges: the thresholds a breakpoint capture plans bands from. */
2
+ import type { BandEdge } from "../model/semantic.ts";
3
+ /** A pure width condition: `above` = lower limit (width must pass it), `below` = upper limit (width must not). */
4
+ export interface WidthQuery {
5
+ above?: BandEdge;
6
+ below?: BandEdge;
7
+ }
8
+ /** Chrome's `conditionText` as a width condition; `undefined` when it is not one this parser reconstructs. */
9
+ export declare function widthQuery(query: string): WidthQuery | undefined;
10
+ /** `width` is past `edge`: `inclusive ? w >= px : w > px`. */
11
+ export declare function passes(edge: BandEdge, width: number): boolean;
12
+ export declare function matchesWidth(q: WidthQuery, width: number): boolean;
13
+ /** First integer width past the edge. */
14
+ export declare function captureWidth(edge: BandEdge): number;
15
+ /** Band index of `width`: the number of (ascending) edges it passes. */
16
+ export declare function bandOf(width: number, edges: BandEdge[]): number;
@@ -0,0 +1,33 @@
1
+ import type { Paint } from "../model/values.ts";
2
+ /**
3
+ * Re-express a gradient painted over `host` so that the same colours land on `sub` (both
4
+ * boxes in one coordinate space): linear stops are projected onto `sub`'s span of the
5
+ * gradient line and cut to 0..1; radial/conic centers move. Used for `background-clip:
6
+ * text`, where the browser paints across the block but the glyph run is what gets filled.
7
+ */
8
+ export declare function paintWithin(p: Paint, host: {
9
+ x: number;
10
+ y: number;
11
+ w: number;
12
+ h: number;
13
+ }, sub: {
14
+ x: number;
15
+ y: number;
16
+ w: number;
17
+ h: number;
18
+ }): Paint;
19
+ /** Computed `background-image` → paints, bottom-most first. `dropped` collects the parts a gradient could not read. */
20
+ export declare function parseBackgroundImage(s: string | undefined, dropped?: string[]): Paint[];
21
+ /** Every `url(…)` in a computed value, in order, unquoted and unescaped (`content`, `list-style-image`). */
22
+ export declare function cssUrls(value: string | undefined): string[];
23
+ /** The alternative text of a computed `content` (the quoted strings after a top-level ` / `, joined); undefined without one. */
24
+ export declare function contentAlt(value: string | undefined): string | undefined;
25
+ export declare function fraction(t: string): number | undefined;
26
+ export declare const COLOR_TOKEN: string;
27
+ /**
28
+ * Resolve a gradient's px stops against the box it paints: linear stops divide by the
29
+ * gradient-line length (`|w·sin θ| + |h·cos θ|`), radial stops by the farthest-corner
30
+ * distance from the center. Non-repeating stops clamp to 0..1; repeating ones keep their
31
+ * period so the consumer can tile. Paints without px stops are returned as-is.
32
+ */
33
+ export declare function resolvePaint(p: Paint, w: number, h: number): Paint;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * One `border-*-radius` corner → `[horizontal, vertical]` px. A single value applies to
3
+ * both axes; `%` resolves against `refW` (horizontal) / `refH` (vertical) as in CSS.
4
+ */
5
+ export declare function parseRadiusXY(s: string | undefined, refW: number, refH: number): [number, number];
@@ -0,0 +1,10 @@
1
+ /** Natural size of an embedded raster from its header bytes; no image decoder. */
2
+ /**
3
+ * A raster `data:` URL → its natural size in CSS px (one pixel each): PNG, GIF, JPEG (EXIF
4
+ * orientations 5–8 swap the axes, as Chrome's `image-orientation: from-image` draws them) and
5
+ * WebP (VP8, VP8L, VP8X). `undefined` for any other URL, format or a truncated header.
6
+ */
7
+ export declare function rasterSize(url: string): {
8
+ w: number;
9
+ h: number;
10
+ } | undefined;
@@ -0,0 +1,3 @@
1
+ import type { Shadow } from "../model/values.ts";
2
+ /** Computed `box-shadow`: `rgba(…) 0px 12px 34px 0px[, …][ inset]`. `dropped` collects the shadows it could not read. */
3
+ export declare function parseShadows(s: string | undefined, dropped?: string[]): Shadow[];
@@ -0,0 +1,12 @@
1
+ /** Pure syntax interpretation of browser-resolved CSS values. */
2
+ export declare function px(s: string | undefined): number;
3
+ /** Declared inline style → property map (lower-cased names, trimmed values). */
4
+ export declare function parseDeclared(style: string | undefined): Record<string, string>;
5
+ /** Split on `sep` at paren depth 0 (for comma-separated lists containing function calls). */
6
+ export declare function splitTop(s: string, sep: string): string[];
7
+ /**
8
+ * `<length-percentage>` → px against `ref`: `12px`, `50%`, `0`, or a linear
9
+ * `calc(100% - 10px)` mixing px and % terms. Unknown units → undefined.
10
+ */
11
+ export declare function resolveLength(t: string, ref: number): number | undefined;
12
+ export declare function round2(v: number): number;
@@ -0,0 +1,45 @@
1
+ import type { Transform2D } from "../model/values.ts";
2
+ /**
3
+ * Computed `transform: matrix(a, b, c, d, tx, ty)` or `matrix3d(…)` → rotation/scale/skew/
4
+ * translation (2 decimals). A 3D matrix keeps only its x/y affine part (orthographic
5
+ * flattening, the way a `rotateY(30deg)` looks squeezed) and is marked `flattened`.
6
+ */
7
+ export declare function parseTransform(s: string | undefined): Transform2D | undefined;
8
+ export interface TransformLoss {
9
+ level: "approximated" | "unmapped";
10
+ feature: "translate" | "rotate" | "transform" | "transform: matrix3d()";
11
+ message: string;
12
+ }
13
+ /** One `translate` component: `±Npx`/`±N%` terms, optionally in `calc(…)`; `%` of `ref`. */
14
+ export declare function translateLength(t: string, ref: number): number | undefined;
15
+ /**
16
+ * Animatable 2D channels of one transform value; `order` = its function kinds (`T`ranslate, `R`otate, `S`cale) in list
17
+ * order, runs merged. Identity functions (tw-animate's `rotate(0deg)`, `scale3d(1, 1, 1)`) compose nothing: no kind.
18
+ */
19
+ export interface TransformChannels {
20
+ tx: number;
21
+ ty: number;
22
+ sx: number;
23
+ sy: number;
24
+ deg: number;
25
+ order: string;
26
+ }
27
+ /**
28
+ * A keyframe's `transform` / `translate` / `scale` / `rotate` value → channels (`w`/`h` = border box for `%`).
29
+ * Only translate*, scale*, rotate/rotateZ (z parts ignored: no perspective); anything else → undefined.
30
+ * A list is composed T·R·S only when `order` is a subsequence of `TRS` — the caller checks.
31
+ */
32
+ export declare function transformChannels(property: "transform" | "translate" | "scale" | "rotate", value: string, w: number, h: number): TransformChannels | undefined;
33
+ /**
34
+ * The element's whole 2D transform, composed the CSS Transforms 2 way:
35
+ * translate · rotate · scale · transform, all about one transform-origin.
36
+ * `w`/`h` = border box (the reference box for % translations). `losses` = what could not be represented.
37
+ */
38
+ export declare function cssTransform(s: Record<string, string | undefined>, w: number, h: number): {
39
+ transform?: Omit<Transform2D, "flattened"> & {
40
+ origin?: [number, number];
41
+ };
42
+ losses: TransformLoss[];
43
+ };
44
+ /** `transform-origin: 17px 158px` → px pair. */
45
+ export declare function parseOrigin(s: string | undefined): [number, number] | undefined;
@@ -0,0 +1,8 @@
1
+ /** Numeric font-weight from computed value (`700`, `bold`, `normal`). */
2
+ export declare function fontWeight(s: string | undefined): number;
3
+ /** First family in a computed font-family list, unquoted. */
4
+ export declare function fontFamilies(s: string | undefined): string[];
5
+ /** Computed `font-variation-settings` (`"GRAD" -20, "wght" 650`) → axis tag → value; `normal` → {}. */
6
+ export declare function variationSettings(s: string | undefined): Record<string, number>;
7
+ /** Computed `font-stretch` in % (Chrome serialises keywords as `75%`); 100 when absent or unparsable. */
8
+ export declare function fontStretch(s: string | undefined): number;
@@ -0,0 +1,16 @@
1
+ export interface FontToolResult {
2
+ upem: number;
3
+ ascent: number;
4
+ descent: number;
5
+ lineGap: number;
6
+ useTypoMetrics: boolean;
7
+ axes: Record<string, [number, number]>;
8
+ converted: boolean;
9
+ renamed: boolean;
10
+ /** Rewritten sfnt bytes; absent when the input already registers under `family` as-is. */
11
+ bytes?: Uint8Array;
12
+ }
13
+ /** Decompress WOFF/WOFF2 and rewrite the name table so `family` resolves; a string is the failure reason. */
14
+ export type FontConverter = (bytes: Uint8Array, family: string, subfamily: string, signal?: AbortSignal) => Promise<FontToolResult | string>;
15
+ /** python3 + fontTools. The only temp files in font packaging live and die here. */
16
+ export declare const pythonFontConverter: FontConverter;
@@ -0,0 +1,6 @@
1
+ import type { BundledFamilies, FontMetrics } from "../model/fonts.ts";
2
+ import type { FontPackage } from "./types.ts";
3
+ /** Metrics captured by this package, isolated from all other conversions. */
4
+ export declare function metricsForFonts(pkg: FontPackage): FontMetrics;
5
+ /** Families of a package, in the shape the inference pass resolves `font-family` against. */
6
+ export declare function bundledFamilies(pkg: FontPackage): BundledFamilies;
@@ -0,0 +1,12 @@
1
+ import type { FontFace } from "../model/layout.ts";
2
+ import type { FontPackage } from "./types.ts";
3
+ import { type FontConverter } from "./converter.ts";
4
+ /**
5
+ * Packages every bundleable face: faces + their captured bytes in, `Fonts/<file>` assets out.
6
+ *
7
+ * `sources` holds the capture's font bytes keyed by `src[].file`; `data:` sources carry their
8
+ * own. Faces are grouped by (family, style): within a group the Basic-Latin subset wins, the
9
+ * rest are reported. A face whose bytes cannot be read, or whose format iOS cannot load and
10
+ * `convert` cannot convert, is noted and left out of the package; no asset is shipped for it.
11
+ */
12
+ export declare function packageFonts(faces: FontFace[], sources: ReadonlyMap<string, Uint8Array>, convert?: FontConverter, signal?: AbortSignal): Promise<FontPackage>;
@@ -0,0 +1,13 @@
1
+ import type { PackagedFace } from "./types.ts";
2
+ /** `UIAppFonts` array for `Info.plist` — the app-target half of loading a bundled font. */
3
+ export declare function plistFragment(files: string[]): string;
4
+ /**
5
+ * `<View>+Fonts.swift`: the runtime half. `UIAppFonts` only works for a real app bundle, so the
6
+ * generated code registers the same files with CoreText — the mechanism the render harness
7
+ * already uses (`MarkswiftFonts.register`), reused rather than duplicated, so a generated view renders
8
+ * identically in the harness, in `#Preview` and in the app. Nested in the view type
9
+ * (`<View>.BundledFonts`) so several conversions coexist in one target. Without `owner` it is the
10
+ * module-level `public enum BundledFonts` of a generated library package (`markswift build`), which
11
+ * reads `Bundle.module` itself: a public default argument cannot name the internal `Bundle.module`.
12
+ */
13
+ export declare function registrationSwift(faces: PackagedFace[], owner?: string): string;
@@ -0,0 +1,14 @@
1
+ import type { FontFace } from "../model/layout.ts";
2
+ /** Codepoints a face must cover to be the one worth bundling: Basic Latin. */
3
+ export declare function coversLatin(range: string | undefined): boolean;
4
+ /** Bytes behind one `src` entry: the `data:` URL itself, or the captured bytes keyed by `src.file`. */
5
+ export declare function srcBytes(src: FontFace["src"][number], sources: ReadonlyMap<string, Uint8Array>): Uint8Array | undefined;
6
+ /** OpenType weight class → the subfamily name a font file conventionally carries for it. */
7
+ export declare const WEIGHT_SUBFAMILY: Record<number, string>;
8
+ /**
9
+ * File stem for a packaged face, unique within one package case-insensitively (as `writeBundle` checks).
10
+ * `claimed` maps lower-cased stems already written to their CSS family. Returns `undefined` when this exact
11
+ * family already owns the stem: the same family+subfamily twice (italic and oblique, or a static 400 and a
12
+ * variable Regular) would register one PostScript name twice on iOS, so only the first can be bundled.
13
+ */
14
+ export declare function fontFileStem(family: string, subfamily: string, claimed: ReadonlyMap<string, string>): string | undefined;
@@ -0,0 +1,28 @@
1
+ import type { FaceMetrics } from "../model/fonts.ts";
2
+ import type { ConversionWarning } from "../model/semantic.ts";
3
+ /** A face bundled with the generated Swift; its bytes are `FontPackage.assets["Fonts/<file>"]`. */
4
+ export interface PackagedFace {
5
+ /** CSS family name — what `font-family` declarations say and what the emitter emits. */
6
+ family: string;
7
+ /** File name under `Fonts/`. */
8
+ file: string;
9
+ style: "normal" | "italic" | "oblique";
10
+ /** `font-weight` range the face covers; `[400, 400]` for a static face. */
11
+ weight: [number, number];
12
+ /** Variation axis ranges, by tag (`wght`, `opsz`, `wdth`); empty for a static face. */
13
+ axes: Record<string, [number, number]>;
14
+ metrics: FaceMetrics;
15
+ /** Source format was WOFF/WOFF2 and the file was decompressed to sfnt. */
16
+ converted: boolean;
17
+ /** The name table was rewritten so the CSS family name resolves. */
18
+ renamed: boolean;
19
+ }
20
+ export interface FontPackage {
21
+ faces: PackagedFace[];
22
+ /** `Fonts/<file>` → bytes to ship; exactly one entry per packaged face. */
23
+ assets: Record<string, Uint8Array>;
24
+ /** `Info.plist` `UIAppFonts` fragment; empty when nothing was packaged. */
25
+ plist: string;
26
+ /** What the design asked for and did not get. */
27
+ notes: ConversionWarning[];
28
+ }
@@ -0,0 +1,8 @@
1
+ import type { ElementPolicy } from "./types.ts";
2
+ /** WHATWG element index, checked 2026-09-16, including SVG and MathML entry points.
3
+ * https://html.spec.whatwg.org/multipage/indices.html
4
+ * Browser-computed display/geometry decides layout; these policies decide exceptional semantics.
5
+ * "implemented" means a compiler path exists. CSS combinations, accessibility and behavior
6
+ * require their own tests and are not established by this registry.
7
+ */
8
+ export declare const HTML_ELEMENTS: Readonly<Record<string, ElementPolicy>>;
@@ -0,0 +1,4 @@
1
+ export { HTML_ELEMENTS } from "./elements.ts";
2
+ export { INPUT_CONTROLS } from "./inputs.ts";
3
+ export { classifyElement } from "./policy.ts";
4
+ export type { ElementPolicy, ElementRoute, ElementSupport } from "./types.ts";
@@ -0,0 +1,4 @@
1
+ import type { ControlKind } from "../model/semantic.ts";
2
+ /** Attribute-specific native routing. The analyzer and capability policy share this table. */
3
+ export declare const INPUT_CONTROLS: Readonly<Record<string, ControlKind>>;
4
+ export declare const INPUT_PLACEHOLDERS: Readonly<Record<string, string>>;
@@ -0,0 +1,3 @@
1
+ import type { ElementPolicy } from "./types.ts";
2
+ /** Pure attribute-based classification, also used before the analyzer merges inline text. */
3
+ export declare function classifyElement(tag: string, attrs?: Record<string, string>): ElementPolicy;
@@ -0,0 +1,12 @@
1
+ import type { Diagnostic } from "../model/semantic.ts";
2
+ /** Compiler strategies describe routing, not a promise of pixel-perfect or behavioral coverage. */
3
+ export type ElementRoute = "flow" | "text" | "control" | "image" | "svg" | "line-break" | "metadata" | "placeholder";
4
+ export type ElementSupport = "implemented" | "approximated" | "unsupported" | "nonvisual";
5
+ export interface ElementPolicy {
6
+ readonly route: ElementRoute;
7
+ readonly support: ElementSupport;
8
+ /** An atomic element must reach inference instead of being swallowed by its parent's text. */
9
+ readonly atomic: boolean;
10
+ readonly known: boolean;
11
+ readonly diagnostic?: Diagnostic;
12
+ }
@@ -0,0 +1,8 @@
1
+ export { convert, convertHtml } from "./api/convert.ts";
2
+ export type { HtmlSource, ConvertOptions, ConversionResult } from "./api/types.ts";
3
+ export { buildLibrary } from "./api/build.ts";
4
+ export type { BuildOptions, BuildComponent, BuildResult } from "./api/build.ts";
5
+ export { compileLayout, compileLayouts } from "./compiler/index.ts";
6
+ export type { CompileOptions, LibraryComponent, LibraryOptions, LibraryResult, CompileResult, LayoutDoc, EmitMode, PaletteMap, Diagnostic, DiagnosticLevel, Confidence, ConversionWarning, } from "./compiler/index.ts";
7
+ export { HTML_ELEMENTS, INPUT_CONTROLS, classifyElement } from "./html/index.ts";
8
+ export type { ElementPolicy, ElementRoute, ElementSupport } from "./html/index.ts";
@@ -0,0 +1,3 @@
1
+ import type { NodeIdentity } from "./types.ts";
2
+ /** Stable names shared by all HTML inputs, independent of stylesheet origin. */
3
+ export declare const htmlIdentity: NodeIdentity;
@@ -0,0 +1 @@
1
+ export declare function mimeType(path: string): string;
@@ -0,0 +1 @@
1
+ export declare const DEFAULT_ROOT = "[data-markswift-root], body:not(:has([data-markswift-root]))";
@@ -0,0 +1,11 @@
1
+ export interface StaticServer {
2
+ /** `http://127.0.0.1:<port>` */
3
+ origin: string;
4
+ stop(): void;
5
+ }
6
+ /**
7
+ * Serve `rootDir` on an ephemeral port. Refused: a Host other than this server's own
8
+ * `127.0.0.1:<port>` (403, DNS rebinding), malformed percent-encoding (400), any dot-segment
9
+ * such as `.env` or `.git/` (404), and paths resolving outside the root (403).
10
+ */
11
+ export declare function serveDir(rootDir: string): Promise<StaticServer>;
@@ -0,0 +1,9 @@
1
+ import type { HtmlSource } from "./types.ts";
2
+ export interface ResolvedSource {
3
+ html?: string;
4
+ url: string;
5
+ label: string;
6
+ close(): void;
7
+ }
8
+ /** Resolve source-relative assets and own any temporary HTTP serving for this source. */
9
+ export declare function resolveSource(source: HtmlSource): Promise<ResolvedSource>;
@@ -0,0 +1,54 @@
1
+ /** Browser capture contract, independent of source frameworks and corpus tooling. */
2
+ import type { Page } from "playwright-core";
3
+ import type { Layer, Theme } from "../model/layout.ts";
4
+ /** An element the open-state pass activates (`browser/layers.ts`). */
5
+ export interface Trigger {
6
+ /** Element path from the capture root. */
7
+ path: string;
8
+ activation: Layer["activation"];
9
+ /** Set by the native rules (`popovertarget`, `commandfor`, `interestfor`, `details`). */
10
+ relation?: Layer["relation"];
11
+ /** Layer id: slug of the trigger's name, unique per page. */
12
+ id: string;
13
+ /** LayoutNode id of the trigger. */
14
+ trigger: string;
15
+ }
16
+ export interface CaptureRequest {
17
+ /** Logical screen name (`home`). */
18
+ screen: string;
19
+ theme: Theme;
20
+ /** Fully-qualified URL, served by the source preparer. */
21
+ url: string;
22
+ /** Optional document served at `url`; relative resources resolve against that URL. */
23
+ html?: string;
24
+ /** CSS selector of the capture root; its box is the coordinate origin and screenshot clip. */
25
+ root: string;
26
+ /** Selector that must be attached before capture (mount check). Defaults to `root`. */
27
+ waitFor?: string;
28
+ /** Also take a device-scale screenshot clipped to the capture root (`Capture.png`). */
29
+ screenshot?: boolean;
30
+ /** Capture at this viewport instead of the browser context's (probe captures). */
31
+ viewport?: {
32
+ width: number;
33
+ height: number;
34
+ };
35
+ /** Hook after load, before settle (class toggles etc.). */
36
+ prepare?(page: Page): Promise<void>;
37
+ /** Internal to the layer pass: open this trigger and report what it shows (`Capture.opened`). */
38
+ open?: Trigger;
39
+ /** Internal to the layer pass: with `open`, also probe how the layer is dismissed. */
40
+ probeDismiss?: boolean;
41
+ /** The conversion reconstructs width media queries: they are not reported as losses. */
42
+ breakpoints?: boolean;
43
+ }
44
+ /** Stable node identity for re-sync. `path` = element-index path from the capture root ("0/2/1"); `tag` lower-case; `attrs` raw. */
45
+ export type NodeIdentity = (tag: string, attrs: Record<string, string>, path: string) => string | undefined;
46
+ export type HtmlSource = {
47
+ html: string;
48
+ baseURL?: string;
49
+ assetsDir?: string;
50
+ } | {
51
+ file: string;
52
+ } | {
53
+ url: string;
54
+ };