@formicoidea/labre-framework-uml 0.42.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 (114) hide show
  1. package/LICENSE +384 -0
  2. package/dist/actions.d.ts +430 -0
  3. package/dist/actions.js +724 -0
  4. package/dist/background.d.ts +153 -0
  5. package/dist/background.js +557 -0
  6. package/dist/board-hit.d.ts +137 -0
  7. package/dist/board-hit.js +191 -0
  8. package/dist/commands-manifest.d.ts +19 -0
  9. package/dist/commands-manifest.js +571 -0
  10. package/dist/commands.d.ts +4 -0
  11. package/dist/commands.js +983 -0
  12. package/dist/component.d.ts +521 -0
  13. package/dist/component.js +708 -0
  14. package/dist/consts.d.ts +365 -0
  15. package/dist/consts.js +463 -0
  16. package/dist/descriptor.d.ts +12 -0
  17. package/dist/descriptor.js +10 -0
  18. package/dist/drawio-decode.d.ts +32 -0
  19. package/dist/drawio-decode.js +96 -0
  20. package/dist/drawio-import.d.ts +133 -0
  21. package/dist/drawio-import.js +885 -0
  22. package/dist/edge-morph.d.ts +154 -0
  23. package/dist/edge-morph.js +153 -0
  24. package/dist/edge-styles.d.ts +78 -0
  25. package/dist/edge-styles.js +210 -0
  26. package/dist/effects.d.ts +9 -0
  27. package/dist/effects.js +6 -0
  28. package/dist/element-renderer.d.ts +64 -0
  29. package/dist/element-renderer.js +114 -0
  30. package/dist/element-view.d.ts +234 -0
  31. package/dist/element-view.js +430 -0
  32. package/dist/export.d.ts +61 -0
  33. package/dist/export.js +41 -0
  34. package/dist/filename.d.ts +17 -0
  35. package/dist/filename.js +26 -0
  36. package/dist/frame-tag.d.ts +70 -0
  37. package/dist/frame-tag.js +78 -0
  38. package/dist/grammar.d.ts +695 -0
  39. package/dist/grammar.js +1436 -0
  40. package/dist/import.d.ts +306 -0
  41. package/dist/import.js +1270 -0
  42. package/dist/index.d.ts +47 -0
  43. package/dist/index.js +67 -0
  44. package/dist/interchange.d.ts +125 -0
  45. package/dist/interchange.js +372 -0
  46. package/dist/keywords.d.ts +204 -0
  47. package/dist/keywords.js +361 -0
  48. package/dist/kinds.d.ts +73 -0
  49. package/dist/kinds.js +91 -0
  50. package/dist/legend.d.ts +30 -0
  51. package/dist/legend.js +255 -0
  52. package/dist/model.d.ts +862 -0
  53. package/dist/model.js +1316 -0
  54. package/dist/morph.d.ts +178 -0
  55. package/dist/morph.js +496 -0
  56. package/dist/node/act-glyphs.d.ts +30 -0
  57. package/dist/node/act-glyphs.js +142 -0
  58. package/dist/node/compartment-watcher.d.ts +107 -0
  59. package/dist/node/compartment-watcher.js +163 -0
  60. package/dist/node/fit.d.ts +85 -0
  61. package/dist/node/fit.js +129 -0
  62. package/dist/node/node-renderer.d.ts +49 -0
  63. package/dist/node/node-renderer.js +611 -0
  64. package/dist/node/node-view.d.ts +51 -0
  65. package/dist/node/node-view.js +89 -0
  66. package/dist/node/paint.d.ts +84 -0
  67. package/dist/node/paint.js +143 -0
  68. package/dist/node/sd-glyphs.d.ts +36 -0
  69. package/dist/node/sd-glyphs.js +79 -0
  70. package/dist/node/stm-glyphs.d.ts +22 -0
  71. package/dist/node/stm-glyphs.js +111 -0
  72. package/dist/node/tier-metrics.d.ts +38 -0
  73. package/dist/node/tier-metrics.js +45 -0
  74. package/dist/operators.d.ts +45 -0
  75. package/dist/operators.js +75 -0
  76. package/dist/plantuml-import.d.ts +113 -0
  77. package/dist/plantuml-import.js +1723 -0
  78. package/dist/plantuml.d.ts +94 -0
  79. package/dist/plantuml.js +985 -0
  80. package/dist/presets.d.ts +149 -0
  81. package/dist/presets.js +302 -0
  82. package/dist/profiles.d.ts +2 -0
  83. package/dist/profiles.js +358 -0
  84. package/dist/reading.d.ts +160 -0
  85. package/dist/reading.js +648 -0
  86. package/dist/roles.d.ts +257 -0
  87. package/dist/roles.js +997 -0
  88. package/dist/rules.d.ts +267 -0
  89. package/dist/rules.js +3090 -0
  90. package/dist/templates.d.ts +2 -0
  91. package/dist/templates.js +197 -0
  92. package/dist/toolbar/config.d.ts +228 -0
  93. package/dist/toolbar/config.js +833 -0
  94. package/dist/toolbar/icons.d.ts +440 -0
  95. package/dist/toolbar/icons.js +711 -0
  96. package/dist/toolbar/senior-tool.d.ts +11 -0
  97. package/dist/toolbar/senior-tool.js +21 -0
  98. package/dist/toolbar/uml-menu.d.ts +17 -0
  99. package/dist/toolbar/uml-menu.js +20 -0
  100. package/dist/toolbar/uml-senior-button.d.ts +18 -0
  101. package/dist/toolbar/uml-senior-button.js +22 -0
  102. package/dist/translations.d.ts +27 -0
  103. package/dist/translations.js +117 -0
  104. package/dist/view.d.ts +33 -0
  105. package/dist/view.js +236 -0
  106. package/dist/xmi-import.d.ts +174 -0
  107. package/dist/xmi-import.js +2268 -0
  108. package/dist/xmi.d.ts +61 -0
  109. package/dist/xmi.js +1860 -0
  110. package/dist/xml-reader.d.ts +157 -0
  111. package/dist/xml-reader.js +430 -0
  112. package/dist/xml.d.ts +72 -0
  113. package/dist/xml.js +96 -0
  114. package/package.json +38 -0
