@weasel-js/diagram-formats 0.0.0-stage → 1.11.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 orochi235
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,238 @@
1
- # Temporary Holding Version
1
+ # @weasel-js/diagram-formats
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Turns `@weasel-js/diagram` scenes into files and files into scenes. Every
4
+ format reads and writes one interchange document, built on the diagram
5
+ package's `DiagramData`. One page at a time exports as an SVG document or a
6
+ PNG image, and every page together as one PDF, each showing the page as the
7
+ canvas draws it.
8
+
9
+ Part of [weasel](https://github.com/orochi235/weasel), a domain-agnostic 2D
10
+ scene-graph canvas kit for React. See the
11
+ [API reference](https://orochi235.github.io/weasel/#pkg/diagram-formats).
12
+
13
+ ```sh
14
+ npm install @weasel-js/diagram-formats
15
+ ```
16
+
17
+ ## The interchange document
18
+
19
+ A `DiagramDocument` is a diagram's pages and its theme. Each page has an id,
20
+ an optional name, a sheet size, and a `DiagramData` whose places, boxes,
21
+ waypoints, and label points run from the page's top-left corner. Ids share one
22
+ namespace across the document. Edges whose ends are on different pages sit in
23
+ `crossPageEdges`, with no waypoints, since they draw as two stubs and their
24
+ off-page tags.
25
+
26
+ ```ts
27
+ import { documentFromScene, documentSpecs } from '@weasel-js/diagram-formats';
28
+
29
+ const doc = documentFromScene(scene);
30
+ const { specs, doc: values } = documentSpecs(doc, { layer: 'shapes', measure });
31
+ // values holds `core:pages` and `diagram:theme`; replace the scene's nodes with specs.
32
+ ```
33
+
34
+ `documentFromScene(scene, { theme })` puts each shape, container, pool, and
35
+ group on the page its outermost container overlaps most, or the first page
36
+ when it overlaps none; a scene with no pages gets one page around everything.
37
+ It keeps the colors the scene's theme would not give: those the author set by
38
+ hand (the trait's `ownStyle`) and any that differ from the theme, as `colors`.
39
+ A route or a port that layout chose, and an avoiding connector's computed
40
+ route, are read as `routed` and `routedPorts`, not as waypoints, so they stay
41
+ layout's. `theme` is what colors are compared against when the scene names
42
+ none.
43
+
44
+ `documentSpecs(doc, { layer, theme, measure })` is the way back. Pages are
45
+ placed with core's `layoutPages`, as `core:pages` places them. A page where a
46
+ node has no `at`, or a pool has no box, is laid out first with `layered`,
47
+ running the way its `direction` says, with whatever it places pinned; the
48
+ result is kept as places and routes, a page that placed nothing is moved to sit
49
+ 40 inside its corner, and the page grows to hold it. Then one `diagramScene`
50
+ call with no layout draws every page and the edges between them, so no layout
51
+ runs again after an import.
52
+
53
+ ## Formats
54
+
55
+ A `DiagramFormat` has an `id`, a `name`, its `extensions`, and `detect(text)`,
56
+ which judges by content alone. `read(text)` returns the document and the
57
+ warnings, one sentence each, for what the file had that a diagram cannot hold;
58
+ `write(doc, { page })` returns the text and the warnings for what the format
59
+ cannot carry. A format with `onePage` writes the page `page` names, else the
60
+ first (`writtenPage`).
61
+
62
+ `DIAGRAM_FORMATS` lists them. `detectFormat(text, fileName)` takes, of the
63
+ formats whose `detect` passes, the first claiming the file's extension, else the
64
+ first; an extension alone never picks one. `readDocument(text, fileName)` reads
65
+ with it and rejects on a file nothing reads.
66
+
67
+ | Format | Extensions | Reads | Writes |
68
+ | --- | --- | --- | --- |
69
+ | `DIAGRAM_JSON`, the document as JSON | `.diagram.json` | yes | the whole document |
70
+ | `DRAW_XML`, draw-style XML | `.xml` | yes, plain or compressed | every page, uncompressed |
71
+ | `DIAGRAM_MERMAID`, a Mermaid flowchart | `.mmd`, `.mermaid` | yes | one page |
72
+ | `DIAGRAM_DOT`, a Graphviz DOT graph | `.dot`, `.gv` | yes | one page |
73
+
74
+ Not read, by decision (2026-10-20): packaged office-suite drawing formats,
75
+ which are zip archives of many XML parts built on master shapes a scene has no
76
+ equivalent for; and SVG, which carries drawn paths rather than shapes and
77
+ connectors, so a connector would arrive as a path that follows nothing.
78
+
79
+ ### Draw-style XML
80
+
81
+ The format that keeps a chart laid out. A file is an `<mxfile>` holding a
82
+ `<diagram name=…>` per page, each a graph model of cells; a bare
83
+ `<mxGraphModel>` reads as one page. A cell has a `key=value;` style string and
84
+ a geometry measured from the corner of the cell holding it. A compressed page
85
+ is base64 of raw deflate of the URI-encoded model, so `read` answers a promise.
86
+ The file is known by its root element, not its `.xml` extension.
87
+
88
+ | Diagram | Draw-style XML |
89
+ | --- | --- |
90
+ | Outline | `rhombus` diamond, `ellipse`, `hexagon`, `parallelogram`, `trapezoid`; `rounded=1` with `arcSize` 50 or more is a stadium; any other shape reads as a rect, with a warning |
91
+ | Colors and font | `fillColor` (`none` is transparent), `strokeColor`, `fontColor`, `strokeWidth`, `dashed`; `fontSize`, `fontFamily`, and bold in `fontStyle` as label rows' style |
92
+ | Text | `value`; with `html=1`, tags stripped and `<br>` and blocks kept as line breaks. Written plain. |
93
+ | Router | `edgeStyle=orthogonalEdgeStyle` orthogonal, `curved=1` bezier, else straight; `avoid` writes as orthogonal along its route |
94
+ | Route | the edge geometry's points: `waypoints`, else `routed`, read back as `waypoints` |
95
+ | Ports | `exitX`/`exitY` and `entryX`/`entryY`, read as the nearest compass port |
96
+ | Edge label | the edge's `value`, or a label cell on it; its geometry `x` (-1 to 1) is where along, `y` how far off the line |
97
+ | Arrowheads | `startArrow`/`endArrow` and their `Fill` |
98
+ | Container, pool, lane | `container=1` or a `swimlane` is a container; a swimlane whose swimlanes span its body is a pool of lanes, stacked in rows with `horizontal=0` |
99
+ | Group | a `group` cell around its members |
100
+ | Page | one `<diagram>` each, `pageWidth` and `pageHeight` its size |
101
+
102
+ Reading leaves a color the style does not name unset, so the chart's theme
103
+ draws it. A page grows to hold what is on it, and what sits left of or above it
104
+ moves onto it. An id an earlier page used is prefixed with its page's id.
105
+ Layers merge into one, and edges with a loose end are left out, each with a
106
+ warning.
107
+
108
+ Writing spells out every color as the document's theme draws it, so the file
109
+ looks the same anywhere. A node is written the size it states, which is its
110
+ drawn size in a document read from a scene; a page with unplaced nodes is laid
111
+ out first, as an import would. Edges between pages are left out, with a
112
+ warning, since a page's cells cannot reach another's; so are marks, port rows,
113
+ and outline paths, which become rects.
114
+
115
+ ### Mermaid and Graphviz DOT
116
+
117
+ Both hold a graph's topology and text, not its places (DOT holds them when
118
+ every node has a `pos`), so a file reads into one page whose nodes have no
119
+ `at`, and `documentSpecs` lays it out the way the page's `direction` says.
120
+ Both readers are hand-written and throw an error naming the line on text they
121
+ cannot read.
122
+
123
+ | Diagram | Mermaid flowchart | Graphviz DOT |
124
+ | --- | --- | --- |
125
+ | rect | `A[text]` | `shape=box` |
126
+ | stadium | `A([text])`, and `A(text)` | `shape=box, style=rounded` |
127
+ | diamond | `A{text}` | `shape=diamond` |
128
+ | ellipse | `A((text))` | `shape=ellipse`, the default, and `circle` |
129
+ | hexagon | `A{{text}}` | `shape=hexagon` |
130
+ | parallelogram | `A[/text/]` | `shape=parallelogram` |
131
+ | trapezoid | `A[/text\]` | `shape=trapezium` |
132
+ | edge and label | `A -->\|text\| B`, `A -- text --> B` | `A -> B [label=…]` |
133
+ | no arrowhead, dashed, thick | `---`, `-.->`, `==>` | `dir`, `arrowhead`, `style=dashed`, `penwidth` |
134
+ | container | `subgraph` | `subgraph cluster_*` |
135
+ | page name | front matter `title` | the graph's `label`, else its name |
136
+ | page `direction` | `flowchart TD/LR/BT/RL` | `rankdir` |
137
+ | colors | `classDef`, `class`, `:::`, `style`, `linkStyle` | `fillcolor` with `style=filled`, `color`, `fontcolor` |
138
+ | ports | — | `node:compass`, `n`, `e`, `s`, and `w` only |
139
+
140
+ A Mermaid shape with no outline here reads as a rect, with a warning; a
141
+ Mermaid diagram of another kind is refused with an error naming the kind. DOT
142
+ reads its whole grammar: `strict`, `graph` and `digraph`, attribute
143
+ statements and their scoping, edge chains, and subgraphs as edge ends. Its
144
+ HTML labels read as their text, and the attributes it does not read are
145
+ listed in one warning. A cluster's container drops its `cluster_` prefix when
146
+ that id is free.
147
+
148
+ Writing, each writes the theme's colors once (Mermaid's `classDef default`,
149
+ DOT's `node` and `edge` defaults) and each item's own where they differ. DOT
150
+ writes every node's `pos`, `width`, and `height` when each has a place and a
151
+ size, so a DOT file read back keeps the layout. Pools, lanes, and groups are
152
+ written as nested clusters or subgraphs and read back as containers. Mermaid
153
+ ids that are keywords or not plain names are renamed, keeping their text.
154
+ Bends, connectors to other pages, drawn outlines, and ports a format lacks
155
+ are dropped with a warning.
156
+
157
+ ## Exporting a page
158
+
159
+ A page is a rect in world space; a `PlacedPage` from core's `placedPagesOf` is
160
+ one. Pages sit apart in one world, and a connector between two pages draws as
161
+ two stubs and their off-page tags, so cutting the scene to the page rect leaves
162
+ nothing from another page.
163
+
164
+ ```ts
165
+ import { placedPagesOf } from '@weasel-js/core';
166
+ import { exportPagePng, exportPageSvg, exportPagesPdf } from '@weasel-js/diagram-formats';
167
+
168
+ const pages = placedPagesOf(scene);
169
+ const svg = await exportPageSvg(scene, pages[0], { title: 'Page 1' });
170
+ const png = await exportPagePng(scene, pages[0], { scale: 2 });
171
+ const { blob, skipped } = await exportPagesPdf(scene, pages, { title: 'Chart' });
172
+ ```
173
+
174
+ None writes to the scene, so an export takes no undo entry. Each takes
175
+ `background`, the color painted under the page: by default the page color of
176
+ the scene's diagram theme (`diagram:theme`), and `null` for none.
177
+
178
+ ### SVG
179
+
180
+ `exportPageSvg` returns the document as a string. Its `viewBox` is the page
181
+ rect and its `width` and `height` the page's size. Only nodes whose box meets
182
+ the page are written, in paint order, on the scene's visible layers;
183
+ annotation layers are left out.
184
+
185
+ | In the scene | In the SVG |
186
+ | --- | --- |
187
+ | A shape's outline (`diagram.outline`) | A path of that outline in the shape's box, with its fill and stroke; a container's divider under its header as a second path. A container's members follow inside its group. |
188
+ | A connector, or any node that derives its path | One path along the route, with its stroke and its `marker-start` and `marker-end`. A path made of parts writes one path per part. |
189
+ | A drawn mark | Its unit-square path stretched over its box. |
190
+ | Rows, labels, text marks, and off-page tags | Text, laid out in the lines the canvas lays it into; a tag's background is a rect behind it. |
191
+ | Anything else | What `@weasel-js/svg`'s `svgLeafFromKit` writes for it. |
192
+
193
+ It waits for the paint kinds and font faces the document uses before
194
+ writing it. A load that fails goes to `onWarn`, and so does anything SVG cannot
195
+ say the way weasel draws it. `title` and `pretty` are passed on to
196
+ `serializeSvg`.
197
+
198
+ `pageSvgNodes(scene, page)` is the walk on its own: the `SvgNode`s, with no
199
+ background, for a caller assembling its own document.
200
+
201
+ ### PNG
202
+
203
+ `exportPagePng` draws the page with core's `renderSceneToPixels`, the renderer
204
+ the canvas uses, so its pixels are the canvas's. The image is the page's size
205
+ times `scale`, and the result is a `Blob` of type `image/png`. It needs WebGL2
206
+ and `OffscreenCanvas`.
207
+
208
+ Paint kinds and fonts that load on demand are waited for, but the painters are
209
+ the caller's to register, as they are to draw the scene at all:
210
+
211
+ ```ts
212
+ import { registerDiagramShape, registerMarkShape } from '@weasel-js/diagram';
213
+
214
+ registerDiagramShape();
215
+ registerMarkShape();
216
+ ```
217
+
218
+ ### PDF
219
+
220
+ `exportPagesPdf` writes each of `pages` as a page of one PDF, in the order
221
+ given, at 0.75 points per unit (96 units to the inch). It answers the `Blob`,
222
+ of type `application/pdf`, and `skipped`: what the PDF could not carry, each a
223
+ `{ kind, detail }` from `@weasel-js/pdf`. Annotation layers are left out.
224
+
225
+ Shapes and strokes are written as vectors and text as selectable text in its
226
+ embedded face, which needs the face's outlines registered from a TrueType file
227
+ (`registerFontOutlines` in `@weasel-js/font`). A face that cannot be embedded
228
+ is drawn as glyph outlines, so its text is not selectable; a glyph with no
229
+ outline at all is left out and listed in `skipped`.
230
+
231
+ Effects, custom shaders, and fills in a registered paint kind are drawn through
232
+ the renderer and placed as images, so the painters are the caller's to
233
+ register, as for the PNG, and this needs WebGL2 and `OffscreenCanvas`.
234
+
235
+ ## Scenes it reads
236
+
237
+ Poses are read as world-space `RectPose`s, which is what a diagram scene
238
+ holds. A scene that composes child poses into a parent's frame is not one.
@@ -0,0 +1,246 @@
1
+ import { DiagramData, LayoutDirection, DataEdge, DiagramTheme, DiagramSpec, MeasureRowText } from '@weasel-js/diagram';
2
+ import { Scene, SerializedDoc, RectPose } from '@weasel-js/core';
3
+ import { SvgNode, SerializeOptions } from '@weasel-js/svg';
4
+ import { PdfSkip } from '@weasel-js/pdf';
5
+
6
+ /**
7
+ * The interchange document every format reads and writes: a diagram's pages,
8
+ * each holding a `DiagramData`, and the theme it is drawn in. Only
9
+ * `documentFromScene` and `documentSpecs` know scenes, so a codec is written
10
+ * once for a chart and for a data-backed host alike.
11
+ */
12
+
13
+ /**
14
+ * One page: its sheet size, and what is on it in coordinates from the page's
15
+ * top-left corner. Ids share one namespace across the whole document.
16
+ */
17
+ interface DocumentPage {
18
+ id: string;
19
+ name?: string;
20
+ width: number;
21
+ height: number;
22
+ data: DiagramData;
23
+ /** The way layout runs when the page is laid out on import, which it is when a node has no `at`. */
24
+ direction?: LayoutDirection;
25
+ }
26
+ /** A diagram as every format reads and writes it. */
27
+ interface DiagramDocument {
28
+ pages: readonly DocumentPage[];
29
+ /**
30
+ * Edges the scene splits off-page, and edges whose ends export to different pages: their ends, ports, router,
31
+ * label, and colors. One the scene splits off-page carries no waypoints,
32
+ * since it draws as two stubs ending at off-page tags; one it keeps whole
33
+ * (an end in the gap between pages) keeps them, in world coordinates.
34
+ */
35
+ crossPageEdges?: readonly DataEdge[];
36
+ /** A shipped theme's id, or a whole theme. Unset, the host's own. */
37
+ theme?: string | DiagramTheme;
38
+ }
39
+ /** What a format read, and what it could not carry into a diagram, one sentence each. */
40
+ interface ImportResult {
41
+ document: DiagramDocument;
42
+ warnings: readonly string[];
43
+ }
44
+ /** What a format wrote, and what it could not carry out of the diagram, one sentence each. */
45
+ interface ExportResult {
46
+ text: string;
47
+ warnings: readonly string[];
48
+ }
49
+ /** Options for {@link DiagramFormat.write}. */
50
+ interface WriteOptions {
51
+ /** The page a format with no pages writes. Default the first. */
52
+ page?: string;
53
+ }
54
+ /** A file format a diagram can be read from or written to. */
55
+ interface DiagramFormat {
56
+ id: string;
57
+ /** What a menu calls it. */
58
+ name: string;
59
+ /** With their dots, most usual first: `['.dot', '.gv']`. */
60
+ extensions: readonly string[];
61
+ /** Whether `text` looks like this format, from its content alone. */
62
+ detect(text: string): boolean;
63
+ /** Throws on text this format cannot read. */
64
+ read?(text: string): ImportResult | Promise<ImportResult>;
65
+ write?(doc: DiagramDocument, opts?: WriteOptions): ExportResult;
66
+ /** Whether {@link write} writes one page rather than the whole document. */
67
+ onePage?: boolean;
68
+ }
69
+ /** The page a one-page format writes: the one `opts.page` names, else the first. `null` for a document with none. */
70
+ declare function writtenPage(doc: DiagramDocument, opts?: WriteOptions): DocumentPage | null;
71
+
72
+ /** The formats a diagram reads from and writes to, and how a file finds its format. */
73
+
74
+ /** Every format this package reads or writes. */
75
+ declare const DIAGRAM_FORMATS: readonly DiagramFormat[];
76
+ /**
77
+ * The format `text` is in: among those whose content test passes, the first
78
+ * that claims `fileName`'s extension, else the first. `null` when none
79
+ * passes, whatever the extension says, since an extension such as `.xml` names
80
+ * many formats.
81
+ */
82
+ declare function detectFormat(text: string, fileName?: string, formats?: readonly DiagramFormat[]): DiagramFormat | null;
83
+ /** Reads `text` with the format {@link detectFormat} picks. Rejects when none reads it. */
84
+ declare function readDocument(text: string, fileName?: string, formats?: readonly DiagramFormat[]): Promise<ImportResult>;
85
+
86
+ /** The native format: a {@link DiagramDocument} written out as JSON, which carries everything the model holds. */
87
+
88
+ /** A diagram document as JSON, every page in one file, recognized by its `format` field. */
89
+ declare const DIAGRAM_JSON: DiagramFormat;
90
+
91
+ /** Draw-style XML as a {@link DiagramFormat}. */
92
+
93
+ /**
94
+ * Draw-style XML: a page per `<diagram>`, each a graph model of cells with
95
+ * geometry, written out or compressed. Recognized by its root element, since
96
+ * `.xml` names many formats.
97
+ */
98
+ declare const DRAW_XML: DiagramFormat;
99
+
100
+ /** Mermaid as a {@link DiagramFormat}. */
101
+
102
+ /**
103
+ * A Mermaid flowchart, one page per file, laid out on import. Any Mermaid
104
+ * diagram is recognized, so reading another kind says which kind it is.
105
+ */
106
+ declare const DIAGRAM_MERMAID: DiagramFormat;
107
+
108
+ /** Graphviz DOT as a {@link DiagramFormat}. */
109
+
110
+ /** A Graphviz DOT graph, one page per file, laid out on import unless every node has a `pos`. */
111
+ declare const DIAGRAM_DOT: DiagramFormat;
112
+
113
+ /** A diagram scene as a {@link DiagramDocument}: what every format writes from. */
114
+
115
+ /** Options for {@link documentFromScene}. */
116
+ interface DocumentFromSceneOptions {
117
+ /** The theme colors are read against when the scene's `diagram:theme` names none. Default the night theme. */
118
+ theme?: DiagramTheme;
119
+ }
120
+ /**
121
+ * Reads a diagram scene into a document: one page per page in its `core:pages`
122
+ * (one page around everything when it has none), each holding the shapes,
123
+ * connectors, containers and pools, and groups on it, in coordinates from the
124
+ * page's corner. A shape belongs to the page its outermost container does, and
125
+ * that is the one its box overlaps most, or the nearest one when it overlaps
126
+ * none. A connector the scene splits off-page, or whose ends export to
127
+ * different pages, goes in `crossPageEdges`: without waypoints when split,
128
+ * with them in world coordinates when not. Colors are kept
129
+ * where the scene's theme would not give them: the author's own, and any a
130
+ * theme never set.
131
+ */
132
+ declare function documentFromScene<TData, TLayer extends string, TPose>(scene: Scene<TData, TLayer, TPose>, opts?: DocumentFromSceneOptions): DiagramDocument;
133
+
134
+ /** A {@link DiagramDocument} as scene specs and document values: what every import draws from. */
135
+
136
+ /** Options for {@link documentSpecs}. */
137
+ interface DocumentSpecsOptions<TLayer extends string = 'main'> {
138
+ /** The layer every spec goes on. Default `'main'`. */
139
+ layer?: TLayer;
140
+ /** The theme to draw in. Default the one the document names, else the night theme. */
141
+ theme?: DiagramTheme;
142
+ /** Measures text. Default an estimate from character count. */
143
+ measure?: MeasureRowText;
144
+ }
145
+ /** What {@link documentSpecs} returns: the nodes, and the `core:pages` and `diagram:theme` document values. */
146
+ interface DocumentScene<TLayer extends string = 'main'> {
147
+ specs: DiagramSpec<TLayer>[];
148
+ doc: SerializedDoc;
149
+ }
150
+ /**
151
+ * The scene a document draws as. Its pages are placed with core's
152
+ * `layoutPages`, as a scene's `core:pages` places them. A page whose nodes
153
+ * all have a place is drawn where they say; any other page is laid out first,
154
+ * with `layered`, its placed nodes pinned (and grows to hold the result). Then
155
+ * every page, moved to its place, and the edges between pages are drawn by one
156
+ * `diagramScene` call with no layout, so the scene holds places and routes and
157
+ * no layout runs again.
158
+ */
159
+ declare function documentSpecs<TLayer extends string = 'main'>(document: DiagramDocument, opts?: DocumentSpecsOptions<TLayer>): DocumentScene<TLayer>;
160
+
161
+ /**
162
+ * One page of a diagram scene as `SvgNode`s: the nodes whose box meets the
163
+ * page, each written the way the canvas paints it.
164
+ */
165
+
166
+ /** A page's rect in world space. A `PlacedPage` is one. */
167
+ interface PageRect {
168
+ readonly x: number;
169
+ readonly y: number;
170
+ readonly width: number;
171
+ readonly height: number;
172
+ }
173
+ /** A diagram scene as the exports read it: world-space `RectPose`s. */
174
+ type PageExportScene = Scene<unknown, string, RectPose>;
175
+ /**
176
+ * The `SvgNode`s of everything on `page`, in paint order: every node on a
177
+ * visible content layer whose box meets the page, with what is under it.
178
+ * Diagram outlines and drawn marks go through the diagram painters, a node
179
+ * that derives its path (a connector) is drawn along that path, and anything
180
+ * else is written by `svgLeafFromKit`.
181
+ */
182
+ declare function pageSvgNodes(scene: PageExportScene, page: PageRect): SvgNode[];
183
+
184
+ /** Options for {@link exportPageSvg}. */
185
+ interface ExportPageSvgOptions extends Pick<SerializeOptions, 'title' | 'onWarn' | 'pretty'> {
186
+ /** The color painted under the page. Default: the page color of the
187
+ * scene's diagram theme (`diagram:theme`). `null` paints none. */
188
+ background?: string | null;
189
+ }
190
+ /**
191
+ * Write `page` of `scene` as an SVG document: its `viewBox` is the page rect,
192
+ * its size the page's, the page color comes first, and the scene is drawn as
193
+ * the canvas draws it, cut to the page's edges. What lies wholly off the page
194
+ * is left out.
195
+ *
196
+ * It waits for the paint kinds and faces the document needs, so its text is
197
+ * written in the lines the canvas lays it out into. A load that fails goes to
198
+ * `onWarn`, and the export goes ahead without it.
199
+ */
200
+ declare function exportPageSvg(scene: PageExportScene, page: PageRect, opts?: ExportPageSvgOptions): Promise<string>;
201
+
202
+ /** Options for {@link exportPagePng}. */
203
+ interface ExportPagePngOptions {
204
+ /** Output pixels per world unit: 2 makes an image twice the page's size. */
205
+ scale: number;
206
+ /** The color painted under the page. Default: the page color of the
207
+ * scene's diagram theme. `null` leaves it transparent. */
208
+ background?: string | null;
209
+ }
210
+ /**
211
+ * Draw `page` of `scene` into a PNG, `page × scale` pixels, through the
212
+ * renderer the canvas draws with, so it shows what the canvas shows, cut to
213
+ * the page's edges. Annotation layers are left out.
214
+ *
215
+ * The caller has registered whatever the scene needs painting with, as it
216
+ * must to draw it at all: the diagram painters (`registerDiagramShape`,
217
+ * `registerMarkShape`) and its fonts. Paint kinds and faces that load on
218
+ * demand are waited for. Needs WebGL2 and `OffscreenCanvas`.
219
+ */
220
+ declare function exportPagePng(scene: PageExportScene, page: PageRect, opts: ExportPagePngOptions): Promise<Blob>;
221
+
222
+ /** Options for {@link exportPagesPdf}. */
223
+ interface ExportPagesPdfOptions {
224
+ /** The color painted under each page. Default: the page color of the
225
+ * scene's diagram theme. `null` leaves it unpainted. */
226
+ background?: string | null;
227
+ /** The document's title. */
228
+ title?: string;
229
+ }
230
+ /**
231
+ * Write each of `pages` of `scene` as a page of one PDF, `page × 0.75` points
232
+ * in size, in the order given. Shapes and strokes are vector; text is real,
233
+ * selectable text in its embedded face. What a PDF cannot draw is painted
234
+ * through the renderer and placed as an image, and anything it could not
235
+ * carry at all comes back in `skipped`. Annotation layers are left out.
236
+ *
237
+ * The caller has registered what the scene needs painting with, as for
238
+ * `exportPagePng`, including each font's outlines. Needs WebGL2 and
239
+ * `OffscreenCanvas`.
240
+ */
241
+ declare function exportPagesPdf(scene: PageExportScene, pages: readonly PageRect[], opts?: ExportPagesPdfOptions): Promise<{
242
+ blob: Blob;
243
+ skipped: readonly PdfSkip[];
244
+ }>;
245
+
246
+ export { DIAGRAM_DOT, DIAGRAM_FORMATS, DIAGRAM_JSON, DIAGRAM_MERMAID, DRAW_XML, type DiagramDocument, type DiagramFormat, type DocumentFromSceneOptions, type DocumentPage, type DocumentScene, type DocumentSpecsOptions, type ExportPagePngOptions, type ExportPageSvgOptions, type ExportPagesPdfOptions, type ExportResult, type ImportResult, type PageExportScene, type PageRect, type WriteOptions, detectFormat, documentFromScene, documentSpecs, exportPagePng, exportPageSvg, exportPagesPdf, pageSvgNodes, readDocument, writtenPage };