@likec4/generators 1.46.3 → 1.47.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/d2/generate-d2.js +5 -1
- package/dist/mmd/generate-mmd.js +32 -17
- package/dist/puml/generate-puml.js +33 -9
- package/dist/puml/index.d.ts +1 -1
- package/dist/puml/index.js +1 -1
- package/package.json +4 -4
- package/src/d2/generate-d2.ts +5 -1
- package/src/mmd/generate-mmd.ts +33 -18
- package/src/puml/generate-puml.ts +45 -17
- package/src/puml/index.ts +1 -1
package/dist/d2/generate-d2.js
CHANGED
|
@@ -26,12 +26,16 @@ const d2shape = ({ shape }) => {
|
|
|
26
26
|
case "queue":
|
|
27
27
|
case "cylinder":
|
|
28
28
|
case "rectangle":
|
|
29
|
-
case "
|
|
29
|
+
case "document": {
|
|
30
30
|
return shape;
|
|
31
31
|
}
|
|
32
|
+
case "person": {
|
|
33
|
+
return "c4-person";
|
|
34
|
+
}
|
|
32
35
|
case "storage": {
|
|
33
36
|
return "stored_data";
|
|
34
37
|
}
|
|
38
|
+
case "bucket":
|
|
35
39
|
case "mobile":
|
|
36
40
|
case "browser": {
|
|
37
41
|
return "rectangle";
|
package/dist/mmd/generate-mmd.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nonexhaustive } from "@likec4/core";
|
|
1
2
|
import { CompositeGeneratorNode, joinToNode, NL, toString } from "langium/generate";
|
|
2
3
|
import { isNullish as isNil } from "remeda";
|
|
3
4
|
const capitalizeFirstLetter = (value) => value.charAt(0).toLocaleUpperCase() + value.slice(1);
|
|
@@ -5,21 +6,37 @@ const fqnName = (nodeId) => nodeId.split(".").map(capitalizeFirstLetter).join(""
|
|
|
5
6
|
const nodeName = (node) => {
|
|
6
7
|
return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id);
|
|
7
8
|
};
|
|
8
|
-
const
|
|
9
|
+
const toSingleQuotes = (str) => str.replace(/\\?"/g, `'`);
|
|
10
|
+
const mmdshape = ({ shape, title }) => {
|
|
11
|
+
const label = `label: ${JSON.stringify(title)}`;
|
|
9
12
|
switch (shape) {
|
|
10
|
-
case "queue":
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
case "queue": {
|
|
14
|
+
return `@{ shape: horizontal-cylinder, ${label} }`;
|
|
15
|
+
}
|
|
13
16
|
case "person": {
|
|
14
|
-
return
|
|
17
|
+
return `@{ icon: "fa:user", shape: rounded, ${label} }`;
|
|
18
|
+
}
|
|
19
|
+
case "storage": {
|
|
20
|
+
return `@{ shape: disk, ${label} }`;
|
|
21
|
+
}
|
|
22
|
+
case "cylinder": {
|
|
23
|
+
return `@{ shape: cylinder, ${label} }`;
|
|
15
24
|
}
|
|
16
|
-
case "storage":
|
|
17
|
-
return ["([", "])"];
|
|
18
25
|
case "mobile":
|
|
19
|
-
case "browser":
|
|
26
|
+
case "browser": {
|
|
27
|
+
return `@{ shape: rounded, ${label} }`;
|
|
28
|
+
}
|
|
29
|
+
case "bucket": {
|
|
30
|
+
return `@{ shape: trap-t, ${label} }`;
|
|
31
|
+
}
|
|
20
32
|
case "rectangle": {
|
|
21
|
-
return
|
|
33
|
+
return `@{ shape: rectangle, ${label} }`;
|
|
34
|
+
}
|
|
35
|
+
case "document": {
|
|
36
|
+
return `@{ shape: doc, ${label} }`;
|
|
22
37
|
}
|
|
38
|
+
default:
|
|
39
|
+
nonexhaustive(shape);
|
|
23
40
|
}
|
|
24
41
|
};
|
|
25
42
|
export function generateMermaid(viewmodel) {
|
|
@@ -30,11 +47,10 @@ export function generateMermaid(viewmodel) {
|
|
|
30
47
|
const name = nodeName(node);
|
|
31
48
|
const fqnName2 = (parentName ? parentName + "." : "") + name;
|
|
32
49
|
names.set(node.id, fqnName2);
|
|
33
|
-
const label = node.title.replaceAll("\n", "\\n");
|
|
34
|
-
const shape = mmdshape(node);
|
|
35
50
|
const baseNode = new CompositeGeneratorNode();
|
|
36
51
|
if (node.children.length > 0) {
|
|
37
|
-
|
|
52
|
+
const label = toSingleQuotes(node.title);
|
|
53
|
+
baseNode.append("subgraph ", fqnName2, '["`', label, '`"]', NL).indent({
|
|
38
54
|
indentedChildren: [
|
|
39
55
|
joinToNode(
|
|
40
56
|
nodes.filter((n) => n.parent === node.id),
|
|
@@ -47,7 +63,7 @@ export function generateMermaid(viewmodel) {
|
|
|
47
63
|
indentation: 2
|
|
48
64
|
}).append("end", NL);
|
|
49
65
|
} else {
|
|
50
|
-
baseNode.append(fqnName2,
|
|
66
|
+
baseNode.append(fqnName2, mmdshape(node));
|
|
51
67
|
}
|
|
52
68
|
return baseNode;
|
|
53
69
|
};
|
|
@@ -55,17 +71,16 @@ export function generateMermaid(viewmodel) {
|
|
|
55
71
|
return new CompositeGeneratorNode().append(
|
|
56
72
|
names.get(edge.source),
|
|
57
73
|
" -.",
|
|
58
|
-
edge.label ? ' "' + edge.label
|
|
74
|
+
edge.label ? ' "`' + toSingleQuotes(edge.label) + '`" .-' : "-",
|
|
59
75
|
"> ",
|
|
60
76
|
names.get(edge.target)
|
|
61
77
|
);
|
|
62
78
|
};
|
|
63
79
|
return toString(
|
|
64
|
-
new CompositeGeneratorNode().
|
|
65
|
-
view.title !== null && view.title.length > 0,
|
|
80
|
+
new CompositeGeneratorNode().append(
|
|
66
81
|
"---",
|
|
67
82
|
NL,
|
|
68
|
-
`title: ${JSON.stringify(
|
|
83
|
+
`title: ${JSON.stringify(toSingleQuotes(viewmodel.titleOrId))}`,
|
|
69
84
|
NL,
|
|
70
85
|
"---",
|
|
71
86
|
NL
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { nonexhaustive } from "@likec4/core";
|
|
1
2
|
import { RichText } from "@likec4/core/types";
|
|
2
3
|
import { CompositeGeneratorNode, joinToNode, NL, toString } from "langium/generate";
|
|
3
|
-
import { isNullish as isNil } from "remeda";
|
|
4
|
+
import { isEmptyish, isNullish as isNil } from "remeda";
|
|
4
5
|
const capitalizeFirstLetter = (value) => value.charAt(0).toLocaleUpperCase() + value.slice(1);
|
|
5
|
-
const fqnName = (nodeId) =>
|
|
6
|
+
const fqnName = (nodeId) => {
|
|
7
|
+
return nodeId.split(/[.-]/).map(capitalizeFirstLetter).join("");
|
|
8
|
+
};
|
|
6
9
|
const nodeName = (node) => {
|
|
7
10
|
return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id);
|
|
8
11
|
};
|
|
@@ -41,13 +44,17 @@ const pumlShape = ({ shape }) => {
|
|
|
41
44
|
case "cylinder": {
|
|
42
45
|
return "database";
|
|
43
46
|
}
|
|
47
|
+
case "document":
|
|
44
48
|
case "mobile":
|
|
49
|
+
case "bucket":
|
|
45
50
|
case "browser": {
|
|
46
51
|
return "rectangle";
|
|
47
52
|
}
|
|
53
|
+
default:
|
|
54
|
+
nonexhaustive(shape);
|
|
48
55
|
}
|
|
49
56
|
};
|
|
50
|
-
const escapeLabel = (label) =>
|
|
57
|
+
const escapeLabel = (label) => isEmptyish(label) ? null : JSON.stringify(label).slice(1, -1).replace(/\\"/g, '"');
|
|
51
58
|
export function generatePuml(viewmodel) {
|
|
52
59
|
const view = viewmodel.$view;
|
|
53
60
|
const colors = viewmodel.$model.$styles.theme.colors;
|
|
@@ -56,7 +63,7 @@ export function generatePuml(viewmodel) {
|
|
|
56
63
|
const relationshipsColorProvider = (key) => (colorKey) => colorKey in colors ? colors[colorKey].relationships[key] : void 0;
|
|
57
64
|
const names = /* @__PURE__ */ new Map();
|
|
58
65
|
const printHeader = () => {
|
|
59
|
-
return new CompositeGeneratorNode().append('title "',
|
|
66
|
+
return new CompositeGeneratorNode().append('title "', viewmodel.titleOrId, '"', NL).append(pumlDirection(view), " direction", NL);
|
|
60
67
|
};
|
|
61
68
|
const printTheme = () => {
|
|
62
69
|
return new CompositeGeneratorNode().append("hide stereotype", NL).append("skinparam ranksep ", "60", NL).append("skinparam nodesep ", "30", NL).append("skinparam {", NL).indent({
|
|
@@ -83,7 +90,7 @@ export function generatePuml(viewmodel) {
|
|
|
83
90
|
const tech = escapeLabel(node.technology);
|
|
84
91
|
names.set(node.id, fqn);
|
|
85
92
|
const description = RichText.from(node.description);
|
|
86
|
-
return new CompositeGeneratorNode().append(shape, " ").append('"').append("==", label).appendIf(!!tech,
|
|
93
|
+
return new CompositeGeneratorNode().append(shape, " ").append('"').append("==", label).appendIf(!!tech, `\\n<size:10>[`, tech, "]</size>").appendIf(description.nonEmpty, `\\n\\n`, escapeLabel(description.text)).append('"', " <<", fqn, ">> ", "as ", fqn, NL);
|
|
87
94
|
};
|
|
88
95
|
const printBoundary = (node) => {
|
|
89
96
|
const label = escapeLabel(node.title) || nodeName(node);
|
|
@@ -112,11 +119,28 @@ export function generatePuml(viewmodel) {
|
|
|
112
119
|
}).append("}", NL);
|
|
113
120
|
};
|
|
114
121
|
const printEdge = (edge) => {
|
|
115
|
-
const tech =
|
|
116
|
-
const label =
|
|
122
|
+
const tech = edge.technology || "";
|
|
123
|
+
const label = edge.label || tech;
|
|
117
124
|
const color = pumlColor(edge.color, relationshipsColorProvider("line"), "#777777");
|
|
118
|
-
const
|
|
119
|
-
|
|
125
|
+
const withColor = (text) => `<color:${color}>${text.replaceAll('"', `'`)}`;
|
|
126
|
+
const out = new CompositeGeneratorNode().append(
|
|
127
|
+
names.get(edge.source),
|
|
128
|
+
" .[",
|
|
129
|
+
color,
|
|
130
|
+
",thickness=2].> ",
|
|
131
|
+
names.get(edge.target)
|
|
132
|
+
);
|
|
133
|
+
if (label || tech) {
|
|
134
|
+
out.append(
|
|
135
|
+
" : ",
|
|
136
|
+
// Prepend color to each line
|
|
137
|
+
label.split("\n").map((l) => isEmptyish(l) ? l : withColor(l)).join("\\n")
|
|
138
|
+
);
|
|
139
|
+
if (tech && tech !== label) {
|
|
140
|
+
out.append("\\n<size:8>[", withColor(tech), "]</size>");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return out.append(NL);
|
|
120
144
|
};
|
|
121
145
|
return toString(
|
|
122
146
|
new CompositeGeneratorNode().append("@startuml", NL).append(printHeader(), NL).append(printTheme(), NL).append(
|
package/dist/puml/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { generatePuml } from './generate-puml';
|
package/dist/puml/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { generatePuml } from "./generate-puml.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/generators",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.47.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
6
6
|
"homepage": "https://likec4.dev",
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
"json5": "^2.2.3",
|
|
40
40
|
"langium": "3.5.0",
|
|
41
41
|
"remeda": "^2.32.0",
|
|
42
|
-
"@likec4/core": "1.
|
|
42
|
+
"@likec4/core": "1.47.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "~22.19.3",
|
|
46
46
|
"typescript": "5.9.3",
|
|
47
47
|
"unbuild": "3.5.0",
|
|
48
48
|
"vitest": "4.0.16",
|
|
49
|
-
"@likec4/
|
|
50
|
-
"@likec4/
|
|
49
|
+
"@likec4/devops": "1.42.0",
|
|
50
|
+
"@likec4/tsconfig": "1.46.1"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"typecheck": "tsc -b --verbose",
|
package/src/d2/generate-d2.ts
CHANGED
|
@@ -36,12 +36,16 @@ const d2shape = ({ shape }: Node) => {
|
|
|
36
36
|
case 'queue':
|
|
37
37
|
case 'cylinder':
|
|
38
38
|
case 'rectangle':
|
|
39
|
-
case '
|
|
39
|
+
case 'document': {
|
|
40
40
|
return shape
|
|
41
41
|
}
|
|
42
|
+
case 'person': {
|
|
43
|
+
return 'c4-person' as const
|
|
44
|
+
}
|
|
42
45
|
case 'storage': {
|
|
43
46
|
return 'stored_data' as const
|
|
44
47
|
}
|
|
48
|
+
case 'bucket':
|
|
45
49
|
case 'mobile':
|
|
46
50
|
case 'browser': {
|
|
47
51
|
return 'rectangle' as const
|
package/src/mmd/generate-mmd.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nonexhaustive } from '@likec4/core'
|
|
1
2
|
import type { LikeC4ViewModel } from '@likec4/core/model'
|
|
2
3
|
import type { aux, NodeId, ProcessedView as AnyView } from '@likec4/core/types'
|
|
3
4
|
import { CompositeGeneratorNode, joinToNode, NL, toString } from 'langium/generate'
|
|
@@ -14,21 +15,38 @@ const nodeName = (node: Node): string => {
|
|
|
14
15
|
return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id)
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
const
|
|
18
|
+
const toSingleQuotes = (str: string): string => str.replace(/\\?"/g, `'`)
|
|
19
|
+
|
|
20
|
+
const mmdshape = ({ shape, title }: Node): string => {
|
|
21
|
+
const label = `label: ${JSON.stringify(title)}`
|
|
18
22
|
switch (shape) {
|
|
19
|
-
case 'queue':
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
case 'queue': {
|
|
24
|
+
return `@{ shape: horizontal-cylinder, ${label} }`
|
|
25
|
+
}
|
|
22
26
|
case 'person': {
|
|
23
|
-
return
|
|
27
|
+
return `@{ icon: "fa:user", shape: rounded, ${label} }`
|
|
28
|
+
}
|
|
29
|
+
case 'storage': {
|
|
30
|
+
return `@{ shape: disk, ${label} }`
|
|
31
|
+
}
|
|
32
|
+
case 'cylinder': {
|
|
33
|
+
return `@{ shape: cylinder, ${label} }`
|
|
24
34
|
}
|
|
25
|
-
case 'storage':
|
|
26
|
-
return ['([', '])']
|
|
27
35
|
case 'mobile':
|
|
28
|
-
case 'browser':
|
|
36
|
+
case 'browser': {
|
|
37
|
+
return `@{ shape: rounded, ${label} }`
|
|
38
|
+
}
|
|
39
|
+
case 'bucket': {
|
|
40
|
+
return `@{ shape: trap-t, ${label} }`
|
|
41
|
+
}
|
|
29
42
|
case 'rectangle': {
|
|
30
|
-
return
|
|
43
|
+
return `@{ shape: rectangle, ${label} }`
|
|
31
44
|
}
|
|
45
|
+
case 'document': {
|
|
46
|
+
return `@{ shape: doc, ${label} }`
|
|
47
|
+
}
|
|
48
|
+
default:
|
|
49
|
+
nonexhaustive(shape)
|
|
32
50
|
}
|
|
33
51
|
}
|
|
34
52
|
|
|
@@ -42,13 +60,11 @@ export function generateMermaid(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
|
42
60
|
const fqnName = (parentName ? parentName + '.' : '') + name
|
|
43
61
|
names.set(node.id, fqnName)
|
|
44
62
|
|
|
45
|
-
const label = node.title.replaceAll('\n', '\\n')
|
|
46
|
-
const shape = mmdshape(node)
|
|
47
|
-
|
|
48
63
|
const baseNode = new CompositeGeneratorNode()
|
|
49
64
|
if (node.children.length > 0) {
|
|
65
|
+
const label = toSingleQuotes(node.title)
|
|
50
66
|
baseNode
|
|
51
|
-
.append('subgraph ', fqnName, '[',
|
|
67
|
+
.append('subgraph ', fqnName, '["`', label, '`"]', NL)
|
|
52
68
|
.indent({
|
|
53
69
|
indentedChildren: [
|
|
54
70
|
joinToNode(
|
|
@@ -63,7 +79,7 @@ export function generateMermaid(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
|
63
79
|
})
|
|
64
80
|
.append('end', NL)
|
|
65
81
|
} else {
|
|
66
|
-
baseNode.append(fqnName,
|
|
82
|
+
baseNode.append(fqnName, mmdshape(node))
|
|
67
83
|
}
|
|
68
84
|
return baseNode
|
|
69
85
|
}
|
|
@@ -72,7 +88,7 @@ export function generateMermaid(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
|
72
88
|
return new CompositeGeneratorNode().append(
|
|
73
89
|
names.get(edge.source),
|
|
74
90
|
' -.',
|
|
75
|
-
edge.label ? ' "' + edge.label
|
|
91
|
+
edge.label ? ' "`' + toSingleQuotes(edge.label) + '`" .-' : '-',
|
|
76
92
|
'> ',
|
|
77
93
|
names.get(edge.target),
|
|
78
94
|
)
|
|
@@ -80,11 +96,10 @@ export function generateMermaid(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
|
80
96
|
|
|
81
97
|
return toString(
|
|
82
98
|
new CompositeGeneratorNode()
|
|
83
|
-
.
|
|
84
|
-
view.title !== null && view.title.length > 0,
|
|
99
|
+
.append(
|
|
85
100
|
'---',
|
|
86
101
|
NL,
|
|
87
|
-
`title: ${JSON.stringify(
|
|
102
|
+
`title: ${JSON.stringify(toSingleQuotes(viewmodel.titleOrId))}`,
|
|
88
103
|
NL,
|
|
89
104
|
'---',
|
|
90
105
|
NL,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nonexhaustive } from '@likec4/core'
|
|
1
2
|
import type { LikeC4ViewModel } from '@likec4/core/model'
|
|
2
3
|
import type {
|
|
3
4
|
aux,
|
|
@@ -13,11 +14,14 @@ import type {
|
|
|
13
14
|
} from '@likec4/core/types'
|
|
14
15
|
import { RichText } from '@likec4/core/types'
|
|
15
16
|
import { CompositeGeneratorNode, joinToNode, NL, toString } from 'langium/generate'
|
|
16
|
-
import { isNullish as isNil } from 'remeda'
|
|
17
|
+
import { isEmptyish, isNullish as isNil } from 'remeda'
|
|
17
18
|
|
|
18
19
|
const capitalizeFirstLetter = (value: string) => value.charAt(0).toLocaleUpperCase() + value.slice(1)
|
|
19
20
|
|
|
20
|
-
const fqnName = (nodeId: string): string =>
|
|
21
|
+
const fqnName = (nodeId: string): string => {
|
|
22
|
+
// Split on both '.' and '-' to handle dashed identifiers (e.g., payment-gateway -> PaymentGateway)
|
|
23
|
+
return nodeId.split(/[.-]/).map(capitalizeFirstLetter).join('')
|
|
24
|
+
}
|
|
21
25
|
|
|
22
26
|
const nodeName = (node: ComputedNode): string => {
|
|
23
27
|
return fqnName(node.parent ? node.id.slice(node.parent.length + 1) : node.id)
|
|
@@ -64,14 +68,21 @@ const pumlShape = ({ shape }: ComputedNode) => {
|
|
|
64
68
|
case 'cylinder': {
|
|
65
69
|
return 'database' as const
|
|
66
70
|
}
|
|
71
|
+
case 'document':
|
|
67
72
|
case 'mobile':
|
|
73
|
+
case 'bucket':
|
|
68
74
|
case 'browser': {
|
|
69
75
|
return 'rectangle' as const
|
|
70
76
|
}
|
|
77
|
+
default:
|
|
78
|
+
nonexhaustive(shape)
|
|
71
79
|
}
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
const escapeLabel = (label: string | null | undefined) =>
|
|
82
|
+
const escapeLabel = (label: string | null | undefined) =>
|
|
83
|
+
isEmptyish(label) ? null : JSON.stringify(label)
|
|
84
|
+
.slice(1, -1)
|
|
85
|
+
.replace(/\\"/g, '"') // Unescape double quotes - PUML does not support escaped double quotes
|
|
75
86
|
|
|
76
87
|
export function generatePuml(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
77
88
|
const view = viewmodel.$view
|
|
@@ -87,7 +98,7 @@ export function generatePuml(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
|
87
98
|
|
|
88
99
|
const printHeader = () => {
|
|
89
100
|
return new CompositeGeneratorNode()
|
|
90
|
-
.append('title "',
|
|
101
|
+
.append('title "', viewmodel.titleOrId, '"', NL)
|
|
91
102
|
.append(pumlDirection(view), ' direction', NL)
|
|
92
103
|
}
|
|
93
104
|
|
|
@@ -144,8 +155,8 @@ export function generatePuml(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
|
144
155
|
.append(shape, ' ')
|
|
145
156
|
.append('"')
|
|
146
157
|
.append('==', label)
|
|
147
|
-
.appendIf(!!tech,
|
|
148
|
-
.appendIf(description.nonEmpty,
|
|
158
|
+
.appendIf(!!tech, `\\n<size:10>[`, tech!, ']</size>')
|
|
159
|
+
.appendIf(description.nonEmpty, `\\n\\n`, escapeLabel(description.text)!)
|
|
149
160
|
.append('"', ' <<', fqn, '>> ', 'as ', fqn, NL)
|
|
150
161
|
}
|
|
151
162
|
|
|
@@ -186,20 +197,37 @@ export function generatePuml(viewmodel: LikeC4ViewModel<aux.Unknown>) {
|
|
|
186
197
|
}
|
|
187
198
|
|
|
188
199
|
const printEdge = (edge: ComputedEdge): CompositeGeneratorNode => {
|
|
189
|
-
const tech =
|
|
190
|
-
const label =
|
|
200
|
+
const tech = edge.technology || ''
|
|
201
|
+
const label = edge.label || tech
|
|
191
202
|
const color = pumlColor(edge.color, relationshipsColorProvider('line'), '#777777')
|
|
192
203
|
|
|
193
|
-
const
|
|
204
|
+
const withColor = (text: string) => `<color:${color}>${text.replaceAll('"', `'`)}`
|
|
194
205
|
|
|
195
|
-
|
|
196
|
-
.append(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
206
|
+
const out = new CompositeGeneratorNode()
|
|
207
|
+
.append(
|
|
208
|
+
names.get(edge.source),
|
|
209
|
+
' .[',
|
|
210
|
+
color,
|
|
211
|
+
',thickness=2].> ',
|
|
212
|
+
names.get(edge.target),
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
if (label || tech) {
|
|
216
|
+
out.append(
|
|
217
|
+
' : ',
|
|
218
|
+
// Prepend color to each line
|
|
219
|
+
label
|
|
220
|
+
.split('\n')
|
|
221
|
+
.map(l => isEmptyish(l) ? l : withColor(l))
|
|
222
|
+
.join('\\n'),
|
|
223
|
+
)
|
|
224
|
+
// Append technology if it exists and is different from the label
|
|
225
|
+
if (tech && tech !== label) {
|
|
226
|
+
out.append('\\n<size:8>[', withColor(tech), ']</size>')
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return out.append(NL)
|
|
203
231
|
}
|
|
204
232
|
|
|
205
233
|
return toString(
|
package/src/puml/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { generatePuml } from './generate-puml'
|