umlimator 0.19.0 → 0.20.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 +32 -6
- package/lib/umlimator-all.js +7 -5
- package/lib/umlimator.d.ts +31 -3
- package/lib/umlimator.js +4 -2
- package/lib/umlimator.schema.json +117 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,6 +58,16 @@ drill-down, a data pipeline, an AI agent's skills, and host pages for embedding,
|
|
|
58
58
|
([`examples/bookshop-packages.json`](examples/bookshop-packages.json), [what it covers](docs/conformance/uml-package.md)).
|
|
59
59
|
Ownership is edited by dropping an element into a box, or with the Owner field; both are checked by their types'
|
|
60
60
|
rules, and the PDF's tables list slots and element kinds.
|
|
61
|
+
- **UML sequence and communication diagrams** (0.20.0): lifelines on a time axis with calls, async messages, replies,
|
|
62
|
+
creates and deletes, activation bars derived from the messages, `alt`, `opt`, `loop`, `par` and `break` frames with
|
|
63
|
+
their guards, and interaction uses ([`examples/checkout-sequence.json`](examples/checkout-sequence.json),
|
|
64
|
+
[what it covers](docs/conformance/uml-sequence.md)); the same interaction as lifelines joined by connectors, each
|
|
65
|
+
link's messages a stack of numbered rows (1, 1.1, 1.1.2) ([`examples/checkout-communication.json`](examples/checkout-communication.json),
|
|
66
|
+
[what it covers](docs/conformance/uml-communication.md)). Messages are inserted, moved in time, wrapped in a frame and
|
|
67
|
+
deleted on the canvas, by pointer and by key, each gesture an `edit` event; checked by the types' rules; a sequence
|
|
68
|
+
diagram is read from and written to Mermaid's `sequenceDiagram`, and an OpenTelemetry trace becomes one
|
|
69
|
+
(`umlimator.py trace --diagram uml.sequence`). The MCP server, the `map-repo` skill and the diff Action learn these
|
|
70
|
+
types in one package after 0.20.0; until then a reorder of a view's messages shows in a diff as changed, not moved.
|
|
61
71
|
- **Export**: any view as a stand-alone SVG or PNG, in the browser or from the CLI; the whole map as one PDF to hand in
|
|
62
72
|
for a review: a cover with the contents, each view with its legend and tables of its cards, lines and boxes, then the
|
|
63
73
|
rules (`umlimator.py pdf`).
|
|
@@ -80,7 +90,7 @@ drill-down, a data pipeline, an AI agent's skills, and host pages for embedding,
|
|
|
80
90
|
npm install umlimator
|
|
81
91
|
```
|
|
82
92
|
|
|
83
|
-
Or from GitHub, at a tag or any commit: `"umlimator": "github:zintaen/umlimator#v0.
|
|
93
|
+
Or from GitHub, at a tag or any commit: `"umlimator": "github:zintaen/umlimator#v0.20.0"`. npm 12 refuses git
|
|
84
94
|
dependencies unless the project opts in, so that also needs `allow-git=root` in the `.npmrc` next to `package.json`.
|
|
85
95
|
|
|
86
96
|
## Embed
|
|
@@ -129,7 +139,7 @@ function MapView({ model, onSelect }) {
|
|
|
129
139
|
`map.shapes` reads the notation shown and sets another (`null`: each view's own again); the cards are drawn again from
|
|
130
140
|
the geometry they have, with the camera, selection and marks kept, and nothing is laid out.
|
|
131
141
|
- `editable: true` turns on editing gestures ([docs/editing.md](docs/editing.md); `examples/edit.html` is a working host).
|
|
132
|
-
- `import { render, apply, history } from 'umlimator/all'` draws diagram types too: a class, object or
|
|
142
|
+
- `import { render, apply, history } from 'umlimator/all'` draws diagram types too: a class, object, package, sequence or communication diagram, whose gestures emit
|
|
133
143
|
`edit` transactions that `apply(model, e.commands)` turns into the next model (`examples/class-editor.html` is a
|
|
134
144
|
working host). `umlimator` alone draws maps, and a typed view as plain cards with a warning.
|
|
135
145
|
- `diff(before, after)` returns `after` with each card and line marked added, changed or removed, what changed in words,
|
|
@@ -208,8 +218,8 @@ path. The full schema is `engine/references/schema.md` (§ Map model); `examples
|
|
|
208
218
|
A model file that starts with `"$schema": "<path to>/umlimator.schema.json"` (exported as `umlimator/schema.json`)
|
|
209
219
|
gets completion and checks in editors, and `validate(model)` lists its errors and warnings, each with where it is.
|
|
210
220
|
`"schemaVersion": 2` marks a model that may hold typed elements and typed views (`docs/diagrams/model.md`). A view whose
|
|
211
|
-
`diagram` is `"uml.class"`, `"uml.object"` or `"uml.
|
|
212
|
-
`umlimator/all` and the CLI; a type not drawn yet shows its
|
|
221
|
+
`diagram` is `"uml.class"`, `"uml.object"`, `"uml.package"`, `"uml.sequence"` or `"uml.communication"` is a UML class, object,
|
|
222
|
+
package, sequence or communication diagram, drawn by `umlimator/all` and the CLI; a type not drawn yet shows its
|
|
213
223
|
nodes as plain cards, with a warning. A model with no `schemaVersion` is a map, as always, and a version newer than the
|
|
214
224
|
module reads is an error.
|
|
215
225
|
|
|
@@ -264,6 +274,19 @@ In a version-2 model, a class diagram (`examples/sales-classes.json`; every fiel
|
|
|
264
274
|
| view | `direction` | `"down"` lays it out top to bottom, the general class above (default `"right"`) |
|
|
265
275
|
| view | `present` | per element: `collapsed` compartments, and at most `rows` rows each, then "+k more" |
|
|
266
276
|
|
|
277
|
+
A sequence diagram (`examples/checkout-sequence.json`, [`docs/conformance/uml-sequence.md`](docs/conformance/uml-sequence.md))
|
|
278
|
+
and a communication diagram (`examples/checkout-communication.json`,
|
|
279
|
+
[`docs/conformance/uml-communication.md`](docs/conformance/uml-communication.md)), from 0.20.0:
|
|
280
|
+
|
|
281
|
+
| On | Field | What it does |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| node | `type` | `uml.Lifeline`; its `props.represents` is what it is an instance of, drawn `name : Type` |
|
|
284
|
+
| edge | `type` | `uml.Message`; on a communication view also `uml.Connector`, the link messages are sent along |
|
|
285
|
+
| edge | `props` | a message's `sort` (`call`, `async`, `reply`, `create`, `delete`) and a reply's `replyTo`, the call it answers |
|
|
286
|
+
| view | `diagram` | `"uml.sequence"` or `"uml.communication"` |
|
|
287
|
+
| view | `edges` | a sequence view's messages and interaction uses (`uml.InteractionUse`, `props.covers`), inline and in time order; a communication view's connectors, then its messages, by id, in order. Bars and numbers are derived |
|
|
288
|
+
| view | `fragments` | a sequence view's combined fragments (`uml.CombinedFragment`, `props.operator`), each with its operands as `members` (`label` the guard); a message's or fragment's `parent` is its operand |
|
|
289
|
+
|
|
267
290
|
## Command line
|
|
268
291
|
|
|
269
292
|
```bash
|
|
@@ -279,11 +302,13 @@ python3 umlimator.py check page.html --expand # also ea
|
|
|
279
302
|
python3 umlimator.py record bike-share.html --story ride --out ride.png # bike-share's story as an animated PNG, its tours riding
|
|
280
303
|
python3 umlimator.py import workspace.dsl --out model.json # a diagram you have already, as a model
|
|
281
304
|
python3 umlimator.py import classes.mmd --out classes.json # a Mermaid classDiagram, as a UML class diagram (needs Node)
|
|
305
|
+
python3 umlimator.py import checkout.mmd --out checkout.json # a Mermaid sequenceDiagram, as a UML sequence diagram (needs Node)
|
|
282
306
|
python3 umlimator.py render examples/sales-classes.json --out classes.html # a class diagram's page; stills, check and pdf take it too
|
|
283
307
|
docker compose config --format json > compose.json && python3 umlimator.py import compose.json --out model.json
|
|
284
308
|
kubectl get deploy,sts,svc,ing -A -o json > cluster.json && python3 umlimator.py import cluster.json --out model.json
|
|
285
309
|
python3 umlimator.py pdf page.html --out map.pdf # every view in one PDF: a cover, each view with its tables, the rules
|
|
286
310
|
python3 umlimator.py trace model.json trace.json --view ride-end --match match.json --out model.json # an OTLP trace kept as a numbered view
|
|
311
|
+
python3 umlimator.py trace model.json trace.json --view ride-end --match match.json --diagram uml.sequence --out traced.json # ... as a UML sequence diagram, in a version-2 model
|
|
287
312
|
python3 umlimator.py mcp model.json # an MCP server over stdio, for an AI assistant (below)
|
|
288
313
|
```
|
|
289
314
|
|
|
@@ -291,7 +316,8 @@ python3 umlimator.py mcp model.json # an MCP
|
|
|
291
316
|
|
|
292
317
|
`import` reads Structurizr DSL (people, systems, containers and components, their relationships, and the workspace's
|
|
293
318
|
views), C4-PlantUML (its element, relationship and boundary macros), Mermaid (`flowchart` or `graph`, and `C4Context`,
|
|
294
|
-
`C4Container` or `C4Component`; a `classDiagram` becomes a UML class diagram
|
|
319
|
+
`C4Container` or `C4Component`; a `classDiagram` becomes a UML class diagram and a `sequenceDiagram` a UML sequence
|
|
320
|
+
diagram, each read through Node), and the JSON of `docker compose config` (services, `depends_on`, networks) and of
|
|
295
321
|
`kubectl get` (workloads, Services, Ingresses). It tells the format from the content, then the extension; `--format`
|
|
296
322
|
decides. Groups, boundaries, subgraphs, networks and namespaces become boxes; Structurizr's views stay views, a card
|
|
297
323
|
opening the view below it; `examples/clinic.json` is `examples/clinic.dsl`, imported. What each element becomes, and
|
|
@@ -342,7 +368,7 @@ jobs:
|
|
|
342
368
|
runs-on: ubuntu-latest
|
|
343
369
|
steps:
|
|
344
370
|
- uses: actions/checkout@v4
|
|
345
|
-
- uses: zintaen/umlimator@v0.
|
|
371
|
+
- uses: zintaen/umlimator@v0.20.0
|
|
346
372
|
with:
|
|
347
373
|
models: "docs/*.json" # optional: where the models are (default: every .json that is a map model)
|
|
348
374
|
```
|
package/lib/umlimator-all.js
CHANGED
|
@@ -1701,7 +1701,9 @@ function routeAudit(geo, where, only, refs) { // only: a set of edges; counts ju
|
|
|
1701
1701
|
const box = n => ({ x: n.x, y: n.y, w: n.w, h: n.h });
|
|
1702
1702
|
function overlapIssues(geo, where, refs) {
|
|
1703
1703
|
const issues = [], nodes = geo.nodes, say = teller(issues, refs);
|
|
1704
|
-
|
|
1704
|
+
const inside = (a, b) => a.x >= b.x - 1 && a.y >= b.y - 1 && a.x + a.w <= b.x + b.w + 1 && a.y + a.h <= b.y + b.h + 1;
|
|
1705
|
+
const holds = (a, b) => (a.holder && inside(b, a)) || (b.holder && inside(a, b)); // a holder (a sequence's frame) may hold what it meets, not cross it
|
|
1706
|
+
for (let i = 0; i < nodes.length; i++) for (let j = i + 1; j < nodes.length; j++) if (hit(box(nodes[i]), box(nodes[j]), -1) && !holds(nodes[i], nodes[j])) say(`${where}: nodes "${nodes[i].label}" and "${nodes[j].label}" overlap`, nodes[i], nodes[j]);
|
|
1705
1707
|
return issues;
|
|
1706
1708
|
}
|
|
1707
1709
|
function leaveIssues(geo, where, refs) {
|
|
@@ -1724,7 +1726,7 @@ function leaveIssues(geo, where, refs) {
|
|
|
1724
1726
|
function auditSvg(svg, geo, where) {
|
|
1725
1727
|
const issues = overlapIssues(geo, where), R = box;
|
|
1726
1728
|
const T = [...svg.querySelectorAll('text[data-t]')].map(t => { let b; try { b = t.getBBox(); } catch (_) { return null; } return { t: t.dataset.t, o: t.dataset.o, txt: t.textContent, b: { x: b.x, y: b.y, w: b.width, h: b.height } }; }).filter(x => x && x.b.w);
|
|
1727
|
-
const nodes = geo.nodes, faces = Object.fromEntries([...svg.querySelectorAll('.node[data-face]')].map(g => [g.dataset.id, g.dataset.face.split(' ').map(Number)])); // a shape's face (0.15.0)
|
|
1729
|
+
const nodes = geo.nodes.filter(n => !n.holder), faces = Object.fromEntries([...svg.querySelectorAll('.node[data-face]')].map(g => [g.dataset.id, g.dataset.face.split(' ').map(Number)])); // a shape's face (0.15.0)
|
|
1728
1730
|
T.forEach(a => {
|
|
1729
1731
|
if (a.t === 'lt' || a.t === 'ft') {
|
|
1730
1732
|
nodes.forEach(n => { if (hit(a.b, R(n), -1)) issues.push(`${where}: lane "${a.txt}": header covers node "${n.label}"`); });
|
|
@@ -7955,11 +7957,11 @@ function sqRun(model, view) {
|
|
|
7955
7957
|
...o.heads.map((h, j) => { const n = H.get(h.id), st = sqStereo(n);
|
|
7956
7958
|
return { ...h, shape: 'lifeline', type: 'uml.Lifeline', label: sqHeadText(n), stereotypes: st, k: 'file', stem: o.stems[j], aria: `Lifeline ${sqHeadText(n)}${st.length ? ` (${st.join(', ')})` : ''}` }; }),
|
|
7957
7959
|
...o.frames.flatMap(fr => { const f = X.F.get(fr.id), op = sqOperator(f), ms = SQ_ARR(f.members).filter(SQ_OBJ);
|
|
7958
|
-
return [{ id: fr.id, shape: 'frame', type: 'uml.CombinedFragment', label: op, k: 'file', x: fr.x, y: fr.y, w: fr.w, h: fr.h, aria: `Combined fragment ${op}, ${ms.length} ${ms.length === 1 ? 'operand' : 'operands'}` },
|
|
7960
|
+
return [{ id: fr.id, shape: 'frame', type: 'uml.CombinedFragment', label: op, k: 'file', holder: true, x: fr.x, y: fr.y, w: fr.w, h: fr.h, aria: `Combined fragment ${op}, ${ms.length} ${ms.length === 1 ? 'operand' : 'operands'}` },
|
|
7959
7961
|
...fr.parts.map(p => { const m = ms.find(x => x.id === p.id) || {}, k = direct(p.id);
|
|
7960
|
-
return { ...p, shape: 'operand', type: 'uml.InteractionOperand', label: m.label, k: 'file', aria: `Operand ${SQ_HAS(m.label) ? m.label + ' ' : ''}of ${op}, ${k} ${k === 1 ? 'occurrence' : 'occurrences'}` }; })]; }),
|
|
7962
|
+
return { ...p, shape: 'operand', type: 'uml.InteractionOperand', label: m.label, k: 'file', holder: true, aria: `Operand ${SQ_HAS(m.label) ? m.label + ' ' : ''}of ${op}, ${k} ${k === 1 ? 'occurrence' : 'occurrences'}` }; })]; }),
|
|
7961
7963
|
...o.spans.map(s => { const u = X.byId.get(s.id), cs = SQ_ARR(sqProps(u.el).covers).filter(id => H.has(id)), all = heads.map(n => n.id), ids = cs.length ? all.filter(id => cs.includes(id)) : all;
|
|
7962
|
-
return { ...s, shape: 'use', type: 'uml.InteractionUse', label: String(u.el.label ?? ''), k: 'file',
|
|
7964
|
+
return { ...s, shape: 'use', type: 'uml.InteractionUse', label: String(u.el.label ?? ''), k: 'file', holder: true,
|
|
7963
7965
|
aria: `Interaction use ${u.el.label ?? ''}${ids.length ? `, over ${sqName(H.get(ids[0]))}${ids.length > 1 ? ' to ' + sqName(H.get(ids[ids.length - 1])) : ''}` : ''}` }; }),
|
|
7964
7966
|
];
|
|
7965
7967
|
const byId = Object.fromEntries(nodes.map(n => [n.id, n]));
|
package/lib/umlimator.d.ts
CHANGED
|
@@ -48,8 +48,8 @@ export interface MapNode {
|
|
|
48
48
|
/** A typed element in schema version 2's envelope (docs/diagrams/model.md §1): a node, a member, a typed edge, a
|
|
49
49
|
* fragment. Nodes, edges, members and fragments share one id space; an id never contains "->". A typed edge is an
|
|
50
50
|
* Element with `from` and `to`, which may name a member. A typed view is a MapView with `diagram` (uml.class), and may
|
|
51
|
-
* have `subject`, `direction` ('right' | 'down'), `notation`, `present`, `fragments` and `timeline`. umlimator/all draws `uml.class` (0.18.0), `uml.object` and `uml.package` (0.19.0); other types draw as plain cards.
|
|
52
|
-
* From 0.19.0
|
|
51
|
+
* have `subject`, `direction` ('right' | 'down'), `notation`, `present`, `fragments` and `timeline`. umlimator/all draws `uml.class` (0.18.0), `uml.object` and `uml.package` (0.19.0), `uml.sequence` and `uml.communication` (0.20.0); other types draw as plain cards.
|
|
52
|
+
* From 0.19.0 the class, object and package types draw a shown package that owns something the view shows as a box holding it (`parent`), and
|
|
53
53
|
* qualify names (`sales::Order`) from the nearest shown owner, the view's `subject`, or the top. */
|
|
54
54
|
export interface Element {
|
|
55
55
|
id: string; type: string; label?: string; parent?: string; props?: Record<string, unknown>; members?: Element[];
|
|
@@ -99,6 +99,33 @@ export interface UmlPackageImportProps { visibility?: 'public' | 'private'; ster
|
|
|
99
99
|
/** What a typed view shows of one element, in its `present` by the element's id: compartments not drawn, divider and
|
|
100
100
|
* all, and at most `rows` rows in each, then "+k more". */
|
|
101
101
|
export interface UmlPresent { collapsed?: ('attributes' | 'operations' | 'literals')[]; rows?: number }
|
|
102
|
+
/** The sequence diagram's vocabulary (a view with `diagram: 'uml.sequence'`, umlimator/all from 0.20.0;
|
|
103
|
+
* docs/conformance/uml-sequence.md). Lifelines are model nodes the view lists in `nodeIds`, left to right. Messages and
|
|
104
|
+
* interaction uses are inline in the view's `edges`, in time order; a fragment's content is one run there, operand by
|
|
105
|
+
* operand. Combined fragments are in the view's `fragments`, each with its operands as `members`; an occurrence's or a
|
|
106
|
+
* fragment's `parent` is the operand that holds it. Activations and message numbers are derived, never stored. */
|
|
107
|
+
export type UmlSequenceElementType = 'uml.Lifeline' | 'uml.InteractionUse' | 'uml.CombinedFragment';
|
|
108
|
+
export type UmlSequenceMemberType = 'uml.InteractionOperand';
|
|
109
|
+
export type UmlSequenceLineType = 'uml.Message';
|
|
110
|
+
/** A lifeline's props: what it represents, by name, as text (drawn `name : Type`); stereotype `actor` draws «actor». */
|
|
111
|
+
export interface UmlLifelineProps { represents?: string; stereotypes?: string[]; [key: string]: unknown }
|
|
112
|
+
/** A message's kind: a call (filled arrow, the default), async (open arrow), reply (dashed, open), create (dashed, open;
|
|
113
|
+
* the receiver's head is lowered to it) or delete (the receiver's stem ends in a cross). */
|
|
114
|
+
export type UmlMessageSort = 'call' | 'async' | 'reply' | 'create' | 'delete';
|
|
115
|
+
/** A message's props: its sort; a reply's `replyTo`, the id of the earlier call it answers. */
|
|
116
|
+
export interface UmlMessageProps { sort?: UmlMessageSort; replyTo?: string; stereotypes?: string[]; [key: string]: unknown }
|
|
117
|
+
/** An interaction use's props: the lifelines it covers (next to each other in `nodeIds`), and the view it refers to. */
|
|
118
|
+
export interface UmlInteractionUseProps { covers?: string[]; refersTo?: string; [key: string]: unknown }
|
|
119
|
+
/** A combined fragment's operator; any other is drawn by its name, with a warning. opt, loop and break have one operand,
|
|
120
|
+
* whose `label` is its guard. */
|
|
121
|
+
export type UmlInteractionOperator = 'alt' | 'opt' | 'loop' | 'par' | 'break';
|
|
122
|
+
export interface UmlCombinedFragmentProps { operator?: UmlInteractionOperator; [key: string]: unknown }
|
|
123
|
+
/** The communication diagram's vocabulary (a view with `diagram: 'uml.communication'`, umlimator/all from 0.20.0;
|
|
124
|
+
* docs/conformance/uml-communication.md): lifelines; connectors and messages are model edges the view's `edges` lists,
|
|
125
|
+
* connectors first. Only the messages' order means anything; their numbers (1, 1.1, 1.1.2) are derived. A message's
|
|
126
|
+
* props are UmlMessageProps; a message needs a connector between its two lifelines. */
|
|
127
|
+
export type UmlCommunicationElementType = 'uml.Lifeline';
|
|
128
|
+
export type UmlCommunicationLineType = 'uml.Connector' | 'uml.Message';
|
|
102
129
|
/** What a line means, drawn as its colour: calls (the default), feeds (hands work on), triggers (suggests, offers, fires),
|
|
103
130
|
* state (reads or writes a file, board or config: a thinner line, a muted label, no flow) and guard (a hook steps in).
|
|
104
131
|
* Colours are --um-w-<kind>. An edge's `style` (emphasis, dashed, security) wins over its kind's colour. */
|
|
@@ -139,7 +166,8 @@ export interface MapEdge {
|
|
|
139
166
|
}
|
|
140
167
|
export interface MapView {
|
|
141
168
|
id: string; parent?: string | null; title?: string; nodeIds: string[];
|
|
142
|
-
|
|
169
|
+
/** Model line ids or lines of its own; in a sequence view (0.20.0) its messages and interaction uses (Elements), in time order. */
|
|
170
|
+
edges?: (string | MapEdge | Element)[]; layout?: Record<string, [number, number]>; repair?: boolean;
|
|
143
171
|
/** Cards 80 px tall that show their sub-line and then their chips (`verbs`) on a third line. Default: 64 px, and a card's
|
|
144
172
|
* chips take its sub-line's place. A script card (no kind) shows no sub-line either way. */
|
|
145
173
|
subAndChips?: boolean;
|
package/lib/umlimator.js
CHANGED
|
@@ -1700,7 +1700,9 @@ function routeAudit(geo, where, only, refs) { // only: a set of edges; counts ju
|
|
|
1700
1700
|
const box = n => ({ x: n.x, y: n.y, w: n.w, h: n.h });
|
|
1701
1701
|
function overlapIssues(geo, where, refs) {
|
|
1702
1702
|
const issues = [], nodes = geo.nodes, say = teller(issues, refs);
|
|
1703
|
-
|
|
1703
|
+
const inside = (a, b) => a.x >= b.x - 1 && a.y >= b.y - 1 && a.x + a.w <= b.x + b.w + 1 && a.y + a.h <= b.y + b.h + 1;
|
|
1704
|
+
const holds = (a, b) => (a.holder && inside(b, a)) || (b.holder && inside(a, b)); // a holder (a sequence's frame) may hold what it meets, not cross it
|
|
1705
|
+
for (let i = 0; i < nodes.length; i++) for (let j = i + 1; j < nodes.length; j++) if (hit(box(nodes[i]), box(nodes[j]), -1) && !holds(nodes[i], nodes[j])) say(`${where}: nodes "${nodes[i].label}" and "${nodes[j].label}" overlap`, nodes[i], nodes[j]);
|
|
1704
1706
|
return issues;
|
|
1705
1707
|
}
|
|
1706
1708
|
function leaveIssues(geo, where, refs) {
|
|
@@ -1723,7 +1725,7 @@ function leaveIssues(geo, where, refs) {
|
|
|
1723
1725
|
function auditSvg(svg, geo, where) {
|
|
1724
1726
|
const issues = overlapIssues(geo, where), R = box;
|
|
1725
1727
|
const T = [...svg.querySelectorAll('text[data-t]')].map(t => { let b; try { b = t.getBBox(); } catch (_) { return null; } return { t: t.dataset.t, o: t.dataset.o, txt: t.textContent, b: { x: b.x, y: b.y, w: b.width, h: b.height } }; }).filter(x => x && x.b.w);
|
|
1726
|
-
const nodes = geo.nodes, faces = Object.fromEntries([...svg.querySelectorAll('.node[data-face]')].map(g => [g.dataset.id, g.dataset.face.split(' ').map(Number)])); // a shape's face (0.15.0)
|
|
1728
|
+
const nodes = geo.nodes.filter(n => !n.holder), faces = Object.fromEntries([...svg.querySelectorAll('.node[data-face]')].map(g => [g.dataset.id, g.dataset.face.split(' ').map(Number)])); // a shape's face (0.15.0)
|
|
1727
1729
|
T.forEach(a => {
|
|
1728
1730
|
if (a.t === 'lt' || a.t === 'ft') {
|
|
1729
1731
|
nodes.forEach(n => { if (hit(a.b, R(n), -1)) issues.push(`${where}: lane "${a.txt}": header covers node "${n.label}"`); });
|
|
@@ -419,7 +419,7 @@
|
|
|
419
419
|
}
|
|
420
420
|
},
|
|
421
421
|
"type": {
|
|
422
|
-
"description": "Schema version 2: the element's type, <notation>.<Name> (uml.Class). validate() checks typed fields only in a model with schemaVersion 2. The class diagram (uml.class, 0.18.0): uml.Class, uml.Interface, uml.Enumeration, uml.DataType, uml.PrimitiveType, uml.Package and uml.Comment; their members uml.Property, uml.Operation and uml.EnumerationLiteral. The object diagram (uml.object, 0.19.0): uml.InstanceSpecification and uml.Comment; an instance's members uml.Slot. The package diagram (uml.package, 0.19.0): uml.Package and the class diagram's classifiers, and uml.Comment.",
|
|
422
|
+
"description": "Schema version 2: the element's type, <notation>.<Name> (uml.Class). validate() checks typed fields only in a model with schemaVersion 2. The class diagram (uml.class, 0.18.0): uml.Class, uml.Interface, uml.Enumeration, uml.DataType, uml.PrimitiveType, uml.Package and uml.Comment; their members uml.Property, uml.Operation and uml.EnumerationLiteral. The object diagram (uml.object, 0.19.0): uml.InstanceSpecification and uml.Comment; an instance's members uml.Slot. The package diagram (uml.package, 0.19.0): uml.Package and the class diagram's classifiers, and uml.Comment. The sequence and communication diagrams (uml.sequence, uml.communication, 0.20.0): uml.Lifeline.",
|
|
423
423
|
"examples": [
|
|
424
424
|
"uml.Class",
|
|
425
425
|
"uml.Interface",
|
|
@@ -428,14 +428,15 @@
|
|
|
428
428
|
"uml.PrimitiveType",
|
|
429
429
|
"uml.Package",
|
|
430
430
|
"uml.Comment",
|
|
431
|
-
"uml.InstanceSpecification"
|
|
431
|
+
"uml.InstanceSpecification",
|
|
432
|
+
"uml.Lifeline"
|
|
432
433
|
]
|
|
433
434
|
},
|
|
434
435
|
"parent": {
|
|
435
436
|
"description": "Schema version 2: the element that owns it (a package, a composite state, a lane). From 0.19.0 a class, object or package view draws a shown package that owns something it shows as a box holding it."
|
|
436
437
|
},
|
|
437
438
|
"props": {
|
|
438
|
-
"description": "Schema version 2: the type's own properties. The class diagram (uml.class, 0.18.0): isAbstract and stereotypes on a classifier; on a member, the fields of its UML text (docs/conformance/uml-class.md). The object diagram (uml.object, 0.19.0): an instance's classifier and stereotypes; a slot's value (docs/conformance/uml-object.md).",
|
|
439
|
+
"description": "Schema version 2: the type's own properties. The class diagram (uml.class, 0.18.0): isAbstract and stereotypes on a classifier; on a member, the fields of its UML text (docs/conformance/uml-class.md). The object diagram (uml.object, 0.19.0): an instance's classifier and stereotypes; a slot's value (docs/conformance/uml-object.md). The sequence and communication diagrams (uml.sequence, uml.communication, 0.20.0): a lifeline's represents, and stereotypes (actor draws «actor» over its name).",
|
|
439
440
|
"anyOf": [
|
|
440
441
|
{
|
|
441
442
|
"type": "object",
|
|
@@ -448,6 +449,9 @@
|
|
|
448
449
|
},
|
|
449
450
|
"classifier": {
|
|
450
451
|
"description": "uml.InstanceSpecification: the name (or qualified name, sales::Order) of the classifier it is an instance of, as text; drawn name : Classifier, underlined."
|
|
452
|
+
},
|
|
453
|
+
"represents": {
|
|
454
|
+
"description": "uml.Lifeline: what it is an instance of, by name, as text; drawn name : Type (docs/diagrams/risks.md M8)."
|
|
451
455
|
}
|
|
452
456
|
}
|
|
453
457
|
},
|
|
@@ -814,7 +818,7 @@
|
|
|
814
818
|
"description": "When the line is used."
|
|
815
819
|
},
|
|
816
820
|
"type": {
|
|
817
|
-
"description": "Schema version 2: the element's type, <notation>.<Name> (uml.Class). The class diagram (uml.class, 0.18.0): uml.Association, uml.Generalization (from the specific to the general), uml.InterfaceRealization (to the interface), uml.Dependency (from the client) and uml.CommentLink (from the comment). The object diagram (uml.object, 0.19.0): uml.Link and uml.CommentLink. The package diagram (uml.package, 0.19.0): uml.PackageImport and uml.PackageMerge (from the importing or merging package), uml.Dependency and uml.CommentLink.",
|
|
821
|
+
"description": "Schema version 2: the element's type, <notation>.<Name> (uml.Class). The class diagram (uml.class, 0.18.0): uml.Association, uml.Generalization (from the specific to the general), uml.InterfaceRealization (to the interface), uml.Dependency (from the client) and uml.CommentLink (from the comment). The object diagram (uml.object, 0.19.0): uml.Link and uml.CommentLink. The package diagram (uml.package, 0.19.0): uml.PackageImport and uml.PackageMerge (from the importing or merging package), uml.Dependency and uml.CommentLink. The sequence diagram (uml.sequence, 0.20.0): uml.Message, inline in its view's edges, in time order. The communication diagram (uml.communication, 0.20.0): uml.Connector and uml.Message, model lines its view lists, connectors first; only the messages' order means anything.",
|
|
818
822
|
"examples": [
|
|
819
823
|
"uml.Association",
|
|
820
824
|
"uml.Generalization",
|
|
@@ -823,14 +827,16 @@
|
|
|
823
827
|
"uml.CommentLink",
|
|
824
828
|
"uml.Link",
|
|
825
829
|
"uml.PackageImport",
|
|
826
|
-
"uml.PackageMerge"
|
|
830
|
+
"uml.PackageMerge",
|
|
831
|
+
"uml.Message",
|
|
832
|
+
"uml.Connector"
|
|
827
833
|
]
|
|
828
834
|
},
|
|
829
835
|
"parent": {
|
|
830
|
-
"description": "Schema version 2: the element that owns it (a package, a composite state, a lane)."
|
|
836
|
+
"description": "Schema version 2: the element that owns it (a package, a composite state, a lane). In a sequence view: the operand (uml.InteractionOperand) of one of its fragments that holds the message; none at the top level."
|
|
831
837
|
},
|
|
832
838
|
"props": {
|
|
833
|
-
"description": "Schema version 2: the type's own properties. The class diagram (uml.class, 0.18.0): an association's ends, and stereotypes on any line («use» on a dependency). The object diagram (uml.object, 0.19.0): a link's association and the roles at its ends. The package diagram (uml.package, 0.19.0): a package import's visibility.",
|
|
839
|
+
"description": "Schema version 2: the type's own properties. The class diagram (uml.class, 0.18.0): an association's ends, and stereotypes on any line («use» on a dependency). The object diagram (uml.object, 0.19.0): a link's association and the roles at its ends. The package diagram (uml.package, 0.19.0): a package import's visibility. The sequence and communication diagrams (0.20.0): a message's sort and replyTo.",
|
|
834
840
|
"anyOf": [
|
|
835
841
|
{
|
|
836
842
|
"type": "object",
|
|
@@ -900,6 +906,19 @@
|
|
|
900
906
|
},
|
|
901
907
|
"visibility": {
|
|
902
908
|
"description": "uml.PackageImport: public (the default, drawn «import») or private (drawn «access»)."
|
|
909
|
+
},
|
|
910
|
+
"sort": {
|
|
911
|
+
"description": "uml.Message: call (the default), async, reply, create or delete; any other is drawn as a call, with a warning.",
|
|
912
|
+
"examples": [
|
|
913
|
+
"call",
|
|
914
|
+
"async",
|
|
915
|
+
"reply",
|
|
916
|
+
"create",
|
|
917
|
+
"delete"
|
|
918
|
+
]
|
|
919
|
+
},
|
|
920
|
+
"replyTo": {
|
|
921
|
+
"description": "uml.Message, a reply: the id of the earlier call it answers, which it goes back along."
|
|
903
922
|
}
|
|
904
923
|
}
|
|
905
924
|
},
|
|
@@ -985,7 +1004,7 @@
|
|
|
985
1004
|
},
|
|
986
1005
|
"edges": {
|
|
987
1006
|
"type": "array",
|
|
988
|
-
"description": "The lines this view draws: model line ids or lines of its own. Default: every model line between its cards; [] draws none.",
|
|
1007
|
+
"description": "The lines this view draws: model line ids or lines of its own. Default: every model line between its cards; [] draws none. In a sequence view (uml.sequence, 0.20.0): its occurrences in time order, each message and interaction use inline, a fragment's operand by operand.",
|
|
989
1008
|
"items": {
|
|
990
1009
|
"anyOf": [
|
|
991
1010
|
{
|
|
@@ -993,6 +1012,49 @@
|
|
|
993
1012
|
},
|
|
994
1013
|
{
|
|
995
1014
|
"$ref": "#/$defs/edge"
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
"type": "object",
|
|
1018
|
+
"required": [
|
|
1019
|
+
"id",
|
|
1020
|
+
"type"
|
|
1021
|
+
],
|
|
1022
|
+
"properties": {
|
|
1023
|
+
"type": {
|
|
1024
|
+
"const": "uml.InteractionUse"
|
|
1025
|
+
},
|
|
1026
|
+
"label": {
|
|
1027
|
+
"description": "The interaction it refers to, by name."
|
|
1028
|
+
},
|
|
1029
|
+
"parent": {
|
|
1030
|
+
"description": "The operand (uml.InteractionOperand) that holds it; none at the top level."
|
|
1031
|
+
},
|
|
1032
|
+
"props": {
|
|
1033
|
+
"properties": {
|
|
1034
|
+
"covers": {
|
|
1035
|
+
"description": "The ids of the lifelines it spans, next to each other in the view's nodeIds."
|
|
1036
|
+
},
|
|
1037
|
+
"refersTo": {
|
|
1038
|
+
"description": "The id of the view it refers to."
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
},
|
|
1043
|
+
"not": {
|
|
1044
|
+
"anyOf": [
|
|
1045
|
+
{
|
|
1046
|
+
"required": [
|
|
1047
|
+
"from"
|
|
1048
|
+
]
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
"required": [
|
|
1052
|
+
"to"
|
|
1053
|
+
]
|
|
1054
|
+
}
|
|
1055
|
+
]
|
|
1056
|
+
},
|
|
1057
|
+
"description": "Schema version 2: an occurrence of a sequence view that is not a line: an interaction use (uml.InteractionUse), its label the interaction it refers to, props.covers the lifelines it spans (next to each other in nodeIds), props.refersTo a view's id, parent its operand."
|
|
996
1058
|
}
|
|
997
1059
|
]
|
|
998
1060
|
}
|
|
@@ -1146,18 +1208,20 @@
|
|
|
1146
1208
|
"description": "Guess a line's kind from its label's words when its edges name none (render() and layout(); the standalone page always does)."
|
|
1147
1209
|
},
|
|
1148
1210
|
"diagram": {
|
|
1149
|
-
"description": "Schema version 2: the view's diagram type; without it the view is a map. uml.class draws a class diagram (0.18.0, lib/umlimator-all.js), uml.object an object diagram and uml.package a package diagram (0.19.0); a type this release does not draw is drawn as plain cards, with a warning.",
|
|
1211
|
+
"description": "Schema version 2: the view's diagram type; without it the view is a map. uml.class draws a class diagram (0.18.0, lib/umlimator-all.js), uml.object an object diagram and uml.package a package diagram (0.19.0), uml.sequence a sequence diagram and uml.communication a communication diagram (0.20.0); a type this release does not draw is drawn as plain cards, with a warning.",
|
|
1150
1212
|
"examples": [
|
|
1151
1213
|
"uml.class",
|
|
1152
1214
|
"uml.object",
|
|
1153
|
-
"uml.package"
|
|
1215
|
+
"uml.package",
|
|
1216
|
+
"uml.sequence",
|
|
1217
|
+
"uml.communication"
|
|
1154
1218
|
]
|
|
1155
1219
|
},
|
|
1156
1220
|
"subject": {
|
|
1157
1221
|
"description": "Schema version 2: the element this diagram is the inside of. In a class, object or package view, the package names are qualified from (sales::Order without sales:: in a view of sales); not drawn unless the view lists it."
|
|
1158
1222
|
},
|
|
1159
1223
|
"direction": {
|
|
1160
|
-
"description": "Schema version 2: a typed view's layout direction (default right). A map stays left to right."
|
|
1224
|
+
"description": "Schema version 2: a typed view's layout direction (default right). A map stays left to right. A sequence view is always down; another direction is a warning."
|
|
1161
1225
|
},
|
|
1162
1226
|
"notation": {
|
|
1163
1227
|
"description": "Schema version 2: a skin of the diagram type (crowsfoot for er)."
|
|
@@ -1189,7 +1253,48 @@
|
|
|
1189
1253
|
]
|
|
1190
1254
|
},
|
|
1191
1255
|
"fragments": {
|
|
1192
|
-
"description": "Schema version 2: a sequence view's combined fragments and
|
|
1256
|
+
"description": "Schema version 2: a sequence view's combined fragments (uml.CombinedFragment, props.operator alt, opt, loop, par or break), outermost first; each one's members are its operands (uml.InteractionOperand, label the guard) in order, and its parent is the operand that holds it (uml.sequence, 0.20.0).",
|
|
1257
|
+
"items": {
|
|
1258
|
+
"properties": {
|
|
1259
|
+
"type": {
|
|
1260
|
+
"examples": [
|
|
1261
|
+
"uml.CombinedFragment"
|
|
1262
|
+
]
|
|
1263
|
+
},
|
|
1264
|
+
"parent": {
|
|
1265
|
+
"description": "The operand (uml.InteractionOperand) that holds it; none at the top level."
|
|
1266
|
+
},
|
|
1267
|
+
"props": {
|
|
1268
|
+
"properties": {
|
|
1269
|
+
"operator": {
|
|
1270
|
+
"description": "The fragment's operator; any other is a warning.",
|
|
1271
|
+
"examples": [
|
|
1272
|
+
"alt",
|
|
1273
|
+
"opt",
|
|
1274
|
+
"loop",
|
|
1275
|
+
"par",
|
|
1276
|
+
"break"
|
|
1277
|
+
]
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
},
|
|
1281
|
+
"members": {
|
|
1282
|
+
"description": "Its operands, in order.",
|
|
1283
|
+
"items": {
|
|
1284
|
+
"properties": {
|
|
1285
|
+
"type": {
|
|
1286
|
+
"examples": [
|
|
1287
|
+
"uml.InteractionOperand"
|
|
1288
|
+
]
|
|
1289
|
+
},
|
|
1290
|
+
"label": {
|
|
1291
|
+
"description": "The operand's guard."
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1193
1298
|
},
|
|
1194
1299
|
"timeline": {
|
|
1195
1300
|
"description": "Schema version 2: a timing view's unit, changes and constraints."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "umlimator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Embeddable, layered architecture maps: layout, orthogonal routing and an interactive canvas in one ES module.",
|
|
5
5
|
"keywords": ["architecture", "diagram", "c4", "map", "svg", "layout", "orthogonal-routing", "drill-down"],
|
|
6
6
|
"homepage": "https://zintaen.github.io/umlimator/",
|