@@ -0,0 +1,648 @@
1
+ import { UML_ROLE, UML_ROLES } from './roles.js';
2
+ /**
3
+ * What a UML diagram lets the tool read of an element (MF3, the reversed
4
+ * reading).
5
+ *
6
+ * DATA, like the legend and the roles beside it: the engine
7
+ * (`@labre/affine-block-surface`) knows how to read a role and a typed edge — it
8
+ * knows nothing about UML. Everything below is already stated in `roles.ts` and
9
+ * is merely POINTED AT here.
10
+ *
11
+ * Registered from the FLAG-GATED view extension: reading a diagram is tooling,
12
+ * so a sheet whose `uml` flag is off keeps every element it has and simply stops
13
+ * being read (ADR 0009).
14
+ *
15
+ * ## FORTY profiles, one per artefact, because the roles are flat
16
+ *
17
+ * There are two chains in the node vocabulary — `uml:classifier` over class,
18
+ * interface and enumeration, and (since phase 2) `uml:node` over device and
19
+ * execution environment — and a single profile written on either parent would
20
+ * read its children through `roleIsA`. Neither shortcut is taken, and the reason
21
+ * is the panel rather than the vocabulary: a profile's `id` is what the DI keys
22
+ * on and what a user sees the reading OF, and "Classifier" is a word the
23
+ * specification uses and an architect does not, while "Node" is a word that
24
+ * would make the panel call a database server something vaguer than the picture
25
+ * already says. Profiles differing by `id` and `appliesTo` cost three lines each
26
+ * and let the panel say "Device" about a device.
27
+ *
28
+ * `uml:node` is NOT in that argument's exception list, though: unlike
29
+ * `uml:classifier` it is a role elements really carry — `uml.addNode` draws one
30
+ * — so it has a profile of its own rather than an entry in
31
+ * `reading-coverage.unit.spec.ts`'s unread list. A parent that is also a
32
+ * concrete kind is read as that kind.
33
+ *
34
+ * The remaining roles are flat by construction (`roles.ts` argues each one), so
35
+ * they get a profile each with nothing to decide.
36
+ *
37
+ * The FRAMES are not read: `uml:diagram` is the sheet, and `uml:subject`,
38
+ * `uml:partition`, `uml:region` and — since phase 3 — `uml:fragment` and the
39
+ * `uml:operand` bands inside it are rectangles drawn round part of it, and
40
+ * `packages/affine/all/src/__tests__/reading-coverage.unit.spec.ts` records
41
+ * every one of them as such so the coverage test does not ask a sheet to read
42
+ * itself back as a sentence.
43
+ *
44
+ * ## The name lives on a separate element
45
+ *
46
+ * Every UML artefact is a composite — a shape, and the canvas texts grouped with
47
+ * it — so every profile points `labelRole` at the tier that names it. Without
48
+ * it the panel would print an id at a human, and the relation lines would name
49
+ * the other end by id too.
50
+ *
51
+ * `uml:name` for everything whose words a keyword may be written over — the
52
+ * compartmented kinds (the state among them, since §14.2.4 draws one), the
53
+ * package, the note and the three deployment cubes — and `uml:label` for the
54
+ * artefacts whose one word is a name and nothing else: the actor, the use case,
55
+ * the port, the two interface marks and the activity vocabulary. See `roles.ts`
56
+ * on why the tier is named twice.
57
+ *
58
+ * The split has a second consequence worth stating, because it is the engine's
59
+ * and not this file's: `readElement` names the OTHER end of a relation through
60
+ * the SAME profile's `labelRole`, so a reading only names its neighbour when the
61
+ * two agree on a tier. That is why `uml-artifact` and `uml-node` are both
62
+ * `uml:name` — they read one another through {@link DEPLOY}, and a deployment
63
+ * that printed an id at the far end would be a panel that answered "where does
64
+ * this run" with a nanoid.
65
+ *
66
+ * ## SEVERAL relations per profile, and which one comes first
67
+ *
68
+ * `ReadingProfile.relation` names the relation an architect reads that artefact
69
+ * THROUGH — the question it answers first — and `ReadingProfile.alsoRelations`
70
+ * names the others, in the order the panel lists them. `roleIsA` does the rest
71
+ * where a chain exists: a table declaring `uml:association` reads aggregations
72
+ * and compositions too, because the specification makes them associations
73
+ * (§11.5.4), and nothing has to restate the diamonds.
74
+ *
75
+ * Phases 1 to 3 declared ONE table each, which was a narrowing this file argued
76
+ * for and named the cost of: a class's generalizations, realizations and
77
+ * dependencies went unread, a use case's `include` and `extend` went unread,
78
+ * and so did a node's communication paths and an artifact's manifestations.
79
+ * The PO's recette of 2026-09-14 (O8) is what overturned it, and the finding is
80
+ * not that the narrowing was wrong but that it is INVISIBLE: the panel says
81
+ * "No typed link touches this component" whether a framework declined to read
82
+ * the line or failed to, and a use case whose only link is an `«include»`
83
+ * therefore reads as an unconnected box on a diagram that plainly connects it.
84
+ * A reader cannot tell a choice from a bug, so the choice had to go.
85
+ *
86
+ * Every table below is one the notation draws and this canvas types. Two rules
87
+ * govern the lists: they must not OVERLAP (an edge matching two tables would be
88
+ * listed twice — which is why no profile declares both `uml:association` and
89
+ * one of its specialisations), and the FIRST is the relation that answers "what
90
+ * is this connected to" first.
91
+ *
92
+ * One line is still read from ONE end on purpose, and it is the only one: the
93
+ * `uml:anchor` of Annex A, which the NOTE reads and the artefact it comments on
94
+ * does not. It is not a relation between two model elements — it is a comment
95
+ * pinned to one — and a class reading "Attached to:" followed by the whole
96
+ * first line of somebody's note would be the panel quoting prose at a reader
97
+ * who asked what the class is connected to.
98
+ *
99
+ * ## No nature, no phase
100
+ *
101
+ * UML ships no type-3 tag pack: the artefacts ARE the roles, and the keyword
102
+ * line of §11.4.4 already says the rest in the author's own words. And a diagram
103
+ * frame declares which kind of diagram it draws, not a set of zones a position
104
+ * could be read against — nothing in UML gives a coordinate a meaning.
105
+ */
106
+ /**
107
+ * The two words an ASSOCIATION is read with.
108
+ *
109
+ * Undirected (§11.5.4), which is the one thing the wording has to survive: the
110
+ * role declares no verb precisely because a plain line claims no direction, so
111
+ * both sides say the same thing. `source` and `target` are still persisted and
112
+ * still mean something to aggregation and composition — which read through this
113
+ * profile and whose diamond IS on the source end — but the panel must not
114
+ * announce a reading the notation declines to draw.
115
+ */
116
+ const ASSOCIATION = {
117
+ edgeRole: UML_ROLE.association,
118
+ sides: {
119
+ consumer: {
120
+ labelKey: 'com.labre.uml.reading.relations.associated',
121
+ labelFallback: 'Associated with',
122
+ },
123
+ supplier: {
124
+ labelKey: 'com.labre.uml.reading.relations.associated',
125
+ labelFallback: 'Associated with',
126
+ },
127
+ },
128
+ };
129
+ /**
130
+ * A GENERALIZATION (§9.9.4) — the hollow triangle, read as the taxonomy it is.
131
+ *
132
+ * Directed, and the two sides are the two halves of one sentence an architect
133
+ * says out loud: the source is the specific classifier and the target the
134
+ * general one (`roles.ts` fixes that, and the triangle lands on the general
135
+ * end), so a subclass reads "Specializes: Payment" and the superclass reads
136
+ * "Specialized by: CardPayment, Transfer".
137
+ *
138
+ * The wording is the reader's rather than the metamodel's — "generalizes" is a
139
+ * word the specification uses about the relationship and nobody uses about a
140
+ * class — and it is asymmetric because the two ends are genuinely not peers.
141
+ */
142
+ const GENERALIZATION = {
143
+ edgeRole: UML_ROLE.generalization,
144
+ sides: {
145
+ consumer: {
146
+ labelKey: 'com.labre.uml.reading.relations.specializedBy',
147
+ labelFallback: 'Specialized by',
148
+ },
149
+ supplier: {
150
+ labelKey: 'com.labre.uml.reading.relations.specializes',
151
+ labelFallback: 'Specializes',
152
+ },
153
+ },
154
+ };
155
+ /**
156
+ * A REALIZATION (§10.4.4) — the dashed line with the hollow triangle, from a
157
+ * class to the interface it implements.
158
+ *
159
+ * Its own table rather than a reading through {@link GENERALIZATION}: the two
160
+ * roles are filed FLAT in `roles.ts` (a realization is not a kind of
161
+ * generalization, it is the other thing a hollow triangle can mean), and the
162
+ * sentence is different — a class does not BECOME its interface, it promises to
163
+ * answer for it.
164
+ */
165
+ const REALIZATION = {
166
+ edgeRole: UML_ROLE.realization,
167
+ sides: {
168
+ consumer: {
169
+ labelKey: 'com.labre.uml.reading.relations.realizedBy',
170
+ labelFallback: 'Realized by',
171
+ },
172
+ supplier: {
173
+ labelKey: 'com.labre.uml.reading.relations.realizes',
174
+ labelFallback: 'Realizes',
175
+ },
176
+ },
177
+ };
178
+ /**
179
+ * An INCLUDE (§18.1.4) — the `«include»` arrow from the base use case to the
180
+ * behaviour it always performs.
181
+ *
182
+ * The wording is the role's own verb (`roles.ts`: "includes"), said from each
183
+ * end: the base reads "Includes: Pay", the included one reads "Included by:
184
+ * Order". §18.1.3 makes both ends use cases, so neither sentence can be about
185
+ * anything else.
186
+ */
187
+ const INCLUDE = {
188
+ edgeRole: UML_ROLE.include,
189
+ sides: {
190
+ consumer: {
191
+ labelKey: 'com.labre.uml.reading.relations.includedBy',
192
+ labelFallback: 'Included by',
193
+ },
194
+ supplier: {
195
+ labelKey: 'com.labre.uml.reading.relations.includes',
196
+ labelFallback: 'Includes',
197
+ },
198
+ },
199
+ };
200
+ /**
201
+ * An EXTEND (§18.1.4) — the `«extend»` arrow, and the one relation of the pack
202
+ * whose arrow points AT what it is about.
203
+ *
204
+ * `roles.ts` draws it from the EXTENDING use case to the base one, which is the
205
+ * specification's direction and the opposite of the include's, so the wordings
206
+ * are swapped with respect to {@link INCLUDE} rather than copied: the extending
207
+ * behaviour reads "Extends: Order", the base reads "Extended by: ApplyCoupon".
208
+ */
209
+ const EXTEND = {
210
+ edgeRole: UML_ROLE.extend,
211
+ sides: {
212
+ consumer: {
213
+ labelKey: 'com.labre.uml.reading.relations.extendedBy',
214
+ labelFallback: 'Extended by',
215
+ },
216
+ supplier: {
217
+ labelKey: 'com.labre.uml.reading.relations.extends',
218
+ labelFallback: 'Extends',
219
+ },
220
+ },
221
+ };
222
+ /**
223
+ * A MANIFESTATION (§19.3.4) — the dashed arrow that says what a file IS.
224
+ *
225
+ * The other half of {@link DEPLOY}: an artifact reads "Manifests: Ordering"
226
+ * and the component reads "Manifested by: ordering.jar", off one table read
227
+ * from its two ends. Asymmetric for the same reason the deployment is — the
228
+ * source is a physical file and the target a piece of the model.
229
+ */
230
+ const MANIFEST = {
231
+ edgeRole: UML_ROLE.manifest,
232
+ sides: {
233
+ consumer: {
234
+ labelKey: 'com.labre.uml.reading.relations.manifestedBy',
235
+ labelFallback: 'Manifested by',
236
+ },
237
+ supplier: {
238
+ labelKey: 'com.labre.uml.reading.relations.manifests',
239
+ labelFallback: 'Manifests',
240
+ },
241
+ },
242
+ };
243
+ /**
244
+ * A COMMUNICATION PATH (§19.4.4) — the plain line between two nodes.
245
+ *
246
+ * Undirected, exactly like {@link ASSOCIATION} and for the same reason: the
247
+ * notation draws no arrow, so both sides say the same thing and the panel
248
+ * claims nothing the drawing declines to.
249
+ */
250
+ const COMMUNICATION_PATH = {
251
+ edgeRole: UML_ROLE['communication-path'],
252
+ sides: {
253
+ consumer: {
254
+ labelKey: 'com.labre.uml.reading.relations.communicatesWith',
255
+ labelFallback: 'Communicates with',
256
+ },
257
+ supplier: {
258
+ labelKey: 'com.labre.uml.reading.relations.communicatesWith',
259
+ labelFallback: 'Communicates with',
260
+ },
261
+ },
262
+ };
263
+ /**
264
+ * A package is read through its DEPENDENCIES (§7.8.4) — which is what a package
265
+ * diagram is for: `«use»` and `«import»` arrows between the parts of a system.
266
+ * Directed, unlike the association, and the two sides say so.
267
+ */
268
+ const DEPENDENCY = {
269
+ edgeRole: UML_ROLE.dependency,
270
+ sides: {
271
+ consumer: {
272
+ labelKey: 'com.labre.uml.reading.relations.dependedOnBy',
273
+ labelFallback: 'Depended on by',
274
+ },
275
+ supplier: {
276
+ labelKey: 'com.labre.uml.reading.relations.dependsOn',
277
+ labelFallback: 'Depends on',
278
+ },
279
+ },
280
+ };
281
+ /**
282
+ * A note is read through its ANCHORS (Annex A) — the dotted lines tying it to
283
+ * what it comments on. The one relation that is not between two model elements,
284
+ * which is why the wording is about attachment rather than about a verb.
285
+ */
286
+ const ANCHOR = {
287
+ edgeRole: UML_ROLE.anchor,
288
+ sides: {
289
+ consumer: {
290
+ labelKey: 'com.labre.uml.reading.relations.attached',
291
+ labelFallback: 'Attached to',
292
+ },
293
+ supplier: {
294
+ labelKey: 'com.labre.uml.reading.relations.attached',
295
+ labelFallback: 'Attached to',
296
+ },
297
+ },
298
+ };
299
+ /**
300
+ * A DEPLOYMENT (§19.2.4) — the dashed arrow that says where a file runs.
301
+ *
302
+ * Directed, and the wording is asymmetric because the two ends are different
303
+ * KINDS of thing rather than two peers: the source is an artifact (`.war`,
304
+ * script, image) and the target is a node. So an artifact reads "Deployed on:
305
+ * AppServer" and the server reads "Hosts: orders.war" — one table, two sentences,
306
+ * and each is the one its side of the arrow actually wants.
307
+ */
308
+ const DEPLOY = {
309
+ edgeRole: UML_ROLE.deploy,
310
+ sides: {
311
+ consumer: {
312
+ labelKey: 'com.labre.uml.reading.relations.hosts',
313
+ labelFallback: 'Hosts',
314
+ },
315
+ supplier: {
316
+ labelKey: 'com.labre.uml.reading.relations.deployedOn',
317
+ labelFallback: 'Deployed on',
318
+ },
319
+ },
320
+ };
321
+ /**
322
+ * A CONTROL FLOW (§15.2.4) — the arrow that says which step comes next.
323
+ *
324
+ * Directed, and the wording is the plainest in the pack on purpose: an activity
325
+ * diagram answers one question — what happens after this — and the panel should
326
+ * answer it in the words a reader would use rather than in the metamodel's.
327
+ */
328
+ const FLOW = {
329
+ edgeRole: UML_ROLE['control-flow'],
330
+ sides: {
331
+ consumer: {
332
+ labelKey: 'com.labre.uml.reading.relations.flowsFrom',
333
+ labelFallback: 'Flows from',
334
+ },
335
+ supplier: {
336
+ labelKey: 'com.labre.uml.reading.relations.flowsTo',
337
+ labelFallback: 'Flows to',
338
+ },
339
+ },
340
+ };
341
+ /**
342
+ * An OBJECT FLOW (§15.4.4) — the same arrow, carrying data rather than a token.
343
+ *
344
+ * Its own table rather than a reading through {@link FLOW}, because the two
345
+ * roles are filed FLAT in `roles.ts`: an object flow is not a control flow, it
346
+ * is the other kind of activity edge, and a profile declaring the one would
347
+ * never reach the other. The data node is the one artefact that wants this
348
+ * table, which is exactly the one artefact that has it.
349
+ */
350
+ const OBJECT_FLOW = {
351
+ edgeRole: UML_ROLE['object-flow'],
352
+ sides: {
353
+ consumer: {
354
+ labelKey: 'com.labre.uml.reading.relations.producedBy',
355
+ labelFallback: 'Produced by',
356
+ },
357
+ supplier: {
358
+ labelKey: 'com.labre.uml.reading.relations.consumedBy',
359
+ labelFallback: 'Consumed by',
360
+ },
361
+ },
362
+ };
363
+ /**
364
+ * A TRANSITION (§14.2.4.8) — what takes the machine from one state to the next.
365
+ *
366
+ * Distinct from {@link FLOW} rather than sharing its wording, because the two
367
+ * sentences are genuinely different: an activity's arrow says what happens
368
+ * NEXT, a state machine's says what this thing BECOMES, and the `trigger
369
+ * [guard] / effect` written on the line is the answer to "when".
370
+ */
371
+ const TRANSITION = {
372
+ edgeRole: UML_ROLE.transition,
373
+ sides: {
374
+ consumer: {
375
+ labelKey: 'com.labre.uml.reading.relations.transitionsFrom',
376
+ labelFallback: 'Entered from',
377
+ },
378
+ supplier: {
379
+ labelKey: 'com.labre.uml.reading.relations.transitionsTo',
380
+ labelFallback: 'Transitions to',
381
+ },
382
+ },
383
+ };
384
+ /**
385
+ * A MESSAGE (§17.4.4) — what one participant asks another to do.
386
+ *
387
+ * Its own table rather than a reading through {@link FLOW}, and the two roles
388
+ * are filed apart for the same reason the object flow is: a message is not a
389
+ * control flow, it is the other thing an arrow can be, and a profile declaring
390
+ * the one would never reach the other.
391
+ *
392
+ * Declared on the PARENT `uml:message`, which is what makes one table answer
393
+ * for all five: `roleIsA` files `uml:message-sync`, `-async`, `-reply`,
394
+ * `-create` and `-delete` under it (`roles.ts`), so a lifeline reads every
395
+ * message drawn on it whichever of the five an author typed it as. The
396
+ * alternative — five tables, one per drawing — would make a participant's
397
+ * reading depend on whether the call it received happened to be asynchronous.
398
+ *
399
+ * The wording is asymmetric and deliberately in the reader's words rather than
400
+ * the metamodel's: the question a sequence diagram answers about a participant
401
+ * is who talks to it and who it talks to.
402
+ */
403
+ const MESSAGE = {
404
+ edgeRole: UML_ROLE.message,
405
+ sides: {
406
+ consumer: {
407
+ labelKey: 'com.labre.uml.reading.relations.receivesFrom',
408
+ labelFallback: 'Receives from',
409
+ },
410
+ supplier: {
411
+ labelKey: 'com.labre.uml.reading.relations.sendsTo',
412
+ labelFallback: 'Sends to',
413
+ },
414
+ },
415
+ };
416
+ /**
417
+ * One artefact, as a profile. The forty below differ by five fields at most.
418
+ *
419
+ * `also` is variadic rather than an array argument because most entries pass
420
+ * none and the ones that pass some pass two or three: `profile('uml-use-case',
421
+ * …, ASSOCIATION, INCLUDE, EXTEND)` reads as the list of lines a use case
422
+ * carries, which is what it is.
423
+ */
424
+ const profile = (id, appliesTo, labelRole, relation, ...also) => ({
425
+ id,
426
+ framework: 'uml',
427
+ roles: UML_ROLES,
428
+ appliesTo,
429
+ labelRole,
430
+ relation,
431
+ ...(also.length > 0 ? { alsoRelations: also } : {}),
432
+ });
433
+ /**
434
+ * The FOUR lines a class diagram draws off a classifier, in the order §11 and
435
+ * §9 put them: the association first (it is what a class diagram is mostly
436
+ * made of), then the taxonomy, then the contract, then the `«use»` arrow.
437
+ *
438
+ * The four are declared once and shared by the four classifier profiles, which
439
+ * is the same argument `roles.ts` makes about the chain: a class, an interface,
440
+ * an enumeration and an object carry the same lines, and four copies of this
441
+ * list would be four places for a wording to drift.
442
+ */
443
+ export const UML_CLASS_READING = profile('uml-class', UML_ROLE.class, UML_ROLE.name, ASSOCIATION, GENERALIZATION, REALIZATION, DEPENDENCY);
444
+ export const UML_INTERFACE_READING = profile('uml-interface', UML_ROLE.interface, UML_ROLE.name, ASSOCIATION, GENERALIZATION, REALIZATION, DEPENDENCY);
445
+ export const UML_ENUMERATION_READING = profile('uml-enumeration', UML_ROLE.enumeration, UML_ROLE.name, ASSOCIATION, GENERALIZATION, REALIZATION, DEPENDENCY);
446
+ /** An instance, read through the links between instances (§9.8.4). */
447
+ export const UML_OBJECT_READING = profile('uml-object', UML_ROLE.object, UML_ROLE.name, ASSOCIATION, GENERALIZATION, REALIZATION, DEPENDENCY);
448
+ export const UML_PACKAGE_READING = profile('uml-package', UML_ROLE.package, UML_ROLE.name, DEPENDENCY);
449
+ export const UML_NOTE_READING = profile('uml-note', UML_ROLE.note, UML_ROLE.name, ANCHOR);
450
+ /** An actor's one word is a `uml:label`: there is no compartment to name. */
451
+ export const UML_ACTOR_READING = profile('uml-actor', UML_ROLE.actor, UML_ROLE.label, ASSOCIATION, GENERALIZATION);
452
+ /**
453
+ * A use case is read through the actors it serves FIRST — which is the question
454
+ * a use-case diagram exists to answer — and then through the two arrows §18.1.4
455
+ * draws between use cases.
456
+ *
457
+ * The include and the extend are the PO's O8 in its plainest form: a use case
458
+ * reached only through an `«include»` had a typed line on the canvas, in the
459
+ * export and in the direction reveal, and a panel that said "No typed link
460
+ * touches this component". A generalization between use cases is legal
461
+ * (§18.1.3) and is here for the same reason.
462
+ */
463
+ export const UML_USE_CASE_READING = profile('uml-use-case', UML_ROLE['use-case'], UML_ROLE.label, ASSOCIATION, INCLUDE, EXTEND, GENERALIZATION);
464
+ /* ── Phase 2: components (§11.6.4, §11.3.4, §10.4.4) ───────────────────── */
465
+ /**
466
+ * A component is read through its DEPENDENCIES, like the package it is often
467
+ * mistaken for: §11.6.4 wires a component diagram with `«use»` arrows to the
468
+ * interfaces its neighbours provide, and "what does this need, and who needs it"
469
+ * is the question the diagram exists to answer.
470
+ *
471
+ * Then through the two other lines that reach it: the `«manifest»` arrows that
472
+ * say which files embody it (§19.3.4 — the far end of {@link MANIFEST}, whose
473
+ * near end the artifact reads) and the realizations §10.4.4 draws from a
474
+ * component to an interface it provides.
475
+ */
476
+ export const UML_COMPONENT_READING = profile('uml-component', UML_ROLE.component, UML_ROLE.name, DEPENDENCY, MANIFEST, REALIZATION);
477
+ /**
478
+ * A port is read through the plain connectors drawn from it (§11.3.4): an
479
+ * assembly or a delegation is an undecorated line, which is to say an
480
+ * association, and it is the only relation a port ever carries.
481
+ */
482
+ export const UML_PORT_READING = profile('uml-port', UML_ROLE.port, UML_ROLE.label, ASSOCIATION);
483
+ /** The ball of §10.4.4, read through the assembly line that joins it to a socket. */
484
+ export const UML_PROVIDED_INTERFACE_READING = profile('uml-provided-interface', UML_ROLE['provided-interface'], UML_ROLE.label, ASSOCIATION);
485
+ /** The socket, read through the same line from the other side. */
486
+ export const UML_REQUIRED_INTERFACE_READING = profile('uml-required-interface', UML_ROLE['required-interface'], UML_ROLE.label, ASSOCIATION);
487
+ /* ── Phase 2: deployment (§19.2.4, §19.3.4, §19.4.4) ───────────────────── */
488
+ /**
489
+ * An artifact is read through WHERE IT RUNS, and then through WHAT IT IS.
490
+ *
491
+ * The order is the reader's rather than the metamodel's: the `«manifest»` arrow
492
+ * to the component a file is the physical form of is the modelling fact, the
493
+ * deployment is the operational one, and an architect opening this panel on a
494
+ * `.war` file is asking which server it is on before asking anything else.
495
+ */
496
+ export const UML_ARTIFACT_READING = profile('uml-artifact', UML_ROLE.artifact, UML_ROLE.name, DEPLOY, MANIFEST);
497
+ /**
498
+ * A node is read through WHAT RUNS ON IT — the same table, from the other end —
499
+ * and then through the nodes it can TALK TO (§19.4.4).
500
+ */
501
+ export const UML_NODE_READING = profile('uml-node', UML_ROLE.node, UML_ROLE.name, DEPLOY, COMMUNICATION_PATH);
502
+ /** A device: a node that is hardware (§19.4.4), and read as one. */
503
+ export const UML_DEVICE_READING = profile('uml-device', UML_ROLE.device, UML_ROLE.name, DEPLOY, COMMUNICATION_PATH);
504
+ /** An execution environment: a node that is software, and read as one. */
505
+ export const UML_EXECUTION_ENVIRONMENT_READING = profile('uml-execution-environment', UML_ROLE['execution-environment'], UML_ROLE.name, DEPLOY, COMMUNICATION_PATH);
506
+ /* ── Phase 2: activities (§15.2.4, §15.3.4, §15.4.4, §16.3.4, §16.10.4) ── */
507
+ /**
508
+ * Every artefact below takes its name off `uml:label` — except the STATE, which
509
+ * is a divided box and takes it off `uml:name` — and thirteen of them have none
510
+ * to take: a control node and a pseudostate are created with no text at all
511
+ * (`actions.ts`), because §15.3.4 and §14.2.4 name none of them. The
512
+ * profile still declares the tier, and that is deliberate rather than sloppy —
513
+ * `readElement` names the OTHER end of a relation through the SAME profile's
514
+ * `labelRole`, so an action reading "Flows to:" about the decision it points at
515
+ * agrees with the decision's own profile on where a name would be if there were
516
+ * one. Declaring a different tier on the unnamed ones would break that
517
+ * agreement for no gain.
518
+ */
519
+ export const UML_ACTION_READING = profile('uml-action', UML_ROLE.action, UML_ROLE.label, FLOW);
520
+ export const UML_INITIAL_READING = profile('uml-initial', UML_ROLE.initial, UML_ROLE.label, FLOW);
521
+ export const UML_ACTIVITY_FINAL_READING = profile('uml-activity-final', UML_ROLE['activity-final'], UML_ROLE.label, FLOW);
522
+ export const UML_FLOW_FINAL_READING = profile('uml-flow-final', UML_ROLE['flow-final'], UML_ROLE.label, FLOW);
523
+ export const UML_DECISION_READING = profile('uml-decision', UML_ROLE.decision, UML_ROLE.label, FLOW);
524
+ export const UML_FORK_READING = profile('uml-fork', UML_ROLE.fork, UML_ROLE.label, FLOW);
525
+ /** The one artefact of the pack read through the DATA that passes through it. */
526
+ export const UML_OBJECT_NODE_READING = profile('uml-object-node', UML_ROLE['object-node'], UML_ROLE.label, OBJECT_FLOW);
527
+ export const UML_SEND_SIGNAL_READING = profile('uml-send-signal', UML_ROLE['send-signal'], UML_ROLE.label, FLOW);
528
+ export const UML_ACCEPT_EVENT_READING = profile('uml-accept-event', UML_ROLE['accept-event'], UML_ROLE.label, FLOW);
529
+ export const UML_TIME_EVENT_READING = profile('uml-time-event', UML_ROLE['time-event'], UML_ROLE.label, FLOW);
530
+ /* ── Phase 2: state machines (§14.2.4) ─────────────────────────────────── */
531
+ /**
532
+ * The one behaviour artefact named off `uml:name` rather than `uml:label`: a
533
+ * state is a DIVIDED BOX (§14.2.4), so its heading is a name compartment with
534
+ * the internal activities ruled off below it, exactly as a classifier's is.
535
+ */
536
+ export const UML_STATE_READING = profile('uml-state', UML_ROLE.state, UML_ROLE.name, TRANSITION);
537
+ export const UML_FINAL_STATE_READING = profile('uml-final-state', UML_ROLE['final-state'], UML_ROLE.label, TRANSITION);
538
+ export const UML_CHOICE_READING = profile('uml-choice', UML_ROLE.choice, UML_ROLE.label, TRANSITION);
539
+ export const UML_JUNCTION_READING = profile('uml-junction', UML_ROLE.junction, UML_ROLE.label, TRANSITION);
540
+ export const UML_SHALLOW_HISTORY_READING = profile('uml-shallow-history', UML_ROLE['shallow-history'], UML_ROLE.label, TRANSITION);
541
+ export const UML_DEEP_HISTORY_READING = profile('uml-deep-history', UML_ROLE['deep-history'], UML_ROLE.label, TRANSITION);
542
+ export const UML_ENTRY_POINT_READING = profile('uml-entry-point', UML_ROLE['entry-point'], UML_ROLE.label, TRANSITION);
543
+ export const UML_EXIT_POINT_READING = profile('uml-exit-point', UML_ROLE['exit-point'], UML_ROLE.label, TRANSITION);
544
+ export const UML_TERMINATE_READING = profile('uml-terminate', UML_ROLE.terminate, UML_ROLE.label, TRANSITION);
545
+ /* ── Phase 3: sequence diagrams (§17.2.4, §17.4.4) ─────────────────────── */
546
+ /**
547
+ * A LIFELINE is read through the MESSAGES drawn on it — which is the whole of
548
+ * what a sequence diagram says about a participant: who calls it, and what it
549
+ * calls in turn (§17.4.4).
550
+ *
551
+ * `uml:lifeline-ident`, and neither of the two tiers it might have been:
552
+ * §17.3.4 writes `<name> : <Type>` in the head as a plain identifier, with no
553
+ * keyword over it and none allowed — so it is not a `uml:name`, which is the
554
+ * tier a keyword is written on — and the clause prints a BNF for it, which no
555
+ * clause does for an actor's word, so it is not a `uml:label` either
556
+ * (`roles.ts`). `parseLifelineIdent` is what reads that line back, and this
557
+ * profile names the tier it reads.
558
+ */
559
+ export const UML_LIFELINE_READING = profile('uml-lifeline', UML_ROLE.lifeline, UML_ROLE['lifeline-ident'], MESSAGE);
560
+ /**
561
+ * An EXECUTION and a DESTRUCTION are read through the same table, and both are
562
+ * marks the notation writes nothing on (§17.2.4).
563
+ *
564
+ * They are read at all because a message may LAND on either: §17.4.4 lets a
565
+ * call arrive on the execution it starts, and a delete message arrives at the
566
+ * cross. Both declare `uml:lifeline-ident` — the tier NEITHER of them carries —
567
+ * and that is the rule phase 2 states for every unnamed artefact, applied here:
568
+ * `readElement` names the far end of a relation through the SUBJECT's
569
+ * `labelRole`, so a bar and the lifeline it answers have to agree on where a
570
+ * name is. Declaring `uml:label` here instead would leave every participant
571
+ * nameless in the panel opened on a bar, and a reading that says a message came
572
+ * from nowhere is worse than one that says nothing.
573
+ */
574
+ export const UML_EXECUTION_READING = profile('uml-execution', UML_ROLE.execution, UML_ROLE['lifeline-ident'], MESSAGE);
575
+ export const UML_DESTRUCTION_READING = profile('uml-destruction', UML_ROLE.destruction, UML_ROLE['lifeline-ident'], MESSAGE);
576
+ /**
577
+ * The two PARENTS, and the reason they are read at all.
578
+ *
579
+ * `uml:control-node` and `uml:pseudostate` are the generalisations §15.3.4 and
580
+ * §14.2.4 give their routing marks, and rules are written on them so that one
581
+ * declaration reaches five children (`rules.ts`). Nothing is ever drawn AS one
582
+ * — every creation command stamps a concrete role — so each of these profiles
583
+ * is a floor rather than an answer: it exists so that a routing mark added to
584
+ * the pack in a later phase is readable from the day its role is filed under
585
+ * its parent, instead of falling through to no reading at all and failing
586
+ * `reading-coverage` in `affine/all`.
587
+ *
588
+ * Registered LAST, after every child, for the reason `uml-node` is: the engine
589
+ * takes the FIRST profile whose `appliesTo` the element's role IS A, so a
590
+ * parent listed early would answer for all five of its children and none of
591
+ * them would ever use its own.
592
+ */
593
+ export const UML_CONTROL_NODE_READING = profile('uml-control-node', UML_ROLE['control-node'], UML_ROLE.label, FLOW);
594
+ export const UML_PSEUDOSTATE_READING = profile('uml-pseudostate', UML_ROLE.pseudostate, UML_ROLE.label, TRANSITION);
595
+ /** Every UML profile, in the order the view extension registers them. */
596
+ export const UML_READINGS = [
597
+ UML_CLASS_READING,
598
+ UML_INTERFACE_READING,
599
+ UML_ENUMERATION_READING,
600
+ UML_OBJECT_READING,
601
+ UML_PACKAGE_READING,
602
+ UML_NOTE_READING,
603
+ UML_ACTOR_READING,
604
+ UML_USE_CASE_READING,
605
+ UML_COMPONENT_READING,
606
+ UML_PORT_READING,
607
+ UML_PROVIDED_INTERFACE_READING,
608
+ UML_REQUIRED_INTERFACE_READING,
609
+ UML_ARTIFACT_READING,
610
+ // The two SPECIALISATIONS before their parent, and the order is load-bearing:
611
+ // `readingProfileFor` takes the FIRST profile whose `appliesTo` the element's
612
+ // role IS A, and `uml:device` is a `uml:node`. With the parent listed first
613
+ // every device would be read as a node and `uml-device` would never fire —
614
+ // the one place in this pack where declaration order changes an answer, which
615
+ // is why `reading.unit.spec.ts` pins it.
616
+ UML_DEVICE_READING,
617
+ UML_EXECUTION_ENVIRONMENT_READING,
618
+ UML_NODE_READING,
619
+ /* ── Phase 2: activities and state machines ──────────────────────────── */
620
+ UML_ACTION_READING,
621
+ UML_INITIAL_READING,
622
+ UML_ACTIVITY_FINAL_READING,
623
+ UML_FLOW_FINAL_READING,
624
+ UML_DECISION_READING,
625
+ UML_FORK_READING,
626
+ UML_OBJECT_NODE_READING,
627
+ UML_SEND_SIGNAL_READING,
628
+ UML_ACCEPT_EVENT_READING,
629
+ UML_TIME_EVENT_READING,
630
+ UML_STATE_READING,
631
+ UML_FINAL_STATE_READING,
632
+ UML_CHOICE_READING,
633
+ UML_JUNCTION_READING,
634
+ UML_SHALLOW_HISTORY_READING,
635
+ UML_DEEP_HISTORY_READING,
636
+ UML_ENTRY_POINT_READING,
637
+ UML_EXIT_POINT_READING,
638
+ UML_TERMINATE_READING,
639
+ /* ── Phase 3: sequence diagrams ──────────────────────────────────────── */
640
+ UML_LIFELINE_READING,
641
+ UML_EXECUTION_READING,
642
+ UML_DESTRUCTION_READING,
643
+ // The two PARENTS last, after every child — the same rule the deployment
644
+ // cubes above obey, and for the same reason: the engine takes the FIRST
645
+ // profile the element's role IS A.
646
+ UML_CONTROL_NODE_READING,
647
+ UML_PSEUDOSTATE_READING,
648
+ ];