@formicoidea/labre-framework-c4 0.40.0 → 0.41.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/dist/actions.js +31 -7
- package/dist/consts.d.ts +24 -0
- package/dist/consts.js +24 -0
- package/dist/legend.d.ts +3 -35
- package/dist/legend.js +27 -1
- package/dist/morph.js +2 -2
- package/dist/node/type-line-watcher.js +6 -1
- package/dist/templates.js +2 -0
- package/dist/translations.js +40 -1
- package/dist/type-line.d.ts +45 -8
- package/dist/type-line.js +133 -16
- package/package.json +3 -3
package/dist/actions.js
CHANGED
|
@@ -7,12 +7,12 @@ import { downloadBlob } from '@formicoidea/labre-core/shared/utils';
|
|
|
7
7
|
import { Bound } from '@formicoidea/labre-core/global/gfx';
|
|
8
8
|
import { GfxControllerIdentifier, } from '@formicoidea/labre-core/std/gfx';
|
|
9
9
|
import { c4TierBoxes } from './component.js';
|
|
10
|
-
import { BOARD_REF_HEIGHT, BOARD_REF_WIDTH, BOUNDARY_LABEL, BOUNDARY_REF_HEIGHT, BOUNDARY_REF_WIDTH, DESCRIPTION_FONT_SIZE, DESCRIPTION_PLACEHOLDER, NODE_LABEL, NODE_PALETTE, NODE_SIZE, RELATIONSHIP_STROKE, RELATIONSHIP_WIDTH, TITLE_FONT_SIZE, TYPE_FONT_SIZE, } from './consts.js';
|
|
10
|
+
import { BOARD_REF_HEIGHT, BOARD_REF_WIDTH, BOUNDARY_LABEL, boundaryLabelKey, BOUNDARY_REF_HEIGHT, BOUNDARY_REF_WIDTH, DESCRIPTION_FONT_SIZE, DESCRIPTION_PLACEHOLDER, DESCRIPTION_PLACEHOLDER_KEY, NODE_LABEL, nodeLabelKey, NODE_PALETTE, NODE_SIZE, RELATIONSHIP_STROKE, RELATIONSHIP_WIDTH, TITLE_FONT_SIZE, TYPE_FONT_SIZE, } from './consts.js';
|
|
11
11
|
import { C4_MERMAID_EXPORT, c4BoardFrom, c4SafeFilename } from './interchange.js';
|
|
12
12
|
import { C4_AUTO_LEGEND } from './legend.js';
|
|
13
13
|
import { c4NodeProps } from './presets.js';
|
|
14
14
|
import { C4_BOUNDARY_ROLE, C4_ROLE, c4BoardRoleKey } from './roles.js';
|
|
15
|
-
import {
|
|
15
|
+
import { c4TypePlaceholder } from './type-line.js';
|
|
16
16
|
/**
|
|
17
17
|
* Standalone creation/activation actions for the C4 toolbox — the same shape
|
|
18
18
|
* BPMN's `actions.ts` has, and for the same reason: the menu is a pure renderer
|
|
@@ -126,13 +126,34 @@ export function createC4Node(std, kind) {
|
|
|
126
126
|
const boxes = c4TierBoxes(kind, x, y, w, h);
|
|
127
127
|
const titleId = addTier(surface, gfx.layer.generateIndex(), C4_ROLE.title,
|
|
128
128
|
// The kind's own label — `Person`, `Web app`. A name and a prompt at once,
|
|
129
|
-
// which is why the exporter writes it through unchanged.
|
|
130
|
-
|
|
129
|
+
// which is why the exporter writes it through unchanged. Resolved HERE,
|
|
130
|
+
// once, exactly like a BPMN node's caption (`nodeLabelKey`): content from
|
|
131
|
+
// the moment it lands, so a component drawn in a translated host starts in
|
|
132
|
+
// that language.
|
|
133
|
+
translateKey(std, nodeLabelKey(kind), NODE_LABEL[kind]), TITLE_FONT_SIZE,
|
|
131
134
|
// The one tier with weight on it: it is the heading of the box, and at 20px
|
|
132
135
|
// against a 16px sentence the size alone does not carry that.
|
|
133
136
|
FontWeight.SemiBold, paint.text, boxes.title);
|
|
134
|
-
const typeLineId = addTier(surface, gfx.layer.generateIndex(), C4_ROLE['type-line'],
|
|
135
|
-
|
|
137
|
+
const typeLineId = addTier(surface, gfx.layer.generateIndex(), C4_ROLE['type-line'],
|
|
138
|
+
// Resolved at placement, like the title above: `c4TypePlaceholder` reads
|
|
139
|
+
// through the host's catalogue for both halves of the prompt (the
|
|
140
|
+
// bracketed word AND the technology slot), and `C4TypeLineWatcher`
|
|
141
|
+
// (`node/type-line-watcher.ts`) now recomputes the canonical line the same
|
|
142
|
+
// way on every edit commit, so a translated seed here is no longer
|
|
143
|
+
// reverted to English the first time an author opens and closes the
|
|
144
|
+
// tier's editor without typing anything. `technologyOfTypeLine` and
|
|
145
|
+
// `c4StatedTechnology` (`component.ts`) recognise EITHER the English
|
|
146
|
+
// literal or the host's own resolved word (`type-line.ts`).
|
|
147
|
+
c4TypePlaceholder(kind, std), TYPE_FONT_SIZE, FontWeight.Regular, paint.text, boxes.typeLine);
|
|
148
|
+
const descriptionId = addTier(surface, gfx.layer.generateIndex(), C4_ROLE.description,
|
|
149
|
+
// Resolved at placement like the title above. `c4StatedDescription`
|
|
150
|
+
// (`component.ts`) still compares the stored text against the ENGLISH
|
|
151
|
+
// `DESCRIPTION_PLACEHOLDER` to read "nothing stated yet" — this lot's own
|
|
152
|
+
// French proposal for this key is the identical word ('description'), so
|
|
153
|
+
// the shipped catalogue keeps that comparison true; a host catalogue that
|
|
154
|
+
// chose a different wording would regain the same residual risk the type
|
|
155
|
+
// line carries permanently (see `notes`).
|
|
156
|
+
translateKey(std, DESCRIPTION_PLACEHOLDER_KEY, DESCRIPTION_PLACEHOLDER), DESCRIPTION_FONT_SIZE, FontWeight.Regular, paint.text, boxes.description);
|
|
136
157
|
const groupId = surface.addElement({
|
|
137
158
|
type: 'group',
|
|
138
159
|
index: gfx.layer.generateIndex(),
|
|
@@ -209,7 +230,10 @@ export function createC4Boundary(std, variant) {
|
|
|
209
230
|
// role of a boundary drawn before the split and of nothing this editor
|
|
210
231
|
// creates. See the note above.
|
|
211
232
|
role: C4_BOUNDARY_ROLE[variant],
|
|
212
|
-
name
|
|
233
|
+
// Resolved HERE, once — the boundary's name is exported verbatim
|
|
234
|
+
// (`export.ts`) with no placeholder comparison, so it is as safe to
|
|
235
|
+
// translate as a component's title.
|
|
236
|
+
name: translateKey(std, boundaryLabelKey(variant), BOUNDARY_LABEL[variant]),
|
|
213
237
|
variant,
|
|
214
238
|
xywh: new Bound(cx - BOUNDARY_REF_WIDTH / 2, cy - BOUNDARY_REF_HEIGHT / 2, BOUNDARY_REF_WIDTH, BOUNDARY_REF_HEIGHT).serialize(),
|
|
215
239
|
});
|
package/dist/consts.d.ts
CHANGED
|
@@ -246,6 +246,22 @@ export declare const NODE_SIZE: Record<C4NodeKind, {
|
|
|
246
246
|
* nothing at all: the words are the artefact.
|
|
247
247
|
*/
|
|
248
248
|
export declare const NODE_LABEL: Record<C4NodeKind, string>;
|
|
249
|
+
/**
|
|
250
|
+
* The i18n key {@link NODE_LABEL} is the English default of — mirrors BPMN's
|
|
251
|
+
* {@link nodeLabelKey} exactly, one package over: resolved at placement
|
|
252
|
+
* (`createC4Node`, the NAME tier) and never afterwards, since the title is
|
|
253
|
+
* content from the moment it lands and an author is free to retype it.
|
|
254
|
+
*
|
|
255
|
+
* Safe to translate where the type line is not: the exporter reads a
|
|
256
|
+
* component's NAME verbatim (`c4StatedName`) with no placeholder suppression,
|
|
257
|
+
* so nothing downstream compares this text against the English literal.
|
|
258
|
+
*/
|
|
259
|
+
export declare const nodeLabelKey: (kind: C4NodeKind) => string;
|
|
260
|
+
/**
|
|
261
|
+
* The prompt a fresh description tier carries, resolved at placement exactly
|
|
262
|
+
* like {@link DESCRIPTION_PLACEHOLDER} below is the English default of.
|
|
263
|
+
*/
|
|
264
|
+
export declare const DESCRIPTION_PLACEHOLDER_KEY = "com.labre.c4.seed.description-placeholder";
|
|
249
265
|
export declare const FONT_FAMILY = "Inter, sans-serif";
|
|
250
266
|
/**
|
|
251
267
|
* The card — the same white every framework background paints, framed and
|
|
@@ -336,6 +352,14 @@ export declare const BOUNDARY_MARGIN = 12;
|
|
|
336
352
|
* on the canvas keeps its words whatever its variant.
|
|
337
353
|
*/
|
|
338
354
|
export declare const BOUNDARY_LABEL: Record<C4BoundaryVariant, string>;
|
|
355
|
+
/**
|
|
356
|
+
* The i18n key {@link BOUNDARY_LABEL} is the English default of — resolved at
|
|
357
|
+
* placement (`createC4Boundary`) exactly like {@link nodeLabelKey}: the name
|
|
358
|
+
* is exported verbatim (`export.ts`, `boundary.name`) with no comparison
|
|
359
|
+
* against the English literal, so translating it is as safe as a component's
|
|
360
|
+
* title.
|
|
361
|
+
*/
|
|
362
|
+
export declare const boundaryLabelKey: (variant: C4BoundaryVariant) => string;
|
|
339
363
|
/**
|
|
340
364
|
* Relationship connector preset — the dashed arrow C4 draws between elements.
|
|
341
365
|
*
|
package/dist/consts.js
CHANGED
|
@@ -291,6 +291,22 @@ export const NODE_LABEL = {
|
|
|
291
291
|
browser: 'Web app',
|
|
292
292
|
component: 'Component',
|
|
293
293
|
};
|
|
294
|
+
/**
|
|
295
|
+
* The i18n key {@link NODE_LABEL} is the English default of — mirrors BPMN's
|
|
296
|
+
* {@link nodeLabelKey} exactly, one package over: resolved at placement
|
|
297
|
+
* (`createC4Node`, the NAME tier) and never afterwards, since the title is
|
|
298
|
+
* content from the moment it lands and an author is free to retype it.
|
|
299
|
+
*
|
|
300
|
+
* Safe to translate where the type line is not: the exporter reads a
|
|
301
|
+
* component's NAME verbatim (`c4StatedName`) with no placeholder suppression,
|
|
302
|
+
* so nothing downstream compares this text against the English literal.
|
|
303
|
+
*/
|
|
304
|
+
export const nodeLabelKey = (kind) => `com.labre.c4.seed.${kind}`;
|
|
305
|
+
/**
|
|
306
|
+
* The prompt a fresh description tier carries, resolved at placement exactly
|
|
307
|
+
* like {@link DESCRIPTION_PLACEHOLDER} below is the English default of.
|
|
308
|
+
*/
|
|
309
|
+
export const DESCRIPTION_PLACEHOLDER_KEY = 'com.labre.c4.seed.description-placeholder';
|
|
294
310
|
/* ── The board ─────────────────────────────────────────────────────────── */
|
|
295
311
|
export const FONT_FAMILY = 'Inter, sans-serif';
|
|
296
312
|
/**
|
|
@@ -389,6 +405,14 @@ export const BOUNDARY_LABEL = {
|
|
|
389
405
|
system: 'System boundary',
|
|
390
406
|
container: 'Container boundary',
|
|
391
407
|
};
|
|
408
|
+
/**
|
|
409
|
+
* The i18n key {@link BOUNDARY_LABEL} is the English default of — resolved at
|
|
410
|
+
* placement (`createC4Boundary`) exactly like {@link nodeLabelKey}: the name
|
|
411
|
+
* is exported verbatim (`export.ts`, `boundary.name`) with no comparison
|
|
412
|
+
* against the English literal, so translating it is as safe as a component's
|
|
413
|
+
* title.
|
|
414
|
+
*/
|
|
415
|
+
export const boundaryLabelKey = (variant) => `com.labre.c4.seed.boundary-${variant}`;
|
|
392
416
|
/* ── The relationship ──────────────────────────────────────────────────── */
|
|
393
417
|
/**
|
|
394
418
|
* Relationship connector preset — the dashed arrow C4 draws between elements.
|
package/dist/legend.d.ts
CHANGED
|
@@ -1,37 +1,5 @@
|
|
|
1
1
|
import { type AutoLegendSpec } from '@formicoidea/labre-ddd-shared';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* three DDD boards.
|
|
6
|
-
*
|
|
7
|
-
* Every row is DERIVED twice over: its WORDING from the role vocabulary's own
|
|
8
|
-
* `labelFallback` ({@link roleLabel}), and its COLOUR from the very palette the
|
|
9
|
-
* creation site paints with ({@link NODE_PALETTE}). Neither is restated here, so
|
|
10
|
-
* renaming a role renames its legend row and restyling the pack restyles its
|
|
11
|
-
* swatches — which is what keeps a legend a description of the board rather than
|
|
12
|
-
* a second opinion about it.
|
|
13
|
-
*
|
|
14
|
-
* ## Why `exact` on the container, and only there
|
|
15
|
-
*
|
|
16
|
-
* `c4:database` specialises `c4:container`, so an inclusive entry on the parent
|
|
17
|
-
* would put a "Container" row — with the container's blue square — on a board
|
|
18
|
-
* carrying nothing but cylinders. The row would name a shape that is nowhere on
|
|
19
|
-
* the diagram. EDGY's four base kinds hit this first and `AutoLegendEntry.exact`
|
|
20
|
-
* exists for it: base and specialisation become two separate statements, each
|
|
21
|
-
* listed when it is the thing the user actually drew.
|
|
22
|
-
*
|
|
23
|
-
* The other four element roles are childless, so `exact` would change nothing
|
|
24
|
-
* for them and is left off — the flag marks the places where the distinction is
|
|
25
|
-
* real.
|
|
26
|
-
*
|
|
27
|
-
* ## What is missing, and why
|
|
28
|
-
*
|
|
29
|
-
* `mobile` and `browser` get no row of their own: they carry `c4:container`,
|
|
30
|
-
* because a phone app and a single-page app are containers with a picture
|
|
31
|
-
* (`roles.ts`). Detection is by role and only by role, so a board of nothing but
|
|
32
|
-
* mobile apps lists "Container" — which is the honest answer about what the
|
|
33
|
-
* boxes MEAN. `person-ext` and `system-ext` collapse the same way onto person
|
|
34
|
-
* and system, for the same reason: the grey says "out of scope", not "a
|
|
35
|
-
* different sort of thing".
|
|
36
|
-
*/
|
|
2
|
+
import { type ChromeWording } from '@formicoidea/labre-core/shared/services';
|
|
3
|
+
/** Every section `titleKey` above, for `translations.ts`'s manifest. */
|
|
4
|
+
export declare const C4_LEGEND_SECTION_WORDINGS: readonly ChromeWording[];
|
|
37
5
|
export declare const C4_AUTO_LEGEND: AutoLegendSpec;
|
package/dist/legend.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { roleLabel } from '@formicoidea/labre-ddd-shared';
|
|
2
|
+
import { BOARD_LEGEND_TITLE, } from '@formicoidea/labre-core/shared/services';
|
|
2
3
|
import { BOUNDARY_STROKE, NODE_PALETTE, RELATIONSHIP_STROKE } from './consts.js';
|
|
3
4
|
import { C4_ROLE, C4_ROLES } from './roles.js';
|
|
4
5
|
/**
|
|
@@ -36,13 +37,36 @@ import { C4_ROLE, C4_ROLES } from './roles.js';
|
|
|
36
37
|
* and system, for the same reason: the grey says "out of scope", not "a
|
|
37
38
|
* different sort of thing".
|
|
38
39
|
*/
|
|
40
|
+
/** This section's own keys. */
|
|
41
|
+
const SECTION_ELEMENTS = [
|
|
42
|
+
'com.labre.c4.legend.section.elements',
|
|
43
|
+
'Elements',
|
|
44
|
+
];
|
|
45
|
+
const SECTION_FRAMES = [
|
|
46
|
+
'com.labre.c4.legend.section.frames',
|
|
47
|
+
'Frames',
|
|
48
|
+
];
|
|
49
|
+
const SECTION_RELATIONS = [
|
|
50
|
+
'com.labre.c4.legend.section.relations',
|
|
51
|
+
'Relations',
|
|
52
|
+
];
|
|
53
|
+
/** Every section `titleKey` above, for `translations.ts`'s manifest. */
|
|
54
|
+
export const C4_LEGEND_SECTION_WORDINGS = [
|
|
55
|
+
SECTION_ELEMENTS,
|
|
56
|
+
SECTION_FRAMES,
|
|
57
|
+
SECTION_RELATIONS,
|
|
58
|
+
];
|
|
39
59
|
export const C4_AUTO_LEGEND = {
|
|
40
|
-
|
|
60
|
+
// The shared DDD auto-legend box's own generic chrome, resolved through
|
|
61
|
+
// the same key every board that has one reuses — see `AutoLegendSpec.title`.
|
|
62
|
+
title: BOARD_LEGEND_TITLE[1],
|
|
63
|
+
titleKey: BOARD_LEGEND_TITLE[0],
|
|
41
64
|
width: 290,
|
|
42
65
|
roles: C4_ROLES,
|
|
43
66
|
sections: [
|
|
44
67
|
{
|
|
45
68
|
title: 'Elements',
|
|
69
|
+
titleKey: SECTION_ELEMENTS[0],
|
|
46
70
|
entries: [
|
|
47
71
|
{
|
|
48
72
|
role: C4_ROLE.person,
|
|
@@ -90,6 +114,7 @@ export const C4_AUTO_LEGEND = {
|
|
|
90
114
|
},
|
|
91
115
|
{
|
|
92
116
|
title: 'Frames',
|
|
117
|
+
titleKey: SECTION_FRAMES[0],
|
|
93
118
|
entries: [
|
|
94
119
|
{
|
|
95
120
|
role: C4_ROLE.boundary,
|
|
@@ -107,6 +132,7 @@ export const C4_AUTO_LEGEND = {
|
|
|
107
132
|
},
|
|
108
133
|
{
|
|
109
134
|
title: 'Relations',
|
|
135
|
+
titleKey: SECTION_RELATIONS[0],
|
|
110
136
|
entries: [
|
|
111
137
|
{
|
|
112
138
|
role: C4_ROLE.relationship,
|
package/dist/morph.js
CHANGED
|
@@ -167,8 +167,8 @@ function rewriteTier(model, role, decide) {
|
|
|
167
167
|
* "Customer database" keeps that name whatever it becomes, which is the PO's
|
|
168
168
|
* "the label is intact" for every title that is real content.
|
|
169
169
|
*/
|
|
170
|
-
function rewriteTiers(model, from, to) {
|
|
171
|
-
rewriteTier(model, C4_ROLE['type-line'], text => c4MorphedTypeLine(from, to, text));
|
|
170
|
+
function rewriteTiers(model, from, to, std) {
|
|
171
|
+
rewriteTier(model, C4_ROLE['type-line'], text => c4MorphedTypeLine(from, to, text, std));
|
|
172
172
|
rewriteTier(model, C4_ROLE.title, text => c4MorphedTitle(from, to, text));
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
@@ -103,7 +103,12 @@ export class C4TypeLineWatcher extends InteractivityExtension {
|
|
|
103
103
|
if (!kind)
|
|
104
104
|
return;
|
|
105
105
|
const raw = element.text.toString();
|
|
106
|
-
|
|
106
|
+
// `this.std` resolves the canonical line through the host's catalogue —
|
|
107
|
+
// both halves of the prompt, and the technology round-trip
|
|
108
|
+
// (`technologyOfTypeLine`) recognising the host's own resolved word —
|
|
109
|
+
// so a translated document's type line stays in that language across a
|
|
110
|
+
// commit instead of being silently reverted to English (`type-line.ts`).
|
|
111
|
+
const canonical = normalizeC4TypeLine(kind, raw, this.std);
|
|
107
112
|
if (canonical === raw)
|
|
108
113
|
return;
|
|
109
114
|
this.std.store.captureSync();
|
package/dist/templates.js
CHANGED
|
@@ -46,6 +46,8 @@ const boundaryPreview = (inner = '') => `<svg ${ATTRS} fill="none"><rect x="14"
|
|
|
46
46
|
const CONTAINER = NODE_PALETTE.container;
|
|
47
47
|
export const c4TemplateCategory = {
|
|
48
48
|
name: 'C4',
|
|
49
|
+
// Reuses the senior button's own key — see `TemplateCategory.nameKey`.
|
|
50
|
+
nameKey: 'com.labre.framework.c4',
|
|
49
51
|
templates: [
|
|
50
52
|
templateFromCommand(byId('c4.addBoard'), `<svg ${ATTRS} fill="none"><rect x="10" y="10" width="115" height="60" rx="6" fill="${BOARD_CARD_FILL}" stroke="${BOARD_CARD_BORDER}" stroke-width="1.5"/><path d="M10 26 H125" stroke="${BOARD_CARD_BORDER}" stroke-width="1.5"/><rect x="11" y="11" width="113" height="15" fill="${BOARD_BAND_FILL}"/><rect x="20" y="15" width="40" height="6" rx="3" fill="${BOARD_TITLE_COLOR}" opacity="0.55"/><rect x="22" y="36" width="34" height="20" rx="2" fill="${NODE_PALETTE.system.fill}"/><rect x="79" y="36" width="34" height="20" rx="2" fill="${CONTAINER.fill}"/><path d="M58 46 H75" stroke="${RELATIONSHIP_STROKE}" stroke-width="1.6" stroke-dasharray="4 3"/></svg>`),
|
|
51
53
|
templateFromCommand(byId('c4.addPerson'), personPreview('person')),
|
package/dist/translations.js
CHANGED
|
@@ -1,11 +1,50 @@
|
|
|
1
1
|
import { collectTranslationKeys, commandCategoryTranslationEntries, commandTranslationEntries, mergeTranslationEntries, } from '@formicoidea/labre-core/std';
|
|
2
2
|
import { C4_BOARD_BACKGROUND, C4_BOUNDARY_BACKGROUND } from './background.js';
|
|
3
3
|
import { c4Commands } from './commands.js';
|
|
4
|
+
import { BOUNDARY_LABEL, boundaryLabelKey, DESCRIPTION_PLACEHOLDER, DESCRIPTION_PLACEHOLDER_KEY, NODE_LABEL, nodeLabelKey, } from './consts.js';
|
|
5
|
+
import { C4_LEGEND_SECTION_WORDINGS } from './legend.js';
|
|
4
6
|
import { C4_BOARD_LEVEL_MENU } from './levels.js';
|
|
5
7
|
import { C4_PROFILES } from './profiles.js';
|
|
6
8
|
import { C4_READINGS } from './reading.js';
|
|
7
9
|
import { C4_ROLES } from './roles.js';
|
|
8
10
|
import { C4_RULES } from './rules.js';
|
|
11
|
+
import { C4_TYPE_LINE_WORDINGS } from './type-line.js';
|
|
12
|
+
/**
|
|
13
|
+
* The captions a placed component and a placed boundary are seeded with — the
|
|
14
|
+
* fallback IS `NODE_LABEL[kind]` / `BOUNDARY_LABEL[variant]`, never restated,
|
|
15
|
+
* mirroring BPMN's `seedEntries` exactly. The type line's own bracketed word
|
|
16
|
+
* and the technology placeholder ARE here too (`C4_TYPE_LINE_WORDINGS`),
|
|
17
|
+
* resolved at placement (`createC4Node`, `actions.ts`) and rebuilt through the
|
|
18
|
+
* same seam on every edit commit (`C4TypeLineWatcher`).
|
|
19
|
+
*/
|
|
20
|
+
const seedEntries = () => [
|
|
21
|
+
...Object.entries(NODE_LABEL).map(([kind, label]) => ({
|
|
22
|
+
key: nodeLabelKey(kind),
|
|
23
|
+
fallback: label,
|
|
24
|
+
source: 'seed',
|
|
25
|
+
})),
|
|
26
|
+
...Object.entries(BOUNDARY_LABEL).map(([variant, label]) => ({
|
|
27
|
+
key: boundaryLabelKey(variant),
|
|
28
|
+
fallback: label,
|
|
29
|
+
source: 'seed',
|
|
30
|
+
})),
|
|
31
|
+
{
|
|
32
|
+
key: DESCRIPTION_PLACEHOLDER_KEY,
|
|
33
|
+
fallback: DESCRIPTION_PLACEHOLDER,
|
|
34
|
+
source: 'seed',
|
|
35
|
+
},
|
|
36
|
+
...C4_TYPE_LINE_WORDINGS.map(([key, fallback]) => ({
|
|
37
|
+
key,
|
|
38
|
+
fallback,
|
|
39
|
+
source: 'seed',
|
|
40
|
+
})),
|
|
41
|
+
];
|
|
42
|
+
/** The auto-legend's own section titles ({@link C4_LEGEND_SECTION_WORDINGS}). */
|
|
43
|
+
const legendSectionEntries = () => C4_LEGEND_SECTION_WORDINGS.map(([key, fallback]) => ({
|
|
44
|
+
key,
|
|
45
|
+
fallback,
|
|
46
|
+
source: 'chrome',
|
|
47
|
+
}));
|
|
9
48
|
/**
|
|
10
49
|
* THIS framework's contribution to the translation-key manifest — every
|
|
11
50
|
* `com.labre.*` key C4 can hand to `TranslationProvider.t`, derived from the
|
|
@@ -40,7 +79,7 @@ commandCategoryTranslationEntries(c4Commands), collectTranslationKeys('role', C4
|
|
|
40
79
|
// nothing is restated in `affine/all`, so a key added to the picker
|
|
41
80
|
// reaches a host's catalogue by construction.
|
|
42
81
|
C4_BOARD_LEVEL_MENU,
|
|
43
|
-
]),
|
|
82
|
+
]), seedEntries(), legendSectionEntries(),
|
|
44
83
|
// AFTER the two above, and the order is load-bearing: a rule carries its
|
|
45
84
|
// framework's `roles` and, for `c4.person-in-boundary`, the boundary's own
|
|
46
85
|
// declaration, so walking the rules reaches keys those two lists already
|
package/dist/type-line.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { C4NodeKind } from '@formicoidea/labre-core/model';
|
|
2
|
+
import { type ChromeWording } from '@formicoidea/labre-core/shared/services';
|
|
3
|
+
import type { BlockStdScope } from '@formicoidea/labre-core/std';
|
|
2
4
|
/**
|
|
3
5
|
* The middle tier of a C4 element's label — `[Person]`, `[Software System]`,
|
|
4
6
|
* `[Container: Java]` — SEMI-DERIVED: the word comes from the kind, the
|
|
@@ -41,6 +43,7 @@ import type { C4NodeKind } from '@formicoidea/labre-core/model';
|
|
|
41
43
|
* without a word to announce it fails the build here.
|
|
42
44
|
*/
|
|
43
45
|
export declare const C4_TYPE_WORD: Record<C4NodeKind, string>;
|
|
46
|
+
export declare const C4_TYPE_WORD_KEY: Record<C4NodeKind, string>;
|
|
44
47
|
/**
|
|
45
48
|
* The type line as it is drawn, brackets included.
|
|
46
49
|
*
|
|
@@ -49,10 +52,12 @@ export declare const C4_TYPE_WORD: Record<C4NodeKind, string>;
|
|
|
49
52
|
* produce a dangling `[Container: ]`. Whitespace runs collapse for the same
|
|
50
53
|
* reason they do in the mermaid sanitizer: the line is one line.
|
|
51
54
|
*
|
|
52
|
-
* Pure
|
|
53
|
-
*
|
|
55
|
+
* Pure and total; `std` is OPTIONAL and, when given, resolves the bracketed
|
|
56
|
+
* word through the host's catalogue ({@link typeWord}) — the renderer, the
|
|
57
|
+
* exporter and a test can all still ask the same question with no `std` at
|
|
58
|
+
* all and get the same English answer they always have.
|
|
54
59
|
*/
|
|
55
|
-
export declare function c4TypeLine(kind: C4NodeKind, technology?: string): string;
|
|
60
|
+
export declare function c4TypeLine(kind: C4NodeKind, technology?: string, std?: BlockStdScope): string;
|
|
56
61
|
/**
|
|
57
62
|
* The technology an author stated in a type line, whatever shape they left it
|
|
58
63
|
* in — `''` when they stated none.
|
|
@@ -70,8 +75,12 @@ export declare function c4TypeLine(kind: C4NodeKind, technology?: string): strin
|
|
|
70
75
|
* https://x/docs → https://x/docs a colon that is NOT a prefix
|
|
71
76
|
* ```
|
|
72
77
|
*
|
|
73
|
-
* Pure and `std
|
|
74
|
-
*
|
|
78
|
+
* Pure and total; `std` is OPTIONAL, exactly like {@link c4TypeLine} —
|
|
79
|
+
* without it this reads a line the same way it always has, and with it the
|
|
80
|
+
* vocabulary the `<word>:` prefix is matched against ALSO recognises the
|
|
81
|
+
* host's own resolved word ({@link knownTypeWords}), so a line seeded or
|
|
82
|
+
* normalized in a translated host still gives back the right technology
|
|
83
|
+
* rather than the whole line.
|
|
75
84
|
*
|
|
76
85
|
* It deliberately does NOT know about the creation placeholder: a node created
|
|
77
86
|
* and never touched carries `[Container: technology]`, and reading that as "no
|
|
@@ -80,7 +89,7 @@ export declare function c4TypeLine(kind: C4NodeKind, technology?: string): strin
|
|
|
80
89
|
* placeholder is a question for whoever asks what the element STATES, which is
|
|
81
90
|
* the exporter, and it is answered there.
|
|
82
91
|
*/
|
|
83
|
-
export declare function technologyOfTypeLine(text: string | null | undefined): string;
|
|
92
|
+
export declare function technologyOfTypeLine(text: string | null | undefined, std?: BlockStdScope): string;
|
|
84
93
|
/**
|
|
85
94
|
* A type line as it must be STORED, whatever was typed into it.
|
|
86
95
|
*
|
|
@@ -91,8 +100,14 @@ export declare function technologyOfTypeLine(text: string | null | undefined): s
|
|
|
91
100
|
*
|
|
92
101
|
* Idempotent by construction — `normalize(normalize(x)) === normalize(x)` —
|
|
93
102
|
* which is what lets it run on every commit without a guard.
|
|
103
|
+
*
|
|
104
|
+
* `std` is OPTIONAL and, when given, is threaded to both halves: the
|
|
105
|
+
* technology is read back recognising the host's own word
|
|
106
|
+
* ({@link technologyOfTypeLine}) and the line is rebuilt with it
|
|
107
|
+
* ({@link c4TypeLine}) — see `C4TypeLineWatcher`, the one real caller that
|
|
108
|
+
* has an `std` to give it.
|
|
94
109
|
*/
|
|
95
|
-
export declare function normalizeC4TypeLine(kind: C4NodeKind, rawText: string | null | undefined): string;
|
|
110
|
+
export declare function normalizeC4TypeLine(kind: C4NodeKind, rawText: string | null | undefined, std?: BlockStdScope): string;
|
|
96
111
|
/**
|
|
97
112
|
* The word a fresh type line prompts the author with, in the technology's slot.
|
|
98
113
|
*
|
|
@@ -101,6 +116,19 @@ export declare function normalizeC4TypeLine(kind: C4NodeKind, rawText: string |
|
|
|
101
116
|
* {@link C4_TYPE_PLACEHOLDER}.
|
|
102
117
|
*/
|
|
103
118
|
export declare const TYPE_TECHNOLOGY_PLACEHOLDER = "technology";
|
|
119
|
+
/**
|
|
120
|
+
* {@link TYPE_TECHNOLOGY_PLACEHOLDER}'s own key — see the long comment on
|
|
121
|
+
* {@link C4_TYPE_WORD_KEY} for why this lot's shipped French proposal keeps
|
|
122
|
+
* it identical to English.
|
|
123
|
+
*/
|
|
124
|
+
export declare const C4_TECHNOLOGY_PLACEHOLDER_KEY = "com.labre.c4.type.technology-placeholder";
|
|
125
|
+
/**
|
|
126
|
+
* Every wording this file writes onto the canvas, for `translations.ts`'s
|
|
127
|
+
* manifest contribution — the four distinct type words plus the technology
|
|
128
|
+
* prompt, all `seed` (written into the document once, at placement or at a
|
|
129
|
+
* commit the watcher normalizes).
|
|
130
|
+
*/
|
|
131
|
+
export declare const C4_TYPE_LINE_WORDINGS: readonly ChromeWording[];
|
|
104
132
|
/**
|
|
105
133
|
* Which kinds announce a technology in their type line AT ALL.
|
|
106
134
|
*
|
|
@@ -131,6 +159,15 @@ export declare const C4_TYPE_TAKES_TECHNOLOGY: Record<C4NodeKind, boolean>;
|
|
|
131
159
|
* with a technology literally called "technology".
|
|
132
160
|
*/
|
|
133
161
|
export declare const C4_TYPE_PLACEHOLDER: Record<C4NodeKind, string>;
|
|
162
|
+
/**
|
|
163
|
+
* {@link C4_TYPE_PLACEHOLDER}, resolved through `std` when given — the
|
|
164
|
+
* placement site (`createC4Node`, `actions.ts`) seeds a fresh element with
|
|
165
|
+
* this rather than the English-only constant, so a component drawn in a
|
|
166
|
+
* translated host starts in that language, like every other seed
|
|
167
|
+
* (`docs/adr/0016`). With no `std` this returns exactly
|
|
168
|
+
* `C4_TYPE_PLACEHOLDER[kind]`.
|
|
169
|
+
*/
|
|
170
|
+
export declare function c4TypePlaceholder(kind: C4NodeKind, std?: BlockStdScope): string;
|
|
134
171
|
/**
|
|
135
172
|
* The type line a component should carry once its shape has morphed from `from`
|
|
136
173
|
* to `to` — or `null` when the line is the AUTHOR's and must not be touched.
|
|
@@ -172,4 +209,4 @@ export declare const C4_TYPE_PLACEHOLDER: Record<C4NodeKind, string>;
|
|
|
172
209
|
*
|
|
173
210
|
* Pure, total and `std`-free, like everything else in this file.
|
|
174
211
|
*/
|
|
175
|
-
export declare function c4MorphedTypeLine(from: C4NodeKind, to: C4NodeKind, rawText: string | null | undefined): string | null;
|
|
212
|
+
export declare function c4MorphedTypeLine(from: C4NodeKind, to: C4NodeKind, rawText: string | null | undefined, std?: BlockStdScope): string | null;
|
package/dist/type-line.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { translateKey, } from '@formicoidea/labre-core/shared/services';
|
|
1
2
|
/**
|
|
2
3
|
* The middle tier of a C4 element's label — `[Person]`, `[Software System]`,
|
|
3
4
|
* `[Container: Java]` — SEMI-DERIVED: the word comes from the kind, the
|
|
@@ -50,6 +51,51 @@ export const C4_TYPE_WORD = {
|
|
|
50
51
|
browser: 'Container',
|
|
51
52
|
component: 'Component',
|
|
52
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* {@link C4_TYPE_WORD}'s own i18n key, one per DISTINCT word (four kinds
|
|
56
|
+
* share `Container`, two share `Person`, two share `Software System`, one
|
|
57
|
+
* word each carries one key).
|
|
58
|
+
*
|
|
59
|
+
* The PO's own glossary (`brief-i18n.md`) names "Software System",
|
|
60
|
+
* "Container" and "Component" franglais — the French proposal IS the English
|
|
61
|
+
* word — and this lot extends the same choice to "Person" and to
|
|
62
|
+
* {@link TYPE_TECHNOLOGY_PLACEHOLDER}, for a reason beyond consistency: this
|
|
63
|
+
* whole file's comparisons (`technologyOfTypeLine`, `C4_TYPE_PLACEHOLDER`,
|
|
64
|
+
* `c4StatedTechnology` in `component.ts`) read the STORED text back against
|
|
65
|
+
* these very words, and `c4StatedTechnology` runs from the `std`-free exporter
|
|
66
|
+
* (`export.ts`, ADR 0012 P3) — it cannot ask a host's catalogue at all. Keeping
|
|
67
|
+
* the shipped French wording IDENTICAL to English is what keeps that
|
|
68
|
+
* comparison correct on a document seeded in French. A host that overrides
|
|
69
|
+
* the catalogue with a genuinely different word regains the risk the
|
|
70
|
+
* `DESCRIPTION_PLACEHOLDER_KEY` comment in `consts.ts` already names for the
|
|
71
|
+
* description tier.
|
|
72
|
+
*/
|
|
73
|
+
// Named constants rather than the key literals inline: `manifest.unit.spec.ts`
|
|
74
|
+
// reads two adjacent single-quoted literals in one argument list as a
|
|
75
|
+
// key/fallback PAIR, with no anchor on `translateKey(` — and a `Record`
|
|
76
|
+
// spelling each key out beside the NEXT (quoted, hyphenated) property name
|
|
77
|
+
// below it reads exactly like one. Referencing an identifier instead of
|
|
78
|
+
// repeating the literal sidesteps the false pairing.
|
|
79
|
+
const PERSON_KEY = 'com.labre.c4.type.person';
|
|
80
|
+
const SYSTEM_KEY = 'com.labre.c4.type.system';
|
|
81
|
+
const CONTAINER_KEY = 'com.labre.c4.type.container';
|
|
82
|
+
const COMPONENT_KEY = 'com.labre.c4.type.component';
|
|
83
|
+
export const C4_TYPE_WORD_KEY = {
|
|
84
|
+
person: PERSON_KEY,
|
|
85
|
+
'person-ext': PERSON_KEY,
|
|
86
|
+
system: SYSTEM_KEY,
|
|
87
|
+
'system-ext': SYSTEM_KEY,
|
|
88
|
+
container: CONTAINER_KEY,
|
|
89
|
+
database: CONTAINER_KEY,
|
|
90
|
+
mobile: CONTAINER_KEY,
|
|
91
|
+
browser: CONTAINER_KEY,
|
|
92
|
+
component: COMPONENT_KEY,
|
|
93
|
+
};
|
|
94
|
+
/** The word an `std` (when given) resolves {@link kind}'s bracket to. */
|
|
95
|
+
function typeWord(kind, std) {
|
|
96
|
+
const english = C4_TYPE_WORD[kind];
|
|
97
|
+
return std ? translateKey(std, C4_TYPE_WORD_KEY[kind], english) : english;
|
|
98
|
+
}
|
|
53
99
|
/**
|
|
54
100
|
* The type line as it is drawn, brackets included.
|
|
55
101
|
*
|
|
@@ -58,11 +104,13 @@ export const C4_TYPE_WORD = {
|
|
|
58
104
|
* produce a dangling `[Container: ]`. Whitespace runs collapse for the same
|
|
59
105
|
* reason they do in the mermaid sanitizer: the line is one line.
|
|
60
106
|
*
|
|
61
|
-
* Pure
|
|
62
|
-
*
|
|
107
|
+
* Pure and total; `std` is OPTIONAL and, when given, resolves the bracketed
|
|
108
|
+
* word through the host's catalogue ({@link typeWord}) — the renderer, the
|
|
109
|
+
* exporter and a test can all still ask the same question with no `std` at
|
|
110
|
+
* all and get the same English answer they always have.
|
|
63
111
|
*/
|
|
64
|
-
export function c4TypeLine(kind, technology) {
|
|
65
|
-
const word =
|
|
112
|
+
export function c4TypeLine(kind, technology, std) {
|
|
113
|
+
const word = typeWord(kind, std);
|
|
66
114
|
const techn = (technology ?? '').replaceAll(/\s+/g, ' ').trim();
|
|
67
115
|
return techn ? `[${word}: ${techn}]` : `[${word}]`;
|
|
68
116
|
}
|
|
@@ -82,6 +130,22 @@ export function c4TypeLine(kind, technology) {
|
|
|
82
130
|
* instead can only ever strip a word the notation itself writes.
|
|
83
131
|
*/
|
|
84
132
|
const KNOWN_TYPE_WORDS = new Set(Object.values(C4_TYPE_WORD).map(word => word.toLowerCase()));
|
|
133
|
+
/**
|
|
134
|
+
* {@link KNOWN_TYPE_WORDS}, plus the host-resolved word of every kind when
|
|
135
|
+
* `std` is given — so a line seeded in a translated host (`c4TypeLine(kind,
|
|
136
|
+
* …, std)` at placement, or after a commit the watcher rebuilt) is still
|
|
137
|
+
* recognised as carrying THE NOTATION'S word and not a technology typed on
|
|
138
|
+
* its own. With no `std` this is exactly {@link KNOWN_TYPE_WORDS}.
|
|
139
|
+
*/
|
|
140
|
+
function knownTypeWords(std) {
|
|
141
|
+
if (!std)
|
|
142
|
+
return KNOWN_TYPE_WORDS;
|
|
143
|
+
const words = new Set(KNOWN_TYPE_WORDS);
|
|
144
|
+
for (const kind of Object.keys(C4_TYPE_WORD)) {
|
|
145
|
+
words.add(typeWord(kind, std).toLowerCase());
|
|
146
|
+
}
|
|
147
|
+
return words;
|
|
148
|
+
}
|
|
85
149
|
/**
|
|
86
150
|
* The technology an author stated in a type line, whatever shape they left it
|
|
87
151
|
* in — `''` when they stated none.
|
|
@@ -99,8 +163,12 @@ const KNOWN_TYPE_WORDS = new Set(Object.values(C4_TYPE_WORD).map(word => word.to
|
|
|
99
163
|
* https://x/docs → https://x/docs a colon that is NOT a prefix
|
|
100
164
|
* ```
|
|
101
165
|
*
|
|
102
|
-
* Pure and `std
|
|
103
|
-
*
|
|
166
|
+
* Pure and total; `std` is OPTIONAL, exactly like {@link c4TypeLine} —
|
|
167
|
+
* without it this reads a line the same way it always has, and with it the
|
|
168
|
+
* vocabulary the `<word>:` prefix is matched against ALSO recognises the
|
|
169
|
+
* host's own resolved word ({@link knownTypeWords}), so a line seeded or
|
|
170
|
+
* normalized in a translated host still gives back the right technology
|
|
171
|
+
* rather than the whole line.
|
|
104
172
|
*
|
|
105
173
|
* It deliberately does NOT know about the creation placeholder: a node created
|
|
106
174
|
* and never touched carries `[Container: technology]`, and reading that as "no
|
|
@@ -109,18 +177,19 @@ const KNOWN_TYPE_WORDS = new Set(Object.values(C4_TYPE_WORD).map(word => word.to
|
|
|
109
177
|
* placeholder is a question for whoever asks what the element STATES, which is
|
|
110
178
|
* the exporter, and it is answered there.
|
|
111
179
|
*/
|
|
112
|
-
export function technologyOfTypeLine(text) {
|
|
180
|
+
export function technologyOfTypeLine(text, std) {
|
|
113
181
|
const flat = (text ?? '')
|
|
114
182
|
.replaceAll(/[[\]]/g, ' ')
|
|
115
183
|
.replaceAll(/\s+/g, ' ')
|
|
116
184
|
.trim();
|
|
117
185
|
const colon = flat.indexOf(':');
|
|
186
|
+
const words = knownTypeWords(std);
|
|
118
187
|
// No colon at all: the line is either the bare notation word — which states no
|
|
119
188
|
// technology — or it is the technology, typed on its own.
|
|
120
189
|
if (colon < 0)
|
|
121
|
-
return
|
|
190
|
+
return words.has(flat.toLowerCase()) ? '' : flat;
|
|
122
191
|
const head = flat.slice(0, colon).trim().toLowerCase();
|
|
123
|
-
if (!
|
|
192
|
+
if (!words.has(head))
|
|
124
193
|
return flat;
|
|
125
194
|
return flat.slice(colon + 1).trim();
|
|
126
195
|
}
|
|
@@ -134,9 +203,15 @@ export function technologyOfTypeLine(text) {
|
|
|
134
203
|
*
|
|
135
204
|
* Idempotent by construction — `normalize(normalize(x)) === normalize(x)` —
|
|
136
205
|
* which is what lets it run on every commit without a guard.
|
|
206
|
+
*
|
|
207
|
+
* `std` is OPTIONAL and, when given, is threaded to both halves: the
|
|
208
|
+
* technology is read back recognising the host's own word
|
|
209
|
+
* ({@link technologyOfTypeLine}) and the line is rebuilt with it
|
|
210
|
+
* ({@link c4TypeLine}) — see `C4TypeLineWatcher`, the one real caller that
|
|
211
|
+
* has an `std` to give it.
|
|
137
212
|
*/
|
|
138
|
-
export function normalizeC4TypeLine(kind, rawText) {
|
|
139
|
-
return c4TypeLine(kind, technologyOfTypeLine(rawText));
|
|
213
|
+
export function normalizeC4TypeLine(kind, rawText, std) {
|
|
214
|
+
return c4TypeLine(kind, technologyOfTypeLine(rawText, std), std);
|
|
140
215
|
}
|
|
141
216
|
/* ── What a fresh element says before anybody writes on it ─────────────── */
|
|
142
217
|
/**
|
|
@@ -147,6 +222,31 @@ export function normalizeC4TypeLine(kind, rawText) {
|
|
|
147
222
|
* {@link C4_TYPE_PLACEHOLDER}.
|
|
148
223
|
*/
|
|
149
224
|
export const TYPE_TECHNOLOGY_PLACEHOLDER = 'technology';
|
|
225
|
+
/**
|
|
226
|
+
* {@link TYPE_TECHNOLOGY_PLACEHOLDER}'s own key — see the long comment on
|
|
227
|
+
* {@link C4_TYPE_WORD_KEY} for why this lot's shipped French proposal keeps
|
|
228
|
+
* it identical to English.
|
|
229
|
+
*/
|
|
230
|
+
export const C4_TECHNOLOGY_PLACEHOLDER_KEY = 'com.labre.c4.type.technology-placeholder';
|
|
231
|
+
/** The word an `std` (when given) resolves the technology prompt to. */
|
|
232
|
+
function technologyPlaceholderWord(std) {
|
|
233
|
+
return std
|
|
234
|
+
? translateKey(std, C4_TECHNOLOGY_PLACEHOLDER_KEY, TYPE_TECHNOLOGY_PLACEHOLDER)
|
|
235
|
+
: TYPE_TECHNOLOGY_PLACEHOLDER;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Every wording this file writes onto the canvas, for `translations.ts`'s
|
|
239
|
+
* manifest contribution — the four distinct type words plus the technology
|
|
240
|
+
* prompt, all `seed` (written into the document once, at placement or at a
|
|
241
|
+
* commit the watcher normalizes).
|
|
242
|
+
*/
|
|
243
|
+
export const C4_TYPE_LINE_WORDINGS = [
|
|
244
|
+
[C4_TYPE_WORD_KEY.person, C4_TYPE_WORD.person],
|
|
245
|
+
[C4_TYPE_WORD_KEY.system, C4_TYPE_WORD.system],
|
|
246
|
+
[C4_TYPE_WORD_KEY.container, C4_TYPE_WORD.container],
|
|
247
|
+
[C4_TYPE_WORD_KEY.component, C4_TYPE_WORD.component],
|
|
248
|
+
[C4_TECHNOLOGY_PLACEHOLDER_KEY, TYPE_TECHNOLOGY_PLACEHOLDER],
|
|
249
|
+
];
|
|
150
250
|
/**
|
|
151
251
|
* Which kinds announce a technology in their type line AT ALL.
|
|
152
252
|
*
|
|
@@ -190,6 +290,17 @@ export const C4_TYPE_PLACEHOLDER = Object.fromEntries(Object.keys(C4_TYPE_WORD).
|
|
|
190
290
|
kind,
|
|
191
291
|
c4TypeLine(kind, C4_TYPE_TAKES_TECHNOLOGY[kind] ? TYPE_TECHNOLOGY_PLACEHOLDER : undefined),
|
|
192
292
|
]));
|
|
293
|
+
/**
|
|
294
|
+
* {@link C4_TYPE_PLACEHOLDER}, resolved through `std` when given — the
|
|
295
|
+
* placement site (`createC4Node`, `actions.ts`) seeds a fresh element with
|
|
296
|
+
* this rather than the English-only constant, so a component drawn in a
|
|
297
|
+
* translated host starts in that language, like every other seed
|
|
298
|
+
* (`docs/adr/0016`). With no `std` this returns exactly
|
|
299
|
+
* `C4_TYPE_PLACEHOLDER[kind]`.
|
|
300
|
+
*/
|
|
301
|
+
export function c4TypePlaceholder(kind, std) {
|
|
302
|
+
return c4TypeLine(kind, C4_TYPE_TAKES_TECHNOLOGY[kind] ? technologyPlaceholderWord(std) : undefined, std);
|
|
303
|
+
}
|
|
193
304
|
/* ── What the line becomes when the shape becomes something else ───────── */
|
|
194
305
|
/**
|
|
195
306
|
* The type line a component should carry once its shape has morphed from `from`
|
|
@@ -232,13 +343,19 @@ export const C4_TYPE_PLACEHOLDER = Object.fromEntries(Object.keys(C4_TYPE_WORD).
|
|
|
232
343
|
*
|
|
233
344
|
* Pure, total and `std`-free, like everything else in this file.
|
|
234
345
|
*/
|
|
235
|
-
export function c4MorphedTypeLine(from, to, rawText) {
|
|
346
|
+
export function c4MorphedTypeLine(from, to, rawText, std) {
|
|
236
347
|
const text = (rawText ?? '').trim();
|
|
237
348
|
if (!text)
|
|
238
349
|
return null;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
350
|
+
// The untouched prompt, in EITHER language: the English literal (a document
|
|
351
|
+
// seeded before these keys existed, or with no host) or the host's own
|
|
352
|
+
// resolved wording (`c4TypePlaceholder`, which equals the English constant
|
|
353
|
+
// when `std` is absent) — see the module docstring.
|
|
354
|
+
if (text === C4_TYPE_PLACEHOLDER[from] ||
|
|
355
|
+
text === c4TypePlaceholder(from, std)) {
|
|
356
|
+
return c4TypePlaceholder(to, std);
|
|
357
|
+
}
|
|
358
|
+
if (text !== normalizeC4TypeLine(from, text, std))
|
|
242
359
|
return null;
|
|
243
|
-
return c4TypeLine(to, technologyOfTypeLine(text));
|
|
360
|
+
return c4TypeLine(to, technologyOfTypeLine(text, std), std);
|
|
244
361
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formicoidea/labre-framework-c4",
|
|
3
3
|
"description": "Labre c4 framework for @formicoidea/labre-core.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.41.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"author": "lajola",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"dist"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@formicoidea/labre-core": "0.
|
|
35
|
-
"@formicoidea/labre-ddd-shared": "0.
|
|
34
|
+
"@formicoidea/labre-core": "0.41.0",
|
|
35
|
+
"@formicoidea/labre-ddd-shared": "0.41.0",
|
|
36
36
|
"lit": "^3.2.0"
|
|
37
37
|
}
|
|
38
38
|
}
|