@mylasertools/kerfscript 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/CLA.md +8 -5
- package/COMMERCIAL-LICENSE.md +23 -28
- package/LANGUAGE.md +149 -46
- package/README.md +68 -29
- package/THIRD-PARTY-NOTICES.md +55 -0
- package/TRADEMARKS.md +16 -10
- package/dist/cli.js +273 -83
- package/dist/evaluator.d.cts +23 -0
- package/dist/evaluator.d.ts +23 -0
- package/dist/export/svg.d.cts +2 -0
- package/dist/export/svg.d.ts +2 -0
- package/dist/index.cjs +14 -14
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -14
- package/dist/render.d.cts +2 -1
- package/dist/render.d.ts +2 -1
- package/docs/cli.md +43 -28
- package/docs/compatibility.md +40 -65
- package/docs/customizer.md +40 -28
- package/docs/getting-started.md +48 -31
- package/docs/javascript.md +106 -51
- package/docs/kerf.md +36 -39
- package/docs/layers.md +71 -37
- package/docs/openscad.md +52 -48
- package/docs/parts-and-sheets.md +45 -31
- package/docs/versions.md +20 -30
- package/package.json +5 -4
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/*! @mylasertools/kerfscript | (c) MyLaserTools | AGPL-3.0-only or commercial licence, see COMMERCIAL-LICENSE.md. Includes Clipper2 (BSL-1.0)
|
|
2
|
+
/*! @mylasertools/kerfscript | (c) MyLaserTools | AGPL-3.0-only or commercial licence, see COMMERCIAL-LICENSE.md. Includes Clipper2 (BSL-1.0), opentype.js, tiny-inflate and string.prototype.codepointat (MIT), see THIRD-PARTY-NOTICES.md. */
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -32,9 +32,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
32
32
|
mod
|
|
33
33
|
));
|
|
34
34
|
|
|
35
|
-
// node_modules/opentype.js/dist/opentype.js
|
|
35
|
+
// ../kerfscript/node_modules/opentype.js/dist/opentype.js
|
|
36
36
|
var require_opentype = __commonJS({
|
|
37
|
-
"node_modules/opentype.js/dist/opentype.js"(exports, module) {
|
|
37
|
+
"../kerfscript/node_modules/opentype.js/dist/opentype.js"(exports, module) {
|
|
38
38
|
(function(global, factory) {
|
|
39
39
|
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global = global || self, factory(global.opentype = {}));
|
|
40
40
|
})(exports, (function(exports2) {
|
|
@@ -12400,8 +12400,8 @@ var FUNCTIONS = {
|
|
|
12400
12400
|
atan: math1("atan", (x) => Math.atan(x) / RAD),
|
|
12401
12401
|
atan2: (a) => clean(Math.atan2(num(a[0], "atan2"), num(a[1], "atan2")) / RAD),
|
|
12402
12402
|
pow: (a) => Math.pow(num(a[0], "pow"), num(a[1], "pow")),
|
|
12403
|
-
min: (a) => minmax(a, (xs) =>
|
|
12404
|
-
max: (a) => minmax(a, (xs) =>
|
|
12403
|
+
min: (a) => minmax(a, (xs) => xs.reduce((m, x) => x < m ? x : m, Infinity), "min"),
|
|
12404
|
+
max: (a) => minmax(a, (xs) => xs.reduce((m, x) => x > m ? x : m, -Infinity), "max"),
|
|
12405
12405
|
clamp: (a) => Math.min(Math.max(num(a[0], "clamp"), num(a[1], "clamp")), num(a[2], "clamp")),
|
|
12406
12406
|
lerp: (a) => {
|
|
12407
12407
|
const t = num(a[2], "lerp");
|
|
@@ -12411,7 +12411,7 @@ var FUNCTIONS = {
|
|
|
12411
12411
|
}
|
|
12412
12412
|
return num(a[0], "lerp") + (num(a[1], "lerp") - num(a[0], "lerp")) * t;
|
|
12413
12413
|
},
|
|
12414
|
-
norm: (a) => Math.
|
|
12414
|
+
norm: (a) => Math.sqrt(list(a[0], "norm").reduce((s, x) => s + num(x, "norm") ** 2, 0)),
|
|
12415
12415
|
cross: (a) => {
|
|
12416
12416
|
const u = list(a[0], "cross").map((x) => num(x, "cross"));
|
|
12417
12417
|
const v = list(a[1], "cross").map((x) => num(x, "cross"));
|
|
@@ -12474,7 +12474,7 @@ var FUNCTIONS = {
|
|
|
12474
12474
|
type_of: (a) => typeName(a[0])
|
|
12475
12475
|
};
|
|
12476
12476
|
|
|
12477
|
-
// node_modules/clipper2-ts/dist/Core.js
|
|
12477
|
+
// ../kerfscript/node_modules/clipper2-ts/dist/Core.js
|
|
12478
12478
|
var ClipType;
|
|
12479
12479
|
(function(ClipType2) {
|
|
12480
12480
|
ClipType2[ClipType2["NoClip"] = 0] = "NoClip";
|
|
@@ -13133,7 +13133,7 @@ var RectDUtils = {
|
|
|
13133
13133
|
var InvalidRect64 = Object.freeze(Rect64Utils.createInvalid());
|
|
13134
13134
|
var InvalidRectD = Object.freeze(RectDUtils.createInvalid());
|
|
13135
13135
|
|
|
13136
|
-
// node_modules/clipper2-ts/dist/Engine.js
|
|
13136
|
+
// ../kerfscript/node_modules/clipper2-ts/dist/Engine.js
|
|
13137
13137
|
var B02 = BigInt(0);
|
|
13138
13138
|
var B22 = BigInt(2);
|
|
13139
13139
|
var B42 = BigInt(4);
|
|
@@ -15898,7 +15898,7 @@ var Clipper = {
|
|
|
15898
15898
|
}
|
|
15899
15899
|
};
|
|
15900
15900
|
|
|
15901
|
-
// node_modules/clipper2-ts/dist/Offset.js
|
|
15901
|
+
// ../kerfscript/node_modules/clipper2-ts/dist/Offset.js
|
|
15902
15902
|
var JoinType;
|
|
15903
15903
|
(function(JoinType2) {
|
|
15904
15904
|
JoinType2[JoinType2["Miter"] = 0] = "Miter";
|
|
@@ -16511,7 +16511,7 @@ var ClipperOffset = class _ClipperOffset {
|
|
|
16511
16511
|
}
|
|
16512
16512
|
};
|
|
16513
16513
|
|
|
16514
|
-
// node_modules/clipper2-ts/dist/Clipper.js
|
|
16514
|
+
// ../kerfscript/node_modules/clipper2-ts/dist/Clipper.js
|
|
16515
16515
|
var B23 = BigInt(2);
|
|
16516
16516
|
function union(subject, clipOrFillRule, fillRule) {
|
|
16517
16517
|
if (typeof clipOrFillRule === "number") {
|
|
@@ -16672,21 +16672,31 @@ function merge(shapes) {
|
|
|
16672
16672
|
for (const s of shapes) {
|
|
16673
16673
|
for (const [k, l] of s.layers) {
|
|
16674
16674
|
const t = out.layers.get(k) ?? { regions: [], lines: [] };
|
|
16675
|
-
t.regions.push(
|
|
16676
|
-
t.lines.push(
|
|
16675
|
+
for (const p of l.regions) t.regions.push(p);
|
|
16676
|
+
for (const p of l.lines) t.lines.push(p);
|
|
16677
16677
|
out.layers.set(k, t);
|
|
16678
16678
|
}
|
|
16679
|
-
out.parts.push(
|
|
16679
|
+
for (const p of s.parts) out.parts.push(p);
|
|
16680
16680
|
}
|
|
16681
16681
|
return out;
|
|
16682
16682
|
}
|
|
16683
|
-
function
|
|
16683
|
+
function allOn(layers, layer) {
|
|
16684
16684
|
const all = { regions: [], lines: [] };
|
|
16685
|
-
for (const l of
|
|
16686
|
-
all.regions.push(
|
|
16687
|
-
all.lines.push(
|
|
16685
|
+
for (const l of layers.values()) {
|
|
16686
|
+
for (const p of l.regions) all.regions.push(p);
|
|
16687
|
+
for (const p of l.lines) all.lines.push(p);
|
|
16688
16688
|
}
|
|
16689
|
-
return
|
|
16689
|
+
return /* @__PURE__ */ new Map([[layer, all]]);
|
|
16690
|
+
}
|
|
16691
|
+
function retag(s, layer) {
|
|
16692
|
+
if (s.parts.length && layer !== "guide")
|
|
16693
|
+
throw new Error(
|
|
16694
|
+
`a part cannot go on the ${layer} layer as a whole. Put ${layer}() inside part() instead.`
|
|
16695
|
+
);
|
|
16696
|
+
return {
|
|
16697
|
+
layers: allOn(s.layers, layer),
|
|
16698
|
+
parts: s.parts.map((p) => ({ ...p, layers: allOn(p.layers, layer) }))
|
|
16699
|
+
};
|
|
16690
16700
|
}
|
|
16691
16701
|
function bounds(polys) {
|
|
16692
16702
|
let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
|
|
@@ -16703,7 +16713,7 @@ function layerBounds(layers, skip) {
|
|
|
16703
16713
|
const all = [];
|
|
16704
16714
|
for (const [k, l] of layers) {
|
|
16705
16715
|
if (skip?.(k)) continue;
|
|
16706
|
-
|
|
16716
|
+
for (const p of [...l.regions, ...l.lines]) all.push(p);
|
|
16707
16717
|
}
|
|
16708
16718
|
return bounds(all);
|
|
16709
16719
|
}
|
|
@@ -17413,13 +17423,14 @@ function flatten(cmds, tolerance = 0.02) {
|
|
|
17413
17423
|
} else {
|
|
17414
17424
|
finish(true);
|
|
17415
17425
|
last = start;
|
|
17416
|
-
cur = [];
|
|
17426
|
+
cur = [start];
|
|
17417
17427
|
}
|
|
17418
17428
|
}
|
|
17419
17429
|
finish(false);
|
|
17420
17430
|
return { closed, open };
|
|
17421
17431
|
}
|
|
17422
17432
|
function parseSvgPath(d2) {
|
|
17433
|
+
const isCommand = (t) => /^[a-zA-Z]$/.test(t);
|
|
17423
17434
|
const tokens = d2.match(/[a-zA-Z]|[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?/g) ?? [];
|
|
17424
17435
|
const out = [];
|
|
17425
17436
|
let i = 0;
|
|
@@ -17429,8 +17440,7 @@ function parseSvgPath(d2) {
|
|
|
17429
17440
|
let prev = "";
|
|
17430
17441
|
const num2 = () => {
|
|
17431
17442
|
const t = tokens[i++];
|
|
17432
|
-
if (t === void 0 ||
|
|
17433
|
-
throw new Error(`Bad path data near "${t ?? "end"}"`);
|
|
17443
|
+
if (t === void 0 || isCommand(t)) throw new Error(`Bad path data near "${t ?? "end"}"`);
|
|
17434
17444
|
return Number(t);
|
|
17435
17445
|
};
|
|
17436
17446
|
const flag = () => {
|
|
@@ -17444,8 +17454,10 @@ function parseSvgPath(d2) {
|
|
|
17444
17454
|
return Number(t);
|
|
17445
17455
|
};
|
|
17446
17456
|
while (i < tokens.length) {
|
|
17447
|
-
if (
|
|
17457
|
+
if (isCommand(tokens[i])) cmd = tokens[i++];
|
|
17448
17458
|
else if (!cmd) throw new Error("Path data must start with a command");
|
|
17459
|
+
else if (cmd === "Z" || cmd === "z")
|
|
17460
|
+
throw new Error(`Bad path data near "${tokens[i]}": Z takes no numbers`);
|
|
17449
17461
|
const rel = cmd === cmd.toLowerCase();
|
|
17450
17462
|
const C = cmd.toUpperCase();
|
|
17451
17463
|
const ox = rel ? x : 0, oy = rel ? y : 0;
|
|
@@ -17657,6 +17669,31 @@ var DEFAULT_LAYERS = [
|
|
|
17657
17669
|
{ name: "cut", mode: "cut", color: "#ff0000" },
|
|
17658
17670
|
{ name: "guide", mode: "guide", color: "#00a0ff" }
|
|
17659
17671
|
];
|
|
17672
|
+
var DEFAULT_LIMITS = {
|
|
17673
|
+
maxParts: 1e4,
|
|
17674
|
+
maxSegments: 1e4,
|
|
17675
|
+
maxListLength: 1e6,
|
|
17676
|
+
maxListItems: 3e6,
|
|
17677
|
+
maxTextLength: 2e3,
|
|
17678
|
+
maxPoints: 2e6,
|
|
17679
|
+
maxOutputPoints: 1e6,
|
|
17680
|
+
maxSheets: 200
|
|
17681
|
+
};
|
|
17682
|
+
var SHAPE_COST = 100;
|
|
17683
|
+
var LIST_COST = 4;
|
|
17684
|
+
var CHARS_PER_ITEM = 8;
|
|
17685
|
+
var shapePoints = (s) => {
|
|
17686
|
+
let n2 = SHAPE_COST;
|
|
17687
|
+
const add = (layers) => {
|
|
17688
|
+
for (const l of layers.values()) {
|
|
17689
|
+
for (const p of l.regions) n2 += p.length;
|
|
17690
|
+
for (const p of l.lines) n2 += p.length;
|
|
17691
|
+
}
|
|
17692
|
+
};
|
|
17693
|
+
add(s.layers);
|
|
17694
|
+
for (const p of s.parts) add(p.layers);
|
|
17695
|
+
return n2;
|
|
17696
|
+
};
|
|
17660
17697
|
var Env = class {
|
|
17661
17698
|
constructor(parent, caller) {
|
|
17662
17699
|
this.parent = parent;
|
|
@@ -17696,11 +17733,15 @@ var Evaluator = class {
|
|
|
17696
17733
|
this.opts = opts;
|
|
17697
17734
|
this.steps = 0;
|
|
17698
17735
|
this.depth = 0;
|
|
17736
|
+
this.pointCount = 0;
|
|
17737
|
+
this.itemCount = 0;
|
|
17738
|
+
this.copies = 0;
|
|
17699
17739
|
this.echoes = [];
|
|
17700
17740
|
this.warnings = [];
|
|
17701
17741
|
this.layers = new Map(DEFAULT_LAYERS.map((l) => [l.name, l]));
|
|
17702
17742
|
this.loaded = /* @__PURE__ */ new Map();
|
|
17703
17743
|
this.maxSteps = opts.maxSteps ?? 5e6;
|
|
17744
|
+
this.limits = { ...DEFAULT_LIMITS, ...opts.limits };
|
|
17704
17745
|
this.builtins = this.makeBuiltins();
|
|
17705
17746
|
}
|
|
17706
17747
|
run(program) {
|
|
@@ -17747,16 +17788,28 @@ var Evaluator = class {
|
|
|
17747
17788
|
if (s.kind === "module") env.mods.set(s.name, { params: s.params, body: s.body, env });
|
|
17748
17789
|
else if (s.kind === "function") env.fns.set(s.name, { params: s.params, body: s.body, env });
|
|
17749
17790
|
else if (s.kind === "use" && !s.include) {
|
|
17750
|
-
const
|
|
17791
|
+
const body = this.included(this.load(s.path, s.pos).body, /* @__PURE__ */ new Set([s.path]));
|
|
17751
17792
|
const libEnv = new Env(env);
|
|
17752
|
-
this.hoist(
|
|
17753
|
-
for (const ls of
|
|
17793
|
+
this.hoist(body, libEnv);
|
|
17794
|
+
for (const ls of body)
|
|
17754
17795
|
if (ls.kind === "assign") this.assign(ls.name, this.expr(ls.value, libEnv), libEnv);
|
|
17755
17796
|
for (const [k, v] of libEnv.mods) env.mods.set(k, v);
|
|
17756
17797
|
for (const [k, v] of libEnv.fns) env.fns.set(k, v);
|
|
17757
17798
|
}
|
|
17758
17799
|
}
|
|
17759
17800
|
}
|
|
17801
|
+
// A library's statements with the files it includes written out in place
|
|
17802
|
+
included(stmts, seen) {
|
|
17803
|
+
const out = [];
|
|
17804
|
+
for (const s of stmts) {
|
|
17805
|
+
if (s.kind !== "use" || !s.include) out.push(s);
|
|
17806
|
+
else if (!seen.has(s.path)) {
|
|
17807
|
+
seen.add(s.path);
|
|
17808
|
+
for (const t of this.included(this.load(s.path, s.pos).body, seen)) out.push(t);
|
|
17809
|
+
}
|
|
17810
|
+
}
|
|
17811
|
+
return out;
|
|
17812
|
+
}
|
|
17760
17813
|
assign(name, value, env) {
|
|
17761
17814
|
env.vars.set(name, value);
|
|
17762
17815
|
}
|
|
@@ -17855,8 +17908,10 @@ var Evaluator = class {
|
|
|
17855
17908
|
});
|
|
17856
17909
|
for (const k of args.named.keys()) {
|
|
17857
17910
|
if (k.startsWith("$")) env.vars.set(k, args.named.get(k));
|
|
17858
|
-
else if (!names.has(k))
|
|
17859
|
-
|
|
17911
|
+
else if (!names.has(k)) {
|
|
17912
|
+
const warning = `${what}: unknown argument "${k}" (line ${args.at.line})`;
|
|
17913
|
+
if (!this.warnings.includes(warning)) this.warnings.push(warning);
|
|
17914
|
+
}
|
|
17860
17915
|
}
|
|
17861
17916
|
void defEnv;
|
|
17862
17917
|
}
|
|
@@ -17892,20 +17947,28 @@ var Evaluator = class {
|
|
|
17892
17947
|
childList: () => {
|
|
17893
17948
|
const e = childEnv();
|
|
17894
17949
|
this.hoist(s.children, e);
|
|
17895
|
-
const
|
|
17950
|
+
const out2 = [];
|
|
17896
17951
|
for (const st of s.children) {
|
|
17897
17952
|
const r = this.stmt(st, e);
|
|
17898
|
-
if (kids.includes(st))
|
|
17953
|
+
if (kids.includes(st)) out2.push(r ?? emptyShape());
|
|
17899
17954
|
}
|
|
17900
|
-
return
|
|
17955
|
+
return out2;
|
|
17901
17956
|
}
|
|
17902
17957
|
};
|
|
17958
|
+
let out;
|
|
17903
17959
|
try {
|
|
17904
|
-
|
|
17960
|
+
out = b(ctx);
|
|
17905
17961
|
} catch (e) {
|
|
17906
17962
|
if (e instanceof KerfError) throw e;
|
|
17907
17963
|
throw new KerfError(`${s.name}(): ${e.message}`, s.pos);
|
|
17908
17964
|
}
|
|
17965
|
+
this.pointCount += shapePoints(out);
|
|
17966
|
+
if (this.pointCount > this.limits.maxPoints)
|
|
17967
|
+
throw new KerfError(
|
|
17968
|
+
`The shapes have more than ${this.limits.maxPoints} points, the limit. Use fewer or simpler shapes, or a lower $fn.`,
|
|
17969
|
+
s.pos
|
|
17970
|
+
);
|
|
17971
|
+
return out;
|
|
17909
17972
|
}
|
|
17910
17973
|
childStmts(stmts) {
|
|
17911
17974
|
return stmts.filter(
|
|
@@ -17943,7 +18006,8 @@ var Evaluator = class {
|
|
|
17943
18006
|
}
|
|
17944
18007
|
case "list": {
|
|
17945
18008
|
const out = [];
|
|
17946
|
-
for (const it of x.items) this.listItem(it, env, out);
|
|
18009
|
+
for (const it of x.items) this.listItem(it, env, out, x.pos);
|
|
18010
|
+
this.charge(LIST_COST, x.pos);
|
|
17947
18011
|
return out;
|
|
17948
18012
|
}
|
|
17949
18013
|
case "range": {
|
|
@@ -18005,30 +18069,50 @@ var Evaluator = class {
|
|
|
18005
18069
|
}
|
|
18006
18070
|
}
|
|
18007
18071
|
}
|
|
18008
|
-
listItem(it, env, out) {
|
|
18072
|
+
listItem(it, env, out, at) {
|
|
18009
18073
|
switch (it.kind) {
|
|
18010
|
-
case "item":
|
|
18011
|
-
|
|
18074
|
+
case "item": {
|
|
18075
|
+
const v = this.expr(it.expr, env);
|
|
18076
|
+
this.grow(out, 1, at);
|
|
18077
|
+
out.push(v);
|
|
18012
18078
|
return;
|
|
18079
|
+
}
|
|
18013
18080
|
case "each": {
|
|
18014
|
-
const
|
|
18015
|
-
|
|
18081
|
+
const xs = this.iterable(this.expr(it.expr, env), at);
|
|
18082
|
+
this.grow(out, xs.length, at);
|
|
18083
|
+
for (const x of xs) out.push(x);
|
|
18016
18084
|
return;
|
|
18017
18085
|
}
|
|
18018
18086
|
case "for":
|
|
18019
|
-
this.loop(it.assigns, env, (e) => this.listItem(it.body, e, out));
|
|
18087
|
+
this.loop(it.assigns, env, (e) => this.listItem(it.body, e, out, at));
|
|
18020
18088
|
return;
|
|
18021
18089
|
case "if":
|
|
18022
|
-
if (truthy(this.expr(it.cond, env))) this.listItem(it.then, env, out);
|
|
18023
|
-
else if (it.else) this.listItem(it.else, env, out);
|
|
18090
|
+
if (truthy(this.expr(it.cond, env))) this.listItem(it.then, env, out, at);
|
|
18091
|
+
else if (it.else) this.listItem(it.else, env, out, at);
|
|
18024
18092
|
return;
|
|
18025
18093
|
case "let": {
|
|
18026
18094
|
const e = new Env(env);
|
|
18027
18095
|
this.bindSeq(it.assigns, e);
|
|
18028
|
-
this.listItem(it.body, e, out);
|
|
18096
|
+
this.listItem(it.body, e, out, at);
|
|
18029
18097
|
}
|
|
18030
18098
|
}
|
|
18031
18099
|
}
|
|
18100
|
+
grow(out, n2, at) {
|
|
18101
|
+
if (out.length + n2 > this.limits.maxListLength)
|
|
18102
|
+
throw new KerfError(
|
|
18103
|
+
`a list of ${out.length + n2} items is more than the limit of ${this.limits.maxListLength}`,
|
|
18104
|
+
at
|
|
18105
|
+
);
|
|
18106
|
+
this.charge(n2, at);
|
|
18107
|
+
}
|
|
18108
|
+
charge(items, at) {
|
|
18109
|
+
this.itemCount += items;
|
|
18110
|
+
if (!(this.itemCount <= this.limits.maxListItems))
|
|
18111
|
+
throw new KerfError(
|
|
18112
|
+
`The lists and strings hold more than ${this.limits.maxListItems} items in all, the limit. Is a loop building more than it needs?`,
|
|
18113
|
+
at
|
|
18114
|
+
);
|
|
18115
|
+
}
|
|
18032
18116
|
call(x, env) {
|
|
18033
18117
|
if (x.callee.kind === "var") {
|
|
18034
18118
|
const name = x.callee.name;
|
|
@@ -18041,11 +18125,17 @@ var Evaluator = class {
|
|
|
18041
18125
|
const b = FUNCTIONS[name];
|
|
18042
18126
|
if (b) {
|
|
18043
18127
|
const args = this.evalArgs(x.args, env, x.pos);
|
|
18128
|
+
let out;
|
|
18044
18129
|
try {
|
|
18045
|
-
|
|
18130
|
+
out = b(args.pos, args.named);
|
|
18046
18131
|
} catch (e) {
|
|
18047
|
-
throw new KerfError(
|
|
18132
|
+
throw new KerfError(
|
|
18133
|
+
e instanceof RangeError ? `${name}(): the result is too large` : e.message,
|
|
18134
|
+
x.pos
|
|
18135
|
+
);
|
|
18048
18136
|
}
|
|
18137
|
+
this.checkValue(out, x.pos, name);
|
|
18138
|
+
return out;
|
|
18049
18139
|
}
|
|
18050
18140
|
throw new KerfError(`Unknown function ${name}()`, x.pos);
|
|
18051
18141
|
}
|
|
@@ -18060,7 +18150,7 @@ var Evaluator = class {
|
|
|
18060
18150
|
specialFunction(name, x, env) {
|
|
18061
18151
|
if (name === "echo") {
|
|
18062
18152
|
const a = this.evalArgs(x.args, env, x.pos);
|
|
18063
|
-
this.
|
|
18153
|
+
this.echo(this.echoText(a), x.pos);
|
|
18064
18154
|
return { handled: true, value: void 0 };
|
|
18065
18155
|
}
|
|
18066
18156
|
if (name === "assert") {
|
|
@@ -18088,6 +18178,10 @@ var Evaluator = class {
|
|
|
18088
18178
|
}
|
|
18089
18179
|
return { handled: false };
|
|
18090
18180
|
}
|
|
18181
|
+
echo(text, at) {
|
|
18182
|
+
this.charge(Math.ceil(text.length / CHARS_PER_ITEM), at);
|
|
18183
|
+
this.echoes.push(text);
|
|
18184
|
+
}
|
|
18091
18185
|
echoText(a) {
|
|
18092
18186
|
const parts = a.pos.map((v) => typeof v === "string" ? v : show(v));
|
|
18093
18187
|
for (const [k, v] of a.named) parts.push(`${k} = ${show(v)}`);
|
|
@@ -18110,7 +18204,10 @@ var Evaluator = class {
|
|
|
18110
18204
|
return Math.pow(a, b);
|
|
18111
18205
|
}
|
|
18112
18206
|
}
|
|
18113
|
-
if (op === "+" && typeof a === "string" && typeof b === "string")
|
|
18207
|
+
if (op === "+" && typeof a === "string" && typeof b === "string") {
|
|
18208
|
+
this.checkSize(a.length + b.length, true, at);
|
|
18209
|
+
return a + b;
|
|
18210
|
+
}
|
|
18114
18211
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
18115
18212
|
if (op === "+" || op === "-") {
|
|
18116
18213
|
if (a.length !== b.length)
|
|
@@ -18118,12 +18215,14 @@ var Evaluator = class {
|
|
|
18118
18215
|
`Can't ${op === "+" ? "add" : "subtract"} lists of length ${a.length} and ${b.length}`,
|
|
18119
18216
|
at
|
|
18120
18217
|
);
|
|
18218
|
+
this.charge(a.length + LIST_COST, at);
|
|
18121
18219
|
return a.map((x, i) => this.arith(op, x, b[i], at));
|
|
18122
18220
|
}
|
|
18123
18221
|
if (op === "*") {
|
|
18124
18222
|
if (Array.isArray(a[0])) return a.map((row) => this.arith("*", row, b, at));
|
|
18125
18223
|
if (Array.isArray(b[0])) {
|
|
18126
18224
|
const cols = b[0].length;
|
|
18225
|
+
this.checkSize(cols, false, at);
|
|
18127
18226
|
return Array.from(
|
|
18128
18227
|
{ length: cols },
|
|
18129
18228
|
(_, j) => a.reduce(
|
|
@@ -18137,10 +18236,14 @@ var Evaluator = class {
|
|
|
18137
18236
|
return a.reduce((s, x, i) => s + this.arith("*", x, b[i], at), 0);
|
|
18138
18237
|
}
|
|
18139
18238
|
}
|
|
18140
|
-
if (Array.isArray(a) && typeof b === "number" && (op === "*" || op === "/"))
|
|
18239
|
+
if (Array.isArray(a) && typeof b === "number" && (op === "*" || op === "/")) {
|
|
18240
|
+
this.charge(a.length + LIST_COST, at);
|
|
18141
18241
|
return a.map((x) => this.arith(op, x, b, at));
|
|
18142
|
-
|
|
18242
|
+
}
|
|
18243
|
+
if (typeof a === "number" && Array.isArray(b) && op === "*") {
|
|
18244
|
+
this.charge(b.length + LIST_COST, at);
|
|
18143
18245
|
return b.map((x) => this.arith(op, a, x, at));
|
|
18246
|
+
}
|
|
18144
18247
|
const verb = {
|
|
18145
18248
|
"+": "add",
|
|
18146
18249
|
"-": "subtract",
|
|
@@ -18157,20 +18260,21 @@ var Evaluator = class {
|
|
|
18157
18260
|
return def;
|
|
18158
18261
|
}
|
|
18159
18262
|
num(v, fn, name) {
|
|
18160
|
-
if (typeof v !== "number" || Number.
|
|
18161
|
-
throw new Error(`${name} must be a number, got ${show(v)}`);
|
|
18263
|
+
if (typeof v !== "number" || !Number.isFinite(v))
|
|
18264
|
+
throw new Error(`${name} must be a finite number, got ${show(v)}`);
|
|
18162
18265
|
return v;
|
|
18163
18266
|
}
|
|
18164
18267
|
vec2(v, name, scalarBoth = true) {
|
|
18165
|
-
|
|
18166
|
-
if (
|
|
18167
|
-
|
|
18268
|
+
const ok = (x) => typeof x === "number" && Number.isFinite(x);
|
|
18269
|
+
if (ok(v) && scalarBoth) return [v, v];
|
|
18270
|
+
if (Array.isArray(v) && ok(v[0]) && (v[1] === void 0 || ok(v[1])))
|
|
18271
|
+
return [v[0], v[1] ?? 0];
|
|
18168
18272
|
throw new Error(`${name} must be a number or [x, y], got ${show(v)}`);
|
|
18169
18273
|
}
|
|
18170
18274
|
points(v, name) {
|
|
18171
18275
|
if (!Array.isArray(v)) throw new Error(`${name} must be a list of [x, y] points`);
|
|
18172
18276
|
return v.map((p, i) => {
|
|
18173
|
-
if (!Array.isArray(p) ||
|
|
18277
|
+
if (!Array.isArray(p) || !Number.isFinite(p[0]) || !Number.isFinite(p[1]))
|
|
18174
18278
|
throw new Error(`${name}[${i}] must be an [x, y] point, got ${show(p)}`);
|
|
18175
18279
|
return [p[0], p[1]];
|
|
18176
18280
|
});
|
|
@@ -18178,11 +18282,38 @@ var Evaluator = class {
|
|
|
18178
18282
|
dyn(env, name) {
|
|
18179
18283
|
return env.get(name).value;
|
|
18180
18284
|
}
|
|
18285
|
+
spend(points) {
|
|
18286
|
+
this.pointCount += points;
|
|
18287
|
+
if (!(this.pointCount <= this.limits.maxPoints))
|
|
18288
|
+
throw new Error(
|
|
18289
|
+
`the shapes need more than ${this.limits.maxPoints} points, the limit. Use fewer or simpler shapes.`
|
|
18290
|
+
);
|
|
18291
|
+
}
|
|
18292
|
+
checkValue(v, pos, fn) {
|
|
18293
|
+
if (Array.isArray(v) || typeof v === "string")
|
|
18294
|
+
this.checkSize(v.length, typeof v === "string", pos, fn);
|
|
18295
|
+
}
|
|
18296
|
+
checkSize(n2, isString, pos, fn) {
|
|
18297
|
+
if (n2 > this.limits.maxListLength)
|
|
18298
|
+
throw new KerfError(
|
|
18299
|
+
`${fn ? `${fn}(): ` : ""}${isString ? `a string of ${n2} characters` : `a list of ${n2} items`} is more than the limit of ${this.limits.maxListLength}`,
|
|
18300
|
+
pos
|
|
18301
|
+
);
|
|
18302
|
+
this.charge(isString ? Math.ceil(n2 / CHARS_PER_ITEM) : n2 + LIST_COST, pos);
|
|
18303
|
+
}
|
|
18181
18304
|
segs(env) {
|
|
18182
18305
|
const fn = Number(this.dyn(env, "$fn")) || 0;
|
|
18183
18306
|
const fa = Number(this.dyn(env, "$fa")) || 2;
|
|
18184
18307
|
const fs = Number(this.dyn(env, "$fs")) || 0.2;
|
|
18185
|
-
|
|
18308
|
+
const max = this.limits.maxSegments;
|
|
18309
|
+
return (r) => {
|
|
18310
|
+
const n2 = fragments(r, fn, fa, fs);
|
|
18311
|
+
if (!(n2 <= max))
|
|
18312
|
+
throw new Error(
|
|
18313
|
+
`a circle with ${n2} segments is more than the limit of ${max}. Lower $fn, or raise $fa or $fs.`
|
|
18314
|
+
);
|
|
18315
|
+
return n2;
|
|
18316
|
+
};
|
|
18186
18317
|
}
|
|
18187
18318
|
thickness(env) {
|
|
18188
18319
|
const t = this.dyn(env, "$thickness");
|
|
@@ -18253,12 +18384,16 @@ var Evaluator = class {
|
|
|
18253
18384
|
Math.floor(this.num(this.arg(c.args, "n", 0, 6), "regular_polygon", "n"))
|
|
18254
18385
|
);
|
|
18255
18386
|
const r = this.num(this.arg(c.args, "r", 1, 10), "regular_polygon", "r");
|
|
18387
|
+
if (!(n2 <= this.limits.maxSegments))
|
|
18388
|
+
throw new Error(`${n2} corners is more than the limit of ${this.limits.maxSegments}`);
|
|
18256
18389
|
return regionShape([ellipsePoly(r, r, n2)]);
|
|
18257
18390
|
},
|
|
18258
18391
|
star: (c) => {
|
|
18259
18392
|
const n2 = Math.max(2, Math.floor(this.num(this.arg(c.args, "n", 0, 5), "star", "n")));
|
|
18260
18393
|
const r = this.num(this.arg(c.args, "r", 1, 10), "star", "r");
|
|
18261
18394
|
const ri = this.num(this.arg(c.args, "inner", 2, r * 0.45), "star", "inner");
|
|
18395
|
+
if (!(n2 * 2 <= this.limits.maxSegments))
|
|
18396
|
+
throw new Error(`${n2} points is more than the limit of ${this.limits.maxSegments / 2}`);
|
|
18262
18397
|
const p = [];
|
|
18263
18398
|
for (let i = 0; i < n2 * 2; i++) {
|
|
18264
18399
|
const a = Math.PI / 2 + Math.PI * i / n2;
|
|
@@ -18298,6 +18433,10 @@ var Evaluator = class {
|
|
|
18298
18433
|
const a0 = this.num(this.arg(c.args, "start", 1, 0), "arc", "start");
|
|
18299
18434
|
const a1 = this.num(this.arg(c.args, "end", 2, 90), "arc", "end");
|
|
18300
18435
|
const n2 = Math.max(2, Math.ceil(this.segs(c.env)(r) * Math.abs(a1 - a0) / 360));
|
|
18436
|
+
if (!(n2 <= this.limits.maxSegments))
|
|
18437
|
+
throw new Error(
|
|
18438
|
+
`an arc with ${n2} segments is more than the limit of ${this.limits.maxSegments}`
|
|
18439
|
+
);
|
|
18301
18440
|
const p = [];
|
|
18302
18441
|
for (let i = 0; i <= n2; i++) {
|
|
18303
18442
|
const a = (a0 + (a1 - a0) * i / n2) * Math.PI / 180;
|
|
@@ -18311,13 +18450,12 @@ var Evaluator = class {
|
|
|
18311
18450
|
"text() needs a font. Pass fonts to render(), or --font on the command line."
|
|
18312
18451
|
);
|
|
18313
18452
|
const text = this.arg(c.args, "text", 0, "");
|
|
18314
|
-
|
|
18315
|
-
|
|
18316
|
-
|
|
18317
|
-
|
|
18318
|
-
|
|
18319
|
-
|
|
18320
|
-
);
|
|
18453
|
+
const shown = typeof text === "string" ? text : show(text);
|
|
18454
|
+
if (shown.length > this.limits.maxTextLength)
|
|
18455
|
+
throw new Error(
|
|
18456
|
+
`${shown.length} characters is more than the limit of ${this.limits.maxTextLength} for one text()`
|
|
18457
|
+
);
|
|
18458
|
+
return regionShape(textRegions(this.opts.fonts, shown, this.textOpts(c.args, c.env)));
|
|
18321
18459
|
},
|
|
18322
18460
|
translate: (c) => {
|
|
18323
18461
|
const [x, y] = this.vec2(this.arg(c.args, "v", 0, [0, 0]), "v", false);
|
|
@@ -18386,7 +18524,7 @@ var Evaluator = class {
|
|
|
18386
18524
|
key = k;
|
|
18387
18525
|
first = false;
|
|
18388
18526
|
}
|
|
18389
|
-
for (const p of [...l.regions, ...l.lines]) pts.push(
|
|
18527
|
+
for (const p of [...l.regions, ...l.lines]) for (const q of p) pts.push(q);
|
|
18390
18528
|
}
|
|
18391
18529
|
const h = hull(pts);
|
|
18392
18530
|
return {
|
|
@@ -18439,6 +18577,9 @@ var Evaluator = class {
|
|
|
18439
18577
|
part: (c) => {
|
|
18440
18578
|
const name = String(this.arg(c.args, "name", 0, "part"));
|
|
18441
18579
|
const qty = Math.max(1, Math.floor(Number(this.arg(c.args, "qty", 1, 1)) || 1));
|
|
18580
|
+
this.copies += qty;
|
|
18581
|
+
if (!(this.copies <= this.limits.maxParts))
|
|
18582
|
+
throw new Error(`more than ${this.limits.maxParts} part copies in total, the limit`);
|
|
18442
18583
|
const s = c.children();
|
|
18443
18584
|
return {
|
|
18444
18585
|
layers: /* @__PURE__ */ new Map(),
|
|
@@ -18487,7 +18628,7 @@ var Evaluator = class {
|
|
|
18487
18628
|
return merge(out);
|
|
18488
18629
|
},
|
|
18489
18630
|
echo: (c) => {
|
|
18490
|
-
this.
|
|
18631
|
+
this.echo(this.echoText(c.args), c.args.at);
|
|
18491
18632
|
return c.children();
|
|
18492
18633
|
},
|
|
18493
18634
|
assert: (c) => {
|
|
@@ -18503,15 +18644,17 @@ var Evaluator = class {
|
|
|
18503
18644
|
const [w, h] = this.vec2(this.arg(c.args, "size", 0), "size");
|
|
18504
18645
|
const edges = this.edges(this.arg(c.args, "edges", 1, "out"));
|
|
18505
18646
|
const t = this.thickness(c.env);
|
|
18506
|
-
|
|
18647
|
+
const finger = this.fingerWidth(c.args, c.env, 2);
|
|
18648
|
+
this.spend(2 * (Math.abs(w) + Math.abs(h)) / finger * 4);
|
|
18649
|
+
return regionShape(fingerRect(w, h, edges, t, finger));
|
|
18507
18650
|
},
|
|
18508
18651
|
finger_holes: (c) => {
|
|
18509
18652
|
const L = this.num(this.arg(c.args, "length", 0), "finger_holes", "length");
|
|
18510
18653
|
const e = this.edges(this.arg(c.args, "edge", 1, "out"))[0];
|
|
18511
18654
|
if (e === "flat") throw new Error('edge must be "out" or "in"');
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
);
|
|
18655
|
+
const finger = this.fingerWidth(c.args, c.env, 2);
|
|
18656
|
+
this.spend(Math.abs(L) / finger * 4);
|
|
18657
|
+
return regionShape(fingerHoles(L, e, this.thickness(c.env), finger));
|
|
18515
18658
|
},
|
|
18516
18659
|
tslot: (c) => {
|
|
18517
18660
|
const d2 = this.num(this.arg(c.args, "d", 0, 3), "tslot", "d");
|
|
@@ -18531,6 +18674,7 @@ var Evaluator = class {
|
|
|
18531
18674
|
);
|
|
18532
18675
|
if (spacing <= 0 || bridge <= 0 || cut <= 0)
|
|
18533
18676
|
throw new Error("spacing, bridge and cut must be positive");
|
|
18677
|
+
this.spend((Math.abs(w) / spacing + 1) * (Math.abs(h) / (cut + bridge) + 2) * 2);
|
|
18534
18678
|
return lineShape(livingHinge(w, h, spacing, bridge, cut));
|
|
18535
18679
|
}
|
|
18536
18680
|
};
|
|
@@ -18538,14 +18682,20 @@ var Evaluator = class {
|
|
|
18538
18682
|
const out = { regions: [], lines: [] };
|
|
18539
18683
|
for (const s of shapes) {
|
|
18540
18684
|
if (s.parts.length) throw new Error(`part() can only be the first child of ${fn}()`);
|
|
18541
|
-
for (const l of s.layers.values()) out.regions.push(
|
|
18685
|
+
for (const l of s.layers.values()) for (const p of l.regions) out.regions.push(p);
|
|
18542
18686
|
}
|
|
18543
18687
|
return out;
|
|
18544
18688
|
}
|
|
18545
18689
|
function mapLayers(s, f) {
|
|
18546
|
-
const
|
|
18547
|
-
|
|
18548
|
-
|
|
18690
|
+
const each = (from) => {
|
|
18691
|
+
const layers = /* @__PURE__ */ new Map();
|
|
18692
|
+
for (const [k, l] of from) layers.set(k, f(l));
|
|
18693
|
+
return layers;
|
|
18694
|
+
};
|
|
18695
|
+
return {
|
|
18696
|
+
layers: each(s.layers),
|
|
18697
|
+
parts: s.parts.map((p) => ({ ...p, layers: each(p.layers) }))
|
|
18698
|
+
};
|
|
18549
18699
|
}
|
|
18550
18700
|
}
|
|
18551
18701
|
};
|
|
@@ -18556,7 +18706,18 @@ var n = (v) => {
|
|
|
18556
18706
|
return Object.is(r, -0) ? "0" : String(r);
|
|
18557
18707
|
};
|
|
18558
18708
|
var esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/"/g, """);
|
|
18559
|
-
|
|
18709
|
+
function tidy(p, closed) {
|
|
18710
|
+
const out = [];
|
|
18711
|
+
for (const [x, y] of p) {
|
|
18712
|
+
const q = [n(x), n(y)];
|
|
18713
|
+
const prev = out[out.length - 1];
|
|
18714
|
+
if (!prev || prev[0] !== q[0] || prev[1] !== q[1]) out.push(q);
|
|
18715
|
+
}
|
|
18716
|
+
while (closed && out.length > 1 && out[0][0] === out[out.length - 1][0] && out[0][1] === out[out.length - 1][1])
|
|
18717
|
+
out.pop();
|
|
18718
|
+
return out;
|
|
18719
|
+
}
|
|
18720
|
+
var d = (p, closed) => `M${tidy(p, closed).map(([x, y]) => `${x} ${y}`).join("L")}${closed ? "Z" : ""}`;
|
|
18560
18721
|
function layerPaths(items, layers) {
|
|
18561
18722
|
const out = [];
|
|
18562
18723
|
for (const def of layers) {
|
|
@@ -18673,11 +18834,14 @@ function toDxf(items, _width, height, layers) {
|
|
|
18673
18834
|
g(20, 0);
|
|
18674
18835
|
g(30, 0);
|
|
18675
18836
|
g(70, closed ? 1 : 0);
|
|
18676
|
-
for (const [x, y] of
|
|
18837
|
+
for (const [x, y] of tidy(
|
|
18838
|
+
p.map(([x2, y2]) => [x2, height - y2]),
|
|
18839
|
+
closed
|
|
18840
|
+
)) {
|
|
18677
18841
|
g(0, "VERTEX");
|
|
18678
18842
|
g(8, layer);
|
|
18679
|
-
g(10,
|
|
18680
|
-
g(20,
|
|
18843
|
+
g(10, x);
|
|
18844
|
+
g(20, y);
|
|
18681
18845
|
g(30, 0);
|
|
18682
18846
|
}
|
|
18683
18847
|
g(0, "SEQEND");
|
|
@@ -18715,13 +18879,17 @@ function render(source, options = {}) {
|
|
|
18715
18879
|
overrides: options.params,
|
|
18716
18880
|
resolve: options.resolve,
|
|
18717
18881
|
fonts,
|
|
18718
|
-
maxSteps: options.maxSteps
|
|
18882
|
+
maxSteps: options.maxSteps,
|
|
18883
|
+
limits: options.limits
|
|
18719
18884
|
});
|
|
18885
|
+
const limits = ev.limits;
|
|
18720
18886
|
let res;
|
|
18721
18887
|
try {
|
|
18722
18888
|
res = ev.run(program);
|
|
18723
18889
|
} catch (e) {
|
|
18724
|
-
const err = e instanceof RangeError
|
|
18890
|
+
const err = e instanceof RangeError ? new KerfError(
|
|
18891
|
+
/call stack/i.test(e.message) ? "Recursion too deep: the program calls itself without stopping" : "A value grew too large. Is a list or string doubling without end?"
|
|
18892
|
+
) : e;
|
|
18725
18893
|
if (err instanceof KerfError) {
|
|
18726
18894
|
err.echoes = ev.echoes;
|
|
18727
18895
|
if (fonts?.missing.size) err.missingFonts = [...fonts.missing];
|
|
@@ -18778,6 +18946,8 @@ function render(source, options = {}) {
|
|
|
18778
18946
|
}
|
|
18779
18947
|
const b = layerBounds(layers) ?? [0, 0, 0, 0];
|
|
18780
18948
|
const kerf = options.kerf ?? p.kerf;
|
|
18949
|
+
if (!(Number.isFinite(kerf) && kerf >= 0))
|
|
18950
|
+
throw new KerfError("$kerf must be a number, 0 or more");
|
|
18781
18951
|
const info = {
|
|
18782
18952
|
name: p.name,
|
|
18783
18953
|
qty: p.qty,
|
|
@@ -18804,11 +18974,27 @@ function render(source, options = {}) {
|
|
|
18804
18974
|
infos.push(info);
|
|
18805
18975
|
ready.push({ info, layers });
|
|
18806
18976
|
}
|
|
18977
|
+
let outputPoints = 0;
|
|
18978
|
+
for (const r of ready) {
|
|
18979
|
+
let n2 = 0;
|
|
18980
|
+
for (const l of r.layers.values()) {
|
|
18981
|
+
for (const p of l.regions) n2 += p.length;
|
|
18982
|
+
for (const p of l.lines) n2 += p.length;
|
|
18983
|
+
}
|
|
18984
|
+
outputPoints += n2 * r.info.qty;
|
|
18985
|
+
}
|
|
18986
|
+
if (outputPoints > limits.maxOutputPoints)
|
|
18987
|
+
throw new KerfError(
|
|
18988
|
+
`The files would have ${outputPoints} points, more than the limit of ${limits.maxOutputPoints}. Use fewer copies or simpler shapes.`
|
|
18989
|
+
);
|
|
18807
18990
|
const sheetSize = options.sheet ?? g("$sheet");
|
|
18808
|
-
if (!Array.isArray(sheetSize) ||
|
|
18809
|
-
throw new KerfError("$sheet must be [width, height]");
|
|
18991
|
+
if (!Array.isArray(sheetSize) || !(Number.isFinite(sheetSize[0]) && sheetSize[0] > 0) || !(Number.isFinite(sheetSize[1]) && sheetSize[1] > 0))
|
|
18992
|
+
throw new KerfError("$sheet must be [width, height], both more than 0");
|
|
18810
18993
|
const gap = options.gap ?? Number(g("$gap") ?? 3);
|
|
18811
18994
|
const margin = options.margin ?? gap;
|
|
18995
|
+
if (!(Number.isFinite(gap) && gap >= 0)) throw new KerfError("$gap must be a number, 0 or more");
|
|
18996
|
+
if (!(Number.isFinite(margin) && margin >= 0))
|
|
18997
|
+
throw new KerfError("margin must be a number, 0 or more");
|
|
18812
18998
|
const layoutMode = options.layout ?? (g("$layout") === "none" ? "none" : "pack");
|
|
18813
18999
|
const order = [
|
|
18814
19000
|
"engrave",
|
|
@@ -18836,8 +19022,8 @@ function render(source, options = {}) {
|
|
|
18836
19022
|
for (const it of items)
|
|
18837
19023
|
for (const [k, l] of it.layers) {
|
|
18838
19024
|
const t = all.get(k) ?? { regions: [], lines: [] };
|
|
18839
|
-
t.regions.push(
|
|
18840
|
-
t.lines.push(
|
|
19025
|
+
for (const p of l.regions) t.regions.push(p);
|
|
19026
|
+
for (const p of l.lines) t.lines.push(p);
|
|
18841
19027
|
all.set(k, t);
|
|
18842
19028
|
}
|
|
18843
19029
|
const b = exportBounds(all);
|
|
@@ -18879,6 +19065,10 @@ function render(source, options = {}) {
|
|
|
18879
19065
|
let items = [];
|
|
18880
19066
|
let x = margin, y = margin, shelf = 0, usedW = 0, usedH = 0;
|
|
18881
19067
|
const flush = () => {
|
|
19068
|
+
if (items.length && sheets.length >= limits.maxSheets)
|
|
19069
|
+
throw new KerfError(
|
|
19070
|
+
`The parts need more than ${limits.maxSheets} sheets, the limit. Use fewer copies or a bigger $sheet.`
|
|
19071
|
+
);
|
|
18882
19072
|
if (items.length)
|
|
18883
19073
|
sheets.push(
|
|
18884
19074
|
finishSheet(
|
|
@@ -19037,7 +19227,7 @@ function parameters(source) {
|
|
|
19037
19227
|
}
|
|
19038
19228
|
|
|
19039
19229
|
// src/index.ts
|
|
19040
|
-
var VERSION = "0.2.
|
|
19230
|
+
var VERSION = "0.2.1";
|
|
19041
19231
|
var LANGUAGE_VERSION = "0.1";
|
|
19042
19232
|
|
|
19043
19233
|
// src/cli.ts
|