lineadraw 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk.js CHANGED
@@ -1,3 +1,10 @@
1
+ import {
2
+ BridgeError,
3
+ DEFAULT_BRIDGE_PORT,
4
+ bridgeFilePath,
5
+ connectEditors,
6
+ createBridge
7
+ } from "./chunk-L2CWZAKW.js";
1
8
  import {
2
9
  ADVANCE_TABLES,
3
10
  ANSI31_BASE_SPACING,
@@ -15,6 +22,7 @@ import {
15
22
  LineTypeSchema,
16
23
  MAX_HATCH_SEGMENTS,
17
24
  ModelObjectSchema,
25
+ PX_TO_MM,
18
26
  REAL_FACES,
19
27
  REFERENCE_FORMATS,
20
28
  TextStyleSchema,
@@ -28,11 +36,13 @@ import {
28
36
  blockDefinitionExists,
29
37
  blockPivot,
30
38
  blockScriptId,
39
+ bytesToDataUrl,
31
40
  cleanRichText,
32
41
  cleanText,
33
42
  closestPointOnSegment,
34
43
  computeHatchLines,
35
44
  computePatternGeometry,
45
+ dataUrlBytes,
36
46
  decodeTextEscapes,
37
47
  dimFontFace,
38
48
  dimStyleFor,
@@ -46,6 +56,7 @@ import {
46
56
  dryRunObjectResolver,
47
57
  effectiveTextFont,
48
58
  ellipseArcToBeziers,
59
+ embeddedAssetId,
49
60
  ensureScriptTranspiler,
50
61
  estimatePatternSegments,
51
62
  executeScriptModule,
@@ -59,10 +70,10 @@ import {
59
70
  getEvaluatedWorldChildren,
60
71
  getHatchPattern,
61
72
  getLineType,
73
+ hashAsset,
62
74
  hatchPatternKey,
63
75
  hexToRgb,
64
- imageCenter,
65
- imageCorners,
76
+ imagePixelSize,
66
77
  invalidateBlockCache,
67
78
  len,
68
79
  lineSegments,
@@ -111,7 +122,7 @@ import {
111
122
  textWidth,
112
123
  translateObject,
113
124
  valueParams
114
- } from "./chunk-VWED6V6F.js";
125
+ } from "./chunk-BQCSFVAF.js";
115
126
  import {
116
127
  embeddedPdfFonts
117
128
  } from "./chunk-L4FNH35X.js";
@@ -446,9 +457,10 @@ var LineaDocumentSchema = z2.preprocess(
446
457
  /** Document-defined hatch patterns (model/hatchPatterns.ts), same model. */
447
458
  hatchPatterns: z2.array(HatchPatternSchema).default([]),
448
459
  /**
449
- * Embedded binary assets for image objects: content hash → data URL.
450
- * Kept IN the document so the .linea file stays self-contained (the
451
- * cost is base64 in the JSON). Entries orphaned by deleted images just
460
+ * Embedded files (the bytes of `asset`-source references — PNG, JPEG,
461
+ * PDF, DXF, DWG, .linea): content hash → data URL. Kept IN the document
462
+ * so the .linea file stays self-contained (the cost is base64 in the
463
+ * JSON). Entries orphaned by deleted references just
452
464
  * ride along (no GC — deletion is undoable, so eager sweeps would break
453
465
  * redo).
454
466
  */
@@ -513,14 +525,6 @@ function emptyDocument() {
513
525
  });
514
526
  }
515
527
 
516
- // ../core/src/model/assets.ts
517
- var hashAsset = (data) => {
518
- let h = 5381;
519
- for (let i = 0; i < data.length; i++)
520
- h = (h << 5) + h + data.charCodeAt(i) | 0;
521
- return `${(h >>> 0).toString(16)}-${data.length.toString(16)}`;
522
- };
523
-
524
528
  // ../core/src/serialize.ts
525
529
  var documentToJson = (doc) => JSON.stringify(doc, null, 2);
526
530
  var documentFromJson = (text) => LineaDocumentSchema.parse(JSON.parse(text));
@@ -1240,7 +1244,9 @@ var paintChildren = (children, sink, env, parentLayerId) => {
1240
1244
  hatchPatterns: env.hatchPatterns,
1241
1245
  blockDefinitions: env.blockDefinitions,
1242
1246
  resolveObject: env.resolveObject,
1243
- assets: env.assets
1247
+ assets: env.assets,
1248
+ // A reference child (linked / embedded file) loads like any other.
1249
+ resolveReference: env.resolveReference
1244
1250
  }
1245
1251
  );
1246
1252
  }
@@ -1258,36 +1264,6 @@ var paintViewport = (obj, sink, env) => {
1258
1264
  sink.stroke({ color: env.style.color, widthMm: env.style.widthMm });
1259
1265
  };
1260
1266
 
1261
- // ../core/src/paint/painters/image.ts
1262
- var paintImage = (obj, sink, env) => {
1263
- const data = env.assets?.[obj.assetId];
1264
- if (data !== void 0 && !env.forceStyle) {
1265
- sink.image({
1266
- data,
1267
- origin: obj.origin,
1268
- widthMm: obj.width,
1269
- heightMm: obj.height,
1270
- rotation: obj.rotation,
1271
- opacity: env.style.opacity ?? 1
1272
- });
1273
- return;
1274
- }
1275
- const [a, b, c, d] = imageCorners(obj);
1276
- sink.beginPath();
1277
- sink.moveTo(a);
1278
- sink.lineTo(b);
1279
- sink.lineTo(c);
1280
- sink.lineTo(d);
1281
- sink.closePath();
1282
- if (data === void 0) {
1283
- sink.moveTo(a);
1284
- sink.lineTo(c);
1285
- sink.moveTo(b);
1286
- sink.lineTo(d);
1287
- }
1288
- sink.stroke(env.style);
1289
- };
1290
-
1291
1267
  // ../core/src/paint/painters/table.ts
1292
1268
  var paintTable = (obj, sink, env) => paintChildren(tableLayout(obj, env.textStyles).children, sink, env);
1293
1269
 
@@ -1757,26 +1733,6 @@ var buildEntry = (obj, ctx) => {
1757
1733
  rings: [outline]
1758
1734
  };
1759
1735
  }
