@draftably/mermaid 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -2
- package/dist/LICENSE +21 -0
- package/dist/cdn/font-data-DbrpaYkG-vzB__apN.mjs +30 -0
- package/dist/cdn/index-MjBeFYcO.mjs +7738 -0
- package/dist/cdn/mermaid-facade-BoLWBerE.mjs +289 -0
- package/dist/cdn/mermaid-importer-SlRnjUhj.mjs +3753 -0
- package/dist/chunks/mermaid-facade-BoLWBerE.js +289 -0
- package/dist/chunks/mermaid-importer-IVovOQE9.js +3753 -0
- package/dist/mermaid.esm.min.mjs +13 -0
- package/dist/mermaid.js +117 -0
- package/dist/types/packages/mermaid/src/index.d.ts +59 -0
- package/dist/types/src/dsl/cells.d.ts +91 -0
- package/dist/types/src/dsl/channels.d.ts +53 -0
- package/dist/types/src/dsl/compile.d.ts +162 -0
- package/dist/types/src/dsl/frame.d.ts +38 -0
- package/dist/types/src/dsl/lanes.d.ts +23 -0
- package/dist/types/src/dsl/legend-notes.d.ts +3 -0
- package/dist/types/src/dsl/project.d.ts +39 -0
- package/dist/types/src/dsl/syntax.d.ts +317 -0
- package/dist/types/src/import/import-core.d.ts +105 -0
- package/dist/types/src/import/mermaid-facade.d.ts +120 -0
- package/dist/types/src/import/mermaid-importer.d.ts +4 -0
- package/dist/types/src/import/mermaid-sequence.d.ts +8 -0
- package/dist/types/src/model/appearance.d.ts +209 -0
- package/dist/types/src/model/bounds.d.ts +19 -0
- package/dist/types/src/model/document.d.ts +24 -0
- package/dist/types/src/model/font-faces.d.ts +24 -0
- package/dist/types/src/model/fonts.d.ts +47 -0
- package/dist/types/src/model/footnote.d.ts +34 -0
- package/dist/types/src/model/geometry.d.ts +29 -0
- package/dist/types/src/model/graph.d.ts +53 -0
- package/dist/types/src/model/heading.d.ts +38 -0
- package/dist/types/src/model/icons.d.ts +2 -0
- package/dist/types/src/model/labels.d.ts +88 -0
- package/dist/types/src/model/link.d.ts +63 -0
- package/dist/types/src/model/markers.d.ts +47 -0
- package/dist/types/src/model/note.d.ts +75 -0
- package/dist/types/src/model/rich-text.d.ts +24 -0
- package/dist/types/src/model/routes.d.ts +170 -0
- package/dist/types/src/model/status.d.ts +84 -0
- package/dist/types/src/model/styles.d.ts +13 -0
- package/dist/types/src/model/types.d.ts +277 -0
- package/package.json +36 -3
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagram appearance: five preset themes, color families with numeric shades, and the overrides a
|
|
3
|
+
* file can set. `resolveAppearance` turns a saved appearance into the concrete colors, spacing and
|
|
4
|
+
* type that sizing, the canvas and both SVG exports read, so all of them agree.
|
|
5
|
+
*
|
|
6
|
+
* Diagram appearance is separate from the editor's light or dark mode.
|
|
7
|
+
*/
|
|
8
|
+
import type { Footnote } from './footnote';
|
|
9
|
+
import type { Note } from './note';
|
|
10
|
+
import { type FontRole, type TypeProfile } from './fonts';
|
|
11
|
+
import type { FileConfig } from './link';
|
|
12
|
+
export type ThemeId = 'drafting' | 'fieldnotes' | 'signal' | 'ink' | 'blueprint';
|
|
13
|
+
export declare const THEME_IDS: ThemeId[];
|
|
14
|
+
export declare const DEFAULT_THEME: ThemeId;
|
|
15
|
+
/** Shade stops. Lower numbers are lighter and higher numbers darker, in every theme. */
|
|
16
|
+
export declare const SHADES: readonly [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
|
|
17
|
+
export type Shade = (typeof SHADES)[number];
|
|
18
|
+
export declare const isShade: (n: unknown) => n is Shade;
|
|
19
|
+
/** Shade of a node that names a color without a shade. */
|
|
20
|
+
export declare const NODE_SHADE: Shade;
|
|
21
|
+
/**
|
|
22
|
+
* Shade of a group that names a color without a shade. Groups are quiet surfaces behind nodes, so
|
|
23
|
+
* this is a pale shade in light themes and a deep one in dark themes; the scale itself never flips.
|
|
24
|
+
*/
|
|
25
|
+
export declare const groupShadeFor: (theme: ThemeId) => Shade;
|
|
26
|
+
/** Built-in color families, available in every theme. `primary` and `secondary` follow the theme. */
|
|
27
|
+
export declare const BUILT_IN_FAMILIES: readonly ["primary", "secondary", "slate", "stone", "blue", "sky", "teal", "mint", "green", "amber", "orange", "red", "rose", "violet"];
|
|
28
|
+
export declare const isBuiltInFamily: (name: string) => boolean;
|
|
29
|
+
export interface Swatch {
|
|
30
|
+
fill: string;
|
|
31
|
+
stroke: string;
|
|
32
|
+
ink: string;
|
|
33
|
+
}
|
|
34
|
+
/** A file's color declaration: one shade of a family. Built-in shades may set some fields only. */
|
|
35
|
+
export interface ColorDefinition {
|
|
36
|
+
family: string;
|
|
37
|
+
shade: Shade;
|
|
38
|
+
fill?: string;
|
|
39
|
+
stroke?: string;
|
|
40
|
+
ink?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface AppearanceOverrides {
|
|
43
|
+
paddingX?: number;
|
|
44
|
+
paddingY?: number;
|
|
45
|
+
radius?: number;
|
|
46
|
+
titleFont?: FontRole;
|
|
47
|
+
annotationFont?: FontRole;
|
|
48
|
+
canvas?: string;
|
|
49
|
+
text?: string;
|
|
50
|
+
connection?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface DiagramAppearance {
|
|
53
|
+
theme: ThemeId;
|
|
54
|
+
overrides: AppearanceOverrides;
|
|
55
|
+
colors: ColorDefinition[];
|
|
56
|
+
/** What the colors mean, from `legend` statements, drawn as a key beside the diagram. */
|
|
57
|
+
legend?: LegendEntry[];
|
|
58
|
+
/** Title and subtitle drawn above exported images, from `diagram` and `subtitle` statements. */
|
|
59
|
+
heading?: Heading;
|
|
60
|
+
/** Sentences drawn on the diagram without moving it, from `note` statements. */
|
|
61
|
+
notes?: Note[];
|
|
62
|
+
/** Entries of the block between the drawing and the key, from `footnote` statements. */
|
|
63
|
+
footnotes?: Footnote[];
|
|
64
|
+
/** Panel labels from a `compare` statement: draw the old and new versions side by side. */
|
|
65
|
+
compare?: {
|
|
66
|
+
/** Set by `draftably compare`: the changes the older panel draws in their new version. */
|
|
67
|
+
undrawn?: string;
|
|
68
|
+
before: string;
|
|
69
|
+
after: string;
|
|
70
|
+
/** `right` sets the panels side by side, `down` stacks them; chosen by `aspect` when unset. */
|
|
71
|
+
direction?: 'right' | 'down';
|
|
72
|
+
/** Width over height the whole image should come closest to; 1.6 when unset. */
|
|
73
|
+
aspect?: number;
|
|
74
|
+
};
|
|
75
|
+
/** File settings from `config` statements. */
|
|
76
|
+
config?: FileConfig;
|
|
77
|
+
/** Named emphasis states from `state` statements, in file order. */
|
|
78
|
+
states?: EmphasisState[];
|
|
79
|
+
}
|
|
80
|
+
/** One way to draw the diagram: these objects and connections in focus, the rest faded or plain. */
|
|
81
|
+
export interface EmphasisState {
|
|
82
|
+
id: string;
|
|
83
|
+
label: string;
|
|
84
|
+
/** Objects (a group brings its members) and connections in focus. */
|
|
85
|
+
ids: string[];
|
|
86
|
+
/** How everything else draws: faded like a context line, or as usual. */
|
|
87
|
+
rest: 'dim' | 'plain';
|
|
88
|
+
}
|
|
89
|
+
export interface Heading {
|
|
90
|
+
title?: string;
|
|
91
|
+
subtitle?: string;
|
|
92
|
+
/** Width of the frame round the drawing, from `diagram width=`; never narrower than its content. */
|
|
93
|
+
width?: number;
|
|
94
|
+
}
|
|
95
|
+
/** The connection styles a `legend line` row can explain. */
|
|
96
|
+
export declare const LEGEND_LINES: readonly ["dashed", "solid"];
|
|
97
|
+
export type LegendLine = (typeof LEGEND_LINES)[number];
|
|
98
|
+
/** One row of the key: a color swatch (`family`), or a short connection (`line`). */
|
|
99
|
+
export interface LegendEntry {
|
|
100
|
+
family?: string;
|
|
101
|
+
line?: LegendLine;
|
|
102
|
+
/** Shade of the swatch; nodes' default when omitted. */
|
|
103
|
+
shade?: Shade;
|
|
104
|
+
label: string;
|
|
105
|
+
}
|
|
106
|
+
export declare const defaultAppearance: () => DiagramAppearance;
|
|
107
|
+
/** Limits for numeric overrides, shared by the file parser and JSON validation. */
|
|
108
|
+
export declare const OVERRIDE_LIMITS: {
|
|
109
|
+
readonly paddingX: {
|
|
110
|
+
readonly min: 4;
|
|
111
|
+
readonly max: 48;
|
|
112
|
+
};
|
|
113
|
+
readonly paddingY: {
|
|
114
|
+
readonly min: 4;
|
|
115
|
+
readonly max: 48;
|
|
116
|
+
};
|
|
117
|
+
readonly radius: {
|
|
118
|
+
readonly min: 0;
|
|
119
|
+
readonly max: 24;
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
export declare const HEX_COLOR: RegExp;
|
|
123
|
+
interface Preset {
|
|
124
|
+
label: string;
|
|
125
|
+
description: string;
|
|
126
|
+
dark: boolean;
|
|
127
|
+
canvas: string;
|
|
128
|
+
text: string;
|
|
129
|
+
muted: string;
|
|
130
|
+
connection: string;
|
|
131
|
+
node: Swatch;
|
|
132
|
+
group: Swatch;
|
|
133
|
+
paddingX: number;
|
|
134
|
+
paddingY: number;
|
|
135
|
+
radius: number;
|
|
136
|
+
shadow: boolean;
|
|
137
|
+
titleFont: FontRole;
|
|
138
|
+
annotationFont: FontRole;
|
|
139
|
+
titleSize: number;
|
|
140
|
+
titleLine: number;
|
|
141
|
+
annotationSize: number;
|
|
142
|
+
/** Chroma multiplier for the built-in families: how saturated this theme's colors are. */
|
|
143
|
+
chroma: number;
|
|
144
|
+
/** Anchor colors for `primary` and `secondary`, at the shade they appear as. */
|
|
145
|
+
primary: [string, Shade];
|
|
146
|
+
secondary: [string, Shade];
|
|
147
|
+
/** Hue and chroma for built-in families this theme draws in its own way. */
|
|
148
|
+
hues?: Partial<Record<string, [number, number]>>;
|
|
149
|
+
}
|
|
150
|
+
export declare const PRESETS: Record<ThemeId, Preset>;
|
|
151
|
+
export declare function contrast(a: string, b: string): number;
|
|
152
|
+
/** Contrast targets (WCAG ratios) every generated color meets. */
|
|
153
|
+
export declare const CONTRAST: {
|
|
154
|
+
/** Dark title text on a pale fill. */
|
|
155
|
+
readonly paleInk: 7;
|
|
156
|
+
/** White title text on a dark fill. */
|
|
157
|
+
readonly darkInk: 4.5;
|
|
158
|
+
/** A shape's outline against the canvas when its fill alone does not separate it. */
|
|
159
|
+
readonly outline: 3;
|
|
160
|
+
/** Connection lines and connection label text against the canvas. */
|
|
161
|
+
readonly connection: 4.5;
|
|
162
|
+
/** A group's frame against the canvas. */
|
|
163
|
+
readonly frame: 2;
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Move a color's lightness away from `against` until it reaches `min` contrast with it. Colors
|
|
167
|
+
* that already meet the target are returned unchanged.
|
|
168
|
+
*/
|
|
169
|
+
export declare function ensureContrast(color: string, against: string, min: number): string;
|
|
170
|
+
/** The built-in families of a preset on a canvas color, generated once. */
|
|
171
|
+
export declare function builtInFamilies(theme: ThemeId, canvas?: string): Map<string, Map<Shade, Swatch>>;
|
|
172
|
+
export interface ResolvedAppearance {
|
|
173
|
+
theme: ThemeId;
|
|
174
|
+
dark: boolean;
|
|
175
|
+
canvas: string;
|
|
176
|
+
text: string;
|
|
177
|
+
muted: string;
|
|
178
|
+
connection: string;
|
|
179
|
+
/** Default node and group colors when nothing names a family. */
|
|
180
|
+
node: Swatch;
|
|
181
|
+
group: Swatch;
|
|
182
|
+
paddingX: number;
|
|
183
|
+
paddingY: number;
|
|
184
|
+
radius: number;
|
|
185
|
+
shadow: boolean;
|
|
186
|
+
title: TypeProfile;
|
|
187
|
+
groupTitle: TypeProfile;
|
|
188
|
+
annotation: TypeProfile;
|
|
189
|
+
/** Space above a group's content; the group title sits in it. */
|
|
190
|
+
groupHeader: number;
|
|
191
|
+
/** Every family and the shades it defines: built-in ones plus the file's own. */
|
|
192
|
+
families: Map<string, Map<Shade, Swatch>>;
|
|
193
|
+
custom: Set<string>;
|
|
194
|
+
/** Strike a removed object's title through (`config strike-removed=on`). */
|
|
195
|
+
strikeRemoved: boolean;
|
|
196
|
+
}
|
|
197
|
+
/** Height of a group's title band, derived from the title's line height. */
|
|
198
|
+
export declare const groupHeaderFor: (lineHeight: number) => number;
|
|
199
|
+
/** Preset values, then file overrides. Omitted fields inherit from the preset. */
|
|
200
|
+
export declare function resolveAppearance(appearance?: DiagramAppearance): ResolvedAppearance;
|
|
201
|
+
/**
|
|
202
|
+
* Colors for an object. `family` is a family name, or `auto` for the theme's default surface; an
|
|
203
|
+
* omitted shade is 500 for nodes and 100 for groups. Unknown families or shades fall back to the
|
|
204
|
+
* default surface; the file parser reports them before they get here.
|
|
205
|
+
*/
|
|
206
|
+
export declare function swatchFor(r: ResolvedAppearance, family: string | undefined, shade: Shade | undefined, kind?: 'node' | 'group'): Swatch;
|
|
207
|
+
/** Shades a family defines, in numeric order. */
|
|
208
|
+
export declare const shadesOf: (r: ResolvedAppearance, family: string) => Shade[];
|
|
209
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { VisibleGraph } from './graph';
|
|
2
|
+
import type { Diagram, Point, Rect } from './types';
|
|
3
|
+
/** How far a connection's ink reaches past its points: half the stroke plus the arrowhead's wings. */
|
|
4
|
+
export declare const ROUTE_INK = 4;
|
|
5
|
+
export interface BoundedRoute {
|
|
6
|
+
id?: string;
|
|
7
|
+
points: readonly Point[];
|
|
8
|
+
label: {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
w: number;
|
|
12
|
+
h: number;
|
|
13
|
+
} | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Bounds of everything drawn: shapes with their labels, containers, every route point with its
|
|
17
|
+
* stroke and arrowhead, and every connection label box. `pad` adds a margin on each side.
|
|
18
|
+
*/
|
|
19
|
+
export declare function drawingBounds(doc: Diagram, vg: VisibleGraph, rects: ReadonlyMap<string, Rect>, routes: readonly BoundedRoute[], pad?: number): Rect;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type DiagramAppearance } from './appearance';
|
|
2
|
+
import type { Diagram, DiagramSettings } from './types';
|
|
3
|
+
export declare const MAX_NODES = 500;
|
|
4
|
+
export declare const MAX_EDGES = 1200;
|
|
5
|
+
export declare function uid(prefix?: string): string;
|
|
6
|
+
export declare const DEFAULT_SETTINGS: DiagramSettings;
|
|
7
|
+
export declare function emptyDiagram(title?: string): Diagram;
|
|
8
|
+
type Raw = any;
|
|
9
|
+
export declare const isLegacyDiagram: (input: Raw) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Validate a diagram from any source and return a complete, canonical copy.
|
|
12
|
+
* Throws a readable error for anything that cannot be repaired.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalize(input: unknown): Diagram;
|
|
15
|
+
/** Validate a saved appearance. A missing appearance is the default theme. */
|
|
16
|
+
export declare function normalizeAppearance(input: Raw): DiagramAppearance;
|
|
17
|
+
/** The meaning of a document, ignoring where the camera happens to be. */
|
|
18
|
+
export declare function documentIdentity(doc: Diagram): string;
|
|
19
|
+
/**
|
|
20
|
+
* Inputs that affect connection routing. The editor store keeps the key order of the document it
|
|
21
|
+
* replaced, so the worker's freshly projected copy of the same document lists its keys differently.
|
|
22
|
+
*/
|
|
23
|
+
export declare function routingFingerprint(doc: Diagram): string;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** SHA-256 prefix of the metric table and its four WOFF2 files, in declared face order. */
|
|
2
|
+
export declare const fontMetricsVersion = "269b2d3580f4";
|
|
3
|
+
export declare const FACES: {
|
|
4
|
+
'sans-500': {
|
|
5
|
+
family: string;
|
|
6
|
+
weight: number;
|
|
7
|
+
file: string;
|
|
8
|
+
};
|
|
9
|
+
'sans-600': {
|
|
10
|
+
family: string;
|
|
11
|
+
weight: number;
|
|
12
|
+
file: string;
|
|
13
|
+
};
|
|
14
|
+
'serif-600': {
|
|
15
|
+
family: string;
|
|
16
|
+
weight: number;
|
|
17
|
+
file: string;
|
|
18
|
+
};
|
|
19
|
+
'mono-500': {
|
|
20
|
+
family: string;
|
|
21
|
+
weight: number;
|
|
22
|
+
file: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type FontRole = 'sans' | 'serif' | 'mono';
|
|
2
|
+
export declare const FONT_ROLES: FontRole[];
|
|
3
|
+
export interface FontFace {
|
|
4
|
+
/** Registered family name; unique so an installed copy of the font is never used instead. */
|
|
5
|
+
family: string;
|
|
6
|
+
weight: number;
|
|
7
|
+
file: string;
|
|
8
|
+
}
|
|
9
|
+
export { FACES } from './font-faces';
|
|
10
|
+
import { FACES } from './font-faces';
|
|
11
|
+
export type FaceId = keyof typeof FACES;
|
|
12
|
+
/** Face used for each role: titles are a little heavier than annotations in sans-serif. */
|
|
13
|
+
export declare const faceFor: (role: FontRole, title: boolean) => FaceId;
|
|
14
|
+
export declare const fontStack: (role: FontRole) => string;
|
|
15
|
+
/** A text style: which face, at what size and line height. */
|
|
16
|
+
export interface TypeProfile {
|
|
17
|
+
role: FontRole;
|
|
18
|
+
face: FaceId;
|
|
19
|
+
family: string;
|
|
20
|
+
weight: number;
|
|
21
|
+
size: number;
|
|
22
|
+
lineHeight: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function typeProfile(role: FontRole, title: boolean, size: number, lineHeight: number): TypeProfile;
|
|
25
|
+
/**
|
|
26
|
+
* Width of `text` in `profile`, from the stored advance widths. Kerning is ignored, which only
|
|
27
|
+
* ever overstates a width slightly, so measured text fits where this says it fits.
|
|
28
|
+
*/
|
|
29
|
+
export declare function measureText(text: string, profile: Pick<TypeProfile, 'face' | 'size'>): number;
|
|
30
|
+
/**
|
|
31
|
+
* The pieces an identifier reads in, so a long one can break where a reader would: after a
|
|
32
|
+
* separator (`/`, `.`, `_`, `-`, `:`) or between a lower-case letter or digit and a capital
|
|
33
|
+
* (camelCase). `annotationCommands` → `annotation`, `Commands`; `src/viz/Treemap.tsx` → `src/`,
|
|
34
|
+
* `viz/`, `Treemap.tsx`. A word with none of these is one piece.
|
|
35
|
+
*/
|
|
36
|
+
export declare function wordPieces(word: string): string[];
|
|
37
|
+
/** Width of the widest piece of any word in `text`: the narrowest line it wraps into whole. */
|
|
38
|
+
export declare function widestPiece(text: string, profile: Pick<TypeProfile, 'face' | 'size'>): number;
|
|
39
|
+
/**
|
|
40
|
+
* Break text into lines no wider than `width`, starting a new line at each `\n`. A word longer
|
|
41
|
+
* than a line breaks between its pieces (`wordPieces`), and only a piece that is itself too long
|
|
42
|
+
* breaks by character. With `balance`, a paragraph that wraps keeps its line count but its lines
|
|
43
|
+
* run near equal (`even`), so no word sits alone on the last line when a better break exists.
|
|
44
|
+
*/
|
|
45
|
+
export declare function wrapLines(text: string, width: number, profile: TypeProfile, balance?: boolean): string[];
|
|
46
|
+
/** Shorten text with an ellipsis so it fits in `width`. */
|
|
47
|
+
export declare function truncateText(text: string, width: number, profile: TypeProfile): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Footnotes: a block of short entries between the drawing and the key, from `footnote`
|
|
3
|
+
* statements, in file order, at body text size and wrapped to the frame. An entry may carry a
|
|
4
|
+
* marker (`1`, `a`, `*`) that a label can point at, and links in `[label](href)` form. The viewer,
|
|
5
|
+
* `inspect --svg`, PDF and the editor's exports all lay it out here.
|
|
6
|
+
*/
|
|
7
|
+
import { type ResolvedAppearance } from './appearance';
|
|
8
|
+
import { type Run } from './rich-text';
|
|
9
|
+
export interface Footnote {
|
|
10
|
+
text: string;
|
|
11
|
+
/** A short marker drawn before the entry, which labels can point at as `[1]`. */
|
|
12
|
+
mark?: string;
|
|
13
|
+
}
|
|
14
|
+
/** The block's entries, wrapped to `width`, with their offsets from its top-left corner. */
|
|
15
|
+
export declare function footnoteSize(look: ResolvedAppearance, notes: readonly Footnote[], width: number): {
|
|
16
|
+
type: import("./fonts").TypeProfile;
|
|
17
|
+
gutter: number;
|
|
18
|
+
items: {
|
|
19
|
+
note: Footnote;
|
|
20
|
+
lines: Run[][];
|
|
21
|
+
y: number;
|
|
22
|
+
}[];
|
|
23
|
+
h: number;
|
|
24
|
+
};
|
|
25
|
+
export type FootnoteLayout = ReturnType<typeof footnoteSize>;
|
|
26
|
+
/** Where each line of every entry is drawn, from the block's top-left corner at (x, y). */
|
|
27
|
+
export declare function footnoteLines(layout: FootnoteLayout, x: number, y: number): {
|
|
28
|
+
entry: number;
|
|
29
|
+
runs: Run[];
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
}[];
|
|
33
|
+
/** SVG markup for the block: a short rule, then each entry's marker and wrapped text. */
|
|
34
|
+
export declare function footnoteMarkup(look: ResolvedAppearance, layout: FootnoteLayout, x: number, y: number, write?: (href: string) => string | null): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Point, Rect } from './types';
|
|
2
|
+
export declare const clamp: (n: number, min: number, max: number) => number;
|
|
3
|
+
export declare const finite: (n: unknown) => n is number;
|
|
4
|
+
/** Document coordinates are stored with one decimal place. */
|
|
5
|
+
export declare const rounded: (n: number) => number;
|
|
6
|
+
export declare const center: (r: Rect) => Point;
|
|
7
|
+
export declare const manhattan: (a: Point, b: Point) => number;
|
|
8
|
+
export declare const inside: (p: Point, r: Rect, pad?: number) => boolean;
|
|
9
|
+
export declare const contains: (outer: Rect, inner: Rect) => boolean;
|
|
10
|
+
export declare const overlaps: (a: Rect, b: Rect, pad?: number) => boolean;
|
|
11
|
+
/** Bounding box of the given rectangles, or a placeholder area when there are none. */
|
|
12
|
+
export declare function rectUnion(rects: readonly Rect[], pad?: number): Rect;
|
|
13
|
+
/** Rectangle spanned by two corner points. */
|
|
14
|
+
export declare const rectFromPoints: (a: Point, b: Point) => Rect;
|
|
15
|
+
export type Segment = [Point, Point];
|
|
16
|
+
export declare const segments: (points: readonly Point[]) => Segment[];
|
|
17
|
+
export declare const shrink: (r: Rect, d: number) => Rect;
|
|
18
|
+
/** Overlap of two rectangles larger than half a pixel on both axes. */
|
|
19
|
+
export declare const covers: (a: Rect, b: Rect) => boolean;
|
|
20
|
+
/** Length of a segment inside a rectangle (Liang–Barsky clipping). */
|
|
21
|
+
export declare function segmentInside([a, b]: Segment, r: Rect): number;
|
|
22
|
+
/** SVG path for an orthogonal polyline with rounded corners. */
|
|
23
|
+
export declare function roundedPath(points: readonly Point[], radius: number): string;
|
|
24
|
+
export declare const clone: <T>(value: T) => T;
|
|
25
|
+
/**
|
|
26
|
+
* A rectangle whose left and right sides are zigzags, for a field of variable length: the reader
|
|
27
|
+
* sees it continue past what is drawn.
|
|
28
|
+
*/
|
|
29
|
+
export declare function brokenRectPath(r: Rect, step?: number, depth?: number): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Diagram, DiagramEdge, DiagramGroup, DiagramNode, Direction, Entity, NodeLayout, NodeStyle, Rect } from './types';
|
|
2
|
+
export declare const findNode: (doc: Diagram, id: string | null | undefined) => DiagramNode | undefined;
|
|
3
|
+
export declare const findGroup: (doc: Diagram, id: string | null | undefined) => DiagramGroup | undefined;
|
|
4
|
+
export declare const findEdge: (doc: Diagram, id: string | null | undefined) => DiagramEdge | undefined;
|
|
5
|
+
export declare const findObject: (doc: Diagram, id: string | null | undefined) => DiagramNode | DiagramGroup | undefined;
|
|
6
|
+
export declare const findEntity: (doc: Diagram, id: string | null | undefined) => Entity | undefined;
|
|
7
|
+
export declare const isNode: (doc: Diagram, id: string) => boolean;
|
|
8
|
+
export declare const isGroup: (doc: Diagram, id: string) => boolean;
|
|
9
|
+
export declare const isEdge: (doc: Diagram, id: string) => boolean;
|
|
10
|
+
export declare const styleOf: (doc: Diagram, id: string) => NodeStyle;
|
|
11
|
+
/** Direct children (shapes and containers) of a container, or of the diagram root. */
|
|
12
|
+
/** The title band of a `cells` group; undefined for any other group. */
|
|
13
|
+
export declare const cellsBandOf: (doc: Diagram, id: string | null | undefined) => number | undefined;
|
|
14
|
+
/** Whether a cell is a field of variable length in a byte or bit layout. */
|
|
15
|
+
export declare const isOpenCell: (doc: Diagram, id: string) => boolean;
|
|
16
|
+
/** Whether a node is a cell of a `cells` group, which holds it in place edge to edge. */
|
|
17
|
+
export declare const isCell: (doc: Diagram, id: string) => boolean;
|
|
18
|
+
export declare function childrenOf(doc: Diagram, parentId: string | null | undefined): (DiagramNode | DiagramGroup)[];
|
|
19
|
+
export declare function descendants(doc: Diagram, id: string): string[];
|
|
20
|
+
/** Containers enclosing an object, nearest first. */
|
|
21
|
+
export declare function ancestors(doc: Diagram, id: string): string[];
|
|
22
|
+
export declare const isCollapsed: (doc: Diagram, id: string) => boolean;
|
|
23
|
+
export declare const isHiddenByCollapse: (doc: Diagram, id: string) => boolean;
|
|
24
|
+
/** The visible object that stands in for `id`: its outermost collapsed container, if any. */
|
|
25
|
+
export declare function visibleProxy(doc: Diagram, id: string): string;
|
|
26
|
+
export interface VisibleEdge extends DiagramEdge {
|
|
27
|
+
/** Visible source, which may be a collapsed container. */
|
|
28
|
+
a: string;
|
|
29
|
+
/** Visible target, which may be a collapsed container. */
|
|
30
|
+
b: string;
|
|
31
|
+
}
|
|
32
|
+
export interface VisibleGraph {
|
|
33
|
+
nodes: DiagramNode[];
|
|
34
|
+
groups: DiagramGroup[];
|
|
35
|
+
edges: VisibleEdge[];
|
|
36
|
+
}
|
|
37
|
+
/** Objects and connections that are not hidden inside a collapsed container. */
|
|
38
|
+
export declare function visibleGraph(doc: Diagram): VisibleGraph;
|
|
39
|
+
/** Selected shapes and containers whose own container is not also selected. */
|
|
40
|
+
export declare function selectionRoots(doc: Diagram, selected: Iterable<string>): string[];
|
|
41
|
+
/** Layout direction for the contents of an object's container. */
|
|
42
|
+
export declare function inheritedDirection(doc: Diagram, id: string): Direction;
|
|
43
|
+
export declare const COLLAPSED_HEIGHT = 58;
|
|
44
|
+
export declare const CONTAINER_HEADER = 28;
|
|
45
|
+
/** Read geometry for an object, preferring a temporary override (preview, animation, brush). */
|
|
46
|
+
export type GeometryLookup = (id: string) => NodeLayout;
|
|
47
|
+
export declare function makeGeometry(doc: Diagram, override?: Record<string, NodeLayout> | null): (id: string) => NodeLayout;
|
|
48
|
+
/**
|
|
49
|
+
* Container frame as drawn: collapsed containers shrink to their title band plus a line for the
|
|
50
|
+
* shape count, so the title stays where it was in the open frame.
|
|
51
|
+
*/
|
|
52
|
+
export declare function frameRect(doc: Diagram, geometry: GeometryLookup, id: string): NodeLayout;
|
|
53
|
+
export declare const objectRect: (doc: Diagram, geometry: GeometryLookup, id: string) => Rect;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The title and subtitle drawn above an exported diagram, shared by `inspect --svg` and the
|
|
3
|
+
* editor's export, so a copied image still says what it shows.
|
|
4
|
+
*/
|
|
5
|
+
import type { Heading, ResolvedAppearance } from './appearance';
|
|
6
|
+
/** Title type: the theme's title face, larger; subtitle type: its annotation face. */
|
|
7
|
+
declare function types(look: ResolvedAppearance): {
|
|
8
|
+
title: import("./fonts").TypeProfile;
|
|
9
|
+
subtitle: import("./fonts").TypeProfile;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Width the subtitle wraps to over a drawing `room` wide: the drawing's width, held between 360px
|
|
13
|
+
* and about 70 characters, so a long subtitle wraps instead of widening the frame.
|
|
14
|
+
*/
|
|
15
|
+
export declare function subtitleMeasure(look: ResolvedAppearance, room: number): number;
|
|
16
|
+
/** Size of the heading block, including the gap under it. Zero when there is nothing to draw. */
|
|
17
|
+
export declare function headingSize(look: ResolvedAppearance, heading: Heading | undefined, wrap: number): {
|
|
18
|
+
w: number;
|
|
19
|
+
h: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Each line of the heading with its own type and box, top-left corner at (x, y). The title is one
|
|
23
|
+
* line; the subtitle wraps to `wrap` (`subtitleMeasure`).
|
|
24
|
+
*/
|
|
25
|
+
export declare function headingLines(look: ResolvedAppearance, heading: Heading | undefined, x: number, y: number, wrap: number): {
|
|
26
|
+
key: "title" | "subtitle";
|
|
27
|
+
text: string;
|
|
28
|
+
type: Type;
|
|
29
|
+
fill: string;
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
}[];
|
|
33
|
+
type Type = ReturnType<typeof types>['title'];
|
|
34
|
+
/** SVG markup for the heading with its top-left corner at (x, y). */
|
|
35
|
+
export declare function headingMarkup(look: ResolvedAppearance, heading: Heading | undefined, x: number, y: number, wrap: number): string;
|
|
36
|
+
/** Title and subtitle type, for drawing and editing them in the viewer. */
|
|
37
|
+
export declare const headingTypes: typeof types;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type ResolvedAppearance } from './appearance';
|
|
2
|
+
import { type TypeProfile } from './fonts';
|
|
3
|
+
import type { Diagram, LabelMode, Rect, ShapeKind } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Room for a shape's title. Every size, wrap and overflow decision goes through these functions,
|
|
6
|
+
* in the compiler, the canvas and the CLI alike.
|
|
7
|
+
*/
|
|
8
|
+
export interface TitleArea {
|
|
9
|
+
/** Line width available to the title. */
|
|
10
|
+
width: number;
|
|
11
|
+
/** Tallest text block that fits inside the shape at its current height. */
|
|
12
|
+
maxHeight: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function titleArea(shape: ShapeKind, w: number, h: number, r: ResolvedAppearance, icon?: boolean): TitleArea;
|
|
15
|
+
/** Height a shape needs for `lines` title lines; never less than `base`. */
|
|
16
|
+
export declare function titleHeight(shape: ShapeKind, lines: number, base: number, r: ResolvedAppearance): number;
|
|
17
|
+
/** A shape's title in balanced lines no wider than `width` (see `wrapLines`). */
|
|
18
|
+
export declare const wrapTitle: (text: string, width: number, r: ResolvedAppearance) => string[];
|
|
19
|
+
/**
|
|
20
|
+
* Line width for a diamond's title, `s` its side. A text block W wide and H tall fits inside a
|
|
21
|
+
* square diamond when W + H <= s, so this takes the widest measure whose wrapped lines still fit:
|
|
22
|
+
* the title reads in as few lines as the shape allows. Undefined when no measure fits.
|
|
23
|
+
*/
|
|
24
|
+
export declare function diamondMeasure(title: string, s: number, r: ResolvedAppearance): number | undefined;
|
|
25
|
+
/** Most lines a group title wraps to; past that the frame widens instead. */
|
|
26
|
+
export declare const GROUP_TITLE_LINES = 3;
|
|
27
|
+
/** A group's header height when its title takes `lines` lines. */
|
|
28
|
+
export declare const groupHeaderFor: (r: ResolvedAppearance, lines?: number) => number;
|
|
29
|
+
/**
|
|
30
|
+
* A group title as drawn in a frame `w` wide: wrapped to at most `lines` lines (the compiler
|
|
31
|
+
* reserves that many), the last shortened with an ellipsis if the text runs on.
|
|
32
|
+
*/
|
|
33
|
+
export declare function groupTitleLines(title: string, w: number, r: ResolvedAppearance, lines?: number): string[];
|
|
34
|
+
export interface NodeLabel {
|
|
35
|
+
/** Center of the label, relative to the shape's top-left corner. */
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
width: number;
|
|
39
|
+
height: number;
|
|
40
|
+
lines: string[];
|
|
41
|
+
mode: LabelMode;
|
|
42
|
+
lineHeight: number;
|
|
43
|
+
leader: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Where a shape's title is drawn, relative to the shape. */
|
|
46
|
+
export declare function nodeLabel(doc: Diagram, id: string, title: string, r: Rect): NodeLabel;
|
|
47
|
+
/** Bounds of a shape together with its label. */
|
|
48
|
+
export declare function visualBounds(doc: Diagram, id: string, title: string, r: Rect): Rect;
|
|
49
|
+
/** Text width a sequence message's label wraps to; the gap between participants follows it. */
|
|
50
|
+
export declare const MESSAGE_WRAP = 168;
|
|
51
|
+
/**
|
|
52
|
+
* The type a connection label is set in: the annotation type, or a step larger for a sequence
|
|
53
|
+
* message (`message`), whose label is the main thing to read.
|
|
54
|
+
*/
|
|
55
|
+
export declare const edgeLabelType: (r: ResolvedAppearance, message?: boolean) => TypeProfile;
|
|
56
|
+
/**
|
|
57
|
+
* Text width a flow line's label wraps to: about 24 characters of the annotation type, so a short
|
|
58
|
+
* phrase stays on one line and a sentence stacks instead of widening its gap.
|
|
59
|
+
*/
|
|
60
|
+
export declare const LABEL_WRAP = 140;
|
|
61
|
+
/**
|
|
62
|
+
* A connection label's lines: split at each `\n` and wrapped to `LABEL_WRAP`, or a sequence
|
|
63
|
+
* message's to `MESSAGE_WRAP`.
|
|
64
|
+
*/
|
|
65
|
+
export declare const edgeLabelLines: (label: string, r: ResolvedAppearance, message?: boolean) => string[];
|
|
66
|
+
/**
|
|
67
|
+
* A self-message's loop: its run out to the right of the lifeline and its drop. Its label sits
|
|
68
|
+
* `label` past the loop, centred on the drop.
|
|
69
|
+
*/
|
|
70
|
+
export declare const SELF_LOOP: {
|
|
71
|
+
out: number;
|
|
72
|
+
down: number;
|
|
73
|
+
label: number;
|
|
74
|
+
};
|
|
75
|
+
/** Box for a connection label in the diagram's annotation type. */
|
|
76
|
+
export declare function edgeLabelSize(label: string, r?: ResolvedAppearance, message?: boolean): {
|
|
77
|
+
w: number;
|
|
78
|
+
h: number;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* What a self-message draws, measured from where its row meets the lifeline: how far right, how
|
|
82
|
+
* far above the row and how far below it.
|
|
83
|
+
*/
|
|
84
|
+
export declare function selfMessageInk(label: string | undefined, r: ResolvedAppearance): {
|
|
85
|
+
right: number;
|
|
86
|
+
above: number;
|
|
87
|
+
below: number;
|
|
88
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Links on objects (`href=`): what a link points at, and where its mark sits on a shape.
|
|
3
|
+
*
|
|
4
|
+
* A link is kept as the author wrote it. A URL (`https://…`, `mailto:`) opens as written; a
|
|
5
|
+
* `.draft` opens in the viewer; anything else is a file path that opens in the editor. A file
|
|
6
|
+
* path may end in `:line` or `:line:col`, and a relative one starts at the link base: the git
|
|
7
|
+
* root of the diagram, unless the file sets `config link-base=`.
|
|
8
|
+
*/
|
|
9
|
+
import { type TypeProfile } from './fonts';
|
|
10
|
+
export type LinkKind = 'url' | 'draft' | 'file';
|
|
11
|
+
export interface LinkTarget {
|
|
12
|
+
kind: LinkKind;
|
|
13
|
+
/** The URL, or the file path without its line and column. */
|
|
14
|
+
path: string;
|
|
15
|
+
line?: number;
|
|
16
|
+
col?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function linkTarget(href: string): LinkTarget;
|
|
19
|
+
/**
|
|
20
|
+
* A relative `href` against a URL `link-base` (`https://host/org/repo/blob/<sha>/`), as the URL
|
|
21
|
+
* it opens; null when the base is a folder or unset, or `href` is already a URL.
|
|
22
|
+
*/
|
|
23
|
+
export declare function baseUrl(href: string, base: string | undefined): string | null;
|
|
24
|
+
/** Join and normalize forward-slash paths; an absolute `path` ignores `base`. */
|
|
25
|
+
export declare function joinPath(base: string, path: string): string;
|
|
26
|
+
/** The path from folder `from` to `to`, both absolute with forward slashes. */
|
|
27
|
+
export declare function relativePath(from: string, to: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* A link as a static SVG carries it. A URL stays as written; a file or `.draft` becomes a path
|
|
30
|
+
* from the diagram's folder (a first guess at where the SVG is saved), without its line.
|
|
31
|
+
*/
|
|
32
|
+
export declare function staticHref(href: string, base: string, folder: string): string;
|
|
33
|
+
/** Editors that open `<scheme>://file/<path>:<line>:<col>`. */
|
|
34
|
+
export declare const EDITORS: readonly ["vscode", "vscode-insiders", "cursor", "windsurf", "zed"];
|
|
35
|
+
export type Editor = (typeof EDITORS)[number];
|
|
36
|
+
/** File settings from `config` statements. */
|
|
37
|
+
export interface FileConfig {
|
|
38
|
+
/**
|
|
39
|
+
* Where relative links start: a folder relative to the diagram's (its git root when unset), or
|
|
40
|
+
* a URL that relative links are joined to.
|
|
41
|
+
*/
|
|
42
|
+
linkBase?: string;
|
|
43
|
+
/** The editor file links open in; VS Code when unset. */
|
|
44
|
+
editor?: Editor;
|
|
45
|
+
/** Strike removed titles through in a diff; off when unset. */
|
|
46
|
+
strikeRemoved?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export declare const editorUrl: (editor: Editor, file: string, line?: number, col?: number) => string;
|
|
49
|
+
/** The link mark: a small arrow out of a shape's top-right corner, inside the shape when it can be. */
|
|
50
|
+
export interface LinkMark {
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
size: number;
|
|
54
|
+
/** Inside the shape's fill (draw in its ink), or on the canvas beside it. */
|
|
55
|
+
inside: boolean;
|
|
56
|
+
}
|
|
57
|
+
export declare const LINK_MARK_SIZE = 10;
|
|
58
|
+
/** `badge` is the width of a `count` badge on the corner, which the mark steps left of. */
|
|
59
|
+
export declare function linkMark(shape: string, w: number, h: number, badge?: number): LinkMark;
|
|
60
|
+
/** The mark next to a container's title. */
|
|
61
|
+
export declare const groupLinkMark: (title: string, font: TypeProfile, band: number) => LinkMark;
|
|
62
|
+
/** The arrow, in a 10×10 box. */
|
|
63
|
+
export declare const LINK_MARK_PATH = "M2 8L8 2M3.5 2H8V6.5";
|