astro-archify 0.3.4 → 0.3.6
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/README.md +70 -4
- package/package.json +6 -3
- package/vendor/archify/NOTICE.md +8 -5
- package/vendor/archify/assets/template.html +1 -1
- package/vendor/archify/renderers/architecture/render-architecture.mjs +1 -12
- package/vendor/archify/renderers/dataflow/render-dataflow.mjs +16 -15
- package/vendor/archify/renderers/lifecycle/render-lifecycle.mjs +1 -10
- package/vendor/archify/renderers/sequence/render-sequence.mjs +1 -16
- package/vendor/archify/renderers/shared/cli.mjs +1 -3
- package/vendor/archify/renderers/shared/diagnostics.mjs +17 -6
- package/vendor/archify/renderers/shared/generated-validators.mjs +2 -2
- package/vendor/archify/renderers/shared/geometry.mjs +129 -40
- package/vendor/archify/renderers/workflow/render-workflow.mjs +21 -735
- package/vendor/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
- package/vendor/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
const TARGET_SCHEMA_VERSION = 2;
|
|
2
|
+
|
|
3
|
+
function clone(value) {
|
|
4
|
+
return JSON.parse(JSON.stringify(value));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Return the authored workflow as a schema-v2 document without its capacity
|
|
9
|
+
* override. The compiler can use this projection to discover the intrinsic v2
|
|
10
|
+
* rank plan before deciding whether an explicit viewBox needs to grow.
|
|
11
|
+
*/
|
|
12
|
+
export function intrinsicWorkflow(workflow) {
|
|
13
|
+
const intrinsic = clone(workflow);
|
|
14
|
+
intrinsic.schema_version = TARGET_SCHEMA_VERSION;
|
|
15
|
+
intrinsic.meta = { ...intrinsic.meta };
|
|
16
|
+
delete intrinsic.meta.viewBox;
|
|
17
|
+
return intrinsic;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Return a schema-v2 planning projection that removes authored route geometry
|
|
22
|
+
* which may only become valid after its legacy X coordinates are remapped.
|
|
23
|
+
* Rank-affecting automatic and straight relationships remain in the projection.
|
|
24
|
+
*/
|
|
25
|
+
export function planningWorkflow(workflow) {
|
|
26
|
+
const planned = intrinsicWorkflow(workflow);
|
|
27
|
+
planned.edges = planned.edges.flatMap((edge) => {
|
|
28
|
+
const hasRoutedGeometry = Array.isArray(edge.via)
|
|
29
|
+
|| (edge.route && !['auto', 'straight'].includes(edge.route))
|
|
30
|
+
|| edge.channelX !== undefined
|
|
31
|
+
|| edge.channelY !== undefined;
|
|
32
|
+
if (hasRoutedGeometry) return [];
|
|
33
|
+
|
|
34
|
+
const automatic = {};
|
|
35
|
+
for (const property of ['id', 'from', 'to', 'variant', 'role', 'width']) {
|
|
36
|
+
if (edge[property] !== undefined) automatic[property] = edge[property];
|
|
37
|
+
}
|
|
38
|
+
if (edge.route === 'straight') automatic.route = 'straight';
|
|
39
|
+
if (edge.labelAt === undefined && edge.label !== undefined) automatic.label = edge.label;
|
|
40
|
+
return [automatic];
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (Array.isArray(planned.mainPath)) {
|
|
44
|
+
const projectedPairs = new Set(planned.edges.map((edge) => `${edge.from}\u0000${edge.to}`));
|
|
45
|
+
const projectionBreaksMainPath = planned.mainPath.some((from, index) => (
|
|
46
|
+
index < planned.mainPath.length - 1
|
|
47
|
+
&& !projectedPairs.has(`${from}\u0000${planned.mainPath[index + 1]}`)
|
|
48
|
+
));
|
|
49
|
+
if (projectionBreaksMainPath) delete planned.mainPath;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return planned;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function mappedNumber(value) {
|
|
56
|
+
return Number(value.toFixed(6));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Build a deterministic piecewise-linear mapping between corresponding legacy
|
|
61
|
+
* and readable rank centers. Coordinates outside the rank span are extrapolated
|
|
62
|
+
* using the nearest segment so explicitly authored outside corridors retain
|
|
63
|
+
* their relative offset.
|
|
64
|
+
*/
|
|
65
|
+
export function createHorizontalRankMapper(oldColumns, newColumns) {
|
|
66
|
+
if (
|
|
67
|
+
!Array.isArray(oldColumns)
|
|
68
|
+
|| !Array.isArray(newColumns)
|
|
69
|
+
|| oldColumns.length !== newColumns.length
|
|
70
|
+
|| oldColumns.length < 2
|
|
71
|
+
|| !oldColumns.every(Number.isFinite)
|
|
72
|
+
|| !newColumns.every(Number.isFinite)
|
|
73
|
+
) {
|
|
74
|
+
throw new TypeError('Horizontal rank mapping requires matching finite column arrays.');
|
|
75
|
+
}
|
|
76
|
+
for (let index = 1; index < oldColumns.length; index += 1) {
|
|
77
|
+
if (oldColumns[index] <= oldColumns[index - 1] || newColumns[index] <= newColumns[index - 1]) {
|
|
78
|
+
throw new TypeError('Horizontal rank mapping requires strictly increasing columns.');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (x) => {
|
|
83
|
+
if (!Number.isFinite(x)) throw new TypeError('Horizontal rank mapping requires a finite x coordinate.');
|
|
84
|
+
let segment = oldColumns.length - 2;
|
|
85
|
+
if (x <= oldColumns[0]) {
|
|
86
|
+
segment = 0;
|
|
87
|
+
} else {
|
|
88
|
+
for (let index = 0; index < oldColumns.length - 1; index += 1) {
|
|
89
|
+
if (x <= oldColumns[index + 1]) {
|
|
90
|
+
segment = index;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const oldSpan = oldColumns[segment + 1] - oldColumns[segment];
|
|
96
|
+
const newSpan = newColumns[segment + 1] - newColumns[segment];
|
|
97
|
+
const ratio = (x - oldColumns[segment]) / oldSpan;
|
|
98
|
+
return mappedNumber(newColumns[segment] + ratio * newSpan);
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Apply one horizontal coordinate mapping to every schema-v1 absolute X pin.
|
|
104
|
+
* The caller owns the supplied workflow; this function reports an audit trail
|
|
105
|
+
* for each changed coordinate in stable document order.
|
|
106
|
+
*/
|
|
107
|
+
export function mapExplicitCoordinates(workflow, mapX) {
|
|
108
|
+
const changedCoordinates = [];
|
|
109
|
+
const record = (path, owner, property) => {
|
|
110
|
+
const from = owner[property];
|
|
111
|
+
const to = mapX(from);
|
|
112
|
+
owner[property] = to;
|
|
113
|
+
if (to !== from) changedCoordinates.push({ path, from, to });
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
for (const [edgeIndex, edge] of workflow.edges.entries()) {
|
|
117
|
+
if (Array.isArray(edge.via)) {
|
|
118
|
+
for (const [pointIndex, point] of edge.via.entries()) {
|
|
119
|
+
if (Array.isArray(point) && Number.isFinite(point[0])) {
|
|
120
|
+
record(`/edges/${edgeIndex}/via/${pointIndex}/0`, point, 0);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (Array.isArray(edge.labelAt) && Number.isFinite(edge.labelAt[0])) {
|
|
125
|
+
record(`/edges/${edgeIndex}/labelAt/0`, edge.labelAt, 0);
|
|
126
|
+
}
|
|
127
|
+
if (Number.isFinite(edge.channelX)) {
|
|
128
|
+
record(`/edges/${edgeIndex}/channelX`, edge, 'channelX');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return changedCoordinates;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Construct an independently owned schema-v2 candidate with all authored
|
|
136
|
+
* absolute X pins mapped to the readable rank plan.
|
|
137
|
+
*/
|
|
138
|
+
export function createMappedWorkflowCandidate(workflow, oldColumns, newColumns) {
|
|
139
|
+
const document = clone(workflow);
|
|
140
|
+
document.schema_version = TARGET_SCHEMA_VERSION;
|
|
141
|
+
const mapX = createHorizontalRankMapper(oldColumns, newColumns);
|
|
142
|
+
const changedCoordinates = mapExplicitCoordinates(document, mapX);
|
|
143
|
+
return { document, changedCoordinates };
|
|
144
|
+
}
|