@popcraft/cli 0.53.1 → 0.53.2
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/popcraft.mjs +357 -165
- package/package.json +2 -2
package/dist/popcraft.mjs
CHANGED
|
@@ -1196,7 +1196,7 @@ function operations(spec = openapi) {
|
|
|
1196
1196
|
}
|
|
1197
1197
|
async function call(target2, method, path, opts = {}) {
|
|
1198
1198
|
const qs = new URLSearchParams(opts.query ?? {}).toString();
|
|
1199
|
-
const headers = { "user-agent": `popcraft-cli/${"0.53.
|
|
1199
|
+
const headers = { "user-agent": `popcraft-cli/${"0.53.2"}`, ...opts.headers };
|
|
1200
1200
|
if (target2.token) headers.authorization = `Bearer ${target2.token}`;
|
|
1201
1201
|
if (opts.contentType) headers["content-type"] = opts.contentType;
|
|
1202
1202
|
try {
|
|
@@ -6786,8 +6786,8 @@ function currentPrintPage(doc2, pageId2, o = {}) {
|
|
|
6786
6786
|
}
|
|
6787
6787
|
const c2 = o.centre;
|
|
6788
6788
|
if (c2) {
|
|
6789
|
-
const
|
|
6790
|
-
if (
|
|
6789
|
+
const inside3 = pages2.find((p2) => c2.x >= p2.x && c2.x <= p2.x + p2.width && c2.y >= p2.y && c2.y <= p2.y + p2.height);
|
|
6790
|
+
if (inside3) return inside3;
|
|
6791
6791
|
let best = pages2[0], bestD = Infinity;
|
|
6792
6792
|
for (const p2 of pages2) {
|
|
6793
6793
|
const dx = Math.max(p2.x - c2.x, 0, c2.x - (p2.x + p2.width));
|
|
@@ -96212,7 +96212,6 @@ function repairDocumentPaints(doc2) {
|
|
|
96212
96212
|
var broken;
|
|
96213
96213
|
var init_paint_repair = __esm({
|
|
96214
96214
|
"lib/document/paint-repair.ts"() {
|
|
96215
|
-
"use strict";
|
|
96216
96215
|
init_shader_graph();
|
|
96217
96216
|
broken = (p2) => {
|
|
96218
96217
|
if (!p2 || typeof p2 !== "object") return false;
|
|
@@ -96870,6 +96869,7 @@ function releaseMediaMemory(hash3) {
|
|
|
96870
96869
|
var key2, peaksKey, objectUrls, sourceKey, remoteResolver, MEDIA_FETCH_TIMEOUT_MS, SHIPPED_MEDIA_PATH, notShipped, MEDIA_SCHEME, isImageDataUrl, memory, pendingLoads, sourceAliases, PAINT_KEYS, URL_KEYS;
|
|
96871
96870
|
var init_media_store = __esm({
|
|
96872
96871
|
"lib/storage/media-store.ts"() {
|
|
96872
|
+
"use strict";
|
|
96873
96873
|
init_media_types();
|
|
96874
96874
|
init_idb();
|
|
96875
96875
|
init_media_hash();
|
|
@@ -251991,12 +251991,65 @@ var require_polygon_clipping_cjs = __commonJS({
|
|
|
251991
251991
|
}
|
|
251992
251992
|
});
|
|
251993
251993
|
|
|
251994
|
+
// lib/engine/geometry/winding.ts
|
|
251995
|
+
function interiorPoint(r) {
|
|
251996
|
+
let cx = 0, cy = 0;
|
|
251997
|
+
for (const [x2, y] of r) {
|
|
251998
|
+
cx += x2;
|
|
251999
|
+
cy += y;
|
|
252000
|
+
}
|
|
252001
|
+
const centroid2 = [cx / r.length, cy / r.length];
|
|
252002
|
+
if (inside(centroid2, r)) return centroid2;
|
|
252003
|
+
const [a, b, c2] = [r[0], r[1], r[2] ?? r[0]];
|
|
252004
|
+
return [(a[0] + b[0] + c2[0]) / 3, (a[1] + b[1] + c2[1]) / 3];
|
|
252005
|
+
}
|
|
252006
|
+
function nonzeroMultiPoly(rings) {
|
|
252007
|
+
const usable = rings.filter((r) => r.length >= 3);
|
|
252008
|
+
if (!usable.length) return [];
|
|
252009
|
+
const polys = usable.map((r) => [r]);
|
|
252010
|
+
if (usable.length === 1) return import_polygon_clipping.default.union(polys[0]);
|
|
252011
|
+
const areas = usable.map(signedArea);
|
|
252012
|
+
const add3 = [], sub2 = [];
|
|
252013
|
+
usable.forEach((r, i2) => {
|
|
252014
|
+
const p2 = interiorPoint(r);
|
|
252015
|
+
let w = Math.sign(areas[i2]);
|
|
252016
|
+
usable.forEach((o, j) => {
|
|
252017
|
+
if (j !== i2 && Math.abs(areas[j]) > Math.abs(areas[i2]) && inside(p2, o)) w += Math.sign(areas[j]);
|
|
252018
|
+
});
|
|
252019
|
+
(w === 0 ? sub2 : add3).push(polys[i2]);
|
|
252020
|
+
});
|
|
252021
|
+
if (!add3.length) return [];
|
|
252022
|
+
const filled2 = import_polygon_clipping.default.union(add3[0], ...add3.slice(1));
|
|
252023
|
+
return sub2.length ? import_polygon_clipping.default.difference(filled2, ...sub2) : filled2;
|
|
252024
|
+
}
|
|
252025
|
+
var import_polygon_clipping, signedArea, inside;
|
|
252026
|
+
var init_winding = __esm({
|
|
252027
|
+
"lib/engine/geometry/winding.ts"() {
|
|
252028
|
+
"use strict";
|
|
252029
|
+
import_polygon_clipping = __toESM(require_polygon_clipping_cjs());
|
|
252030
|
+
signedArea = (r) => {
|
|
252031
|
+
let a = 0;
|
|
252032
|
+
for (let i2 = 0, j = r.length - 1; i2 < r.length; j = i2++) a += (r[j][0] - r[i2][0]) * (r[j][1] + r[i2][1]);
|
|
252033
|
+
return a / 2;
|
|
252034
|
+
};
|
|
252035
|
+
inside = ([x2, y], r) => {
|
|
252036
|
+
let c2 = false;
|
|
252037
|
+
for (let i2 = 0, j = r.length - 1; i2 < r.length; j = i2++) {
|
|
252038
|
+
const [xi, yi] = r[i2], [xj, yj] = r[j];
|
|
252039
|
+
if (yi > y !== yj > y && x2 < (xj - xi) * (y - yi) / (yj - yi) + xi) c2 = !c2;
|
|
252040
|
+
}
|
|
252041
|
+
return c2;
|
|
252042
|
+
};
|
|
252043
|
+
}
|
|
252044
|
+
});
|
|
252045
|
+
|
|
251994
252046
|
// lib/engine/geometry/triangulate.ts
|
|
251995
|
-
var
|
|
252047
|
+
var import_polygon_clipping2;
|
|
251996
252048
|
var init_triangulate = __esm({
|
|
251997
252049
|
"lib/engine/geometry/triangulate.ts"() {
|
|
251998
252050
|
"use strict";
|
|
251999
|
-
|
|
252051
|
+
import_polygon_clipping2 = __toESM(require_polygon_clipping_cjs());
|
|
252052
|
+
init_winding();
|
|
252000
252053
|
}
|
|
252001
252054
|
});
|
|
252002
252055
|
|
|
@@ -252020,7 +252073,7 @@ function computeBooleanMultiPoly(node2, allNodes) {
|
|
|
252020
252073
|
const asPolys = rings.map((r) => [r]);
|
|
252021
252074
|
let mp;
|
|
252022
252075
|
try {
|
|
252023
|
-
mp = asPolys.length > 1 ?
|
|
252076
|
+
mp = asPolys.length > 1 ? import_polygon_clipping3.default.union(asPolys[0], ...asPolys.slice(1)) : asPolys;
|
|
252024
252077
|
} catch {
|
|
252025
252078
|
mp = asPolys;
|
|
252026
252079
|
}
|
|
@@ -252032,25 +252085,25 @@ function computeBooleanMultiPoly(node2, allNodes) {
|
|
|
252032
252085
|
try {
|
|
252033
252086
|
const rest = operands.slice(1);
|
|
252034
252087
|
if (rest.length > 0) {
|
|
252035
|
-
if (op4 === "SUBTRACT") result =
|
|
252036
|
-
else if (op4 === "INTERSECT") result =
|
|
252037
|
-
else if (op4 === "EXCLUDE") result =
|
|
252038
|
-
else result =
|
|
252088
|
+
if (op4 === "SUBTRACT") result = import_polygon_clipping3.default.difference(operands[0], ...rest);
|
|
252089
|
+
else if (op4 === "INTERSECT") result = import_polygon_clipping3.default.intersection(operands[0], ...rest);
|
|
252090
|
+
else if (op4 === "EXCLUDE") result = import_polygon_clipping3.default.xor(operands[0], ...rest);
|
|
252091
|
+
else result = import_polygon_clipping3.default.union(operands[0], ...rest);
|
|
252039
252092
|
}
|
|
252040
252093
|
} catch {
|
|
252041
252094
|
try {
|
|
252042
|
-
result =
|
|
252095
|
+
result = import_polygon_clipping3.default.union(operands[0], ...operands.slice(1));
|
|
252043
252096
|
} catch {
|
|
252044
252097
|
result = operands[0];
|
|
252045
252098
|
}
|
|
252046
252099
|
}
|
|
252047
252100
|
return result;
|
|
252048
252101
|
}
|
|
252049
|
-
var
|
|
252102
|
+
var import_polygon_clipping3;
|
|
252050
252103
|
var init_vector_geometry_cache = __esm({
|
|
252051
252104
|
"lib/engine/vector-geometry-cache.ts"() {
|
|
252052
252105
|
"use strict";
|
|
252053
|
-
|
|
252106
|
+
import_polygon_clipping3 = __toESM(require_polygon_clipping_cjs());
|
|
252054
252107
|
init_flatten();
|
|
252055
252108
|
init_triangulate();
|
|
252056
252109
|
init_shape_outline();
|
|
@@ -252069,11 +252122,11 @@ function arrangementFaces(shapes) {
|
|
|
252069
252122
|
const next2 = [];
|
|
252070
252123
|
let rest = shape2;
|
|
252071
252124
|
for (const f2 of faces2) {
|
|
252072
|
-
const
|
|
252073
|
-
if (solid(
|
|
252074
|
-
const outside = op2(
|
|
252125
|
+
const inside3 = op2(import_polygon_clipping4.default.intersection, f2.mp, shape2);
|
|
252126
|
+
if (solid(inside3)) next2.push({ mp: inside3, sources: [...f2.sources, i2] });
|
|
252127
|
+
const outside = op2(import_polygon_clipping4.default.difference, f2.mp, shape2);
|
|
252075
252128
|
if (solid(outside)) next2.push({ mp: outside, sources: f2.sources });
|
|
252076
|
-
if (solid(
|
|
252129
|
+
if (solid(inside3)) rest = op2(import_polygon_clipping4.default.difference, rest, f2.mp);
|
|
252077
252130
|
}
|
|
252078
252131
|
if (solid(rest)) next2.push({ mp: rest, sources: [i2] });
|
|
252079
252132
|
faces2 = next2;
|
|
@@ -252082,15 +252135,15 @@ function arrangementFaces(shapes) {
|
|
|
252082
252135
|
}
|
|
252083
252136
|
function pointInMultiPoly(mp, x2, y) {
|
|
252084
252137
|
for (const poly of mp) {
|
|
252085
|
-
let
|
|
252138
|
+
let inside3 = false;
|
|
252086
252139
|
for (const ring of poly) {
|
|
252087
252140
|
for (let i2 = 0, j = ring.length - 1; i2 < ring.length; j = i2++) {
|
|
252088
252141
|
const [xi, yi] = ring[i2];
|
|
252089
252142
|
const [xj, yj] = ring[j];
|
|
252090
|
-
if (yi > y !== yj > y && x2 < (xj - xi) * (y - yi) / (yj - yi) + xi)
|
|
252143
|
+
if (yi > y !== yj > y && x2 < (xj - xi) * (y - yi) / (yj - yi) + xi) inside3 = !inside3;
|
|
252091
252144
|
}
|
|
252092
252145
|
}
|
|
252093
|
-
if (
|
|
252146
|
+
if (inside3) return true;
|
|
252094
252147
|
}
|
|
252095
252148
|
return false;
|
|
252096
252149
|
}
|
|
@@ -252102,16 +252155,16 @@ function unionFaces(faces2, picked) {
|
|
|
252102
252155
|
const parts = picked.map((i2) => faces2[i2]?.mp).filter(solid);
|
|
252103
252156
|
if (parts.length === 0) return [];
|
|
252104
252157
|
try {
|
|
252105
|
-
return parts.length > 1 ?
|
|
252158
|
+
return parts.length > 1 ? import_polygon_clipping4.default.union(parts[0], ...parts.slice(1)) : parts[0];
|
|
252106
252159
|
} catch {
|
|
252107
252160
|
return parts[0];
|
|
252108
252161
|
}
|
|
252109
252162
|
}
|
|
252110
|
-
var
|
|
252163
|
+
var import_polygon_clipping4, MAX_SHAPE_BUILDER_SHAPES, area2, MIN_FACE_AREA, solid, op2;
|
|
252111
252164
|
var init_regions = __esm({
|
|
252112
252165
|
"lib/engine/geometry/regions.ts"() {
|
|
252113
252166
|
"use strict";
|
|
252114
|
-
|
|
252167
|
+
import_polygon_clipping4 = __toESM(require_polygon_clipping_cjs());
|
|
252115
252168
|
MAX_SHAPE_BUILDER_SHAPES = 12;
|
|
252116
252169
|
area2 = (mp) => {
|
|
252117
252170
|
let a = 0;
|
|
@@ -252213,7 +252266,7 @@ function bufferPolylines(lines2, width) {
|
|
|
252213
252266
|
}
|
|
252214
252267
|
if (pieces.length === 0) return [];
|
|
252215
252268
|
try {
|
|
252216
|
-
return pieces.length > 1 ?
|
|
252269
|
+
return pieces.length > 1 ? import_polygon_clipping5.default.union(pieces[0], ...pieces.slice(1)) : [pieces[0]];
|
|
252217
252270
|
} catch {
|
|
252218
252271
|
return pieces.map((p2) => [p2[0]]);
|
|
252219
252272
|
}
|
|
@@ -252222,7 +252275,7 @@ function combineRings(rings, mode2) {
|
|
|
252222
252275
|
const polys = rings.filter((r) => r.length >= 3).map((r) => [r]);
|
|
252223
252276
|
if (polys.length === 0) return [];
|
|
252224
252277
|
try {
|
|
252225
|
-
return polys.length > 1 ?
|
|
252278
|
+
return polys.length > 1 ? import_polygon_clipping5.default[mode2](polys[0], ...polys.slice(1)) : [polys[0]];
|
|
252226
252279
|
} catch {
|
|
252227
252280
|
return polys.map((p2) => [p2[0]]);
|
|
252228
252281
|
}
|
|
@@ -252236,8 +252289,15 @@ function nodeWorldMultiPoly(doc2, id3) {
|
|
|
252236
252289
|
return mp.map((poly) => poly.map((ring) => ring.map(([x2, y]) => place4(x2, y))));
|
|
252237
252290
|
}
|
|
252238
252291
|
const rings = nodeWorldRings(doc2, id3);
|
|
252239
|
-
|
|
252240
|
-
|
|
252292
|
+
if (node2.type === "VECTOR") {
|
|
252293
|
+
if (node2.fillRule === "EVENODD") return combineRings(rings, "xor");
|
|
252294
|
+
try {
|
|
252295
|
+
return nonzeroMultiPoly(rings);
|
|
252296
|
+
} catch {
|
|
252297
|
+
return combineRings(rings, "union");
|
|
252298
|
+
}
|
|
252299
|
+
}
|
|
252300
|
+
return combineRings(rings, "union");
|
|
252241
252301
|
}
|
|
252242
252302
|
function nodeAreaMultiPoly(doc2, id3) {
|
|
252243
252303
|
if (!doc2.nodes[id3]) return [];
|
|
@@ -252247,13 +252307,23 @@ function nodeAreaMultiPoly(doc2, id3) {
|
|
|
252247
252307
|
}
|
|
252248
252308
|
function flattenNodesMultiPoly(doc2, ids2) {
|
|
252249
252309
|
const operands = [];
|
|
252250
|
-
|
|
252251
|
-
const
|
|
252252
|
-
if (
|
|
252253
|
-
|
|
252310
|
+
const visit2 = (id3) => {
|
|
252311
|
+
const n = doc2.nodes[id3];
|
|
252312
|
+
if (!n || n.visible === false) return;
|
|
252313
|
+
if (n.type !== "GROUP") {
|
|
252314
|
+
const mp = n.type === "FRAME" || n.type === "COMPONENT" || n.type === "INSTANCE" || n.type === "SECTION" ? (n.fills ?? []).some((f2) => f2.visible !== false) ? nodeWorldMultiPoly(doc2, id3) : [] : nodeAreaMultiPoly(doc2, id3);
|
|
252315
|
+
if (mp.length > 0) operands.push(mp);
|
|
252316
|
+
}
|
|
252317
|
+
if (n.type !== "BOOLEAN") for (const c2 of n.childIds ?? []) visit2(c2);
|
|
252318
|
+
};
|
|
252319
|
+
ids2.forEach(visit2);
|
|
252320
|
+
return unionAll(operands);
|
|
252321
|
+
}
|
|
252322
|
+
function unionAll(mps) {
|
|
252323
|
+
const operands = mps.filter((mp) => mp.length > 0);
|
|
252254
252324
|
if (operands.length === 0) return [];
|
|
252255
252325
|
try {
|
|
252256
|
-
return operands.length > 1 ?
|
|
252326
|
+
return operands.length > 1 ? import_polygon_clipping5.default.union(operands[0], ...operands.slice(1)) : operands[0];
|
|
252257
252327
|
} catch {
|
|
252258
252328
|
return operands[0];
|
|
252259
252329
|
}
|
|
@@ -252279,7 +252349,7 @@ function outlineStrokeMultiPoly(doc2, id3) {
|
|
|
252279
252349
|
const buffer2 = bufferPolylines(lines2, width * 2);
|
|
252280
252350
|
if (fill.length === 0 || buffer2.length === 0) return bufferPolylines(lines2, width);
|
|
252281
252351
|
try {
|
|
252282
|
-
return alignment === "INSIDE" ?
|
|
252352
|
+
return alignment === "INSIDE" ? import_polygon_clipping5.default.intersection(buffer2, fill) : import_polygon_clipping5.default.difference(buffer2, fill);
|
|
252283
252353
|
} catch {
|
|
252284
252354
|
return bufferPolylines(lines2, width);
|
|
252285
252355
|
}
|
|
@@ -252311,16 +252381,17 @@ function shapeBuilderFaces(doc2, ids2) {
|
|
|
252311
252381
|
facesCache = { nodes: doc2.nodes, key: key5, faces: faces2 };
|
|
252312
252382
|
return faces2;
|
|
252313
252383
|
}
|
|
252314
|
-
var
|
|
252384
|
+
var import_polygon_clipping5, JOIN_CIRCLE_SEGMENTS, facesCache;
|
|
252315
252385
|
var init_vector_ops = __esm({
|
|
252316
252386
|
"lib/engine/geometry/vector-ops.ts"() {
|
|
252317
252387
|
"use strict";
|
|
252318
|
-
|
|
252388
|
+
import_polygon_clipping5 = __toESM(require_polygon_clipping_cjs());
|
|
252319
252389
|
init_scene_graph();
|
|
252320
252390
|
init_transform();
|
|
252321
252391
|
init_shape_outline();
|
|
252322
252392
|
init_flatten();
|
|
252323
252393
|
init_vector_geometry_cache();
|
|
252394
|
+
init_winding();
|
|
252324
252395
|
init_regions();
|
|
252325
252396
|
JOIN_CIRCLE_SEGMENTS = 16;
|
|
252326
252397
|
facesCache = null;
|
|
@@ -252374,15 +252445,15 @@ var init_brush_along_path = __esm({
|
|
|
252374
252445
|
|
|
252375
252446
|
// lib/engine/geometry/polygon.ts
|
|
252376
252447
|
function pointInPolygon(p2, poly) {
|
|
252377
|
-
let
|
|
252448
|
+
let inside3 = false;
|
|
252378
252449
|
for (let i2 = 0, j = poly.length - 1; i2 < poly.length; j = i2++) {
|
|
252379
252450
|
const a = poly[i2], b = poly[j];
|
|
252380
252451
|
if (a.y > p2.y !== b.y > p2.y) {
|
|
252381
252452
|
const xCross = a.x + (p2.y - a.y) * (b.x - a.x) / (b.y - a.y);
|
|
252382
|
-
if (p2.x < xCross)
|
|
252453
|
+
if (p2.x < xCross) inside3 = !inside3;
|
|
252383
252454
|
}
|
|
252384
252455
|
}
|
|
252385
|
-
return
|
|
252456
|
+
return inside3;
|
|
252386
252457
|
}
|
|
252387
252458
|
var init_polygon = __esm({
|
|
252388
252459
|
"lib/engine/geometry/polygon.ts"() {
|
|
@@ -252422,8 +252493,8 @@ function enclosedRegion(shapes, pt, view2) {
|
|
|
252422
252493
|
}
|
|
252423
252494
|
try {
|
|
252424
252495
|
let region = rectMP(view2);
|
|
252425
|
-
for (const c2 of containing) region =
|
|
252426
|
-
if (subtract.length) region =
|
|
252496
|
+
for (const c2 of containing) region = import_polygon_clipping6.default.intersection(region, c2);
|
|
252497
|
+
if (subtract.length) region = import_polygon_clipping6.default.difference(region, ...subtract);
|
|
252427
252498
|
const hit = region.find((p2) => pointInPoly(pt, p2));
|
|
252428
252499
|
if (!hit) return { ok: false, reason: "EMPTY" };
|
|
252429
252500
|
if (!containing.length && touchesRect(hit, view2)) return { ok: false, reason: "OPEN" };
|
|
@@ -252474,11 +252545,11 @@ function findEnclosedRegion(doc2, pageId2, pt, view2) {
|
|
|
252474
252545
|
walk4(pageId2);
|
|
252475
252546
|
return enclosedRegion(shapes, pt, view2);
|
|
252476
252547
|
}
|
|
252477
|
-
var
|
|
252548
|
+
var import_polygon_clipping6, ringPts, pointInMP, rectMP;
|
|
252478
252549
|
var init_bucket = __esm({
|
|
252479
252550
|
"lib/engine/geometry/bucket.ts"() {
|
|
252480
252551
|
"use strict";
|
|
252481
|
-
|
|
252552
|
+
import_polygon_clipping6 = __toESM(require_polygon_clipping_cjs());
|
|
252482
252553
|
init_scene_graph();
|
|
252483
252554
|
init_vector_ops();
|
|
252484
252555
|
init_polygon();
|
|
@@ -257639,10 +257710,10 @@ function collapse(doc2) {
|
|
|
257639
257710
|
else groups.set(h, [id3]);
|
|
257640
257711
|
}
|
|
257641
257712
|
const chosen = [];
|
|
257642
|
-
const
|
|
257713
|
+
const inside3 = /* @__PURE__ */ new Set();
|
|
257643
257714
|
const sorted = [...groups.values()].filter((g) => g.length >= MIN_COPIES).sort((a, b) => (size6.get(b[0]) ?? 0) - (size6.get(a[0]) ?? 0));
|
|
257644
257715
|
const within3 = (id3) => {
|
|
257645
|
-
for (let p2 = nodes[id3]?.parentId, guard2 = 0; p2 && guard2 < 200; p2 = nodes[p2]?.parentId, guard2++) if (
|
|
257716
|
+
for (let p2 = nodes[id3]?.parentId, guard2 = 0; p2 && guard2 < 200; p2 = nodes[p2]?.parentId, guard2++) if (inside3.has(p2)) return true;
|
|
257646
257717
|
return false;
|
|
257647
257718
|
};
|
|
257648
257719
|
for (const g of sorted) {
|
|
@@ -257650,7 +257721,7 @@ function collapse(doc2) {
|
|
|
257650
257721
|
const copies = g.filter((id3) => !within3(id3) && (id3 === rep || sameContents(nodes, rep, id3)));
|
|
257651
257722
|
if (copies.length < MIN_COPIES || !copies.includes(rep)) continue;
|
|
257652
257723
|
chosen.push(copies);
|
|
257653
|
-
for (const id3 of copies)
|
|
257724
|
+
for (const id3 of copies) inside3.add(id3);
|
|
257654
257725
|
}
|
|
257655
257726
|
if (!chosen.length) return doc2;
|
|
257656
257727
|
const out = { ...nodes };
|
|
@@ -257995,7 +258066,6 @@ function onTabMessage(fn) {
|
|
|
257995
258066
|
var EDITOR_HOME, localDocPath, cloudFilePath, CHANNEL2, channel2;
|
|
257996
258067
|
var init_tab_mode = __esm({
|
|
257997
258068
|
"lib/desktop/tab-mode.ts"() {
|
|
257998
|
-
"use strict";
|
|
257999
258069
|
EDITOR_HOME = "/home";
|
|
258000
258070
|
localDocPath = (docId) => `${EDITOR_HOME}?doc=${encodeURIComponent(docId)}`;
|
|
258001
258071
|
cloudFilePath = (key5) => `/pop/${encodeURIComponent(key5)}`;
|
|
@@ -258012,6 +258082,64 @@ function scaleVectorPaths(paths, sx, sy, rebuild) {
|
|
|
258012
258082
|
return { ...path, points, data: rebuild(points, path.closed) };
|
|
258013
258083
|
});
|
|
258014
258084
|
}
|
|
258085
|
+
function scaledChildProps(orig, sx, sy, rebuild) {
|
|
258086
|
+
return {
|
|
258087
|
+
x: orig.x * sx,
|
|
258088
|
+
y: orig.y * sy,
|
|
258089
|
+
width: orig.width * sx,
|
|
258090
|
+
height: orig.height * sy,
|
|
258091
|
+
...orig.type === "VECTOR" ? { paths: scaleVectorPaths(orig.paths, sx, sy, rebuild) } : {}
|
|
258092
|
+
};
|
|
258093
|
+
}
|
|
258094
|
+
function rebuildVectorData(points, closed) {
|
|
258095
|
+
if (points.length < 2) return [];
|
|
258096
|
+
const data = [];
|
|
258097
|
+
data.push("M", points[0].x, points[0].y);
|
|
258098
|
+
for (let i2 = 1; i2 < points.length; i2++) {
|
|
258099
|
+
const prev = points[i2 - 1];
|
|
258100
|
+
const curr = points[i2];
|
|
258101
|
+
if (prev.handleOut && curr.handleIn) {
|
|
258102
|
+
data.push("C", prev.handleOut.x, prev.handleOut.y, curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
258103
|
+
} else if (prev.handleOut) {
|
|
258104
|
+
data.push("Q", prev.handleOut.x, prev.handleOut.y, curr.x, curr.y);
|
|
258105
|
+
} else if (curr.handleIn) {
|
|
258106
|
+
data.push("Q", curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
258107
|
+
} else {
|
|
258108
|
+
data.push("L", curr.x, curr.y);
|
|
258109
|
+
}
|
|
258110
|
+
}
|
|
258111
|
+
if (closed) {
|
|
258112
|
+
const prev = points[points.length - 1];
|
|
258113
|
+
const curr = points[0];
|
|
258114
|
+
if (prev.handleOut && curr.handleIn) {
|
|
258115
|
+
data.push("C", prev.handleOut.x, prev.handleOut.y, curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
258116
|
+
} else if (prev.handleOut) {
|
|
258117
|
+
data.push("Q", prev.handleOut.x, prev.handleOut.y, curr.x, curr.y);
|
|
258118
|
+
} else if (curr.handleIn) {
|
|
258119
|
+
data.push("Q", curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
258120
|
+
}
|
|
258121
|
+
data.push("Z");
|
|
258122
|
+
}
|
|
258123
|
+
return data;
|
|
258124
|
+
}
|
|
258125
|
+
function scaleSubtreePatches(nodes, id3, sx, sy, includeSelf = true) {
|
|
258126
|
+
const out = /* @__PURE__ */ new Map();
|
|
258127
|
+
const root2 = nodes[id3];
|
|
258128
|
+
if (!root2 || sx === 1 && sy === 1) return out;
|
|
258129
|
+
if (includeSelf && root2.type === "VECTOR") out.set(id3, { paths: scaleVectorPaths(root2.paths, sx, sy, rebuildVectorData) });
|
|
258130
|
+
const walk4 = (parent) => {
|
|
258131
|
+
for (const cid of parent.childIds ?? []) {
|
|
258132
|
+
const c2 = nodes[cid];
|
|
258133
|
+
if (!c2) continue;
|
|
258134
|
+
const patch2 = { ...scaledChildProps(c2, sx, sy, rebuildVectorData) };
|
|
258135
|
+
if (c2.type === "TEXT") patch2.fontSize = (c2.fontSize ?? 16) * Math.min(sx, sy);
|
|
258136
|
+
out.set(cid, patch2);
|
|
258137
|
+
walk4(c2);
|
|
258138
|
+
}
|
|
258139
|
+
};
|
|
258140
|
+
if (root2.type === "GROUP" || root2.type === "BOOLEAN" || !includeSelf) walk4(root2);
|
|
258141
|
+
return out;
|
|
258142
|
+
}
|
|
258015
258143
|
var scalePoint;
|
|
258016
258144
|
var init_scale_geometry = __esm({
|
|
258017
258145
|
"lib/document/scale-geometry.ts"() {
|
|
@@ -262651,7 +262779,6 @@ function formatLimit(key5, max3) {
|
|
|
262651
262779
|
var formatBytes;
|
|
262652
262780
|
var init_limits2 = __esm({
|
|
262653
262781
|
"lib/billing/limits.ts"() {
|
|
262654
|
-
"use strict";
|
|
262655
262782
|
init_format();
|
|
262656
262783
|
init_plans();
|
|
262657
262784
|
formatBytes = formatFileSize;
|
|
@@ -310254,6 +310381,7 @@ function importSVGFile(file2, document2, parentId) {
|
|
|
310254
310381
|
var ENTITIES, decode3, I, mul2, apply2, scaleOf, NUM2, nums, near, NAMED, INHERITED, PRESENTATION, len2, CAP, JOIN, SKIPPED, refId;
|
|
310255
310382
|
var init_svg_import = __esm({
|
|
310256
310383
|
"lib/io/svg-import.ts"() {
|
|
310384
|
+
"use strict";
|
|
310257
310385
|
init_dist_node();
|
|
310258
310386
|
init_types();
|
|
310259
310387
|
ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: "\xA0" };
|
|
@@ -311857,7 +311985,6 @@ async function dispatchShaped(key5, options) {
|
|
|
311857
311985
|
var onViolation;
|
|
311858
311986
|
var init_dispatch = __esm({
|
|
311859
311987
|
"lib/commands/dispatch.ts"() {
|
|
311860
|
-
"use strict";
|
|
311861
311988
|
init_errors();
|
|
311862
311989
|
init_registry();
|
|
311863
311990
|
init_confirm();
|
|
@@ -312919,7 +313046,6 @@ function applyTextPath(layout2, path, tp, rebase = true) {
|
|
|
312919
313046
|
var defaultCircleRadius, ownsPath, mapPoint;
|
|
312920
313047
|
var init_text_path = __esm({
|
|
312921
313048
|
"lib/engine/text/text-path.ts"() {
|
|
312922
|
-
"use strict";
|
|
312923
313049
|
init_scene_graph();
|
|
312924
313050
|
init_transform();
|
|
312925
313051
|
init_shape_to_path();
|
|
@@ -315574,12 +315700,12 @@ function textStrokeSVG(node2) {
|
|
|
315574
315700
|
const w = Array.isArray(stroke3.width) ? Math.max(...stroke3.width) : stroke3.width;
|
|
315575
315701
|
if (!(w > 0)) return null;
|
|
315576
315702
|
const behind = strokeBehindFill(node2) || stroke3.alignment === "OUTSIDE";
|
|
315577
|
-
const
|
|
315578
|
-
if (
|
|
315703
|
+
const inside3 = stroke3.alignment === "INSIDE";
|
|
315704
|
+
if (inside3 && behind) return null;
|
|
315579
315705
|
const alpha2 = (stroke3.color.a ?? 1) * (stroke3.opacity ?? 1);
|
|
315580
315706
|
const join13 = stroke3.join === "ROUND" ? "round" : stroke3.join === "BEVEL" ? "bevel" : "miter";
|
|
315581
315707
|
const attrs = `stroke="${colorToSVG(stroke3.color)}"${alpha2 < 1 ? ` stroke-opacity="${fmt2(alpha2)}"` : ""} stroke-width="${fmt2(stroke3.alignment === "CENTER" ? w : w * 2)}" stroke-linejoin="${join13}"${behind ? ' paint-order="stroke fill"' : ""}`;
|
|
315582
|
-
return { attrs, behind, inside:
|
|
315708
|
+
return { attrs, behind, inside: inside3 };
|
|
315583
315709
|
}
|
|
315584
315710
|
function textFillAttr(resolved, node2, ctx2) {
|
|
315585
315711
|
const fill0 = resolved.fills?.[0];
|
|
@@ -316503,12 +316629,12 @@ Q
|
|
|
316503
316629
|
};
|
|
316504
316630
|
const paintStrokes = () => {
|
|
316505
316631
|
for (const s of item.strokes) {
|
|
316506
|
-
const
|
|
316507
|
-
const wdt =
|
|
316632
|
+
const inside3 = s.alignment === "INSIDE";
|
|
316633
|
+
const wdt = inside3 ? s.width * 2 : s.width;
|
|
316508
316634
|
this.w(`q /${this.gs(1, opacity * s.alpha, blend2)} gs ${this.res.color.stroke(s.color)} ${num7(wdt)} w ${CAP2[s.cap]} J ${JOIN2[s.join]} j`);
|
|
316509
316635
|
this.w(s.dash ? ` [${num7(s.dash[0])} ${num7(s.dash[1])}] 0 d
|
|
316510
316636
|
` : " [] 0 d\n");
|
|
316511
|
-
if (
|
|
316637
|
+
if (inside3) this.w(`${ops2}${clipOp} n
|
|
316512
316638
|
`);
|
|
316513
316639
|
this.w(`${ops2}S
|
|
316514
316640
|
Q
|
|
@@ -316681,8 +316807,8 @@ function removeOverlaps(cmds) {
|
|
|
316681
316807
|
break;
|
|
316682
316808
|
}
|
|
316683
316809
|
if (!touching) return cmds;
|
|
316684
|
-
const pos = rings.filter((r) =>
|
|
316685
|
-
const clip =
|
|
316810
|
+
const pos = rings.filter((r) => signedArea2(r) > 0).map((r) => [r]), neg = rings.filter((r) => signedArea2(r) < 0).map((r) => [r]);
|
|
316811
|
+
const clip = import_polygon_clipping7.default;
|
|
316686
316812
|
let result;
|
|
316687
316813
|
try {
|
|
316688
316814
|
const a = pos.length ? clip.union(...pos) : [], b = neg.length ? clip.union(...neg) : [];
|
|
@@ -316795,12 +316921,12 @@ function buildCFF(name2, unitsPerEm, glyphs) {
|
|
|
316795
316921
|
}
|
|
316796
316922
|
return out;
|
|
316797
316923
|
}
|
|
316798
|
-
var
|
|
316924
|
+
var import_polygon_clipping7, signedArea2, bbox, intersects;
|
|
316799
316925
|
var init_cff = __esm({
|
|
316800
316926
|
"lib/io/pdf/cff.ts"() {
|
|
316801
316927
|
"use strict";
|
|
316802
|
-
|
|
316803
|
-
|
|
316928
|
+
import_polygon_clipping7 = __toESM(require_polygon_clipping_cjs());
|
|
316929
|
+
signedArea2 = (p2) => p2.reduce((a, [x2, y], i2) => {
|
|
316804
316930
|
const [nx, ny] = p2[(i2 + 1) % p2.length];
|
|
316805
316931
|
return a + x2 * ny - nx * y;
|
|
316806
316932
|
}, 0) / 2;
|
|
@@ -317473,7 +317599,6 @@ async function selectionReferenceImages(doc2, selection, opts = {}) {
|
|
|
317473
317599
|
var FIT_QUALITIES, FIT_SCALES, blobToDataUrl;
|
|
317474
317600
|
var init_reference_images = __esm({
|
|
317475
317601
|
"lib/ai/reference-images.ts"() {
|
|
317476
|
-
"use strict";
|
|
317477
317602
|
init_export();
|
|
317478
317603
|
init_selection_bounds();
|
|
317479
317604
|
init_renderer_registry();
|
|
@@ -318354,6 +318479,7 @@ __export(tools_exports, {
|
|
|
318354
318479
|
allTools: () => allTools,
|
|
318355
318480
|
defineTool: () => defineTool,
|
|
318356
318481
|
getTool: () => getTool,
|
|
318482
|
+
parseToolArgs: () => parseToolArgs,
|
|
318357
318483
|
registerTools: () => registerTools,
|
|
318358
318484
|
runTool: () => runTool,
|
|
318359
318485
|
toolSpecs: () => toolSpecs
|
|
@@ -318374,14 +318500,53 @@ function toolSpecs(names) {
|
|
|
318374
318500
|
function: { name: t3.name, description: t3.description, parameters: toolParameters(t3.parameters) }
|
|
318375
318501
|
}));
|
|
318376
318502
|
}
|
|
318503
|
+
function parseToolArgs(text) {
|
|
318504
|
+
try {
|
|
318505
|
+
return JSON.parse(text);
|
|
318506
|
+
} catch {
|
|
318507
|
+
}
|
|
318508
|
+
let depth = 0, inStr = false, esc3 = false;
|
|
318509
|
+
const stack = [];
|
|
318510
|
+
for (let i2 = 0; i2 < text.length; i2++) {
|
|
318511
|
+
const c2 = text[i2];
|
|
318512
|
+
if (inStr) {
|
|
318513
|
+
if (esc3) esc3 = false;
|
|
318514
|
+
else if (c2 === "\\") esc3 = true;
|
|
318515
|
+
else if (c2 === '"') inStr = false;
|
|
318516
|
+
continue;
|
|
318517
|
+
}
|
|
318518
|
+
if (c2 === '"') inStr = true;
|
|
318519
|
+
else if (c2 === "{" || c2 === "[") {
|
|
318520
|
+
stack.push(c2 === "{" ? "}" : "]");
|
|
318521
|
+
depth++;
|
|
318522
|
+
} else if (c2 === "}" || c2 === "]") {
|
|
318523
|
+
stack.pop();
|
|
318524
|
+
depth--;
|
|
318525
|
+
if (depth === 0) {
|
|
318526
|
+
try {
|
|
318527
|
+
return JSON.parse(text.slice(0, i2 + 1));
|
|
318528
|
+
} catch {
|
|
318529
|
+
return void 0;
|
|
318530
|
+
}
|
|
318531
|
+
}
|
|
318532
|
+
}
|
|
318533
|
+
}
|
|
318534
|
+
if (!stack.length) return void 0;
|
|
318535
|
+
try {
|
|
318536
|
+
return JSON.parse(text + (inStr ? '"' : "") + stack.reverse().join(""));
|
|
318537
|
+
} catch {
|
|
318538
|
+
return void 0;
|
|
318539
|
+
}
|
|
318540
|
+
}
|
|
318377
318541
|
async function runTool(name2, argsText, ctx2) {
|
|
318378
318542
|
let raw = {};
|
|
318379
318543
|
if (argsText.trim()) {
|
|
318380
|
-
|
|
318381
|
-
|
|
318382
|
-
|
|
318383
|
-
throw new ToolError(`The arguments for ${name2} were not valid JSON.`, "invalid_params");
|
|
318544
|
+
const parsed2 = parseToolArgs(argsText);
|
|
318545
|
+
if (parsed2 === void 0) {
|
|
318546
|
+
console.warn(`[agent] unparseable arguments for ${name2}:`, argsText.slice(0, 500));
|
|
318547
|
+
throw new ToolError(`The arguments for ${name2} were not valid JSON. Send one JSON object.`, "invalid_params");
|
|
318384
318548
|
}
|
|
318549
|
+
raw = parsed2;
|
|
318385
318550
|
}
|
|
318386
318551
|
return dispatch2(name2, {
|
|
318387
318552
|
surface: "agent",
|
|
@@ -319099,16 +319264,28 @@ function placeSvgLayers(doc2, parentId, svg, place4) {
|
|
|
319099
319264
|
if (n.type === "IMAGE" && !doc2.nodes[n.id] && url4?.startsWith("data:")) nodes[n.id] = { ...n, imageUrl: place4.intern(url4) };
|
|
319100
319265
|
}
|
|
319101
319266
|
}
|
|
319102
|
-
const minX = Math.min(...kids.map((
|
|
319103
|
-
const maxX = Math.max(...kids.map((
|
|
319104
|
-
for (const
|
|
319105
|
-
|
|
319106
|
-
|
|
319267
|
+
const minX = Math.min(...kids.map((k3) => k3.x)), minY = Math.min(...kids.map((k3) => k3.y));
|
|
319268
|
+
const maxX = Math.max(...kids.map((k3) => k3.x + k3.width)), maxY = Math.max(...kids.map((k3) => k3.y + k3.height));
|
|
319269
|
+
for (const k3 of kids) nodes[k3.id] = { ...nodes[k3.id], x: k3.x - minX, y: k3.y - minY };
|
|
319270
|
+
let w = Math.max(1, maxX - minX), h = Math.max(1, maxY - minY);
|
|
319271
|
+
const f2 = place4.fit;
|
|
319272
|
+
const k2 = f2 && (f2.width || f2.height) ? Math.min(f2.width ? f2.width / w : Infinity, f2.height ? f2.height / h : Infinity) : 1;
|
|
319273
|
+
if (k2 !== 1 && Number.isFinite(k2) && k2 > 0) {
|
|
319274
|
+
const wrapper = { childIds: kids.map((c2) => c2.id) };
|
|
319275
|
+
for (const [id3, patch2] of scaleSubtreePatches({ ...nodes, [frame3.id]: { ...nodes[frame3.id], ...wrapper } }, frame3.id, k2, k2, false)) {
|
|
319276
|
+
nodes[id3] = { ...nodes[id3], ...patch2 };
|
|
319277
|
+
}
|
|
319278
|
+
w *= k2;
|
|
319279
|
+
h *= k2;
|
|
319280
|
+
}
|
|
319281
|
+
const topLeft = place4.anchor === "top-left";
|
|
319282
|
+
nodes[frame3.id] = { ...nodes[frame3.id], x: Math.round(topLeft ? place4.cx : place4.cx - w / 2), y: Math.round(topLeft ? place4.cy : place4.cy - h / 2), width: w, height: h };
|
|
319107
319283
|
return { doc: { ...next2, nodes }, id: frame3.id };
|
|
319108
319284
|
}
|
|
319109
319285
|
var MAX_SVG_LAYER_BYTES;
|
|
319110
319286
|
var init_svg_place = __esm({
|
|
319111
319287
|
"lib/io/svg-place.ts"() {
|
|
319288
|
+
init_scale_geometry();
|
|
319112
319289
|
init_scene_graph();
|
|
319113
319290
|
init_svg_import();
|
|
319114
319291
|
MAX_SVG_LAYER_BYTES = 8 * 1024 * 1024;
|
|
@@ -319128,6 +319305,31 @@ function descendants(doc2, rootId, skipRoot = true) {
|
|
|
319128
319305
|
}
|
|
319129
319306
|
return out;
|
|
319130
319307
|
}
|
|
319308
|
+
function normalizeColor(c2, key5) {
|
|
319309
|
+
if (typeof c2 === "string") return parseHex(c2);
|
|
319310
|
+
const o = c2;
|
|
319311
|
+
const ch = o && ["r", "g", "b"].map((k2) => o[k2]);
|
|
319312
|
+
if (!ch || !ch.every((v) => typeof v === "number" && Number.isFinite(v))) {
|
|
319313
|
+
throw new ToolError(`${key5} has a colour without numeric r, g and b. Give 0\u20131 channels, or use set_fills with a hex colour.`);
|
|
319314
|
+
}
|
|
319315
|
+
const nums2 = ch;
|
|
319316
|
+
const scale = nums2.some((v) => v > 1) ? 255 : 1;
|
|
319317
|
+
const a = typeof o.a === "number" && Number.isFinite(o.a) ? o.a > 1 ? o.a / 255 : o.a : 1;
|
|
319318
|
+
return createColor(nums2[0] / scale, nums2[1] / scale, nums2[2] / scale, a);
|
|
319319
|
+
}
|
|
319320
|
+
function normalizePaints(v, key5) {
|
|
319321
|
+
if (!Array.isArray(v)) throw new ToolError(`${key5} must be an array of paints.`);
|
|
319322
|
+
return v.map((p2) => {
|
|
319323
|
+
const paint = p2;
|
|
319324
|
+
if (!paint || typeof paint !== "object") throw new ToolError(`${key5} must be an array of paint objects.`);
|
|
319325
|
+
const out = { ...paint };
|
|
319326
|
+
if ("color" in paint) out.color = normalizeColor(paint.color, key5);
|
|
319327
|
+
if (Array.isArray(paint.gradientStops)) {
|
|
319328
|
+
out.gradientStops = paint.gradientStops.map((s) => ({ ...s, color: normalizeColor(s.color, key5) }));
|
|
319329
|
+
}
|
|
319330
|
+
return out;
|
|
319331
|
+
});
|
|
319332
|
+
}
|
|
319131
319333
|
var nodeFind, nodeGet, nodeMeasure, docOutline, CREATABLE, nodeCreate, FORBIDDEN_PROPS, nodeUpdate, nodeDelete, nodeMove, nodeResize, nodeReparent, nodeGroup, nodeUngroup, nodeOrder, nodeAlign, nodeDistribute, nodeRename, nodeDuplicate, nodeImportSvg, nodeApplyAutoLayout, nodeSetLock, nodeSetVisibility, nodeFlip, nodeRotate;
|
|
319132
319334
|
var init_node = __esm({
|
|
319133
319335
|
"lib/commands/node.ts"() {
|
|
@@ -319140,6 +319342,7 @@ var init_node = __esm({
|
|
|
319140
319342
|
init_scene_graph();
|
|
319141
319343
|
init_types();
|
|
319142
319344
|
init_errors();
|
|
319345
|
+
init_scale_geometry();
|
|
319143
319346
|
init_plugin_shim();
|
|
319144
319347
|
init_types5();
|
|
319145
319348
|
init_ui();
|
|
@@ -319474,7 +319677,7 @@ var init_node = __esm({
|
|
|
319474
319677
|
for (const [k2, v] of Object.entries(u.props)) {
|
|
319475
319678
|
if (args2.strict && FORBIDDEN_PROPS.has(k2)) throw new ToolError(`update_nodes cannot change "${k2}". Use reparent, delete_nodes or create_node instead.`);
|
|
319476
319679
|
if (FORBIDDEN_PROPS.has(k2) || v === void 0) continue;
|
|
319477
|
-
patch2[k2] = v;
|
|
319680
|
+
patch2[k2] = k2 === "fills" || k2 === "strokes" ? normalizePaints(v, k2) : v;
|
|
319478
319681
|
changedKeys.add(k2);
|
|
319479
319682
|
}
|
|
319480
319683
|
if (args2.strict && !Object.keys(patch2).length) throw new ToolError(`No properties given for "${u.id}".`);
|
|
@@ -319589,9 +319792,21 @@ var init_node = __esm({
|
|
|
319589
319792
|
const n = doc2.nodes[id3];
|
|
319590
319793
|
const w = args2.width ?? (args2.scale ? n.width * args2.scale : n.width);
|
|
319591
319794
|
const h = args2.height ?? (args2.scale ? n.height * args2.scale : n.height);
|
|
319592
|
-
|
|
319795
|
+
const width = Math.max(AI_LIMITS.minSize, w), height = Math.max(AI_LIMITS.minSize, h);
|
|
319796
|
+
patches.set(id3, { width, height });
|
|
319797
|
+
if (n.width <= 0 || n.height <= 0) continue;
|
|
319798
|
+
for (const [pid, patch2] of scaleSubtreePatches(doc2.nodes, id3, width / n.width, height / n.height)) {
|
|
319799
|
+
patches.set(pid, { ...patches.get(pid), ...patch2 });
|
|
319800
|
+
}
|
|
319593
319801
|
}
|
|
319594
|
-
|
|
319802
|
+
let next2 = doc2;
|
|
319803
|
+
for (const id3 of ids2) {
|
|
319804
|
+
const n = doc2.nodes[id3], p2 = patches.get(id3);
|
|
319805
|
+
if (n.type === "FRAME" || n.type === "COMPONENT" || n.type === "SECTION") {
|
|
319806
|
+
next2 = applyConstraints(next2, id3, n.width, n.height, p2.width, p2.height);
|
|
319807
|
+
}
|
|
319808
|
+
}
|
|
319809
|
+
commitUpdates(ctx2, next2, patches);
|
|
319595
319810
|
return { summary: `Resized ${plural2(ids2.length, "layer")}`, data: { ids: ids2 } };
|
|
319596
319811
|
}
|
|
319597
319812
|
});
|
|
@@ -319928,6 +320143,9 @@ var init_node = __esm({
|
|
|
319928
320143
|
svg: external_exports.string().min(8).optional().describe("The full <svg>\u2026</svg> markup."),
|
|
319929
320144
|
parentId: external_exports.string().optional(),
|
|
319930
320145
|
at: external_exports.object({ x: external_exports.number(), y: external_exports.number() }).optional().describe("Place the layers in one frame centred on this point (parent coordinates) instead of at the SVG's own coordinates."),
|
|
320146
|
+
anchor: external_exports.enum(["center", "top-left"]).optional().describe("Whether `at` is the frame's centre (default) or its top-left corner."),
|
|
320147
|
+
width: external_exports.number().positive().optional().describe("With `at`: scale the artwork to fit this width (keeps proportions)."),
|
|
320148
|
+
height: external_exports.number().positive().optional().describe("With `at`: scale the artwork to fit this height (keeps proportions)."),
|
|
319931
320149
|
name: external_exports.string().max(200).optional().describe("Name of that frame (with `at`)."),
|
|
319932
320150
|
more: external_exports.array(external_exports.object({ svg: external_exports.string().min(8), name: external_exports.string().max(200).optional() })).max(50).optional().describe("Further SVGs placed in the same step (with `at`), each 24 px further down and right.")
|
|
319933
320151
|
}),
|
|
@@ -319935,7 +320153,7 @@ var init_node = __esm({
|
|
|
319935
320153
|
plugin: { method: "importSvg" },
|
|
319936
320154
|
agent: {
|
|
319937
320155
|
name: "import_svg",
|
|
319938
|
-
description:
|
|
320156
|
+
description: 'Import SVG markup as editable layers under a parent (default: the current page). Pass `at` (in the PARENT\'s coordinates) to place them in one frame centred on that point, or with its top-left there when anchor is "top-left"; add width and/or height to scale the artwork to fit that box. Returns the ids of the new top-level layers.'
|
|
319939
320157
|
},
|
|
319940
320158
|
// Paste, drop and File › Import: one undo step, and the ones that would not convert reported back so the
|
|
319941
320159
|
// caller can place them as pictures instead (lib/editor/svg-paste.ts).
|
|
@@ -319953,7 +320171,7 @@ var init_node = __esm({
|
|
|
319953
320171
|
const added2 = [];
|
|
319954
320172
|
const failed2 = [];
|
|
319955
320173
|
items.forEach((item, i2) => {
|
|
319956
|
-
const placed2 = placeSvgLayers2(next3, parentId, item.svg, { name: item.name || "SVG", cx: args2.at.x + i2 * 24, cy: args2.at.y + i2 * 24, intern: (url4) => internDataUrl2(url4) });
|
|
320174
|
+
const placed2 = placeSvgLayers2(next3, parentId, item.svg, { name: item.name || "SVG", cx: args2.at.x + i2 * 24, cy: args2.at.y + i2 * 24, anchor: args2.anchor, fit: { width: args2.width, height: args2.height }, intern: (url4) => internDataUrl2(url4) });
|
|
319957
320175
|
if (placed2) {
|
|
319958
320176
|
next3 = placed2.doc;
|
|
319959
320177
|
added2.push(placed2.id);
|
|
@@ -320948,7 +321166,8 @@ var init_paint = __esm({
|
|
|
320948
321166
|
const rec = n;
|
|
320949
321167
|
const patch2 = {};
|
|
320950
321168
|
let hit = 0;
|
|
320951
|
-
const
|
|
321169
|
+
const fillStyle = rec.fillStyleId ? doc2.styles?.[rec.fillStyleId] : void 0;
|
|
321170
|
+
const paints = fillStyle?.type === "PAINT" ? fillStyle.paints : rec.fills;
|
|
320952
321171
|
if (paints?.length) {
|
|
320953
321172
|
let changed = false;
|
|
320954
321173
|
const next2 = paints.map((p2) => {
|
|
@@ -320975,7 +321194,10 @@ var init_paint = __esm({
|
|
|
320975
321194
|
}
|
|
320976
321195
|
return out;
|
|
320977
321196
|
});
|
|
320978
|
-
if (changed)
|
|
321197
|
+
if (changed) {
|
|
321198
|
+
patch2.fills = next2;
|
|
321199
|
+
if (rec.fillStyleId) patch2.fillStyleId = void 0;
|
|
321200
|
+
}
|
|
320979
321201
|
}
|
|
320980
321202
|
const strokes = rec.strokes;
|
|
320981
321203
|
if (strokes?.length) {
|
|
@@ -320987,7 +321209,10 @@ var init_paint = __esm({
|
|
|
320987
321209
|
hit++;
|
|
320988
321210
|
return { ...s, color: c2 };
|
|
320989
321211
|
});
|
|
320990
|
-
if (changed)
|
|
321212
|
+
if (changed) {
|
|
321213
|
+
patch2.strokes = next2;
|
|
321214
|
+
if (rec.strokeStyleId) patch2.strokeStyleId = void 0;
|
|
321215
|
+
}
|
|
320991
321216
|
}
|
|
320992
321217
|
const effects = effectsOf(n);
|
|
320993
321218
|
if (effects.length) {
|
|
@@ -321018,7 +321243,7 @@ var init_paint = __esm({
|
|
|
321018
321243
|
}
|
|
321019
321244
|
}
|
|
321020
321245
|
if (!swaps) throw new ToolError(`No ${args2.from} found under ${args2.rootId ?? "the selection"}. Check the color with get_node, or raise "tolerance".`);
|
|
321021
|
-
ctx2.commit({ ...doc2, nodes });
|
|
321246
|
+
ctx2.commit(applyInvariants({ ...doc2, nodes }, touched));
|
|
321022
321247
|
return { summary: `Replaced ${args2.from} with ${args2.to} in ${plural2(touched.length, "layer")} (${swaps} paints)`, data: { ids: touched.slice(0, 50), swaps } };
|
|
321023
321248
|
}
|
|
321024
321249
|
});
|
|
@@ -328471,7 +328696,7 @@ var init_package = __esm({
|
|
|
328471
328696
|
"packages/runtime/package.json"() {
|
|
328472
328697
|
package_default = {
|
|
328473
328698
|
name: "@popcraft/runtime",
|
|
328474
|
-
version: "0.53.
|
|
328699
|
+
version: "0.53.2",
|
|
328475
328700
|
description: "What code exported from PopCraft shares: the meaning of expressions (operators and functions) and, as it grows, the parts of a design's behaviour that are common code rather than generated React.",
|
|
328476
328701
|
license: "MIT",
|
|
328477
328702
|
homepage: "https://popcraft.app/docs/exporting/nextjs",
|
|
@@ -353179,6 +353404,7 @@ function compileModule(module2) {
|
|
|
353179
353404
|
var import_sucrase, BUILT_IN, memo4;
|
|
353180
353405
|
var init_compile2 = __esm({
|
|
353181
353406
|
"lib/code/compile.ts"() {
|
|
353407
|
+
"use strict";
|
|
353182
353408
|
import_sucrase = __toESM(require_dist2());
|
|
353183
353409
|
init_source2();
|
|
353184
353410
|
init_source2();
|
|
@@ -355184,7 +355410,7 @@ function reading(doc2, ids2) {
|
|
|
355184
355410
|
}
|
|
355185
355411
|
function boardColumns(doc2, roots, looseTitle, within3) {
|
|
355186
355412
|
const areas = within3?.map((n) => boxOf(doc2, n));
|
|
355187
|
-
const wanted = (p2) => !areas || areas.some((a) =>
|
|
355413
|
+
const wanted = (p2) => !areas || areas.some((a) => inside2(p2, a));
|
|
355188
355414
|
const cards = [];
|
|
355189
355415
|
const boxes = [];
|
|
355190
355416
|
const texts = [];
|
|
@@ -355215,7 +355441,7 @@ function boardColumns(doc2, roots, looseTitle, within3) {
|
|
|
355215
355441
|
const band = b.box.minY + (b.box.maxY - b.box.minY) * 0.25;
|
|
355216
355442
|
const top = texts.filter((t3) => {
|
|
355217
355443
|
const c2 = centre(t3.box);
|
|
355218
|
-
return
|
|
355444
|
+
return inside2(c2, b.box) && c2.y <= band;
|
|
355219
355445
|
}).sort((x2, y) => x2.box.minY - y.box.minY)[0];
|
|
355220
355446
|
if (top) titles.set(b.node.id, { text: top.text, id: top.id });
|
|
355221
355447
|
else if (!DEFAULT_NAMES.test(b.node.name.trim())) titles.set(b.node.id, { text: b.node.name });
|
|
@@ -355223,7 +355449,7 @@ function boardColumns(doc2, roots, looseTitle, within3) {
|
|
|
355223
355449
|
const columnAt = (p2) => {
|
|
355224
355450
|
let best = null;
|
|
355225
355451
|
for (const b of boxes) {
|
|
355226
|
-
if (!
|
|
355452
|
+
if (!inside2(p2, b.box)) continue;
|
|
355227
355453
|
if (!best) {
|
|
355228
355454
|
best = b;
|
|
355229
355455
|
continue;
|
|
@@ -355266,7 +355492,7 @@ function boardCsv(columns) {
|
|
|
355266
355492
|
const rows = Math.max(0, ...columns.map((c2) => c2.items.length));
|
|
355267
355493
|
return toCsv([columns.map((c2) => c2.title), ...Array.from({ length: rows }, (_, i2) => columns.map((c2) => c2.items[i2] ?? ""))]);
|
|
355268
355494
|
}
|
|
355269
|
-
var MARGIN, MAX_BOARD_EXPORT_PX, textOf, boxOf, centre,
|
|
355495
|
+
var MARGIN, MAX_BOARD_EXPORT_PX, textOf, boxOf, centre, inside2, area3, textLayer, COLUMN_TYPES;
|
|
355270
355496
|
var init_board_export = __esm({
|
|
355271
355497
|
"lib/popcorn/board-export.ts"() {
|
|
355272
355498
|
init_scene_graph();
|
|
@@ -355276,7 +355502,7 @@ var init_board_export = __esm({
|
|
|
355276
355502
|
textOf = (n) => (n.text ?? "").replace(/\s+/g, " ").trim();
|
|
355277
355503
|
boxOf = (doc2, n) => uprightBounds(getWorldTransform(doc2, n.id), n.width, n.height);
|
|
355278
355504
|
centre = (b) => ({ x: (b.minX + b.maxX) / 2, y: (b.minY + b.maxY) / 2 });
|
|
355279
|
-
|
|
355505
|
+
inside2 = (p2, b) => p2.x >= b.minX && p2.x <= b.maxX && p2.y >= b.minY && p2.y <= b.maxY;
|
|
355280
355506
|
area3 = (b) => (b.maxX - b.minX) * (b.maxY - b.minY);
|
|
355281
355507
|
textLayer = (n) => n.type === "TEXT" ? (n.characters ?? "").replace(/\s+/g, " ").trim() : "";
|
|
355282
355508
|
COLUMN_TYPES = /* @__PURE__ */ new Set(["FRAME", "SECTION", "GROUP", "RECTANGLE", "INSTANCE", "COMPONENT", "ELLIPSE"]);
|
|
@@ -358625,11 +358851,11 @@ function mapCompilerMessages(messages, offset, lines2) {
|
|
|
358625
358851
|
for (const m of messages) {
|
|
358626
358852
|
if (m.type !== "error" && m.type !== "warning") continue;
|
|
358627
358853
|
const line = m.lineNum - offset;
|
|
358628
|
-
const
|
|
358854
|
+
const inside3 = m.lineNum > 0 && line >= 1 && line <= lines2;
|
|
358629
358855
|
out.push({
|
|
358630
|
-
line:
|
|
358631
|
-
column:
|
|
358632
|
-
message:
|
|
358856
|
+
line: inside3 ? line : null,
|
|
358857
|
+
column: inside3 && m.linePos > 0 ? m.linePos : null,
|
|
358858
|
+
message: inside3 ? m.message : harnessMessage(m.message),
|
|
358633
358859
|
severity: m.type === "error" ? "error" : "warning"
|
|
358634
358860
|
});
|
|
358635
358861
|
}
|
|
@@ -359144,9 +359370,9 @@ var init_motion_rich = __esm({
|
|
|
359144
359370
|
if (def.type !== "NUMBER" && def.type !== "COLOR" && def.type !== "IMAGE") throw new ToolError("Only a NUMBER, COLOR or IMAGE property feeds a layer input.");
|
|
359145
359371
|
const layer2 = nodeOrThrow(doc2, op4.layer);
|
|
359146
359372
|
const owner = target2.type === "COMPONENT_SET" ? target2.id : target2.id;
|
|
359147
|
-
let
|
|
359148
|
-
for (let n = layer2; n; n = n.parentId ? doc2.nodes[n.parentId] : void 0) if (n.id === owner)
|
|
359149
|
-
if (!
|
|
359373
|
+
let inside3 = false;
|
|
359374
|
+
for (let n = layer2; n; n = n.parentId ? doc2.nodes[n.parentId] : void 0) if (n.id === owner) inside3 = true;
|
|
359375
|
+
if (!inside3 || layer2.id === owner) throw new ToolError(`"${layer2.name}" is not a layer inside "${target2.name}".`);
|
|
359150
359376
|
const props = layerInputPatch(layer2, op4.name, op4.path);
|
|
359151
359377
|
if (!props) throw new ToolError(`"${layer2.name}" has no ${op4.path}.`);
|
|
359152
359378
|
commitUpdates(ctx2, doc2, /* @__PURE__ */ new Map([[layer2.id, props]]));
|
|
@@ -361276,7 +361502,14 @@ var init_media = __esm({
|
|
|
361276
361502
|
},
|
|
361277
361503
|
run: async (args2) => {
|
|
361278
361504
|
const { listLibraryMedia: listLibraryMedia2 } = await Promise.resolve().then(() => (init_client5(), client_exports3));
|
|
361279
|
-
const
|
|
361505
|
+
const q = { ...args2 };
|
|
361506
|
+
if (!q.workspace) {
|
|
361507
|
+
const { syncStatus: syncStatus2 } = await Promise.resolve().then(() => (init_sync2(), sync_exports2));
|
|
361508
|
+
const link2 = syncStatus2().link;
|
|
361509
|
+
if (!link2) throw new ToolError("This document is not saved to the cloud, so it has no team media library. Pass workspace.");
|
|
361510
|
+
q.workspace = (await listLibraryMedia2({ file: link2.key, limit: 1 })).workspaceId;
|
|
361511
|
+
}
|
|
361512
|
+
const page = await listLibraryMedia2(q);
|
|
361280
361513
|
return { summary: `${page.items.length} media item${page.items.length === 1 ? "" : "s"}${page.nextCursor ? " (more)" : ""}`, data: { workspaceId: page.workspaceId, items: page.items.map(brief3), nextCursor: page.nextCursor } };
|
|
361281
361514
|
}
|
|
361282
361515
|
});
|
|
@@ -362221,7 +362454,6 @@ var init_delete_current_file = __esm({
|
|
|
362221
362454
|
var storeOpsSeam;
|
|
362222
362455
|
var init_seams = __esm({
|
|
362223
362456
|
"lib/commands/seams.ts"() {
|
|
362224
|
-
"use strict";
|
|
362225
362457
|
storeOpsSeam = (st) => ({
|
|
362226
362458
|
booleanOperation: (op4) => st().booleanOperation(op4),
|
|
362227
362459
|
flatten: () => st().flattenSelection(),
|
|
@@ -401852,6 +402084,10 @@ async function drive(meta3, start2) {
|
|
|
401852
402084
|
return [...notes, ...runtime.drainParentNotifications()];
|
|
401853
402085
|
},
|
|
401854
402086
|
maxParallel: MAX_PARALLEL_TOOLS,
|
|
402087
|
+
// The loop's default cut every result at 8000 characters AFTER the tool had honoured its own limit, so
|
|
402088
|
+
// export_svg with maxChars 40000 still came back without its last paths and the model could not
|
|
402089
|
+
// rebuild the artwork. Tools bound their own output; this is only the backstop.
|
|
402090
|
+
maxResultChars: MAX_TOOL_RESULT_CHARS,
|
|
401855
402091
|
maxRounds: TURN_MAX_ROUNDS,
|
|
401856
402092
|
modelRetries: 3,
|
|
401857
402093
|
isRecoverable: (err2) => !abort.signal.aborted && isInterruption(err2),
|
|
@@ -401977,7 +402213,7 @@ async function drive(meta3, start2) {
|
|
|
401977
402213
|
useAgentStore.setState({ running: false, resuming: false, abort: null });
|
|
401978
402214
|
}
|
|
401979
402215
|
}
|
|
401980
|
-
var ALWAYS_ALLOWED, MAX_HISTORY_MESSAGES, MAX_PARALLEL_TOOLS, TURN_MAX_ROUNDS, registerTurnTools, specsFor, loopTools, runs, agentRuns, setAgentRuns, RESUME_WINDOW_MS, MAX_INTERRUPTIONS, SUSPEND_RESTART_MS, STOPPED_MESSAGE;
|
|
402216
|
+
var ALWAYS_ALLOWED, MAX_HISTORY_MESSAGES, MAX_PARALLEL_TOOLS, MAX_TOOL_RESULT_CHARS, TURN_MAX_ROUNDS, registerTurnTools, specsFor, loopTools, runs, agentRuns, setAgentRuns, RESUME_WINDOW_MS, MAX_INTERRUPTIONS, SUSPEND_RESTART_MS, STOPPED_MESSAGE;
|
|
401981
402217
|
var init_runner = __esm({
|
|
401982
402218
|
"lib/agent/runner.ts"() {
|
|
401983
402219
|
init_editor_store();
|
|
@@ -402003,6 +402239,7 @@ var init_runner = __esm({
|
|
|
402003
402239
|
ALWAYS_ALLOWED = ["list_skills", "read_skill", "manage_todos", "notify", "get_selection", "task", "await_job", "send_message", "stop_agent", "list_agents", "list_profiles", "read_profile", "ask_user"];
|
|
402004
402240
|
MAX_HISTORY_MESSAGES = 24;
|
|
402005
402241
|
MAX_PARALLEL_TOOLS = 4;
|
|
402242
|
+
MAX_TOOL_RESULT_CHARS = 48e3;
|
|
402006
402243
|
TURN_MAX_ROUNDS = 500;
|
|
402007
402244
|
registerTurnTools = (deps) => {
|
|
402008
402245
|
registerBuiltinTools();
|
|
@@ -406487,7 +406724,6 @@ function registerBuiltinCommands() {
|
|
|
406487
406724
|
var builtinCommands, uiOnlyCommands;
|
|
406488
406725
|
var init_builtin4 = __esm({
|
|
406489
406726
|
"lib/commands/builtin.ts"() {
|
|
406490
|
-
"use strict";
|
|
406491
406727
|
init_registry();
|
|
406492
406728
|
init_node();
|
|
406493
406729
|
init_node();
|
|
@@ -407369,7 +407605,6 @@ __export(editor_store_exports, {
|
|
|
407369
407605
|
rebuildVectorData: () => rebuildVectorData,
|
|
407370
407606
|
recoverPointsFromData: () => recoverPointsFromData,
|
|
407371
407607
|
resetLibraryDocuments: () => resetLibraryDocuments,
|
|
407372
|
-
scaleChildrenRecursively: () => scaleChildrenRecursively,
|
|
407373
407608
|
tabPrefsOnly: () => tabPrefsOnly,
|
|
407374
407609
|
useActiveTool: () => useActiveTool,
|
|
407375
407610
|
useCamera: () => useCamera,
|
|
@@ -407542,37 +407777,6 @@ function stripImagePlaceholderFills(nodes, prevNodes, changed) {
|
|
|
407542
407777
|
}
|
|
407543
407778
|
return out ?? nodes;
|
|
407544
407779
|
}
|
|
407545
|
-
function rebuildVectorData(points, closed) {
|
|
407546
|
-
if (points.length < 2) return [];
|
|
407547
|
-
const data = [];
|
|
407548
|
-
data.push("M", points[0].x, points[0].y);
|
|
407549
|
-
for (let i2 = 1; i2 < points.length; i2++) {
|
|
407550
|
-
const prev = points[i2 - 1];
|
|
407551
|
-
const curr = points[i2];
|
|
407552
|
-
if (prev.handleOut && curr.handleIn) {
|
|
407553
|
-
data.push("C", prev.handleOut.x, prev.handleOut.y, curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
407554
|
-
} else if (prev.handleOut) {
|
|
407555
|
-
data.push("Q", prev.handleOut.x, prev.handleOut.y, curr.x, curr.y);
|
|
407556
|
-
} else if (curr.handleIn) {
|
|
407557
|
-
data.push("Q", curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
407558
|
-
} else {
|
|
407559
|
-
data.push("L", curr.x, curr.y);
|
|
407560
|
-
}
|
|
407561
|
-
}
|
|
407562
|
-
if (closed) {
|
|
407563
|
-
const prev = points[points.length - 1];
|
|
407564
|
-
const curr = points[0];
|
|
407565
|
-
if (prev.handleOut && curr.handleIn) {
|
|
407566
|
-
data.push("C", prev.handleOut.x, prev.handleOut.y, curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
407567
|
-
} else if (prev.handleOut) {
|
|
407568
|
-
data.push("Q", prev.handleOut.x, prev.handleOut.y, curr.x, curr.y);
|
|
407569
|
-
} else if (curr.handleIn) {
|
|
407570
|
-
data.push("Q", curr.handleIn.x, curr.handleIn.y, curr.x, curr.y);
|
|
407571
|
-
}
|
|
407572
|
-
data.push("Z");
|
|
407573
|
-
}
|
|
407574
|
-
return data;
|
|
407575
|
-
}
|
|
407576
407780
|
function fixCorruptedVectors(doc2) {
|
|
407577
407781
|
let changed = false;
|
|
407578
407782
|
const newNodes = { ...doc2.nodes };
|
|
@@ -407722,30 +407926,6 @@ function recoverPointsFromData(data) {
|
|
|
407722
407926
|
}
|
|
407723
407927
|
return points;
|
|
407724
407928
|
}
|
|
407725
|
-
function scaleChildrenRecursively(doc2, parentId, scaleX, scaleY) {
|
|
407726
|
-
const parent = doc2.nodes[parentId];
|
|
407727
|
-
if (!parent || !parent.childIds) return doc2;
|
|
407728
|
-
const newDoc = { ...doc2, nodes: { ...doc2.nodes } };
|
|
407729
|
-
const processNode = (nodeId2) => {
|
|
407730
|
-
const node2 = newDoc.nodes[nodeId2];
|
|
407731
|
-
if (!node2) return;
|
|
407732
|
-
const updates = {
|
|
407733
|
-
x: node2.x * scaleX,
|
|
407734
|
-
y: node2.y * scaleY,
|
|
407735
|
-
width: node2.width * scaleX,
|
|
407736
|
-
height: node2.height * scaleY
|
|
407737
|
-
};
|
|
407738
|
-
if (node2.type === "TEXT") {
|
|
407739
|
-
updates.fontSize = (node2.fontSize ?? 16) * Math.min(scaleX, scaleY);
|
|
407740
|
-
}
|
|
407741
|
-
newDoc.nodes[nodeId2] = { ...node2, ...updates };
|
|
407742
|
-
if (node2.childIds) {
|
|
407743
|
-
node2.childIds.forEach(processNode);
|
|
407744
|
-
}
|
|
407745
|
-
};
|
|
407746
|
-
parent.childIds.forEach(processNode);
|
|
407747
|
-
return newDoc;
|
|
407748
|
-
}
|
|
407749
407929
|
function placeInstance(document2, mainComponentId, pageId2, x2, y) {
|
|
407750
407930
|
const main2 = document2.nodes[mainComponentId];
|
|
407751
407931
|
if (!main2 || main2.type !== "COMPONENT") return null;
|
|
@@ -409352,10 +409532,10 @@ var init_editor_store = __esm({
|
|
|
409352
409532
|
if ("childIds" in node2 && node2.childIds.length > 0) {
|
|
409353
409533
|
newDoc = applyConstraints(newDoc, id3, node2.width, node2.height, newWidth, newHeight);
|
|
409354
409534
|
}
|
|
409355
|
-
if (node2.type === "GROUP" && node2.width > 0 && node2.height > 0) {
|
|
409356
|
-
const
|
|
409357
|
-
|
|
409358
|
-
|
|
409535
|
+
if ((node2.type === "GROUP" || node2.type === "VECTOR") && node2.width > 0 && node2.height > 0) {
|
|
409536
|
+
for (const [pid, patch2] of scaleSubtreePatches(newDoc.nodes, id3, newWidth / node2.width, newHeight / node2.height)) {
|
|
409537
|
+
newDoc = updateNode(newDoc, pid, patch2);
|
|
409538
|
+
}
|
|
409359
409539
|
} else if (node2.type === "TABLE" && node2.width > 0 && node2.height > 0) {
|
|
409360
409540
|
const table3 = node2;
|
|
409361
409541
|
const totalW = (table3.colWidths || []).reduce((a, b) => a + b, 0) || 1;
|
|
@@ -410364,23 +410544,35 @@ var init_editor_store = __esm({
|
|
|
410364
410544
|
const geo = multiPolyToVectorGeometry(mp);
|
|
410365
410545
|
if (!geo) return;
|
|
410366
410546
|
const first2 = doc2.nodes[state.selection[0]];
|
|
410547
|
+
const firstFills = (id3) => {
|
|
410548
|
+
const n = doc2.nodes[id3];
|
|
410549
|
+
if (!n) return void 0;
|
|
410550
|
+
if (n.fills?.length && n.type !== "GROUP") return n.fills;
|
|
410551
|
+
for (const c2 of n.childIds ?? []) {
|
|
410552
|
+
const f2 = firstFills(c2);
|
|
410553
|
+
if (f2) return f2;
|
|
410554
|
+
}
|
|
410555
|
+
return void 0;
|
|
410556
|
+
};
|
|
410557
|
+
const fills = state.selection.map(firstFills).find(Boolean);
|
|
410367
410558
|
const vectorNode = createVector({
|
|
410368
410559
|
...geo,
|
|
410369
|
-
fills:
|
|
410560
|
+
fills: fills ?? [{ type: "SOLID", color: { r: 0.85, g: 0.85, b: 0.85, a: 1 }, visible: true }],
|
|
410370
410561
|
strokes: [],
|
|
410371
410562
|
fillRule: "EVENODD",
|
|
410372
410563
|
name: state.selection.length > 1 ? "Flattened" : `${first2?.name ?? "Vector"} (flattened)`
|
|
410373
410564
|
});
|
|
410374
410565
|
doc2 = addNode(doc2, vectorNode, state.currentPageId);
|
|
410566
|
+
const parentId = first2?.parentId;
|
|
410567
|
+
if (parentId && parentId !== state.currentPageId && doc2.nodes[parentId]) {
|
|
410568
|
+
const placed2 = placementUnder(doc2, vectorNode.id, parentId);
|
|
410569
|
+
if (placed2) doc2 = reparentNode(updateNode(doc2, vectorNode.id, placed2), vectorNode.id, parentId);
|
|
410570
|
+
}
|
|
410375
410571
|
state.selection.forEach((id3) => {
|
|
410376
410572
|
if (doc2.nodes[id3]) doc2 = removeNode(doc2, id3);
|
|
410377
410573
|
});
|
|
410378
|
-
|
|
410379
|
-
set4({
|
|
410380
|
-
document: doc2,
|
|
410381
|
-
history: pushCommand(state.history, command),
|
|
410382
|
-
selection: [vectorNode.id]
|
|
410383
|
-
});
|
|
410574
|
+
if (documentBefore !== doc2) get4().commitDocument(doc2, "Flatten selection");
|
|
410575
|
+
set4({ selection: [vectorNode.id] });
|
|
410384
410576
|
},
|
|
410385
410577
|
joinPaths: () => {
|
|
410386
410578
|
const state = get4();
|
|
@@ -414092,7 +414284,7 @@ init_resources();
|
|
|
414092
414284
|
init_desktop();
|
|
414093
414285
|
init_hypery();
|
|
414094
414286
|
import { createInterface } from "node:readline";
|
|
414095
|
-
var VERSION2 = "0.53.
|
|
414287
|
+
var VERSION2 = "0.53.2";
|
|
414096
414288
|
var HELP = `popcraft ${VERSION2} \u2014 the PopCraft command line
|
|
414097
414289
|
|
|
414098
414290
|
Files (headless, on .popcraft files):
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@popcraft/cli",
|
|
3
|
-
"version": "0.53.
|
|
3
|
+
"version": "0.53.2",
|
|
4
4
|
"description": "The PopCraft command line: edit .popcraft files headlessly, call the REST API, publish to the marketplace and manage the desktop app's local plugins, themes, fonts, skills and agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://popcraft.app/docs/api/cli",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"esbuild": "0.28.2"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@popcraft/kit": "0.53.
|
|
37
|
+
"@popcraft/kit": "0.53.2"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "node build.mjs",
|