@formicoidea/labre-framework-wardley 0.32.0 → 0.34.1
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/actions.d.ts +49 -2
- package/dist/actions.js +113 -21
- package/dist/commands-manifest.d.ts +18 -0
- package/dist/commands-manifest.js +146 -0
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +166 -4
- package/dist/element-view.d.ts +22 -0
- package/dist/element-view.js +35 -12
- package/dist/export.d.ts +211 -0
- package/dist/export.js +655 -0
- package/dist/gradient.js +1 -1
- package/dist/import.d.ts +116 -0
- package/dist/import.js +905 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +22 -0
- package/dist/interchange.d.ts +80 -0
- package/dist/interchange.js +138 -0
- package/dist/node/node-renderer.js +1 -1
- package/dist/rules.js +16 -0
- package/dist/templates/index.js +15 -3
- package/dist/templates/maps.js +26 -6
- package/dist/toolbar/config.d.ts +10 -2
- package/dist/toolbar/config.js +12 -5
- package/dist/toolbar/icons.d.ts +20 -0
- package/dist/toolbar/icons.js +34 -0
- package/dist/toolbar/senior-tool.js +1 -0
- package/dist/toolbar/wardley-senior-button.js +12 -6
- package/dist/translations.js +8 -2
- package/dist/view.js +13 -2
- package/package.json +6 -2
package/dist/element-view.js
CHANGED
|
@@ -18,11 +18,15 @@ export class WardleyView extends GfxElementModelView {
|
|
|
18
18
|
this._closeLabelEditor();
|
|
19
19
|
super.onDestroyed();
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The editable label under a MODEL-space point, or null.
|
|
23
|
+
*
|
|
24
|
+
* Which labels exist, where they sit, what they SAY and which are editable
|
|
25
|
+
* all come from the declaration the renderer paints — one source, resolved
|
|
26
|
+
* through the same catalogue, so a label can never be drawn in one place
|
|
27
|
+
* and clicked in another, nor read one thing and open on another.
|
|
28
|
+
*/
|
|
29
|
+
_labelAt(mx, my) {
|
|
26
30
|
const [bx, by, w, h] = this.model.deserializedXYWH;
|
|
27
31
|
// Convert the model-space point into element-local coordinates, undoing the
|
|
28
32
|
// element rotation around its center.
|
|
@@ -35,15 +39,34 @@ export class WardleyView extends GfxElementModelView {
|
|
|
35
39
|
lx = ux - bx;
|
|
36
40
|
ly = uy - by;
|
|
37
41
|
}
|
|
38
|
-
// Which labels exist, where they sit, what they SAY and which are editable
|
|
39
|
-
// all come from the declaration the renderer paints — one source, resolved
|
|
40
|
-
// through the same catalogue, so a label can never be drawn in one place
|
|
41
|
-
// and clicked in another, nor read one thing and open on another.
|
|
42
42
|
const hit = hitTestBackgroundLabel(backgroundLabelHits(WARDLEY_BACKGROUND, this.model, w, h, this.gfx.std.getOptional(TranslationProvider)), lx, ly);
|
|
43
|
-
if (!hit)
|
|
44
|
-
return;
|
|
45
43
|
// The declaration names the prop; this decides whether it may be written.
|
|
46
|
-
if (!isWardleyLabelProp(hit.prop))
|
|
44
|
+
if (!hit || !isWardleyLabelProp(hit.prop))
|
|
45
|
+
return null;
|
|
46
|
+
return { prop: hit.prop, text: hit.text };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The map is SELECTED by its border (`WardleyBackgroundElementModel`), but
|
|
50
|
+
* its axis labels must still receive the double-click that renames them.
|
|
51
|
+
*
|
|
52
|
+
* So the two areas differ, and this is where they are allowed to: the pointer
|
|
53
|
+
* router asks the VIEW (`GfxViewEventManager`), and the view adds the zones
|
|
54
|
+
* the declaration draws its labels in. Picking is unaffected —
|
|
55
|
+
* `getElementByPoint` still asks the model, so a click in the middle of the
|
|
56
|
+
* map still goes to whatever the user put there.
|
|
57
|
+
*/
|
|
58
|
+
includesPoint(x, y, options, host) {
|
|
59
|
+
if (super.includesPoint(x, y, options, host))
|
|
60
|
+
return true;
|
|
61
|
+
return this._labelAt(x, y) !== null;
|
|
62
|
+
}
|
|
63
|
+
/** Double-click on a label → edit its text in place. */
|
|
64
|
+
_onDblClick(e) {
|
|
65
|
+
if (this.model.isLocked())
|
|
66
|
+
return;
|
|
67
|
+
const [mx, my] = this.gfx.viewport.toModelCoord(e.x, e.y);
|
|
68
|
+
const hit = this._labelAt(mx, my);
|
|
69
|
+
if (!hit)
|
|
47
70
|
return;
|
|
48
71
|
this._openLabelEditor(hit.prop, hit.text, e);
|
|
49
72
|
}
|
package/dist/export.d.ts
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { ConnectorElementModel, TextElementModel, WardleyBackgroundElementModel, WardleyNodeElementModel } from '@formicoidea/labre-core/model';
|
|
2
|
+
import type { GfxPrimitiveElementModel } from '@formicoidea/labre-core/std/gfx';
|
|
3
|
+
/**
|
|
4
|
+
* A Wardley map as an OnlineWardleyMaps (OWM) DSL document — models in, text
|
|
5
|
+
* out (`docs/adr/0012`, P3).
|
|
6
|
+
*
|
|
7
|
+
* This is the function ADR 0012 records as owed: the Wardley serializer that
|
|
8
|
+
* exists today in **labre-mcp**, outside this repo, and is the ADR's one named
|
|
9
|
+
* violation of P3. It lands here so that both consumers — the editor command
|
|
10
|
+
* and the MCP tool — call one implementation, tested once, and so that the
|
|
11
|
+
* reader next door (`import.ts`) has a writer it agrees with about every
|
|
12
|
+
* coordinate, name and carried line.
|
|
13
|
+
*
|
|
14
|
+
* ## Pure, like its BPMN sibling
|
|
15
|
+
*
|
|
16
|
+
* Element models in, a string out. No `BlockStdScope`, no surface, no DOM, no
|
|
17
|
+
* clock, no randomness. `interchange.ts` is the thin adapter that names the
|
|
18
|
+
* file; `actions.ts` is the thinner one that downloads it.
|
|
19
|
+
*
|
|
20
|
+
* ## The plot IS the coordinate
|
|
21
|
+
*
|
|
22
|
+
* A Wardley node carries **no** `visibility` and **no** `evolution` prop — its
|
|
23
|
+
* position on the map's plot is the whole of what the map says about it. So the
|
|
24
|
+
* writer inverts the projection the reader applied: a node's centre, measured
|
|
25
|
+
* against the plot of the background it sits on, is the `[visibility,
|
|
26
|
+
* evolution]` pair OWM spells. Both numbers are written to exactly **two
|
|
27
|
+
* decimals**, and that stability is load-bearing rather than cosmetic: the
|
|
28
|
+
* fixed point `export(import(export(board)))` is byte-identical only because a
|
|
29
|
+
* value that survives one rounding survives every one after it. The reader
|
|
30
|
+
* tolerates any precision a foreign file happens to use.
|
|
31
|
+
*
|
|
32
|
+
* ## A name is a separate element, so it has to be found
|
|
33
|
+
*
|
|
34
|
+
* On this canvas the name of an artefact is a free text element beside it, not
|
|
35
|
+
* a prop on it (`roles.ts`, `WARDLEY_ROLE.label`). The writer therefore matches
|
|
36
|
+
* each label to the node it names by comparing where the label IS with where a
|
|
37
|
+
* label for that node WOULD be — see {@link matchLabels}, which is the one
|
|
38
|
+
* heuristic in this module and is documented as one.
|
|
39
|
+
*
|
|
40
|
+
* ## v1 reads one map
|
|
41
|
+
*
|
|
42
|
+
* An OWM document is one map. A surface holding several Wardley backgrounds is
|
|
43
|
+
* serialized against the FIRST in document order, and the export warns; the
|
|
44
|
+
* other maps' artefacts are written against that first plot, which is the
|
|
45
|
+
* honest behaviour (nothing is dropped) and is named in the warning so nobody
|
|
46
|
+
* discovers it from a file.
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* The format id, and therefore THE KEY foreign matter rides under on an element
|
|
50
|
+
* (ADR 0012, D2) — `interchange.owm`. Declared here and re-exported by
|
|
51
|
+
* `import.ts`, so a reader filing a fragment and a writer looking one up cannot
|
|
52
|
+
* disagree about where it went.
|
|
53
|
+
*/
|
|
54
|
+
export declare const WARDLEY_OWM_FORMAT_ID = "owm";
|
|
55
|
+
/**
|
|
56
|
+
* OWM's scope vocabulary — where a carried line came off (D2).
|
|
57
|
+
*
|
|
58
|
+
* The DSL is a flat list of statements with no nesting and no ids, so it needs
|
|
59
|
+
* exactly two `@`-prefixed role keys and never an element id:
|
|
60
|
+
*
|
|
61
|
+
* - `@document` — the whole file: the lines this reader has no artefact for,
|
|
62
|
+
* and the `title` it consumed. They ride on the map's background element,
|
|
63
|
+
* which is D6's stated asymmetry (delete the map and the residue goes with
|
|
64
|
+
* it) and is where `profileId` already lives for the same reason.
|
|
65
|
+
* - `@self` — the line an element WAS. Used for the verbatim tail of a mapped
|
|
66
|
+
* line, i.e. everything the writer would otherwise drop: `label [x, y]`,
|
|
67
|
+
* `(build)`, `inertia`, a trailing comment.
|
|
68
|
+
*/
|
|
69
|
+
export declare const OWM_SCOPE: {
|
|
70
|
+
readonly document: "@document";
|
|
71
|
+
readonly self: "@self";
|
|
72
|
+
};
|
|
73
|
+
/** Where a mapped line's un-modelled tail is filed, under `attrs['@self']`. */
|
|
74
|
+
export declare const OWM_TAIL_ATTR = "tail";
|
|
75
|
+
/** Where the file's own `title` is filed, under `attrs['@document']`. */
|
|
76
|
+
export declare const OWM_TITLE_ATTR = "title";
|
|
77
|
+
/**
|
|
78
|
+
* Keywords a line may open on, none of which can be a bare component name.
|
|
79
|
+
*
|
|
80
|
+
* Two different parsers care. `BaseStrategyRunner` claims a line for a keyword
|
|
81
|
+
* when the TRIMMED line opens on `"<keyword> "`, and `LinksExtractionStrategy`
|
|
82
|
+
* refuses to read a line as a link when it opens on any of these — so a
|
|
83
|
+
* component genuinely called `style` would silently stop being linkable. The
|
|
84
|
+
* writer quotes such a name rather than betting nobody ever picks one.
|
|
85
|
+
*/
|
|
86
|
+
export declare const OWM_KEYWORDS: Set<string>;
|
|
87
|
+
/**
|
|
88
|
+
* A name as the DSL spells it — bare when it can be, quoted and escaped
|
|
89
|
+
* otherwise.
|
|
90
|
+
*
|
|
91
|
+
* The escaping mirrors OWM's own `escapeComponentNameForMapText` /
|
|
92
|
+
* `unescapeComponentNameFromMapText` pair character for character, which is
|
|
93
|
+
* what makes `"Vente retail thés, accessoires, coffrets"` come back with its
|
|
94
|
+
* commas and its accents intact.
|
|
95
|
+
*/
|
|
96
|
+
export declare function owmName(raw: string): string;
|
|
97
|
+
/** A name in quotes, escaped as OWM's `escapeComponentNameForMapText` does. */
|
|
98
|
+
export declare function owmQuote(raw: string): string;
|
|
99
|
+
/**
|
|
100
|
+
* A coordinate, to exactly two decimals — the whole of the fixed point's
|
|
101
|
+
* arithmetic.
|
|
102
|
+
*
|
|
103
|
+
* `-0` is written as `0.00`, because `(-0).toFixed(2)` is `"-0.00"` and a
|
|
104
|
+
* node dropped one pixel above the plot's top edge would otherwise produce a
|
|
105
|
+
* file whose bytes depend on which side of zero a float landed on. A
|
|
106
|
+
* non-finite value (an element with no geometry) is written as `0.00` rather
|
|
107
|
+
* than as `NaN`, which no parser reads.
|
|
108
|
+
*/
|
|
109
|
+
export declare function owmNumber(value: number): string;
|
|
110
|
+
/** The plot of a map, in ABSOLUTE surface units. */
|
|
111
|
+
export interface OwmPlot {
|
|
112
|
+
/** Surface x of evolution `0`, and y of visibility `1`. */
|
|
113
|
+
x0: number;
|
|
114
|
+
y0: number;
|
|
115
|
+
width: number;
|
|
116
|
+
height: number;
|
|
117
|
+
}
|
|
118
|
+
/** The reference map an import lays out on, and an export falls back to. */
|
|
119
|
+
export declare const OWM_DEFAULT_MAP_WIDTH: number;
|
|
120
|
+
export declare const OWM_DEFAULT_MAP_HEIGHT: number;
|
|
121
|
+
/**
|
|
122
|
+
* The plot of a background element, in absolute units — the declaration's
|
|
123
|
+
* margins, never a hand-written inset.
|
|
124
|
+
*
|
|
125
|
+
* `templates/maps.ts` learned this the hard way: a plot copied as four numbers
|
|
126
|
+
* drifted from the drawn one, and a rule measuring against the declaration then
|
|
127
|
+
* judged nodes laid out against the copy. Both directions of this format read
|
|
128
|
+
* the same function for the same reason.
|
|
129
|
+
*/
|
|
130
|
+
export declare function owmPlotOf(bound: {
|
|
131
|
+
x: number;
|
|
132
|
+
y: number;
|
|
133
|
+
w: number;
|
|
134
|
+
h: number;
|
|
135
|
+
}): OwmPlot;
|
|
136
|
+
/** The default plot: a reference map at the origin. */
|
|
137
|
+
export declare function owmDefaultPlot(): OwmPlot;
|
|
138
|
+
/**
|
|
139
|
+
* `[visibility, evolution]` → a surface point.
|
|
140
|
+
*
|
|
141
|
+
* Mind the inversion, which is the one thing about these axes that is easy to
|
|
142
|
+
* get backwards and impossible to see in a test that only round-trips: OWM's
|
|
143
|
+
* visibility `1.0` is the TOP of the value chain, and a canvas' y grows
|
|
144
|
+
* downwards.
|
|
145
|
+
*/
|
|
146
|
+
export declare function owmPointOf(plot: OwmPlot, visibility: number, evolution: number): [number, number];
|
|
147
|
+
/** A surface point → `[visibility, evolution]`. The exact inverse. */
|
|
148
|
+
export declare function owmCoordsOf(plot: OwmPlot, x: number, y: number): {
|
|
149
|
+
visibility: number;
|
|
150
|
+
evolution: number;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* The artefacts the writer speaks about, picked out of a surface's elements and
|
|
154
|
+
* kept in the order they were given.
|
|
155
|
+
*
|
|
156
|
+
* Document order matters for the same reason it does in BPMN: it decides which
|
|
157
|
+
* map is THE map when a board holds several, and it is the order every section
|
|
158
|
+
* of the produced file is written in — so a file exported twice from an
|
|
159
|
+
* untouched board is the same file, byte for byte.
|
|
160
|
+
*
|
|
161
|
+
* `notes` is every text element with NO role. That is a deliberate reading and
|
|
162
|
+
* not a leak: an OWM `note` IS a free text at a position, so a text somebody
|
|
163
|
+
* dropped on the map is written as one. Only a text carrying the `label` role
|
|
164
|
+
* is a name, and only a name is resolved onto a node.
|
|
165
|
+
*/
|
|
166
|
+
export interface WardleyExportBoard {
|
|
167
|
+
maps: WardleyBackgroundElementModel[];
|
|
168
|
+
nodes: WardleyNodeElementModel[];
|
|
169
|
+
labels: TextElementModel[];
|
|
170
|
+
notes: TextElementModel[];
|
|
171
|
+
connectors: ConnectorElementModel[];
|
|
172
|
+
}
|
|
173
|
+
export declare function wardleyBoardFrom(elements: readonly GfxPrimitiveElementModel[]): WardleyExportBoard;
|
|
174
|
+
/**
|
|
175
|
+
* A name a file system will accept, minus the extension. BPMN's sanitizer,
|
|
176
|
+
* verbatim in behaviour and different only in its fallback — `map`, because
|
|
177
|
+
* that is what an OWM document is.
|
|
178
|
+
*/
|
|
179
|
+
export declare function wardleySafeFilename(raw: string | undefined): string;
|
|
180
|
+
/** The label box an import writes, and the width a prediction assumes. */
|
|
181
|
+
export declare const OWM_LABEL_WIDTH = 200;
|
|
182
|
+
export declare const OWM_LABEL_HEIGHT: number;
|
|
183
|
+
/** A text element's string, whether it is a `Y.Text` or a test's plain one. */
|
|
184
|
+
export declare function textOf(element: {
|
|
185
|
+
text?: unknown;
|
|
186
|
+
}): string;
|
|
187
|
+
export interface WardleyOwmExportOptions {
|
|
188
|
+
/** The board's own title, already sanitized by the caller. */
|
|
189
|
+
name?: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The board as an OWM document, plus what the format could not say.
|
|
193
|
+
*
|
|
194
|
+
* Sections in a fixed order — title, nodes, pipelines, notes, evolutions,
|
|
195
|
+
* links, carried lines — and DOCUMENT order inside each. That pairing is what
|
|
196
|
+
* makes the fixed point hold: the reader creates elements in the order it meets
|
|
197
|
+
* them, so a file's sections come back as a document whose order re-sections
|
|
198
|
+
* identically.
|
|
199
|
+
*/
|
|
200
|
+
export declare function exportWardleyOwmWithWarnings(board: WardleyExportBoard, options?: WardleyOwmExportOptions): {
|
|
201
|
+
text: string;
|
|
202
|
+
warnings: string[];
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* The board as an OWM document — models in, text out, and nothing else.
|
|
206
|
+
*
|
|
207
|
+
* The signature P3 names: exported from this package's index so that labre-mcp
|
|
208
|
+
* calls THIS function rather than keeping the copy ADR 0012 records as the one
|
|
209
|
+
* violation of it.
|
|
210
|
+
*/
|
|
211
|
+
export declare function exportWardleyOwm(board: WardleyExportBoard, options?: WardleyOwmExportOptions): string;
|