1760
- case "image": {
1761
- const corners = imageCorners(obj);
1762
- const segments = corners.map((c, i) => ({
1763
- a: c,
1764
- b: corners[(i + 1) % corners.length]
1765
- }));
1766
- const points = corners.map((p) => ({
1767
- p,
1768
- type: "endpoint"
1769
- }));
1770
- for (const s of segments)
1771
- points.push({ p: mid(s.a, s.b), type: "midpoint" });
1772
- points.push({ p: imageCenter(obj), type: "center" });
1773
- return {
1774
- bounds: boundsOfPoints(corners),
1775
- points,
1776
- segments,
1777
- arcs: []
1778
- };
1779
- }
1780
1736
  case "comment": {
1781
1737
  const bounds = emptyBounds();
1782
1738
  addPointToBounds(bounds, obj.position);
@@ -4300,10 +4256,9 @@ var convertAcadTable = (e, ctx) => {
4300
4256
  const cell = cells[r * cols + c];
4301
4257
  const raw = cell.text || cell.display || "";
4302
4258
  const a = cell.alignment;
4303
- const rich = cleanRichText(
4304
- raw,
4305
- cell.height && cell.height > 0 ? cell.height : 2.5
4306
- );
4259
+ const inlineHeight = Number(/\\H(\d+(?:\.\d+)?);/.exec(raw)?.[1]);
4260
+ const height = cell.height && cell.height > 0 ? cell.height : inlineHeight > 0 ? inlineHeight : void 0;
4261
+ const rich = cleanRichText(raw, height ?? 2.5);
4307
4262
  const text = rich.content.replace(/\s+$/, "");
4308
4263
  const spans = normalizeSpans(rich.spans, text).filter(
4309
4264
  (s) => s.start > 0 || s.end < text.length
@@ -4317,7 +4272,7 @@ var convertAcadTable = (e, ctx) => {
4317
4272
  vAlign: a <= 3 ? "top" : a <= 6 ? "center" : "bottom"
4318
4273
  } : {},
4319
4274
  styleOverride: {
4320
- ...cell.height && cell.height > 0 ? { textHeight: cell.height * f } : {},
4275
+ ...height !== void 0 ? { textHeight: height * f } : {},
4321
4276
  ...mtextFontFlags(raw)
4322
4277
  }
4323
4278
  };
@@ -4985,7 +4940,7 @@ var dxfToModel = (text, input) => {
4985
4940
 
4986
4941
  // ../core/src/reference/reference.ts
4987
4942
  var rebaseReferenceSource = (child, parent) => {
4988
- if (child.kind === "url" || parent.kind === "url") return child;
4943
+ if (child.kind !== "path" || parent.kind !== "path") return child;
4989
4944
  if (/^([A-Za-z]:[\\/]|[\\/])/.test(child.path)) return child;
4990
4945
  const folder = parent.path.replace(/\\/g, "/").replace(/\/?[^/]*$/, "");
4991
4946
  return { ...child, path: folder ? `${folder}/${child.path}` : child.path };
@@ -5090,39 +5045,43 @@ var documentFromDxf = (text) => documentWithObjects((doc) => {
5090
5045
  ]
5091
5046
  };
5092
5047
  });
5093
- var documentFromImage = (dataUrl, widthMm, heightMm) => {
5094
- const doc = emptyDocument();
5095
- const assetId = hashAsset(dataUrl);
5096
- doc.assets = { [assetId]: dataUrl };
5097
- doc.objects = [
5098
- {
5099
- id: "image",
5100
- type: "image",
5101
- layerId: doc.layers[0].id,
5102
- assetId,
5103
- origin: { x: 0, y: 0 },
5104
- width: widthMm,
5105
- height: heightMm,
5106
- rotation: 0
5107
- }
5048
+ var rasterSnap = (w, h, layer) => {
5049
+ const corners = [
5050
+ { x: 0, y: 0 },
5051
+ { x: w, y: 0 },
5052
+ { x: w, y: h },
5053
+ { x: 0, y: h }
5108
5054
  ];
5109
- return doc;
5055
+ return {
5056
+ points: [
5057
+ ...corners.map((p) => ({ p, type: "endpoint", layer })),
5058
+ ...corners.map((p, i) => {
5059
+ const q = corners[(i + 1) % 4];
5060
+ return {
5061
+ p: { x: (p.x + q.x) / 2, y: (p.y + q.y) / 2 },
5062
+ type: "midpoint",
5063
+ layer
5064
+ };
5065
+ }),
5066
+ { p: { x: w / 2, y: h / 2 }, type: "center", layer }
5067
+ ],
5068
+ segments: corners.map((a, i) => ({ a, b: corners[(i + 1) % 4], layer })),
5069
+ arcs: [],
5070
+ ellipses: []
5071
+ };
5110
5072
  };
5111
- var imagePixelSize = (b) => {
5112
- const u32 = (i) => (b[i] << 24 | b[i + 1] << 16 | b[i + 2] << 8 | b[i + 3]) >>> 0;
5113
- const u16 = (i) => b[i] << 8 | b[i + 1];
5114
- if (b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71)
5115
- return { width: u32(16), height: u32(20) };
5116
- if (b[0] !== 255 || b[1] !== 216) return null;
5117
- for (let i = 2; i + 9 < b.length; ) {
5118
- if (b[i] !== 255) return null;
5119
- const marker = b[i + 1];
5120
- const len2 = u16(i + 2);
5121
- if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204)
5122
- return { width: u16(i + 7), height: u16(i + 5) };
5123
- i += 2 + len2;
5124
- }
5125
- return null;
5073
+ var contentFromRaster = (refId, data, width, height) => {
5074
+ const content = contentFromDocument(emptyDocument(), refId, {
5075
+ minX: 0,
5076
+ minY: 0,
5077
+ maxX: width,
5078
+ maxY: height
5079
+ });
5080
+ return {
5081
+ ...content,
5082
+ raster: { data, width, height },
5083
+ snap: rasterSnap(width, height, content.layers[0].id)
5084
+ };
5126
5085
  };
5127
5086
  var measureContentBounds = (content, measure) => {
5128
5087
  const ctx = {
@@ -5266,6 +5225,26 @@ var paintReference = (obj, sink, env) => {
5266
5225
  w: clip.maxX - clip.minX,
5267
5226
  h: clip.maxY - clip.minY
5268
5227
  });
5228
+ const raster = content.raster;
5229
+ if (raster) {
5230
+ if (env.forceStyle) {
5231
+ out.beginPath();
5232
+ out.moveTo({ x: 0, y: 0 });
5233
+ out.lineTo({ x: raster.width, y: 0 });
5234
+ out.lineTo({ x: raster.width, y: raster.height });
5235
+ out.lineTo({ x: 0, y: raster.height });
5236
+ out.closePath();
5237
+ out.stroke(env.style);
5238
+ } else
5239
+ out.image({
5240
+ data: raster.data,
5241
+ origin: { x: 0, y: 0 },
5242
+ widthMm: raster.width,
5243
+ heightMm: raster.height,
5244
+ rotation: 0,
5245
+ opacity: fade
5246
+ });
5247
+ }
5269
5248
  for (const child of content.objects) {
5270
5249
  if (shown.get(child.layerId) === false) continue;
5271
5250
  const own = resolveStyle(
@@ -5345,7 +5324,6 @@ var painters = {
5345
5324
  dimension: paintDimension,
5346
5325
  block: paintBlockInstance,
5347
5326
  viewport: paintViewport,
5348
- image: paintImage,
5349
5327
  table: paintTable,
5350
5328
  reference: paintReference,
5351
5329
  // Screen-fixed editor chrome — painted by the editor's canvas renderer
@@ -8012,7 +7990,7 @@ var applySetAsset = (doc, op) => {
8012
7990
  };
8013
7991
  };
8014
7992
  var assetInUse = (doc, id) => {
8015
- const used = (objs) => objs.some((o) => o.type === "image" && o.assetId === id);
7993
+ const used = (objs) => objs.some((o) => embeddedAssetId(o) === id);
8016
7994
  return used(doc.objects) || doc.layouts.some((l) => used(l.objects));
8017
7995
  };
8018
7996
  var applyRemoveAsset = (doc, op) => {
@@ -8688,8 +8666,9 @@ var LocalDrawing = class {
8688
8666
  }
8689
8667
  // --- document meta / assets ------------------------------------------------
8690
8668
  /**
8691
- * Embed image pixels (a data URL) and return the assetId that `image`
8692
- * objects reference. Content-keyed: the same data reuses one entry.
8669
+ * Embed a file (a data URL — PNG, JPEG, PDF…) and return the assetId an
8670
+ * embedded reference's `source: { kind: "asset", assetId }` names.
8671
+ * Content-keyed: the same data reuses one entry.
8693
8672
  */
8694
8673
  addAsset(dataUrl) {
8695
8674
  const id = hashAsset(dataUrl);
@@ -8697,7 +8676,7 @@ var LocalDrawing = class {
8697
8676
  this.applyForward({ type: "set-asset", id, dataUrl });
8698
8677
  return id;
8699
8678
  }
8700
- /** Remove an asset (the kernel refuses while an image references it). */
8679
+ /** Remove an asset (the kernel refuses while a reference embeds it). */
8701
8680
  removeAsset(id) {
8702
8681
  this.applyForward({ type: "remove-asset", id });
8703
8682
  }
@@ -8707,9 +8686,10 @@ var LocalDrawing = class {
8707
8686
  this.state.objects,
8708
8687
  ...this.state.layouts.map((l) => l.objects)
8709
8688
  ])
8710
- for (const o of objs)
8711
- if (o.type === "image")
8712
- users.set(o.assetId, (users.get(o.assetId) ?? 0) + 1);
8689
+ for (const o of objs) {
8690
+ const id = embeddedAssetId(o);
8691
+ if (id !== void 0) users.set(id, (users.get(id) ?? 0) + 1);
8692
+ }
8713
8693
  return Object.entries(this.state.assets).map(([id, dataUrl]) => {
8714
8694
  const comma = dataUrl.indexOf(",");
8715
8695
  const base64 = dataUrl.slice(comma + 1);
@@ -8748,7 +8728,8 @@ var LocalDrawing = class {
8748
8728
  return this.importDxfText(await dwgToDxf(data), opts);
8749
8729
  }
8750
8730
  /** Merge a PDF: its vector/text content onto the current layer, or
8751
- * (`as: "image"`) every page as an image at true page scale. */
8731
+ * (`as: "image"`) embedded, every page a raster reference at true page
8732
+ * scale. */
8752
8733
  async importPdfData(data, opts = {}) {
8753
8734
  if (opts.as === "image") {
8754
8735
  if (!this.rasterizePdf)
@@ -8758,15 +8739,20 @@ var LocalDrawing = class {
8758
8739
  const pages = await this.rasterizePdf(data);
8759
8740
  const at = toVec(opts.origin ?? [0, 0]);
8760
8741
  const layerId2 = this.state.currentLayerId;
8742
+ const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
8743
+ const assetId = this.addAsset(bytesToDataUrl(bytes, "application/pdf"));
8761
8744
  let x = at.x;
8762
- const placed = pages.map((p) => {
8745
+ const placed = pages.map((p, i) => {
8763
8746
  const object = {
8764
- type: "image",
8747
+ type: "reference",
8765
8748
  layerId: layerId2,
8766
- assetId: this.addAsset(p.dataUrl),
8767
- origin: { x, y: at.y },
8768
- width: p.widthMm,
8769
- height: p.heightMm
8749
+ format: "pdf",
8750
+ name: pages.length > 1 ? `PDF page ${i + 1}` : "PDF",
8751
+ source: { kind: "asset", assetId },
8752
+ pdfPage: i + 1,
8753
+ pdfMode: "raster",
8754
+ position: { x, y: at.y },
8755
+ extent: { minX: 0, minY: 0, maxX: p.widthMm, maxY: p.heightMm }
8770
8756
  };
8771
8757
  x += p.widthMm + PDF_PAGE_GAP_MM;
8772
8758
  return object;
@@ -8952,10 +8938,6 @@ var LocalDrawing = class {
8952
8938
  id: this.resolveStyle(this.state.dimStyles, nameOrId, "dim style").id
8953
8939
  });
8954
8940
  }
8955
- /** @deprecated Use updateDimStyle (default here: the first style). */
8956
- setDimStyle(patch, styleId) {
8957
- this.updateDimStyle(styleId ?? this.state.dimStyles[0].id, patch);
8958
- }
8959
8941
  /** Replace the document's dimension styles (min 1; objects reference by
8960
8942
  * id). Diffed into granular per-style ops. */
8961
8943
  setDimStyles(styles) {
@@ -8963,10 +8945,6 @@ var LocalDrawing = class {
8963
8945
  assertUniqueIds(parsed, "setDimStyles()");
8964
8946
  this.applyForwardAll(diffDimStyleOps(this.state.dimStyles, parsed));
8965
8947
  }
8966
- /** @deprecated Use updateTextStyle (default here: the first style). */
8967
- setTextStyle(patch, styleId) {
8968
- this.updateTextStyle(styleId ?? this.state.textStyles[0].id, patch);
8969
- }
8970
8948
  /** Replace the document's text styles (min 1; objects reference by id).
8971
8949
  * Diffed into granular per-style ops. */
8972
8950
  setTextStyles(styles) {
@@ -9469,6 +9447,7 @@ var LocalDrawing = class {
9469
9447
  return {
9470
9448
  dimStyles: this.state.dimStyles,
9471
9449
  textStyles: this.state.textStyles,
9450
+ layers: this.state.layers,
9472
9451
  blockDefinitions: this.state.blockDefinitions,
9473
9452
  resolveObject: this.resolveObject(),
9474
9453
  resolveReference: this.resolveReference,
@@ -9635,19 +9614,17 @@ var LocalDrawing = class {
9635
9614
  }
9636
9615
  /** Export the document to a DXF string. */
9637
9616
  async toDxf() {
9638
- const { buildDxf } = await import("./exportDxf-2VU5475O.js");
9617
+ const { buildDxf } = await import("./exportDxf-T2RTSTH5.js");
9639
9618
  return buildDxf(this.state, this.measurer).content;
9640
9619
  }
9641
9620
  /** Export the document to DWG bytes (the DXF content, wasm-transcoded).
9642
9621
  * Defaults to AC1027 (AutoCAD 2013) — readable by every current CAD tool.
9643
- * Dimensions transcode as real DIMENSION objects; leaders are exploded to
9644
- * plain geometry (acadrust's MULTILEADER DWG output is unproven in real
9645
- * CADs — exploded geometry always displays). */
9622
+ * Dimensions transcode as real DIMENSION objects; leaders and tables are
9623
+ * exploded to plain geometry (DWG_DXF_OPTIONS — the transcoder's DWG
9624
+ * output for them is not accepted by AutoCAD). */
9646
9625
  async toDwg(opts) {
9647
- const { buildDxf } = await import("./exportDxf-2VU5475O.js");
9648
- const dxf = buildDxf(this.state, this.measurer, {
9649
- explodeLeaders: true
9650
- }).content;
9626
+ const { buildDxf, DWG_DXF_OPTIONS } = await import("./exportDxf-T2RTSTH5.js");
9627
+ const dxf = buildDxf(this.state, this.measurer, DWG_DXF_OPTIONS).content;
9651
9628
  return dxfToDwg(dxf, opts?.version ?? "AC1027");
9652
9629
  }
9653
9630
  toLinea() {
@@ -9656,24 +9633,13 @@ var LocalDrawing = class {
9656
9633
  };
9657
9634
 
9658
9635
  // ../core/src/drawing/runCommand.ts
9659
- var needsEditor = (what) => () => {
9660
- throw new Error(`${what} needs an editor (this command runs headlessly)`);
9661
- };
9662
9636
  var makeContext = (opts, inputs, params) => {
9663
9637
  const { document, editor } = opts;
9664
9638
  return {
9665
9639
  document,
9666
9640
  editor,
9667
9641
  inputs,
9668
- params,
9669
- // Deprecated shorthands (pre-`editor` wire form) — one release.
9670
- pickPoint: editor ? (label) => editor.pickPoint({ label }) : needsEditor("pickPoint"),
9671
- pickObject: editor ? (label) => editor.pickObject({ label }) : needsEditor("pickObject"),
9672
- selection: editor ? () => editor.state().selectedIds : needsEditor("selection"),
9673
- setSelection: editor ? (ids) => editor.setSelection(ids) : needsEditor("setSelection"),
9674
- prompt: editor ? (message, o) => editor.prompt(message, o) : needsEditor("prompt"),
9675
- showToast: editor ? (message, kind) => editor.toast(message, kind) : () => {
9676
- }
9642
+ params
9677
9643
  };
9678
9644
  };
9679
9645
  var paramMismatch = (def, value) => {
@@ -9824,18 +9790,30 @@ var referenceDocument = async (ref, bytes) => {
9824
9790
  }));
9825
9791
  }
9826
9792
  case "png":
9827
- case "jpg": {
9828
- const size = imagePixelSize(bytes);
9829
- if (!size) throw new Error(`${ref.name}: not a PNG/JPEG`);
9830
- const mime = ref.format === "png" ? "image/png" : "image/jpeg";
9831
- const px = 25.4 / 96;
9832
- return documentFromImage(
9833
- `data:${mime};base64,${Buffer.from(bytes).toString("base64")}`,
9834
- size.width * px,
9835
- size.height * px
9836
- );
9837
- }
9793
+ case "jpg":
9794
+ throw new Error("pictures load as raster content");
9795
+ }
9796
+ };
9797
+ var referenceContent = async (ref, bytes) => {
9798
+ if (ref.format === "png" || ref.format === "jpg") {
9799
+ const size = imagePixelSize(bytes);
9800
+ if (!size) throw new Error(`${ref.name}: not a PNG/JPEG`);
9801
+ const mime = ref.format === "png" ? "image/png" : "image/jpeg";
9802
+ return contentFromRaster(
9803
+ ref.id,
9804
+ `data:${mime};base64,${Buffer.from(bytes).toString("base64")}`,
9805
+ size.width * PX_TO_MM,
9806
+ size.height * PX_TO_MM
9807
+ );
9838
9808
  }
9809
+ const content = contentFromDocument(
9810
+ await referenceDocument(ref, bytes),
9811
+ ref.id
9812
+ );
9813
+ return {
9814
+ ...content,
9815
+ bounds: measureContentBounds(content, approximateTextMeasurer)
9816
+ };
9839
9817
  };
9840
9818
  var Drawing = class extends LocalDrawing {
9841
9819
  path;
@@ -9873,22 +9851,31 @@ var Drawing = class extends LocalDrawing {
9873
9851
  ...this.layouts.flatMap((l) => l.objects)
9874
9852
  ].filter((o) => o.type === "reference");
9875
9853
  for (const ref of refs) {
9876
- const content = await this.loadReference(ref, ref.source, 0, /* @__PURE__ */ new Set());
9854
+ const content = await this.loadReference(
9855
+ ref,
9856
+ ref.source,
9857
+ this.state.assets,
9858
+ 0,
9859
+ /* @__PURE__ */ new Set()
9860
+ );
9877
9861
  if (content) this.referenceContent.set(ref.id, content);
9878
9862
  else this.referenceContent.delete(ref.id);
9879
9863
  }
9880
9864
  }
9881
9865
  /** One reference's content (null when unreadable); a .linea's own
9882
- * references load relative to it — depth-limited, never re-entering a
9883
- * file above in the chain (the editor's rules). */
9884
- async loadReference(ref, source, depth, seen) {
9885
- let doc;
9866
+ * references load relative to it — and its embedded ones from ITS assets —
9867
+ * depth-limited, never re-entering a file above in the chain (the
9868
+ * editor's rules). */
9869
+ async loadReference(ref, source, assets, depth, seen) {
9870
+ let content;
9886
9871
  try {
9887
- doc = await referenceDocument(ref, await this.readSource(source));
9872
+ content = await referenceContent(
9873
+ ref,
9874
+ await this.readSource(source, assets)
9875
+ );
9888
9876
  } catch {
9889
9877
  return null;
9890
9878
  }
9891
- const content = contentFromDocument(doc, ref.id);
9892
9879
  if (ref.format === "linea" && depth + 1 < 4) {
9893
9880
  const above = new Set(seen).add(JSON.stringify(source));
9894
9881
  const nested = /* @__PURE__ */ new Map();
@@ -9899,19 +9886,23 @@ var Drawing = class extends LocalDrawing {
9899
9886
  const c = await this.loadReference(
9900
9887
  child,
9901
9888
  childSource,
9889
+ content.assets ?? {},
9902
9890
  depth + 1,
9903
9891
  above
9904
9892
  );
9905
9893
  if (c) nested.set(child.id, c);
9906
9894
  }
9907
9895
  content.resolveReference = (r) => nested.get(r.id) ?? null;
9896
+ content.bounds = measureContentBounds(content, approximateTextMeasurer);
9908
9897
  }
9909
- return {
9910
- ...content,
9911
- bounds: measureContentBounds(content, approximateTextMeasurer)
9912
- };
9898
+ return content;
9913
9899
  }
9914
- async readSource(source) {
9900
+ async readSource(source, assets) {
9901
+ if (source.kind === "asset") {
9902
+ const data = assets[source.assetId];
9903
+ if (data === void 0) throw new Error("embedded file missing");
9904
+ return dataUrlBytes(data);
9905
+ }
9915
9906
  if (source.kind === "url") {
9916
9907
  const res = await fetch(source.url);
9917
9908
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
@@ -10032,7 +10023,12 @@ async function openDrawing(path, options = {}) {
10032
10023
  return doc;
10033
10024
  }
10034
10025
  export {
10026
+ BridgeError,
10027
+ DEFAULT_BRIDGE_PORT,
10035
10028
  Drawing,
10029
+ bridgeFilePath,
10030
+ connectEditors,
10031
+ createBridge,
10036
10032
  drawingFromJson,
10037
10033
  ensureScriptTranspiler,
10038
10034
  getBlockMetaResult,