lineadraw 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -14
- package/dist/{chunk-BQCSFVAF.js → chunk-YYJAXJOY.js} +4037 -1180
- package/dist/chunk-YYJAXJOY.js.map +1 -0
- package/dist/{exportDxf-T2RTSTH5.js → exportDxf-C4CLQCC3.js} +2 -2
- package/dist/sdk.d.ts +259 -42
- package/dist/sdk.js +127 -66
- package/dist/sdk.js.map +1 -1
- package/lineadraw.d.ts +505 -37
- package/package.json +2 -2
- package/templates/README.md +6 -4
- package/dist/chunk-BQCSFVAF.js.map +0 -1
- /package/dist/{exportDxf-T2RTSTH5.js.map → exportDxf-C4CLQCC3.js.map} +0 -0
package/dist/sdk.js
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
EXTRACTED_EXTRAS,
|
|
18
18
|
EXTRACTED_RANGES,
|
|
19
19
|
FONTS,
|
|
20
|
-
HEX_COLOR,
|
|
21
20
|
HatchPatternSchema,
|
|
22
21
|
LineTypeSchema,
|
|
23
22
|
MAX_HATCH_SEGMENTS,
|
|
@@ -28,6 +27,7 @@ import {
|
|
|
28
27
|
TextStyleSchema,
|
|
29
28
|
Vec2Schema,
|
|
30
29
|
aciToHex,
|
|
30
|
+
acquireInputTable,
|
|
31
31
|
add,
|
|
32
32
|
angle,
|
|
33
33
|
approximateTextMeasurer,
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
blockPivot,
|
|
38
38
|
blockScriptId,
|
|
39
39
|
bytesToDataUrl,
|
|
40
|
+
checkNamedInputs,
|
|
40
41
|
cleanRichText,
|
|
41
42
|
cleanText,
|
|
42
43
|
closestPointOnSegment,
|
|
@@ -50,9 +51,10 @@ import {
|
|
|
50
51
|
dimensionRawToLabels,
|
|
51
52
|
dimensionRawToOffset,
|
|
52
53
|
dist,
|
|
54
|
+
documentBlocks,
|
|
53
55
|
documentObjectResolver,
|
|
54
56
|
dot,
|
|
55
|
-
|
|
57
|
+
dryRunBlockPlacement,
|
|
56
58
|
dryRunObjectResolver,
|
|
57
59
|
effectiveTextFont,
|
|
58
60
|
ellipseArcToBeziers,
|
|
@@ -73,14 +75,20 @@ import {
|
|
|
73
75
|
hashAsset,
|
|
74
76
|
hatchPatternKey,
|
|
75
77
|
hexToRgb,
|
|
78
|
+
hostedClosure,
|
|
76
79
|
imagePixelSize,
|
|
80
|
+
inputLabel,
|
|
81
|
+
inputPoints,
|
|
82
|
+
inputRefs,
|
|
77
83
|
invalidateBlockCache,
|
|
84
|
+
isRequiredInput,
|
|
78
85
|
len,
|
|
79
86
|
lineSegments,
|
|
80
87
|
lineTypeKey,
|
|
81
88
|
lineWeightToMm,
|
|
82
89
|
linearAxis,
|
|
83
90
|
listBlockMeta,
|
|
91
|
+
mapInputValues,
|
|
84
92
|
matApply,
|
|
85
93
|
matIdentity,
|
|
86
94
|
matMultiply,
|
|
@@ -92,7 +100,9 @@ import {
|
|
|
92
100
|
norm,
|
|
93
101
|
normAngle,
|
|
94
102
|
normalizeSpans,
|
|
103
|
+
paramMismatch,
|
|
95
104
|
parseFontFace,
|
|
105
|
+
parseInputTable,
|
|
96
106
|
parseParamsExport,
|
|
97
107
|
perp,
|
|
98
108
|
realFace,
|
|
@@ -107,7 +117,9 @@ import {
|
|
|
107
117
|
rotateObject,
|
|
108
118
|
scale,
|
|
109
119
|
scaleObjectUniform,
|
|
120
|
+
scanScriptId,
|
|
110
121
|
scriptTranspilerReady,
|
|
122
|
+
selectionFits,
|
|
111
123
|
signedArcSweep,
|
|
112
124
|
sub,
|
|
113
125
|
tableLayout,
|
|
@@ -121,8 +133,9 @@ import {
|
|
|
121
133
|
textStyleFor,
|
|
122
134
|
textWidth,
|
|
123
135
|
translateObject,
|
|
124
|
-
valueParams
|
|
125
|
-
|
|
136
|
+
valueParams,
|
|
137
|
+
withEmptyLists
|
|
138
|
+
} from "./chunk-YYJAXJOY.js";
|
|
126
139
|
import {
|
|
127
140
|
embeddedPdfFonts
|
|
128
141
|
} from "./chunk-L4FNH35X.js";
|
|
@@ -1682,10 +1695,8 @@ var buildEntry = (obj, ctx) => {
|
|
|
1682
1695
|
};
|
|
1683
1696
|
}
|
|
1684
1697
|
case "block": {
|
|
1685
|
-
const
|
|
1686
|
-
|
|
1687
|
-
);
|
|
1688
|
-
const points = (inputPoints.length > 0 ? inputPoints : [blockPivot(obj)]).map((p) => ({ p, type: "endpoint" }));
|
|
1698
|
+
const pts = inputPoints(obj.inputs);
|
|
1699
|
+
const points = (pts.length > 0 ? pts : inputRefs(obj.inputs).length > 0 ? [] : [blockPivot(obj)]).map((p) => ({ p, type: "endpoint" }));
|
|
1689
1700
|
const segments = [];
|
|
1690
1701
|
const arcs = [];
|
|
1691
1702
|
const ellipses = [];
|
|
@@ -4983,7 +4994,10 @@ var contentFromDocument = (doc, refId, bounds = emptyBounds()) => {
|
|
|
4983
4994
|
(o) => o.type === "block" ? {
|
|
4984
4995
|
...o,
|
|
4985
4996
|
id: prefix + o.id,
|
|
4986
|
-
inputs:
|
|
4997
|
+
inputs: mapInputValues(
|
|
4998
|
+
o.inputs,
|
|
4999
|
+
(v) => typeof v === "string" ? prefix + v : v
|
|
5000
|
+
)
|
|
4987
5001
|
} : { ...o, id: prefix + o.id }
|
|
4988
5002
|
);
|
|
4989
5003
|
const byId = new Map(objects.map((o) => [o.id, o]));
|
|
@@ -5344,7 +5358,7 @@ var renderBlockThumbnailSvg = async (script, {
|
|
|
5344
5358
|
} = {}) => {
|
|
5345
5359
|
await ensureScriptTranspiler();
|
|
5346
5360
|
const defId = getBlockMeta(script).id;
|
|
5347
|
-
const inputs = await
|
|
5361
|
+
const { inputs, params } = await dryRunBlockPlacement(script);
|
|
5348
5362
|
const defs = [script];
|
|
5349
5363
|
const present = /* @__PURE__ */ new Set([defId]);
|
|
5350
5364
|
for (const extra of definitions) {
|
|
@@ -5360,7 +5374,7 @@ var renderBlockThumbnailSvg = async (script, {
|
|
|
5360
5374
|
definitionId: defId,
|
|
5361
5375
|
rotation: 0,
|
|
5362
5376
|
scale: 1,
|
|
5363
|
-
params
|
|
5377
|
+
params,
|
|
5364
5378
|
inputs
|
|
5365
5379
|
};
|
|
5366
5380
|
const env = {
|
|
@@ -5526,8 +5540,23 @@ var OptionalMetaSchema = z3.object({
|
|
|
5526
5540
|
version: z3.string().optional(),
|
|
5527
5541
|
authors: z3.array(z3.string()).optional(),
|
|
5528
5542
|
tags: z3.array(z3.string()).optional(),
|
|
5529
|
-
|
|
5543
|
+
requiresEditor: z3.boolean().optional()
|
|
5530
5544
|
});
|
|
5545
|
+
var isInputTable = (inputs) => inputs !== void 0 && inputs.length > 0 && typeof inputs[0] !== "string";
|
|
5546
|
+
var parseCommandInputs = (raw, params) => {
|
|
5547
|
+
if (raw === void 0) return void 0;
|
|
5548
|
+
if (Array.isArray(raw) && raw.every((l) => typeof l === "string")) {
|
|
5549
|
+
if (raw.some((l) => l === ""))
|
|
5550
|
+
throw new Error("Invalid command metadata \u2014 inputs: empty label");
|
|
5551
|
+
return raw;
|
|
5552
|
+
}
|
|
5553
|
+
const table = parseInputTable(raw, params);
|
|
5554
|
+
if (table?.some((d) => d.type === "host"))
|
|
5555
|
+
throw new Error(
|
|
5556
|
+
"Invalid command metadata \u2014 inputs: `host` is a block input (a command has no frame to live in)"
|
|
5557
|
+
);
|
|
5558
|
+
return table;
|
|
5559
|
+
};
|
|
5531
5560
|
var extractCommandMeta = (mod) => {
|
|
5532
5561
|
if (typeof mod.id !== "string" || mod.id.trim() === "")
|
|
5533
5562
|
throw new Error("Command script must export a non-empty string `id`");
|
|
@@ -5541,10 +5570,12 @@ var extractCommandMeta = (mod) => {
|
|
|
5541
5570
|
);
|
|
5542
5571
|
}
|
|
5543
5572
|
const params = parseParamsExport(mod.params);
|
|
5573
|
+
const inputs = parseCommandInputs(mod.inputs, params);
|
|
5544
5574
|
return {
|
|
5545
5575
|
id: mod.id,
|
|
5546
5576
|
name: mod.name,
|
|
5547
5577
|
...parsed.data,
|
|
5578
|
+
...inputs ? { inputs } : {},
|
|
5548
5579
|
...params.length > 0 ? { params } : {}
|
|
5549
5580
|
};
|
|
5550
5581
|
};
|
|
@@ -5583,16 +5614,11 @@ var getCommandMetaResult = (script) => {
|
|
|
5583
5614
|
};
|
|
5584
5615
|
var listCommandMeta = (scripts) => scripts.map(getCommandMetaResult);
|
|
5585
5616
|
var getCommandRun = (script) => compileCommand(script).run;
|
|
5586
|
-
var ID_EXPORT_RE = /export\s+const\s+id\s*=\s*["']([^"']+)["']/;
|
|
5587
5617
|
var commandScriptId = (script) => {
|
|
5588
5618
|
try {
|
|
5589
5619
|
return compileCommand(script).meta.id;
|
|
5590
5620
|
} catch {
|
|
5591
|
-
|
|
5592
|
-
if (named) return named[1];
|
|
5593
|
-
const call = script.search(/defineCommand\s*\(|export\s+default\s*\{/);
|
|
5594
|
-
if (call === -1) return void 0;
|
|
5595
|
-
return /\bid\s*:\s*["']([^"']+)["']/.exec(script.slice(call))?.[1];
|
|
5621
|
+
return scanScriptId(script, /defineCommand\s*\(|export\s+default\s*\{/);
|
|
5596
5622
|
}
|
|
5597
5623
|
};
|
|
5598
5624
|
var mergeCommandModules = (existing, incoming) => mergeScriptModules(existing, incoming, {
|
|
@@ -8171,7 +8197,9 @@ var invalidationIds = (op) => {
|
|
|
8171
8197
|
switch (op.type) {
|
|
8172
8198
|
case "add-objects":
|
|
8173
8199
|
case "update-objects":
|
|
8174
|
-
return op.objects.
|
|
8200
|
+
return op.objects.flatMap(
|
|
8201
|
+
(o) => o.type === "block" ? [o.id, ...inputRefs(o.inputs)] : [o.id]
|
|
8202
|
+
);
|
|
8175
8203
|
case "remove-objects":
|
|
8176
8204
|
return op.ids;
|
|
8177
8205
|
case "set-current-layer":
|
|
@@ -9312,7 +9340,12 @@ var LocalDrawing = class {
|
|
|
9312
9340
|
/** Delete objects by id (unknown ids are skipped); returns how many went. */
|
|
9313
9341
|
remove(ids) {
|
|
9314
9342
|
const entries = [];
|
|
9315
|
-
|
|
9343
|
+
const all = hostedClosure(
|
|
9344
|
+
ids,
|
|
9345
|
+
this.state.blockDefinitions,
|
|
9346
|
+
documentBlocks(this.state)
|
|
9347
|
+
);
|
|
9348
|
+
for (const id of all) {
|
|
9316
9349
|
try {
|
|
9317
9350
|
entries.push({ space: this.findObject(id).space, item: id });
|
|
9318
9351
|
} catch {
|
|
@@ -9614,7 +9647,7 @@ var LocalDrawing = class {
|
|
|
9614
9647
|
}
|
|
9615
9648
|
/** Export the document to a DXF string. */
|
|
9616
9649
|
async toDxf() {
|
|
9617
|
-
const { buildDxf } = await import("./exportDxf-
|
|
9650
|
+
const { buildDxf } = await import("./exportDxf-C4CLQCC3.js");
|
|
9618
9651
|
return buildDxf(this.state, this.measurer).content;
|
|
9619
9652
|
}
|
|
9620
9653
|
/** Export the document to DWG bytes (the DXF content, wasm-transcoded).
|
|
@@ -9623,7 +9656,7 @@ var LocalDrawing = class {
|
|
|
9623
9656
|
* exploded to plain geometry (DWG_DXF_OPTIONS — the transcoder's DWG
|
|
9624
9657
|
* output for them is not accepted by AutoCAD). */
|
|
9625
9658
|
async toDwg(opts) {
|
|
9626
|
-
const { buildDxf, DWG_DXF_OPTIONS } = await import("./exportDxf-
|
|
9659
|
+
const { buildDxf, DWG_DXF_OPTIONS } = await import("./exportDxf-C4CLQCC3.js");
|
|
9627
9660
|
const dxf = buildDxf(this.state, this.measurer, DWG_DXF_OPTIONS).content;
|
|
9628
9661
|
return dxfToDwg(dxf, opts?.version ?? "AC1027");
|
|
9629
9662
|
}
|
|
@@ -9642,46 +9675,6 @@ var makeContext = (opts, inputs, params) => {
|
|
|
9642
9675
|
params
|
|
9643
9676
|
};
|
|
9644
9677
|
};
|
|
9645
|
-
var paramMismatch = (def, value) => {
|
|
9646
|
-
switch (def.type) {
|
|
9647
|
-
case "number":
|
|
9648
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
9649
|
-
return "expected a number";
|
|
9650
|
-
if (def.integer && !Number.isInteger(value))
|
|
9651
|
-
return "expected a whole number";
|
|
9652
|
-
if (def.min !== void 0 && value < def.min)
|
|
9653
|
-
return `below the minimum ${def.min}`;
|
|
9654
|
-
if (def.max !== void 0 && value > def.max)
|
|
9655
|
-
return `above the maximum ${def.max}`;
|
|
9656
|
-
return null;
|
|
9657
|
-
case "string":
|
|
9658
|
-
case "textStyle":
|
|
9659
|
-
case "dimStyle":
|
|
9660
|
-
case "font":
|
|
9661
|
-
case "lineType":
|
|
9662
|
-
case "hatchPattern":
|
|
9663
|
-
return typeof value === "string" ? null : "expected a string";
|
|
9664
|
-
case "boolean":
|
|
9665
|
-
return typeof value === "boolean" ? null : "expected true or false";
|
|
9666
|
-
case "numberList": {
|
|
9667
|
-
if (!Array.isArray(value) || !value.every((v) => typeof v === "number" && Number.isFinite(v)))
|
|
9668
|
-
return "expected an array of numbers";
|
|
9669
|
-
const low = value.find((v) => def.min !== void 0 && v < def.min);
|
|
9670
|
-
if (low !== void 0) return `${low} is below the minimum ${def.min}`;
|
|
9671
|
-
const high = value.find((v) => def.max !== void 0 && v > def.max);
|
|
9672
|
-
if (high !== void 0) return `${high} is above the maximum ${def.max}`;
|
|
9673
|
-
return null;
|
|
9674
|
-
}
|
|
9675
|
-
case "color":
|
|
9676
|
-
return typeof value === "string" && HEX_COLOR.test(value) ? null : 'expected a "#rrggbb" color';
|
|
9677
|
-
case "stringList":
|
|
9678
|
-
return Array.isArray(value) && value.every((v) => typeof v === "string") ? null : "expected an array of strings";
|
|
9679
|
-
case "enum":
|
|
9680
|
-
return def.options.some((o) => o.value === value) ? null : `expected one of ${def.options.map((o) => JSON.stringify(o.value)).join(", ")}`;
|
|
9681
|
-
default:
|
|
9682
|
-
return "a label carries no value";
|
|
9683
|
-
}
|
|
9684
|
-
};
|
|
9685
9678
|
var resolveCommandParams = (meta, given = {}) => {
|
|
9686
9679
|
const defs = valueParams(meta.params ?? []);
|
|
9687
9680
|
const params = /* @__PURE__ */ Object.create(null);
|
|
@@ -9699,8 +9692,57 @@ var resolveCommandParams = (meta, given = {}) => {
|
|
|
9699
9692
|
}
|
|
9700
9693
|
return params;
|
|
9701
9694
|
};
|
|
9695
|
+
var surfacePickers = (editor, document) => {
|
|
9696
|
+
let selectionUsed = false;
|
|
9697
|
+
const fromSelection = (def) => {
|
|
9698
|
+
if (selectionUsed) return null;
|
|
9699
|
+
const selected = editor.state().selectedIds.map((id) => document.getObject(id)).filter((o) => o !== void 0);
|
|
9700
|
+
if (!selectionFits(def, selected)) return null;
|
|
9701
|
+
selectionUsed = true;
|
|
9702
|
+
return selected.map((o) => o.id);
|
|
9703
|
+
};
|
|
9704
|
+
return {
|
|
9705
|
+
point: (def, ref) => editor.pickPoint({ label: inputLabel(def), referencePoint: ref }),
|
|
9706
|
+
points: (def, ref) => editor.pickPoints({ ...def, referencePoint: ref }),
|
|
9707
|
+
object: async (def) => fromSelection({ types: def.types, min: 1, max: 1 })?.[0] ?? editor.pickObject({ label: inputLabel(def), types: def.types }),
|
|
9708
|
+
objects: async (def) => fromSelection(def) ?? editor.pickObjects(def)
|
|
9709
|
+
};
|
|
9710
|
+
};
|
|
9711
|
+
var acquireNamedCommandInputs = async (meta, table, opts) => {
|
|
9712
|
+
const { inputs, missing } = checkNamedInputs(
|
|
9713
|
+
meta.name,
|
|
9714
|
+
table,
|
|
9715
|
+
opts.inputs,
|
|
9716
|
+
(id) => opts.document.getObject(id)
|
|
9717
|
+
);
|
|
9718
|
+
if (!opts.editor) {
|
|
9719
|
+
const required = missing.filter(isRequiredInput);
|
|
9720
|
+
if (required.length > 0)
|
|
9721
|
+
throw new Error(
|
|
9722
|
+
`${meta.name} needs an editor for: ${required.map((d) => d.name).join(", ")} \u2014 supply inputs`
|
|
9723
|
+
);
|
|
9724
|
+
return withEmptyLists(table, inputs);
|
|
9725
|
+
}
|
|
9726
|
+
if (missing.length === 0) return inputs;
|
|
9727
|
+
const picked = await acquireInputTable(
|
|
9728
|
+
missing,
|
|
9729
|
+
surfacePickers(opts.editor, opts.document)
|
|
9730
|
+
);
|
|
9731
|
+
const out = {};
|
|
9732
|
+
for (const def of table) {
|
|
9733
|
+
const v = inputs[def.name] ?? picked[def.name];
|
|
9734
|
+
if (v !== void 0) out[def.name] = v;
|
|
9735
|
+
}
|
|
9736
|
+
return out;
|
|
9737
|
+
};
|
|
9702
9738
|
var acquireCommandInputs = async (meta, opts) => {
|
|
9739
|
+
if (isInputTable(meta.inputs))
|
|
9740
|
+
return acquireNamedCommandInputs(meta, meta.inputs, opts);
|
|
9703
9741
|
const labels = meta.inputs ?? [];
|
|
9742
|
+
if (opts.inputs !== void 0 && !Array.isArray(opts.inputs))
|
|
9743
|
+
throw new Error(
|
|
9744
|
+
`${meta.name}: inputs are positional (${labels.join(", ") || "none declared"}) \u2014 pass an array`
|
|
9745
|
+
);
|
|
9704
9746
|
const given = (opts.inputs ?? []).map((p, i) => {
|
|
9705
9747
|
try {
|
|
9706
9748
|
return Vec2Schema.parse(p);
|
|
@@ -9732,11 +9774,29 @@ var runCommandModule = async (source, opts) => {
|
|
|
9732
9774
|
const result = getCommandMetaResult(source);
|
|
9733
9775
|
if (!result.ok) throw new Error(`Command failed to compile: ${result.error}`);
|
|
9734
9776
|
const run = getCommandRun(source);
|
|
9777
|
+
if (result.meta.requiresEditor && !opts.editor)
|
|
9778
|
+
throw new Error(
|
|
9779
|
+
`${result.meta.name} needs the editor (it asks during the run) \u2014 run it from Linea`
|
|
9780
|
+
);
|
|
9735
9781
|
const params = resolveCommandParams(result.meta, opts.params);
|
|
9736
9782
|
const inputs = await acquireCommandInputs(result.meta, opts);
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
|
|
9783
|
+
try {
|
|
9784
|
+
return await opts.document.transaction(
|
|
9785
|
+
() => run(makeContext(opts, inputs, params)),
|
|
9786
|
+
result.meta.name
|
|
9787
|
+
);
|
|
9788
|
+
} catch (e) {
|
|
9789
|
+
throw opts.editor ? e : namedEditorError(result.meta.name, e);
|
|
9790
|
+
}
|
|
9791
|
+
};
|
|
9792
|
+
var namedEditorError = (name, e) => {
|
|
9793
|
+
const m = e instanceof TypeError ? /reading '(pickPoint|pickPoints|pickObject|pickObjects|prompt|ask|toast|state|setSelection|setActiveSpace|zoom|listCommands|runCommand)'/.exec(
|
|
9794
|
+
e.message
|
|
9795
|
+
) : null;
|
|
9796
|
+
if (!m) return e;
|
|
9797
|
+
return new Error(
|
|
9798
|
+
`${name} used editor.${m[1]} but runs without an editor here \u2014 check \`editor\` before using it, or declare \`requiresEditor: true\``,
|
|
9799
|
+
{ cause: e }
|
|
9740
9800
|
);
|
|
9741
9801
|
};
|
|
9742
9802
|
var runDocumentCommand = async (id, opts) => {
|
|
@@ -9982,7 +10042,8 @@ var Drawing = class extends LocalDrawing {
|
|
|
9982
10042
|
}
|
|
9983
10043
|
// --- scripts ---------------------------------------------------------------
|
|
9984
10044
|
/** Run a command module source (`defineCommand`) against this drawing as
|
|
9985
|
-
* ONE undo step, headlessly: declared `inputs` must be supplied
|
|
10045
|
+
* ONE undo step, headlessly: declared `inputs` must be supplied (points
|
|
10046
|
+
* in label order, or a record by name for an inputs table); declared
|
|
9986
10047
|
* `params` take their defaults unless given by name (unknown names and
|
|
9987
10048
|
* wrong types throw). Resolves with the script's return value. */
|
|
9988
10049
|
runScript(source, inputs, params) {
|