@spectratools/graphic-designer-cli 0.6.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/dist/cli.js +189 -17
- package/dist/index.d.ts +15 -5
- package/dist/index.js +189 -17
- package/dist/qa.d.ts +1 -1
- package/dist/qa.js +22 -2
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.js +189 -17
- package/dist/{spec.schema-Dm_wOLTd.d.ts → spec.schema-BeFz_nk1.d.ts} +387 -21
- package/dist/spec.schema.d.ts +1 -1
- package/dist/spec.schema.js +22 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -852,6 +852,15 @@ var drawGradientRectSchema = z2.object({
|
|
|
852
852
|
radius: z2.number().min(0).max(256).default(0),
|
|
853
853
|
opacity: z2.number().min(0).max(1).default(1)
|
|
854
854
|
}).strict();
|
|
855
|
+
var drawGridSchema = z2.object({
|
|
856
|
+
type: z2.literal("grid"),
|
|
857
|
+
spacing: z2.number().min(5).max(200).default(40),
|
|
858
|
+
color: colorHexSchema2.default("#1E2D4A"),
|
|
859
|
+
width: z2.number().min(0.1).max(4).default(0.5),
|
|
860
|
+
opacity: z2.number().min(0).max(1).default(0.2),
|
|
861
|
+
offsetX: z2.number().default(0),
|
|
862
|
+
offsetY: z2.number().default(0)
|
|
863
|
+
}).strict();
|
|
855
864
|
var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
856
865
|
drawRectSchema,
|
|
857
866
|
drawCircleSchema,
|
|
@@ -860,7 +869,8 @@ var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
|
860
869
|
drawBezierSchema,
|
|
861
870
|
drawPathSchema,
|
|
862
871
|
drawBadgeSchema,
|
|
863
|
-
drawGradientRectSchema
|
|
872
|
+
drawGradientRectSchema,
|
|
873
|
+
drawGridSchema
|
|
864
874
|
]);
|
|
865
875
|
var defaultCanvas = {
|
|
866
876
|
width: 1200,
|
|
@@ -966,6 +976,13 @@ var flowNodeElementSchema = z2.object({
|
|
|
966
976
|
badgePosition: z2.enum(["top", "inside-top"]).default("inside-top"),
|
|
967
977
|
shadow: flowNodeShadowSchema.optional()
|
|
968
978
|
}).strict();
|
|
979
|
+
var anchorHintSchema = z2.union([
|
|
980
|
+
z2.enum(["top", "bottom", "left", "right", "center"]),
|
|
981
|
+
z2.object({
|
|
982
|
+
x: z2.number().min(-1).max(1),
|
|
983
|
+
y: z2.number().min(-1).max(1)
|
|
984
|
+
}).strict()
|
|
985
|
+
]);
|
|
969
986
|
var connectionElementSchema = z2.object({
|
|
970
987
|
type: z2.literal("connection"),
|
|
971
988
|
from: z2.string().min(1).max(120),
|
|
@@ -979,9 +996,12 @@ var connectionElementSchema = z2.object({
|
|
|
979
996
|
width: z2.number().min(0.5).max(10).optional(),
|
|
980
997
|
strokeWidth: z2.number().min(0.5).max(10).default(2),
|
|
981
998
|
arrowSize: z2.number().min(4).max(32).optional(),
|
|
999
|
+
arrowPlacement: z2.enum(["endpoint", "boundary"]).default("endpoint"),
|
|
982
1000
|
opacity: z2.number().min(0).max(1).default(1),
|
|
983
1001
|
routing: z2.enum(["auto", "orthogonal", "curve", "arc"]).default("auto"),
|
|
984
|
-
tension: z2.number().min(0.1).max(0.8).default(0.35)
|
|
1002
|
+
tension: z2.number().min(0.1).max(0.8).default(0.35),
|
|
1003
|
+
fromAnchor: anchorHintSchema.optional(),
|
|
1004
|
+
toAnchor: anchorHintSchema.optional()
|
|
985
1005
|
}).strict();
|
|
986
1006
|
var codeBlockStyleSchema = z2.object({
|
|
987
1007
|
paddingVertical: z2.number().min(0).max(128).default(56),
|
|
@@ -3105,21 +3125,61 @@ function edgeAnchor(bounds, target) {
|
|
|
3105
3125
|
const t = absDx * hh > absDy * hw ? hw / absDx : hh / absDy;
|
|
3106
3126
|
return { x: c.x + dx * t, y: c.y + dy * t };
|
|
3107
3127
|
}
|
|
3128
|
+
function resolveAnchor(bounds, anchor, fallbackTarget) {
|
|
3129
|
+
if (!anchor) return edgeAnchor(bounds, fallbackTarget);
|
|
3130
|
+
if (typeof anchor === "string") {
|
|
3131
|
+
const c2 = rectCenter(bounds);
|
|
3132
|
+
switch (anchor) {
|
|
3133
|
+
case "top":
|
|
3134
|
+
return { x: c2.x, y: bounds.y };
|
|
3135
|
+
case "bottom":
|
|
3136
|
+
return { x: c2.x, y: bounds.y + bounds.height };
|
|
3137
|
+
case "left":
|
|
3138
|
+
return { x: bounds.x, y: c2.y };
|
|
3139
|
+
case "right":
|
|
3140
|
+
return { x: bounds.x + bounds.width, y: c2.y };
|
|
3141
|
+
case "center":
|
|
3142
|
+
return c2;
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
const c = rectCenter(bounds);
|
|
3146
|
+
return {
|
|
3147
|
+
x: c.x + anchor.x * (bounds.width / 2),
|
|
3148
|
+
y: c.y + anchor.y * (bounds.height / 2)
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
function anchorNormal(anchor, point, diagramCenter) {
|
|
3152
|
+
if (typeof anchor === "string") {
|
|
3153
|
+
switch (anchor) {
|
|
3154
|
+
case "top":
|
|
3155
|
+
return { x: 0, y: -1 };
|
|
3156
|
+
case "bottom":
|
|
3157
|
+
return { x: 0, y: 1 };
|
|
3158
|
+
case "left":
|
|
3159
|
+
return { x: -1, y: 0 };
|
|
3160
|
+
case "right":
|
|
3161
|
+
return { x: 1, y: 0 };
|
|
3162
|
+
case "center":
|
|
3163
|
+
return outwardNormal(point, diagramCenter);
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
return outwardNormal(point, diagramCenter);
|
|
3167
|
+
}
|
|
3108
3168
|
function outwardNormal(point, diagramCenter) {
|
|
3109
3169
|
const dx = point.x - diagramCenter.x;
|
|
3110
3170
|
const dy = point.y - diagramCenter.y;
|
|
3111
3171
|
const len = Math.hypot(dx, dy) || 1;
|
|
3112
3172
|
return { x: dx / len, y: dy / len };
|
|
3113
3173
|
}
|
|
3114
|
-
function curveRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
3174
|
+
function curveRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, toAnchor) {
|
|
3115
3175
|
const fromCenter = rectCenter(fromBounds);
|
|
3116
3176
|
const toCenter = rectCenter(toBounds);
|
|
3117
|
-
const p0 =
|
|
3118
|
-
const p3 =
|
|
3177
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
3178
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
3119
3179
|
const dist = Math.hypot(p3.x - p0.x, p3.y - p0.y);
|
|
3120
3180
|
const offset = dist * tension;
|
|
3121
|
-
const n0 =
|
|
3122
|
-
const n3 =
|
|
3181
|
+
const n0 = anchorNormal(fromAnchor, p0, diagramCenter);
|
|
3182
|
+
const n3 = anchorNormal(toAnchor, p3, diagramCenter);
|
|
3123
3183
|
const cp1 = { x: p0.x + n0.x * offset, y: p0.y + n0.y * offset };
|
|
3124
3184
|
const cp2 = { x: p3.x + n3.x * offset, y: p3.y + n3.y * offset };
|
|
3125
3185
|
return [p0, cp1, cp2, p3];
|
|
@@ -3133,11 +3193,11 @@ function localToWorld(origin, axisX, axisY, local) {
|
|
|
3133
3193
|
y: origin.y + axisX.y * local.x + axisY.y * local.y
|
|
3134
3194
|
};
|
|
3135
3195
|
}
|
|
3136
|
-
function arcRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
3196
|
+
function arcRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, toAnchor) {
|
|
3137
3197
|
const fromCenter = rectCenter(fromBounds);
|
|
3138
3198
|
const toCenter = rectCenter(toBounds);
|
|
3139
|
-
const start =
|
|
3140
|
-
const end =
|
|
3199
|
+
const start = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
3200
|
+
const end = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
3141
3201
|
const chord = { x: end.x - start.x, y: end.y - start.y };
|
|
3142
3202
|
const chordLength = Math.hypot(chord.x, chord.y);
|
|
3143
3203
|
if (chordLength < 1e-6) {
|
|
@@ -3175,11 +3235,11 @@ function arcRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
|
3175
3235
|
[pMid, cp3, cp4, p3]
|
|
3176
3236
|
];
|
|
3177
3237
|
}
|
|
3178
|
-
function orthogonalRoute(fromBounds, toBounds) {
|
|
3238
|
+
function orthogonalRoute(fromBounds, toBounds, fromAnchor, toAnchor) {
|
|
3179
3239
|
const fromC = rectCenter(fromBounds);
|
|
3180
3240
|
const toC = rectCenter(toBounds);
|
|
3181
|
-
const p0 =
|
|
3182
|
-
const p3 =
|
|
3241
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toC);
|
|
3242
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromC);
|
|
3183
3243
|
const midX = (p0.x + p3.x) / 2;
|
|
3184
3244
|
return [p0, { x: midX, y: p0.y }, { x: midX, y: p3.y }, p3];
|
|
3185
3245
|
}
|
|
@@ -3190,6 +3250,35 @@ function bezierPointAt(p0, cp1, cp2, p3, t) {
|
|
|
3190
3250
|
y: mt * mt * mt * p0.y + 3 * mt * mt * t * cp1.y + 3 * mt * t * t * cp2.y + t * t * t * p3.y
|
|
3191
3251
|
};
|
|
3192
3252
|
}
|
|
3253
|
+
function bezierTangentAt(p0, cp1, cp2, p3, t) {
|
|
3254
|
+
const mt = 1 - t;
|
|
3255
|
+
return {
|
|
3256
|
+
x: 3 * mt * mt * (cp1.x - p0.x) + 6 * mt * t * (cp2.x - cp1.x) + 3 * t * t * (p3.x - cp2.x),
|
|
3257
|
+
y: 3 * mt * mt * (cp1.y - p0.y) + 6 * mt * t * (cp2.y - cp1.y) + 3 * t * t * (p3.y - cp2.y)
|
|
3258
|
+
};
|
|
3259
|
+
}
|
|
3260
|
+
function isInsideRect(point, rect) {
|
|
3261
|
+
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
3262
|
+
}
|
|
3263
|
+
function findBoundaryIntersection(p0, cp1, cp2, p3, targetRect, searchFromEnd) {
|
|
3264
|
+
const step = 5e-3;
|
|
3265
|
+
if (searchFromEnd) {
|
|
3266
|
+
for (let t = 0.95; t >= 0.5; t -= step) {
|
|
3267
|
+
const pt = bezierPointAt(p0, cp1, cp2, p3, t);
|
|
3268
|
+
if (!isInsideRect(pt, targetRect)) {
|
|
3269
|
+
return t;
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
} else {
|
|
3273
|
+
for (let t = 0.05; t <= 0.5; t += step) {
|
|
3274
|
+
const pt = bezierPointAt(p0, cp1, cp2, p3, t);
|
|
3275
|
+
if (!isInsideRect(pt, targetRect)) {
|
|
3276
|
+
return t;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
return void 0;
|
|
3281
|
+
}
|
|
3193
3282
|
function pointAlongArc(route, t) {
|
|
3194
3283
|
const [first, second] = route;
|
|
3195
3284
|
if (t <= 0.5) {
|
|
@@ -3317,8 +3406,16 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3317
3406
|
let labelPoint;
|
|
3318
3407
|
ctx.save();
|
|
3319
3408
|
ctx.globalAlpha = conn.opacity;
|
|
3409
|
+
const arrowPlacement = conn.arrowPlacement ?? "endpoint";
|
|
3320
3410
|
if (routing === "curve") {
|
|
3321
|
-
const [p0, cp1, cp2, p3] = curveRoute(
|
|
3411
|
+
const [p0, cp1, cp2, p3] = curveRoute(
|
|
3412
|
+
fromBounds,
|
|
3413
|
+
toBounds,
|
|
3414
|
+
diagramCenter,
|
|
3415
|
+
tension,
|
|
3416
|
+
conn.fromAnchor,
|
|
3417
|
+
conn.toAnchor
|
|
3418
|
+
);
|
|
3322
3419
|
ctx.strokeStyle = style.color;
|
|
3323
3420
|
ctx.lineWidth = style.width;
|
|
3324
3421
|
ctx.setLineDash(style.dash ?? []);
|
|
@@ -3332,8 +3429,33 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3332
3429
|
startAngle = Math.atan2(p0.y - cp1.y, p0.x - cp1.x);
|
|
3333
3430
|
endAngle = Math.atan2(p3.y - cp2.y, p3.x - cp2.x);
|
|
3334
3431
|
labelPoint = bezierPointAt(p0, cp1, cp2, p3, labelT);
|
|
3432
|
+
if (arrowPlacement === "boundary") {
|
|
3433
|
+
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
3434
|
+
const tEnd = findBoundaryIntersection(p0, cp1, cp2, p3, toBounds, true);
|
|
3435
|
+
if (tEnd !== void 0) {
|
|
3436
|
+
endPoint = bezierPointAt(p0, cp1, cp2, p3, tEnd);
|
|
3437
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, p3, tEnd);
|
|
3438
|
+
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
3442
|
+
const tStart = findBoundaryIntersection(p0, cp1, cp2, p3, fromBounds, false);
|
|
3443
|
+
if (tStart !== void 0) {
|
|
3444
|
+
startPoint = bezierPointAt(p0, cp1, cp2, p3, tStart);
|
|
3445
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, p3, tStart);
|
|
3446
|
+
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3335
3450
|
} else if (routing === "arc") {
|
|
3336
|
-
const [first, second] = arcRoute(
|
|
3451
|
+
const [first, second] = arcRoute(
|
|
3452
|
+
fromBounds,
|
|
3453
|
+
toBounds,
|
|
3454
|
+
diagramCenter,
|
|
3455
|
+
tension,
|
|
3456
|
+
conn.fromAnchor,
|
|
3457
|
+
conn.toAnchor
|
|
3458
|
+
);
|
|
3337
3459
|
const [p0, cp1, cp2, pMid] = first;
|
|
3338
3460
|
const [, cp3, cp4, p3] = second;
|
|
3339
3461
|
ctx.strokeStyle = style.color;
|
|
@@ -3350,9 +3472,29 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3350
3472
|
startAngle = Math.atan2(p0.y - cp1.y, p0.x - cp1.x);
|
|
3351
3473
|
endAngle = Math.atan2(p3.y - cp4.y, p3.x - cp4.x);
|
|
3352
3474
|
labelPoint = pointAlongArc([first, second], labelT);
|
|
3475
|
+
if (arrowPlacement === "boundary") {
|
|
3476
|
+
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
3477
|
+
const [, s_cp3, s_cp4, s_p3] = second;
|
|
3478
|
+
const tEnd = findBoundaryIntersection(pMid, s_cp3, s_cp4, s_p3, toBounds, true);
|
|
3479
|
+
if (tEnd !== void 0) {
|
|
3480
|
+
endPoint = bezierPointAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3481
|
+
const tangent = bezierTangentAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3482
|
+
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
3486
|
+
const tStart = findBoundaryIntersection(p0, cp1, cp2, pMid, fromBounds, false);
|
|
3487
|
+
if (tStart !== void 0) {
|
|
3488
|
+
startPoint = bezierPointAt(p0, cp1, cp2, pMid, tStart);
|
|
3489
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, pMid, tStart);
|
|
3490
|
+
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3353
3494
|
} else {
|
|
3354
|
-
const
|
|
3355
|
-
|
|
3495
|
+
const hasAnchorHints = conn.fromAnchor !== void 0 || conn.toAnchor !== void 0;
|
|
3496
|
+
const useElkRoute = routing === "auto" && !hasAnchorHints && (edgeRoute?.points.length ?? 0) >= 2;
|
|
3497
|
+
linePoints = useElkRoute ? edgeRoute?.points ?? orthogonalRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor) : orthogonalRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor);
|
|
3356
3498
|
startPoint = linePoints[0];
|
|
3357
3499
|
const startSegment = linePoints[1] ?? linePoints[0];
|
|
3358
3500
|
const endStart = linePoints[linePoints.length - 2] ?? linePoints[0];
|
|
@@ -4009,6 +4151,36 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4009
4151
|
});
|
|
4010
4152
|
break;
|
|
4011
4153
|
}
|
|
4154
|
+
case "grid": {
|
|
4155
|
+
const canvasWidth = ctx.canvas.width;
|
|
4156
|
+
const canvasHeight = ctx.canvas.height;
|
|
4157
|
+
withOpacity(ctx, command.opacity, () => {
|
|
4158
|
+
ctx.strokeStyle = command.color;
|
|
4159
|
+
ctx.lineWidth = command.width;
|
|
4160
|
+
const startX = command.offsetX % command.spacing;
|
|
4161
|
+
for (let x = startX; x <= canvasWidth; x += command.spacing) {
|
|
4162
|
+
ctx.beginPath();
|
|
4163
|
+
ctx.moveTo(x, 0);
|
|
4164
|
+
ctx.lineTo(x, canvasHeight);
|
|
4165
|
+
ctx.stroke();
|
|
4166
|
+
}
|
|
4167
|
+
const startY = command.offsetY % command.spacing;
|
|
4168
|
+
for (let y = startY; y <= canvasHeight; y += command.spacing) {
|
|
4169
|
+
ctx.beginPath();
|
|
4170
|
+
ctx.moveTo(0, y);
|
|
4171
|
+
ctx.lineTo(canvasWidth, y);
|
|
4172
|
+
ctx.stroke();
|
|
4173
|
+
}
|
|
4174
|
+
});
|
|
4175
|
+
rendered.push({
|
|
4176
|
+
id,
|
|
4177
|
+
kind: "draw",
|
|
4178
|
+
bounds: { x: 0, y: 0, width: canvasWidth, height: canvasHeight },
|
|
4179
|
+
foregroundColor: command.color,
|
|
4180
|
+
allowOverlap: true
|
|
4181
|
+
});
|
|
4182
|
+
break;
|
|
4183
|
+
}
|
|
4012
4184
|
}
|
|
4013
4185
|
}
|
|
4014
4186
|
return rendered;
|
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, C as ConnectionElement } from './spec.schema-
|
|
3
|
-
export {
|
|
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-BeFz_nk1.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 DrawBadge, s as DrawBezier, t as DrawCircle, u as DrawFontFamily, v as DrawGradientRect, w as DrawLine, x as DrawPath, y as DrawPoint, z as DrawRect, E as DrawText, F as Element, G as FlowNodeElement, H as Gradient, I as GradientOverlayDecorator, J as GradientSpec, K as GradientStop, L as GridLayoutConfig, M as ImageElement, N as LayoutConfig, O as LayoutSnapshot, P as ManualLayoutConfig, Q as RainbowRuleDecorator, R as RenderMetadata, S as RenderResult, U as ShapeElement, V as StackLayoutConfig, W as TerminalElement, X as TextElement, Y as ThemeInput, Z as VignetteDecorator, _ as WrittenArtifacts, $ as builtInThemeBackgrounds, a0 as builtInThemes, a1 as computeSpecHash, a2 as connectionElementSchema, a3 as defaultAutoLayout, a4 as defaultCanvas, a5 as defaultConstraints, a6 as defaultGridLayout, a7 as defaultLayout, a8 as defaultStackLayout, a9 as defaultTheme, aa as deriveSafeFrame, ab as designSpecSchema, ac as diagramElementSchema, ad as diagramLayoutSchema, ae as diagramSpecSchema, af as drawGradientRect, ag as drawRainbowRule, ah as drawVignette, ai as flowNodeElementSchema, aj as inferLayout, ak as inferSidecarPath, al as parseDesignSpec, am as parseDiagramSpec, an as renderDesign, ao as resolveTheme, ap as writeRenderArtifacts } from './spec.schema-BeFz_nk1.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';
|
|
@@ -275,21 +275,31 @@ declare function outwardNormal(point: Point, diagramCenter: Point): Point;
|
|
|
275
275
|
/**
|
|
276
276
|
* Compute a cubic bezier curve that bows outward from the diagram center.
|
|
277
277
|
* Returns `[startPoint, controlPoint1, controlPoint2, endPoint]`.
|
|
278
|
+
*
|
|
279
|
+
* When `fromAnchor` or `toAnchor` hints are provided, they override the
|
|
280
|
+
* automatic edge anchor calculation and the outward normal is derived from
|
|
281
|
+
* the hint direction instead of from the diagram center.
|
|
278
282
|
*/
|
|
279
|
-
declare function curveRoute(fromBounds: Rect, toBounds: Rect, diagramCenter: Point, tension: number): [Point, Point, Point, Point];
|
|
283
|
+
declare function curveRoute(fromBounds: Rect, toBounds: Rect, diagramCenter: Point, tension: number, fromAnchor?: AnchorHint, toAnchor?: AnchorHint): [Point, Point, Point, Point];
|
|
280
284
|
/**
|
|
281
285
|
* Approximate an outward-bowing half-ellipse with two cubic bezier segments.
|
|
282
286
|
*
|
|
283
287
|
* Uses the classic kappa constant (`4 * (sqrt(2) - 1) / 3`) for quarter-ellipse
|
|
284
288
|
* control points, producing a stable arc from source edge anchor to target edge
|
|
285
289
|
* anchor.
|
|
290
|
+
*
|
|
291
|
+
* When `fromAnchor` or `toAnchor` hints are provided, they override the
|
|
292
|
+
* automatic edge anchor calculation.
|
|
286
293
|
*/
|
|
287
|
-
declare function arcRoute(fromBounds: Rect, toBounds: Rect, diagramCenter: Point, tension: number): [CubicBezierSegment, CubicBezierSegment];
|
|
294
|
+
declare function arcRoute(fromBounds: Rect, toBounds: Rect, diagramCenter: Point, tension: number, fromAnchor?: AnchorHint, toAnchor?: AnchorHint): [CubicBezierSegment, CubicBezierSegment];
|
|
288
295
|
/**
|
|
289
296
|
* Compute an orthogonal (right-angle) path between two rectangles.
|
|
290
297
|
* Returns an array of waypoints forming a 3-segment path.
|
|
298
|
+
*
|
|
299
|
+
* When `fromAnchor` or `toAnchor` hints are provided, they override the
|
|
300
|
+
* automatic edge anchor calculation.
|
|
291
301
|
*/
|
|
292
|
-
declare function orthogonalRoute(fromBounds: Rect, toBounds: Rect): Point[];
|
|
302
|
+
declare function orthogonalRoute(fromBounds: Rect, toBounds: Rect, fromAnchor?: AnchorHint, toAnchor?: AnchorHint): Point[];
|
|
293
303
|
/** Evaluate cubic bezier at parameter `t`. */
|
|
294
304
|
declare function bezierPointAt(p0: Point, cp1: Point, cp2: Point, p3: Point, t: number): Point;
|
|
295
305
|
/**
|
package/dist/index.js
CHANGED
|
@@ -861,6 +861,15 @@ var drawGradientRectSchema = z2.object({
|
|
|
861
861
|
radius: z2.number().min(0).max(256).default(0),
|
|
862
862
|
opacity: z2.number().min(0).max(1).default(1)
|
|
863
863
|
}).strict();
|
|
864
|
+
var drawGridSchema = z2.object({
|
|
865
|
+
type: z2.literal("grid"),
|
|
866
|
+
spacing: z2.number().min(5).max(200).default(40),
|
|
867
|
+
color: colorHexSchema2.default("#1E2D4A"),
|
|
868
|
+
width: z2.number().min(0.1).max(4).default(0.5),
|
|
869
|
+
opacity: z2.number().min(0).max(1).default(0.2),
|
|
870
|
+
offsetX: z2.number().default(0),
|
|
871
|
+
offsetY: z2.number().default(0)
|
|
872
|
+
}).strict();
|
|
864
873
|
var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
865
874
|
drawRectSchema,
|
|
866
875
|
drawCircleSchema,
|
|
@@ -869,7 +878,8 @@ var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
|
869
878
|
drawBezierSchema,
|
|
870
879
|
drawPathSchema,
|
|
871
880
|
drawBadgeSchema,
|
|
872
|
-
drawGradientRectSchema
|
|
881
|
+
drawGradientRectSchema,
|
|
882
|
+
drawGridSchema
|
|
873
883
|
]);
|
|
874
884
|
var defaultCanvas = {
|
|
875
885
|
width: 1200,
|
|
@@ -976,6 +986,13 @@ var flowNodeElementSchema = z2.object({
|
|
|
976
986
|
badgePosition: z2.enum(["top", "inside-top"]).default("inside-top"),
|
|
977
987
|
shadow: flowNodeShadowSchema.optional()
|
|
978
988
|
}).strict();
|
|
989
|
+
var anchorHintSchema = z2.union([
|
|
990
|
+
z2.enum(["top", "bottom", "left", "right", "center"]),
|
|
991
|
+
z2.object({
|
|
992
|
+
x: z2.number().min(-1).max(1),
|
|
993
|
+
y: z2.number().min(-1).max(1)
|
|
994
|
+
}).strict()
|
|
995
|
+
]);
|
|
979
996
|
var connectionElementSchema = z2.object({
|
|
980
997
|
type: z2.literal("connection"),
|
|
981
998
|
from: z2.string().min(1).max(120),
|
|
@@ -989,9 +1006,12 @@ var connectionElementSchema = z2.object({
|
|
|
989
1006
|
width: z2.number().min(0.5).max(10).optional(),
|
|
990
1007
|
strokeWidth: z2.number().min(0.5).max(10).default(2),
|
|
991
1008
|
arrowSize: z2.number().min(4).max(32).optional(),
|
|
1009
|
+
arrowPlacement: z2.enum(["endpoint", "boundary"]).default("endpoint"),
|
|
992
1010
|
opacity: z2.number().min(0).max(1).default(1),
|
|
993
1011
|
routing: z2.enum(["auto", "orthogonal", "curve", "arc"]).default("auto"),
|
|
994
|
-
tension: z2.number().min(0.1).max(0.8).default(0.35)
|
|
1012
|
+
tension: z2.number().min(0.1).max(0.8).default(0.35),
|
|
1013
|
+
fromAnchor: anchorHintSchema.optional(),
|
|
1014
|
+
toAnchor: anchorHintSchema.optional()
|
|
995
1015
|
}).strict();
|
|
996
1016
|
var codeBlockStyleSchema = z2.object({
|
|
997
1017
|
paddingVertical: z2.number().min(0).max(128).default(56),
|
|
@@ -3122,21 +3142,61 @@ function edgeAnchor(bounds, target) {
|
|
|
3122
3142
|
const t = absDx * hh > absDy * hw ? hw / absDx : hh / absDy;
|
|
3123
3143
|
return { x: c.x + dx * t, y: c.y + dy * t };
|
|
3124
3144
|
}
|
|
3145
|
+
function resolveAnchor(bounds, anchor, fallbackTarget) {
|
|
3146
|
+
if (!anchor) return edgeAnchor(bounds, fallbackTarget);
|
|
3147
|
+
if (typeof anchor === "string") {
|
|
3148
|
+
const c2 = rectCenter(bounds);
|
|
3149
|
+
switch (anchor) {
|
|
3150
|
+
case "top":
|
|
3151
|
+
return { x: c2.x, y: bounds.y };
|
|
3152
|
+
case "bottom":
|
|
3153
|
+
return { x: c2.x, y: bounds.y + bounds.height };
|
|
3154
|
+
case "left":
|
|
3155
|
+
return { x: bounds.x, y: c2.y };
|
|
3156
|
+
case "right":
|
|
3157
|
+
return { x: bounds.x + bounds.width, y: c2.y };
|
|
3158
|
+
case "center":
|
|
3159
|
+
return c2;
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
const c = rectCenter(bounds);
|
|
3163
|
+
return {
|
|
3164
|
+
x: c.x + anchor.x * (bounds.width / 2),
|
|
3165
|
+
y: c.y + anchor.y * (bounds.height / 2)
|
|
3166
|
+
};
|
|
3167
|
+
}
|
|
3168
|
+
function anchorNormal(anchor, point, diagramCenter) {
|
|
3169
|
+
if (typeof anchor === "string") {
|
|
3170
|
+
switch (anchor) {
|
|
3171
|
+
case "top":
|
|
3172
|
+
return { x: 0, y: -1 };
|
|
3173
|
+
case "bottom":
|
|
3174
|
+
return { x: 0, y: 1 };
|
|
3175
|
+
case "left":
|
|
3176
|
+
return { x: -1, y: 0 };
|
|
3177
|
+
case "right":
|
|
3178
|
+
return { x: 1, y: 0 };
|
|
3179
|
+
case "center":
|
|
3180
|
+
return outwardNormal(point, diagramCenter);
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
return outwardNormal(point, diagramCenter);
|
|
3184
|
+
}
|
|
3125
3185
|
function outwardNormal(point, diagramCenter) {
|
|
3126
3186
|
const dx = point.x - diagramCenter.x;
|
|
3127
3187
|
const dy = point.y - diagramCenter.y;
|
|
3128
3188
|
const len = Math.hypot(dx, dy) || 1;
|
|
3129
3189
|
return { x: dx / len, y: dy / len };
|
|
3130
3190
|
}
|
|
3131
|
-
function curveRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
3191
|
+
function curveRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, toAnchor) {
|
|
3132
3192
|
const fromCenter = rectCenter(fromBounds);
|
|
3133
3193
|
const toCenter = rectCenter(toBounds);
|
|
3134
|
-
const p0 =
|
|
3135
|
-
const p3 =
|
|
3194
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
3195
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
3136
3196
|
const dist = Math.hypot(p3.x - p0.x, p3.y - p0.y);
|
|
3137
3197
|
const offset = dist * tension;
|
|
3138
|
-
const n0 =
|
|
3139
|
-
const n3 =
|
|
3198
|
+
const n0 = anchorNormal(fromAnchor, p0, diagramCenter);
|
|
3199
|
+
const n3 = anchorNormal(toAnchor, p3, diagramCenter);
|
|
3140
3200
|
const cp1 = { x: p0.x + n0.x * offset, y: p0.y + n0.y * offset };
|
|
3141
3201
|
const cp2 = { x: p3.x + n3.x * offset, y: p3.y + n3.y * offset };
|
|
3142
3202
|
return [p0, cp1, cp2, p3];
|
|
@@ -3150,11 +3210,11 @@ function localToWorld(origin, axisX, axisY, local) {
|
|
|
3150
3210
|
y: origin.y + axisX.y * local.x + axisY.y * local.y
|
|
3151
3211
|
};
|
|
3152
3212
|
}
|
|
3153
|
-
function arcRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
3213
|
+
function arcRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, toAnchor) {
|
|
3154
3214
|
const fromCenter = rectCenter(fromBounds);
|
|
3155
3215
|
const toCenter = rectCenter(toBounds);
|
|
3156
|
-
const start =
|
|
3157
|
-
const end =
|
|
3216
|
+
const start = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
3217
|
+
const end = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
3158
3218
|
const chord = { x: end.x - start.x, y: end.y - start.y };
|
|
3159
3219
|
const chordLength = Math.hypot(chord.x, chord.y);
|
|
3160
3220
|
if (chordLength < 1e-6) {
|
|
@@ -3192,11 +3252,11 @@ function arcRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
|
3192
3252
|
[pMid, cp3, cp4, p3]
|
|
3193
3253
|
];
|
|
3194
3254
|
}
|
|
3195
|
-
function orthogonalRoute(fromBounds, toBounds) {
|
|
3255
|
+
function orthogonalRoute(fromBounds, toBounds, fromAnchor, toAnchor) {
|
|
3196
3256
|
const fromC = rectCenter(fromBounds);
|
|
3197
3257
|
const toC = rectCenter(toBounds);
|
|
3198
|
-
const p0 =
|
|
3199
|
-
const p3 =
|
|
3258
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toC);
|
|
3259
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromC);
|
|
3200
3260
|
const midX = (p0.x + p3.x) / 2;
|
|
3201
3261
|
return [p0, { x: midX, y: p0.y }, { x: midX, y: p3.y }, p3];
|
|
3202
3262
|
}
|
|
@@ -3207,6 +3267,35 @@ function bezierPointAt(p0, cp1, cp2, p3, t) {
|
|
|
3207
3267
|
y: mt * mt * mt * p0.y + 3 * mt * mt * t * cp1.y + 3 * mt * t * t * cp2.y + t * t * t * p3.y
|
|
3208
3268
|
};
|
|
3209
3269
|
}
|
|
3270
|
+
function bezierTangentAt(p0, cp1, cp2, p3, t) {
|
|
3271
|
+
const mt = 1 - t;
|
|
3272
|
+
return {
|
|
3273
|
+
x: 3 * mt * mt * (cp1.x - p0.x) + 6 * mt * t * (cp2.x - cp1.x) + 3 * t * t * (p3.x - cp2.x),
|
|
3274
|
+
y: 3 * mt * mt * (cp1.y - p0.y) + 6 * mt * t * (cp2.y - cp1.y) + 3 * t * t * (p3.y - cp2.y)
|
|
3275
|
+
};
|
|
3276
|
+
}
|
|
3277
|
+
function isInsideRect(point, rect) {
|
|
3278
|
+
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
3279
|
+
}
|
|
3280
|
+
function findBoundaryIntersection(p0, cp1, cp2, p3, targetRect, searchFromEnd) {
|
|
3281
|
+
const step = 5e-3;
|
|
3282
|
+
if (searchFromEnd) {
|
|
3283
|
+
for (let t = 0.95; t >= 0.5; t -= step) {
|
|
3284
|
+
const pt = bezierPointAt(p0, cp1, cp2, p3, t);
|
|
3285
|
+
if (!isInsideRect(pt, targetRect)) {
|
|
3286
|
+
return t;
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
} else {
|
|
3290
|
+
for (let t = 0.05; t <= 0.5; t += step) {
|
|
3291
|
+
const pt = bezierPointAt(p0, cp1, cp2, p3, t);
|
|
3292
|
+
if (!isInsideRect(pt, targetRect)) {
|
|
3293
|
+
return t;
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
return void 0;
|
|
3298
|
+
}
|
|
3210
3299
|
function pointAlongArc(route, t) {
|
|
3211
3300
|
const [first, second] = route;
|
|
3212
3301
|
if (t <= 0.5) {
|
|
@@ -3334,8 +3423,16 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3334
3423
|
let labelPoint;
|
|
3335
3424
|
ctx.save();
|
|
3336
3425
|
ctx.globalAlpha = conn.opacity;
|
|
3426
|
+
const arrowPlacement = conn.arrowPlacement ?? "endpoint";
|
|
3337
3427
|
if (routing === "curve") {
|
|
3338
|
-
const [p0, cp1, cp2, p3] = curveRoute(
|
|
3428
|
+
const [p0, cp1, cp2, p3] = curveRoute(
|
|
3429
|
+
fromBounds,
|
|
3430
|
+
toBounds,
|
|
3431
|
+
diagramCenter,
|
|
3432
|
+
tension,
|
|
3433
|
+
conn.fromAnchor,
|
|
3434
|
+
conn.toAnchor
|
|
3435
|
+
);
|
|
3339
3436
|
ctx.strokeStyle = style.color;
|
|
3340
3437
|
ctx.lineWidth = style.width;
|
|
3341
3438
|
ctx.setLineDash(style.dash ?? []);
|
|
@@ -3349,8 +3446,33 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3349
3446
|
startAngle = Math.atan2(p0.y - cp1.y, p0.x - cp1.x);
|
|
3350
3447
|
endAngle = Math.atan2(p3.y - cp2.y, p3.x - cp2.x);
|
|
3351
3448
|
labelPoint = bezierPointAt(p0, cp1, cp2, p3, labelT);
|
|
3449
|
+
if (arrowPlacement === "boundary") {
|
|
3450
|
+
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
3451
|
+
const tEnd = findBoundaryIntersection(p0, cp1, cp2, p3, toBounds, true);
|
|
3452
|
+
if (tEnd !== void 0) {
|
|
3453
|
+
endPoint = bezierPointAt(p0, cp1, cp2, p3, tEnd);
|
|
3454
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, p3, tEnd);
|
|
3455
|
+
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
3459
|
+
const tStart = findBoundaryIntersection(p0, cp1, cp2, p3, fromBounds, false);
|
|
3460
|
+
if (tStart !== void 0) {
|
|
3461
|
+
startPoint = bezierPointAt(p0, cp1, cp2, p3, tStart);
|
|
3462
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, p3, tStart);
|
|
3463
|
+
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3352
3467
|
} else if (routing === "arc") {
|
|
3353
|
-
const [first, second] = arcRoute(
|
|
3468
|
+
const [first, second] = arcRoute(
|
|
3469
|
+
fromBounds,
|
|
3470
|
+
toBounds,
|
|
3471
|
+
diagramCenter,
|
|
3472
|
+
tension,
|
|
3473
|
+
conn.fromAnchor,
|
|
3474
|
+
conn.toAnchor
|
|
3475
|
+
);
|
|
3354
3476
|
const [p0, cp1, cp2, pMid] = first;
|
|
3355
3477
|
const [, cp3, cp4, p3] = second;
|
|
3356
3478
|
ctx.strokeStyle = style.color;
|
|
@@ -3367,9 +3489,29 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3367
3489
|
startAngle = Math.atan2(p0.y - cp1.y, p0.x - cp1.x);
|
|
3368
3490
|
endAngle = Math.atan2(p3.y - cp4.y, p3.x - cp4.x);
|
|
3369
3491
|
labelPoint = pointAlongArc([first, second], labelT);
|
|
3492
|
+
if (arrowPlacement === "boundary") {
|
|
3493
|
+
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
3494
|
+
const [, s_cp3, s_cp4, s_p3] = second;
|
|
3495
|
+
const tEnd = findBoundaryIntersection(pMid, s_cp3, s_cp4, s_p3, toBounds, true);
|
|
3496
|
+
if (tEnd !== void 0) {
|
|
3497
|
+
endPoint = bezierPointAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3498
|
+
const tangent = bezierTangentAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3499
|
+
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
3503
|
+
const tStart = findBoundaryIntersection(p0, cp1, cp2, pMid, fromBounds, false);
|
|
3504
|
+
if (tStart !== void 0) {
|
|
3505
|
+
startPoint = bezierPointAt(p0, cp1, cp2, pMid, tStart);
|
|
3506
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, pMid, tStart);
|
|
3507
|
+
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3370
3511
|
} else {
|
|
3371
|
-
const
|
|
3372
|
-
|
|
3512
|
+
const hasAnchorHints = conn.fromAnchor !== void 0 || conn.toAnchor !== void 0;
|
|
3513
|
+
const useElkRoute = routing === "auto" && !hasAnchorHints && (edgeRoute?.points.length ?? 0) >= 2;
|
|
3514
|
+
linePoints = useElkRoute ? edgeRoute?.points ?? orthogonalRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor) : orthogonalRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor);
|
|
3373
3515
|
startPoint = linePoints[0];
|
|
3374
3516
|
const startSegment = linePoints[1] ?? linePoints[0];
|
|
3375
3517
|
const endStart = linePoints[linePoints.length - 2] ?? linePoints[0];
|
|
@@ -4026,6 +4168,36 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4026
4168
|
});
|
|
4027
4169
|
break;
|
|
4028
4170
|
}
|
|
4171
|
+
case "grid": {
|
|
4172
|
+
const canvasWidth = ctx.canvas.width;
|
|
4173
|
+
const canvasHeight = ctx.canvas.height;
|
|
4174
|
+
withOpacity(ctx, command.opacity, () => {
|
|
4175
|
+
ctx.strokeStyle = command.color;
|
|
4176
|
+
ctx.lineWidth = command.width;
|
|
4177
|
+
const startX = command.offsetX % command.spacing;
|
|
4178
|
+
for (let x = startX; x <= canvasWidth; x += command.spacing) {
|
|
4179
|
+
ctx.beginPath();
|
|
4180
|
+
ctx.moveTo(x, 0);
|
|
4181
|
+
ctx.lineTo(x, canvasHeight);
|
|
4182
|
+
ctx.stroke();
|
|
4183
|
+
}
|
|
4184
|
+
const startY = command.offsetY % command.spacing;
|
|
4185
|
+
for (let y = startY; y <= canvasHeight; y += command.spacing) {
|
|
4186
|
+
ctx.beginPath();
|
|
4187
|
+
ctx.moveTo(0, y);
|
|
4188
|
+
ctx.lineTo(canvasWidth, y);
|
|
4189
|
+
ctx.stroke();
|
|
4190
|
+
}
|
|
4191
|
+
});
|
|
4192
|
+
rendered.push({
|
|
4193
|
+
id,
|
|
4194
|
+
kind: "draw",
|
|
4195
|
+
bounds: { x: 0, y: 0, width: canvasWidth, height: canvasHeight },
|
|
4196
|
+
foregroundColor: command.color,
|
|
4197
|
+
allowOverlap: true
|
|
4198
|
+
});
|
|
4199
|
+
break;
|
|
4200
|
+
}
|
|
4029
4201
|
}
|
|
4030
4202
|
}
|
|
4031
4203
|
return rendered;
|
package/dist/qa.d.ts
CHANGED