@draftably/markdown 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +16 -64
  2. package/dist/chunks/{core-DPjuIyPG.js → core-D4HpamVq.js} +19 -13
  3. package/dist/chunks/mermaid-facade-BoLWBerE.js +289 -0
  4. package/dist/chunks/mermaid-importer-IVovOQE9.js +3753 -0
  5. package/dist/markdown-it.js +86 -85
  6. package/dist/mermaid.js +93 -0
  7. package/dist/remark.js +46 -46
  8. package/dist/types/{core.d.ts → packages/markdown/src/core.d.ts} +11 -0
  9. package/dist/types/packages/markdown/src/mermaid.d.ts +8 -0
  10. package/dist/types/{remark.d.ts → packages/markdown/src/remark.d.ts} +1 -1
  11. package/dist/types/src/dsl/cells.d.ts +91 -0
  12. package/dist/types/src/dsl/channels.d.ts +53 -0
  13. package/dist/types/src/dsl/compile.d.ts +162 -0
  14. package/dist/types/src/dsl/frame.d.ts +38 -0
  15. package/dist/types/src/dsl/lanes.d.ts +23 -0
  16. package/dist/types/src/dsl/legend-notes.d.ts +3 -0
  17. package/dist/types/src/dsl/project.d.ts +39 -0
  18. package/dist/types/src/dsl/syntax.d.ts +317 -0
  19. package/dist/types/src/import/import-core.d.ts +105 -0
  20. package/dist/types/src/import/mermaid-facade.d.ts +120 -0
  21. package/dist/types/src/import/mermaid-importer.d.ts +4 -0
  22. package/dist/types/src/import/mermaid-sequence.d.ts +8 -0
  23. package/dist/types/src/model/appearance.d.ts +209 -0
  24. package/dist/types/src/model/bounds.d.ts +19 -0
  25. package/dist/types/src/model/document.d.ts +24 -0
  26. package/dist/types/src/model/font-faces.d.ts +24 -0
  27. package/dist/types/src/model/fonts.d.ts +47 -0
  28. package/dist/types/src/model/footnote.d.ts +34 -0
  29. package/dist/types/src/model/geometry.d.ts +29 -0
  30. package/dist/types/src/model/graph.d.ts +53 -0
  31. package/dist/types/src/model/heading.d.ts +38 -0
  32. package/dist/types/src/model/icons.d.ts +2 -0
  33. package/dist/types/src/model/labels.d.ts +88 -0
  34. package/dist/types/src/model/link.d.ts +63 -0
  35. package/dist/types/src/model/markers.d.ts +47 -0
  36. package/dist/types/src/model/note.d.ts +75 -0
  37. package/dist/types/src/model/rich-text.d.ts +24 -0
  38. package/dist/types/src/model/routes.d.ts +170 -0
  39. package/dist/types/src/model/status.d.ts +84 -0
  40. package/dist/types/src/model/styles.d.ts +13 -0
  41. package/dist/types/src/model/types.d.ts +277 -0
  42. package/package.json +9 -7
  43. /package/dist/types/{client-validation.d.ts → packages/markdown/src/client-validation.d.ts} +0 -0
  44. /package/dist/types/{client.d.ts → packages/markdown/src/client.d.ts} +0 -0
  45. /package/dist/types/{files.d.ts → packages/markdown/src/files.d.ts} +0 -0
  46. /package/dist/types/{index.d.ts → packages/markdown/src/index.d.ts} +0 -0
  47. /package/dist/types/{markdown-it-helpers.d.ts → packages/markdown/src/markdown-it-helpers.d.ts} +0 -0
  48. /package/dist/types/{markdown-it.d.ts → packages/markdown/src/markdown-it.d.ts} +0 -0
  49. /package/dist/types/{metadata.d.ts → packages/markdown/src/metadata.d.ts} +0 -0
  50. /package/dist/types/{source.d.ts → packages/markdown/src/source.d.ts} +0 -0
