@drawtonomy/sdk 0.5.0 → 0.7.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/README.ja.md +36 -0
- package/README.md +22 -2
- package/dist/exporter/index.d.ts +3 -0
- package/dist/exporter/index.d.ts.map +1 -1
- package/dist/exporter/index.js +8 -3
- package/dist/exporter/index.js.map +1 -1
- package/dist/exporter/lanelet2.d.ts +26 -0
- package/dist/exporter/lanelet2.d.ts.map +1 -0
- package/dist/exporter/lanelet2.js +261 -0
- package/dist/exporter/lanelet2.js.map +1 -0
- package/dist/exporter/osmParser.d.ts +54 -0
- package/dist/exporter/osmParser.d.ts.map +1 -0
- package/dist/exporter/osmParser.js +247 -0
- package/dist/exporter/osmParser.js.map +1 -0
- package/dist/exporter/osmToShapes.d.ts +107 -0
- package/dist/exporter/osmToShapes.d.ts.map +1 -0
- package/dist/exporter/osmToShapes.js +370 -0
- package/dist/exporter/osmToShapes.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/snapshot.d.ts +9 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +60 -0
- package/dist/snapshot.js.map +1 -0
- package/package.json +7 -6
- package/LICENSE +0 -190
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
// Convert parsed Lanelet2 OSM data into the shape primitives that the
|
|
2
|
+
// drawtonomy editor consumes (points, linestrings, lanes).
|
|
3
|
+
//
|
|
4
|
+
// The output is the intermediate `ImportedShapes` structure used by the
|
|
5
|
+
// editor's import flow — not a full DrawtonomySnapshot — because the editor
|
|
6
|
+
// needs per-shape positioning + bounds to drive its chunked import (camera
|
|
7
|
+
// alignment, progress reporting, etc.). Callers can wrap the result into
|
|
8
|
+
// shapes themselves.
|
|
9
|
+
import { latLonToCanvas } from './osmParser';
|
|
10
|
+
/** Default allocator: monotonic counter per shape kind. */
|
|
11
|
+
export function createShapeIdAllocator() {
|
|
12
|
+
const counters = { point: 0, linestring: 0, lane: 0 };
|
|
13
|
+
return {
|
|
14
|
+
next(kind) {
|
|
15
|
+
const id = `shape:${kind}_${counters[kind]}`;
|
|
16
|
+
counters[kind] += 1;
|
|
17
|
+
return id;
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function getMiddlePoint(points) {
|
|
22
|
+
if (points.length === 0)
|
|
23
|
+
return { x: 0, y: 0 };
|
|
24
|
+
if (points.length === 1)
|
|
25
|
+
return points[0];
|
|
26
|
+
if (points.length === 2) {
|
|
27
|
+
return {
|
|
28
|
+
x: (points[0].x + points[1].x) / 2,
|
|
29
|
+
y: (points[0].y + points[1].y) / 2,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return points[Math.floor(points.length / 2)];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Decide whether to reverse the left and/or right boundary so the lane is
|
|
36
|
+
* interpreted consistently by the editor.
|
|
37
|
+
*
|
|
38
|
+
* In Lanelet2, the way's node order defines the lane direction (the left
|
|
39
|
+
* boundary's direction is the lane's direction). This routine preserves that
|
|
40
|
+
* direction whenever possible, only flipping a boundary when needed to keep
|
|
41
|
+
* the right-of-left invariant.
|
|
42
|
+
*/
|
|
43
|
+
export function alignBoundaries(leftPoints, rightPoints) {
|
|
44
|
+
if (leftPoints.length < 2 || rightPoints.length < 2) {
|
|
45
|
+
return { invertLeft: false, invertRight: false };
|
|
46
|
+
}
|
|
47
|
+
const getEffective = (points, invert) => invert ? [...points].reverse() : points;
|
|
48
|
+
const areParallel = (left, right) => {
|
|
49
|
+
const ls = left[0], le = left[left.length - 1];
|
|
50
|
+
const rs = right[0], re = right[right.length - 1];
|
|
51
|
+
const parallelDist = Math.hypot(ls.x - rs.x, ls.y - rs.y) + Math.hypot(le.x - re.x, le.y - re.y);
|
|
52
|
+
const crossDist = Math.hypot(ls.x - re.x, ls.y - re.y) + Math.hypot(le.x - rs.x, le.y - rs.y);
|
|
53
|
+
return parallelDist <= crossDist;
|
|
54
|
+
};
|
|
55
|
+
const isRightOnRightSide = (left, right) => {
|
|
56
|
+
if (left.length < 2 || right.length < 1)
|
|
57
|
+
return false;
|
|
58
|
+
const leftDir = {
|
|
59
|
+
x: left[left.length - 1].x - left[0].x,
|
|
60
|
+
y: left[left.length - 1].y - left[0].y,
|
|
61
|
+
};
|
|
62
|
+
const leftMid = getMiddlePoint(left);
|
|
63
|
+
const rightMid = getMiddlePoint(right);
|
|
64
|
+
const leftToRight = {
|
|
65
|
+
x: rightMid.x - leftMid.x,
|
|
66
|
+
y: rightMid.y - leftMid.y,
|
|
67
|
+
};
|
|
68
|
+
// Cross product. In screen coordinates (Y points down), the sign is
|
|
69
|
+
// inverted vs. standard math convention; positive means "right is on the
|
|
70
|
+
// right of left".
|
|
71
|
+
const cross = leftDir.x * leftToRight.y - leftDir.y * leftToRight.x;
|
|
72
|
+
if (Math.abs(cross) < 1e-6) {
|
|
73
|
+
// Converging boundaries: fall back to comparing start-to-start.
|
|
74
|
+
const leftToRightStart = {
|
|
75
|
+
x: right[0].x - left[0].x,
|
|
76
|
+
y: right[0].y - left[0].y,
|
|
77
|
+
};
|
|
78
|
+
const crossStart = leftDir.x * leftToRightStart.y - leftDir.y * leftToRightStart.x;
|
|
79
|
+
return crossStart > 0;
|
|
80
|
+
}
|
|
81
|
+
return cross > 0;
|
|
82
|
+
};
|
|
83
|
+
if (areParallel(leftPoints, rightPoints) && isRightOnRightSide(leftPoints, rightPoints)) {
|
|
84
|
+
return { invertLeft: false, invertRight: false };
|
|
85
|
+
}
|
|
86
|
+
const rightInverted = getEffective(rightPoints, true);
|
|
87
|
+
if (areParallel(leftPoints, rightInverted) && isRightOnRightSide(leftPoints, rightInverted)) {
|
|
88
|
+
return { invertLeft: false, invertRight: true };
|
|
89
|
+
}
|
|
90
|
+
const leftInverted = getEffective(leftPoints, true);
|
|
91
|
+
if (areParallel(leftInverted, rightPoints) && isRightOnRightSide(leftInverted, rightPoints)) {
|
|
92
|
+
return { invertLeft: true, invertRight: false };
|
|
93
|
+
}
|
|
94
|
+
if (areParallel(leftInverted, rightInverted) && isRightOnRightSide(leftInverted, rightInverted)) {
|
|
95
|
+
return { invertLeft: true, invertRight: true };
|
|
96
|
+
}
|
|
97
|
+
if (areParallel(leftPoints, rightPoints)) {
|
|
98
|
+
return { invertLeft: false, invertRight: false };
|
|
99
|
+
}
|
|
100
|
+
if (areParallel(leftPoints, rightInverted)) {
|
|
101
|
+
return { invertLeft: false, invertRight: true };
|
|
102
|
+
}
|
|
103
|
+
return { invertLeft: false, invertRight: false };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Detect lane connectivity (next/prev) by matching the boundary endpoints of
|
|
107
|
+
* one lane to the start of another. Runs in O(n) using start/end node hash
|
|
108
|
+
* maps.
|
|
109
|
+
*/
|
|
110
|
+
function detectLaneConnections(laneInfos) {
|
|
111
|
+
const connections = new Map();
|
|
112
|
+
laneInfos.forEach(info => {
|
|
113
|
+
connections.set(info.laneId, { next: [], prev: [] });
|
|
114
|
+
});
|
|
115
|
+
const getEffectiveNodes = (lane) => {
|
|
116
|
+
const leftStart = lane.invertLeft ? lane.leftLastNode : lane.leftFirstNode;
|
|
117
|
+
const leftEnd = lane.invertLeft ? lane.leftFirstNode : lane.leftLastNode;
|
|
118
|
+
const rightStart = lane.invertRight ? lane.rightLastNode : lane.rightFirstNode;
|
|
119
|
+
const rightEnd = lane.invertRight ? lane.rightFirstNode : lane.rightLastNode;
|
|
120
|
+
return { leftStart, leftEnd, rightStart, rightEnd };
|
|
121
|
+
};
|
|
122
|
+
const startNodeMap = new Map();
|
|
123
|
+
const endNodeMap = new Map();
|
|
124
|
+
for (const lane of laneInfos) {
|
|
125
|
+
const nodes = getEffectiveNodes(lane);
|
|
126
|
+
const startKey = `${nodes.leftStart}|${nodes.rightStart}`;
|
|
127
|
+
const endKey = `${nodes.leftEnd}|${nodes.rightEnd}`;
|
|
128
|
+
if (!startNodeMap.has(startKey))
|
|
129
|
+
startNodeMap.set(startKey, []);
|
|
130
|
+
startNodeMap.get(startKey).push(lane.laneId);
|
|
131
|
+
if (!endNodeMap.has(endKey))
|
|
132
|
+
endNodeMap.set(endKey, []);
|
|
133
|
+
endNodeMap.get(endKey).push(lane.laneId);
|
|
134
|
+
}
|
|
135
|
+
for (const lane of laneInfos) {
|
|
136
|
+
const nodes = getEffectiveNodes(lane);
|
|
137
|
+
const endKey = `${nodes.leftEnd}|${nodes.rightEnd}`;
|
|
138
|
+
const nextLaneIds = startNodeMap.get(endKey);
|
|
139
|
+
if (!nextLaneIds)
|
|
140
|
+
continue;
|
|
141
|
+
const conn = connections.get(lane.laneId);
|
|
142
|
+
for (const nextLaneId of nextLaneIds) {
|
|
143
|
+
if (nextLaneId === lane.laneId)
|
|
144
|
+
continue;
|
|
145
|
+
if (!conn.next.includes(nextLaneId)) {
|
|
146
|
+
conn.next.push(nextLaneId);
|
|
147
|
+
const nextConn = connections.get(nextLaneId);
|
|
148
|
+
if (!nextConn.prev.includes(lane.laneId)) {
|
|
149
|
+
nextConn.prev.push(lane.laneId);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return connections;
|
|
155
|
+
}
|
|
156
|
+
function emptyBounds() {
|
|
157
|
+
return {
|
|
158
|
+
minX: Infinity,
|
|
159
|
+
maxX: -Infinity,
|
|
160
|
+
minY: Infinity,
|
|
161
|
+
maxY: -Infinity,
|
|
162
|
+
centerX: 0,
|
|
163
|
+
centerY: 0,
|
|
164
|
+
width: 0,
|
|
165
|
+
height: 0,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Convert parsed OSM data into editor-ready point/linestring/lane records.
|
|
170
|
+
*
|
|
171
|
+
* Pass `selectedLaneIds` to restrict to a subset of lanelet relations
|
|
172
|
+
* (selective import); leave it `undefined` to import every `type=lanelet`
|
|
173
|
+
* relation.
|
|
174
|
+
*/
|
|
175
|
+
export function osmToShapes(osmData, options = {}) {
|
|
176
|
+
const idAllocator = options.idAllocator ?? createShapeIdAllocator();
|
|
177
|
+
const result = {
|
|
178
|
+
points: [],
|
|
179
|
+
linestrings: [],
|
|
180
|
+
lanes: [],
|
|
181
|
+
bounds: emptyBounds(),
|
|
182
|
+
};
|
|
183
|
+
// Compute the projection center.
|
|
184
|
+
let minLat = Infinity, maxLat = -Infinity;
|
|
185
|
+
let minLon = Infinity, maxLon = -Infinity;
|
|
186
|
+
osmData.nodes.forEach(node => {
|
|
187
|
+
if (node.lat < minLat)
|
|
188
|
+
minLat = node.lat;
|
|
189
|
+
if (node.lat > maxLat)
|
|
190
|
+
maxLat = node.lat;
|
|
191
|
+
if (node.lon < minLon)
|
|
192
|
+
minLon = node.lon;
|
|
193
|
+
if (node.lon > maxLon)
|
|
194
|
+
maxLon = node.lon;
|
|
195
|
+
});
|
|
196
|
+
// For files emitted by drawtonomy, honor the embedded origin so page
|
|
197
|
+
// coordinates round-trip exactly. Otherwise center on the bbox.
|
|
198
|
+
const centerLat = osmData.drawtonomyOrigin?.lat ?? (minLat + maxLat) / 2;
|
|
199
|
+
const centerLon = osmData.drawtonomyOrigin?.lon ?? (minLon + maxLon) / 2;
|
|
200
|
+
result.originLatLon = { lat: centerLat, lon: centerLon };
|
|
201
|
+
const osmNodeToPointId = new Map();
|
|
202
|
+
const osmWayToLinestringId = new Map();
|
|
203
|
+
const pointIdToPoint = new Map();
|
|
204
|
+
const linestringIdToLinestring = new Map();
|
|
205
|
+
// Only `type=lanelet` relations become lanes. Other relation types
|
|
206
|
+
// (regulatory_element, multipolygon, etc.) are preserved verbatim via the
|
|
207
|
+
// OSM sidecar.
|
|
208
|
+
let laneletRelations = osmData.relations.filter(r => r.tags.type === 'lanelet');
|
|
209
|
+
if (options.selectedLaneIds) {
|
|
210
|
+
const selected = new Set(options.selectedLaneIds);
|
|
211
|
+
laneletRelations = laneletRelations.filter(r => selected.has(r.id));
|
|
212
|
+
}
|
|
213
|
+
// Collect ways and nodes referenced by the chosen lanelets.
|
|
214
|
+
const usedWayIds = new Set();
|
|
215
|
+
const usedNodeIds = new Set();
|
|
216
|
+
for (const relation of laneletRelations) {
|
|
217
|
+
for (const member of relation.members) {
|
|
218
|
+
if (member.type === 'way')
|
|
219
|
+
usedWayIds.add(member.ref);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (const wayId of usedWayIds) {
|
|
223
|
+
const way = osmData.ways.get(wayId);
|
|
224
|
+
if (!way)
|
|
225
|
+
continue;
|
|
226
|
+
for (const ref of way.nodeRefs)
|
|
227
|
+
usedNodeIds.add(ref);
|
|
228
|
+
}
|
|
229
|
+
// Materialize points (one per OSM node, shared across boundaries).
|
|
230
|
+
for (const nodeId of usedNodeIds) {
|
|
231
|
+
const node = osmData.nodes.get(nodeId);
|
|
232
|
+
if (!node)
|
|
233
|
+
continue;
|
|
234
|
+
const { x, y } = latLonToCanvas(node.lat, node.lon, centerLat, centerLon);
|
|
235
|
+
const pointId = idAllocator.next('point');
|
|
236
|
+
osmNodeToPointId.set(nodeId, pointId);
|
|
237
|
+
const data = { id: pointId, x, y, osmId: nodeId };
|
|
238
|
+
result.points.push(data);
|
|
239
|
+
pointIdToPoint.set(pointId, data);
|
|
240
|
+
}
|
|
241
|
+
// Materialize linestrings (one per used way).
|
|
242
|
+
for (const wayId of usedWayIds) {
|
|
243
|
+
const way = osmData.ways.get(wayId);
|
|
244
|
+
if (!way)
|
|
245
|
+
continue;
|
|
246
|
+
const pointIds = [];
|
|
247
|
+
for (const nodeRef of way.nodeRefs) {
|
|
248
|
+
const pid = osmNodeToPointId.get(nodeRef);
|
|
249
|
+
if (pid)
|
|
250
|
+
pointIds.push(pid);
|
|
251
|
+
}
|
|
252
|
+
if (pointIds.length < 2)
|
|
253
|
+
continue;
|
|
254
|
+
const firstPoint = pointIdToPoint.get(pointIds[0]);
|
|
255
|
+
if (!firstPoint)
|
|
256
|
+
continue;
|
|
257
|
+
const linestringId = idAllocator.next('linestring');
|
|
258
|
+
osmWayToLinestringId.set(wayId, linestringId);
|
|
259
|
+
const data = {
|
|
260
|
+
id: linestringId,
|
|
261
|
+
x: firstPoint.x,
|
|
262
|
+
y: firstPoint.y,
|
|
263
|
+
pointIds,
|
|
264
|
+
osmId: wayId,
|
|
265
|
+
attributes: {
|
|
266
|
+
type: way.tags.type || 'line_thin',
|
|
267
|
+
subtype: way.tags.subtype || 'solid',
|
|
268
|
+
width: way.tags.width || '0.2',
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
result.linestrings.push(data);
|
|
272
|
+
linestringIdToLinestring.set(linestringId, data);
|
|
273
|
+
}
|
|
274
|
+
// Materialize lanes and collect info for connectivity detection.
|
|
275
|
+
const laneInfos = [];
|
|
276
|
+
for (const relation of laneletRelations) {
|
|
277
|
+
let leftWayId = null;
|
|
278
|
+
let rightWayId = null;
|
|
279
|
+
let leftBoundaryId = null;
|
|
280
|
+
let rightBoundaryId = null;
|
|
281
|
+
for (const member of relation.members) {
|
|
282
|
+
if (member.type !== 'way')
|
|
283
|
+
continue;
|
|
284
|
+
const linestringId = osmWayToLinestringId.get(member.ref);
|
|
285
|
+
if (!linestringId)
|
|
286
|
+
continue;
|
|
287
|
+
if (member.role === 'left') {
|
|
288
|
+
leftBoundaryId = linestringId;
|
|
289
|
+
leftWayId = member.ref;
|
|
290
|
+
}
|
|
291
|
+
else if (member.role === 'right') {
|
|
292
|
+
rightBoundaryId = linestringId;
|
|
293
|
+
rightWayId = member.ref;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (!leftBoundaryId || !rightBoundaryId || !leftWayId || !rightWayId)
|
|
297
|
+
continue;
|
|
298
|
+
const leftWay = osmData.ways.get(leftWayId);
|
|
299
|
+
const rightWay = osmData.ways.get(rightWayId);
|
|
300
|
+
const leftLinestring = linestringIdToLinestring.get(leftBoundaryId);
|
|
301
|
+
const rightLinestring = linestringIdToLinestring.get(rightBoundaryId);
|
|
302
|
+
if (!leftWay || !rightWay || !leftLinestring || !rightLinestring)
|
|
303
|
+
continue;
|
|
304
|
+
const getPointCoords = (pointIds) => pointIds
|
|
305
|
+
.map(pid => pointIdToPoint.get(pid))
|
|
306
|
+
.filter((p) => p !== undefined)
|
|
307
|
+
.map(p => ({ x: p.x, y: p.y }));
|
|
308
|
+
const { invertLeft, invertRight } = alignBoundaries(getPointCoords(leftLinestring.pointIds), getPointCoords(rightLinestring.pointIds));
|
|
309
|
+
const laneId = idAllocator.next('lane');
|
|
310
|
+
laneInfos.push({
|
|
311
|
+
osmId: relation.id,
|
|
312
|
+
laneId,
|
|
313
|
+
leftWayId,
|
|
314
|
+
rightWayId,
|
|
315
|
+
leftFirstNode: leftWay.nodeRefs[0],
|
|
316
|
+
leftLastNode: leftWay.nodeRefs[leftWay.nodeRefs.length - 1],
|
|
317
|
+
rightFirstNode: rightWay.nodeRefs[0],
|
|
318
|
+
rightLastNode: rightWay.nodeRefs[rightWay.nodeRefs.length - 1],
|
|
319
|
+
invertLeft,
|
|
320
|
+
invertRight,
|
|
321
|
+
});
|
|
322
|
+
result.lanes.push({
|
|
323
|
+
id: laneId,
|
|
324
|
+
x: leftLinestring.x,
|
|
325
|
+
y: leftLinestring.y,
|
|
326
|
+
leftBoundaryId,
|
|
327
|
+
rightBoundaryId,
|
|
328
|
+
invertLeft,
|
|
329
|
+
invertRight,
|
|
330
|
+
osmId: relation.id,
|
|
331
|
+
attributes: {
|
|
332
|
+
type: 'lanelet',
|
|
333
|
+
subtype: relation.tags.subtype || 'road',
|
|
334
|
+
location: relation.tags.location || 'urban',
|
|
335
|
+
one_way: relation.tags.one_way || 'yes',
|
|
336
|
+
speed_limit: relation.tags.speed_limit || '30',
|
|
337
|
+
turn_direction: relation.tags.turn_direction || 'straight',
|
|
338
|
+
},
|
|
339
|
+
next: [],
|
|
340
|
+
prev: [],
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
const connections = detectLaneConnections(laneInfos);
|
|
344
|
+
for (const lane of result.lanes) {
|
|
345
|
+
const conn = connections.get(lane.id);
|
|
346
|
+
if (conn) {
|
|
347
|
+
lane.next = conn.next;
|
|
348
|
+
lane.prev = conn.prev;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// Bounds across all materialized points.
|
|
352
|
+
for (const point of result.points) {
|
|
353
|
+
if (point.x < result.bounds.minX)
|
|
354
|
+
result.bounds.minX = point.x;
|
|
355
|
+
if (point.x > result.bounds.maxX)
|
|
356
|
+
result.bounds.maxX = point.x;
|
|
357
|
+
if (point.y < result.bounds.minY)
|
|
358
|
+
result.bounds.minY = point.y;
|
|
359
|
+
if (point.y > result.bounds.maxY)
|
|
360
|
+
result.bounds.maxY = point.y;
|
|
361
|
+
}
|
|
362
|
+
if (result.points.length > 0) {
|
|
363
|
+
result.bounds.width = result.bounds.maxX - result.bounds.minX;
|
|
364
|
+
result.bounds.height = result.bounds.maxY - result.bounds.minY;
|
|
365
|
+
result.bounds.centerX = result.bounds.minX + result.bounds.width / 2;
|
|
366
|
+
result.bounds.centerY = result.bounds.minY + result.bounds.height / 2;
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=osmToShapes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"osmToShapes.js","sourceRoot":"","sources":["../../src/exporter/osmToShapes.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,2DAA2D;AAC3D,EAAE;AACF,wEAAwE;AACxE,4EAA4E;AAC5E,2EAA2E;AAC3E,yEAAyE;AACzE,qBAAqB;AAGrB,OAAO,EAAE,cAAc,EAAgB,MAAM,aAAa,CAAA;AAW1D,2DAA2D;AAC3D,MAAM,UAAU,sBAAsB;IACpC,MAAM,QAAQ,GAA2B,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;IAC7E,OAAO;QACL,IAAI,CAAC,IAAI;YACP,MAAM,EAAE,GAAG,SAAS,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAa,CAAA;YACvD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACnB,OAAO,EAAE,CAAA;QACX,CAAC;KACF,CAAA;AACH,CAAC;AA8ED,SAAS,cAAc,CAAC,MAAiB;IACvC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAA;IACzC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAClC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;SACnC,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;AAC9C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAqB,EACrB,WAAsB;IAEtB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;IAClD,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,MAAiB,EAAE,MAAe,EAAE,EAAE,CAC1D,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IAEzC,MAAM,WAAW,GAAG,CAAC,IAAe,EAAE,KAAgB,EAAE,EAAE;QACxD,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAC9C,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;QAChG,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;QAC7F,OAAO,YAAY,IAAI,SAAS,CAAA;IAClC,CAAC,CAAA;IAED,MAAM,kBAAkB,GAAG,CAAC,IAAe,EAAE,KAAgB,EAAE,EAAE;QAC/D,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAA;QAErD,MAAM,OAAO,GAAG;YACd,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;SACvC,CAAA;QAED,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;QACpC,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;QAEtC,MAAM,WAAW,GAAG;YAClB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;YACzB,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;SAC1B,CAAA;QAED,oEAAoE;QACpE,yEAAyE;QACzE,kBAAkB;QAClB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAA;QAEnE,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;YAC3B,gEAAgE;YAChE,MAAM,gBAAgB,GAAG;gBACvB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;aAC1B,CAAA;YACD,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAA;YAClF,OAAO,UAAU,GAAG,CAAC,CAAA;QACvB,CAAC;QAED,OAAO,KAAK,GAAG,CAAC,CAAA;IAClB,CAAC,CAAA;IAED,IAAI,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,kBAAkB,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;QACxF,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;IAClD,CAAC;IAED,MAAM,aAAa,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;IACrD,IAAI,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,IAAI,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC;QAC5F,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;IACjD,CAAC;IAED,MAAM,YAAY,GAAG,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IACnD,IAAI,WAAW,CAAC,YAAY,EAAE,WAAW,CAAC,IAAI,kBAAkB,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,CAAC;QAC5F,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;IACjD,CAAC;IAED,IAAI,WAAW,CAAC,YAAY,EAAE,aAAa,CAAC,IAAI,kBAAkB,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,CAAC;QAChG,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;IAChD,CAAC;IAED,IAAI,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;QACzC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;IAClD,CAAC;IACD,IAAI,WAAW,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;IACjD,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAA;AAClD,CAAC;AAeD;;;;GAIG;AACH,SAAS,qBAAqB,CAC5B,SAAqB;IAErB,MAAM,WAAW,GAAG,IAAI,GAAG,EAA8C,CAAA;IACzE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACvB,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,MAAM,iBAAiB,GAAG,CAAC,IAAc,EAAE,EAAE;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAA;QAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAA;QACxE,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAA;QAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAA;QAC5E,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAA;IACrD,CAAC,CAAA;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAqB,CAAA;IACjD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAqB,CAAA;IAE/C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;QACrC,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,UAAU,EAAE,CAAA;QACzD,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAA;QACnD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;QAC/D,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC7C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QACvD,UAAU,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;QACrC,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAA;QACnD,MAAM,WAAW,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC5C,IAAI,CAAC,WAAW;YAAE,SAAQ;QAC1B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAE,CAAA;QAC1C,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,UAAU,KAAK,IAAI,CAAC,MAAM;gBAAE,SAAQ;YACxC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACpC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;gBAC1B,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,UAAU,CAAE,CAAA;gBAC7C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACzC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAA;AACpB,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,CAAC,QAAQ;QACf,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,CAAC,QAAQ;QACf,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,CAAC;QACV,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;KACV,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,UAA8B,EAAE;IAC5E,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,sBAAsB,EAAE,CAAA;IACnE,MAAM,MAAM,GAAmB;QAC7B,MAAM,EAAE,EAAE;QACV,WAAW,EAAE,EAAE;QACf,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,WAAW,EAAE;KACtB,CAAA;IAED,iCAAiC;IACjC,IAAI,MAAM,GAAG,QAAQ,EAAE,MAAM,GAAG,CAAC,QAAQ,CAAA;IACzC,IAAI,MAAM,GAAG,QAAQ,EAAE,MAAM,GAAG,CAAC,QAAQ,CAAA;IACzC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QAC3B,IAAI,IAAI,CAAC,GAAG,GAAG,MAAM;YAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAA;QACxC,IAAI,IAAI,CAAC,GAAG,GAAG,MAAM;YAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAA;QACxC,IAAI,IAAI,CAAC,GAAG,GAAG,MAAM;YAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAA;QACxC,IAAI,IAAI,CAAC,GAAG,GAAG,MAAM;YAAE,MAAM,GAAG,IAAI,CAAC,GAAG,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,qEAAqE;IACrE,gEAAgE;IAChE,MAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;IACxE,MAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;IACxE,MAAM,CAAC,YAAY,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,CAAA;IAExD,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAmB,CAAA;IACnD,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAmB,CAAA;IACvD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAyB,CAAA;IACvD,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAA8B,CAAA;IAEtE,mEAAmE;IACnE,0EAA0E;IAC1E,eAAe;IACf,IAAI,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;IAC/E,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;QACjD,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACrE,CAAC;IAED,4DAA4D;IAC5D,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAA;IACpC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IACrC,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;gBAAE,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACvD,CAAC;IACH,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,GAAG;YAAE,SAAQ;QAClB,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ;YAAE,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACtD,CAAC;IAED,mEAAmE;IACnE,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;QACzE,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzC,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACrC,MAAM,IAAI,GAAkB,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;QAChE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxB,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACnC,CAAC;IAED,8CAA8C;IAC9C,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,GAAG;YAAE,SAAQ;QAClB,MAAM,QAAQ,GAAa,EAAE,CAAA;QAC7B,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACzC,IAAI,GAAG;gBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC7B,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,SAAQ;QAEjC,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QAClD,IAAI,CAAC,UAAU;YAAE,SAAQ;QAEzB,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;QACnD,oBAAoB,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;QAC7C,MAAM,IAAI,GAAuB;YAC/B,EAAE,EAAE,YAAY;YAChB,CAAC,EAAE,UAAU,CAAC,CAAC;YACf,CAAC,EAAE,UAAU,CAAC,CAAC;YACf,QAAQ;YACR,KAAK,EAAE,KAAK;YACZ,UAAU,EAAE;gBACV,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,WAAW;gBAClC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO;gBACpC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK;aAC/B;SACF,CAAA;QACD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC7B,wBAAwB,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;IAClD,CAAC;IAED,iEAAiE;IACjE,MAAM,SAAS,GAAe,EAAE,CAAA;IAChC,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;QACxC,IAAI,SAAS,GAAkB,IAAI,CAAA;QACnC,IAAI,UAAU,GAAkB,IAAI,CAAA;QACpC,IAAI,cAAc,GAAkB,IAAI,CAAA;QACxC,IAAI,eAAe,GAAkB,IAAI,CAAA;QACzC,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK;gBAAE,SAAQ;YACnC,MAAM,YAAY,GAAG,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACzD,IAAI,CAAC,YAAY;gBAAE,SAAQ;YAC3B,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC3B,cAAc,GAAG,YAAY,CAAA;gBAC7B,SAAS,GAAG,MAAM,CAAC,GAAG,CAAA;YACxB,CAAC;iBAAM,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACnC,eAAe,GAAG,YAAY,CAAA;gBAC9B,UAAU,GAAG,MAAM,CAAC,GAAG,CAAA;YACzB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU;YAAE,SAAQ;QAE9E,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAC7C,MAAM,cAAc,GAAG,wBAAwB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;QACnE,MAAM,eAAe,GAAG,wBAAwB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;QACrE,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe;YAAE,SAAQ;QAE1E,MAAM,cAAc,GAAG,CAAC,QAAkB,EAAa,EAAE,CACvD,QAAQ;aACL,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aACnC,MAAM,CAAC,CAAC,CAAC,EAAsB,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;aAClD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAEnC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,eAAe,CACjD,cAAc,CAAC,cAAc,CAAC,QAAQ,CAAC,EACvC,cAAc,CAAC,eAAe,CAAC,QAAQ,CAAC,CACzC,CAAA;QAED,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvC,SAAS,CAAC,IAAI,CAAC;YACb,KAAK,EAAE,QAAQ,CAAC,EAAE;YAClB,MAAM;YACN,SAAS;YACT,UAAU;YACV,aAAa,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClC,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YAC3D,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YACpC,aAAa,EAAE,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YAC9D,UAAU;YACV,WAAW;SACZ,CAAC,CAAA;QAEF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;YAChB,EAAE,EAAE,MAAM;YACV,CAAC,EAAE,cAAc,CAAC,CAAC;YACnB,CAAC,EAAE,cAAc,CAAC,CAAC;YACnB,cAAc;YACd,eAAe;YACf,UAAU;YACV,WAAW;YACX,KAAK,EAAE,QAAQ,CAAC,EAAE;YAClB,UAAU,EAAE;gBACV,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,MAAM;gBACxC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO;gBAC3C,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,KAAK;gBACvC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI;gBAC9C,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,IAAI,UAAU;aAC3D;YACD,IAAI,EAAE,EAAE;YACR,IAAI,EAAE,EAAE;SACT,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAA;IACpD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;YACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACvB,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAA;QAC9D,IAAI,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAA;QAC9D,IAAI,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAA;QAC9D,IAAI,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI;YAAE,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAA;IAChE,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAA;QAC7D,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAA;QAC9D,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAA;QACpE,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;IACvE,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from './types';
|
|
|
3
3
|
export * from './helpers';
|
|
4
4
|
export * from './geometry';
|
|
5
5
|
export { ExtensionClient } from './ExtensionClient';
|
|
6
|
+
export { parseDrawtonomySvg } from './snapshot';
|
|
6
7
|
// Exporter sub-module is also available via "@drawtonomy/sdk/exporter".
|
|
7
8
|
export * as exporter from './exporter';
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,wEAAwE;AACxE,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,wEAAwE;AACxE,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DrawtonomySnapshot } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a `.drawtonomy.svg` source string and return the embedded
|
|
4
|
+
* DrawtonomySnapshot. Returns `null` if the file is not a drawtonomy SVG
|
|
5
|
+
* (e.g. plain SVG without an embedded snapshot) or the embedded payload is
|
|
6
|
+
* malformed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseDrawtonomySvg(svgContent: string): DrawtonomySnapshot | null;
|
|
9
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAkCjD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAgBhF"}
|
package/dist/snapshot.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Parse a `.drawtonomy.svg` file (a regular SVG with a base64-encoded
|
|
2
|
+
// snapshot embedded in `data-drawtonomy-snapshot`) back into a
|
|
3
|
+
// DrawtonomySnapshot. The legacy attribute name `data-drawauto-snapshot`
|
|
4
|
+
// is also accepted for backwards compatibility.
|
|
5
|
+
/**
|
|
6
|
+
* Decode a base64-encoded UTF-8 string. Mirrors the encoder used when the
|
|
7
|
+
* editor produces .drawtonomy.svg files: `btoa(unescape(encodeURIComponent(json)))`.
|
|
8
|
+
*/
|
|
9
|
+
function base64DecodeUtf8(encoded) {
|
|
10
|
+
if (typeof atob === 'function') {
|
|
11
|
+
return decodeURIComponent(escape(atob(encoded)));
|
|
12
|
+
}
|
|
13
|
+
// Node fallback (Buffer is global in Node 18+).
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
const buf = globalThis.Buffer;
|
|
16
|
+
if (buf) {
|
|
17
|
+
return buf.from(encoded, 'base64').toString('utf-8');
|
|
18
|
+
}
|
|
19
|
+
throw new Error('No base64 decoder available in this environment');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Extract the value of an attribute from the root `<svg>` element of an SVG
|
|
23
|
+
* source string. Used instead of DOMParser so the parser works in plain
|
|
24
|
+
* Node without jsdom.
|
|
25
|
+
*/
|
|
26
|
+
function extractRootSvgAttribute(svg, attrName) {
|
|
27
|
+
// Match the opening <svg ...> tag (allow line breaks inside).
|
|
28
|
+
const openTagMatch = svg.match(/<svg\b[^>]*>/);
|
|
29
|
+
if (!openTagMatch)
|
|
30
|
+
return null;
|
|
31
|
+
const openTag = openTagMatch[0];
|
|
32
|
+
const attrRegex = new RegExp(`\\b${attrName}="([^"]*)"`);
|
|
33
|
+
const m = openTag.match(attrRegex);
|
|
34
|
+
return m ? m[1] : null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse a `.drawtonomy.svg` source string and return the embedded
|
|
38
|
+
* DrawtonomySnapshot. Returns `null` if the file is not a drawtonomy SVG
|
|
39
|
+
* (e.g. plain SVG without an embedded snapshot) or the embedded payload is
|
|
40
|
+
* malformed.
|
|
41
|
+
*/
|
|
42
|
+
export function parseDrawtonomySvg(svgContent) {
|
|
43
|
+
if (!svgContent || typeof svgContent !== 'string')
|
|
44
|
+
return null;
|
|
45
|
+
const encoded = extractRootSvgAttribute(svgContent, 'data-drawtonomy-snapshot') ??
|
|
46
|
+
extractRootSvgAttribute(svgContent, 'data-drawauto-snapshot');
|
|
47
|
+
if (!encoded)
|
|
48
|
+
return null;
|
|
49
|
+
try {
|
|
50
|
+
const jsonString = base64DecodeUtf8(encoded);
|
|
51
|
+
const parsed = JSON.parse(jsonString);
|
|
52
|
+
if (!parsed || !Array.isArray(parsed.shapes))
|
|
53
|
+
return null;
|
|
54
|
+
return parsed;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,+DAA+D;AAC/D,yEAAyE;AACzE,gDAAgD;AAIhD;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAClD,CAAC;IACD,gDAAgD;IAChD,8DAA8D;IAC9D,MAAM,GAAG,GAAI,UAAkB,CAAC,MAAM,CAAA;IACtC,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IACtD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;AACpE,CAAC;AAED;;;;GAIG;AACH,SAAS,uBAAuB,CAAC,GAAW,EAAE,QAAgB;IAC5D,8DAA8D;IAC9D,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAA;IAC9C,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAA;IAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAA;IAC/B,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,MAAM,QAAQ,YAAY,CAAC,CAAA;IACxD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAClC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAE9D,MAAM,OAAO,GACX,uBAAuB,CAAC,UAAU,EAAE,0BAA0B,CAAC;QAC/D,uBAAuB,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAA;IAC/D,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAuB,CAAA;QAC3D,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAA;QACzD,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drawtonomy/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "SDK for building drawtonomy extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
"dist",
|
|
16
16
|
"README.md"
|
|
17
17
|
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"prepublishOnly": "pnpm build"
|
|
22
|
+
},
|
|
18
23
|
"keywords": [
|
|
19
24
|
"drawtonomy",
|
|
20
25
|
"extension",
|
|
@@ -27,9 +32,5 @@
|
|
|
27
32
|
"jsdom": "29.0.1",
|
|
28
33
|
"typescript": "5.9.3",
|
|
29
34
|
"vitest": "4.1.2"
|
|
30
|
-
},
|
|
31
|
-
"scripts": {
|
|
32
|
-
"build": "tsc",
|
|
33
|
-
"test": "vitest run"
|
|
34
35
|
}
|
|
35
|
-
}
|
|
36
|
+
}
|