@weasel-js/labkit 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/_dts/{CanvasStackContext-D2jnIwfk.d.ts → CanvasStackContext-Cjy6I-Iv.d.ts} +4 -1
- package/dist/_dts/{Stage-CCWfQQWM.d.ts → Stage-D6t7o0pF.d.ts} +3 -2
- package/dist/_dts/{index-CsYqUHD3.d.ts → index-BTmaRy6a.d.ts} +10 -6
- package/dist/_dts/{types-CSm9jgol.d.ts → index-DCMA4Fy1.d.ts} +59 -113
- package/dist/_dts/{types-CRPSGFAp.d.ts → types-BUBSIZuV.d.ts} +8 -7
- package/dist/_dts/{useTrialState-CTZPgeZ7.d.ts → useTrialState-Bh8bzFgE.d.ts} +1 -1
- package/dist/canvas/index.d.ts +8 -6
- package/dist/canvas/index.js +6 -6
- package/dist/chrome/index.d.ts +7 -5
- package/dist/chrome/index.js +10 -9
- package/dist/chunk-2ES4W47N.js +8 -0
- package/dist/chunk-2ES4W47N.js.map +1 -0
- package/dist/{chunk-WPLAANH4.js → chunk-2N7UBSS2.js} +12 -12
- package/dist/chunk-2N7UBSS2.js.map +1 -0
- package/dist/chunk-4KSC7NXL.js +15491 -0
- package/dist/chunk-4KSC7NXL.js.map +1 -0
- package/dist/{chunk-7BO7HNGF.js → chunk-CEGFXTBD.js} +8 -61
- package/dist/chunk-CEGFXTBD.js.map +1 -0
- package/dist/{chunk-275JRRVD.js → chunk-E23Q6A3Y.js} +232 -37
- package/dist/chunk-E23Q6A3Y.js.map +1 -0
- package/dist/{chunk-GOZLNM4L.js → chunk-E6NARGU7.js} +5 -5
- package/dist/{chunk-GOZLNM4L.js.map → chunk-E6NARGU7.js.map} +1 -1
- package/dist/{chunk-IJJUK4FU.js → chunk-EESJUSYR.js} +5 -6
- package/dist/chunk-EESJUSYR.js.map +1 -0
- package/dist/{chunk-HXXTULDN.js → chunk-EFXRM6XQ.js} +8 -11
- package/dist/chunk-EFXRM6XQ.js.map +1 -0
- package/dist/chunk-F4ACIK7Z.js +210 -0
- package/dist/chunk-F4ACIK7Z.js.map +1 -0
- package/dist/{chunk-FMK7UQ6V.js → chunk-FB4MIZOO.js} +61 -44
- package/dist/chunk-FB4MIZOO.js.map +1 -0
- package/dist/{chunk-AWQG7FCC.js → chunk-FG3EXZDV.js} +3 -3
- package/dist/{chunk-AWQG7FCC.js.map → chunk-FG3EXZDV.js.map} +1 -1
- package/dist/{chunk-I5DUQ5HM.js → chunk-GAHELLJT.js} +75 -72
- package/dist/chunk-GAHELLJT.js.map +1 -0
- package/dist/{chunk-YT75VYRD.js → chunk-IBVRMHW5.js} +5 -5
- package/dist/{chunk-YT75VYRD.js.map → chunk-IBVRMHW5.js.map} +1 -1
- package/dist/{chunk-T5IBSPAM.js → chunk-JFOJESJF.js} +33 -23
- package/dist/chunk-JFOJESJF.js.map +1 -0
- package/dist/{chunk-RWNDDKOH.js → chunk-PMLZP7RT.js} +18 -15
- package/dist/chunk-PMLZP7RT.js.map +1 -0
- package/dist/{chunk-Y23G2VZL.js → chunk-READTDQX.js} +2 -2
- package/dist/chunk-READTDQX.js.map +1 -0
- package/dist/{chunk-JVBYV6TL.js → chunk-ROGJWDQA.js} +3 -3
- package/dist/{chunk-JVBYV6TL.js.map → chunk-ROGJWDQA.js.map} +1 -1
- package/dist/{chunk-ZIFPHIWZ.js → chunk-T6DLGEJB.js} +12 -14
- package/dist/chunk-T6DLGEJB.js.map +1 -0
- package/dist/{chunk-24W5VEJW.js → chunk-ULYYNWGP.js} +2 -2
- package/dist/{chunk-24W5VEJW.js.map → chunk-ULYYNWGP.js.map} +1 -1
- package/dist/{chunk-UNAZSLWE.js → chunk-VYVGVBGY.js} +17 -20
- package/dist/chunk-VYVGVBGY.js.map +1 -0
- package/dist/{chunk-KMJ7RWD3.js → chunk-WLMDTI2Q.js} +3 -3
- package/dist/{chunk-KMJ7RWD3.js.map → chunk-WLMDTI2Q.js.map} +1 -1
- package/dist/{chunk-J7OWWTCW.js → chunk-XE5HJOPL.js} +5 -6
- package/dist/chunk-XE5HJOPL.js.map +1 -0
- package/dist/chunk-XVUKDSYV.js +38 -0
- package/dist/chunk-XVUKDSYV.js.map +1 -0
- package/dist/{chunk-FZ7YFQN7.js → chunk-YCFKW5RX.js} +3 -3
- package/dist/chunk-YCFKW5RX.js.map +1 -0
- package/dist/{chunk-CQLQPQ4P.js → chunk-ZQIHJXP4.js} +2 -2
- package/dist/chunk-ZQIHJXP4.js.map +1 -0
- package/dist/config/index.d.ts +18 -10
- package/dist/config/index.js +4 -4
- package/dist/controls/index.d.ts +4 -7
- package/dist/controls/index.js +6 -5
- package/dist/dragdrop/index.d.ts +23 -3
- package/dist/dragdrop/index.js +4 -3
- package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
- package/dist/index.d.ts +60 -714
- package/dist/index.js +357 -334
- package/dist/index.js.map +1 -1
- package/dist/job/index.d.ts +8 -0
- package/dist/job/index.js +1 -1
- package/dist/layers/index.d.ts +6 -5
- package/dist/layers/index.js +3 -2
- package/dist/loupe/index.d.ts +100 -30
- package/dist/loupe/index.js +585 -6
- package/dist/loupe/index.js.map +1 -1
- package/dist/overview/index.d.ts +4 -2
- package/dist/overview/index.js +15 -14
- package/dist/overview/index.js.map +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +2 -0
- package/dist/passthrough/weasel-ui.d.ts +2 -2871
- package/dist/passthrough/weasel-ui.js +3 -2
- package/dist/primitives/index.d.ts +213 -3
- package/dist/primitives/index.js +8 -7
- package/dist/state/index.d.ts +7 -5
- package/dist/state/index.js +6 -6
- package/dist/styles.css +60 -44
- package/dist/surface/index.d.ts +10 -2
- package/dist/surface/index.js +1 -1
- package/dist/undo/index.d.ts +5 -3
- package/package.json +11 -11
- package/src/annotations/AnnotationOverlay.abandon.test.tsx +143 -0
- package/src/annotations/AnnotationOverlay.tsx +50 -31
- package/src/annotations/Annotations.overlay.test.tsx +31 -0
- package/src/annotations/capture.browser.test.ts +41 -0
- package/src/annotations/capture.ts +14 -7
- package/src/annotations/drawOne.ts +2 -2
- package/src/annotations/frac.test.ts +44 -1
- package/src/annotations/frac.ts +46 -18
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +74 -33
- package/src/annotations/paint.ts +70 -32
- package/src/annotations/store.test.ts +212 -2
- package/src/annotations/store.ts +130 -27
- package/src/annotations/svgNodes.test.ts +22 -10
- package/src/annotations/svgNodes.ts +3 -3
- package/src/annotations/types.ts +29 -10
- package/src/canvas/CameraInput.test.tsx +30 -0
- package/src/canvas/CameraInput.tsx +16 -15
- package/src/canvas/CanvasStack.tsx +5 -5
- package/src/canvas/CanvasStackContext.ts +4 -1
- package/src/canvas/Stage.tsx +3 -3
- package/src/canvas/cameraRegistry.ts +1 -0
- package/src/canvas/worldSpec.ts +3 -1
- package/src/chrome/builtins.test.ts +7 -6
- package/src/chrome/builtins.tsx +5 -1
- package/src/chrome/index.ts +1 -1
- package/src/chrome/merge.test.ts +5 -0
- package/src/chrome/merge.ts +4 -2
- package/src/chrome/regions/PaletteRegion.test.tsx +2 -3
- package/src/chrome/regions/PaletteRegion.tsx +3 -4
- package/src/chrome/regions/ViewportRegion.browser.test.less +6 -0
- package/src/chrome/regions/ViewportRegion.browser.test.tsx +38 -0
- package/src/chrome/regions/ViewportRegion.less +6 -0
- package/src/chrome/regions/ViewportRegion.tsx +10 -4
- package/src/chrome/types.ts +4 -2
- package/src/config/auto.ts +1 -0
- package/src/config/builder.ts +6 -0
- package/src/config/types.ts +2 -1
- package/src/controls/ControlPanel.test.tsx +37 -3
- package/src/controls/ControlPanel.tsx +12 -3
- package/src/dragdrop/DragDropRuntime.tsx +22 -13
- package/src/dragdrop/DragGhost.tsx +3 -0
- package/src/dragdrop/Palette.tsx +2 -0
- package/src/index.test.ts +5 -0
- package/src/index.ts +1 -1
- package/src/instrument/types.ts +0 -6
- package/src/job/useJob.ts +14 -9
- package/src/lab/Lab.tsx +5 -1
- package/src/lab/LabShell.less +1 -0
- package/src/lab/LabSwitcher.browser.test.tsx +27 -0
- package/src/lab/LabSwitcher.less +2 -0
- package/src/lab/LabZoom.tsx +4 -4
- package/src/lab/Workspace.tsx +48 -52
- package/src/loupe/AGENTS.md +28 -15
- package/src/loupe/CanvasLoupe.tsx +2 -3
- package/src/loupe/DomLoupe.tsx +1 -7
- package/src/loupe/Loupe.less +16 -0
- package/src/loupe/TrialLoupe.tsx +120 -57
- package/src/loupe/index.ts +1 -6
- package/src/loupe/types.test.ts +3 -3
- package/src/loupe/types.ts +24 -27
- package/src/loupe/useLoupe.test.tsx +29 -4
- package/src/loupe/useLoupe.ts +20 -17
- package/src/overview/OverviewMarks.tsx +12 -4
- package/src/overview/TrialOverview.tsx +3 -3
- package/src/passthrough/weasel-ui.test.ts +1 -1
- package/src/passthrough/weasel-ui.ts +1 -1
- package/src/primitives/FloatingPanel.tsx +7 -3
- package/src/primitives/JobProgress.less +1 -0
- package/src/primitives/Readout.test.tsx +2 -2
- package/src/primitives/Split.tsx +69 -41
- package/src/primitives/Toolbar.tsx +3 -3
- package/src/primitives/ZoomControl.less +1 -2
- package/src/specimen/Specimen.tsx +0 -1
- package/src/state/undock.ts +3 -0
- package/src/state/useOpenOnce.ts +20 -16
- package/src/state/view.ts +1 -0
- package/src/surface/index.ts +1 -1
- package/src/surface/useTiledSurface.test.tsx +14 -0
- package/src/surface/useTiledSurface.ts +11 -3
- package/src/trial/Trial.annotations.test.tsx +73 -0
- package/src/trial/Trial.less +0 -16
- package/src/trial/Trial.loupe.test.tsx +28 -11
- package/src/trial/Trial.tsx +74 -62
- package/src/trial/TrialChrome.tsx +6 -3
- package/src/trial/index.ts +2 -0
- package/src/trial/loupeSwitch.ts +15 -0
- package/dist/_dts/LayerList.d-DiuEArKq.d.ts +0 -83
- package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +0 -79
- package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +0 -141
- package/dist/_dts/Select.d-Bensr_MT.d.ts +0 -579
- package/dist/_dts/index-B2Yj5aA0.d.ts +0 -274
- package/dist/chunk-275JRRVD.js.map +0 -1
- package/dist/chunk-4LJSC7MB.js +0 -143
- package/dist/chunk-4LJSC7MB.js.map +0 -1
- package/dist/chunk-7BO7HNGF.js.map +0 -1
- package/dist/chunk-CQLQPQ4P.js.map +0 -1
- package/dist/chunk-FMK7UQ6V.js.map +0 -1
- package/dist/chunk-FZ7YFQN7.js.map +0 -1
- package/dist/chunk-HXXTULDN.js.map +0 -1
- package/dist/chunk-I5DUQ5HM.js.map +0 -1
- package/dist/chunk-IJJUK4FU.js.map +0 -1
- package/dist/chunk-J7OWWTCW.js.map +0 -1
- package/dist/chunk-M7HP3FTK.js +0 -549
- package/dist/chunk-M7HP3FTK.js.map +0 -1
- package/dist/chunk-MIM5R4ZT.js +0 -14972
- package/dist/chunk-MIM5R4ZT.js.map +0 -1
- package/dist/chunk-RWNDDKOH.js.map +0 -1
- package/dist/chunk-T5IBSPAM.js.map +0 -1
- package/dist/chunk-UNAZSLWE.js.map +0 -1
- package/dist/chunk-WPLAANH4.js.map +0 -1
- package/dist/chunk-Y23G2VZL.js.map +0 -1
- package/dist/chunk-ZIFPHIWZ.js.map +0 -1
- package/src/primitives/useRovingTabIndex.test.ts +0 -48
- package/src/primitives/useRovingTabIndex.ts +0 -88
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
import './FloatingPanel-7j0IcXwz.js';
|
|
2
|
-
import * as react from 'react';
|
|
3
|
-
import { ReactNode, MouseEventHandler } from 'react';
|
|
4
|
-
import { J as JobHandle } from './types-DJ79Tg5J.js';
|
|
5
|
-
|
|
6
|
-
/** Whether a row's label sits beside its value or above it. */
|
|
7
|
-
type DetailListLayout = 'inline' | 'block';
|
|
8
|
-
/**
|
|
9
|
-
* How a list sets its values. `text` starts each value at the column's edge
|
|
10
|
-
* and wraps it; `figures` right-aligns it in a column at least
|
|
11
|
-
* `--wzl-detail-figure-min-width` (default `8ch`) wide, in the mono face,
|
|
12
|
-
* with spaces kept, so figure-space padding lines a column up on its decimal
|
|
13
|
-
* point.
|
|
14
|
-
*/
|
|
15
|
-
type DetailListValues = 'text' | 'figures';
|
|
16
|
-
/** The state a row's status dot reports, painted from `--wzl-success`,
|
|
17
|
-
* `--wzl-warning` or `--wzl-danger`. */
|
|
18
|
-
type DetailRowStatus = 'success' | 'warn' | 'danger';
|
|
19
|
-
/** Props for {@link DetailList}. */
|
|
20
|
-
interface DetailListProps {
|
|
21
|
-
/** {@link DetailRow}s. */
|
|
22
|
-
children: ReactNode;
|
|
23
|
-
/** Heading drawn above the list, which also names it. */
|
|
24
|
-
title?: ReactNode;
|
|
25
|
-
/**
|
|
26
|
-
* `inline` puts every label in one rail beside the values; `block` stacks
|
|
27
|
-
* each label over its value, for a column too narrow to hold both.
|
|
28
|
-
*/
|
|
29
|
-
layout?: DetailListLayout;
|
|
30
|
-
/** `text` by default. See {@link DetailListValues}. */
|
|
31
|
-
values?: DetailListValues;
|
|
32
|
-
/** Class on the outermost element: the `<dl>`, or the `<section>` holding
|
|
33
|
-
* the heading and the list when there is a `title`. */
|
|
34
|
-
className?: string;
|
|
35
|
-
}
|
|
36
|
-
/** Props for {@link DetailRow}. */
|
|
37
|
-
interface DetailRowProps {
|
|
38
|
-
label: ReactNode;
|
|
39
|
-
/** The value: text, or any run of elements — code chips, badges, keycaps,
|
|
40
|
-
* links. Several children wrap as a line of items. `null` or `undefined`
|
|
41
|
-
* keeps the row in place showing `placeholder`, so a list whose values
|
|
42
|
-
* come and go holds its height. */
|
|
43
|
-
children?: ReactNode;
|
|
44
|
-
/** Shown while there is no value. An en dash by default. */
|
|
45
|
-
placeholder?: ReactNode;
|
|
46
|
-
/**
|
|
47
|
-
* Draws a dot in the status color before the value. The dot is hidden from
|
|
48
|
-
* assistive technology and color is never the only signal, so the value
|
|
49
|
-
* itself has to say the same thing — "locked", not just a green dot.
|
|
50
|
-
*/
|
|
51
|
-
status?: DetailRowStatus;
|
|
52
|
-
/** Sets this row's value as `text` or `figures`, whatever the list's
|
|
53
|
-
* `values` says — a sentence among figures, or one figure among text. */
|
|
54
|
-
values?: DetailListValues;
|
|
55
|
-
className?: string;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* A read-only list of labeled values — the `<dl>` a property panel would be
|
|
59
|
-
* if its rows held facts instead of controls. Labels take the params label
|
|
60
|
-
* recipe and rail: `--wzl-params-label-width` sets the rail, so a detail list
|
|
61
|
-
* and a property panel beside it line their labels up from one declaration.
|
|
62
|
-
*/
|
|
63
|
-
declare function DetailList({ children, title, layout, values, className }: DetailListProps): react.JSX.Element;
|
|
64
|
-
/** One label and its value in a {@link DetailList}. */
|
|
65
|
-
declare function DetailRow({ label, children, placeholder, status, values, className }: DetailRowProps): react.JSX.Element;
|
|
66
|
-
|
|
67
|
-
/** A live frame-rate readout, averaged over the last 30 frames. */
|
|
68
|
-
declare function FpsMeter(): react.JSX.Element;
|
|
69
|
-
|
|
70
|
-
/** Props for `<JobProgress>`. */
|
|
71
|
-
interface JobProgressProps {
|
|
72
|
-
job: JobHandle;
|
|
73
|
-
className?: string;
|
|
74
|
-
}
|
|
75
|
-
/** A running job's progress, failures and outcome. Determinate once the job
|
|
76
|
-
* reports a total; a job that cannot count up front never sends one, so the
|
|
77
|
-
* bar stays indeterminate rather than inventing a denominator. */
|
|
78
|
-
declare function JobProgress({ job, className }: JobProgressProps): react.JSX.Element | null;
|
|
79
|
-
|
|
80
|
-
/** How a legend entry's swatch is drawn, matching how the thing looks on canvas. */
|
|
81
|
-
type LegendMark = 'line' | 'dash' | 'dot' | 'band';
|
|
82
|
-
/** One row of a legend: a swatch and what it means. */
|
|
83
|
-
interface LegendEntry {
|
|
84
|
-
key: string;
|
|
85
|
-
label: string;
|
|
86
|
-
color: string;
|
|
87
|
-
/** Defaults to `'line'`. */
|
|
88
|
-
mark?: LegendMark;
|
|
89
|
-
}
|
|
90
|
-
/** Props for `<Legend>`. */
|
|
91
|
-
interface LegendProps {
|
|
92
|
-
entries: readonly LegendEntry[];
|
|
93
|
-
className?: string;
|
|
94
|
-
}
|
|
95
|
-
/** A color key. Presentational only — no handlers, no state, no hover behavior. */
|
|
96
|
-
declare function Legend({ entries, className }: LegendProps): react.JSX.Element;
|
|
97
|
-
|
|
98
|
-
/** One measurement in a {@link Readout}. */
|
|
99
|
-
interface ReadoutRow {
|
|
100
|
-
/** React key. Defaults to `label` when that is a string, else the row's index. */
|
|
101
|
-
key?: string;
|
|
102
|
-
label: ReactNode;
|
|
103
|
-
/** `null` or `undefined` keeps the row in place showing an en dash, so the
|
|
104
|
-
* readout holds its height while a measurement comes and goes. */
|
|
105
|
-
value?: ReactNode;
|
|
106
|
-
/** A dot in the status color before the value. Color is never the only
|
|
107
|
-
* signal: the value has to say the same thing in words. */
|
|
108
|
-
status?: DetailRowStatus;
|
|
109
|
-
/** `text` sets this row's value as wrapping prose instead of a figure. */
|
|
110
|
-
values?: DetailListValues;
|
|
111
|
-
}
|
|
112
|
-
/** Props for {@link Readout}. */
|
|
113
|
-
interface ReadoutProps {
|
|
114
|
-
rows: readonly ReadoutRow[];
|
|
115
|
-
/** Heading above the rows, which also names the list. */
|
|
116
|
-
title?: ReactNode;
|
|
117
|
-
/** Drawn below the rows — a small table, a note. */
|
|
118
|
-
children?: ReactNode;
|
|
119
|
-
className?: string;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Values a lab only reads — measurements shown beside its picture, such as
|
|
123
|
-
* "Lock margin +47.9°". A {@link DetailList} set as figures: labels take the
|
|
124
|
-
* params label recipe and `--wzl-params-label-width` rail, so a readout lines
|
|
125
|
-
* up with a `ControlPanel` beside it, and values sit right-aligned in the mono
|
|
126
|
-
* face with spaces kept, so figure-space padding aligns a column on its
|
|
127
|
-
* decimal point. Rows compose by hand as `DetailRow`s inside a `DetailList`
|
|
128
|
-
* with `values="figures"`.
|
|
129
|
-
*/
|
|
130
|
-
declare function Readout({ rows, title, children, className }: ReadoutProps): react.JSX.Element;
|
|
131
|
-
|
|
132
|
-
/** Props for `<ScaleIndicator>`. */
|
|
133
|
-
interface ScaleIndicatorProps {
|
|
134
|
-
/** Current view zoom factor. If omitted, reads from CanvasStackContext. Defaults to 1. */
|
|
135
|
-
zoom?: number;
|
|
136
|
-
/** World pixels per unit at zoom=1. Default: 1. */
|
|
137
|
-
pixelsPerUnit?: number;
|
|
138
|
-
/** Unit label. Default: 'px'. */
|
|
139
|
-
unit?: string;
|
|
140
|
-
/** Target bar width in display pixels. Default: 100. */
|
|
141
|
-
targetWidth?: number;
|
|
142
|
-
}
|
|
143
|
-
/** A scale bar: a labeled rule showing how far a round number of world units
|
|
144
|
-
* is at the current zoom. Reads the zoom from the surrounding canvas stack
|
|
145
|
-
* unless one is passed. */
|
|
146
|
-
declare function ScaleIndicator({ zoom, pixelsPerUnit, unit, targetWidth, }: ScaleIndicatorProps): react.JSX.Element;
|
|
147
|
-
|
|
148
|
-
/** Props for `<Split>`. */
|
|
149
|
-
interface SplitProps {
|
|
150
|
-
/** The sidebar pane's contents. */
|
|
151
|
-
sidebar: ReactNode;
|
|
152
|
-
/** The edge the sidebar sits on. Read once, when the strip mounts. Default `'start'`. */
|
|
153
|
-
side?: 'start' | 'end';
|
|
154
|
-
/** The content pane's contents. */
|
|
155
|
-
children: ReactNode;
|
|
156
|
-
/** Names the sidebar pane, and through it the seam. Default `'Sidebar'`. */
|
|
157
|
-
label?: string;
|
|
158
|
-
/** Extra classes on the strip, which always has `lk-split`. */
|
|
159
|
-
className?: string;
|
|
160
|
-
/** The class on the sidebar pane. */
|
|
161
|
-
sidebarClassName?: string;
|
|
162
|
-
/** The class on the content pane. */
|
|
163
|
-
contentClassName?: string;
|
|
164
|
-
/** The sidebar's current extent in pixels. Omit to leave it unpersisted: the
|
|
165
|
-
* seam still works, its result just does not outlive the mount. */
|
|
166
|
-
width?: number;
|
|
167
|
-
/** Where the sidebar starts before anyone drags it. */
|
|
168
|
-
defaultWidth?: number;
|
|
169
|
-
minWidth?: number;
|
|
170
|
-
maxWidth?: number;
|
|
171
|
-
/** How little the content pane may be squeezed to. Reported as the seam's
|
|
172
|
-
* reachable maximum, so the drag stops there rather than clamping silently. */
|
|
173
|
-
contentMinWidth?: number;
|
|
174
|
-
/** Fires through the drag, not on release: the pane is already there. */
|
|
175
|
-
onWidthChange?: (width: number) => void;
|
|
176
|
-
/**
|
|
177
|
-
* Fixed extent. Omit in an app — the strip measures its own box. Supply it
|
|
178
|
-
* where nothing measures, notably jsdom, or both panes lay out at zero.
|
|
179
|
-
*/
|
|
180
|
-
viewport?: {
|
|
181
|
-
w: number;
|
|
182
|
-
h: number;
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* A sidebar and a content pane as a two-pane strip with a draggable seam.
|
|
187
|
-
*
|
|
188
|
-
* The seam is `stripStrategy`'s own resize affordance, so it arrives as a
|
|
189
|
-
* `role="separator"` carrying the reachable range, operable by pointer and by
|
|
190
|
-
* arrows / Home / End, and clamped against the content pane's floor rather
|
|
191
|
-
* than against the sidebar's alone.
|
|
192
|
-
*/
|
|
193
|
-
declare function Split({ sidebar, children, side, label, className, sidebarClassName, contentClassName, width, defaultWidth, minWidth, maxWidth, contentMinWidth, onWidthChange, viewport, }: SplitProps): react.JSX.Element;
|
|
194
|
-
|
|
195
|
-
/** Props for `<StatusBar>`. */
|
|
196
|
-
interface StatusBarProps {
|
|
197
|
-
children: ReactNode;
|
|
198
|
-
}
|
|
199
|
-
/** A footer strip for readouts. Fill it with `<StatusBar.Section>`. */
|
|
200
|
-
declare function StatusBar({ children }: StatusBarProps): react.JSX.Element;
|
|
201
|
-
declare namespace StatusBar {
|
|
202
|
-
var Section: ({ children, end }: StatusBarSectionProps) => react.JSX.Element;
|
|
203
|
-
}
|
|
204
|
-
/** Props for `<StatusBar.Section>`. */
|
|
205
|
-
interface StatusBarSectionProps {
|
|
206
|
-
children: ReactNode;
|
|
207
|
-
/** Pushes this section, and everything after it, to the far end. */
|
|
208
|
-
end?: boolean;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** Props for `<Toolbar>`. */
|
|
212
|
-
interface ToolbarProps {
|
|
213
|
-
children: ReactNode;
|
|
214
|
-
/** Names the toolbar for assistive tech. Required by the APG pattern when a
|
|
215
|
-
* view holds more than one. */
|
|
216
|
-
'aria-label'?: string;
|
|
217
|
-
}
|
|
218
|
-
/** A horizontal bar of controls. Fill it with `<Toolbar.Title>`,
|
|
219
|
-
* `<Toolbar.Group>`, `<Toolbar.Button>` and `<Toolbar.Spacer>`. */
|
|
220
|
-
declare function Toolbar({ children, 'aria-label': ariaLabel }: ToolbarProps): react.JSX.Element;
|
|
221
|
-
declare namespace Toolbar {
|
|
222
|
-
var Title: ({ children }: TitleProps) => react.JSX.Element;
|
|
223
|
-
var Group: ({ children, end, "aria-label": ariaLabel }: ToolbarGroupProps) => react.JSX.Element;
|
|
224
|
-
var Button: ({ children, onClick, disabled, title, "aria-label": ariaLabel, variant, iconOnly, pressed, }: ToolbarButtonProps) => react.JSX.Element;
|
|
225
|
-
var Spacer: () => react.JSX.Element;
|
|
226
|
-
}
|
|
227
|
-
interface TitleProps {
|
|
228
|
-
children: ReactNode;
|
|
229
|
-
}
|
|
230
|
-
/** Props for `<Toolbar.Group>`. */
|
|
231
|
-
interface ToolbarGroupProps {
|
|
232
|
-
children: ReactNode;
|
|
233
|
-
/** Pushes this group, and everything after it, to the far end. */
|
|
234
|
-
end?: boolean;
|
|
235
|
-
'aria-label'?: string;
|
|
236
|
-
}
|
|
237
|
-
/** Props for `<Toolbar.Button>`. */
|
|
238
|
-
interface ToolbarButtonProps {
|
|
239
|
-
children: ReactNode;
|
|
240
|
-
onClick: MouseEventHandler<HTMLButtonElement>;
|
|
241
|
-
disabled?: boolean;
|
|
242
|
-
title?: string;
|
|
243
|
-
/** Required when `children` is an icon with no text of its own. */
|
|
244
|
-
'aria-label'?: string;
|
|
245
|
-
/** `danger` reddens on hover — for actions that discard work. */
|
|
246
|
-
variant?: 'default' | 'danger';
|
|
247
|
-
/** Square, for a button whose whole content is one glyph. */
|
|
248
|
-
iconOnly?: boolean;
|
|
249
|
-
/** Makes this a toggle: `aria-pressed`, and held down while true. */
|
|
250
|
-
pressed?: boolean;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/** Props for `<ZoomControl>`. */
|
|
254
|
-
interface ZoomControlProps {
|
|
255
|
-
/** Current zoom as a scale factor: 1 is actual size. */
|
|
256
|
-
zoom: number;
|
|
257
|
-
/** Fired continuously while the slider drags. */
|
|
258
|
-
onZoomChange: (zoom: number) => void;
|
|
259
|
-
/** Fired when a drag settles or the field is committed. Defaults to
|
|
260
|
-
* `onZoomChange`. */
|
|
261
|
-
onZoomCommit?: (zoom: number) => void;
|
|
262
|
-
/** Smallest selectable zoom. Defaults to 0.1 (10%). */
|
|
263
|
-
min?: number;
|
|
264
|
-
/** Largest selectable zoom. Defaults to 8 (800%). */
|
|
265
|
-
max?: number;
|
|
266
|
-
className?: string;
|
|
267
|
-
}
|
|
268
|
-
/** Zoom as a log-scaled slider with an editable percentage beside it. Pair it
|
|
269
|
-
* with zoom-in / zoom-out buttons in a `<Toolbar.Group>`; this component owns
|
|
270
|
-
* only the continuous part. */
|
|
271
|
-
declare function ZoomControl({ zoom, onZoomChange, onZoomCommit, min: minProp, max: maxProp, className, }: ZoomControlProps): react.JSX.Element;
|
|
272
|
-
|
|
273
|
-
export { DetailList as D, FpsMeter as F, JobProgress as J, Legend as L, Readout as R, Toolbar as T, ZoomControl as Z, DetailRow as d, ScaleIndicator as m, Split as o, StatusBar as p };
|
|
274
|
-
export type { SplitProps as S, DetailListLayout as a, DetailListProps as b, DetailListValues as c, DetailRowProps as e, DetailRowStatus as f, JobProgressProps as g, LegendEntry as h, LegendMark as i, LegendProps as j, ReadoutProps as k, ReadoutRow as l, ScaleIndicatorProps as n, StatusBarProps as q, StatusBarSectionProps as r, ToolbarButtonProps as s, ToolbarGroupProps as t, ToolbarProps as u, ZoomControlProps as v };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../geom/src/mat3.ts","../../svg/src/types.ts","../../svg/src/transform.ts","../../svg/src/textAnchor.ts","../../svg/src/patterns.ts","../../svg/src/path-serializer.ts","../../svg/src/gradients.ts","../../svg/src/serialize.ts"],"names":["PATH_M","PATH_L","PATH_C","PATH_Q","PATH_Z","escapeAttr","localName","resolveScreenLength","boundsOfPath"],"mappings":"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","file":"chunk-275JRRVD.js","sourcesContent":["/**\n * 2D affine transforms in canvas/DOMMatrix order: [a, b, c, d, e, f].\n * x' = a·x + c·y + e\n * y' = b·x + d·y + f\n * Represented as a readonly 6-tuple (f64). The affine tier of the kernel.\n *\n * Convention alignment: the renderer already has a `Mat3` in\n * `src/renderer/math/mat3.ts`. That one is a 9-element column-major\n * `Float32Array` (a full 3×3) shaped for `uniformMatrix3fv` — a deliberately\n * different *representation* for the WebGL upload path. Its *logical element\n * order* is identical to ours: `create(a, b, c, d, tx, ty)` maps\n * `x' = a·x + c·y + tx`, `y' = b·x + d·y + ty` (canvas/DOMMatrix a,b,c,d,e,f).\n * We keep the pure 6-tuple f64 form here (the kernel form); the 9-element f32\n * form stays a render-layer concern. No second logical convention is created.\n */\nimport { SINGULAR_RATIO } from './scalar';\n\nexport type Mat3 = readonly [number, number, number, number, number, number];\n\n/** The transform that leaves a point where it is. */\nexport function identity(): Mat3 {\n return [1, 0, 0, 1, 0, 0];\n}\n\n/** A pure translation by `(tx, ty)`. */\nexport function translate(tx: number, ty: number): Mat3 {\n return [1, 0, 0, 1, tx, ty];\n}\n\n/** A pure scale about the origin. Scale about another point by composing\n * translate → scale → inverse translate with `multiply`. */\nexport function scale(sx: number, sy: number): Mat3 {\n return [sx, 0, 0, sy, 0, 0];\n}\n\n/** A pure rotation about the origin, in radians, clockwise in canvas\n * coordinates (y down). */\nexport function rotate(rad: number): Mat3 {\n const c = Math.cos(rad);\n const s = Math.sin(rad);\n return [c, s, -s, c, 0, 0];\n}\n\n/** Compose: result applies `n` first, then `m` (m·n). */\nexport function multiply(m: Mat3, n: Mat3): Mat3 {\n return [\n m[0] * n[0] + m[2] * n[1],\n m[1] * n[0] + m[3] * n[1],\n m[0] * n[2] + m[2] * n[3],\n m[1] * n[2] + m[3] * n[3],\n m[0] * n[4] + m[2] * n[5] + m[4],\n m[1] * n[4] + m[3] * n[5] + m[5],\n ];\n}\n\n/** Inverse, or null when the matrix is singular, non-finite, or too\n * ill-conditioned to invert meaningfully at its own scale. */\nexport function invert(m: Mat3): Mat3 | null {\n const det = m[0] * m[3] - m[1] * m[2];\n // The determinant is an area, so it is judged against the squared column norms.\n const norm2 = Math.max(m[0] * m[0] + m[1] * m[1], m[2] * m[2] + m[3] * m[3]);\n // Negated so a non-finite determinant falls out as singular.\n if (!(Math.abs(det) > SINGULAR_RATIO * norm2)) return null;\n const id = 1 / det;\n const a = m[3] * id;\n const b = -m[1] * id;\n const c = -m[2] * id;\n const d = m[0] * id;\n return [a, b, c, d, -(m[4] * a + m[5] * c), -(m[4] * b + m[5] * d)];\n}\n\n/** Apply to a point, returning a tuple. Cold-path use; hot loops inline. */\nexport function applyToPoint(m: Mat3, x: number, y: number): [number, number] {\n return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];\n}\n\n/** Affine that maps source box (sx,sy,sw,sh) onto destination box (dx,dy,dw,dh). */\nexport function boxToBox(\n sx: number, sy: number, sw: number, sh: number,\n dx: number, dy: number, dw: number, dh: number,\n): Mat3 {\n const kx = sw === 0 ? 1 : dw / sw;\n const ky = sh === 0 ? 1 : dh / sh;\n // translate(dx,dy) · scale(kx,ky) · translate(-sx,-sy)\n return [kx, 0, 0, ky, dx - sx * kx, dy - sy * ky];\n}\n\n/** Rotation by `rad` about pivot (cx,cy): translate(c)·rotate·translate(-c). */\nexport function rotateAboutPoint(cx: number, cy: number, rad: number): Mat3 {\n return multiply(translate(cx, cy), multiply(rotate(rad), translate(-cx, -cy)));\n}\n","/**\n * Public types for `@weasel-js/svg`. The package exposes a flat,\n * discriminated-union node model (`SvgNode`) that mirrors the SVG element\n * tree but uses weasel-native leaf data (`Path`, `FillStyle`) for geometry and\n * paint.\n *\n * Parsing collapses every `transform=\"...\"` onto its descendants' geometry,\n * so the `SvgNode` tree returned from `parseSvg` never has a non-identity\n * group transform. Consumers may still construct groups with explicit\n * transforms before serializing, in which case the serializer emits a\n * single `matrix(a b c d e f)` on the `<g>`.\n */\n\nimport { identity, type Mat3 } from '@weasel-js/geom';\nimport type {\n Path, FillStyle, MarkerEntry, MarkerRef, ScreenLength, Stroke, StrokeAlign, StyledRun, TextStyle,\n TextVerticalAlign,\n} from '@weasel-js/core';\n\n/**\n * Opaque pass-through bag for namespaced XML content.\n *\n * weasel-svg does not interpret the contents — it only ensures that any\n * attributes or child elements in a *declared* XML namespace round-trip\n * losslessly through parse → serialize. Consumers (e.g. an app-specific\n * bridge layer) hang their domain semantics off this structure.\n *\n * Keyed by namespace prefix (the prefix is a write-time choice; the URI\n * is the canonical identifier and is supplied via `ParseOptions.namespaces`\n * / `SerializeOptions.namespaces`).\n */\nexport interface NamespaceMeta {\n [prefix: string]: {\n /** Local-name → string-value map for attributes in this namespace. */\n attrs?: Record<string, string>;\n /**\n * Child elements in this namespace, keyed by local name. Each entry\n * is an array because a namespace can host multiple sibling elements\n * with the same tag (e.g. `<wd:layer/><wd:layer/>`).\n */\n elements?: Record<string, NamespacedElement[]>;\n };\n}\n\n/** Opaque structured representation of a namespaced element. */\nexport interface NamespacedElement {\n /** Attribute local-name → string-value. */\n attrs: Record<string, string>;\n /** Text content, when the element contains only text (no child elements). */\n text?: string;\n /** Nested namespaced children, keyed by local name (recursive). */\n children?: Record<string, NamespacedElement[]>;\n}\n\n/**\n * 2x3 affine matrix in SVG's `matrix(a b c d e f)` order, mapping\n * `[x', y'] = [a*x + c*y + e, b*x + d*y + f]`.\n *\n * The same order the kernel's affine tier uses, so this is that type under\n * the name the SVG spec gives it — not a parallel one. An `SvgGroupNode`'s\n * transform and a geom `Mat3` are interchangeable without a conversion.\n */\nexport type Matrix = Mat3;\n\n/** Re-exported so this package's own stroke widths are namable beside the\n * rest of the SVG model. It is core's type; there is no second one. */\nexport type { ScreenLength };\n\n/** Identity matrix — useful as a default in tests / constructors. */\nexport const IDENTITY_MATRIX: Matrix = identity();\n\n/**\n * FillStyle description in the SVG sense — either explicit `none`, a solid\n * color, or a reference to a weasel-native gradient `FillStyle`. Solid colors\n * are normalized to `#rrggbb` strings; opacity is carried separately so\n * `fill-opacity` and `stroke-opacity` round-trip cleanly.\n */\nexport type SvgPaint =\n | { kind: 'none' }\n | { kind: 'solid'; color: string; opacity?: number }\n | { kind: 'gradient'; paint: FillStyle };\n\n/** Stroke description: a paint plus structural line parameters. */\nexport interface SvgStroke {\n paint: SvgPaint;\n /** World units, or `{ px }` for a width that holds its rendered thickness\n * however the document is scaled — SVG's `vector-effect=\"non-scaling-stroke\"`.\n * Literally the kit's own unit, not a second spelling of it. */\n width: ScreenLength;\n opacity?: number;\n /** `stroke-linecap`. Default per SVG spec is `'butt'`. */\n cap?: 'butt' | 'round' | 'square';\n /** `stroke-linejoin`. Default per SVG spec is `'miter'`. SVG's `arcs` / `miter-clip` map to `'miter'` with a warning. */\n join?: 'miter' | 'round' | 'bevel';\n /** `stroke-dasharray` as a flat number array. Odd-length inputs are doubled per SVG spec. */\n dash?: number[];\n /**\n * `stroke-miterlimit`. SVG's default is 4. Weasel's renderer defaults to\n * 10 (Canvas2D) when unset, so parsed strokes without an explicit\n * attribute may render with longer miters than the source SVG intended.\n */\n miterLimit?: number;\n /** The kit stroke's `align`. SVG has no stroke alignment, so the serializer\n * writes the stroke centered and says so through `onWarn`; the parser\n * never sets it. */\n align?: StrokeAlign;\n /** `marker-start` / `marker-mid` / `marker-end` as the kit's `MarkerRef`: the\n * bare `url(#id)` key, or a key with the `size` the serializer writes into a\n * def of its own. */\n markerStart?: MarkerRef;\n markerMid?: MarkerRef;\n markerEnd?: MarkerRef;\n}\n\n/**\n * Leaf node: a path geometry plus fill/stroke. All other v1 shapes\n * (`<rect>`, `<ellipse>`, etc.) are lowered to this representation on\n * parse — `<rect>` uses weasel's `RectPath` fast-path subtype when\n * possible, everything else becomes a `PolygonPath`.\n */\nexport interface SvgPathNode {\n kind: 'path';\n path: Path;\n fill: SvgPaint;\n stroke?: SvgStroke;\n /** Element-level opacity (`opacity=\"...\"`), 0..1. */\n opacity?: number;\n /** Element-level rotation in **radians**, pivoting around the AABB\n * center of the underlying `path` geometry. Emitted as SVG\n * `transform=\"rotate(angleDegrees cx cy)\"`. */\n rotation?: number;\n /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */\n meta?: NamespaceMeta;\n}\n\n/**\n * Group node: an SVG `<g>`. On parse, `transform` is always omitted (any\n * `transform` attribute is collapsed onto descendants' geometry). On\n * serialize, a non-identity `transform` is emitted as\n * `matrix(a b c d e f)`.\n */\nexport interface SvgGroupNode {\n kind: 'group';\n children: SvgNode[];\n transform?: Matrix;\n /** Clips the group's contents. Serializes to a `<clipPath>` def plus\n * `clip-path=\"url(#id)\"`, and lives in the same space as `children` —\n * SVG applies the group's own `transform` to the clip as well.\n * A `<clipPath>` of more than one shape parses back as no clip: SVG\n * unions them and a `Path` holds one outline. */\n clip?: Path;\n opacity?: number;\n /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */\n meta?: NamespaceMeta;\n}\n\n/**\n * Text leaf node. Mirrors the kit's `TextPose` shape — a bounding box plus\n * text content, optional rich-text `runs` (per-range styling), and an\n * optional `TextStyle` for the node-wide defaults.\n *\n * Note on SVG text geometry: native `<text>` flows from a baseline; it\n * doesn't have width/height attributes. The serializer emits\n * `dominant-baseline=\"text-before-edge\"` so `y` is the top of the text\n * box, plus `data-weasel-width` / `data-weasel-height` so weasel's\n * explicit box dimensions round-trip losslessly. External SVG text\n * (lacking the data-* attrs) imports with the width the kit's text layout\n * measures — an em-based estimate when no registered font can — and\n * `height = fontSize * lineHeight * (lineCount || 1)`.\n *\n * `x` here is always the box's left edge. In the SVG it is the\n * `text-anchor` point, and the parser and serializer convert between them.\n */\nexport interface SvgTextNode {\n kind: 'text';\n x: number;\n y: number;\n width: number;\n height: number;\n /** Plain text. When `runs` is set, `runsToPlainText(runs)` must equal `text`. */\n text: string;\n /** Optional per-range styling — same shape as `TextPose.runs`. */\n runs?: StyledRun[];\n /** Node-wide typography. Defaults applied at render time via `resolveTextStyle`. */\n style?: TextStyle;\n /** Where the laid-out text sits inside the box — `kit:text`'s\n * `data.verticalAlign`. SVG text has no box to align in, so this rides in\n * `data-weasel-vertical-align` and other readers draw the text top-aligned. */\n verticalAlign?: TextVerticalAlign;\n /**\n * Node-wide glyph paint, the `FillStyle` / `Stroke` a kit text node holds\n * in `data.fill` / `data.stroke`. Not `SvgPaint`, which is the path\n * nodes' shape — a text paint reaches the renderer through the runs, and\n * `StyledRun.fill` / `.stroke` override these per range.\n *\n * `null` is SVG's `fill=\"none\"`: outline-only text, painted by its stroke\n * alone. Absent takes the default black.\n */\n fill?: FillStyle | null;\n stroke?: Stroke;\n /** Element-level opacity (`opacity=\"...\"`), 0..1. */\n opacity?: number;\n /** Element-level rotation in **radians**, pivoting around the unrotated\n * AABB center `(x + width/2, y + height/2)`. Emitted as SVG\n * `transform=\"rotate(angleDegrees cx cy)\"`. */\n rotation?: number;\n /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */\n meta?: NamespaceMeta;\n}\n\n/**\n * Raster-image leaf — an SVG `<image>`. `href` is the element's `href` (or\n * legacy `xlink:href`) verbatim: an external URL or a `data:` URI. The\n * package neither fetches nor decodes it, so an external URL round-trips as\n * a reference and only resolves when something downstream loads it.\n *\n * SVG's `preserveAspectRatio` is not modeled; the box is taken literally.\n *\n * With a `source` rect or a flip, the element is written as a `<g\n * data-weasel-image>` holding a nested `<svg>` viewport at the box, whose\n * `viewBox` is the source window over a unit-square `<image>` — plain SVG 1.1,\n * which any reader crops and mirrors the same way, and which `parseSvg` reads\n * back as one image node.\n */\nexport interface SvgImageNode {\n kind: 'image';\n href: string;\n x: number;\n y: number;\n width: number;\n height: number;\n /** The part of the bitmap drawn into the box, as fractions of the bitmap's\n * width and height from its top-left. Omitted draws the whole bitmap.\n * Fractions rather than bitmap pixels because this package never decodes\n * the image, so it cannot know its size. */\n source?: { x: number; y: number; width: number; height: number };\n /** Mirror the drawn region within the box, as `ImageDrawCommand` does. The\n * box does not move. */\n flipX?: boolean;\n flipY?: boolean;\n /** Element-level opacity (`opacity=\"...\"`), 0..1. */\n opacity?: number;\n /** Element-level rotation in **radians**, pivoting around the unrotated\n * AABB center `(x + width/2, y + height/2)`. Emitted as SVG\n * `transform=\"rotate(angleDegrees cx cy)\"`. */\n rotation?: number;\n /** Opaque per-element bag for declared namespaces. See `NamespaceMeta`. */\n meta?: NamespaceMeta;\n}\n\n/** Discriminated-union node — the leaf of the public tree. */\nexport type SvgNode = SvgPathNode | SvgGroupNode | SvgTextNode | SvgImageNode;\n\n/** Options for {@link parseSvg}. */\nexport interface ParseOptions {\n /**\n * Map of prefix → URI for XML namespaces the caller wants surfaced.\n * Attributes / child elements in any declared namespace are collected\n * into `SvgNode.meta` (per element) or `ParseResult.documentMeta` (root).\n * Undeclared namespaces are preserved in the DOM but not promoted into\n * the structured `meta` bag; they are silently dropped at serialize time.\n */\n namespaces?: Record<string, string>;\n}\n\n/** Output of {@link parseSvg}. */\nexport interface ParseResult {\n nodes: SvgNode[];\n /** Non-fatal notices (unsupported elements, unrecognized attributes). */\n warnings: string[];\n /**\n * Opaque per-document bag for declared namespaces. Holds root-level\n * namespaced attributes (`documentMeta.<prefix>.attrs`) and namespaced\n * root children (`documentMeta.<prefix>.elements`).\n */\n documentMeta?: NamespaceMeta;\n /** Root `viewBox` attribute, parsed from `\"x y width height\"`. */\n viewBox?: { x: number; y: number; width: number; height: number };\n /** Root `width` attribute, parsed as a unitless number when present. */\n width?: number;\n /** Root `height` attribute, parsed as a unitless number when present. */\n height?: number;\n /** Text content of the first `<title>` child of `<svg>`, when present. */\n title?: string;\n /**\n * An entry for each document `<marker>` a stroke references under a key the\n * marker registry does not know, keyed as the strokes in `nodes` now name\n * them. Nothing draws them until they are registered (`registerMarker`),\n * which `unpackSvgFiles` does.\n */\n markers?: MarkerEntry[];\n}\n\n/** Options for {@link serializeSvg}. */\nexport interface SerializeOptions {\n /**\n * Override the root `viewBox`. When omitted, the serializer computes\n * a tight bounding box from the supplied nodes.\n */\n viewBox?: { x: number; y: number; width: number; height: number };\n /**\n * Called for what the document cannot carry the way weasel draws it: a\n * paint SVG cannot express (a pattern carrying a `TextureHandle` instead of\n * a `TilePatternSpec`), a stroke aligned off its edge, text that wraps or\n * sits lower than the top of its box. Each message is said once per call.\n * Without this the loss is silent.\n */\n onWarn?: (message: string) => void;\n /** Emit `width=\"...\"` on the root `<svg>`. */\n width?: number;\n /** Emit `height=\"...\"` on the root `<svg>`. */\n height?: number;\n /**\n * Emit `<title>...</title>` as the first child of the root `<svg>`. The\n * value is XML-escaped on output. Empty strings are skipped.\n */\n title?: string;\n /**\n * Map of prefix → URI for XML namespaces to declare on the root\n * `<svg>`. The serializer reads `documentMeta[prefix]` and\n * `node.meta[prefix]` to write the actual attributes and elements.\n */\n namespaces?: Record<string, string>;\n /**\n * Opaque per-document namespaced extras. Each `<prefix>.attrs` becomes\n * `<prefix>:<name>=\"...\"` attributes on the root `<svg>`. Each\n * `<prefix>.elements[localName]` becomes `<prefix>:<localName>...>`\n * children placed immediately before any geometry.\n */\n documentMeta?: NamespaceMeta;\n /** Pretty-print with newlines + indentation. Default `false`. */\n pretty?: boolean;\n}\n","/**\n * SVG transform attribute helpers. Parses the four primitive transform\n * functions weasel-svg supports (`matrix`, `translate`, `scale`, `rotate`)\n * into a single 2x3 affine matrix, and exposes the point/path mappers we\n * need to collapse `transform=` onto leaf geometry at parse time.\n */\n\nimport { invert, multiply } from '@weasel-js/geom';\nimport type { Matrix } from './types';\nimport { IDENTITY_MATRIX } from './types';\n\n/** Compose two 2x3 affines, `a` then `b` applied to a column vector. The\n * kernel's own composition — `Matrix` is `Mat3`, so nothing converts. */\nexport { multiply };\n\n/** Apply a 2x3 affine to a 2D point. The `{x, y}` spelling the rest of this\n * package works in; geom's `applyToPoint` returns the same numbers as a\n * tuple. */\nexport function applyMatrix(m: Matrix, x: number, y: number): { x: number; y: number } {\n return { x: m[0] * x + m[2] * y + m[4], y: m[1] * x + m[3] * y + m[5] };\n}\n\n/** True if `m` is the identity within a small epsilon. */\nexport function isIdentity(m: Matrix, eps = 1e-9): boolean {\n return (\n Math.abs(m[0] - 1) < eps &&\n Math.abs(m[1]) < eps &&\n Math.abs(m[2]) < eps &&\n Math.abs(m[3] - 1) < eps &&\n Math.abs(m[4]) < eps &&\n Math.abs(m[5]) < eps\n );\n}\n\nconst NUM_RE = /[-+]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][-+]?\\d+)?/g;\n\nfunction readNumbers(s: string): number[] {\n const out: number[] = [];\n const matches = s.match(NUM_RE);\n if (!matches) return out;\n for (const m of matches) {\n const n = Number(m);\n if (Number.isFinite(n)) out.push(n);\n }\n return out;\n}\n\n/**\n * Parse an SVG `transform=\"...\"` string into a single 2x3 matrix.\n * Functions compose right-to-left in SVG's coordinate model: in\n * `transform=\"A B\"`, the rightmost function is applied first to a point's\n * local coordinates. We accumulate accordingly: `result = result * fn`.\n *\n * Unrecognized functions emit a warning via the optional callback and are\n * skipped (the rest of the transform list still applies).\n */\nexport function parseTransform(\n attr: string | null | undefined,\n onWarn?: (message: string) => void,\n): Matrix {\n if (!attr) return IDENTITY_MATRIX;\n let result: Matrix = IDENTITY_MATRIX;\n // Split into \"name(args)\" chunks.\n const fnRe = /([A-Za-z]+)\\s*\\(([^)]*)\\)/g;\n let match: RegExpExecArray | null;\n while ((match = fnRe.exec(attr)) !== null) {\n const name = match[1].toLowerCase();\n const nums = readNumbers(match[2]);\n let local: Matrix | null = null;\n if (name === 'matrix' && nums.length >= 6) {\n local = [nums[0], nums[1], nums[2], nums[3], nums[4], nums[5]];\n } else if (name === 'translate') {\n const tx = nums[0] ?? 0;\n const ty = nums[1] ?? 0;\n local = [1, 0, 0, 1, tx, ty];\n } else if (name === 'scale') {\n const sx = nums[0] ?? 1;\n const sy = nums.length >= 2 ? nums[1] : sx;\n local = [sx, 0, 0, sy, 0, 0];\n } else if (name === 'rotate') {\n const ang = ((nums[0] ?? 0) * Math.PI) / 180;\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n const rot: Matrix = [c, s, -s, c, 0, 0];\n if (nums.length >= 3) {\n // rotate(angle, cx, cy) = translate(cx,cy) * rotate * translate(-cx,-cy)\n const cx = nums[1];\n const cy = nums[2];\n local = multiply(multiply([1, 0, 0, 1, cx, cy], rot), [1, 0, 0, 1, -cx, -cy]);\n } else {\n local = rot;\n }\n } else if (name === 'skewx' || name === 'skewy') {\n const ang = ((nums[0] ?? 0) * Math.PI) / 180;\n const t = Math.tan(ang);\n local = name === 'skewx' ? [1, 0, t, 1, 0, 0] : [1, t, 0, 1, 0, 0];\n } else {\n onWarn?.(`unsupported transform function: ${name}`);\n continue;\n }\n result = multiply(result, local);\n }\n return result;\n}\n\n/**\n * Re-express an element's own `transform` in the frame its inherited `ctm`\n * maps into: `ctm * local * ctm⁻¹`.\n *\n * A leaf's geometry is baked through `ctm` at parse time, so its own\n * transform has to move with it. Decomposing the raw local matrix against\n * bounds that have already been through `ctm` compares two different\n * coordinate spaces, and a rotation inside a translated `<g>` fails to\n * decompose for no reason but the offset.\n *\n * `null` when `@weasel-js/geom`'s `invert` finds `ctm` singular: the geometry\n * has collapsed through it, and the local transform has no frame to live in.\n */\nexport function rebaseTransform(ctm: Matrix, local: Matrix): Matrix | null {\n const inv = invert(ctm);\n if (!inv) return null;\n return multiply(multiply(ctm, local), inv);\n}\n\n/** Try to factor `m` as \"rotation by theta about (cx, cy)\". Returns the\n * angle in radians when `m` is (within `eps`) a pure rotation about the\n * given pivot. Returns `null` otherwise.\n *\n * Pure rotation about (cx, cy) has the matrix form:\n * [ cos -sin cx - cx*cos + cy*sin ]\n * [ sin cos cy - cx*sin - cy*cos ]\n * i.e. m[0] = m[3] = cos, m[1] = -m[2] = sin, with a translation that\n * equals the pivot's \"rotate-then-translate-back\" residue. We reconstruct\n * theta from atan2(m[1], m[0]) and verify the rest.\n */\nexport function decomposeRotation(\n m: Matrix,\n cx: number,\n cy: number,\n eps = 1e-4,\n): number | null {\n const [a, b, c, d, e, f] = m;\n // Pure rotation requires a == d and b == -c.\n if (Math.abs(a - d) > eps) return null;\n if (Math.abs(b + c) > eps) return null;\n // Determinant must be 1 (no scale, no flip).\n const det = a * d - b * c;\n if (Math.abs(det - 1) > eps) return null;\n const theta = Math.atan2(b, a);\n // Verify translation = (cx - cx*cos + cy*sin, cy - cx*sin - cy*cos).\n const expectedE = cx - cx * a + cy * b;\n const expectedF = cy - cx * b - cy * a;\n if (Math.abs(e - expectedE) > eps) return null;\n if (Math.abs(f - expectedF) > eps) return null;\n return theta;\n}\n\n/** Best-effort rotational-component extraction for a general matrix (any\n * scale + rotation, ignoring translation). Used for parse-time warnings\n * on un-decomposable matrices: we can detect \"there is a rotation here\"\n * even if we won't preserve it as `node.rotation`. For a non-uniform\n * matrix the \"rotation\" is ambiguous; we report atan2(b, a) which\n * corresponds to where the +x basis vector points.\n */\nexport function rotationComponent(m: Matrix): number {\n return Math.atan2(m[1], m[0]);\n}\n\n/**\n * Format a matrix as an SVG `matrix(a b c d e f)` value. Returns `null`\n * when `m` is (effectively) the identity, so the caller can omit the\n * attribute entirely.\n */\nexport function formatMatrix(m: Matrix): string | null {\n if (isIdentity(m)) return null;\n return `matrix(${m.map((n) => trimNumber(n)).join(' ')})`;\n}\n\n/** Trim trailing zeros from a numeric value for compact SVG output. */\nexport function trimNumber(n: number): string {\n if (!Number.isFinite(n)) return '0';\n // Round to ~6 decimal places to avoid floating-point cruft.\n const r = Math.round(n * 1e6) / 1e6;\n if (Number.isInteger(r)) return String(r);\n return String(r);\n}\n","import { resolveAlign, type TextStyle } from '@weasel-js/core';\n\n/**\n * Distance from a text box's left edge to its SVG anchor point: `x` on a\n * `<text>` is where `text-anchor` lands, which is the box's left edge, center\n * or right edge once `align` and `direction` resolve to an absolute edge.\n */\nexport function anchorOffset(style: TextStyle | undefined, width: number): number {\n const edge = resolveAlign(style?.align ?? 'left', style?.direction ?? 'ltr');\n return edge === 'center' ? width / 2 : edge === 'right' ? width : 0;\n}\n","/**\n * Map between SVG `<pattern>` elements and weasel's `pattern` `FillStyle`.\n * The counterpart to `gradients.ts` for the other paint-server kind.\n *\n * The tile's shapes come from `tileGeometry` in core, so the vector form a\n * viewer sees is generated from the same description that rasterizes the GL\n * texture. Alongside them we write the spec itself onto a `data-weasel-tile`\n * attribute: any SVG consumer renders the shapes, and weasel reads the\n * attribute back to recover the exact spec rather than reverse-engineering\n * it from geometry.\n *\n * A pattern whose payload is a `TextureHandle` has no vector form — the\n * handle is a session-scoped registry key with no tile description behind\n * it — and exports as nothing, with a warning. Same treatment conic\n * gradients get.\n */\n\nimport { tileGeometry, type TileShape } from '@weasel-js/core/patterns-builtin';\nimport type { FillStyle, TilePatternSpec } from '@weasel-js/core';\nimport { collectElementsByTag } from './elements';\nimport { trimNumber } from './transform';\n\ntype PatternFill = Extract<FillStyle, { fill: 'pattern' }>;\n\n/** Collected pattern definitions, keyed by element id. */\nexport type PatternTable = Map<string, FillStyle>;\n\n/** Whether a pattern paint carries a serializable spec. */\nexport function patternSpecOf(paint: PatternFill): TilePatternSpec | null {\n return 'tile' in paint.pattern ? paint.pattern : null;\n}\n\nexport function patternXml(id: string, paint: PatternFill, onWarn?: (m: string) => void): string {\n const spec = patternSpecOf(paint);\n if (!spec) {\n onWarn?.('pattern fill carries a TextureHandle, which has no vector form — omitted from <defs>');\n return '';\n }\n const geometry = tileGeometry(spec);\n const body = geometry.shapes.map(shapeXml).join('');\n const origin = paint.origin ?? { x: 0, y: 0 };\n const attrs = [\n `id=\"${id}\"`,\n 'patternUnits=\"userSpaceOnUse\"',\n `width=\"${trimNumber(geometry.size)}\"`,\n `height=\"${trimNumber(geometry.size)}\"`,\n ];\n if (origin.x !== 0 || origin.y !== 0) {\n attrs.push(`x=\"${trimNumber(origin.x)}\"`, `y=\"${trimNumber(origin.y)}\"`);\n }\n attrs.push(`data-weasel-tile=\"${escapeAttr(JSON.stringify(spec))}\"`);\n return `<pattern ${attrs.join(' ')}>${body}</pattern>`;\n}\n\n/**\n * A single tile as a standalone `<svg>` document, sized to its own extent.\n * For UI that needs to show a tile outside a document — a picker swatch,\n * set as a repeating CSS `background-image` via a data URI. Shares the shape\n * mapper with `patternXml`, so a preview can't drift from what paints.\n */\nexport function tilePreviewSvg(spec: TilePatternSpec, background?: string): string {\n const geometry = tileGeometry(spec);\n const s = trimNumber(geometry.size);\n const bg = background\n ? `<rect width=\"${s}\" height=\"${s}\" fill=\"${background}\"/>`\n : '';\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${s}\" height=\"${s}\" `\n + `viewBox=\"0 0 ${s} ${s}\">${bg}${geometry.shapes.map(shapeXml).join('')}</svg>`;\n}\n\n/** `tilePreviewSvg` packed as a `url(...)` value for CSS `background-image`. */\nexport function tilePreviewCssUrl(spec: TilePatternSpec, background?: string): string {\n return `url(\"data:image/svg+xml,${encodeURIComponent(tilePreviewSvg(spec, background))}\")`;\n}\n\nfunction shapeXml(shape: TileShape): string {\n switch (shape.kind) {\n case 'line':\n return `<line x1=\"${trimNumber(shape.x1)}\" y1=\"${trimNumber(shape.y1)}\" `\n + `x2=\"${trimNumber(shape.x2)}\" y2=\"${trimNumber(shape.y2)}\" `\n + `stroke=\"${shape.color}\" stroke-width=\"${trimNumber(shape.width)}\"/>`;\n case 'circle':\n return `<circle cx=\"${trimNumber(shape.cx)}\" cy=\"${trimNumber(shape.cy)}\" `\n + `r=\"${trimNumber(shape.r)}\" fill=\"${shape.color}\"/>`;\n case 'ellipse': {\n const deg = (shape.rotation * 180) / Math.PI;\n const transform = deg === 0\n ? ''\n : ` transform=\"rotate(${trimNumber(deg)} ${trimNumber(shape.cx)} ${trimNumber(shape.cy)})\"`;\n return `<ellipse cx=\"${trimNumber(shape.cx)}\" cy=\"${trimNumber(shape.cy)}\" `\n + `rx=\"${trimNumber(shape.rx)}\" ry=\"${trimNumber(shape.ry)}\" `\n + `fill=\"${shape.color}\"${transform}/>`;\n }\n case 'rect':\n return `<rect x=\"${trimNumber(shape.x)}\" y=\"${trimNumber(shape.y)}\" `\n + `width=\"${trimNumber(shape.width)}\" height=\"${trimNumber(shape.height)}\" `\n + `fill=\"${shape.color}\"/>`;\n default:\n return '';\n }\n}\n\n/** Read every `<pattern>` in the document back into pattern paints. */\nexport function collectPatterns(svg: Element, onWarn?: (m: string) => void): PatternTable {\n const out: PatternTable = new Map();\n for (const [id, el] of collectElementsByTag(svg, PATTERN_TAGS)) {\n const paint = readPattern(el, onWarn);\n if (paint) out.set(id, paint);\n }\n return out;\n}\n\nconst PATTERN_TAGS = new Set(['pattern']);\n\nfunction readPattern(el: Element, onWarn?: (m: string) => void): FillStyle | null {\n const raw = el.getAttribute('data-weasel-tile');\n if (!raw) {\n // A hand-authored pattern (Illustrator, Inkscape) holds arbitrary\n // geometry no `TilePatternSpec` can express. Recognizing it would mean\n // reverse-engineering a tile from its children; dropping it with a\n // warning is honest, and the element survives in the source file.\n onWarn?.(`<pattern id=\"${el.getAttribute('id')}\"> has no data-weasel-tile — unsupported pattern, dropped`);\n return null;\n }\n let spec: TilePatternSpec;\n try {\n spec = JSON.parse(raw) as TilePatternSpec;\n } catch {\n onWarn?.(`<pattern id=\"${el.getAttribute('id')}\"> has malformed data-weasel-tile — dropped`);\n return null;\n }\n if (typeof spec?.tile !== 'string' || typeof spec?.color !== 'string') {\n onWarn?.(`<pattern id=\"${el.getAttribute('id')}\"> data-weasel-tile is not a tile spec — dropped`);\n return null;\n }\n const x = parseFloat(el.getAttribute('x') ?? '0');\n const y = parseFloat(el.getAttribute('y') ?? '0');\n const paint: PatternFill = { fill: 'pattern', pattern: spec };\n if (x !== 0 || y !== 0) paint.origin = { x, y };\n return paint;\n}\n\nfunction escapeAttr(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n","/**\n * Serialize a weasel `Path` to an SVG `d=` attribute string. `RectPath`\n * lowers to `M h v h Z`; `PolygonPath` walks the (commands, coords)\n * arrays, emitting one SVG command per kit command.\n *\n * Output uses absolute commands only and a small amount of whitespace\n * compression (no leading zeros stripped beyond what `Number.toString`\n * already does). Numbers are rounded to ~6 decimals via `trimNumber`.\n */\n\nimport {\n PATH_C, PATH_L, PATH_M, PATH_Q, PATH_Z,\n type Path,\n} from '@weasel-js/core';\nimport { trimNumber } from './transform';\n\n/** Serialize a weasel `Path` to an SVG `d=` attribute string. */\nexport function serializePathD(path: Path): string {\n if (path.kind === 'rect') {\n const { x, y, width, height } = path;\n return `M${trimNumber(x)} ${trimNumber(y)}h${trimNumber(width)}v${trimNumber(height)}h${trimNumber(-width)}Z`;\n }\n const cmds = path.commands;\n const xs = path.coords;\n const out: string[] = [];\n let ci = 0;\n for (let i = 0; i < cmds.length; i++) {\n const c = cmds[i];\n if (c === PATH_M) {\n out.push(`M${trimNumber(xs[ci])} ${trimNumber(xs[ci + 1])}`);\n ci += 2;\n } else if (c === PATH_L) {\n out.push(`L${trimNumber(xs[ci])} ${trimNumber(xs[ci + 1])}`);\n ci += 2;\n } else if (c === PATH_C) {\n out.push(\n `C${trimNumber(xs[ci])} ${trimNumber(xs[ci + 1])} ` +\n `${trimNumber(xs[ci + 2])} ${trimNumber(xs[ci + 3])} ` +\n `${trimNumber(xs[ci + 4])} ${trimNumber(xs[ci + 5])}`,\n );\n ci += 6;\n } else if (c === PATH_Q) {\n out.push(\n `Q${trimNumber(xs[ci])} ${trimNumber(xs[ci + 1])} ` +\n `${trimNumber(xs[ci + 2])} ${trimNumber(xs[ci + 3])}`,\n );\n ci += 4;\n } else if (c === PATH_Z) {\n out.push('Z');\n }\n }\n return out.join('');\n}\n","/**\n * Map between SVG `<linearGradient>` / `<radialGradient>` elements and\n * weasel's `FillStyle` gradient variants. Definitions are indexed by id\n * wherever in the document they appear, and looked up when a `fill` /\n * `stroke` attribute references one as `url(#id)`. On serialize, we\n * emit a fresh `<defs>` block with stable generated ids.\n */\n\nimport { getPaintKind, getMarker, resolveMarkerSize } from '@weasel-js/core';\nimport type {\n FillStyle, GradStop, GradientUnits, MarkerEntry, MarkerPaint, MarkerRef, Path, ScreenLength,\n} from '@weasel-js/core';\nimport { ownProp } from './cascade';\nimport { parsePaintAttr } from './color';\nimport { trimNumber } from './transform';\nimport { patternXml } from './patterns';\nimport { collectElementsByTag, type ElementTable } from './elements';\nimport { serializePathD } from './path-serializer';\n\n/** Collected gradient definitions, keyed by element id. */\nexport type GradientTable = Map<string, FillStyle>;\n\n/**\n * The namespace weasel's own paint servers are written in, and the prefix they\n * are written under. A conic gradient has no SVG element to target — SVG has\n * `linearGradient` and `radialGradient` and nothing else — so it goes out as a\n * foreign-namespaced def that this package reads back and every other renderer\n * skips in favor of the paint fallback color beside the reference.\n *\n * A registered paint kind's own `toSvg` may use this prefix too: the root\n * declares it whenever any paint in the document lacks a native SVG form.\n */\nexport const WEASEL_NS = 'urn:weasel-js:svg';\nexport const WEASEL_NS_PREFIX = 'wzl';\n\n/** `true` when SVG has a paint server for this kind, so the reference needs no\n * fallback color and the root needs no foreign namespace. */\n/** Whether SVG has its own paint server for paint kind `kind`: solids, the\n * linear and radial gradients, and patterns. Any other kind is written in\n * weasel's namespace with a fallback color, which other renderers paint flat. */\nexport function nativeSvgKind(kind: string): boolean {\n return kind === 'solid' || kind === 'linear-gradient' || kind === 'radial-gradient' || kind === 'pattern';\n}\n\nfunction hasNativeSvgForm(paint: FillStyle): boolean {\n return nativeSvgKind(paint.fill ?? 'solid');\n}\n\n/**\n * The spaces `interpolate` can name, as SVG spells them. SVG's own\n * `color-interpolation` carries `sRGB` and `linearRGB` only, so anything\n * perceptual goes out as a namespaced attribute a foreign renderer ignores —\n * which leaves it interpolating in sRGB. That is a shifted midpoint rather\n * than a lost paint, so these gradients keep their native element and take no\n * fallback color.\n */\nconst INTERPOLATE_SPACES = new Set(['rgb', 'oklab', 'oklch']);\n\n/** Whether a gradient interpolating through `space` blends the same in every\n * SVG renderer — only sRGB, the default. A perceptual space still exports,\n * but renderers other than weasel blend it in sRGB. */\nexport function nativeSvgSpace(space: string | null | undefined): boolean {\n return !space || space === 'rgb';\n}\n\n/** The `wzl:interpolate` attribute a gradient needs, or `''` for the sRGB\n * default every other renderer already assumes. */\nfunction interpolateAttr(space: string | undefined): string {\n if (nativeSvgSpace(space)) return '';\n return ` ${WEASEL_NS_PREFIX}:interpolate=\"${space}\"`;\n}\n\n/** `interpolate` off a gradient element, or `undefined` — for the field's\n * absence and for a space this package does not model alike. */\nfunction readInterpolate(el: Element, elements: ElementTable): 'oklab' | 'oklch' | undefined {\n const raw = inheritedAttr(el, elements, `${WEASEL_NS_PREFIX}:interpolate`)\n ?? el.getAttributeNS(WEASEL_NS, 'interpolate');\n if (raw === 'oklab' || raw === 'oklch') return raw;\n return undefined;\n}\n\n/** Whether any gradient in the document names a space SVG cannot, so the root\n * has to declare the namespace the attribute is written in. */\nfunction usesInterpolateAttr(paint: FillStyle): boolean {\n const space = (paint as { interpolate?: string }).interpolate;\n return !nativeSvgSpace(space) && INTERPOLATE_SPACES.has(space!);\n}\n\n/** The local name of a tag, prefix stripped. */\nfunction localName(tag: string): string {\n const i = tag.indexOf(':');\n return (i < 0 ? tag : tag.slice(i + 1)).toLowerCase();\n}\n\nconst GRADIENT_TAGS = new Set([\n 'lineargradient', 'radialgradient', 'conicgradient', `${WEASEL_NS_PREFIX}:conicgradient`,\n 'meshgradient', `${WEASEL_NS_PREFIX}:meshgradient`,\n]);\n\nconst XLINK_NS = 'http://www.w3.org/1999/xlink';\n\n/** Read every gradient definition in the document, keyed by element id. */\nexport function collectGradients(svg: Element, onWarn?: (m: string) => void): GradientTable {\n const out: GradientTable = new Map();\n const elements = collectElementsByTag(svg, GRADIENT_TAGS);\n for (const [id, el] of elements) {\n const tag = localName(el.tagName);\n const paint = tag === 'lineargradient'\n ? readLinearGradient(el, elements, onWarn)\n : tag === 'conicgradient'\n ? readConicGradient(el, elements, onWarn)\n : tag === 'meshgradient'\n ? readMeshGradient(el, onWarn)\n : readRadialGradient(el, elements, onWarn);\n if (paint) out.set(id, paint);\n }\n warnUnsupportedDefsChildren(svg, onWarn);\n return out;\n}\n\n/** Paint servers, `<marker>`, `<clipPath>` and `<style>` aside, a `<defs>` child is\n * something this package does not model (a `<use>` template, a `<filter>`).\n * Say so once here. */\nfunction warnUnsupportedDefsChildren(svg: Element, onWarn?: (m: string) => void): void {\n if (!onWarn) return;\n const defs = svg.getElementsByTagName('defs');\n for (let d = 0; d < defs.length; d++) {\n const root = defs[d];\n for (let i = 0; i < root.children.length; i++) {\n const child = root.children[i];\n const tag = child.tagName.toLowerCase();\n if (GRADIENT_TAGS.has(tag) || GRADIENT_TAGS.has(localName(tag))) continue;\n if (tag === 'pattern' || tag === 'marker' || tag === 'clippath' || tag === 'style') continue;\n onWarn(`unsupported <defs> child: <${child.tagName}>`);\n }\n }\n}\n\n/**\n * The gradient a `href` / `xlink:href` attribute points at, or null. SVG lets\n * one gradient inherit another's stops and attributes this way, and authoring\n * tools lean on it heavily — a chain that isn't followed resolves to a\n * gradient with no stops, which paints nothing.\n */\nfunction hrefTarget(el: Element, elements: ElementTable): Element | null {\n const raw = el.getAttribute('href')\n ?? el.getAttributeNS(XLINK_NS, 'href')\n ?? el.getAttribute('xlink:href');\n if (!raw || !raw.startsWith('#')) return null;\n return elements.get(raw.slice(1)) ?? null;\n}\n\n/** An attribute's value on `el` or, when absent, on the gradient it inherits\n * from. `seen` breaks a reference cycle. */\nfunction inheritedAttr(\n el: Element, elements: ElementTable, name: string, seen: Set<Element> = new Set(),\n): string | null {\n if (el.hasAttribute(name)) return el.getAttribute(name);\n seen.add(el);\n const ref = hrefTarget(el, elements);\n if (!ref || seen.has(ref)) return null;\n return inheritedAttr(ref, elements, name, seen);\n}\n\n/** `el`'s own stops or, when it declares none, the stops it inherits. */\nfunction inheritedStops(\n el: Element, elements: ElementTable, onWarn?: (m: string) => void,\n seen: Set<Element> = new Set(),\n): GradStop[] {\n const own = readStops(el, onWarn);\n if (own.length > 0) return own;\n seen.add(el);\n const ref = hrefTarget(el, elements);\n if (!ref || seen.has(ref)) return own;\n return inheritedStops(ref, elements, onWarn, seen);\n}\n\n/** Parse a `stop-opacity` / offset value that may carry a `%` suffix. */\nfunction parseRatio(raw: string): number {\n const n = parseFloat(raw);\n if (!Number.isFinite(n)) return NaN;\n return raw.trimEnd().endsWith('%') ? n / 100 : n;\n}\n\nfunction readStops(el: Element, onWarn?: (m: string) => void): GradStop[] {\n const stops: GradStop[] = [];\n for (let i = 0; i < el.children.length; i++) {\n const c = el.children[i];\n if (c.tagName.toLowerCase() !== 'stop') continue;\n const offsetRaw = parseRatio(c.getAttribute('offset') ?? '0');\n const offset = Number.isFinite(offsetRaw) ? offsetRaw : 0;\n const colorAttr = ownProp(c, 'stop-color') ?? '#000000';\n const parsed = parsePaintAttr(colorAttr);\n if (parsed && parsed.kind === 'solid') {\n const opacityAttr = ownProp(c, 'stop-opacity');\n const own = opacityAttr != null ? parseRatio(opacityAttr) : NaN;\n const alpha = Number.isFinite(own) ? own : parsed.alpha;\n stops.push({ offset, color: alpha < 1 ? applyAlpha(parsed.color, alpha) : parsed.color });\n } else {\n onWarn?.(`gradient stop has unrecognized stop-color: ${colorAttr}`);\n stops.push({ offset, color: '#000000' });\n }\n }\n return stops;\n}\n\nfunction applyAlpha(hex: string, alpha: number): string {\n // Pack alpha into an 8-digit hex so it round-trips through weasel's\n // string-color storage. This is non-standard CSS hex but parses cleanly\n // back via our color.ts parser.\n const a = Math.max(0, Math.min(255, Math.round(alpha * 255)));\n return `${hex}${a.toString(16).padStart(2, '0')}`;\n}\n\n/** SVG `gradientUnits` → the kit's `GradientUnits`. SVG's default is\n * `objectBoundingBox`, which is what the attribute defaults above assume\n * (`x2=\"1\"`, `r=\"0.5\"`), so the two have to be read together. */\nfunction readGradientUnits(el: Element, elements: ElementTable): 'bounds' | 'world' {\n return inheritedAttr(el, elements, 'gradientUnits') === 'userSpaceOnUse' ? 'world' : 'bounds';\n}\n\n/** `gradientTransform` has no slot in the kit's gradient model, so a gradient\n * carrying one paints in the wrong place rather than not at all. */\nfunction warnGradientTransform(\n el: Element, elements: ElementTable, onWarn?: (m: string) => void,\n): void {\n const t = inheritedAttr(el, elements, 'gradientTransform');\n if (t != null && t.trim() !== '') {\n onWarn?.(`gradientTransform=\"${t}\" is not modeled; the gradient paints untransformed`);\n }\n}\n\nfunction num(raw: string | null, fallback: number): number {\n if (raw == null) return fallback;\n const n = parseRatio(raw);\n return Number.isFinite(n) ? n : fallback;\n}\n\nfunction readLinearGradient(\n el: Element, elements: ElementTable, onWarn?: (m: string) => void,\n): FillStyle | null {\n warnGradientTransform(el, elements, onWarn);\n return {\n fill: 'linear-gradient',\n from: {\n x: num(inheritedAttr(el, elements, 'x1'), 0),\n y: num(inheritedAttr(el, elements, 'y1'), 0),\n },\n to: {\n x: num(inheritedAttr(el, elements, 'x2'), 1),\n y: num(inheritedAttr(el, elements, 'y2'), 0),\n },\n stops: inheritedStops(el, elements, onWarn),\n units: readGradientUnits(el, elements),\n interpolate: readInterpolate(el, elements),\n };\n}\n\nfunction readRadialGradient(\n el: Element, elements: ElementTable, onWarn?: (m: string) => void,\n): FillStyle | null {\n warnGradientTransform(el, elements, onWarn);\n return {\n fill: 'radial-gradient',\n center: {\n x: num(inheritedAttr(el, elements, 'cx'), 0.5),\n y: num(inheritedAttr(el, elements, 'cy'), 0.5),\n },\n radius: num(inheritedAttr(el, elements, 'r'), 0.5),\n stops: inheritedStops(el, elements, onWarn),\n units: readGradientUnits(el, elements),\n interpolate: readInterpolate(el, elements),\n };\n}\n\nfunction readConicGradient(\n el: Element, elements: ElementTable, onWarn?: (m: string) => void,\n): FillStyle | null {\n warnGradientTransform(el, elements, onWarn);\n return {\n fill: 'conic-gradient',\n center: {\n x: num(inheritedAttr(el, elements, 'cx'), 0.5),\n y: num(inheritedAttr(el, elements, 'cy'), 0.5),\n },\n angle: num(inheritedAttr(el, elements, 'angle'), 0),\n stops: inheritedStops(el, elements, onWarn),\n units: readGradientUnits(el, elements),\n interpolate: readInterpolate(el, elements),\n };\n}\n\n/**\n * A `<wzl:meshGradient>` back into the `mesh-gradient` paint core registers.\n *\n * Every patch carries all twelve (or sixteen) of its points, so nothing here\n * infers a shared edge — the trap that makes SVG's own abandoned\n * `<meshgradient>` hard to read correctly. A patch whose attributes do not\n * parse is dropped with a warning rather than guessed at: a mesh missing a\n * patch is visibly wrong, where a mesh holding an invented one is not.\n */\nfunction readMeshGradient(el: Element, onWarn?: (m: string) => void): FillStyle | null {\n const patches: { points: { x: number; y: number }[]; colors: string[] }[] = [];\n for (let i = 0; i < el.children.length; i++) {\n const child = el.children[i];\n if (localName(child.tagName) !== 'patch') continue;\n const points = (child.getAttribute('points') ?? '').trim().split(/\\s+/)\n .filter(Boolean)\n .map((pair) => {\n const [x, y] = pair.split(',').map(Number);\n return { x, y };\n });\n const colors = (child.getAttribute('colors') ?? '').trim().split(/\\s+/).filter(Boolean);\n const sane = (points.length === 12 || points.length === 16)\n && points.every((p) => Number.isFinite(p.x) && Number.isFinite(p.y))\n && colors.length === 4;\n if (!sane) {\n onWarn?.(`<${WEASEL_NS_PREFIX}:patch> with ${points.length} points and ${colors.length} colors — dropped`);\n continue;\n }\n patches.push({ points, colors });\n }\n if (patches.length === 0) return null;\n const space = el.getAttribute('interpolate') ?? el.getAttributeNS(WEASEL_NS, 'interpolate');\n return {\n fill: 'mesh-gradient',\n patches,\n units: el.getAttribute('gradientUnits') === 'objectBoundingBox' ? 'bounds' : 'world',\n ...(space === 'oklab' || space === 'oklch' ? { interpolate: space } : {}),\n } as unknown as FillStyle;\n}\n\n/**\n * Pre-pass that assigns stable serialization ids to the paint servers —\n * gradients and patterns — used by any leaf in the tree. We key on object\n * identity so two leaves sharing the exact same `FillStyle` reference reuse\n * one `<defs>` entry; structurally equal but distinct objects get separate\n * ids.\n */\nexport class PaintServerRegistry {\n private byPaint = new Map<FillStyle, string>();\n private order: FillStyle[] = [];\n private counter = 0;\n\n // Marker defs referenced by any stroke, by `<defs>` id in first-use order.\n // An unsized reference's id is the marker key itself, not a minted counter\n // id: `parseSvg` reads a `marker-end=\"url(#id)\"` fragment back as the marker\n // key directly when the registry knows it, so a synthetic id would come\n // back as a stranger. A sized one gets a def of its own, stamped with its\n // key and size so the parser can read the reference back whole.\n private markers = new Map<string, { key: string; size?: ScreenLength }>();\n\n // Clip paths, in first-use order. Identity, not value: two groups clipped by\n // equal outlines get a def each, which costs bytes and misleads nobody.\n private clips: Path[] = [];\n private clipIds = new Map<Path, string>();\n\n register(paint: FillStyle): string {\n const existing = this.byPaint.get(paint);\n if (existing) return existing;\n const id = paint.fill === 'pattern' ? `pat${this.counter++}` : `grad${this.counter++}`;\n this.byPaint.set(paint, id);\n this.order.push(paint);\n return id;\n }\n\n /**\n * The `fill` / `stroke` attribute value referencing this paint server: a\n * `url(#id)` reference, plus the fallback paint SVG's own grammar allows\n * after one for any kind SVG cannot express. A renderer that cannot resolve\n * the reference takes the fallback instead of dropping the fill, which is\n * the difference between a flat shape and a vanished one.\n */\n ref(paint: FillStyle): string {\n const id = this.register(paint);\n if (hasNativeSvgForm(paint)) return `url(#${id})`;\n return `url(#${id}) ${paintFallback(paint)}`;\n }\n\n /** Whether any registered paint serializes outside SVG's own vocabulary, so\n * the root has to declare {@link WEASEL_NS}. */\n usesPrivateNamespace(): boolean {\n return this.order.some((paint) => !hasNativeSvgForm(paint) || usesInterpolateAttr(paint))\n || [...this.markers.values()].some((m) => m.size !== undefined || writesInset(getMarker(m.key)));\n }\n\n /** The `<defs>` id for a marker reference — the key itself when it has no\n * size, else the key suffixed with the size. `undefined` when nothing is\n * registered under the key, so a caller emits no attribute at all rather\n * than a `url(#…)` pointing at a def that will never be written. */\n markerId(ref: MarkerRef): string | undefined {\n const key = typeof ref === 'string' ? ref : ref.key;\n const size = typeof ref === 'string' ? undefined : ref.size;\n if (getMarker(key) === undefined) return undefined;\n const id = size === undefined\n ? key\n : `${key}-s${typeof size === 'number' ? trimNumber(size) : `${trimNumber(size.px)}px`}`;\n if (!this.markers.has(id)) this.markers.set(id, size === undefined ? { key } : { key, size });\n return id;\n }\n\n /** Mint (or recall) the `<defs>` id for a clip outline. */\n clipId(path: Path): string {\n const existing = this.clipIds.get(path);\n if (existing) return existing;\n const id = `clip${this.clips.length}`;\n this.clipIds.set(path, id);\n this.clips.push(path);\n return id;\n }\n\n /** Emit `<defs>...</defs>` XML for every registered paint server, marker\n * and clip path. */\n toDefsXml(onWarn?: (m: string) => void): string {\n if (this.order.length === 0 && this.markers.size === 0 && this.clips.length === 0) {\n return '';\n }\n const parts: string[] = ['<defs>'];\n for (const paint of this.order) {\n parts.push(paintServerXml(this.byPaint.get(paint)!, paint, onWarn));\n }\n for (const [id, { key, size }] of this.markers) {\n const entry = getMarker(key);\n if (!entry) continue;\n if (entry.toSvg) {\n if (size !== undefined) onWarn?.(`marker \"${key}\" writes its own <marker> def, which cannot carry a reference's size; written at its own size`);\n parts.push(entry.toSvg(id, entry));\n } else {\n parts.push(defaultMarkerXml(id, entry, onWarn, key, size));\n }\n }\n for (const path of this.clips) {\n parts.push(\n `<clipPath id=\"${this.clipIds.get(path)!}\">`\n + `<path d=\"${serializePathD(path)}\"/>`\n + '</clipPath>',\n );\n }\n parts.push('</defs>');\n return parts.join('');\n }\n}\n\n/** Whether `entry`'s def carries `wzl:inset`: SVG has no way to say how far\n * a line stops short of its marker, so the parser needs it spelled out. */\nfunction writesInset(entry: MarkerEntry | undefined): boolean {\n return entry !== undefined && !entry.toSvg && (entry.inset ?? 0) !== 0;\n}\n\n/** The `<marker>` def for an entry with no `toSvg` of its own. Unsized, one\n * marker unit is one stroke width, as the kit draws it. A sized reference is\n * drawn in user space at `resolveMarkerSize`'s reading of its size, and\n * records its key and size in the private namespace for the parser. The\n * inset goes there too, in marker units either way. */\nfunction defaultMarkerXml(\n id: string, entry: MarkerEntry, onWarn?: (m: string) => void, key?: string, size?: ScreenLength,\n): string {\n const unit = size === undefined ? 1 : resolveMarkerSize({ key: key ?? id, size }, 1);\n const path = entry.path({ size: unit, stroke: { paint: { fill: 'solid', color: '#000' } } });\n const d = serializePathD(path);\n const fill = markerPaintAttrs('fill', entry.fill, id, onWarn);\n const outline = entry.outline\n ? ` ${markerPaintAttrs('stroke', entry.outline.paint, id, onWarn)} stroke-width=\"${trimNumber(entry.outline.width * unit)}\"`\n + ' stroke-linecap=\"round\" stroke-linejoin=\"round\"'\n : '';\n // The kit turns every start marker around, which is what SVG 2 spells\n // `auto-start-reverse`; plain `auto` would point a start head into the line.\n const orient = typeof entry.orient === 'number'\n ? trimNumber((entry.orient * 180) / Math.PI)\n : 'auto-start-reverse';\n const units = size === undefined\n ? 'markerUnits=\"strokeWidth\" markerWidth=\"8\" markerHeight=\"8\"'\n : `markerUnits=\"userSpaceOnUse\" markerWidth=\"${trimNumber(8 * unit)}\" markerHeight=\"${trimNumber(8 * unit)}\"`\n + ` ${WEASEL_NS_PREFIX}:key=\"${key}\" ${WEASEL_NS_PREFIX}:size=\"${\n typeof size === 'number' ? trimNumber(size) : `${trimNumber(size.px)}px`}\"`;\n const inset = writesInset(entry) ? ` ${WEASEL_NS_PREFIX}:inset=\"${trimNumber(entry.inset!)}\"` : '';\n // `overflow=\"visible\"` overrides the UA default of `hidden`, which would\n // otherwise clip the arrowhead to the marker's viewport.\n return (\n `<marker id=\"${id}\" ${units}${inset}` +\n ` refX=\"0\" refY=\"0\" orient=\"${orient}\" overflow=\"visible\">` +\n `<path d=\"${d}\" ${fill}${outline}/></marker>`\n );\n}\n\n/** A marker paint as `fill` / `stroke` attributes. `'line'` is SVG 2's\n * `context-stroke`; a paint server has no `<defs>` slot from here, so it\n * falls back to the line's paint and says so. */\nfunction markerPaintAttrs(\n attr: 'fill' | 'stroke',\n paint: MarkerPaint | undefined,\n id: string,\n onWarn?: (m: string) => void,\n): string {\n if (paint === 'none') return `${attr}=\"none\"`;\n if (paint === undefined || paint === 'line') return `${attr}=\"context-stroke\"`;\n if ('color' in paint && (paint.fill === undefined || paint.fill === 'solid')) {\n return paint.opacity != null && paint.opacity !== 1\n ? `${attr}=\"${paint.color}\" ${attr}-opacity=\"${trimNumber(paint.opacity)}\"`\n : `${attr}=\"${paint.color}\"`;\n }\n onWarn?.(`marker \"${id}\" ${attr} is a paint server, which a <marker> def cannot reference here; written as the line's paint`);\n return `${attr}=\"context-stroke\"`;\n}\n\n/** One paint server's `<defs>` entry: the built-in mapping, else the kind's\n * own `toSvg`, else nothing plus a warning. The referencing element already\n * carries `fill=\"url(#id)\"`, so a silent omission is a dangling reference and\n * the shape vanishes in a viewer. */\nfunction paintServerXml(id: string, paint: FillStyle, onWarn?: (m: string) => void): string {\n if (paint.fill === 'pattern') return patternXml(id, paint, onWarn);\n const builtin = gradientXml(id, paint);\n if (builtin) return builtin;\n const custom = getPaintKind(paint.fill)?.toSvg?.(id, paint);\n if (custom) return custom;\n onWarn?.(`${paint.fill} fill has no vector form — omitted from <defs>`);\n return '';\n}\n\n/** `GradientUnits` → SVG `gradientUnits`. `'screen'` (the kit's default, and\n * a viewport-fixed wash) has no SVG analog at all; it lowers to user space,\n * which at least puts the paint somewhere the geometry is. */\nfunction gradientUnitsAttr(units: GradientUnits | undefined): string {\n return units === 'bounds' ? 'objectBoundingBox' : 'userSpaceOnUse';\n}\n\nfunction gradientXml(id: string, paint: FillStyle): string {\n if (paint.fill === 'linear-gradient') {\n const stops = paint.stops.map(stopXml).join('');\n return (\n `<linearGradient id=\"${id}\" gradientUnits=\"${gradientUnitsAttr(paint.units)}\" ` +\n `x1=\"${trimNumber(paint.from.x)}\" y1=\"${trimNumber(paint.from.y)}\" ` +\n `x2=\"${trimNumber(paint.to.x)}\" y2=\"${trimNumber(paint.to.y)}\"` +\n `${interpolateAttr(paint.interpolate)}>${stops}</linearGradient>`\n );\n }\n if (paint.fill === 'conic-gradient') {\n const stops = paint.stops.map(stopXml).join('');\n const P = WEASEL_NS_PREFIX;\n return (\n `<${P}:conicGradient id=\"${id}\" gradientUnits=\"${gradientUnitsAttr(paint.units)}\" ` +\n `cx=\"${trimNumber(paint.center.x)}\" cy=\"${trimNumber(paint.center.y)}\" ` +\n `angle=\"${trimNumber(paint.angle)}\"` +\n `${interpolateAttr(paint.interpolate)}>${stops}</${P}:conicGradient>`\n );\n }\n if (paint.fill === 'radial-gradient') {\n const stops = paint.stops.map(stopXml).join('');\n return (\n `<radialGradient id=\"${id}\" gradientUnits=\"${gradientUnitsAttr(paint.units)}\" ` +\n `cx=\"${trimNumber(paint.center.x)}\" cy=\"${trimNumber(paint.center.y)}\" ` +\n `r=\"${trimNumber(paint.radius)}\"` +\n `${interpolateAttr(paint.interpolate)}>${stops}</radialGradient>`\n );\n }\n return '';\n}\n\n/**\n * The color a renderer that cannot resolve the reference should paint. `none`\n * when the paint has no single color to name — nothing painted is at least\n * honest, where an invented black is not.\n */\nfunction paintFallback(paint: FillStyle): string {\n const color = getPaintKind(paint.fill)?.colorOf(paint);\n if (!color) return 'none';\n // Whoever reads the fallback is by definition an older renderer, so the\n // packed alpha comes off rather than riding out as an 8-digit hex.\n const packed = /^#([0-9a-f]{6})[0-9a-f]{2}$/i.exec(color);\n return packed ? `#${packed[1].toLowerCase()}` : color;\n}\n\nfunction stopXml(s: GradStop): string {\n // Detect packed-alpha hex (#rrggbbaa) and split out stop-opacity.\n const m = /^#([0-9a-f]{6})([0-9a-f]{2})$/i.exec(s.color);\n if (m) {\n const alpha = parseInt(m[2], 16) / 255;\n return `<stop offset=\"${trimNumber(s.offset)}\" stop-color=\"#${m[1].toLowerCase()}\" stop-opacity=\"${trimNumber(alpha)}\"/>`;\n }\n return `<stop offset=\"${trimNumber(s.offset)}\" stop-color=\"${s.color}\"/>`;\n}\n","/**\n * Serialize a `SvgNode[]` tree to an SVG document string. Every leaf is\n * emitted as a `<path>` (even shapes that started as `<rect>` etc.) —\n * lossless geometry round-trip beats round-tripping the element-kind\n * label. Gradient paints are gathered into a single `<defs>` block.\n */\n\nimport type { Path, Stroke, StrokeAlign } from '@weasel-js/core';\nimport { boundsOfPath, resolveScreenLength, SCRIPT_METRICS } from '@weasel-js/core';\nimport type {\n Matrix, NamespaceMeta, NamespacedElement, SerializeOptions, SvgGroupNode,\n SvgNode, SvgPaint, SvgPathNode, SvgStroke, SvgTextNode, SvgImageNode,\n ScreenLength,\n} from './types';\nimport { IDENTITY_MATRIX } from './types';\nimport { serializePathD } from './path-serializer';\nimport { formatMatrix, multiply, trimNumber } from './transform';\nimport { PaintServerRegistry, WEASEL_NS, WEASEL_NS_PREFIX } from './gradients';\nimport { anchorOffset } from './textAnchor';\n\n/**\n * Walk the tree and produce an SVG document string. The root `<svg>`'s\n * `viewBox` is taken from `opts.viewBox` if supplied, otherwise computed\n * as a tight bounding box around every leaf.\n */\nexport function serializeSvg(nodes: SvgNode[], opts: SerializeOptions = {}): string {\n const registry = new PaintServerRegistry();\n registerPaintServers(nodes, registry);\n\n const bounds = opts.viewBox ?? computeBounds(nodes);\n const vb = `${trimNumber(bounds.x)} ${trimNumber(bounds.y)} ${trimNumber(bounds.width)} ${trimNumber(bounds.height)}`;\n const namespaces = opts.namespaces ?? {};\n\n const rootAttrs: string[] = [`xmlns=\"http://www.w3.org/2000/svg\"`];\n // Declared before the caller's namespaces and only when something needs it,\n // so a document of ordinary paints carries no trace of it. The paint pre-pass\n // above has already seen every paint, so this answer is final.\n if (registry.usesPrivateNamespace() && namespaces[WEASEL_NS_PREFIX] == null) {\n rootAttrs.push(`xmlns:${WEASEL_NS_PREFIX}=\"${WEASEL_NS}\"`);\n }\n for (const [prefix, uri] of Object.entries(namespaces)) {\n rootAttrs.push(`xmlns:${prefix}=\"${escapeAttr(uri)}\"`);\n }\n rootAttrs.push(`viewBox=\"${vb}\"`);\n if (opts.width != null) rootAttrs.push(`width=\"${trimNumber(opts.width)}\"`);\n if (opts.height != null) rootAttrs.push(`height=\"${trimNumber(opts.height)}\"`);\n // documentMeta attrs onto the root, in declared-namespace order.\n if (opts.documentMeta) {\n for (const prefix of Object.keys(namespaces)) {\n const bucket = opts.documentMeta[prefix];\n if (!bucket?.attrs) continue;\n for (const [name, value] of Object.entries(bucket.attrs)) {\n rootAttrs.push(`${prefix}:${name}=\"${escapeAttr(value)}\"`);\n }\n }\n }\n\n // documentMeta elements after <defs>, before geometry body.\n let docMetaXml = '';\n if (opts.documentMeta) {\n for (const prefix of Object.keys(namespaces)) {\n const bucket = opts.documentMeta[prefix];\n if (!bucket?.elements) continue;\n for (const [localName, list] of Object.entries(bucket.elements)) {\n for (const el of list) docMetaXml += namespacedElementXml(prefix, localName, el);\n }\n }\n }\n\n const defsXml = registry.toDefsXml(opts.onWarn);\n // Once per message: a hundred inner-aligned strokes are one fact.\n const said = new Set<string>();\n const warn: Warn = (m) => {\n if (!opts.onWarn || said.has(m)) return;\n said.add(m);\n opts.onWarn(m);\n };\n const bodyXml = nodes.map((n) => nodeXml(n, registry, namespaces, warn)).join('');\n\n // `<title>` goes immediately inside `<svg>` per SVG-spec convention; it's\n // an accessibility hook and (for our purposes) a stable place to round-trip\n // the user-visible document title.\n const titleXml = opts.title && opts.title.length > 0\n ? `<title>${escapeText(opts.title)}</title>`\n : '';\n\n return `<svg ${rootAttrs.join(' ')}>${titleXml}${defsXml}${docMetaXml}${bodyXml}</svg>`;\n}\n\nfunction namespacedElementXml(prefix: string, localName: string, el: NamespacedElement): string {\n const attrs: string[] = [];\n for (const [name, value] of Object.entries(el.attrs)) {\n attrs.push(`${name}=\"${escapeAttr(value)}\"`);\n }\n const head = attrs.length > 0 ? `<${prefix}:${localName} ${attrs.join(' ')}>` : `<${prefix}:${localName}>`;\n let body = '';\n if (el.children) {\n for (const [childName, list] of Object.entries(el.children)) {\n for (const child of list) body += namespacedElementXml(prefix, childName, child);\n }\n } else if (el.text != null) {\n body = escapeText(el.text);\n }\n return `${head}${body}</${prefix}:${localName}>`;\n}\n\nfunction metaAttrsXml(meta: NamespaceMeta | undefined, namespaces: Record<string, string>): string {\n if (!meta) return '';\n const parts: string[] = [];\n for (const prefix of Object.keys(namespaces)) {\n const bucket = meta[prefix];\n if (!bucket?.attrs) continue;\n for (const [name, value] of Object.entries(bucket.attrs)) {\n parts.push(`${prefix}:${name}=\"${escapeAttr(value)}\"`);\n }\n }\n return parts.length > 0 ? ` ${parts.join(' ')}` : '';\n}\n\nfunction metaElementsXml(meta: NamespaceMeta | undefined, namespaces: Record<string, string>): string {\n if (!meta) return '';\n let out = '';\n for (const prefix of Object.keys(namespaces)) {\n const bucket = meta[prefix];\n if (!bucket?.elements) continue;\n for (const [localName, list] of Object.entries(bucket.elements)) {\n for (const el of list) out += namespacedElementXml(prefix, localName, el);\n }\n }\n return out;\n}\n\nfunction registerPaintServers(nodes: SvgNode[], registry: PaintServerRegistry): void {\n for (const n of nodes) {\n if (n.kind === 'group') {\n if (n.clip) registry.clipId(n.clip);\n registerPaintServers(n.children, registry);\n } else if (n.kind === 'path') {\n if (n.fill.kind === 'gradient') registry.register(n.fill.paint);\n if (n.stroke && n.stroke.paint.kind === 'gradient') registry.register(n.stroke.paint.paint);\n registerMarkers(n.stroke, registry);\n } else if (n.kind === 'text') {\n // Text paints flow through `style` / `runs` rather than a top-level\n // SvgPaint, so register direct FillStyle references when present. This\n // pre-pass is load-bearing: `<defs>` is emitted before the body, so a\n // paint first seen while writing an element would be referenced by an\n // id that no definition backs.\n registerTextPaint(n.fill, registry);\n registerTextPaint(n.stroke?.paint, registry);\n registerMarkers(n.stroke, registry);\n for (const run of n.runs ?? []) {\n registerTextPaint(run.fill, registry);\n registerTextPaint(run.stroke?.paint, registry);\n }\n }\n }\n}\n\n/** Register one text paint if it is a paint server rather than a colour. */\nfunction registerTextPaint(\n paint: import('@weasel-js/core').FillStyle | null | undefined,\n registry: PaintServerRegistry,\n): void {\n if (paint && !('color' in paint)) registry.register(paint);\n}\n\n/** Mint a `<defs>` id for every marker a stroke names, before the body is\n * written — same reason as the paint pre-pass above. */\nfunction registerMarkers(stroke: Pick<Stroke, 'markerStart' | 'markerMid' | 'markerEnd'> | undefined, registry: PaintServerRegistry): void {\n if (!stroke) return;\n for (const ref of [stroke.markerStart, stroke.markerMid, stroke.markerEnd]) {\n if (ref !== undefined) registry.markerId(ref);\n }\n}\n\ntype Warn = (message: string) => void;\n\nfunction nodeXml(\n node: SvgNode, registry: PaintServerRegistry, namespaces: Record<string, string>, warn: Warn,\n): string {\n if (node.kind === 'group') return groupXml(node, registry, namespaces, warn);\n if (node.kind === 'text') return textXml(node, registry, namespaces, warn);\n if (node.kind === 'image') return imageXml(node, namespaces);\n return pathXml(node, registry, namespaces, warn);\n}\n\n/** SVG 1.1 has no stroke alignment; SVG 2's `stroke-alignment` never shipped\n * in a browser. */\nfunction warnStrokeAlign(align: StrokeAlign | undefined, warn: Warn): void {\n if (align && align !== 'center') {\n warn(`a stroke aligned \"${align}\" of its edge is written centered: SVG has no stroke alignment`);\n }\n}\n\n/**\n * Emit an `<image>`. `preserveAspectRatio=\"none\"` is unconditional: the node\n * carries a literal box and nothing else, so letting a viewer letterbox it\n * would place the pixels somewhere the model never said.\n *\n * A source rect or a flip takes the cropped form described on `SvgImageNode`.\n * The nested `<svg>` cannot carry the rotation itself — SVG 1.1 gives it no\n * `transform` — so the rotation, opacity and meta go on the wrapping `<g>`.\n */\nfunction imageXml(node: SvgImageNode, namespaces: Record<string, string>): string {\n const box = `x=\"${trimNumber(node.x)}\" y=\"${trimNumber(node.y)}\"`\n + ` width=\"${trimNumber(node.width)}\" height=\"${trimNumber(node.height)}\"`;\n const outer: string[] = [];\n if (node.opacity != null && node.opacity !== 1) {\n outer.push(`opacity=\"${trimNumber(node.opacity)}\"`);\n }\n if (node.rotation != null && node.rotation !== 0) {\n const cx = node.x + node.width / 2;\n const cy = node.y + node.height / 2;\n const deg = (node.rotation * 180) / Math.PI;\n outer.push(`transform=\"rotate(${trimNumber(deg)} ${trimNumber(cx)} ${trimNumber(cy)})\"`);\n }\n const metaAttrs = metaAttrsXml(node.meta, namespaces);\n const metaEls = metaElementsXml(node.meta, namespaces);\n const href = `href=\"${escapeAttr(node.href)}\"`;\n\n if (!node.source && !node.flipX && !node.flipY) {\n const attrs = [href, box, 'preserveAspectRatio=\"none\"', ...outer].join(' ');\n if (metaEls) return `<image ${attrs}${metaAttrs}>${metaEls}</image>`;\n return `<image ${attrs}${metaAttrs}/>`;\n }\n\n const src = node.source ?? { x: 0, y: 0, width: 1, height: 1 };\n const viewBox = [src.x, src.y, src.width, src.height].map(trimNumber).join(' ');\n // A mirror about the source window's center, so the flipped image still\n // fills exactly the window the viewport shows.\n const flip = node.flipX || node.flipY\n ? ` transform=\"matrix(${node.flipX ? -1 : 1} 0 0 ${node.flipY ? -1 : 1}`\n + ` ${trimNumber(node.flipX ? 2 * src.x + src.width : 0)}`\n + ` ${trimNumber(node.flipY ? 2 * src.y + src.height : 0)})\"`\n : '';\n const head = ['<g data-weasel-image=\"true\"', ...outer].join(' ');\n return `${head}${metaAttrs}>`\n + `<svg ${box} viewBox=\"${viewBox}\" preserveAspectRatio=\"none\">`\n + `<image ${href} x=\"0\" y=\"0\" width=\"1\" height=\"1\" preserveAspectRatio=\"none\"${flip}/>`\n + `</svg>${metaEls}</g>`;\n}\n\nfunction groupXml(\n node: SvgGroupNode, registry: PaintServerRegistry, namespaces: Record<string, string>, warn: Warn,\n): string {\n const attrs: string[] = [];\n if (node.transform) {\n const m = formatMatrix(node.transform);\n if (m) attrs.push(`transform=\"${m}\"`);\n }\n if (node.clip) {\n attrs.push(`clip-path=\"url(#${registry.clipId(node.clip)})\"`);\n }\n if (node.opacity != null && node.opacity !== 1) {\n attrs.push(`opacity=\"${trimNumber(node.opacity)}\"`);\n }\n const metaAttrs = metaAttrsXml(node.meta, namespaces);\n // `metaAttrs` already starts with a leading space (or is empty), so we\n // can splice it after the existing attr list without extra logic.\n const head = attrs.length > 0\n ? `<g ${attrs.join(' ')}${metaAttrs}>`\n : `<g${metaAttrs}>`;\n const body = node.children.map((c) => nodeXml(c, registry, namespaces, warn)).join('');\n return `${head}${body}${metaElementsXml(node.meta, namespaces)}</g>`;\n}\n\nfunction pathXml(\n node: SvgPathNode, registry: PaintServerRegistry, namespaces: Record<string, string>, warn: Warn,\n): string {\n const attrs: string[] = [`d=\"${serializePathD(node.path)}\"`];\n const fillAttrs = paintAttrs(node.fill, 'fill', registry);\n for (const a of fillAttrs) attrs.push(a);\n // Emit fill-rule only when it diverges from SVG's default ('nonzero').\n // RectPath has no fillRule field — only PolygonPath carries one.\n if (node.path.kind === 'polygon' && node.path.fillRule === 'evenodd') {\n attrs.push(`fill-rule=\"evenodd\"`);\n }\n if (node.stroke) {\n const strokeAttrs = strokeAttrsFor(node.stroke, registry, warn);\n for (const a of strokeAttrs) attrs.push(a);\n } else {\n attrs.push('stroke=\"none\"');\n }\n if (node.opacity != null && node.opacity !== 1) {\n attrs.push(`opacity=\"${trimNumber(node.opacity)}\"`);\n }\n if (node.rotation != null && node.rotation !== 0) {\n const b = pathBounds(node.path);\n const cx = b.minX + (b.maxX - b.minX) / 2;\n const cy = b.minY + (b.maxY - b.minY) / 2;\n const deg = (node.rotation * 180) / Math.PI;\n attrs.push(`transform=\"rotate(${trimNumber(deg)} ${trimNumber(cx)} ${trimNumber(cy)})\"`);\n }\n const metaAttrs = metaAttrsXml(node.meta, namespaces);\n const metaEls = metaElementsXml(node.meta, namespaces);\n if (metaEls) {\n return `<path ${attrs.join(' ')}${metaAttrs}>${metaEls}</path>`;\n }\n return `<path ${attrs.join(' ')}${metaAttrs}/>`;\n}\n\nfunction paintAttrs(\n paint: SvgPaint,\n name: 'fill' | 'stroke',\n registry: PaintServerRegistry,\n includeOpacity = true,\n): string[] {\n if (paint.kind === 'none') return [`${name}=\"none\"`];\n const out = [`${name}=\"${paint.kind === 'solid' ? paint.color : registry.ref(paint.paint)}\"`];\n if (includeOpacity) out.push(...opacityAttr(`${name}-opacity`, svgPaintOpacity(paint)));\n return out;\n}\n\n/** The opacity an `SvgPaint` carries, whichever kind holds it. */\nfunction svgPaintOpacity(paint: SvgPaint): number | undefined {\n if (paint.kind === 'solid') return paint.opacity;\n return paint.kind === 'gradient' ? paint.paint.opacity : undefined;\n}\n\n/** `name=\"v\"`, or nothing when `v` is absent or fully opaque. */\nfunction opacityAttr(name: string, v: number | undefined): string[] {\n return v != null && v !== 1 ? [`${name}=\"${trimNumber(v)}\"`] : [];\n}\n\n/**\n * Attributes for a kit `Stroke` — the shape text carries, whose `paint` is a\n * `FillStyle` rather than an `SvgPaint`. Text strokes ride inside\n * `TextStyle` / `StyledRun` rather than as a node-level `SvgStroke`, because\n * that is where the kit's text model puts them.\n *\n * Absent, unpainted, or zero-width emits nothing at all: unstroked text should\n * not carry a `stroke` attribute, and SVG's own default (`none`) already says\n * so.\n */\n/**\n * `stroke-width`, plus `vector-effect` when the width is in screen pixels.\n *\n * A `{ px }` width means \"this thickness once rendered, whatever the view is\n * doing\", which is exactly what `non-scaling-stroke` says — so the number goes\n * out unresolved and the attribute carries the unit. There is no accumulated\n * transform scale here to resolve it against, and picking one would bake a\n * single zoom level into the document.\n */\nfunction strokeWidthAttrs(width: ScreenLength): string[] {\n if (typeof width === 'number') return [`stroke-width=\"${trimNumber(width)}\"`];\n return [`stroke-width=\"${trimNumber(width.px)}\"`, 'vector-effect=\"non-scaling-stroke\"'];\n}\n\nfunction coreStrokeAttrs(stroke: Stroke | undefined, registry: PaintServerRegistry, warn: Warn): string[] {\n const paint = stroke?.paint;\n if (!stroke || !paint) return [];\n const width = stroke.width ?? 1;\n if (!((typeof width === 'object' ? width.px : width) > 0)) return [];\n warnStrokeAlign(stroke.align, warn);\n const attrs: string[] = [`stroke=\"${'color' in paint ? paint.color : registry.ref(paint)}\"`];\n attrs.push(...opacityAttr('stroke-opacity', paint.opacity));\n attrs.push(...strokeWidthAttrs(width));\n if (stroke.cap) attrs.push(`stroke-linecap=\"${stroke.cap}\"`);\n if (stroke.join) attrs.push(`stroke-linejoin=\"${stroke.join}\"`);\n if (stroke.dash && stroke.dash.length > 0) {\n attrs.push(`stroke-dasharray=\"${stroke.dash.map(trimNumber).join(' ')}\"`);\n }\n if (stroke.miterLimit != null) attrs.push(`stroke-miterlimit=\"${trimNumber(stroke.miterLimit)}\"`);\n for (const [field, attr] of [\n ['markerStart', 'marker-start'],\n ['markerMid', 'marker-mid'],\n ['markerEnd', 'marker-end'],\n ] as const) {\n const ref = stroke[field];\n if (ref === undefined) continue;\n const id = registry.markerId(ref);\n if (id === undefined) continue;\n attrs.push(`${attr}=\"url(#${id})\"`);\n }\n return attrs;\n}\n\nfunction strokeAttrsFor(stroke: SvgStroke, registry: PaintServerRegistry, warn: Warn): string[] {\n warnStrokeAlign(stroke.align, warn);\n // `SvgStroke.opacity` and the paint's own `opacity` are two models of one\n // SVG attribute, and parse fills in both. Emitting each would write\n // `stroke-opacity` twice, which is not well-formed XML at all.\n const attrs = paintAttrs(stroke.paint, 'stroke', registry, false);\n attrs.push(...strokeWidthAttrs(stroke.width));\n attrs.push(...opacityAttr('stroke-opacity', stroke.opacity ?? svgPaintOpacity(stroke.paint)));\n if (stroke.cap) {\n attrs.push(`stroke-linecap=\"${stroke.cap}\"`);\n }\n if (stroke.join) {\n attrs.push(`stroke-linejoin=\"${stroke.join}\"`);\n }\n if (stroke.dash && stroke.dash.length > 0) {\n attrs.push(`stroke-dasharray=\"${stroke.dash.map(trimNumber).join(' ')}\"`);\n }\n if (stroke.miterLimit != null) {\n attrs.push(`stroke-miterlimit=\"${trimNumber(stroke.miterLimit)}\"`);\n }\n for (const [field, attr] of [\n ['markerStart', 'marker-start'],\n ['markerMid', 'marker-mid'],\n ['markerEnd', 'marker-end'],\n ] as const) {\n const ref = stroke[field];\n if (ref === undefined) continue;\n const id = registry.markerId(ref);\n if (id === undefined) continue;\n attrs.push(`${attr}=\"url(#${id})\"`);\n }\n return attrs;\n}\n\n/**\n * Tight bounding box around everything the tree draws, in the root's\n * coordinates — the fallback `viewBox` when the caller supplies none. A\n * node's `rotation` and a group's `transform` both move ink, so both are\n * applied here; a box taken from unrotated geometry crops the document.\n */\nfunction computeBounds(nodes: SvgNode[]): { x: number; y: number; width: number; height: number } {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n const visit = (n: SvgNode, ctm: Matrix): void => {\n if (n.kind === 'group') {\n const childCtm = n.transform ? multiply(ctm, n.transform) : ctm;\n n.children.forEach((c) => visit(c, childCtm));\n return;\n }\n const b = n.kind === 'text' || n.kind === 'image'\n ? { minX: n.x, minY: n.y, maxX: n.x + n.width, maxY: n.y + n.height }\n : pathBounds(n.path);\n const local = n.rotation ? rotateAboutCenter(ctm, b, n.rotation) : ctm;\n for (const [x, y] of corners(b)) {\n const px = local[0] * x + local[2] * y + local[4];\n const py = local[1] * x + local[3] * y + local[5];\n if (px < minX) minX = px;\n if (py < minY) minY = py;\n if (px > maxX) maxX = px;\n if (py > maxY) maxY = py;\n }\n };\n nodes.forEach((n) => visit(n, IDENTITY_MATRIX));\n if (!Number.isFinite(minX)) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\nfunction corners(b: { minX: number; minY: number; maxX: number; maxY: number }): [number, number][] {\n return [[b.minX, b.minY], [b.maxX, b.minY], [b.maxX, b.maxY], [b.minX, b.maxY]];\n}\n\n/** `ctm` composed with the same `rotate(angle cx cy)` the element emits. */\nfunction rotateAboutCenter(\n ctm: Matrix,\n b: { minX: number; minY: number; maxX: number; maxY: number },\n angle: number,\n): Matrix {\n const cx = (b.minX + b.maxX) / 2;\n const cy = (b.minY + b.maxY) / 2;\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n return multiply(ctm, [c, s, -s, c, cx - cx * c + cy * s, cy - cx * s - cy * c]);\n}\n\n/**\n * Emit a `<text>` element. `x` is the `text-anchor` point, per the SVG spec:\n * the box's left edge, center or right edge as its alignment resolves. Uses\n * `dominant-baseline=\"text-before-edge\"` so `y` matches weasel's top-of-box\n * pose; stashes the explicit width/height (which native SVG text doesn't\n * model) in `data-weasel-*` attributes so they round-trip through the parser\n * losslessly.\n */\nfunction textXml(\n node: SvgTextNode, registry: PaintServerRegistry, namespaces: Record<string, string>, warn: Warn,\n): string {\n const attrs: string[] = [\n `x=\"${trimNumber(node.x + anchorOffset(node.style, node.width))}\"`,\n `y=\"${trimNumber(node.y)}\"`,\n `dominant-baseline=\"text-before-edge\"`,\n // The runs model stores real line breaks; SVG's default whitespace\n // handling would collapse them (and any indentation) away on re-import.\n `xml:space=\"preserve\"`,\n `data-weasel-width=\"${trimNumber(node.width)}\"`,\n `data-weasel-height=\"${trimNumber(node.height)}\"`,\n ];\n\n const style = node.style;\n // SVG user space has no camera, so a `{ px }` size writes as that many\n // user units — the reading it already has at scale 1.\n if (style?.fontSize != null) attrs.push(`font-size=\"${trimNumber(resolveScreenLength(style.fontSize, 1))}\"`);\n if (style?.fontFamily) attrs.push(`font-family=\"${escapeAttr(style.fontFamily)}\"`);\n if (style?.fontWeight != null) attrs.push(`font-weight=\"${String(style.fontWeight)}\"`);\n if (style?.fontStyle && style.fontStyle !== 'normal') attrs.push(`font-style=\"${style.fontStyle}\"`);\n const direction = style?.direction ?? 'ltr';\n if (direction === 'rtl') attrs.push('direction=\"rtl\"');\n if (style?.align != null || direction === 'rtl') {\n // `text-anchor` is reading-order relative in SVG exactly as `start` / `end`\n // are here, so the two relative values pass straight through and only the\n // absolute pair has to be turned into an edge the reader resolves the same\n // way. Under `ltr` this collapses to what it always wrote.\n const align = style?.align ?? 'left';\n const anchor = align === 'center' ? 'middle'\n : align === 'start' ? 'start'\n : align === 'end' ? 'end'\n : (align === 'left') === (direction === 'ltr') ? 'start' : 'end';\n if (anchor !== 'start') attrs.push(`text-anchor=\"${anchor}\"`);\n }\n if (style?.letterSpacing != null && style.letterSpacing !== 0) {\n attrs.push(`letter-spacing=\"${trimNumber(resolveScreenLength(style.letterSpacing, 1))}\"`);\n }\n const decoration = textDecorationValue(style?.underline, style?.strikethrough, style?.overline);\n if (decoration) attrs.push(`text-decoration=\"${decoration}\"`);\n if (style?.script) attrs.push(`baseline-shift=\"${style.script}\"`);\n // A CSS property rather than an SVG 1.1 presentation attribute, so it goes\n // where every CSS-aware reader looks for it.\n if (style?.textTransform && style.textTransform !== 'none') {\n attrs.push(`style=\"text-transform:${style.textTransform}\"`);\n }\n // SVG text never wraps, so this is for weasel's own reader, beside the box\n // width it wraps at.\n if (style?.wrap) {\n attrs.push('data-weasel-wrap=\"true\"');\n warn('text that wraps at its box width is written unwrapped: SVG text does not wrap, so other'\n + ' readers draw one line per hard break (weasel reads the wrap back)');\n }\n if (node.verticalAlign && node.verticalAlign !== 'top') {\n attrs.push(`data-weasel-vertical-align=\"${node.verticalAlign}\"`);\n warn(`text aligned to the ${node.verticalAlign} of its box is written top-aligned: SVG text has`\n + ' no box, so other readers draw it at the top (weasel reads the alignment back)');\n }\n // Note: `lineHeight` is NOT emitted here. The bridge layer (svgInterop)\n // lifts it into `meta.wd.attrs['line-height']`, which `metaAttrsXml`\n // below emits as `wd:line-height=\"...\"`. There is no compat write of\n // `data-weasel-line-height` — per the SVG-native plan's Migration section,\n // no installed base exists to compat against.\n if (node.fill === null) {\n attrs.push('fill=\"none\"');\n } else if (node.fill) {\n attrs.push(`fill=\"${'color' in node.fill ? node.fill.color : registry.ref(node.fill)}\"`);\n attrs.push(...opacityAttr('fill-opacity', node.fill.opacity));\n }\n for (const a of coreStrokeAttrs(node.stroke, registry, warn)) attrs.push(a);\n if (node.opacity != null && node.opacity !== 1) {\n attrs.push(`opacity=\"${trimNumber(node.opacity)}\"`);\n }\n if (node.rotation != null && node.rotation !== 0) {\n const cx = node.x + node.width / 2;\n const cy = node.y + node.height / 2;\n const deg = (node.rotation * 180) / Math.PI;\n attrs.push(`transform=\"rotate(${trimNumber(deg)} ${trimNumber(cx)} ${trimNumber(cy)})\"`);\n }\n\n const body = node.runs && node.runs.length > 0\n ? node.runs.map((r) => runXml(r, registry, warn)).join('')\n : escapeText(node.text);\n const metaAttrs = metaAttrsXml(node.meta, namespaces);\n const metaEls = metaElementsXml(node.meta, namespaces);\n return `<text ${attrs.join(' ')}${metaAttrs}>${body}${metaEls}</text>`;\n}\n\nfunction runXml(run: import('@weasel-js/core').StyledRun, registry: PaintServerRegistry, warn: Warn): string {\n const attrs: string[] = [];\n if (run.bold) attrs.push(`font-weight=\"700\"`);\n if (run.italic) attrs.push(`font-style=\"italic\"`);\n if (run.fontFamily) attrs.push(`font-family=\"${escapeAttr(run.fontFamily)}\"`);\n // A percentage `font-size` is relative to the parent's, which is what\n // `fontScale` means; an absolute `fontSize` wins over it here as it does in\n // the runs model.\n //\n // `baseline-shift=\"super\"` carries the preset's *size* as well as its rise,\n // so a run that overrode only the rise has no keyword left to say the size\n // with and must spell it out — without this the superscript comes back\n // full-size at a raised baseline.\n const presetScale = run.script != null && run.baselineShift != null\n ? SCRIPT_METRICS[run.script].size\n : undefined;\n const scale = run.fontScale ?? presetScale;\n if (run.fontSize != null) attrs.push(`font-size=\"${trimNumber(resolveScreenLength(run.fontSize, 1))}\"`);\n else if (scale != null) attrs.push(`font-size=\"${trimNumber(scale * 100)}%\"`);\n // Same story for `baseline-shift`: an SVG percentage resolves against the\n // parent's font size, which is the unit `baselineShift` is already in.\n if (run.baselineShift != null) {\n attrs.push(`baseline-shift=\"${trimNumber(run.baselineShift * 100)}%\"`);\n } else if (run.script) {\n attrs.push(`baseline-shift=\"${run.script}\"`);\n }\n // Unlike the node-level style guard above, a run-level `0` is a meaningful\n // *override* (distinct from \"inherit the node's letterSpacing\") per the\n // runs model's additive-flags contract — emit it whenever it's set.\n if (run.letterSpacing != null) {\n attrs.push(`letter-spacing=\"${trimNumber(resolveScreenLength(run.letterSpacing, 1))}\"`);\n }\n const runDecoration = textDecorationValue(run.underline, run.strikethrough, run.overline);\n if (runDecoration) attrs.push(`text-decoration=\"${runDecoration}\"`);\n if (run.fill) {\n if ('color' in run.fill) {\n attrs.push(`fill=\"${run.fill.color}\"`);\n } else {\n attrs.push(`fill=\"${registry.ref(run.fill)}\"`);\n }\n }\n for (const a of coreStrokeAttrs(run.stroke, registry, warn)) attrs.push(a);\n // `none` included: on a run it overrides a transform the node would pass down.\n if (run.textTransform) attrs.push(`style=\"text-transform:${run.textTransform}\"`);\n const head = attrs.length > 0 ? `<tspan ${attrs.join(' ')}>` : '<tspan>';\n return `${head}${escapeText(run.text)}</tspan>`;\n}\n\n/**\n * Combine the decoration flags into an SVG `text-decoration` value —\n * `\"underline line-through\"` when both are set, a single token when only\n * one is, or `null` (omit the attribute) when none is set.\n */\nfunction textDecorationValue(\n underline: boolean | undefined,\n strikethrough: boolean | undefined,\n overline: boolean | undefined,\n): string | null {\n const tokens: string[] = [];\n if (underline) tokens.push('underline');\n if (strikethrough) tokens.push('line-through');\n if (overline) tokens.push('overline');\n return tokens.length > 0 ? tokens.join(' ') : null;\n}\n\nfunction escapeAttr(s: string): string {\n return s.replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<');\n}\n\nfunction escapeText(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction pathBounds(path: Path): { minX: number; minY: number; maxX: number; maxY: number } {\n if (path.kind === 'rect') {\n return {\n minX: path.x, minY: path.y,\n maxX: path.x + path.width, maxY: path.y + path.height,\n };\n }\n const b = boundsOfPath(path);\n return { minX: b.x, minY: b.y, maxX: b.x + b.width, maxY: b.y + b.height };\n}\n\n"]}
|