@draftably/markdown 0.2.3 → 0.2.4
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/dist/chunks/mermaid-importer-S5o6DWXk.js +4381 -0
- package/dist/mermaid.js +1 -1
- package/dist/types/src/dsl/compile.d.ts +2 -0
- package/dist/types/src/dsl/sequence-layout.d.ts +87 -0
- package/dist/types/src/dsl/syntax.d.ts +8 -2
- package/dist/types/src/engines/layout/arrange.d.ts +36 -0
- package/dist/types/src/engines/layout/compute.d.ts +7 -0
- package/dist/types/src/engines/layout/forces.d.ts +8 -0
- package/dist/types/src/engines/layout/grid.d.ts +10 -0
- package/dist/types/src/engines/layout/intent.d.ts +14 -0
- package/dist/types/src/engines/layout/layered.d.ts +5 -0
- package/dist/types/src/engines/layout/objective.d.ts +6 -0
- package/dist/types/src/engines/layout/packing.d.ts +7 -0
- package/dist/types/src/engines/layout/report.d.ts +7 -0
- package/dist/types/src/engines/layout/scene.d.ts +53 -0
- package/dist/types/src/engines/layout/seed.d.ts +3 -0
- package/dist/types/src/engines/layout/separation.d.ts +17 -0
- package/dist/types/src/engines/layout/settings.d.ts +6 -0
- package/dist/types/src/engines/layout/topology.d.ts +18 -0
- package/dist/types/src/engines/layout/trees.d.ts +8 -0
- package/dist/types/src/engines/layout/types.d.ts +133 -0
- package/dist/types/src/engines/layout/util.d.ts +19 -0
- package/dist/types/src/engines/layout-engine.d.ts +15 -0
- package/dist/types/src/engines/routing/compute.d.ts +6 -0
- package/dist/types/src/engines/routing/conflicts.d.ts +36 -0
- package/dist/types/src/engines/routing/context.d.ts +37 -0
- package/dist/types/src/engines/routing/cost.d.ts +13 -0
- package/dist/types/src/engines/routing/doglegs.d.ts +16 -0
- package/dist/types/src/engines/routing/find.d.ts +6 -0
- package/dist/types/src/engines/routing/geometry.d.ts +24 -0
- package/dist/types/src/engines/routing/heap.d.ts +20 -0
- package/dist/types/src/engines/routing/improve.d.ts +7 -0
- package/dist/types/src/engines/routing/nudge.d.ts +7 -0
- package/dist/types/src/engines/routing/paths.d.ts +8 -0
- package/dist/types/src/engines/routing/planned.d.ts +7 -0
- package/dist/types/src/engines/routing/ports.d.ts +10 -0
- package/dist/types/src/engines/routing/repair.d.ts +9 -0
- package/dist/types/src/engines/routing/score.d.ts +12 -0
- package/dist/types/src/engines/routing/search.d.ts +16 -0
- package/dist/types/src/engines/routing/settings.d.ts +4 -0
- package/dist/types/src/engines/routing/sidepairs.d.ts +20 -0
- package/dist/types/src/engines/routing/tidy-ports.d.ts +13 -0
- package/dist/types/src/engines/routing/tidy.d.ts +10 -0
- package/dist/types/src/engines/routing/tuning.d.ts +9 -0
- package/dist/types/src/engines/routing/types.d.ts +157 -0
- package/dist/types/src/engines/routing-engine.d.ts +20 -0
- package/dist/types/src/import/import-core.d.ts +5 -0
- package/dist/types/src/import/mermaid-sequence.d.ts +1 -1
- package/dist/types/src/model/appearance.d.ts +10 -1
- package/dist/types/src/model/labels.d.ts +23 -0
- package/dist/types/src/model/markers.d.ts +7 -0
- package/dist/types/src/model/note.d.ts +11 -2
- package/dist/types/src/model/routes.d.ts +5 -3
- package/dist/types/src/model/status.d.ts +18 -0
- package/dist/types/src/model/types.d.ts +20 -1
- package/package.json +2 -2
- package/dist/chunks/mermaid-importer-DcseMRou.js +0 -4157
package/dist/mermaid.js
CHANGED
|
@@ -61,7 +61,7 @@ async function S() {
|
|
|
61
61
|
globalThis.fetch = async () => {
|
|
62
62
|
throw Error("Mermaid resource loading is disabled.");
|
|
63
63
|
};
|
|
64
|
-
const { JSDOM: i } = await import("jsdom"), { createMermaidFlowParser: s, makePlainLabel: e } = await import("./chunks/mermaid-facade-BoLWBerE.js"), { importMermaidFlow: t } = await import("./chunks/mermaid-importer-
|
|
64
|
+
const { JSDOM: i } = await import("jsdom"), { createMermaidFlowParser: s, makePlainLabel: e } = await import("./chunks/mermaid-facade-BoLWBerE.js"), { importMermaidFlow: t } = await import("./chunks/mermaid-importer-S5o6DWXk.js"), r = new i("<!doctype html><html><body></body></html>", {
|
|
65
65
|
url: "https://import.invalid/"
|
|
66
66
|
});
|
|
67
67
|
Object.assign(globalThis, {
|
|
@@ -49,6 +49,8 @@ export interface SceneEdge extends ModelEdge {
|
|
|
49
49
|
plan?: Planned;
|
|
50
50
|
/** A sequence message: the height of its row; it is drawn straight between lifelines there. */
|
|
51
51
|
row?: number;
|
|
52
|
+
/** A message between distant lanes: the middle of the gap its label sits in. */
|
|
53
|
+
labelX?: number;
|
|
52
54
|
}
|
|
53
55
|
export interface Scene {
|
|
54
56
|
model: Model;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The arithmetic of a sequence diagram's layout, apart from the scene it is applied to: where a
|
|
3
|
+
* label that spans several lanes sits, where each lane stands, and how tall each phase is.
|
|
4
|
+
* `sequenced` in `compile.ts` measures the text and calls these.
|
|
5
|
+
*/
|
|
6
|
+
/** A lower bound on a lane's centre: at least `room` past the centre of lane `from`. */
|
|
7
|
+
export type Hold = {
|
|
8
|
+
from: number;
|
|
9
|
+
room: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The gap a distant message's label sits in, so it crosses no lifeline between its two ends.
|
|
13
|
+
* `base` holds the lane centres that the headers alone give. The choice prefers a gap inside one
|
|
14
|
+
* band, so the label covers no band's border, then a gap that already has room, then the gap
|
|
15
|
+
* nearest the middle of the message, then the left one. Returns the left lane of the gap.
|
|
16
|
+
*/
|
|
17
|
+
export declare function labelSlot(base: number[], a: number, b: number, room: number, across: (lane: number) => boolean): number;
|
|
18
|
+
/**
|
|
19
|
+
* Lane centres from left to right: each lane takes the header gap from its neighbour, or what
|
|
20
|
+
* holds it away from an earlier lane, if that is more.
|
|
21
|
+
*/
|
|
22
|
+
export declare function laneCentres(first: number, gaps: number[], holds: Hold[][]): number[];
|
|
23
|
+
/** What one event draws round its row: how far above it and how far below. */
|
|
24
|
+
export type EventInk = {
|
|
25
|
+
id: string;
|
|
26
|
+
/** The phase that lists the event, if one does. */
|
|
27
|
+
phase?: string;
|
|
28
|
+
/** Height of the label above the line; 0 with no label or for a self-message. */
|
|
29
|
+
label: number;
|
|
30
|
+
/** Ink above and below the row. */
|
|
31
|
+
above: number;
|
|
32
|
+
below: number;
|
|
33
|
+
/** A self-message or a local action: the row after it must clear its ink. */
|
|
34
|
+
tall: boolean;
|
|
35
|
+
/** How far the event runs on down its lifeline, which the next row starts from. */
|
|
36
|
+
drop: number;
|
|
37
|
+
};
|
|
38
|
+
export type RowRules = {
|
|
39
|
+
/** Least distance between two rows. */
|
|
40
|
+
row: number;
|
|
41
|
+
/** Room between a tall event's ink and the next event's ink. */
|
|
42
|
+
clear: number;
|
|
43
|
+
/** Room between a phase band's edge and the ink inside it. */
|
|
44
|
+
pad: number;
|
|
45
|
+
/** Room between two phase bands. */
|
|
46
|
+
gap: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Rows from top to bottom, starting under the headers at `top`. A phase is one block: its band
|
|
50
|
+
* starts `gap` under what came before, holds its events with `pad` round them, and is at least
|
|
51
|
+
* as tall as its title needs. Events outside every phase keep the plain row rule.
|
|
52
|
+
*/
|
|
53
|
+
export declare function eventRows(events: EventInk[], top: number, titleHeight: (phase: string) => number, rules: RowRules): {
|
|
54
|
+
rows: Map<string, number>;
|
|
55
|
+
bands: Map<string, {
|
|
56
|
+
y: number;
|
|
57
|
+
h: number;
|
|
58
|
+
}>;
|
|
59
|
+
end: number;
|
|
60
|
+
};
|
|
61
|
+
/** An event as activation bars read it: who sends to whom, its kind, and what it answers. */
|
|
62
|
+
export type SequenceEvent = {
|
|
63
|
+
id: string;
|
|
64
|
+
source: string;
|
|
65
|
+
target: string;
|
|
66
|
+
message?: string;
|
|
67
|
+
replyTo?: string;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* A stretch in which a participant is at work on a call: from the event at index `start` to
|
|
71
|
+
* the one at `end`, or a short stub when `end` is unset. `level` is 0, or more when the
|
|
72
|
+
* participant took the call while another of its bars was open.
|
|
73
|
+
*/
|
|
74
|
+
export type ActivationSpan = {
|
|
75
|
+
lane: string;
|
|
76
|
+
call: string;
|
|
77
|
+
start: number;
|
|
78
|
+
end?: number;
|
|
79
|
+
level: number;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* The activation bars of a sequence, read from its calls and their replies. A bar opens where a
|
|
83
|
+
* participant receives a `call` from another and closes at the last reply that answers that
|
|
84
|
+
* call. A call with no reply closes at the participant's next message to another, and without
|
|
85
|
+
* one it is a stub. A call a participant sends to itself opens no bar.
|
|
86
|
+
*/
|
|
87
|
+
export declare function activationSpans(events: SequenceEvent[]): ActivationSpan[];
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* keeps every comment and unrelated statement.
|
|
7
7
|
*/
|
|
8
8
|
import { type DiagramAppearance, type Shade } from '../model/appearance';
|
|
9
|
-
import { type EndMarker } from '../model/markers';
|
|
9
|
+
import { type EndMarker, type MessageKind } from '../model/markers';
|
|
10
10
|
import type { Status } from '../model/status';
|
|
11
11
|
import type { ColorKey, LayoutAlgorithmId, LayoutSettings, PortSide, RoutingSettings, ShapeKind } from '../model/types';
|
|
12
12
|
export declare class DslError extends Error {
|
|
@@ -131,9 +131,13 @@ export interface ModelEdge {
|
|
|
131
131
|
tail?: EndMarker;
|
|
132
132
|
/** `constraint=false`: drawn and routed, but layout doesn't rank or order by it. */
|
|
133
133
|
constraint?: false;
|
|
134
|
+
/** Sequence diagrams: `message=`, or `action` for an `action` line. */
|
|
135
|
+
message?: MessageKind;
|
|
136
|
+
/** `answers=`: the earlier message a reply answers. */
|
|
137
|
+
replyTo?: string;
|
|
134
138
|
line: number;
|
|
135
139
|
}
|
|
136
|
-
/** A layout engine run cold over a scope's subtree; see `src/engines/layout-engine.
|
|
140
|
+
/** A layout engine run cold over a scope's subtree; see `src/engines/layout-engine.ts`. */
|
|
137
141
|
export interface EngineRecipe {
|
|
138
142
|
algorithm: LayoutAlgorithmId;
|
|
139
143
|
params: Partial<LayoutSettings>;
|
|
@@ -160,6 +164,8 @@ export interface ModelLayout {
|
|
|
160
164
|
/** With `unit`: the width of one unit, and whether unit numbers run above the first row. */
|
|
161
165
|
unitWidth?: number;
|
|
162
166
|
ruler?: boolean;
|
|
167
|
+
/** `sequence` only: draw a bar on a participant's lifeline while it is at work on a call. */
|
|
168
|
+
activations?: true;
|
|
163
169
|
/** `flow` only: whether a long run of ranks folds into bands. Engines take `fold` as a param. */
|
|
164
170
|
fold: 'auto' | 'never';
|
|
165
171
|
/** Root only: the image shape to aim for; compile tries direction and folding to get closest. */
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DiagramEdge, Direction } from '../../model/types.ts';
|
|
2
|
+
import type { Scene } from './scene.ts';
|
|
3
|
+
import type { Centres, Item, LayoutIntent, Point, Rect, Topology } from './types.ts';
|
|
4
|
+
/** A link with an end outside the solve, or between two of its items: `a` and `b` are the items that own its ends. */
|
|
5
|
+
export interface BoundaryLink extends DiagramEdge {
|
|
6
|
+
a: string | null;
|
|
7
|
+
b: string | null;
|
|
8
|
+
}
|
|
9
|
+
/** What one solve of one container's children shares with its force, separation and packing steps. */
|
|
10
|
+
export interface Batch {
|
|
11
|
+
parentId: string | null;
|
|
12
|
+
direction: Direction;
|
|
13
|
+
items: Item[];
|
|
14
|
+
byId: Map<string, Item>;
|
|
15
|
+
t: Topology;
|
|
16
|
+
localIntent: LayoutIntent;
|
|
17
|
+
boundaryLinks: BoundaryLink[];
|
|
18
|
+
/** Hop counts, for the stress solve only. */
|
|
19
|
+
distances: Map<string, Map<string, number>> | null;
|
|
20
|
+
target: Centres | null;
|
|
21
|
+
/** The inside of the parent's frame, or null at the top level. */
|
|
22
|
+
container: Rect | null;
|
|
23
|
+
availableAspect: number;
|
|
24
|
+
/** Each item's centre when the solve began. */
|
|
25
|
+
origin: Centres;
|
|
26
|
+
anchor: number;
|
|
27
|
+
baseCenter: Point;
|
|
28
|
+
pairGap(a: Item, b: Item): number;
|
|
29
|
+
/** Copies the document's positions back onto the items. */
|
|
30
|
+
sync(): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Solves the children of one container: builds the target for the chosen algorithm, runs the
|
|
34
|
+
* force ticks, and keeps the best state by collisions first and energy second.
|
|
35
|
+
*/
|
|
36
|
+
export declare function arrange(scene: Scene, activeIds: string[], parentId: string | null, direction: Direction): Promise<void>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Diagram } from '../../model/types.ts';
|
|
2
|
+
import type { LayoutOptions, LayoutResult } from './types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Lays out a copy of `input`. A pass moves boxes at most `maxMove` from where they are; a rebuild
|
|
5
|
+
* starts from a seed. Pins, fixed frames and the scope bound what may move.
|
|
6
|
+
*/
|
|
7
|
+
export declare function compute(input: Diagram, opts?: LayoutOptions): Promise<LayoutResult>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Batch } from './arrange.ts';
|
|
2
|
+
import type { Scene } from './scene.ts';
|
|
3
|
+
/** The force on each item for one tick, by ID; `degree` is the weight of the links behind it. */
|
|
4
|
+
export declare function tickForces(scene: Scene, batch: Batch): Map<string, {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
degree: number;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Centres, Item, Rect, Settings } from './types.ts';
|
|
2
|
+
/** Items in ID order on a grid of even cells, near the wanted aspect. */
|
|
3
|
+
export declare function seedGrid(items: Item[], s: Settings, aspect: number): Centres;
|
|
4
|
+
/** The nearest free cell of a grid round the current centre, closest matches first. */
|
|
5
|
+
export declare function gridTarget(items: Item[], s: Settings, aspect: number): Centres;
|
|
6
|
+
/**
|
|
7
|
+
* Shifts a target onto the drawing: onto the container's corner, the mean of the fixed items, a
|
|
8
|
+
* fixed origin for a rebuild (`canonical`), or else the items' current centre.
|
|
9
|
+
*/
|
|
10
|
+
export declare function alignTarget(map: Centres, items: Item[], container: Rect | null, canonical?: boolean): Centres;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IntentPlacement, IntentRole } from '../../model/types.ts';
|
|
2
|
+
import type { Centres, Item, LayoutIntent } from './types.ts';
|
|
3
|
+
export type Hint = {
|
|
4
|
+
id: string;
|
|
5
|
+
placement: IntentPlacement;
|
|
6
|
+
};
|
|
7
|
+
/** The hints of an intent with their roles, in the order the intent holds them. */
|
|
8
|
+
export declare const hintsOf: (intent: LayoutIntent) => Array<[IntentRole, Hint]>;
|
|
9
|
+
/** Where in the drawing's box each placement puts a shape, as fractions of its free width and height. */
|
|
10
|
+
export declare const placements: Record<IntentPlacement, [number, number]>;
|
|
11
|
+
/** A checked start and end hint. Throws on an unknown shape, an unknown placement, or one shape in both roles. */
|
|
12
|
+
export declare function normalizeIntent(raw?: unknown, validIds?: Set<string> | null): LayoutIntent;
|
|
13
|
+
/** The centre each hinted item should reach, inside the items' current box. */
|
|
14
|
+
export declare function hintTargets(items: Item[], intent: LayoutIntent): Centres;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Centres, Item, Settings, Topology } from './types.ts';
|
|
2
|
+
/** Straight centre-to-centre crossings between a candidate placement's edges. */
|
|
3
|
+
export declare function sketchCrossings(t: Topology, map: Centres): number;
|
|
4
|
+
/** Ranks as columns (or rows), ordered by barycentre sweeps, folded into bands when that fits the aspect better. */
|
|
5
|
+
export declare function layeredTarget(items: Item[], t: Topology, s: Settings, aspect: number): Centres;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Centres, Item, Settings, Topology } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The energy a solve lowers: hint and target errors, link lengths by algorithm, overlap area and
|
|
4
|
+
* forward links that run backwards. `compoundEnergy` adds the cross-boundary links of a compound solve.
|
|
5
|
+
*/
|
|
6
|
+
export declare function objective(items: Item[], t: Topology, s: Settings, distances: Map<string, Map<string, number>> | null, target: Centres | null, compoundEnergy: (() => number) | null): number;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Batch } from './arrange.ts';
|
|
2
|
+
import type { Scene } from './scene.ts';
|
|
3
|
+
/**
|
|
4
|
+
* After a rebuild that left overlaps inside a fixed frame: place the movable items one at a time
|
|
5
|
+
* at the free spot nearest their target, in up to four orders. Moves them only when one order fits.
|
|
6
|
+
*/
|
|
7
|
+
export declare function packIntoFrame(scene: Scene, batch: Batch, collisions: number): void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Scene } from './scene.ts';
|
|
2
|
+
import type { LayoutResult, LayoutScope } from './types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Ends a run: holds each move to the pass limit and rounds it, rejects a pass that added
|
|
5
|
+
* overlaps, writes the settings back, and builds the report.
|
|
6
|
+
*/
|
|
7
|
+
export declare function finish(scene: Scene, scope: LayoutScope, started: number, authoredRootId: string): LayoutResult;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { DiagramGroup, DiagramNode, Direction, NodeLayout } from '../../model/types.ts';
|
|
2
|
+
import type { Diagram, LayoutMetrics, LayoutOptions, Settings, SolverStop, TraceFrame } from './types.ts';
|
|
3
|
+
/** A shape or group ID, or nothing for the top level. */
|
|
4
|
+
export type ParentId = string | null | undefined;
|
|
5
|
+
/** Counters and findings that every solve of one layout run adds to. */
|
|
6
|
+
export interface Run {
|
|
7
|
+
batchCount: number;
|
|
8
|
+
totalIterations: number;
|
|
9
|
+
/** Which hierarchy sweep is running; odd sweeps of a compound layout go top down. */
|
|
10
|
+
hierarchyPhase: number;
|
|
11
|
+
stops: SolverStop[];
|
|
12
|
+
warnings: Set<string>;
|
|
13
|
+
/** Containers whose children a rebuild has already placed from a seed. */
|
|
14
|
+
seeded: Set<string | null>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* One layout run's view of the document: the hierarchy, what is fixed or hidden, and the only
|
|
18
|
+
* ways a solve may move or measure boxes. `doc` is the copy the run changes; `original` keeps the
|
|
19
|
+
* geometry it started from.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createScene(input: Diagram, doc: Diagram, s: Settings, opts: LayoutOptions): {
|
|
22
|
+
doc: Diagram;
|
|
23
|
+
original: Record<string, NodeLayout>;
|
|
24
|
+
nodeIndex: Map<string, number>;
|
|
25
|
+
s: Settings;
|
|
26
|
+
opts: LayoutOptions;
|
|
27
|
+
run: Run;
|
|
28
|
+
aspect: number;
|
|
29
|
+
intent: Partial<Record<import("../../model/types.ts").IntentRole, {
|
|
30
|
+
id: string;
|
|
31
|
+
placement: import("../../model/types.ts").IntentPlacement;
|
|
32
|
+
}>>;
|
|
33
|
+
compound: boolean;
|
|
34
|
+
globalTopology: import("./types.ts").Topology<import("../../model/types.ts").DiagramEdge>;
|
|
35
|
+
groups: Map<string, DiagramGroup>;
|
|
36
|
+
entities: Map<string, DiagramNode | DiagramGroup>;
|
|
37
|
+
pos: Record<string, NodeLayout>;
|
|
38
|
+
child: (id: ParentId) => (DiagramNode | DiagramGroup)[];
|
|
39
|
+
parent: (id: string) => string | undefined;
|
|
40
|
+
inheritedDirection: (id: ParentId) => Direction;
|
|
41
|
+
descend: (id: string) => string[];
|
|
42
|
+
branch: (id: ParentId) => boolean;
|
|
43
|
+
fixed: (id: string) => boolean;
|
|
44
|
+
visible: (id: string) => boolean;
|
|
45
|
+
padded: (id: string) => NodeLayout;
|
|
46
|
+
move: (id: string, dx: number, dy: number) => void;
|
|
47
|
+
resizeAuto: (id: string) => void;
|
|
48
|
+
metrics: () => LayoutMetrics;
|
|
49
|
+
before: LayoutMetrics;
|
|
50
|
+
trace: TraceFrame[];
|
|
51
|
+
captureTrace: (phase: string, force?: boolean) => void;
|
|
52
|
+
};
|
|
53
|
+
export type Scene = ReturnType<typeof createScene>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Batch } from './arrange.ts';
|
|
2
|
+
import type { Scene } from './scene.ts';
|
|
3
|
+
import type { Axis, Item } from './types.ts';
|
|
4
|
+
/**
|
|
5
|
+
* The guarded moves of one solve: a move that keeps an item in its frame and inside the pass's
|
|
6
|
+
* movement limit, the room an item has along one axis, and the pairwise pass that pushes
|
|
7
|
+
* overlapping items apart.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createSeparation(scene: Scene, batch: Batch): {
|
|
10
|
+
constrainedMove: (p: Item, dx: number, dy: number) => void;
|
|
11
|
+
axisCapacity: (p: Item, axis: Axis, sign: number) => number;
|
|
12
|
+
separate: (rounds?: number) => void;
|
|
13
|
+
collisions: () => {
|
|
14
|
+
n: number;
|
|
15
|
+
a: number;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { LayoutSettings } from '../../model/types.ts';
|
|
2
|
+
import type { LayoutAlgorithm } from './types.ts';
|
|
3
|
+
export declare const ALGORITHMS: LayoutAlgorithm[];
|
|
4
|
+
export declare const defaults: LayoutSettings;
|
|
5
|
+
/** Checked settings: defaults under `values`, old names mapped, numbers held to their ranges. */
|
|
6
|
+
export declare function settings(values?: object): LayoutSettings;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LayoutIntent, Link, Settings, Topology } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The link structure of one solve: neighbours, feedback links, longest-path ranks and connected
|
|
4
|
+
* parts. Links stay as given; a feedback link is only left out of the ranks.
|
|
5
|
+
*/
|
|
6
|
+
export declare function topology<E extends Link>(items: Array<{
|
|
7
|
+
id: string;
|
|
8
|
+
}>, edges: E[], intent?: LayoutIntent): Topology<E>;
|
|
9
|
+
/** Hop counts between every pair of items that links join. */
|
|
10
|
+
export declare function shortestPaths(t: Topology): Map<string, Map<string, number>>;
|
|
11
|
+
export interface Forest {
|
|
12
|
+
roots: string[];
|
|
13
|
+
parent: Map<string, string>;
|
|
14
|
+
kids: Map<string, string[]>;
|
|
15
|
+
depth: Map<string, number>;
|
|
16
|
+
}
|
|
17
|
+
/** A breadth-first spanning forest: from the chosen root, then every source, then the rest. */
|
|
18
|
+
export declare function forest(t: Topology, s: Settings): Forest;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Centres, Item, Link, Settings, Topology } from './types.ts';
|
|
2
|
+
/** A span-based tree: each subtree gets its own width and parents sit over their children. */
|
|
3
|
+
export declare function treeTarget(items: Item[], t: Topology, s: Settings): Centres;
|
|
4
|
+
/** Rings round each root by depth. No solve reaches it: see `Settings`. */
|
|
5
|
+
export declare function radialTarget(items: Item[], t: Topology, s: Settings): Centres;
|
|
6
|
+
export declare function bilateralTarget(items: Item[], t: Topology, s: Settings): Centres | null;
|
|
7
|
+
/** Which way a forward link should run: 1, -1 on the far side of a centred start, 0 across it. */
|
|
8
|
+
export declare function forwardSign(t: Topology, e: Link): number;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { Diagram, Direction, IntentPlacement, LayoutAlgorithmId, LayoutIntent, LayoutSettings, NodeGeometry, NodeLayout, Point, Rect } from '../../model/types.ts';
|
|
2
|
+
export type LayoutSettingKey = 'boundaryPull' | 'hierarchySweeps' | 'groupGap' | 'rankGap' | 'edgeLength' | 'repulsion' | 'flowStrength' | 'alignment' | 'compactness' | 'gridStrength' | 'ordering' | 'fold' | 'rootId';
|
|
3
|
+
export interface LayoutAlgorithm {
|
|
4
|
+
id: LayoutAlgorithmId;
|
|
5
|
+
name: string;
|
|
6
|
+
family: string;
|
|
7
|
+
short: string;
|
|
8
|
+
detail: string;
|
|
9
|
+
controls: LayoutSettingKey[];
|
|
10
|
+
}
|
|
11
|
+
export interface LayoutMetrics {
|
|
12
|
+
overlaps: number;
|
|
13
|
+
overlapArea: number;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
aspect: number;
|
|
17
|
+
area: number;
|
|
18
|
+
linkLength: number;
|
|
19
|
+
}
|
|
20
|
+
export type LayoutScope = 'all' | 'selection' | 'neighbourhood' | 'container';
|
|
21
|
+
export interface LayoutOptions extends Partial<LayoutSettings> {
|
|
22
|
+
scope?: LayoutScope;
|
|
23
|
+
containerId?: string;
|
|
24
|
+
selected?: string[];
|
|
25
|
+
fixedIds?: string[];
|
|
26
|
+
viewport?: {
|
|
27
|
+
w: number;
|
|
28
|
+
h: number;
|
|
29
|
+
};
|
|
30
|
+
warmStart?: boolean;
|
|
31
|
+
settle?: boolean;
|
|
32
|
+
maxIterations?: number;
|
|
33
|
+
trace?: boolean;
|
|
34
|
+
rebuild?: boolean;
|
|
35
|
+
/** Travel per tick below which a settling solve counts the tick as quiet; 0.08 when unset. */
|
|
36
|
+
tolerance?: number;
|
|
37
|
+
/** False restores the v7 order within ranks: a rebuild never keeps the authored order. */
|
|
38
|
+
orderPrior?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export type Termination = 'settled' | 'objective plateau' | 'iteration limit' | 'bounded pass';
|
|
41
|
+
/** Why one solve of one container's children stopped. */
|
|
42
|
+
export interface SolverStop {
|
|
43
|
+
parentId: string | null;
|
|
44
|
+
iterations: number;
|
|
45
|
+
reason: Exclude<Termination, 'bounded pass'>;
|
|
46
|
+
}
|
|
47
|
+
export interface LayoutReport {
|
|
48
|
+
intent: Array<{
|
|
49
|
+
role: string;
|
|
50
|
+
id: string;
|
|
51
|
+
placement: IntentPlacement;
|
|
52
|
+
error: number;
|
|
53
|
+
satisfied: boolean;
|
|
54
|
+
pinned: boolean;
|
|
55
|
+
}>;
|
|
56
|
+
backwardEdges: number;
|
|
57
|
+
directedEdges: number;
|
|
58
|
+
feedbackEdges: number;
|
|
59
|
+
algorithm: LayoutAlgorithmId;
|
|
60
|
+
name: string;
|
|
61
|
+
mode: 'pass' | 'rebuild' | 'journey';
|
|
62
|
+
scope: LayoutScope;
|
|
63
|
+
moved: number;
|
|
64
|
+
maxDisplacement: number;
|
|
65
|
+
rmsDisplacement: number;
|
|
66
|
+
movementLimit: number | null;
|
|
67
|
+
iterations: number;
|
|
68
|
+
batches: number;
|
|
69
|
+
before: LayoutMetrics;
|
|
70
|
+
after: LayoutMetrics;
|
|
71
|
+
warnings: string[];
|
|
72
|
+
milliseconds: number;
|
|
73
|
+
deterministic: boolean;
|
|
74
|
+
termination: Termination;
|
|
75
|
+
solverStops: SolverStop[];
|
|
76
|
+
/** Added by the app: where the computation ran. */
|
|
77
|
+
thread?: string;
|
|
78
|
+
/** Added by the app when a timeline step is kept. */
|
|
79
|
+
selectedStep?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface TraceFrame {
|
|
82
|
+
nodes: NodeGeometry;
|
|
83
|
+
iteration: number;
|
|
84
|
+
phase: string;
|
|
85
|
+
metrics: LayoutMetrics;
|
|
86
|
+
}
|
|
87
|
+
export interface LayoutResult {
|
|
88
|
+
document: Diagram;
|
|
89
|
+
report: LayoutReport;
|
|
90
|
+
trace?: TraceFrame[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Settings inside a solve. `radial` is an old name that `settings` maps to `tree`, so no solve
|
|
94
|
+
* runs with it; the radial target and its branches stay as the original engine had them.
|
|
95
|
+
*/
|
|
96
|
+
export interface Settings extends Omit<LayoutSettings, 'algorithm'> {
|
|
97
|
+
algorithm: LayoutAlgorithmId | 'radial';
|
|
98
|
+
}
|
|
99
|
+
/** A box a solve places: a shape or a whole group, with its top-left corner and size. */
|
|
100
|
+
export type Item = Rect & {
|
|
101
|
+
id: string;
|
|
102
|
+
fixed?: boolean;
|
|
103
|
+
};
|
|
104
|
+
/** A link between two items of one solve. */
|
|
105
|
+
export interface Link {
|
|
106
|
+
from: string;
|
|
107
|
+
to: string;
|
|
108
|
+
directed?: boolean;
|
|
109
|
+
}
|
|
110
|
+
export interface Topology<E extends Link = Link> {
|
|
111
|
+
intent: LayoutIntent;
|
|
112
|
+
/** Item IDs, sorted. */
|
|
113
|
+
ids: string[];
|
|
114
|
+
index: Map<string, number>;
|
|
115
|
+
/** Directed neighbours out of, into, and (with undirected links) beside each item. */
|
|
116
|
+
out: Map<string, string[]>;
|
|
117
|
+
inc: Map<string, string[]>;
|
|
118
|
+
adj: Map<string, string[]>;
|
|
119
|
+
rank: Map<string, number>;
|
|
120
|
+
/** `from + '\0' + to` of each directed link that runs against the ranks. */
|
|
121
|
+
feedback: Set<string>;
|
|
122
|
+
edges: E[];
|
|
123
|
+
forward: E[];
|
|
124
|
+
components: string[][];
|
|
125
|
+
/** Source order of each item, when a rebuild keeps the authored order within ranks. */
|
|
126
|
+
declared?: Map<string, number>;
|
|
127
|
+
/** Which side of a centred start each item sits on: 1, -1, or 0 for the start. */
|
|
128
|
+
branchSides?: Map<string, number>;
|
|
129
|
+
}
|
|
130
|
+
/** Centre points by item ID. */
|
|
131
|
+
export type Centres = Map<string, Point>;
|
|
132
|
+
export type Axis = 'x' | 'y';
|
|
133
|
+
export type { Diagram, Direction, LayoutIntent, NodeLayout, Point, Rect };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Point, Rect } from './types.ts';
|
|
2
|
+
export declare const copy: <T>(x: T) => T;
|
|
3
|
+
export declare const clamp: (x: number, lo: number, hi: number) => number;
|
|
4
|
+
export declare const cmp: (a: string, b: string) => 0 | 1 | -1;
|
|
5
|
+
export declare const magnitude: (x: number, y: number) => number;
|
|
6
|
+
export declare const wait: () => Promise<unknown>;
|
|
7
|
+
export declare function bounds(items: Rect[]): Rect;
|
|
8
|
+
export declare const midpoint: (r: Rect) => Point;
|
|
9
|
+
/** How far two boxes, kept `gap` apart, reach into each other; null when they are clear. */
|
|
10
|
+
export interface Penetration {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
dx: number;
|
|
14
|
+
dy: number;
|
|
15
|
+
area: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function penetration(a: Rect, b: Rect, gap?: number): Penetration | null;
|
|
18
|
+
/** A fixed number in [0, 1) for an ID: FNV-1a. It stands in for a random start. */
|
|
19
|
+
export declare function hash(id: string): number;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { compute } from './layout/compute.ts';
|
|
2
|
+
import { normalizeIntent } from './layout/intent.ts';
|
|
3
|
+
import { settings } from './layout/settings.ts';
|
|
4
|
+
import { topology } from './layout/topology.ts';
|
|
5
|
+
export declare const LayoutLab: {
|
|
6
|
+
algorithms: import("./layout-engine.ts").LayoutAlgorithm[];
|
|
7
|
+
defaults: import("../model/types.ts").LayoutSettings;
|
|
8
|
+
settings: typeof settings;
|
|
9
|
+
compute: typeof compute;
|
|
10
|
+
normalizeIntent: typeof normalizeIntent;
|
|
11
|
+
placements: Record<import("../model/types.ts").IntentPlacement, [number, number]>;
|
|
12
|
+
topology: typeof topology;
|
|
13
|
+
};
|
|
14
|
+
export type { LayoutAlgorithm, LayoutMetrics, LayoutOptions, LayoutReport, LayoutResult, LayoutScope, LayoutSettingKey, SolverStop, Termination, TraceFrame, } from './layout/types.ts';
|
|
15
|
+
export type { Point } from '../model/types.ts';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RouteInput, RoutingOptions, RoutingResult } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Routes every edge between boxes that stay where they are: each edge in turn (locked ones and
|
|
4
|
+
* short ones first), then the improvement, repair, nudge and tidy passes unless `quick`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function compute(input: RouteInput, rawOptions?: RoutingOptions): RoutingResult;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Point, RoutingSettings } from './types.ts';
|
|
2
|
+
/** A routed line, as the pair checks read it: only its points. */
|
|
3
|
+
export type Line = {
|
|
4
|
+
points: Point[];
|
|
5
|
+
};
|
|
6
|
+
export interface Span {
|
|
7
|
+
/** Segment count. */
|
|
8
|
+
n: number;
|
|
9
|
+
h: Uint8Array;
|
|
10
|
+
lo: Float64Array;
|
|
11
|
+
hi: Float64Array;
|
|
12
|
+
at: Float64Array;
|
|
13
|
+
x0: number;
|
|
14
|
+
y0: number;
|
|
15
|
+
x1: number;
|
|
16
|
+
y1: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function spanOf(ps: Point[]): Span;
|
|
19
|
+
/** Flattens `used` for the checks below. False when it already was: the caller that got true calls `unflatten`. */
|
|
20
|
+
export declare function flatten(used: Line[]): boolean;
|
|
21
|
+
export declare const unflatten: (used: Line[]) => boolean;
|
|
22
|
+
export declare function parallelNear(a: Point, b: Point, c: Point, d: Point, gap: number): {
|
|
23
|
+
overlap: number;
|
|
24
|
+
separation: number;
|
|
25
|
+
deficit: number;
|
|
26
|
+
} | null;
|
|
27
|
+
export declare function parallelConflicts(points: Point[], used: Line[], gap: number): {
|
|
28
|
+
lanePairs: number;
|
|
29
|
+
laneDeficit: number;
|
|
30
|
+
minGap: number | null;
|
|
31
|
+
};
|
|
32
|
+
export declare function siblingDeficit(points: Point[], used: Line[], min: number, gap: number): number;
|
|
33
|
+
export declare function conflicts(points: Point[], used: Line[], bound?: number, s?: RoutingSettings): {
|
|
34
|
+
crossings: number;
|
|
35
|
+
shared: number;
|
|
36
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Box, NearBox, Obstacle, Point, Route, RouteEdge, RouteGroupInput, RouteInput, RouteMetrics, RoutingOptions, Side } from './types.ts';
|
|
2
|
+
/** The drawing as the passes change it. */
|
|
3
|
+
export interface RouteState {
|
|
4
|
+
routes: Route[];
|
|
5
|
+
/** Edges whose planned route was taken as it is: no pass moves them. */
|
|
6
|
+
fixedPlans: Set<string>;
|
|
7
|
+
}
|
|
8
|
+
export declare function gate(obs: Obstacle[], start: Point, fs: Side, end: Point, ts: Side): Obstacle[];
|
|
9
|
+
/**
|
|
10
|
+
* One routing run's view of the scene: the boxes and groups, the edges in routing order, the
|
|
11
|
+
* obstacles each edge sees, and the measures the passes compare drawings with.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createContext(input: RouteInput, rawOptions: RoutingOptions): {
|
|
14
|
+
rawOptions: RoutingOptions;
|
|
15
|
+
facingFans: boolean;
|
|
16
|
+
titleBands: boolean;
|
|
17
|
+
began: number;
|
|
18
|
+
s: import("./types.ts").RoutingSettings;
|
|
19
|
+
rects: Map<string, Box>;
|
|
20
|
+
groups: Map<string, RouteGroupInput>;
|
|
21
|
+
near: NearBox[];
|
|
22
|
+
ancestors: (id: string) => string[];
|
|
23
|
+
previous: Map<string, import("./types.ts").PriorRoute>;
|
|
24
|
+
edges: RouteEdge[];
|
|
25
|
+
state: RouteState;
|
|
26
|
+
opened: WeakSet<Route>;
|
|
27
|
+
syncOpen: () => void;
|
|
28
|
+
beyond: (id: string, other: string, side: Side) => boolean;
|
|
29
|
+
crowdedSide: (id: string, side: Side) => boolean;
|
|
30
|
+
flowOf: (e: RouteEdge) => "right" | "down" | undefined;
|
|
31
|
+
scores: WeakMap<Route, number>;
|
|
32
|
+
obsFor: (e: RouteEdge, open?: boolean) => Obstacle[];
|
|
33
|
+
metrics: (rs: Route[]) => RouteMetrics;
|
|
34
|
+
total: (rs: Route[]) => number;
|
|
35
|
+
far: (r: Route) => boolean;
|
|
36
|
+
};
|
|
37
|
+
export type Context = ReturnType<typeof createContext>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Line } from './conflicts.ts';
|
|
2
|
+
import type { NearBox, Point, RoutingSettings } from './types.ts';
|
|
3
|
+
export declare const STANDOFF_WEIGHT = 0.5, BORDER_WEIGHT = 2;
|
|
4
|
+
export declare function standoffCost(ps: Point[], near: NearBox[], bound?: number): number;
|
|
5
|
+
export declare function standoffSegment(a: Point, b: Point, near: NearBox[]): number;
|
|
6
|
+
/** Adds the grid lines a standoff band out from each box to `xs` and `ys`. */
|
|
7
|
+
export declare function standoffLines(near: NearBox[], xs: number[], ys: number[]): void;
|
|
8
|
+
export declare function ownCost(ps: Point[], s: RoutingSettings): number;
|
|
9
|
+
export declare function cost(ps: Point[], used: Line[], s: RoutingSettings, near?: NearBox[]): number;
|
|
10
|
+
export declare function costOf(ps: Point[], s: RoutingSettings, standoff: number, c: {
|
|
11
|
+
crossings: number;
|
|
12
|
+
shared: number;
|
|
13
|
+
}, laneDeficit: number): number;
|