@spectratools/graphic-designer-cli 0.10.0 → 0.12.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.md +42 -1
- package/dist/cli.js +262 -124
- package/dist/index.d.ts +44 -4
- package/dist/index.js +266 -74
- package/dist/qa.d.ts +1 -1
- package/dist/qa.js +50 -7
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.js +262 -124
- package/dist/{spec.schema-B6sXTTou.d.ts → spec.schema-BkbcnVcm.d.ts} +1790 -1267
- package/dist/spec.schema.d.ts +1 -1
- package/dist/spec.schema.js +50 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Cli } from 'incur';
|
|
2
|
-
import { T as ThemeInput, D as DesignSpec, a as Rect$1, b as DrawCommand, c as Theme, d as RenderedElement, A as AnchorHint, C as ConnectionElement } from './spec.schema-
|
|
3
|
-
export { e as AutoLayoutConfig, B as BuiltInTheme, f as CardElement, g as CodeBlockElement, h as ConstraintSpec, i as DEFAULT_GENERATOR_VERSION, j as DEFAULT_RAINBOW_COLORS, k as Decorator, l as DesignCardSpec, m as DesignSafeFrame, n as DesignTheme, o as DiagramElement, p as DiagramLayout, q as DiagramSpec, r as DrawArc, s as DrawBadge, t as DrawBezier, u as DrawCircle, v as DrawFontFamily, w as DrawGradientRect, x as DrawLine, y as DrawPath, z as DrawPoint, E as DrawRect, F as DrawShadow, G as DrawText, H as DrawTextRow, I as DrawTextRowSegment, J as Element, K as
|
|
2
|
+
import { T as ThemeInput, D as DesignSpec, a as Rect$1, b as DrawCommand, c as Theme, d as RenderedElement, A as AnchorHint, C as ConnectionElement } from './spec.schema-BkbcnVcm.js';
|
|
3
|
+
export { e as AutoLayoutConfig, B as BuiltInTheme, f as CardElement, g as CodeBlockElement, h as ConstraintSpec, i as DEFAULT_GENERATOR_VERSION, j as DEFAULT_RAINBOW_COLORS, k as Decorator, l as DesignCardSpec, m as DesignSafeFrame, n as DesignTheme, o as DiagramElement, p as DiagramLayout, q as DiagramSpec, r as DrawArc, s as DrawBadge, t as DrawBezier, u as DrawCircle, v as DrawFontFamily, w as DrawGradientRect, x as DrawLine, y as DrawPath, z as DrawPoint, E as DrawRect, F as DrawShadow, G as DrawText, H as DrawTextRow, I as DrawTextRowSegment, J as Element, K as EllipseLayoutConfig, L as FlowNodeElement, M as Gradient, N as GradientOverlayDecorator, O as GradientSpec, P as GradientStop, Q as GridLayoutConfig, S as ImageElement, U as IterationMeta, V as LayoutConfig, W as LayoutSnapshot, X as ManualLayoutConfig, Y as RainbowRuleDecorator, Z as RenderDesignOptions, R as RenderMetadata, _ as RenderResult, $ as ShapeElement, a0 as StackLayoutConfig, a1 as TerminalElement, a2 as TextElement, a3 as ThemeInput, a4 as VignetteDecorator, a5 as WrittenArtifacts, a6 as builtInThemeBackgrounds, a7 as builtInThemes, a8 as computeSpecHash, a9 as connectionElementSchema, aa as defaultAutoLayout, ab as defaultCanvas, ac as defaultConstraints, ad as defaultGridLayout, ae as defaultLayout, af as defaultStackLayout, ag as defaultTheme, ah as deriveSafeFrame, ai as designSpecSchema, aj as diagramElementSchema, ak as diagramLayoutSchema, al as diagramSpecSchema, am as drawGradientRect, an as drawRainbowRule, ao as drawVignette, ap as flowNodeElementSchema, aq as inferLayout, ar as inferSidecarPath, as as parseDesignSpec, at as parseDiagramSpec, au as renderDesign, av as resolveTheme, aw as writeRenderArtifacts } from './spec.schema-BkbcnVcm.js';
|
|
4
4
|
import { SKRSContext2D } from '@napi-rs/canvas';
|
|
5
5
|
export { QaIssue, QaReferenceResult, QaReport, QaSeverity, readMetadata, runQa } from './qa.js';
|
|
6
6
|
import { Highlighter } from 'shiki';
|
|
@@ -245,9 +245,16 @@ type Point$1 = {
|
|
|
245
245
|
|
|
246
246
|
type Point = Point$1;
|
|
247
247
|
type Rect = Rect$1;
|
|
248
|
-
type ConnectionRouting = 'auto' | 'orthogonal' | 'curve' | 'arc';
|
|
248
|
+
type ConnectionRouting = 'auto' | 'orthogonal' | 'curve' | 'arc' | 'straight';
|
|
249
|
+
type ConnectionCurveMode = 'normal' | 'ellipse';
|
|
249
250
|
type ConnectionArrow = 'none' | 'end' | 'start' | 'both';
|
|
250
251
|
type ConnectionStrokeStyle = 'solid' | 'dashed' | 'dotted';
|
|
252
|
+
type EllipseParams = {
|
|
253
|
+
cx: number;
|
|
254
|
+
cy: number;
|
|
255
|
+
rx: number;
|
|
256
|
+
ry: number;
|
|
257
|
+
};
|
|
251
258
|
type ConnectionRenderOptions = {
|
|
252
259
|
fromBounds: Rect;
|
|
253
260
|
toBounds: Rect;
|
|
@@ -292,6 +299,38 @@ declare function curveRoute(fromBounds: Rect, toBounds: Rect, diagramCenter: Poi
|
|
|
292
299
|
* automatic edge anchor calculation.
|
|
293
300
|
*/
|
|
294
301
|
declare function arcRoute(fromBounds: Rect, toBounds: Rect, diagramCenter: Point, tension: number, fromAnchor?: AnchorHint, toAnchor?: AnchorHint): [CubicBezierSegment, CubicBezierSegment];
|
|
302
|
+
/**
|
|
303
|
+
* Infer ellipse parameters from the bounding boxes of all flow-node elements.
|
|
304
|
+
*
|
|
305
|
+
* When explicit `ellipseRx`/`ellipseRy` are provided they are used directly.
|
|
306
|
+
* Otherwise the ellipse is fitted by computing the centroid of all node centers
|
|
307
|
+
* as the center, with `rx` and `ry` derived from the maximum horizontal and
|
|
308
|
+
* vertical distance from the centroid to any node center.
|
|
309
|
+
*/
|
|
310
|
+
declare function inferEllipseParams(nodeBounds: Rect[], explicitCenter?: Point, explicitRx?: number, explicitRy?: number): EllipseParams;
|
|
311
|
+
/**
|
|
312
|
+
* Compute a cubic bezier curve that traces an arc on a shared global ellipse.
|
|
313
|
+
*
|
|
314
|
+
* Uses the generalized kappa formula: `κ = (4/3) × tan(angularSpan / 4)`
|
|
315
|
+
* to produce control points from the ellipse tangent vectors at the source
|
|
316
|
+
* and target angles.
|
|
317
|
+
*
|
|
318
|
+
* The source and target points are the edge anchors of the respective node
|
|
319
|
+
* bounding boxes (not points on the ellipse itself), but the control points
|
|
320
|
+
* are derived from the ellipse tangent at the angle each node center makes
|
|
321
|
+
* with the ellipse center. This produces curves that follow the global
|
|
322
|
+
* ellipse arc while connecting node boundaries correctly.
|
|
323
|
+
*
|
|
324
|
+
* @returns `[startPoint, controlPoint1, controlPoint2, endPoint]`
|
|
325
|
+
*/
|
|
326
|
+
declare function ellipseRoute(fromBounds: Rect, toBounds: Rect, ellipse: EllipseParams, fromAnchor?: AnchorHint, toAnchor?: AnchorHint): [Point, Point, Point, Point];
|
|
327
|
+
/**
|
|
328
|
+
* Compute a straight-line route between two rectangles.
|
|
329
|
+
*
|
|
330
|
+
* When `fromAnchor` or `toAnchor` hints are provided, they override the
|
|
331
|
+
* automatic edge anchor calculation.
|
|
332
|
+
*/
|
|
333
|
+
declare function straightRoute(fromBounds: Rect, toBounds: Rect, fromAnchor?: AnchorHint, toAnchor?: AnchorHint): [Point, Point];
|
|
295
334
|
/**
|
|
296
335
|
* Compute an orthogonal (right-angle) path between two rectangles.
|
|
297
336
|
* Returns an array of waypoints forming a 3-segment path.
|
|
@@ -309,6 +348,7 @@ declare function bezierPointAt(p0: Point, cp1: Point, cp2: Point, p3: Point, t:
|
|
|
309
348
|
declare function computeDiagramCenter(nodeBounds: Rect[], canvasCenter?: Point): Point;
|
|
310
349
|
declare function renderConnection(ctx: SKRSContext2D, conn: ConnectionElement, fromBounds: Rect, toBounds: Rect, theme: Theme, edgeRoute?: EdgeRoute, options?: {
|
|
311
350
|
diagramCenter?: Point;
|
|
351
|
+
ellipseParams?: EllipseParams;
|
|
312
352
|
}): RenderedElement[];
|
|
313
353
|
|
|
314
354
|
/**
|
|
@@ -366,4 +406,4 @@ declare function highlightCode(code: string, language: string, themeName: string
|
|
|
366
406
|
*/
|
|
367
407
|
declare function disposeHighlighter(): void;
|
|
368
408
|
|
|
369
|
-
export { type CompareImagesOptions, type CompareImagesReport, type CompareRegionScore, type CompareVerdict, type ConnectionArrow, ConnectionElement, type ConnectionRenderOptions, type ConnectionRouting, type ConnectionStrokeStyle, type CubicBezierSegment, DesignSpec, DrawCommand, type EdgeRoute, type ElkLayoutResult, type HighlightedLine, type LayoutResult, type Point, Rect$1 as Rect, RenderedElement, Theme, arcRoute, bezierPointAt, buildCardsSpec, buildCodeSpec, buildFlowchartSpec, buildTerminalSpec, cli, compareImages, computeDiagramCenter, curveRoute, disposeHighlighter, edgeAnchor, highlightCode, initHighlighter, loadFonts, orthogonalRoute, outwardNormal, rectCenter, renderConnection, renderDrawCommands, resolveShikiTheme, themeToShikiMap };
|
|
409
|
+
export { type CompareImagesOptions, type CompareImagesReport, type CompareRegionScore, type CompareVerdict, type ConnectionArrow, type ConnectionCurveMode, ConnectionElement, type ConnectionRenderOptions, type ConnectionRouting, type ConnectionStrokeStyle, type CubicBezierSegment, DesignSpec, DrawCommand, type EdgeRoute, type ElkLayoutResult, type EllipseParams, type HighlightedLine, type LayoutResult, type Point, Rect$1 as Rect, RenderedElement, Theme, arcRoute, bezierPointAt, buildCardsSpec, buildCodeSpec, buildFlowchartSpec, buildTerminalSpec, cli, compareImages, computeDiagramCenter, curveRoute, disposeHighlighter, edgeAnchor, ellipseRoute, highlightCode, inferEllipseParams, initHighlighter, loadFonts, orthogonalRoute, outwardNormal, rectCenter, renderConnection, renderDrawCommands, resolveShikiTheme, straightRoute, themeToShikiMap };
|
package/dist/index.js
CHANGED
|
@@ -775,6 +775,10 @@ var drawShadowSchema = z2.object({
|
|
|
775
775
|
offsetY: z2.number().default(4)
|
|
776
776
|
}).strict();
|
|
777
777
|
var drawFontFamilySchema = z2.enum(["heading", "body", "mono"]);
|
|
778
|
+
var strokeGradientSchema = z2.object({
|
|
779
|
+
from: colorHexSchema2,
|
|
780
|
+
to: colorHexSchema2
|
|
781
|
+
}).strict();
|
|
778
782
|
var drawRectSchema = z2.object({
|
|
779
783
|
type: z2.literal("rect"),
|
|
780
784
|
x: z2.number(),
|
|
@@ -822,6 +826,7 @@ var drawLineSchema = z2.object({
|
|
|
822
826
|
x2: z2.number(),
|
|
823
827
|
y2: z2.number(),
|
|
824
828
|
color: colorHexSchema2.default("#FFFFFF"),
|
|
829
|
+
strokeGradient: strokeGradientSchema.optional(),
|
|
825
830
|
width: z2.number().min(0.5).max(32).default(2),
|
|
826
831
|
dash: z2.array(z2.number()).max(6).optional(),
|
|
827
832
|
arrow: z2.enum(["none", "end", "start", "both"]).default("none"),
|
|
@@ -852,6 +857,7 @@ var drawBezierSchema = z2.object({
|
|
|
852
857
|
type: z2.literal("bezier"),
|
|
853
858
|
points: z2.array(drawPointSchema).min(2).max(20),
|
|
854
859
|
color: colorHexSchema2.default("#FFFFFF"),
|
|
860
|
+
strokeGradient: strokeGradientSchema.optional(),
|
|
855
861
|
width: z2.number().min(0.5).max(32).default(2),
|
|
856
862
|
dash: z2.array(z2.number()).max(6).optional(),
|
|
857
863
|
arrow: z2.enum(["none", "end", "start", "both"]).default("none"),
|
|
@@ -1060,7 +1066,8 @@ var connectionElementSchema = z2.object({
|
|
|
1060
1066
|
from: z2.string().min(1).max(120),
|
|
1061
1067
|
to: z2.string().min(1).max(120),
|
|
1062
1068
|
style: z2.enum(["solid", "dashed", "dotted"]).default("solid"),
|
|
1063
|
-
|
|
1069
|
+
/** @deprecated Use `style` instead. */
|
|
1070
|
+
strokeStyle: z2.enum(["solid", "dashed", "dotted"]).optional(),
|
|
1064
1071
|
arrow: z2.enum(["end", "start", "both", "none"]).default("end"),
|
|
1065
1072
|
label: z2.string().min(1).max(200).optional(),
|
|
1066
1073
|
labelPosition: z2.enum(["start", "middle", "end"]).default("middle"),
|
|
@@ -1072,7 +1079,8 @@ var connectionElementSchema = z2.object({
|
|
|
1072
1079
|
arrowSize: z2.number().min(4).max(32).optional(),
|
|
1073
1080
|
arrowPlacement: z2.enum(["endpoint", "boundary"]).default("endpoint"),
|
|
1074
1081
|
opacity: z2.number().min(0).max(1).default(1),
|
|
1075
|
-
routing: z2.enum(["auto", "orthogonal", "curve", "arc"]).default("auto"),
|
|
1082
|
+
routing: z2.enum(["auto", "orthogonal", "curve", "arc", "straight"]).default("auto"),
|
|
1083
|
+
curveMode: z2.enum(["normal", "ellipse"]).default("normal"),
|
|
1076
1084
|
tension: z2.number().min(0.1).max(0.8).default(0.35),
|
|
1077
1085
|
fromAnchor: anchorHintSchema.optional(),
|
|
1078
1086
|
toAnchor: anchorHintSchema.optional()
|
|
@@ -1165,7 +1173,11 @@ var autoLayoutConfigSchema = z2.object({
|
|
|
1165
1173
|
/** Sort strategy for radial layout node ordering. Only relevant when algorithm is 'radial'. */
|
|
1166
1174
|
radialSortBy: z2.enum(["id", "connections"]).optional(),
|
|
1167
1175
|
/** Explicit center used by curve/arc connection routing. */
|
|
1168
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
1176
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
1177
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1178
|
+
ellipseRx: z2.number().positive().optional(),
|
|
1179
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1180
|
+
ellipseRy: z2.number().positive().optional()
|
|
1169
1181
|
}).strict();
|
|
1170
1182
|
var gridLayoutConfigSchema = z2.object({
|
|
1171
1183
|
mode: z2.literal("grid"),
|
|
@@ -1175,7 +1187,11 @@ var gridLayoutConfigSchema = z2.object({
|
|
|
1175
1187
|
cardMaxHeight: z2.number().int().min(32).max(4096).optional(),
|
|
1176
1188
|
equalHeight: z2.boolean().default(false),
|
|
1177
1189
|
/** Explicit center used by curve/arc connection routing. */
|
|
1178
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
1190
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
1191
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1192
|
+
ellipseRx: z2.number().positive().optional(),
|
|
1193
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1194
|
+
ellipseRy: z2.number().positive().optional()
|
|
1179
1195
|
}).strict();
|
|
1180
1196
|
var stackLayoutConfigSchema = z2.object({
|
|
1181
1197
|
mode: z2.literal("stack"),
|
|
@@ -1183,7 +1199,25 @@ var stackLayoutConfigSchema = z2.object({
|
|
|
1183
1199
|
gap: z2.number().int().min(0).max(256).default(24),
|
|
1184
1200
|
alignment: z2.enum(["start", "center", "end", "stretch"]).default("stretch"),
|
|
1185
1201
|
/** Explicit center used by curve/arc connection routing. */
|
|
1186
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
1202
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
1203
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1204
|
+
ellipseRx: z2.number().positive().optional(),
|
|
1205
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1206
|
+
ellipseRy: z2.number().positive().optional()
|
|
1207
|
+
}).strict();
|
|
1208
|
+
var ellipseLayoutConfigSchema = z2.object({
|
|
1209
|
+
mode: z2.literal("ellipse"),
|
|
1210
|
+
cx: z2.number().optional(),
|
|
1211
|
+
cy: z2.number().optional(),
|
|
1212
|
+
rx: z2.number().positive(),
|
|
1213
|
+
ry: z2.number().positive(),
|
|
1214
|
+
startAngle: z2.number().default(-90),
|
|
1215
|
+
/** Explicit center used by curve/arc connection routing. */
|
|
1216
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
1217
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1218
|
+
ellipseRx: z2.number().positive().optional(),
|
|
1219
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1220
|
+
ellipseRy: z2.number().positive().optional()
|
|
1187
1221
|
}).strict();
|
|
1188
1222
|
var manualPositionSchema = z2.object({
|
|
1189
1223
|
x: z2.number().int(),
|
|
@@ -1195,12 +1229,17 @@ var manualLayoutConfigSchema = z2.object({
|
|
|
1195
1229
|
mode: z2.literal("manual"),
|
|
1196
1230
|
positions: z2.record(z2.string().min(1), manualPositionSchema).default({}),
|
|
1197
1231
|
/** Explicit center used by curve/arc connection routing. */
|
|
1198
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
1232
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
1233
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1234
|
+
ellipseRx: z2.number().positive().optional(),
|
|
1235
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1236
|
+
ellipseRy: z2.number().positive().optional()
|
|
1199
1237
|
}).strict();
|
|
1200
1238
|
var layoutConfigSchema = z2.discriminatedUnion("mode", [
|
|
1201
1239
|
autoLayoutConfigSchema,
|
|
1202
1240
|
gridLayoutConfigSchema,
|
|
1203
1241
|
stackLayoutConfigSchema,
|
|
1242
|
+
ellipseLayoutConfigSchema,
|
|
1204
1243
|
manualLayoutConfigSchema
|
|
1205
1244
|
]);
|
|
1206
1245
|
var constraintsSchema = z2.object({
|
|
@@ -1260,7 +1299,11 @@ var diagramElementSchema = z2.discriminatedUnion("type", [
|
|
|
1260
1299
|
var diagramLayoutSchema = z2.object({
|
|
1261
1300
|
mode: z2.enum(["manual", "auto"]).default("manual"),
|
|
1262
1301
|
positions: z2.record(z2.string(), diagramPositionSchema).optional(),
|
|
1263
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
1302
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
1303
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1304
|
+
ellipseRx: z2.number().positive().optional(),
|
|
1305
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
1306
|
+
ellipseRy: z2.number().positive().optional()
|
|
1264
1307
|
}).strict();
|
|
1265
1308
|
var diagramSpecSchema = z2.object({
|
|
1266
1309
|
version: z2.literal(1),
|
|
@@ -2430,6 +2473,35 @@ async function computeElkLayout(elements, config, safeFrame) {
|
|
|
2430
2473
|
};
|
|
2431
2474
|
}
|
|
2432
2475
|
|
|
2476
|
+
// src/layout/ellipse.ts
|
|
2477
|
+
function clampDimension(estimated, max) {
|
|
2478
|
+
return Math.max(1, Math.min(max, Math.floor(estimated)));
|
|
2479
|
+
}
|
|
2480
|
+
function computeEllipseLayout(elements, config, safeFrame) {
|
|
2481
|
+
const placeable = elements.filter((element) => element.type !== "connection");
|
|
2482
|
+
const positions = /* @__PURE__ */ new Map();
|
|
2483
|
+
if (placeable.length === 0) {
|
|
2484
|
+
return { positions };
|
|
2485
|
+
}
|
|
2486
|
+
const cx = config.cx ?? safeFrame.x + safeFrame.width / 2;
|
|
2487
|
+
const cy = config.cy ?? safeFrame.y + safeFrame.height / 2;
|
|
2488
|
+
const stepDegrees = 360 / placeable.length;
|
|
2489
|
+
for (const [index, element] of placeable.entries()) {
|
|
2490
|
+
const angleRadians = (config.startAngle + index * stepDegrees) * Math.PI / 180;
|
|
2491
|
+
const centerX = cx + config.rx * Math.cos(angleRadians);
|
|
2492
|
+
const centerY = cy + config.ry * Math.sin(angleRadians);
|
|
2493
|
+
const width = clampDimension(estimateElementWidth(element), safeFrame.width);
|
|
2494
|
+
const height = clampDimension(estimateElementHeight(element), safeFrame.height);
|
|
2495
|
+
positions.set(element.id, {
|
|
2496
|
+
x: Math.round(centerX - width / 2),
|
|
2497
|
+
y: Math.round(centerY - height / 2),
|
|
2498
|
+
width,
|
|
2499
|
+
height
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
return { positions };
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2433
2505
|
// src/layout/grid.ts
|
|
2434
2506
|
function computeGridLayout(elements, config, safeFrame) {
|
|
2435
2507
|
const placeable = elements.filter((element) => element.type !== "connection");
|
|
@@ -2525,6 +2597,8 @@ async function computeLayout(elements, layout, safeFrame) {
|
|
|
2525
2597
|
return computeGridLayout(elements, layout, safeFrame);
|
|
2526
2598
|
case "stack":
|
|
2527
2599
|
return computeStackLayout(elements, layout, safeFrame);
|
|
2600
|
+
case "ellipse":
|
|
2601
|
+
return computeEllipseLayout(elements, layout, safeFrame);
|
|
2528
2602
|
case "manual":
|
|
2529
2603
|
return computeManualLayout(elements, layout, safeFrame);
|
|
2530
2604
|
default:
|
|
@@ -3338,6 +3412,72 @@ function arcRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, toAn
|
|
|
3338
3412
|
[pMid, cp3, cp4, p3]
|
|
3339
3413
|
];
|
|
3340
3414
|
}
|
|
3415
|
+
function inferEllipseParams(nodeBounds, explicitCenter, explicitRx, explicitRy) {
|
|
3416
|
+
if (nodeBounds.length === 0) {
|
|
3417
|
+
return {
|
|
3418
|
+
cx: explicitCenter?.x ?? 0,
|
|
3419
|
+
cy: explicitCenter?.y ?? 0,
|
|
3420
|
+
rx: explicitRx ?? 1,
|
|
3421
|
+
ry: explicitRy ?? 1
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3424
|
+
const centers = nodeBounds.map(rectCenter);
|
|
3425
|
+
const cx = explicitCenter?.x ?? centers.reduce((sum, c) => sum + c.x, 0) / centers.length;
|
|
3426
|
+
const cy = explicitCenter?.y ?? centers.reduce((sum, c) => sum + c.y, 0) / centers.length;
|
|
3427
|
+
const rx = explicitRx ?? Math.max(1, ...centers.map((c) => Math.abs(c.x - cx)));
|
|
3428
|
+
const ry = explicitRy ?? Math.max(1, ...centers.map((c) => Math.abs(c.y - cy)));
|
|
3429
|
+
return { cx, cy, rx, ry };
|
|
3430
|
+
}
|
|
3431
|
+
function ellipseRoute(fromBounds, toBounds, ellipse, fromAnchor, toAnchor) {
|
|
3432
|
+
const fromCenter = rectCenter(fromBounds);
|
|
3433
|
+
const toCenter = rectCenter(toBounds);
|
|
3434
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
3435
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
3436
|
+
const theta1 = Math.atan2(
|
|
3437
|
+
(fromCenter.y - ellipse.cy) / ellipse.ry,
|
|
3438
|
+
(fromCenter.x - ellipse.cx) / ellipse.rx
|
|
3439
|
+
);
|
|
3440
|
+
const theta2 = Math.atan2(
|
|
3441
|
+
(toCenter.y - ellipse.cy) / ellipse.ry,
|
|
3442
|
+
(toCenter.x - ellipse.cx) / ellipse.rx
|
|
3443
|
+
);
|
|
3444
|
+
let angularSpan = theta2 - theta1;
|
|
3445
|
+
while (angularSpan > Math.PI) angularSpan -= 2 * Math.PI;
|
|
3446
|
+
while (angularSpan <= -Math.PI) angularSpan += 2 * Math.PI;
|
|
3447
|
+
const absSpan = Math.abs(angularSpan);
|
|
3448
|
+
const kappa = absSpan < 1e-6 ? 0 : 4 / 3 * Math.tan(absSpan / 4);
|
|
3449
|
+
const tangent1 = {
|
|
3450
|
+
x: -ellipse.rx * Math.sin(theta1),
|
|
3451
|
+
y: ellipse.ry * Math.cos(theta1)
|
|
3452
|
+
};
|
|
3453
|
+
const tangent2 = {
|
|
3454
|
+
x: -ellipse.rx * Math.sin(theta2),
|
|
3455
|
+
y: ellipse.ry * Math.cos(theta2)
|
|
3456
|
+
};
|
|
3457
|
+
const len1 = Math.hypot(tangent1.x, tangent1.y) || 1;
|
|
3458
|
+
const len2 = Math.hypot(tangent2.x, tangent2.y) || 1;
|
|
3459
|
+
const norm1 = { x: tangent1.x / len1, y: tangent1.y / len1 };
|
|
3460
|
+
const norm2 = { x: tangent2.x / len2, y: tangent2.y / len2 };
|
|
3461
|
+
const chordLength = Math.hypot(p3.x - p0.x, p3.y - p0.y);
|
|
3462
|
+
const cpDistance = chordLength * kappa * 0.5;
|
|
3463
|
+
const sign = angularSpan >= 0 ? 1 : -1;
|
|
3464
|
+
const cp1 = {
|
|
3465
|
+
x: p0.x + norm1.x * cpDistance * sign,
|
|
3466
|
+
y: p0.y + norm1.y * cpDistance * sign
|
|
3467
|
+
};
|
|
3468
|
+
const cp2 = {
|
|
3469
|
+
x: p3.x - norm2.x * cpDistance * sign,
|
|
3470
|
+
y: p3.y - norm2.y * cpDistance * sign
|
|
3471
|
+
};
|
|
3472
|
+
return [p0, cp1, cp2, p3];
|
|
3473
|
+
}
|
|
3474
|
+
function straightRoute(fromBounds, toBounds, fromAnchor, toAnchor) {
|
|
3475
|
+
const fromC = rectCenter(fromBounds);
|
|
3476
|
+
const toC = rectCenter(toBounds);
|
|
3477
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toC);
|
|
3478
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromC);
|
|
3479
|
+
return [p0, p3];
|
|
3480
|
+
}
|
|
3341
3481
|
function orthogonalRoute(fromBounds, toBounds, fromAnchor, toAnchor) {
|
|
3342
3482
|
const fromC = rectCenter(fromBounds);
|
|
3343
3483
|
const toC = rectCenter(toBounds);
|
|
@@ -3382,15 +3522,6 @@ function findBoundaryIntersection(p0, cp1, cp2, p3, targetRect, searchFromEnd) {
|
|
|
3382
3522
|
}
|
|
3383
3523
|
return void 0;
|
|
3384
3524
|
}
|
|
3385
|
-
function pointAlongArc(route, t) {
|
|
3386
|
-
const [first, second] = route;
|
|
3387
|
-
if (t <= 0.5) {
|
|
3388
|
-
const localT2 = Math.max(0, Math.min(1, t * 2));
|
|
3389
|
-
return bezierPointAt(first[0], first[1], first[2], first[3], localT2);
|
|
3390
|
-
}
|
|
3391
|
-
const localT = Math.max(0, Math.min(1, (t - 0.5) * 2));
|
|
3392
|
-
return bezierPointAt(second[0], second[1], second[2], second[3], localT);
|
|
3393
|
-
}
|
|
3394
3525
|
function computeDiagramCenter(nodeBounds, canvasCenter) {
|
|
3395
3526
|
if (nodeBounds.length === 0) {
|
|
3396
3527
|
return canvasCenter ?? { x: 0, y: 0 };
|
|
@@ -3513,8 +3644,19 @@ function polylineBounds(points) {
|
|
|
3513
3644
|
};
|
|
3514
3645
|
}
|
|
3515
3646
|
function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, options) {
|
|
3516
|
-
|
|
3517
|
-
|
|
3647
|
+
let routing = conn.routing ?? "auto";
|
|
3648
|
+
let curveMode = conn.curveMode ?? "normal";
|
|
3649
|
+
if (conn.strokeStyle !== void 0) {
|
|
3650
|
+
console.warn("connection.strokeStyle is deprecated, use style instead");
|
|
3651
|
+
}
|
|
3652
|
+
if (routing === "arc") {
|
|
3653
|
+
console.warn(
|
|
3654
|
+
"connection routing: 'arc' is deprecated. Use routing: 'curve' with curveMode: 'ellipse' instead."
|
|
3655
|
+
);
|
|
3656
|
+
routing = "curve";
|
|
3657
|
+
curveMode = "ellipse";
|
|
3658
|
+
}
|
|
3659
|
+
const strokeStyle = conn.style ?? conn.strokeStyle ?? "solid";
|
|
3518
3660
|
const strokeWidth = conn.width ?? conn.strokeWidth ?? 2;
|
|
3519
3661
|
const tension = conn.tension ?? 0.35;
|
|
3520
3662
|
const dash = dashFromStyle(strokeStyle);
|
|
@@ -3536,14 +3678,29 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3536
3678
|
ctx.globalAlpha = conn.opacity;
|
|
3537
3679
|
const arrowPlacement = conn.arrowPlacement ?? "endpoint";
|
|
3538
3680
|
if (routing === "curve") {
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3681
|
+
let p0;
|
|
3682
|
+
let cp1;
|
|
3683
|
+
let cp2;
|
|
3684
|
+
let p3;
|
|
3685
|
+
if (curveMode === "ellipse") {
|
|
3686
|
+
const ellipse = options?.ellipseParams ?? inferEllipseParams([fromBounds, toBounds]);
|
|
3687
|
+
[p0, cp1, cp2, p3] = ellipseRoute(
|
|
3688
|
+
fromBounds,
|
|
3689
|
+
toBounds,
|
|
3690
|
+
ellipse,
|
|
3691
|
+
conn.fromAnchor,
|
|
3692
|
+
conn.toAnchor
|
|
3693
|
+
);
|
|
3694
|
+
} else {
|
|
3695
|
+
[p0, cp1, cp2, p3] = curveRoute(
|
|
3696
|
+
fromBounds,
|
|
3697
|
+
toBounds,
|
|
3698
|
+
diagramCenter,
|
|
3699
|
+
tension,
|
|
3700
|
+
conn.fromAnchor,
|
|
3701
|
+
conn.toAnchor
|
|
3702
|
+
);
|
|
3703
|
+
}
|
|
3547
3704
|
const stroke = resolveConnectionStroke(ctx, p0, p3, conn.fromColor, style.color, conn.toColor);
|
|
3548
3705
|
ctx.strokeStyle = stroke;
|
|
3549
3706
|
ctx.lineWidth = style.width;
|
|
@@ -3576,51 +3733,22 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3576
3733
|
}
|
|
3577
3734
|
}
|
|
3578
3735
|
}
|
|
3579
|
-
} else if (routing === "
|
|
3580
|
-
const [
|
|
3581
|
-
fromBounds,
|
|
3582
|
-
toBounds,
|
|
3583
|
-
diagramCenter,
|
|
3584
|
-
tension,
|
|
3585
|
-
conn.fromAnchor,
|
|
3586
|
-
conn.toAnchor
|
|
3587
|
-
);
|
|
3588
|
-
const [p0, cp1, cp2, pMid] = first;
|
|
3589
|
-
const [, cp3, cp4, p3] = second;
|
|
3736
|
+
} else if (routing === "straight") {
|
|
3737
|
+
const [p0, p3] = straightRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor);
|
|
3590
3738
|
const stroke = resolveConnectionStroke(ctx, p0, p3, conn.fromColor, style.color, conn.toColor);
|
|
3591
3739
|
ctx.strokeStyle = stroke;
|
|
3592
3740
|
ctx.lineWidth = style.width;
|
|
3593
3741
|
ctx.setLineDash(style.dash ?? []);
|
|
3594
3742
|
ctx.beginPath();
|
|
3595
3743
|
ctx.moveTo(p0.x, p0.y);
|
|
3596
|
-
ctx.
|
|
3597
|
-
ctx.bezierCurveTo(cp3.x, cp3.y, cp4.x, cp4.y, p3.x, p3.y);
|
|
3744
|
+
ctx.lineTo(p3.x, p3.y);
|
|
3598
3745
|
ctx.stroke();
|
|
3599
|
-
linePoints = [p0,
|
|
3746
|
+
linePoints = [p0, p3];
|
|
3600
3747
|
startPoint = p0;
|
|
3601
3748
|
endPoint = p3;
|
|
3602
|
-
startAngle = Math.atan2(p0.y -
|
|
3603
|
-
endAngle = Math.atan2(p3.y -
|
|
3604
|
-
labelPoint =
|
|
3605
|
-
if (arrowPlacement === "boundary") {
|
|
3606
|
-
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
3607
|
-
const [, s_cp3, s_cp4, s_p3] = second;
|
|
3608
|
-
const tEnd = findBoundaryIntersection(pMid, s_cp3, s_cp4, s_p3, toBounds, true);
|
|
3609
|
-
if (tEnd !== void 0) {
|
|
3610
|
-
endPoint = bezierPointAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3611
|
-
const tangent = bezierTangentAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3612
|
-
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
3613
|
-
}
|
|
3614
|
-
}
|
|
3615
|
-
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
3616
|
-
const tStart = findBoundaryIntersection(p0, cp1, cp2, pMid, fromBounds, false);
|
|
3617
|
-
if (tStart !== void 0) {
|
|
3618
|
-
startPoint = bezierPointAt(p0, cp1, cp2, pMid, tStart);
|
|
3619
|
-
const tangent = bezierTangentAt(p0, cp1, cp2, pMid, tStart);
|
|
3620
|
-
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
3621
|
-
}
|
|
3622
|
-
}
|
|
3623
|
-
}
|
|
3749
|
+
startAngle = Math.atan2(p0.y - p3.y, p0.x - p3.x);
|
|
3750
|
+
endAngle = Math.atan2(p3.y - p0.y, p3.x - p0.x);
|
|
3751
|
+
labelPoint = pointAlongPolyline(linePoints, labelT);
|
|
3624
3752
|
} else {
|
|
3625
3753
|
const hasAnchorHints = conn.fromAnchor !== void 0 || conn.toAnchor !== void 0;
|
|
3626
3754
|
const useElkRoute = routing === "auto" && !hasAnchorHints && (edgeRoute?.points.length ?? 0) >= 2;
|
|
@@ -3886,6 +4014,24 @@ function fromPoints(points) {
|
|
|
3886
4014
|
function resolveDrawFont(theme, family) {
|
|
3887
4015
|
return resolveFont(theme.fonts[family], family);
|
|
3888
4016
|
}
|
|
4017
|
+
function createDrawStrokeGradient(ctx, start, end, strokeGradient) {
|
|
4018
|
+
const gradient = ctx.createLinearGradient(start.x, start.y, end.x, end.y);
|
|
4019
|
+
gradient.addColorStop(0, strokeGradient.from);
|
|
4020
|
+
gradient.addColorStop(1, strokeGradient.to);
|
|
4021
|
+
return gradient;
|
|
4022
|
+
}
|
|
4023
|
+
function resolveDrawStroke(ctx, start, end, color, strokeGradient) {
|
|
4024
|
+
if (!strokeGradient) {
|
|
4025
|
+
return color;
|
|
4026
|
+
}
|
|
4027
|
+
return createDrawStrokeGradient(ctx, start, end, strokeGradient);
|
|
4028
|
+
}
|
|
4029
|
+
function resolveArrowFill(color, strokeGradient, position) {
|
|
4030
|
+
if (!strokeGradient) {
|
|
4031
|
+
return color;
|
|
4032
|
+
}
|
|
4033
|
+
return position === "start" ? strokeGradient.from : strokeGradient.to;
|
|
4034
|
+
}
|
|
3889
4035
|
function measureSpacedTextWidth(ctx, text, letterSpacing) {
|
|
3890
4036
|
const chars = [...text];
|
|
3891
4037
|
if (chars.length === 0) {
|
|
@@ -4164,18 +4310,31 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4164
4310
|
const from = { x: command.x1, y: command.y1 };
|
|
4165
4311
|
const to = { x: command.x2, y: command.y2 };
|
|
4166
4312
|
const lineAngle = angleBetween(from, to);
|
|
4313
|
+
const stroke = resolveDrawStroke(ctx, from, to, command.color, command.strokeGradient);
|
|
4167
4314
|
withOpacity(ctx, command.opacity, () => {
|
|
4168
4315
|
applyDrawShadow(ctx, command.shadow);
|
|
4169
4316
|
drawLine(ctx, from, to, {
|
|
4170
|
-
color:
|
|
4317
|
+
color: stroke,
|
|
4171
4318
|
width: command.width,
|
|
4172
4319
|
...command.dash ? { dash: command.dash } : {}
|
|
4173
4320
|
});
|
|
4174
4321
|
if (command.arrow === "end" || command.arrow === "both") {
|
|
4175
|
-
drawArrowhead(
|
|
4322
|
+
drawArrowhead(
|
|
4323
|
+
ctx,
|
|
4324
|
+
to,
|
|
4325
|
+
lineAngle,
|
|
4326
|
+
command.arrowSize,
|
|
4327
|
+
resolveArrowFill(command.color, command.strokeGradient, "end")
|
|
4328
|
+
);
|
|
4176
4329
|
}
|
|
4177
4330
|
if (command.arrow === "start" || command.arrow === "both") {
|
|
4178
|
-
drawArrowhead(
|
|
4331
|
+
drawArrowhead(
|
|
4332
|
+
ctx,
|
|
4333
|
+
from,
|
|
4334
|
+
lineAngle + Math.PI,
|
|
4335
|
+
command.arrowSize,
|
|
4336
|
+
resolveArrowFill(command.color, command.strokeGradient, "start")
|
|
4337
|
+
);
|
|
4179
4338
|
}
|
|
4180
4339
|
});
|
|
4181
4340
|
const arrowPadding = command.arrow === "none" ? 0 : command.arrowSize;
|
|
@@ -4183,7 +4342,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4183
4342
|
id,
|
|
4184
4343
|
kind: "draw",
|
|
4185
4344
|
bounds: expandRect(fromPoints([from, to]), Math.max(command.width / 2, arrowPadding)),
|
|
4186
|
-
foregroundColor: command.color
|
|
4345
|
+
foregroundColor: command.strokeGradient?.from ?? command.color
|
|
4187
4346
|
});
|
|
4188
4347
|
break;
|
|
4189
4348
|
}
|
|
@@ -4217,10 +4376,17 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4217
4376
|
}
|
|
4218
4377
|
case "bezier": {
|
|
4219
4378
|
const points = command.points;
|
|
4379
|
+
const stroke = resolveDrawStroke(
|
|
4380
|
+
ctx,
|
|
4381
|
+
points[0],
|
|
4382
|
+
points[points.length - 1],
|
|
4383
|
+
command.color,
|
|
4384
|
+
command.strokeGradient
|
|
4385
|
+
);
|
|
4220
4386
|
withOpacity(ctx, command.opacity, () => {
|
|
4221
4387
|
applyDrawShadow(ctx, command.shadow);
|
|
4222
4388
|
drawBezier(ctx, points, {
|
|
4223
|
-
color:
|
|
4389
|
+
color: stroke,
|
|
4224
4390
|
width: command.width,
|
|
4225
4391
|
...command.dash ? { dash: command.dash } : {}
|
|
4226
4392
|
});
|
|
@@ -4232,11 +4398,17 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4232
4398
|
points[points.length - 1],
|
|
4233
4399
|
endAngle,
|
|
4234
4400
|
command.arrowSize,
|
|
4235
|
-
command.color
|
|
4401
|
+
resolveArrowFill(command.color, command.strokeGradient, "end")
|
|
4236
4402
|
);
|
|
4237
4403
|
}
|
|
4238
4404
|
if (command.arrow === "start" || command.arrow === "both") {
|
|
4239
|
-
drawArrowhead(
|
|
4405
|
+
drawArrowhead(
|
|
4406
|
+
ctx,
|
|
4407
|
+
points[0],
|
|
4408
|
+
startAngle + Math.PI,
|
|
4409
|
+
command.arrowSize,
|
|
4410
|
+
resolveArrowFill(command.color, command.strokeGradient, "start")
|
|
4411
|
+
);
|
|
4240
4412
|
}
|
|
4241
4413
|
});
|
|
4242
4414
|
const arrowPadding = command.arrow === "none" ? 0 : command.arrowSize;
|
|
@@ -4244,7 +4416,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4244
4416
|
id,
|
|
4245
4417
|
kind: "draw",
|
|
4246
4418
|
bounds: expandRect(fromPoints(points), Math.max(command.width / 2, arrowPadding)),
|
|
4247
|
-
foregroundColor: command.color
|
|
4419
|
+
foregroundColor: command.strokeGradient?.from ?? command.color
|
|
4248
4420
|
});
|
|
4249
4421
|
break;
|
|
4250
4422
|
}
|
|
@@ -5049,10 +5221,19 @@ async function renderDesign(input, options = {}) {
|
|
|
5049
5221
|
break;
|
|
5050
5222
|
}
|
|
5051
5223
|
}
|
|
5052
|
-
const
|
|
5053
|
-
|
|
5054
|
-
|
|
5224
|
+
const nodeBounds = spec.elements.filter((element) => element.type !== "connection").map((element) => elementRects.get(element.id)).filter((rect) => rect != null);
|
|
5225
|
+
const diagramCenter = spec.layout.diagramCenter ?? computeDiagramCenter(nodeBounds, { x: spec.canvas.width / 2, y: spec.canvas.height / 2 });
|
|
5226
|
+
const layoutEllipseRx = "ellipseRx" in spec.layout ? spec.layout.ellipseRx : void 0;
|
|
5227
|
+
const layoutEllipseRy = "ellipseRy" in spec.layout ? spec.layout.ellipseRy : void 0;
|
|
5228
|
+
const hasEllipseConnections = spec.elements.some(
|
|
5229
|
+
(el) => el.type === "connection" && (el.curveMode === "ellipse" || el.routing === "arc")
|
|
5055
5230
|
);
|
|
5231
|
+
const ellipseParams = hasEllipseConnections ? inferEllipseParams(
|
|
5232
|
+
nodeBounds,
|
|
5233
|
+
spec.layout.diagramCenter ?? diagramCenter,
|
|
5234
|
+
layoutEllipseRx,
|
|
5235
|
+
layoutEllipseRy
|
|
5236
|
+
) : void 0;
|
|
5056
5237
|
for (const element of spec.elements) {
|
|
5057
5238
|
if (element.type !== "connection") {
|
|
5058
5239
|
continue;
|
|
@@ -5066,7 +5247,15 @@ async function renderDesign(input, options = {}) {
|
|
|
5066
5247
|
}
|
|
5067
5248
|
const edgeRoute = edgeRoutes?.get(`${element.from}-${element.to}`);
|
|
5068
5249
|
elements.push(
|
|
5069
|
-
...renderConnection(
|
|
5250
|
+
...renderConnection(
|
|
5251
|
+
ctx,
|
|
5252
|
+
element,
|
|
5253
|
+
fromRect,
|
|
5254
|
+
toRect,
|
|
5255
|
+
theme,
|
|
5256
|
+
edgeRoute,
|
|
5257
|
+
ellipseParams ? { diagramCenter, ellipseParams } : { diagramCenter }
|
|
5258
|
+
)
|
|
5070
5259
|
);
|
|
5071
5260
|
}
|
|
5072
5261
|
if (footerRect && spec.footer) {
|
|
@@ -6128,8 +6317,10 @@ export {
|
|
|
6128
6317
|
drawRainbowRule,
|
|
6129
6318
|
drawVignette,
|
|
6130
6319
|
edgeAnchor,
|
|
6320
|
+
ellipseRoute,
|
|
6131
6321
|
flowNodeElementSchema,
|
|
6132
6322
|
highlightCode,
|
|
6323
|
+
inferEllipseParams,
|
|
6133
6324
|
inferLayout,
|
|
6134
6325
|
inferSidecarPath,
|
|
6135
6326
|
initHighlighter,
|
|
@@ -6148,6 +6339,7 @@ export {
|
|
|
6148
6339
|
resolveShikiTheme,
|
|
6149
6340
|
resolveTheme,
|
|
6150
6341
|
runQa,
|
|
6342
|
+
straightRoute,
|
|
6151
6343
|
themeToShikiMap,
|
|
6152
6344
|
writeRenderArtifacts
|
|
6153
6345
|
};
|
package/dist/qa.d.ts
CHANGED