@likec4/core 0.4.0 → 0.6.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/compute-view/EdgeBuilder.js +5 -2
- package/dist/compute-view/compute.element-view.js +13 -10
- package/dist/compute-view/utils/evaluate-expression.js +5 -20
- package/dist/compute-view/utils/sortNodes.js +1 -1
- package/dist/model-index/model-index.d.ts +1 -1
- package/dist/model-index/model-index.js +4 -2
- package/dist/types/diagram.d.ts +10 -8
- package/dist/utils/relations.js +4 -4
- package/package.json +7 -5
|
@@ -12,7 +12,8 @@ export class EdgeBuilder {
|
|
|
12
12
|
return this;
|
|
13
13
|
}
|
|
14
14
|
build() {
|
|
15
|
-
return keys(this._relationsObj)
|
|
15
|
+
return keys(this._relationsObj)
|
|
16
|
+
.flatMap(source => {
|
|
16
17
|
const targets = this._relationsObj[source] ?? {};
|
|
17
18
|
return keys(targets).map(target => {
|
|
18
19
|
const relations = (targets[target] ?? []).sort(compareRelations);
|
|
@@ -26,6 +27,8 @@ export class EdgeBuilder {
|
|
|
26
27
|
relations: pluck('id', relations)
|
|
27
28
|
};
|
|
28
29
|
});
|
|
29
|
-
})
|
|
30
|
+
})
|
|
31
|
+
.sort(compareRelations)
|
|
32
|
+
.reverse();
|
|
30
33
|
}
|
|
31
34
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { anyPass, filter } from 'rambdax';
|
|
1
|
+
import { anyPass, filter, head } from 'rambdax';
|
|
2
2
|
import { DefaultElementShape, DefaultThemeColor } from '../types';
|
|
3
3
|
import * as Expression from '../types/expression';
|
|
4
4
|
import { isViewRuleAutoLayout, isViewRuleExpression, isViewRuleStyle } from '../types/view';
|
|
@@ -12,8 +12,10 @@ function updateSetWith(set, elements, addToSet = true) {
|
|
|
12
12
|
addToSet ? set.add(e) : set.delete(e);
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
function transformToNodes(elementsIterator, index) {
|
|
16
|
-
return [...elementsIterator]
|
|
15
|
+
function transformToNodes(elementsIterator, index, currentViewid) {
|
|
16
|
+
return [...elementsIterator]
|
|
17
|
+
.sort(compareByFqnHierarchically)
|
|
18
|
+
.reduce((map, { id, title, color, shape, description }) => {
|
|
17
19
|
let parent = parentFqn(id);
|
|
18
20
|
while (parent) {
|
|
19
21
|
if (map.has(parent)) {
|
|
@@ -21,14 +23,14 @@ function transformToNodes(elementsIterator, index) {
|
|
|
21
23
|
}
|
|
22
24
|
parent = parentFqn(parent);
|
|
23
25
|
}
|
|
24
|
-
const navigateTo = index.defaultViewOf(id);
|
|
26
|
+
const navigateTo = head(index.defaultViewOf(id).filter(v => v !== currentViewid));
|
|
25
27
|
map.set(id, Object.assign({
|
|
26
28
|
id,
|
|
27
29
|
parent,
|
|
28
30
|
title,
|
|
29
31
|
color: color ?? DefaultThemeColor,
|
|
30
32
|
shape: shape ?? DefaultElementShape,
|
|
31
|
-
children: []
|
|
33
|
+
children: []
|
|
32
34
|
}, description ? { description } : {}, navigateTo ? { navigateTo } : {}));
|
|
33
35
|
if (parent) {
|
|
34
36
|
map.get(parent)?.children.push(id);
|
|
@@ -50,9 +52,7 @@ function applyViewRuleStyles(rules, nodes) {
|
|
|
50
52
|
}
|
|
51
53
|
if (Expression.isElementRef(target)) {
|
|
52
54
|
const { element, isDescedants } = target;
|
|
53
|
-
predicates.push(isDescedants
|
|
54
|
-
? (n) => n.id.startsWith(element + '.')
|
|
55
|
-
: (n) => n.id === element);
|
|
55
|
+
predicates.push(isDescedants ? n => n.id.startsWith(element + '.') : n => n.id === element);
|
|
56
56
|
continue;
|
|
57
57
|
}
|
|
58
58
|
failExpectedNever(target);
|
|
@@ -79,7 +79,10 @@ export function computeElementView(view, index) {
|
|
|
79
79
|
if (isInclude) {
|
|
80
80
|
const filters = [];
|
|
81
81
|
// When include element(s) without newNeighbours, include in-out relations
|
|
82
|
-
if (elements.size > 0 &&
|
|
82
|
+
if (elements.size > 0 &&
|
|
83
|
+
newElements.length > 0 &&
|
|
84
|
+
newNeighbours.length === 0 &&
|
|
85
|
+
Expression.isElement(expr)) {
|
|
83
86
|
for (const e of elements) {
|
|
84
87
|
for (const newE of newElements) {
|
|
85
88
|
if (!isSameHierarchy(e, newE)) {
|
|
@@ -144,7 +147,7 @@ export function computeElementView(view, index) {
|
|
|
144
147
|
idx = resolvedRelations.findIndex(findPredicate);
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
|
-
const nodesreg = transformToNodes(elements, index);
|
|
150
|
+
const nodesreg = transformToNodes(elements, index, view.id);
|
|
148
151
|
const edges = edgeBuilder.build().map(edge => {
|
|
149
152
|
while (edge.parent) {
|
|
150
153
|
if (nodesreg.has(edge.parent)) {
|
|
@@ -54,21 +54,12 @@ const evaluateElementExpression = (index, expr, rootElement = null) => {
|
|
|
54
54
|
// WildcardExpression
|
|
55
55
|
if (Expr.isWildcard(expr)) {
|
|
56
56
|
if (rootElement) {
|
|
57
|
-
elements = [
|
|
58
|
-
index.find(rootElement),
|
|
59
|
-
...index.children(rootElement)
|
|
60
|
-
];
|
|
57
|
+
elements = [index.find(rootElement), ...index.children(rootElement)];
|
|
61
58
|
neighbours = [
|
|
62
59
|
...index.siblings(rootElement),
|
|
63
|
-
...index.ancestors(rootElement).flatMap(a => [
|
|
64
|
-
...index.siblings(a.id)
|
|
65
|
-
])
|
|
60
|
+
...index.ancestors(rootElement).flatMap(a => [...index.siblings(a.id)])
|
|
66
61
|
];
|
|
67
|
-
relations = index.filterRelations(anyPass([
|
|
68
|
-
isInside(rootElement),
|
|
69
|
-
isIncoming(rootElement),
|
|
70
|
-
isOutgoing(rootElement),
|
|
71
|
-
]));
|
|
62
|
+
relations = index.filterRelations(anyPass([isInside(rootElement), isIncoming(rootElement), isOutgoing(rootElement)]));
|
|
72
63
|
}
|
|
73
64
|
else {
|
|
74
65
|
elements = index.rootElements();
|
|
@@ -116,14 +107,8 @@ export function evaluateExpression(index, expr, rootElement) {
|
|
|
116
107
|
const outgoing = index.filterRelations(isOutgoing(target.id));
|
|
117
108
|
if (incoming.length + outgoing.length > 0) {
|
|
118
109
|
elements.push(target);
|
|
119
|
-
neighbours = neighbours.concat(map(index.find, [
|
|
120
|
-
|
|
121
|
-
...pluck('target', outgoing),
|
|
122
|
-
]));
|
|
123
|
-
relations = relations.concat([
|
|
124
|
-
...incoming,
|
|
125
|
-
...outgoing
|
|
126
|
-
]);
|
|
110
|
+
neighbours = neighbours.concat(map(index.find, [...pluck('source', incoming), ...pluck('target', outgoing)]));
|
|
111
|
+
relations = relations.concat([...incoming, ...outgoing]);
|
|
127
112
|
}
|
|
128
113
|
}
|
|
129
114
|
return {
|
|
@@ -36,7 +36,7 @@ export function sortNodes(_nodes, edges) {
|
|
|
36
36
|
const sorted = alg.topsort(g);
|
|
37
37
|
const nodes = sorted.map(id => _nodes.get(id));
|
|
38
38
|
for (const node of nodes) {
|
|
39
|
-
node.children = nodes.flatMap(n => n.parent === node.id ? n.id : []);
|
|
39
|
+
node.children = nodes.flatMap(n => (n.parent === node.id ? n.id : []));
|
|
40
40
|
}
|
|
41
41
|
return nodes;
|
|
42
42
|
}
|
|
@@ -38,7 +38,9 @@ export class ModelIndex {
|
|
|
38
38
|
}
|
|
39
39
|
for (const { id, viewOf } of Object.values(views)) {
|
|
40
40
|
if (viewOf) {
|
|
41
|
-
index._defaultElementView.
|
|
41
|
+
const views = index._defaultElementView.get(viewOf) ?? [];
|
|
42
|
+
views.push(id);
|
|
43
|
+
index._defaultElementView.set(viewOf, views);
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
return index;
|
|
@@ -136,6 +138,6 @@ export class ModelIndex {
|
|
|
136
138
|
// }
|
|
137
139
|
}
|
|
138
140
|
defaultViewOf = (id) => {
|
|
139
|
-
return this._defaultElementView.get(id);
|
|
141
|
+
return this._defaultElementView.get(id) ?? [];
|
|
140
142
|
};
|
|
141
143
|
}
|
package/dist/types/diagram.d.ts
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
import type { ComputedEdge, ComputedNode, ComputedView } from './computed-view';
|
|
2
2
|
export type Point = [x: number, y: number];
|
|
3
|
+
export interface DiagramLabel {
|
|
4
|
+
align: 'left' | 'right' | 'center';
|
|
5
|
+
fontStyle?: 'bold' | 'normal';
|
|
6
|
+
fontSize: number;
|
|
7
|
+
pt: Point;
|
|
8
|
+
width: number;
|
|
9
|
+
text: string;
|
|
10
|
+
}
|
|
3
11
|
export interface DiagramNode extends ComputedNode {
|
|
4
12
|
size: {
|
|
5
13
|
width: number;
|
|
6
14
|
height: number;
|
|
7
15
|
};
|
|
16
|
+
labels: DiagramLabel[];
|
|
8
17
|
position: Point;
|
|
9
|
-
relative: Point;
|
|
10
18
|
}
|
|
11
19
|
export interface DiagramEdge extends ComputedEdge {
|
|
12
20
|
points: Point[];
|
|
13
21
|
headArrow?: Point[];
|
|
14
|
-
|
|
15
|
-
x: number;
|
|
16
|
-
y: number;
|
|
17
|
-
width: number;
|
|
18
|
-
height?: number;
|
|
19
|
-
align?: 'left' | 'right' | 'center';
|
|
20
|
-
} | null;
|
|
22
|
+
labels: DiagramLabel[];
|
|
21
23
|
}
|
|
22
24
|
export interface DiagramView extends ComputedView<DiagramNode, DiagramEdge> {
|
|
23
25
|
width: number;
|
package/dist/utils/relations.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { either } from 'rambdax';
|
|
2
2
|
import { compareFqnHierarchically } from './fqn';
|
|
3
3
|
export const compareRelations = (a, b) => {
|
|
4
|
-
return compareFqnHierarchically(a.source, b.source) || compareFqnHierarchically(a.target, b.target);
|
|
4
|
+
return (compareFqnHierarchically(a.source, b.source) || compareFqnHierarchically(a.target, b.target));
|
|
5
5
|
};
|
|
6
6
|
export const isInside = (parent) => {
|
|
7
7
|
const prefix = parent + '.';
|
|
@@ -13,7 +13,7 @@ export const isBetween = (source, target) => {
|
|
|
13
13
|
const sourcePrefix = source + '.';
|
|
14
14
|
const targetPrefix = target + '.';
|
|
15
15
|
return (rel) => {
|
|
16
|
-
return (rel.source + '.').startsWith(sourcePrefix) && (rel.target + '.').startsWith(targetPrefix);
|
|
16
|
+
return ((rel.source + '.').startsWith(sourcePrefix) && (rel.target + '.').startsWith(targetPrefix));
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
export const isAnyBetween = (source, target) => {
|
|
@@ -22,13 +22,13 @@ export const isAnyBetween = (source, target) => {
|
|
|
22
22
|
export const isIncoming = (target) => {
|
|
23
23
|
const targetPrefix = target + '.';
|
|
24
24
|
return (rel) => {
|
|
25
|
-
return !(rel.source + '.').startsWith(targetPrefix) && (rel.target + '.').startsWith(targetPrefix);
|
|
25
|
+
return (!(rel.source + '.').startsWith(targetPrefix) && (rel.target + '.').startsWith(targetPrefix));
|
|
26
26
|
};
|
|
27
27
|
};
|
|
28
28
|
export const isOutgoing = (source) => {
|
|
29
29
|
const sourcePrefix = source + '.';
|
|
30
30
|
return (rel) => {
|
|
31
|
-
return (rel.source + '.').startsWith(sourcePrefix) && !(rel.target + '.').startsWith(sourcePrefix);
|
|
31
|
+
return ((rel.source + '.').startsWith(sourcePrefix) && !(rel.target + '.').startsWith(sourcePrefix));
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
34
|
export const isAnyInOut = (source) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
5
6
|
"homepage": "https://like-c4.dev",
|
|
6
7
|
"author": "Denis Davydkov <denis@davydkov.com>",
|
|
@@ -9,7 +10,8 @@
|
|
|
9
10
|
],
|
|
10
11
|
"repository": {
|
|
11
12
|
"type": "git",
|
|
12
|
-
"url": "https://github.com/likec4/likec4.git"
|
|
13
|
+
"url": "https://github.com/likec4/likec4.git",
|
|
14
|
+
"directory": "packages/core"
|
|
13
15
|
},
|
|
14
16
|
"scripts": {
|
|
15
17
|
"compile": "",
|
|
@@ -19,7 +21,7 @@
|
|
|
19
21
|
"lint": "run -T eslint src/ --fix",
|
|
20
22
|
"test": "vitest run",
|
|
21
23
|
"test:watch": "vitest",
|
|
22
|
-
"clean": "rimraf dist"
|
|
24
|
+
"clean": "run -T rimraf dist"
|
|
23
25
|
},
|
|
24
26
|
"main": "./dist/index.js",
|
|
25
27
|
"types": "./dist/index.d.ts",
|
|
@@ -81,8 +83,8 @@
|
|
|
81
83
|
"tiny-invariant": "^1.3.1"
|
|
82
84
|
},
|
|
83
85
|
"devDependencies": {
|
|
84
|
-
"typescript": "^5.0.
|
|
85
|
-
"vite": "^4.2.
|
|
86
|
+
"typescript": "^5.0.4",
|
|
87
|
+
"vite": "^4.2.2",
|
|
86
88
|
"vitest": "^0.30.1"
|
|
87
89
|
}
|
|
88
90
|
}
|