@crazyhappyone/auto-graph 0.1.4 → 0.2.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/cli/index.cjs +475 -49
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +475 -49
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +476 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +476 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -808,7 +808,6 @@ function applyDistributeContained(input, boxes, locks, diagnostics) {
|
|
|
808
808
|
const lock = locks.get(childId);
|
|
809
809
|
if (lock?.source === "fixed-position") {
|
|
810
810
|
unlocked.push({ id: childId, box });
|
|
811
|
-
locks.delete(childId);
|
|
812
811
|
continue;
|
|
813
812
|
}
|
|
814
813
|
diagnostics.push({
|
|
@@ -3981,6 +3980,240 @@ function isValidDimension(value) {
|
|
|
3981
3980
|
return Number.isFinite(value) && value >= 0;
|
|
3982
3981
|
}
|
|
3983
3982
|
|
|
3983
|
+
// src/routing/astar.ts
|
|
3984
|
+
function findObstacleFreePath(source, target, obstacles, options = {}, diagnostics) {
|
|
3985
|
+
const margin = options.margin ?? 0;
|
|
3986
|
+
const turnPenalty = options.turnPenalty ?? 50;
|
|
3987
|
+
const segmentPenalty = options.segmentPenalty ?? 1;
|
|
3988
|
+
const endpointObstacles = options.endpointObstacles ?? [];
|
|
3989
|
+
const maxNodes = options.maxNodes ?? (obstacles.length > 30 ? 16e3 : 4e3);
|
|
3990
|
+
const xs = collectXs(source, target, obstacles, margin);
|
|
3991
|
+
const ys = collectYs(source, target, obstacles, margin);
|
|
3992
|
+
if (xs.length * ys.length > maxNodes) {
|
|
3993
|
+
diagnostics?.push({
|
|
3994
|
+
severity: "warning",
|
|
3995
|
+
code: "routing.astar.grid_overflow",
|
|
3996
|
+
message: `A* grid overflow: ${xs.length * ys.length} nodes > ${maxNodes} limit. Falling back to heuristic routing.`,
|
|
3997
|
+
detail: {
|
|
3998
|
+
xsCount: xs.length,
|
|
3999
|
+
ysCount: ys.length,
|
|
4000
|
+
maxNodes
|
|
4001
|
+
}
|
|
4002
|
+
});
|
|
4003
|
+
return null;
|
|
4004
|
+
}
|
|
4005
|
+
const { nodes, nodeIndex } = buildGraph(xs, ys);
|
|
4006
|
+
connectHorizontalEdges(nodes, ys, obstacles, endpointObstacles, margin);
|
|
4007
|
+
connectVerticalEdges(nodes, xs, obstacles, endpointObstacles, margin);
|
|
4008
|
+
const path = aStarSearch(
|
|
4009
|
+
nodes,
|
|
4010
|
+
nodeIndex,
|
|
4011
|
+
source,
|
|
4012
|
+
target,
|
|
4013
|
+
turnPenalty,
|
|
4014
|
+
segmentPenalty
|
|
4015
|
+
);
|
|
4016
|
+
if (path === null) return null;
|
|
4017
|
+
return simplifyRoute(path);
|
|
4018
|
+
}
|
|
4019
|
+
function collectXs(source, target, obstacles, margin) {
|
|
4020
|
+
const raw = [];
|
|
4021
|
+
for (const obs of obstacles) {
|
|
4022
|
+
raw.push(obs.x - margin - 2, obs.x + obs.width + margin + 2);
|
|
4023
|
+
}
|
|
4024
|
+
const deduped = dedupSorted(raw);
|
|
4025
|
+
for (const v of [source.x, target.x]) {
|
|
4026
|
+
if (!deduped.includes(v)) {
|
|
4027
|
+
deduped.push(v);
|
|
4028
|
+
}
|
|
4029
|
+
}
|
|
4030
|
+
return deduped.sort((a, b) => a - b);
|
|
4031
|
+
}
|
|
4032
|
+
function collectYs(source, target, obstacles, margin) {
|
|
4033
|
+
const raw = [];
|
|
4034
|
+
for (const obs of obstacles) {
|
|
4035
|
+
raw.push(obs.y - margin - 2, obs.y + obs.height + margin + 2);
|
|
4036
|
+
}
|
|
4037
|
+
const deduped = dedupSorted(raw);
|
|
4038
|
+
for (const v of [source.y, target.y]) {
|
|
4039
|
+
if (!deduped.includes(v)) {
|
|
4040
|
+
deduped.push(v);
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
return deduped.sort((a, b) => a - b);
|
|
4044
|
+
}
|
|
4045
|
+
function dedupSorted(values) {
|
|
4046
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
4047
|
+
const result = [];
|
|
4048
|
+
for (const v of sorted) {
|
|
4049
|
+
const last = result[result.length - 1];
|
|
4050
|
+
if (last === void 0 || v - last > 2) {
|
|
4051
|
+
result.push(v);
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
return result;
|
|
4055
|
+
}
|
|
4056
|
+
function buildGraph(xs, ys) {
|
|
4057
|
+
const nodes = [];
|
|
4058
|
+
const nodeIndex = /* @__PURE__ */ new Map();
|
|
4059
|
+
for (let xi = 0; xi < xs.length; xi++) {
|
|
4060
|
+
for (let yi = 0; yi < ys.length; yi++) {
|
|
4061
|
+
const x = xs[xi];
|
|
4062
|
+
const y = ys[yi];
|
|
4063
|
+
const id = nodes.length;
|
|
4064
|
+
nodes.push({ x, y, id, neighbors: /* @__PURE__ */ new Map() });
|
|
4065
|
+
nodeIndex.set(`${x},${y}`, id);
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
return { nodes, nodeIndex };
|
|
4069
|
+
}
|
|
4070
|
+
function connectHorizontalEdges(nodes, ys, obstacles, endpointObstacles, margin) {
|
|
4071
|
+
for (const y of ys) {
|
|
4072
|
+
const row = nodes.filter((n) => n.y === y).sort((a, b) => a.x - b.x);
|
|
4073
|
+
for (let i = 0; i < row.length - 1; i++) {
|
|
4074
|
+
const a = row[i];
|
|
4075
|
+
const b = row[i + 1];
|
|
4076
|
+
const dx = b.x - a.x;
|
|
4077
|
+
if (dx <= 0) continue;
|
|
4078
|
+
if (segmentCrossesAny(a, b, obstacles, endpointObstacles, margin)) {
|
|
4079
|
+
continue;
|
|
4080
|
+
}
|
|
4081
|
+
a.neighbors.set(b.id, dx);
|
|
4082
|
+
b.neighbors.set(a.id, dx);
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4086
|
+
function connectVerticalEdges(nodes, xs, obstacles, endpointObstacles, margin) {
|
|
4087
|
+
for (const x of xs) {
|
|
4088
|
+
const col = nodes.filter((n) => n.x === x).sort((a, b) => a.y - b.y);
|
|
4089
|
+
for (let i = 0; i < col.length - 1; i++) {
|
|
4090
|
+
const a = col[i];
|
|
4091
|
+
const b = col[i + 1];
|
|
4092
|
+
const dy = b.y - a.y;
|
|
4093
|
+
if (dy <= 0) continue;
|
|
4094
|
+
if (segmentCrossesAny(a, b, obstacles, endpointObstacles, margin)) {
|
|
4095
|
+
continue;
|
|
4096
|
+
}
|
|
4097
|
+
a.neighbors.set(b.id, dy);
|
|
4098
|
+
b.neighbors.set(a.id, dy);
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
4102
|
+
function segmentCrossesAny(a, b, obstacles, endpointObstacles, margin) {
|
|
4103
|
+
for (const obs of obstacles) {
|
|
4104
|
+
if (segmentCrossesBoxStrict(a, b, obs, margin)) return true;
|
|
4105
|
+
}
|
|
4106
|
+
for (const ep of endpointObstacles) {
|
|
4107
|
+
if (segmentCrossesBoxStrict(a, b, ep, margin)) return true;
|
|
4108
|
+
}
|
|
4109
|
+
return false;
|
|
4110
|
+
}
|
|
4111
|
+
function segmentCrossesBoxStrict(start, end, box, margin) {
|
|
4112
|
+
const left = box.x - margin;
|
|
4113
|
+
const right = box.x + box.width + margin;
|
|
4114
|
+
const top = box.y - margin;
|
|
4115
|
+
const bottom = box.y + box.height + margin;
|
|
4116
|
+
if (pointInsideStrict(start, left, right, top, bottom)) return true;
|
|
4117
|
+
if (pointInsideStrict(end, left, right, top, bottom)) return true;
|
|
4118
|
+
if (start.x === end.x) {
|
|
4119
|
+
return start.x >= left && start.x <= right && rangesOverlap(start.y, end.y, top, bottom);
|
|
4120
|
+
}
|
|
4121
|
+
if (start.y === end.y) {
|
|
4122
|
+
return start.y >= top && start.y <= bottom && rangesOverlap(start.x, end.x, left, right);
|
|
4123
|
+
}
|
|
4124
|
+
return segmentEdgeIntersect(start, end, left, top, right, top) || segmentEdgeIntersect(start, end, right, top, right, bottom) || segmentEdgeIntersect(start, end, right, bottom, left, bottom) || segmentEdgeIntersect(start, end, left, bottom, left, top);
|
|
4125
|
+
}
|
|
4126
|
+
function pointInsideStrict(p, left, right, top, bottom) {
|
|
4127
|
+
return p.x > left && p.x < right && p.y > top && p.y < bottom;
|
|
4128
|
+
}
|
|
4129
|
+
function rangesOverlap(a, b, min, max) {
|
|
4130
|
+
const low = Math.min(a, b);
|
|
4131
|
+
const high = Math.max(a, b);
|
|
4132
|
+
return high > min && low < max;
|
|
4133
|
+
}
|
|
4134
|
+
function segmentEdgeIntersect(start, end, x1, y1, x2, y2) {
|
|
4135
|
+
const denominator = (end.x - start.x) * (y2 - y1) - (end.y - start.y) * (x2 - x1);
|
|
4136
|
+
if (denominator === 0) return false;
|
|
4137
|
+
const t = ((start.x - x1) * (y2 - y1) - (start.y - y1) * (x2 - x1)) / denominator;
|
|
4138
|
+
const u = ((start.x - x1) * (end.y - start.y) - (start.y - y1) * (end.x - start.x)) / denominator;
|
|
4139
|
+
return t > 0 && t < 1 && u > 0 && u < 1;
|
|
4140
|
+
}
|
|
4141
|
+
function aStarSearch(nodes, nodeIndex, source, target, turnPenalty, segmentPenalty) {
|
|
4142
|
+
const startId = nodeIndex.get(`${source.x},${source.y}`);
|
|
4143
|
+
const goalId = nodeIndex.get(`${target.x},${target.y}`);
|
|
4144
|
+
if (startId === void 0 || goalId === void 0) return null;
|
|
4145
|
+
const gScore = /* @__PURE__ */ new Map();
|
|
4146
|
+
gScore.set(startId, 0);
|
|
4147
|
+
const cameFrom = /* @__PURE__ */ new Map();
|
|
4148
|
+
const cameFromDir = /* @__PURE__ */ new Map();
|
|
4149
|
+
const openSet = [];
|
|
4150
|
+
openSet.push({
|
|
4151
|
+
id: startId,
|
|
4152
|
+
f: manhattan(source, target)
|
|
4153
|
+
});
|
|
4154
|
+
while (openSet.length > 0) {
|
|
4155
|
+
let bestIdx = 0;
|
|
4156
|
+
for (let i = 1; i < openSet.length; i++) {
|
|
4157
|
+
if (openSet[i].f < openSet[bestIdx].f) {
|
|
4158
|
+
bestIdx = i;
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
const current = openSet.splice(bestIdx, 1)[0];
|
|
4162
|
+
if (current.id === goalId) {
|
|
4163
|
+
return reconstructPath(nodes, cameFrom, goalId);
|
|
4164
|
+
}
|
|
4165
|
+
const node = nodes[current.id];
|
|
4166
|
+
const currentG = gScore.get(current.id);
|
|
4167
|
+
const prevDir = cameFromDir.get(current.id);
|
|
4168
|
+
for (const [neighborId, edgeCost] of node.neighbors) {
|
|
4169
|
+
const neighbor = nodes[neighborId];
|
|
4170
|
+
const tentativeG = currentG + edgeCost * segmentPenalty;
|
|
4171
|
+
const newDir = neighbor.y === node.y ? "h" : "v";
|
|
4172
|
+
const turnCost = prevDir !== void 0 && prevDir !== newDir ? turnPenalty : 0;
|
|
4173
|
+
const totalG = tentativeG + turnCost;
|
|
4174
|
+
const existingG = gScore.get(neighborId);
|
|
4175
|
+
if (existingG === void 0 || totalG < existingG) {
|
|
4176
|
+
gScore.set(neighborId, totalG);
|
|
4177
|
+
cameFrom.set(neighborId, current.id);
|
|
4178
|
+
cameFromDir.set(neighborId, newDir);
|
|
4179
|
+
const f = totalG + manhattan(neighbor, target);
|
|
4180
|
+
openSet.push({ id: neighborId, f });
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
return null;
|
|
4185
|
+
}
|
|
4186
|
+
function manhattan(a, b) {
|
|
4187
|
+
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
4188
|
+
}
|
|
4189
|
+
function reconstructPath(nodes, cameFrom, goalId) {
|
|
4190
|
+
const path = [];
|
|
4191
|
+
let current = goalId;
|
|
4192
|
+
while (current !== void 0) {
|
|
4193
|
+
const node = nodes[current];
|
|
4194
|
+
path.unshift({ x: node.x, y: node.y });
|
|
4195
|
+
current = cameFrom.get(current);
|
|
4196
|
+
}
|
|
4197
|
+
return path;
|
|
4198
|
+
}
|
|
4199
|
+
function simplifyRoute(points) {
|
|
4200
|
+
if (points.length <= 2) return [...points];
|
|
4201
|
+
const result = [points[0]];
|
|
4202
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
4203
|
+
const prev = result[result.length - 1];
|
|
4204
|
+
const curr = points[i];
|
|
4205
|
+
const next = points[i + 1];
|
|
4206
|
+
if (!areCollinear(prev, curr, next)) {
|
|
4207
|
+
result.push(curr);
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
result.push(points[points.length - 1]);
|
|
4211
|
+
return result;
|
|
4212
|
+
}
|
|
4213
|
+
function areCollinear(a, b, c) {
|
|
4214
|
+
return a.x === b.x && b.x === c.x || a.y === b.y && b.y === c.y;
|
|
4215
|
+
}
|
|
4216
|
+
|
|
3984
4217
|
// src/routing/routes.ts
|
|
3985
4218
|
function routeEdge(input) {
|
|
3986
4219
|
const diagnostics = [];
|
|
@@ -4026,6 +4259,44 @@ function routeEdge(input) {
|
|
|
4026
4259
|
}
|
|
4027
4260
|
return { points, diagnostics };
|
|
4028
4261
|
}
|
|
4262
|
+
if ((input.kind ?? "orthogonal") === "obstacle-avoiding") {
|
|
4263
|
+
const endpointObstacles = endpointObstaclesForAutoAnchors(input);
|
|
4264
|
+
for (const { sourceAnchor, targetAnchor } of routeAnchorPairs(
|
|
4265
|
+
input,
|
|
4266
|
+
defaultAnchors
|
|
4267
|
+
)) {
|
|
4268
|
+
const source = getEdgePort(
|
|
4269
|
+
input.source,
|
|
4270
|
+
input.target.center,
|
|
4271
|
+
sourceAnchor
|
|
4272
|
+
);
|
|
4273
|
+
const target = getEdgePort(
|
|
4274
|
+
input.target,
|
|
4275
|
+
input.source.center,
|
|
4276
|
+
targetAnchor
|
|
4277
|
+
);
|
|
4278
|
+
const path = findObstacleFreePath(
|
|
4279
|
+
source,
|
|
4280
|
+
target,
|
|
4281
|
+
[...softObstacles, ...hardObstacles],
|
|
4282
|
+
{
|
|
4283
|
+
endpointObstacles
|
|
4284
|
+
},
|
|
4285
|
+
diagnostics
|
|
4286
|
+
);
|
|
4287
|
+
if (path !== null && path.length >= 2) {
|
|
4288
|
+
const finalized = finalizeRoute(
|
|
4289
|
+
path,
|
|
4290
|
+
softObstacles,
|
|
4291
|
+
hardObstacles,
|
|
4292
|
+
diagnostics
|
|
4293
|
+
);
|
|
4294
|
+
if (!routeIntersectsObstacles(finalized, softObstacles) && !routeIntersectsObstacles(finalized, hardObstacles)) {
|
|
4295
|
+
return { points: finalized, diagnostics };
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4029
4300
|
const routeLaneObstacles = [...softObstacles, ...hardObstacles];
|
|
4030
4301
|
const anchorPairs = routeAnchorPairs(input, defaultAnchors);
|
|
4031
4302
|
const candidateRoutes = anchorPairs.flatMap(
|
|
@@ -4228,7 +4499,7 @@ function routeEdge(input) {
|
|
|
4228
4499
|
};
|
|
4229
4500
|
}
|
|
4230
4501
|
function finalizeRoute(points, softObstacles, hardObstacles, diagnostics) {
|
|
4231
|
-
const simplified =
|
|
4502
|
+
const simplified = simplifyRoute2(points);
|
|
4232
4503
|
if (simplified.length >= 3) {
|
|
4233
4504
|
return simplified;
|
|
4234
4505
|
}
|
|
@@ -4516,7 +4787,7 @@ function squaredDistance2(a, b) {
|
|
|
4516
4787
|
const dy = a.y - b.y;
|
|
4517
4788
|
return dx * dx + dy * dy;
|
|
4518
4789
|
}
|
|
4519
|
-
function
|
|
4790
|
+
function simplifyRoute2(points) {
|
|
4520
4791
|
const withoutDuplicates = [];
|
|
4521
4792
|
for (const point2 of points) {
|
|
4522
4793
|
const previous = withoutDuplicates.at(-1);
|
|
@@ -4528,7 +4799,7 @@ function simplifyRoute(points) {
|
|
|
4528
4799
|
for (const point2 of withoutDuplicates) {
|
|
4529
4800
|
const previous = simplified.at(-1);
|
|
4530
4801
|
const beforePrevious = simplified.at(-2);
|
|
4531
|
-
if (previous !== void 0 && beforePrevious !== void 0 &&
|
|
4802
|
+
if (previous !== void 0 && beforePrevious !== void 0 && areCollinear2(beforePrevious, previous, point2)) {
|
|
4532
4803
|
simplified[simplified.length - 1] = { ...point2 };
|
|
4533
4804
|
} else {
|
|
4534
4805
|
simplified.push({ ...point2 });
|
|
@@ -4743,17 +5014,17 @@ function segmentIntersectsBox(start, end, box) {
|
|
|
4743
5014
|
return true;
|
|
4744
5015
|
}
|
|
4745
5016
|
if (start.x === end.x) {
|
|
4746
|
-
return start.x > left && start.x < right &&
|
|
5017
|
+
return start.x > left && start.x < right && rangesOverlap2(start.y, end.y, top, bottom);
|
|
4747
5018
|
}
|
|
4748
5019
|
if (start.y === end.y) {
|
|
4749
|
-
return start.y > top && start.y < bottom &&
|
|
5020
|
+
return start.y > top && start.y < bottom && rangesOverlap2(start.x, end.x, left, right);
|
|
4750
5021
|
}
|
|
4751
5022
|
return segmentIntersectsBoxEdge(start, end, left, top, right, top) || segmentIntersectsBoxEdge(start, end, right, top, right, bottom) || segmentIntersectsBoxEdge(start, end, right, bottom, left, bottom) || segmentIntersectsBoxEdge(start, end, left, bottom, left, top);
|
|
4752
5023
|
}
|
|
4753
5024
|
function pointInsideBox(point2, box) {
|
|
4754
5025
|
return point2.x > box.x && point2.x < box.x + box.width && point2.y > box.y && point2.y < box.y + box.height;
|
|
4755
5026
|
}
|
|
4756
|
-
function
|
|
5027
|
+
function rangesOverlap2(a, b, min, max) {
|
|
4757
5028
|
const low = Math.min(a, b);
|
|
4758
5029
|
const high = Math.max(a, b);
|
|
4759
5030
|
return high > min && low < max;
|
|
@@ -4777,7 +5048,7 @@ function segmentBox(a, b) {
|
|
|
4777
5048
|
height: Math.max(1, Math.abs(a.y - b.y))
|
|
4778
5049
|
};
|
|
4779
5050
|
}
|
|
4780
|
-
function
|
|
5051
|
+
function areCollinear2(a, b, c) {
|
|
4781
5052
|
return a.x === b.x && b.x === c.x || a.y === b.y && b.y === c.y;
|
|
4782
5053
|
}
|
|
4783
5054
|
|
|
@@ -4857,11 +5128,12 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4857
5128
|
options,
|
|
4858
5129
|
diagnostics
|
|
4859
5130
|
);
|
|
5131
|
+
expandNodeBoxesForPorts(styledNodes, initialNodeBoxes, options, diagnostics);
|
|
4860
5132
|
const constrained = applyLayoutConstraints({
|
|
4861
5133
|
direction: diagram.direction,
|
|
4862
5134
|
overlapSpacing: options?.overlapSpacing ?? 40,
|
|
4863
5135
|
...options.minSiblingGap === void 0 ? {} : { minSiblingGap: options.minSiblingGap },
|
|
4864
|
-
|
|
5136
|
+
distributeContainedChildren: options.distributeContainedChildren ?? true,
|
|
4865
5137
|
boxes: initialNodeBoxes,
|
|
4866
5138
|
nodes: styledNodes,
|
|
4867
5139
|
constraints
|
|
@@ -4920,6 +5192,11 @@ function solveDiagram(diagram, options = {}) {
|
|
|
4920
5192
|
swimlanes: coordinatedSwimlanes,
|
|
4921
5193
|
...options.textMeasurer === void 0 ? {} : { textMeasurer: options.textMeasurer }
|
|
4922
5194
|
});
|
|
5195
|
+
const edgeLabelEstimates = estimateEdgeLabelAnnotations(
|
|
5196
|
+
styledEdges,
|
|
5197
|
+
nodeGeometryById,
|
|
5198
|
+
options.textMeasurer
|
|
5199
|
+
);
|
|
4923
5200
|
const layoutBoxes = [
|
|
4924
5201
|
...coordinatedNodes.map((node) => node.box),
|
|
4925
5202
|
...coordinatedNodes.flatMap(
|
|
@@ -5000,7 +5277,10 @@ function solveDiagram(diagram, options = {}) {
|
|
|
5000
5277
|
const frameTextAnnotation = frame === void 0 ? [] : [coordinateFrameTextAnnotation(frame, options.textMeasurer)];
|
|
5001
5278
|
const routingTextObstacles = [
|
|
5002
5279
|
...baseTextAnnotations.filter(isPreRouteTextObstacle),
|
|
5003
|
-
...frameTextAnnotation.filter(isPreRouteTextObstacle)
|
|
5280
|
+
...frameTextAnnotation.filter(isPreRouteTextObstacle),
|
|
5281
|
+
// Dry-run edge-label estimates so edges route around
|
|
5282
|
+
// each other's label areas (Issue #41).
|
|
5283
|
+
...edgeLabelEstimates
|
|
5004
5284
|
];
|
|
5005
5285
|
const margin = options.obstacleMargin ?? 0;
|
|
5006
5286
|
const softObstacles = [
|
|
@@ -5033,7 +5313,8 @@ function solveDiagram(diagram, options = {}) {
|
|
|
5033
5313
|
hardObstacles,
|
|
5034
5314
|
diagram.direction,
|
|
5035
5315
|
options,
|
|
5036
|
-
diagnostics
|
|
5316
|
+
diagnostics,
|
|
5317
|
+
coordinatedGroups
|
|
5037
5318
|
);
|
|
5038
5319
|
const edgeTextAnnotations = coordinateEdgeTextAnnotations(
|
|
5039
5320
|
coordinatedEdges,
|
|
@@ -5149,22 +5430,7 @@ function expandLabelLayoutToNode(layout2, nodeSize) {
|
|
|
5149
5430
|
y: layout2.box.y + offsetY,
|
|
5150
5431
|
width: layout2.box.width,
|
|
5151
5432
|
height: layout2.box.height
|
|
5152
|
-
}
|
|
5153
|
-
contentBox: {
|
|
5154
|
-
x: layout2.contentBox.x + offsetX,
|
|
5155
|
-
y: layout2.contentBox.y + offsetY,
|
|
5156
|
-
width: layout2.contentBox.width,
|
|
5157
|
-
height: layout2.contentBox.height
|
|
5158
|
-
},
|
|
5159
|
-
lines: layout2.lines.map((line) => ({
|
|
5160
|
-
...line,
|
|
5161
|
-
box: {
|
|
5162
|
-
x: line.box.x + offsetX,
|
|
5163
|
-
y: line.box.y + offsetY,
|
|
5164
|
-
width: line.box.width,
|
|
5165
|
-
height: line.box.height
|
|
5166
|
-
}
|
|
5167
|
-
}))
|
|
5433
|
+
}
|
|
5168
5434
|
};
|
|
5169
5435
|
}
|
|
5170
5436
|
function reportPageOverflow(contentBounds, pageBounds) {
|
|
@@ -6111,6 +6377,7 @@ function coordinateNodes(nodes, boxes, options, diagnostics) {
|
|
|
6111
6377
|
});
|
|
6112
6378
|
continue;
|
|
6113
6379
|
}
|
|
6380
|
+
const ports = node.ports === void 0 ? void 0 : coordinatePorts(node, box, options.portShifting);
|
|
6114
6381
|
const geometry = computeShapeGeometry({
|
|
6115
6382
|
shape: node.shape,
|
|
6116
6383
|
box,
|
|
@@ -6120,7 +6387,7 @@ function coordinateNodes(nodes, boxes, options, diagnostics) {
|
|
|
6120
6387
|
id: node.id,
|
|
6121
6388
|
...node.label === void 0 ? {} : { label: node.label },
|
|
6122
6389
|
...node.style === void 0 ? {} : { style: node.style },
|
|
6123
|
-
...
|
|
6390
|
+
...ports === void 0 ? {} : { ports },
|
|
6124
6391
|
...node.compartments === void 0 ? {} : { compartments: node.compartments },
|
|
6125
6392
|
...node.labelLayout === void 0 ? {} : { labelLayout: node.labelLayout },
|
|
6126
6393
|
shape: node.shape,
|
|
@@ -6132,6 +6399,78 @@ function coordinateNodes(nodes, boxes, options, diagnostics) {
|
|
|
6132
6399
|
}
|
|
6133
6400
|
return coordinated;
|
|
6134
6401
|
}
|
|
6402
|
+
var PORT_BOX_SIZE = 10;
|
|
6403
|
+
var MIN_PORT_EDGE_GAP = 12;
|
|
6404
|
+
function expandNodeBoxesForPorts(nodes, boxes, options, diagnostics) {
|
|
6405
|
+
const shiftingEnabled = options.portShifting?.enabled ?? true;
|
|
6406
|
+
if (!shiftingEnabled) return;
|
|
6407
|
+
const requestedSpacing = options.portShifting?.spacing ?? 24;
|
|
6408
|
+
const minSpacing = Math.max(
|
|
6409
|
+
requestedSpacing,
|
|
6410
|
+
PORT_BOX_SIZE + MIN_PORT_EDGE_GAP
|
|
6411
|
+
);
|
|
6412
|
+
for (const node of nodes) {
|
|
6413
|
+
if (node.ports === void 0 || node.ports.length === 0) continue;
|
|
6414
|
+
const box = boxes.get(node.id);
|
|
6415
|
+
if (box === void 0) continue;
|
|
6416
|
+
let heightExpansion = 0;
|
|
6417
|
+
let widthExpansion = 0;
|
|
6418
|
+
const portsBySide = /* @__PURE__ */ new Map();
|
|
6419
|
+
for (const port of node.ports) {
|
|
6420
|
+
const list = portsBySide.get(port.side) ?? [];
|
|
6421
|
+
list.push(port);
|
|
6422
|
+
portsBySide.set(port.side, list);
|
|
6423
|
+
}
|
|
6424
|
+
for (const [side, ports] of portsBySide) {
|
|
6425
|
+
const count = (ports ?? []).length;
|
|
6426
|
+
if (count <= 1) continue;
|
|
6427
|
+
const isVertical = side === "left" || side === "right";
|
|
6428
|
+
const availableSpan = isVertical ? box.height : box.width;
|
|
6429
|
+
const requiredSpan = (count - 1) * minSpacing + PORT_BOX_SIZE;
|
|
6430
|
+
if (requiredSpan > availableSpan) {
|
|
6431
|
+
const expansion = requiredSpan - availableSpan;
|
|
6432
|
+
if (isVertical) {
|
|
6433
|
+
heightExpansion = Math.max(heightExpansion, expansion);
|
|
6434
|
+
} else {
|
|
6435
|
+
widthExpansion = Math.max(widthExpansion, expansion);
|
|
6436
|
+
}
|
|
6437
|
+
diagnostics.push({
|
|
6438
|
+
severity: "info",
|
|
6439
|
+
code: "port_capacity_overflow",
|
|
6440
|
+
message: `Expanded node ${node.id} ${isVertical ? "height" : "width"} by ${Math.ceil(expansion)} px to fit ${count} port(s) on ${side} side.`,
|
|
6441
|
+
path: ["nodes", node.id, "ports"],
|
|
6442
|
+
detail: {
|
|
6443
|
+
nodeId: node.id,
|
|
6444
|
+
side,
|
|
6445
|
+
portCount: count,
|
|
6446
|
+
expansion: Math.ceil(expansion)
|
|
6447
|
+
}
|
|
6448
|
+
});
|
|
6449
|
+
}
|
|
6450
|
+
}
|
|
6451
|
+
if (heightExpansion > 0) {
|
|
6452
|
+
box.y -= heightExpansion / 2;
|
|
6453
|
+
box.height += heightExpansion;
|
|
6454
|
+
}
|
|
6455
|
+
if (widthExpansion > 0) {
|
|
6456
|
+
box.x -= widthExpansion / 2;
|
|
6457
|
+
box.width += widthExpansion;
|
|
6458
|
+
}
|
|
6459
|
+
if ((heightExpansion > 0 || widthExpansion > 0) && node.labelLayout !== void 0) {
|
|
6460
|
+
const layout2 = node.labelLayout;
|
|
6461
|
+
const newOffsetX = Math.max(0, (box.width - layout2.box.width) / 2);
|
|
6462
|
+
const newOffsetY = Math.max(0, (box.height - layout2.box.height) / 2);
|
|
6463
|
+
node.labelLayout = {
|
|
6464
|
+
...layout2,
|
|
6465
|
+
box: {
|
|
6466
|
+
...layout2.box,
|
|
6467
|
+
x: newOffsetX,
|
|
6468
|
+
y: newOffsetY
|
|
6469
|
+
}
|
|
6470
|
+
};
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6135
6474
|
function coordinatePorts(node, nodeBox, portShifting) {
|
|
6136
6475
|
const portsBySide = /* @__PURE__ */ new Map();
|
|
6137
6476
|
for (const port of node.ports ?? []) {
|
|
@@ -6168,7 +6507,11 @@ function portAnchor(nodeBox, side, index, count, portShifting) {
|
|
|
6168
6507
|
const requestedSpacing = portShifting?.spacing ?? 24;
|
|
6169
6508
|
const maxOffset = side === "left" || side === "right" ? nodeBox.height / 2 : nodeBox.width / 2;
|
|
6170
6509
|
const availableSpan = 2 * maxOffset;
|
|
6171
|
-
const
|
|
6510
|
+
const minSpacing = PORT_BOX_SIZE + MIN_PORT_EDGE_GAP;
|
|
6511
|
+
const spacing = shiftingEnabled && count > 1 ? Math.max(
|
|
6512
|
+
Math.min(requestedSpacing, availableSpan / (count - 1)),
|
|
6513
|
+
minSpacing
|
|
6514
|
+
) : requestedSpacing;
|
|
6172
6515
|
const centeredOffset = shiftingEnabled ? (index - (count - 1) / 2) * spacing : 0;
|
|
6173
6516
|
switch (side) {
|
|
6174
6517
|
case "left":
|
|
@@ -6194,7 +6537,7 @@ function portAnchor(nodeBox, side, index, count, portShifting) {
|
|
|
6194
6537
|
}
|
|
6195
6538
|
}
|
|
6196
6539
|
function portBox(anchor) {
|
|
6197
|
-
const size =
|
|
6540
|
+
const size = PORT_BOX_SIZE;
|
|
6198
6541
|
return {
|
|
6199
6542
|
x: anchor.x - size / 2,
|
|
6200
6543
|
y: anchor.y - size / 2,
|
|
@@ -6783,7 +7126,7 @@ function evidenceOverlapDiagnostic(block, conflict) {
|
|
|
6783
7126
|
}
|
|
6784
7127
|
};
|
|
6785
7128
|
}
|
|
6786
|
-
function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacles, textObstacles, hardObstacles, direction, options, diagnostics) {
|
|
7129
|
+
function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacles, textObstacles, hardObstacles, direction, options, diagnostics, groups) {
|
|
6787
7130
|
const coordinated = [];
|
|
6788
7131
|
const coordinatedNodeById = new Map(
|
|
6789
7132
|
coordinatedNodes.map((node) => [node.id, node])
|
|
@@ -6807,8 +7150,7 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
6807
7150
|
}
|
|
6808
7151
|
const sourcePort = coordinatedNodeById.get(edge.source.nodeId)?.ports?.find((port) => port.id === edge.source.portId);
|
|
6809
7152
|
const targetPort = coordinatedNodeById.get(edge.target.nodeId)?.ports?.find((port) => port.id === edge.target.portId);
|
|
6810
|
-
const
|
|
6811
|
-
const routeTextObstacles = textObstacles.filter((annotation) => !connectedTextOwners.has(annotation.ownerId)).map((annotation) => annotation.box);
|
|
7153
|
+
const routeTextObstacles = textObstacles.filter((annotation) => !isEdgeConnectedTextAnnotation(edge, annotation)).map((annotation) => annotation.box);
|
|
6812
7154
|
const route = routeEdge({
|
|
6813
7155
|
kind: options.routeKind ?? "orthogonal",
|
|
6814
7156
|
direction,
|
|
@@ -6821,6 +7163,7 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
6821
7163
|
(obstacle) => obstacle !== source.obstacleBox && obstacle !== target.obstacleBox
|
|
6822
7164
|
),
|
|
6823
7165
|
...softObstacles,
|
|
7166
|
+
...groupObstaclesForEdge(edge, groups, options.obstacleMargin ?? 0),
|
|
6824
7167
|
...routeTextObstacles
|
|
6825
7168
|
],
|
|
6826
7169
|
hardObstacles,
|
|
@@ -6839,15 +7182,52 @@ function coordinateEdges(edges, nodes, coordinatedNodes, obstacles, softObstacle
|
|
|
6839
7182
|
}
|
|
6840
7183
|
return coordinated;
|
|
6841
7184
|
}
|
|
6842
|
-
function
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
7185
|
+
function isEdgeConnectedTextAnnotation(edge, annotation) {
|
|
7186
|
+
switch (annotation.surfaceKind) {
|
|
7187
|
+
case "edge-label":
|
|
7188
|
+
return annotation.ownerId === edge.id;
|
|
7189
|
+
case "node-label":
|
|
7190
|
+
case "compartment-row":
|
|
7191
|
+
return annotation.ownerId === edge.source.nodeId || annotation.ownerId === edge.target.nodeId;
|
|
7192
|
+
case "port-label":
|
|
7193
|
+
return edge.source.portId !== void 0 && annotation.ownerId === `${edge.source.nodeId}.${edge.source.portId}` || edge.target.portId !== void 0 && annotation.ownerId === `${edge.target.nodeId}.${edge.target.portId}`;
|
|
7194
|
+
case "group-label":
|
|
7195
|
+
case "swimlane-label":
|
|
7196
|
+
case "frame-title":
|
|
7197
|
+
return false;
|
|
6846
7198
|
}
|
|
6847
|
-
|
|
6848
|
-
|
|
7199
|
+
}
|
|
7200
|
+
function ancestorGroupIds(groups, nodeId) {
|
|
7201
|
+
const direct = /* @__PURE__ */ new Set();
|
|
7202
|
+
for (const group of groups) {
|
|
7203
|
+
if (group.nodeIds.includes(nodeId)) {
|
|
7204
|
+
direct.add(group.id);
|
|
7205
|
+
}
|
|
7206
|
+
}
|
|
7207
|
+
let previousSize = -1;
|
|
7208
|
+
const ancestors = new Set(direct);
|
|
7209
|
+
while (ancestors.size !== previousSize) {
|
|
7210
|
+
previousSize = ancestors.size;
|
|
7211
|
+
for (const group of groups) {
|
|
7212
|
+
for (const candidate of ancestors) {
|
|
7213
|
+
if (group.groupIds.includes(candidate)) {
|
|
7214
|
+
ancestors.add(group.id);
|
|
7215
|
+
break;
|
|
7216
|
+
}
|
|
7217
|
+
}
|
|
7218
|
+
}
|
|
6849
7219
|
}
|
|
6850
|
-
return
|
|
7220
|
+
return ancestors;
|
|
7221
|
+
}
|
|
7222
|
+
function groupObstaclesForEdge(edge, groups, margin) {
|
|
7223
|
+
const sourceAncestors = ancestorGroupIds(groups, edge.source.nodeId);
|
|
7224
|
+
const targetAncestors = ancestorGroupIds(groups, edge.target.nodeId);
|
|
7225
|
+
return groups.filter((group) => {
|
|
7226
|
+
if (sourceAncestors.has(group.id) || targetAncestors.has(group.id)) {
|
|
7227
|
+
return false;
|
|
7228
|
+
}
|
|
7229
|
+
return true;
|
|
7230
|
+
}).map((group) => margin === 0 ? group.box : expandBox(group.box, margin));
|
|
6851
7231
|
}
|
|
6852
7232
|
function coordinateBaseTextAnnotations(input) {
|
|
6853
7233
|
const measurer = input.textMeasurer ?? createDefaultTextMeasurer();
|
|
@@ -7035,6 +7415,55 @@ function coordinateEdgeTextAnnotations(edges, obstacleBoxes, textMeasurer, label
|
|
|
7035
7415
|
}
|
|
7036
7416
|
return annotations;
|
|
7037
7417
|
}
|
|
7418
|
+
function estimateEdgeLabelAnnotations(edges, nodes, textMeasurer) {
|
|
7419
|
+
const measurer = textMeasurer ?? createDefaultTextMeasurer();
|
|
7420
|
+
const annotations = [];
|
|
7421
|
+
for (const edge of edges) {
|
|
7422
|
+
if (edge.label?.text === void 0) {
|
|
7423
|
+
continue;
|
|
7424
|
+
}
|
|
7425
|
+
const sourceGeom = nodes.get(edge.source.nodeId);
|
|
7426
|
+
const targetGeom = nodes.get(edge.target.nodeId);
|
|
7427
|
+
if (sourceGeom === void 0 || targetGeom === void 0) {
|
|
7428
|
+
continue;
|
|
7429
|
+
}
|
|
7430
|
+
const layout2 = fitLabel(
|
|
7431
|
+
edge.label.text,
|
|
7432
|
+
{
|
|
7433
|
+
font: typographyTextStyle(edge.label, {
|
|
7434
|
+
fontFamily: "Arial",
|
|
7435
|
+
fontSize: 12,
|
|
7436
|
+
lineHeight: 14
|
|
7437
|
+
}),
|
|
7438
|
+
padding: { top: 0, right: 0, bottom: 0, left: 0 },
|
|
7439
|
+
minSize: { width: 0, height: 0 },
|
|
7440
|
+
maxWidth: 200
|
|
7441
|
+
},
|
|
7442
|
+
measurer
|
|
7443
|
+
);
|
|
7444
|
+
const cx = (sourceGeom.center.x + targetGeom.center.x) / 2;
|
|
7445
|
+
const cy = (sourceGeom.center.y + targetGeom.center.y) / 2;
|
|
7446
|
+
const box = {
|
|
7447
|
+
x: cx - layout2.box.width / 2,
|
|
7448
|
+
y: cy - layout2.box.height / 2,
|
|
7449
|
+
width: layout2.box.width,
|
|
7450
|
+
height: layout2.box.height
|
|
7451
|
+
};
|
|
7452
|
+
annotations.push({
|
|
7453
|
+
text: layout2.text,
|
|
7454
|
+
ownerId: edge.id,
|
|
7455
|
+
surfaceKind: "edge-label",
|
|
7456
|
+
box,
|
|
7457
|
+
anchor: { x: cx, y: cy },
|
|
7458
|
+
paddings: layout2.padding,
|
|
7459
|
+
lines: layout2.lines,
|
|
7460
|
+
fontFamily: normalizeOutputFontFamily(layout2.font),
|
|
7461
|
+
fontSize: layout2.font.fontSize,
|
|
7462
|
+
textBackend: layout2.textBackend
|
|
7463
|
+
});
|
|
7464
|
+
}
|
|
7465
|
+
return annotations;
|
|
7466
|
+
}
|
|
7038
7467
|
function coordinateFrameTextAnnotation(frame, textMeasurer) {
|
|
7039
7468
|
const layout2 = fitLabel(
|
|
7040
7469
|
frame.titleTab,
|
|
@@ -7155,9 +7584,8 @@ function reportRouteTextClearance(edges, annotations) {
|
|
|
7155
7584
|
const diagnostics = [];
|
|
7156
7585
|
const relevantAnnotations = annotations.filter(isRouteClearanceText);
|
|
7157
7586
|
for (const edge of edges) {
|
|
7158
|
-
const connectedTextOwners = edgeConnectedTextOwnerIds(edge);
|
|
7159
7587
|
for (const annotation of relevantAnnotations) {
|
|
7160
|
-
if (
|
|
7588
|
+
if (isEdgeConnectedTextAnnotation(edge, annotation)) {
|
|
7161
7589
|
continue;
|
|
7162
7590
|
}
|
|
7163
7591
|
if (!routeIntersectsTextBox(edge.points, annotation.box)) {
|
|
@@ -7181,9 +7609,6 @@ function reportRouteTextClearance(edges, annotations) {
|
|
|
7181
7609
|
return diagnostics;
|
|
7182
7610
|
}
|
|
7183
7611
|
function isPreRouteTextObstacle(annotation) {
|
|
7184
|
-
if (annotation.surfaceKind === "edge-label") {
|
|
7185
|
-
return false;
|
|
7186
|
-
}
|
|
7187
7612
|
return isRouteClearanceText(annotation);
|
|
7188
7613
|
}
|
|
7189
7614
|
function isRouteClearanceText(annotation) {
|
|
@@ -7194,8 +7619,9 @@ function isRouteClearanceText(annotation) {
|
|
|
7194
7619
|
case "frame-title":
|
|
7195
7620
|
return true;
|
|
7196
7621
|
case "node-label":
|
|
7197
|
-
case "group-label":
|
|
7198
7622
|
case "compartment-row":
|
|
7623
|
+
return true;
|
|
7624
|
+
case "group-label":
|
|
7199
7625
|
return textExtendsOutsideAnchor(annotation);
|
|
7200
7626
|
}
|
|
7201
7627
|
}
|
|
@@ -7228,17 +7654,17 @@ function segmentIntersectsBox2(start, end, box) {
|
|
|
7228
7654
|
return true;
|
|
7229
7655
|
}
|
|
7230
7656
|
if (start.x === end.x) {
|
|
7231
|
-
return start.x > left && start.x < right &&
|
|
7657
|
+
return start.x > left && start.x < right && rangesOverlap3(start.y, end.y, top, bottom);
|
|
7232
7658
|
}
|
|
7233
7659
|
if (start.y === end.y) {
|
|
7234
|
-
return start.y > top && start.y < bottom &&
|
|
7660
|
+
return start.y > top && start.y < bottom && rangesOverlap3(start.x, end.x, left, right);
|
|
7235
7661
|
}
|
|
7236
7662
|
return segmentIntersectsBoxEdge2(start, end, left, top, right, top) || segmentIntersectsBoxEdge2(start, end, right, top, right, bottom) || segmentIntersectsBoxEdge2(start, end, right, bottom, left, bottom) || segmentIntersectsBoxEdge2(start, end, left, bottom, left, top);
|
|
7237
7663
|
}
|
|
7238
7664
|
function pointInsideBox2(point2, box) {
|
|
7239
7665
|
return point2.x > box.x && point2.x < box.x + box.width && point2.y > box.y && point2.y < box.y + box.height;
|
|
7240
7666
|
}
|
|
7241
|
-
function
|
|
7667
|
+
function rangesOverlap3(a, b, min, max) {
|
|
7242
7668
|
const low = Math.min(a, b);
|
|
7243
7669
|
const high = Math.max(a, b);
|
|
7244
7670
|
return high > min && low < max;
|
|
@@ -7834,6 +8260,6 @@ function isPointLikeRecord(value) {
|
|
|
7834
8260
|
return isPlainObject(value) && typeof value.x === "number" && typeof value.y === "number";
|
|
7835
8261
|
}
|
|
7836
8262
|
|
|
7837
|
-
export { DEFAULT_CANONICAL_PRECISION, DEFAULT_DSL_MAX_BYTES, DELIVERABILITY_DIAGNOSTIC_CODES, DeterministicTextMeasurer, LabelFitter, PretextTextMeasurer, applyLayoutConstraints, assertFiniteNonNegative, assertFinitePositive, boxCenter, canonicalize, computeArrowhead, computeContainerGeometry, computeShapeGeometry, createDefaultTextMeasurer, expandBox, exportExcalidraw, exportSvg, fitLabel, getEdgePort, installNodeCanvasRuntime, intersectsAabb, isPretextRuntimeAvailable, normalizeDiagramDsl, normalizeInsets, parseDiagramDsl, parseEdgeShorthand, renderDiagramDsl, resolveLineHeight, resolveOutputFormat, routeEdge, runDagreInitialLayout, simplifyRoute, solveDiagram, solveDiagramSafe, sortDslDiagnostics, stringifyCanonical, toCanvasFont, unionBoxes, validateBox, validateTextStyle };
|
|
8263
|
+
export { DEFAULT_CANONICAL_PRECISION, DEFAULT_DSL_MAX_BYTES, DELIVERABILITY_DIAGNOSTIC_CODES, DeterministicTextMeasurer, LabelFitter, PretextTextMeasurer, applyLayoutConstraints, assertFiniteNonNegative, assertFinitePositive, boxCenter, canonicalize, computeArrowhead, computeContainerGeometry, computeShapeGeometry, createDefaultTextMeasurer, expandBox, exportExcalidraw, exportSvg, fitLabel, getEdgePort, installNodeCanvasRuntime, intersectsAabb, isPretextRuntimeAvailable, normalizeDiagramDsl, normalizeInsets, parseDiagramDsl, parseEdgeShorthand, renderDiagramDsl, resolveLineHeight, resolveOutputFormat, routeEdge, runDagreInitialLayout, simplifyRoute2 as simplifyRoute, solveDiagram, solveDiagramSafe, sortDslDiagnostics, stringifyCanonical, toCanvasFont, unionBoxes, validateBox, validateTextStyle };
|
|
7838
8264
|
//# sourceMappingURL=index.js.map
|
|
7839
8265
|
//# sourceMappingURL=index.js.map
|