@@ -0,0 +1,105 @@
1
+ /** Build native source from the facts retained by an importer. */
2
+ import type { EndMarker } from '../model/markers';
3
+ export type Format = 'dot' | 'mermaid' | 'd2';
4
+ export type Impact = 'syntax' | 'semantics' | 'appearance' | 'layout' | 'security' | 'limit';
5
+ export interface Diagnostic {
6
+ code: string;
7
+ severity: 'error' | 'warning' | 'info';
8
+ impact: Impact;
9
+ message: string;
10
+ line?: number;
11
+ column?: number;
12
+ foreignIds?: string[];
13
+ }
14
+ export interface NativeObject {
15
+ id: string;
16
+ kind: 'node' | 'group';
17
+ label: string;
18
+ parent?: string;
19
+ shape?: 'box' | 'pill' | 'circle' | 'diamond' | 'text';
20
+ color?: string;
21
+ shade?: number;
22
+ }
23
+ export interface NativeEdge {
24
+ id: string;
25
+ from: string;
26
+ to: string;
27
+ label: string;
28
+ directed: boolean;
29
+ head?: EndMarker;
30
+ tail?: EndMarker;
31
+ dashed?: boolean;
32
+ constraint?: false;
33
+ fromSide?: 'left' | 'right' | 'top' | 'bottom';
34
+ toSide?: 'left' | 'right' | 'top' | 'bottom';
35
+ }
36
+ export interface NativeLayout {
37
+ scope: string;
38
+ kind: 'flow' | 'column' | 'row' | 'sequence';
39
+ direction?: 'right' | 'down';
40
+ }
41
+ export interface NativeColor {
42
+ name: string;
43
+ fill: string;
44
+ stroke: string;
45
+ ink: string;
46
+ }
47
+ export interface NativePhase {
48
+ id: string;
49
+ label: string;
50
+ members: string[];
51
+ }
52
+ export interface NativeNote {
53
+ text: string;
54
+ near?: string;
55
+ side?: 'left' | 'right' | 'above' | 'below';
56
+ }
57
+ export interface NativePlan {
58
+ title: string;
59
+ objects: NativeObject[];
60
+ edges: NativeEdge[];
61
+ layouts: NativeLayout[];
62
+ colors: NativeColor[];
63
+ /** Sequence diagrams only. */
64
+ phases?: NativePhase[];
65
+ notes?: NativeNote[];
66
+ }
67
+ export interface IdMapping {
68
+ kind: string;
69
+ foreign: string;
70
+ native: string;
71
+ }
72
+ export interface ImportResult {
73
+ status: 'ready' | 'needs-review' | 'failed';
74
+ format: Format;
75
+ family: string;
76
+ diagnostics: Diagnostic[];
77
+ /** Absent on every fatal error; callers must not apply a partial graph. */
78
+ nativeSource?: string;
79
+ facts?: NativePlan;
80
+ ids: IdMapping[];
81
+ requires: string[];
82
+ }
83
+ export declare const LIMITS: Readonly<{
84
+ sourceBytes: number;
85
+ objects: 500;
86
+ edges: 1200;
87
+ depth: 12;
88
+ labelChars: number;
89
+ totalLabelBytes: number;
90
+ outputBytes: number;
91
+ nativeSourceChars: 300000;
92
+ }>;
93
+ export declare class Ids {
94
+ readonly entries: IdMapping[];
95
+ private readonly byForeign;
96
+ private readonly taken;
97
+ get(kind: string, foreign: string, preferred?: string): string;
98
+ }
99
+ export declare const quote: (value: string) => string;
100
+ export declare const blankPlan: (title: string) => NativePlan;
101
+ export declare function inputLimit(source: string): Diagnostic[];
102
+ export declare function finish(format: Format, family: string, plan: NativePlan, diagnostics: Diagnostic[], ids: Ids): ImportResult;
103
+ /** Only an explicit hex color is accepted. No CSS, URL, or Graphviz colorscheme interpretation. */
104
+ export declare function hex(value: string | undefined): string | undefined;
105
+ export declare function applyColor(plan: NativePlan, o: NativeObject, fill?: string, stroke?: string, ink?: string): void;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Tested against mermaid 12.2.0. Uses its internal DB behind a narrow, checked boundary.
3
+ * This file parses only; it neither renders Mermaid nor attaches interaction callbacks.
4
+ * Call in an isolated Node worker with a DOM, or in a dedicated browser Mermaid instance.
5
+ */
6
+ export declare const MERMAID_VERSION: "12.2.0";
7
+ export type ParserDiagnostic = {
8
+ code: string;
9
+ severity: 'warning' | 'error';
10
+ message: string;
11
+ line?: number;
12
+ column?: number;
13
+ locationKind?: 'source' | 'parser-relative';
14
+ };
15
+ export type FlowVertex = {
16
+ id: string;
17
+ text: string;
18
+ type?: string;
19
+ labelType: string;
20
+ classes: string[];
21
+ styles: string[];
22
+ link?: string;
23
+ icon?: string;
24
+ img?: string;
25
+ props?: Record<string, unknown>;
26
+ };
27
+ export type FlowEdge = {
28
+ start: string;
29
+ end: string;
30
+ text: string;
31
+ type?: string;
32
+ stroke?: string;
33
+ id?: string;
34
+ isUserDefinedId: boolean;
35
+ labelType: string;
36
+ classes: string[];
37
+ style: string[];
38
+ length?: number;
39
+ interpolate?: string;
40
+ animate?: boolean;
41
+ animation?: string;
42
+ };
43
+ export type FlowGroup = {
44
+ id: string;
45
+ title: string;
46
+ nodes: string[];
47
+ dir?: string;
48
+ labelType: string;
49
+ classes: string[];
50
+ metadata?: Record<string, unknown>;
51
+ };
52
+ export type FlowClass = {
53
+ id: string;
54
+ styles: string[];
55
+ textStyles: string[];
56
+ };
57
+ export type FlowSnapshot = {
58
+ format: 'mermaid';
59
+ family: 'flowchart';
60
+ parserVersion: typeof MERMAID_VERSION;
61
+ direction: string;
62
+ vertices: FlowVertex[];
63
+ edges: FlowEdge[];
64
+ groups: FlowGroup[];
65
+ classes: FlowClass[];
66
+ defaultEdgeStyle: string[];
67
+ defaultEdgeInterpolate?: string;
68
+ };
69
+ /** One entry of Mermaid's ordered sequence log; `kind` is its LINETYPE name. */
70
+ export type SequenceEvent = {
71
+ kind: string;
72
+ from?: string;
73
+ to?: string;
74
+ text: string;
75
+ placement?: 'left' | 'right' | 'over';
76
+ central: boolean;
77
+ };
78
+ export type SequenceActor = {
79
+ id: string;
80
+ name: string;
81
+ type: string;
82
+ box?: number;
83
+ links: string[];
84
+ };
85
+ export type SequenceBox = {
86
+ name?: string;
87
+ fill?: string;
88
+ };
89
+ export type SequenceSnapshot = {
90
+ format: 'mermaid';
91
+ family: 'sequence';
92
+ parserVersion: typeof MERMAID_VERSION;
93
+ title?: string;
94
+ actors: SequenceActor[];
95
+ boxes: SequenceBox[];
96
+ events: SequenceEvent[];
97
+ created: string[];
98
+ destroyed: string[];
99
+ };
100
+ export type ParseFlowResult = {
101
+ ok: true;
102
+ snapshot: FlowSnapshot | SequenceSnapshot;
103
+ diagnostics: ParserDiagnostic[];
104
+ } | {
105
+ ok: false;
106
+ diagnostics: ParserDiagnostic[];
107
+ };
108
+ type MermaidApi = Pick<(typeof import('mermaid'))['default'], 'initialize' | 'mermaidAPI'>;
109
+ /** DB strings contain Mermaid entity sentinels; preserve entity spelling for text decoding. */
110
+ export declare function restoreEntitySpelling(value: string): string;
111
+ /**
112
+ * Use an unattached HTML template only. Its content is inert and is never adopted into the page.
113
+ * Caller supplies the browser document or the dedicated worker's JSDOM document.
114
+ * Markdown markers deliberately remain visible; native Markdown rendering is not assumed.
115
+ */
116
+ export declare function makePlainLabel(document: Document): (value: string) => string;
117
+ export declare function preflightMermaidFlow(source: string): ParserDiagnostic[];
118
+ /** Each factory owns a serialized queue because Mermaid maintains parser/configuration state. */
119
+ export declare function createMermaidFlowParser(load: () => Promise<MermaidApi>): (source: string) => Promise<ParseFlowResult>;
120
+ export {};
@@ -0,0 +1,4 @@
1
+ import { type ImportResult } from './import-core';
2
+ import { type ParseFlowResult } from './mermaid-facade';
3
+ /** Convert a checked Mermaid snapshot into valid native source. */
4
+ export declare function importMermaidFlow(parsed: ParseFlowResult, plainText: (value: string) => string, title?: string): ImportResult;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Mermaid `sequenceDiagram` -> native source. Participants become nodes and messages become edges
3
+ * in file order. Native sequences have no fragments, so each top-level branch of a block becomes
4
+ * a phase band, and the warning says that the branch logic is gone.
5
+ */
6
+ import { type Diagnostic, type ImportResult } from './import-core';
7
+ import type { SequenceSnapshot } from './mermaid-facade';
8
+ export declare function mapMermaidSequence(snapshot: SequenceSnapshot, plainText: (value: string) => string, title: string, diagnostics: Diagnostic[]): ImportResult;
@@ -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;