diagramo 0.1.0 → 0.2.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/LICENSE CHANGED
@@ -1,4 +1,7 @@
1
- UNLICENSED
1
+ A **Software License for Non-Commercial Use Only** grants the user permission to install and use the software solely for personal, educational, research, or other non-commercial purposes. Under this license, the software may not be used directly or indirectly for commercial advantage, monetary compensation, business operations, or any activity intended to generate revenue.
2
2
 
3
- All rights reserved.
4
- Replace this file with your intended license before publishing.
3
+ Permitted uses typically include personal projects, academic work, learning, experimentation, or other activities that do not involve commercial gain. The license does not transfer ownership of the software to the user; all rights, title, and intellectual property remain with the original developer or copyright holder.
4
+
5
+ Prohibited uses include, but are not limited to, using the software within a business environment, providing paid services using the software, incorporating the software into commercial products or services, or otherwise using the software in connection with revenue-generating activities unless a separate commercial license has been obtained.
6
+
7
+ By using the software, the user agrees to comply with the terms of this non-commercial license. Any commercial use requires prior written permission or the purchase of an appropriate commercial license from the software owner.
package/README.md CHANGED
@@ -4,8 +4,10 @@ Diagramo renders Surface, Core, and NCF S-expression diagrams into SVG.
4
4
 
5
5
  This package includes:
6
6
 
7
- - `dist/diagramo.js`: ESM library entry for npm consumers
8
- - `dist/diagramo.browser.js`: standalone browser bundle for drop-in static pages
7
+ - `src/diagramo.js`: editable source module
8
+ - `src/browser-entry.js`: browser-global auto-render entry
9
+ - `dist/diagramo.js`: npm ESM entry
10
+ - `dist/diagramo.browser.js`: standalone browser bundle for static pages
9
11
 
10
12
  ## Install
11
13
 
@@ -13,7 +15,27 @@ This package includes:
13
15
  npm install diagramo
14
16
  ```
15
17
 
16
- This package declares `d3` and `d3-dag` as runtime dependencies.
18
+ ## Dev Demo
19
+
20
+ clone repo then enter root project repo
21
+
22
+ ```bash
23
+ python -m http.server
24
+ ```
25
+
26
+ ## Publishable package layout
27
+
28
+ Edit `src/diagramo.js`, then regenerate the browser bundle with:
29
+
30
+ ```bash
31
+ npm install
32
+ npm run build
33
+ ```
34
+
35
+ That command:
36
+
37
+ - copies `src/diagramo.js` to `dist/diagramo.js`
38
+ - bundles `src/browser-entry.js` to `dist/diagramo.browser.js`
17
39
 
18
40
  ## ESM usage
19
41
 
@@ -43,7 +65,7 @@ renderSource(`(program (X) (-> f X Y))`, host, { zoom: false, height: 320 });
43
65
 
44
66
  ## Static page drop-in
45
67
 
46
- After you publish the package, you can use the browser bundle from a CDN:
68
+ After publishing, you can use the browser bundle from a CDN:
47
69
 
48
70
  ```html
49
71
  <pre class="diagramo">
@@ -66,6 +88,7 @@ The browser bundle auto-renders `pre.diagramo` elements on page load.
66
88
  - source `<pre>` elements are replaced with rendered hosts
67
89
  - labels default to IDs in Surface shorthand
68
90
  - `(-> f A B)` synthesizes missing nodes `A` and `B`
91
+ - the host auto-grows to avoid clipping labels and arrowheads
69
92
 
70
93
  ### Data attributes
71
94
 
@@ -102,19 +125,11 @@ The standalone browser bundle exposes `window.Diagramo` with:
102
125
  - `renderAll`
103
126
  - `autoRender`
104
127
 
105
- Example:
106
-
107
- ```html
108
- <script>
109
- window.Diagramo.renderAll();
110
- </script>
111
- ```
112
-
113
128
  ## API
114
129
 
115
130
  ### `compileSource(source, mode = "auto")`
116
131
 
117
- Compiles source text into:
132
+ Returns:
118
133
 
119
134
  ```js
120
135
  {
@@ -159,13 +174,12 @@ Returns:
159
174
  (-> f A B) ; arrow f from A to B, label "f", synthesize A/B if needed
160
175
  ```
161
176
 
162
- ## Notes before publishing
163
-
164
- - The package name `diagramo` may already be taken on npm. Change `name` in `package.json` if needed.
165
- - The package is marked `UNLICENSED`. Replace the license field and `LICENSE` file with your intended license before publishing.
166
-
167
177
  ## Files
168
178
 
179
+ - `src/diagramo.js`
180
+ - `src/browser-entry.js`
181
+ - `scripts/build.mjs`
169
182
  - `dist/diagramo.js`
170
183
  - `dist/diagramo.browser.js`
171
184
  - `examples/static-page.html`
185
+
@@ -1,3 +1,4 @@
1
+ /* diagramo browser bundle */
1
2
  var DiagramoBundle = (() => {
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -17,12 +18,29 @@ var DiagramoBundle = (() => {
17
18
  };
18
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
20
 
20
- // browser-entry.js
21
+ // src/browser-entry.js
21
22
  var browser_entry_exports = {};
22
23
  __export(browser_entry_exports, {
23
24
  default: () => browser_entry_default
24
25
  });
25
26
 
27
+ // src/diagramo.js
28
+ var diagramo_exports = {};
29
+ __export(diagramo_exports, {
30
+ Diagramo: () => Diagramo,
31
+ VERSION: () => VERSION,
32
+ autoRender: () => autoRender,
33
+ compileAst: () => compileAst,
34
+ compileSource: () => compileSource,
35
+ default: () => diagramo_default,
36
+ emitCoreDoc: () => emitCoreDoc,
37
+ emitNCFDoc: () => emitNCFDoc,
38
+ parseSexpr: () => parseSexpr,
39
+ renderAll: () => renderAll,
40
+ renderElement: () => renderElement,
41
+ renderSource: () => renderSource
42
+ });
43
+
26
44
  // node_modules/d3-dispatch/src/dispatch.js
27
45
  var noop = { value: () => {
28
46
  } };
@@ -5642,8 +5660,8 @@ var DiagramoBundle = (() => {
5642
5660
  throw D`invalid tweakFlip style: ${e}`;
5643
5661
  }
5644
5662
 
5645
- // dist/diagramo.js
5646
- var VERSION = "0.1.0";
5663
+ // src/diagramo.js
5664
+ var VERSION = "0.2.0";
5647
5665
  var RESERVED_HEADS = /* @__PURE__ */ new Set([
5648
5666
  "program",
5649
5667
  "root",
@@ -5676,7 +5694,8 @@ var DiagramoBundle = (() => {
5676
5694
  position: relative;
5677
5695
  display: block;
5678
5696
  width: 100%;
5679
- min-height: 240px;
5697
+ height: var(--diagramo-height, 360px);
5698
+ min-height: var(--diagramo-height, 360px);
5680
5699
  border-radius: 14px;
5681
5700
  border: 1px solid var(--diagramo-border);
5682
5701
  background: linear-gradient(180deg, rgba(17,19,26,0.98), rgba(15,17,23,0.98));
@@ -5733,7 +5752,8 @@ var DiagramoBundle = (() => {
5733
5752
  document.head.appendChild(style);
5734
5753
  }
5735
5754
  function tokenizeSexpr(src) {
5736
- src = String(src ?? "").replace(/;[^\n\r]*/g, "");
5755
+ var _a;
5756
+ src = String(src != null ? src : "").replace(/;[^\n\r]*/g, "");
5737
5757
  const tokens = [];
5738
5758
  let i = 0;
5739
5759
  while (i < src.length) {
@@ -5753,7 +5773,7 @@ var DiagramoBundle = (() => {
5753
5773
  while (j2 < src.length) {
5754
5774
  const ch = src[j2];
5755
5775
  if (ch === "\\") {
5756
- const nxt = src[j2 + 1] ?? "";
5776
+ const nxt = (_a = src[j2 + 1]) != null ? _a : "";
5757
5777
  if (nxt === "n") out += "\n";
5758
5778
  else if (nxt === "t") out += " ";
5759
5779
  else out += nxt;
@@ -5806,7 +5826,7 @@ var DiagramoBundle = (() => {
5806
5826
  }
5807
5827
  function atomValue(x) {
5808
5828
  if (isList(x)) throw new Error("Expected atom, got list");
5809
- return typeof x === "object" && x ? String(x.value) : String(x ?? "");
5829
+ return typeof x === "object" && x ? String(x.value) : String(x != null ? x : "");
5810
5830
  }
5811
5831
  function ensureAnyAtom(x, ctx) {
5812
5832
  if (isList(x)) throw new Error(`${ctx}: expected atom, got list`);
@@ -6110,6 +6130,7 @@ var DiagramoBundle = (() => {
6110
6130
  for (const item of doc.items || []) visit(item);
6111
6131
  }
6112
6132
  function validateCoreDoc(doc) {
6133
+ var _a;
6113
6134
  const entities = /* @__PURE__ */ new Map();
6114
6135
  const parents = /* @__PURE__ */ new Map();
6115
6136
  const refs = [];
@@ -6133,7 +6154,7 @@ var DiagramoBundle = (() => {
6133
6154
  while (cur && cur !== doc.rootId) {
6134
6155
  if (seen.has(cur)) throw new Error(`Containment cycle involving ${id2}`);
6135
6156
  seen.add(cur);
6136
- cur = parents.get(cur) ?? doc.rootId;
6157
+ cur = (_a = parents.get(cur)) != null ? _a : doc.rootId;
6137
6158
  }
6138
6159
  }
6139
6160
  }
@@ -6141,7 +6162,7 @@ var DiagramoBundle = (() => {
6141
6162
  const data = {};
6142
6163
  const classes = [...extraClasses];
6143
6164
  for (const [k, v] of Object.entries(attrs || {})) {
6144
- if (k === "class") classes.push(...String(v ?? "").trim().split(/\s+/).filter(Boolean));
6165
+ if (k === "class") classes.push(...String(v != null ? v : "").trim().split(/\s+/).filter(Boolean));
6145
6166
  else data[k] = v;
6146
6167
  }
6147
6168
  return { data, classString: [...new Set(classes)].join(" ") };
@@ -6217,8 +6238,8 @@ var DiagramoBundle = (() => {
6217
6238
  if (headOf(item) === "nodes") nodesBlock = item;
6218
6239
  if (headOf(item) === "edges") edgesBlock = item;
6219
6240
  }
6220
- nodesBlock ||= [{ type: "sym", value: "nodes" }];
6221
- edgesBlock ||= [{ type: "sym", value: "edges" }];
6241
+ nodesBlock || (nodesBlock = [{ type: "sym", value: "nodes" }]);
6242
+ edgesBlock || (edgesBlock = [{ type: "sym", value: "edges" }]);
6222
6243
  const doc = { rootId: "__root__", nodes: [], edges: [] };
6223
6244
  for (const expr of nodesBlock.slice(1)) doc.nodes.push(parseNCFNode(expr));
6224
6245
  for (const expr of edgesBlock.slice(1)) doc.edges.push(parseNCFEdge(expr));
@@ -6246,7 +6267,7 @@ var DiagramoBundle = (() => {
6246
6267
  function printVal(v) {
6247
6268
  if (typeof v === "number") return String(v);
6248
6269
  if (typeof v === "boolean") return v ? "true" : "false";
6249
- const s = String(v ?? "");
6270
+ const s = String(v != null ? v : "");
6250
6271
  return /^[^\s()";]+$/.test(s) ? s : JSON.stringify(s);
6251
6272
  }
6252
6273
  function emitAttr(attrs) {
@@ -6534,7 +6555,8 @@ var DiagramoBundle = (() => {
6534
6555
  return comps;
6535
6556
  }
6536
6557
  function gridPack(ids, sizes, opts = {}) {
6537
- const gapX = opts.gapX ?? 50, gapY = opts.gapY ?? 45, maxCols = opts.maxCols ?? 4;
6558
+ var _a, _b, _c;
6559
+ const gapX = (_a = opts.gapX) != null ? _a : 50, gapY = (_b = opts.gapY) != null ? _b : 45, maxCols = (_c = opts.maxCols) != null ? _c : 4;
6538
6560
  const pos = /* @__PURE__ */ new Map();
6539
6561
  let col = 0, y = 0, rowH = 0, x = 0;
6540
6562
  const sorted = [...ids].sort((a, b) => String(a).localeCompare(String(b)));
@@ -6570,10 +6592,11 @@ var DiagramoBundle = (() => {
6570
6592
  return { left, top, right, bottom };
6571
6593
  }
6572
6594
  function layoutWithD3Dag(ids, edges, sizes) {
6595
+ var _a, _b, _c, _d;
6573
6596
  if (ids.length === 0) return /* @__PURE__ */ new Map();
6574
6597
  if (ids.length === 1) {
6575
6598
  const only = ids[0];
6576
- return /* @__PURE__ */ new Map([[only, { x: (sizes.get(only)?.w ?? 120) / 2, y: (sizes.get(only)?.h ?? 36) / 2 }]]);
6599
+ return /* @__PURE__ */ new Map([[only, { x: ((_b = (_a = sizes.get(only)) == null ? void 0 : _a.w) != null ? _b : 120) / 2, y: ((_d = (_c = sizes.get(only)) == null ? void 0 : _c.h) != null ? _d : 36) / 2 }]]);
6577
6600
  }
6578
6601
  const comps = connectedComponents(ids, edges);
6579
6602
  const positions = /* @__PURE__ */ new Map();
@@ -6614,10 +6637,15 @@ var DiagramoBundle = (() => {
6614
6637
  }
6615
6638
  function createSvgShell(host, options) {
6616
6639
  host.classList.add("diagramo-host");
6640
+ host.style.setProperty("--diagramo-height", `${options.height}px`);
6641
+ host.style.height = `${options.height}px`;
6617
6642
  host.style.minHeight = `${options.height}px`;
6618
6643
  host.innerHTML = "";
6619
6644
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
6620
6645
  svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
6646
+ svg.setAttribute("width", "100%");
6647
+ svg.setAttribute("height", "100%");
6648
+ svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
6621
6649
  const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
6622
6650
  const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
6623
6651
  marker.setAttribute("id", `diagramoArrowHead-${Math.random().toString(36).slice(2)}`);
@@ -6647,13 +6675,25 @@ var DiagramoBundle = (() => {
6647
6675
  statusEl.textContent = msg;
6648
6676
  statusEl.className = "diagramo-status" + (kind === "ok" ? " ok" : kind === "bad" ? " bad" : "");
6649
6677
  }
6650
- function fitToView(svgSel, zoomLayerSel, sceneSel, host, zoomBehavior, animate = false) {
6651
- const w = host.clientWidth || 800;
6652
- const h = host.clientHeight || 360;
6678
+ function measuredSceneBBox(sceneSel) {
6653
6679
  const g = sceneSel.node();
6654
- if (!g) return;
6680
+ if (!g) return null;
6655
6681
  const bbox = g.getBBox();
6656
- if (!(bbox.width > 0 && bbox.height > 0)) return;
6682
+ if (!(bbox.width > 0 && bbox.height > 0)) return null;
6683
+ const bleedX = 24;
6684
+ const bleedY = 28;
6685
+ return {
6686
+ x: bbox.x - bleedX,
6687
+ y: bbox.y - bleedY,
6688
+ width: bbox.width + bleedX * 2,
6689
+ height: bbox.height + bleedY * 2
6690
+ };
6691
+ }
6692
+ function fitToView(svgSel, zoomLayerSel, sceneSel, host, zoomBehavior, animate = false, bboxOverride = null) {
6693
+ const w = host.clientWidth || 800;
6694
+ const h = host.clientHeight || 360;
6695
+ const bbox = bboxOverride || measuredSceneBBox(sceneSel);
6696
+ if (!bbox || !(bbox.width > 0 && bbox.height > 0)) return;
6657
6697
  const pad = 24;
6658
6698
  const scale = Math.min((w - pad * 2) / bbox.width, (h - pad * 2) / bbox.height);
6659
6699
  const tx = w / 2 - scale * (bbox.x + bbox.width / 2);
@@ -6667,6 +6707,7 @@ var DiagramoBundle = (() => {
6667
6707
  }
6668
6708
  }
6669
6709
  function renderNCFDocIntoHost(ncfDoc, host, options) {
6710
+ var _a, _b;
6670
6711
  injectStyles();
6671
6712
  const warnings = [];
6672
6713
  const { svg, zoomLayer, scene, status, arrowHeadId } = createSvgShell(host, options);
@@ -6720,14 +6761,15 @@ var DiagramoBundle = (() => {
6720
6761
  for (const [p, kids] of childrenByParent.entries()) renderableChildrenByParent.set(p, kids.filter((k) => renderable.has(k)));
6721
6762
  for (const id2 of renderable) nodes[id2].isCompound = (renderableChildrenByParent.get(id2) || []).length > 0;
6722
6763
  function computeDepth(id2) {
6764
+ var _a2, _b2, _c;
6723
6765
  let d = 0;
6724
- let cur = nodes[id2]?.parent ?? "__root__";
6766
+ let cur = (_b2 = (_a2 = nodes[id2]) == null ? void 0 : _a2.parent) != null ? _b2 : "__root__";
6725
6767
  const guard = /* @__PURE__ */ new Set([id2]);
6726
6768
  while (cur && cur !== "__root__" && nodes[cur]) {
6727
6769
  if (guard.has(cur)) break;
6728
6770
  guard.add(cur);
6729
6771
  d++;
6730
- cur = nodes[cur].parent ?? "__root__";
6772
+ cur = (_c = nodes[cur].parent) != null ? _c : "__root__";
6731
6773
  }
6732
6774
  return d;
6733
6775
  }
@@ -6735,10 +6777,11 @@ var DiagramoBundle = (() => {
6735
6777
  const measurer = document.createElement("canvas").getContext("2d");
6736
6778
  measurer.font = "12px system-ui, -apple-system, Segoe UI, Roboto, sans-serif";
6737
6779
  function measureLabel(s) {
6738
- return Math.ceil(measurer.measureText(String(s ?? "")).width);
6780
+ return Math.ceil(measurer.measureText(String(s != null ? s : "")).width);
6739
6781
  }
6740
6782
  function nodeLabel(n) {
6741
- return n.data.label ?? n.data.name ?? n.data.title ?? n.id;
6783
+ var _a2, _b2, _c;
6784
+ return (_c = (_b2 = (_a2 = n.data.label) != null ? _a2 : n.data.name) != null ? _b2 : n.data.title) != null ? _c : n.id;
6742
6785
  }
6743
6786
  for (const id2 of renderable) {
6744
6787
  const n = nodes[id2];
@@ -6763,6 +6806,7 @@ var DiagramoBundle = (() => {
6763
6806
  }
6764
6807
  }
6765
6808
  function directChildUnder(parentId, nodeId) {
6809
+ var _a2, _b2;
6766
6810
  if (!nodes[nodeId]) return null;
6767
6811
  let cur = nodeId, prev = null;
6768
6812
  const guard = /* @__PURE__ */ new Set();
@@ -6770,7 +6814,7 @@ var DiagramoBundle = (() => {
6770
6814
  if (guard.has(cur)) return null;
6771
6815
  guard.add(cur);
6772
6816
  prev = cur;
6773
- cur = nodes[cur]?.parent ?? "__root__";
6817
+ cur = (_b2 = (_a2 = nodes[cur]) == null ? void 0 : _a2.parent) != null ? _b2 : "__root__";
6774
6818
  if (cur === "__root__" && parentId !== "__root__") return null;
6775
6819
  }
6776
6820
  return cur === parentId ? prev : null;
@@ -6804,17 +6848,18 @@ var DiagramoBundle = (() => {
6804
6848
  }
6805
6849
  const basePairsCache = /* @__PURE__ */ new Map();
6806
6850
  function arrowBasePairs(aid, stack = /* @__PURE__ */ new Set()) {
6851
+ var _a2, _b2;
6807
6852
  if (basePairsCache.has(aid)) return basePairsCache.get(aid);
6808
6853
  if (stack.has(aid)) return /* @__PURE__ */ new Set();
6809
6854
  stack.add(aid);
6810
6855
  const out = /* @__PURE__ */ new Set();
6811
6856
  const w = arrowWiring.get(aid);
6812
- if (w?.fromId && w?.toId) {
6857
+ if ((w == null ? void 0 : w.fromId) && (w == null ? void 0 : w.toId)) {
6813
6858
  const f = w.fromId, t = w.toId;
6814
6859
  if (renderable.has(f) && renderable.has(t)) out.add(unorderedKey(f, t));
6815
6860
  else {
6816
- if (nodes[f]?.isArrow) for (const k of arrowBasePairs(f, stack)) out.add(k);
6817
- if (nodes[t]?.isArrow) for (const k of arrowBasePairs(t, stack)) out.add(k);
6861
+ if ((_a2 = nodes[f]) == null ? void 0 : _a2.isArrow) for (const k of arrowBasePairs(f, stack)) out.add(k);
6862
+ if ((_b2 = nodes[t]) == null ? void 0 : _b2.isArrow) for (const k of arrowBasePairs(t, stack)) out.add(k);
6818
6863
  }
6819
6864
  }
6820
6865
  stack.delete(aid);
@@ -6824,9 +6869,9 @@ var DiagramoBundle = (() => {
6824
6869
  const scoreByPair = new Map(baseCountByPair);
6825
6870
  const bump = (k, amt = 1) => scoreByPair.set(k, (scoreByPair.get(k) || 0) + amt);
6826
6871
  for (const [mid, w] of arrowWiring.entries()) {
6827
- if (!w?.fromId || !w?.toId) continue;
6828
- if (nodes[w.fromId]?.isArrow) for (const k of arrowBasePairs(w.fromId)) bump(k, 1);
6829
- if (nodes[w.toId]?.isArrow) for (const k of arrowBasePairs(w.toId)) bump(k, 1);
6872
+ if (!(w == null ? void 0 : w.fromId) || !(w == null ? void 0 : w.toId)) continue;
6873
+ if ((_a = nodes[w.fromId]) == null ? void 0 : _a.isArrow) for (const k of arrowBasePairs(w.fromId)) bump(k, 1);
6874
+ if ((_b = nodes[w.toId]) == null ? void 0 : _b.isArrow) for (const k of arrowBasePairs(w.toId)) bump(k, 1);
6830
6875
  }
6831
6876
  function extraSpacersForPairKey(k) {
6832
6877
  const base = baseCountByPair.get(k) || 0;
@@ -6957,51 +7002,54 @@ var DiagramoBundle = (() => {
6957
7002
  }
6958
7003
  function approxArrowCenter(aid) {
6959
7004
  const w = arrowWiring.get(aid);
6960
- if (w?.fromId && w?.toId && nodes[w.fromId] && nodes[w.toId]) return { x: (nodes[w.fromId].cx + nodes[w.toId].cx) / 2, y: (nodes[w.fromId].cy + nodes[w.toId].cy) / 2 };
7005
+ if ((w == null ? void 0 : w.fromId) && (w == null ? void 0 : w.toId) && nodes[w.fromId] && nodes[w.toId]) return { x: (nodes[w.fromId].cx + nodes[w.toId].cx) / 2, y: (nodes[w.fromId].cy + nodes[w.toId].cy) / 2 };
6961
7006
  return { x: 0, y: 0 };
6962
7007
  }
6963
7008
  function endpointAnchor(endpointId2) {
7009
+ var _a2, _b2;
6964
7010
  const n = nodes[endpointId2];
6965
7011
  if (!n) return { x: 0, y: 0, type: "missing" };
6966
7012
  if (n.isArrow) return { ...getArrowAnchor(endpointId2), type: "arrow" };
6967
7013
  if (renderable.has(endpointId2)) return { x: n.cx, y: n.cy, type: "node" };
6968
- return { x: n.cx ?? 0, y: n.cy ?? 0, type: "other" };
7014
+ return { x: (_a2 = n.cx) != null ? _a2 : 0, y: (_b2 = n.cy) != null ? _b2 : 0, type: "other" };
6969
7015
  }
6970
7016
  function buildPathBetween(fromId, toId, opts) {
7017
+ var _a2, _b2;
6971
7018
  const aA = endpointAnchor(fromId);
6972
7019
  const aB = endpointAnchor(toId);
6973
7020
  let start2 = { x: aA.x, y: aA.y }, end = { x: aB.x, y: aB.y };
6974
7021
  if (aA.type === "node") start2 = trimToRect(nodeRect(fromId), end);
6975
7022
  if (aB.type === "node") end = trimToRect(nodeRect(toId), start2);
6976
- const offset = opts.offset ?? 0;
7023
+ const offset = (_a2 = opts.offset) != null ? _a2 : 0;
6977
7024
  if (opts.ortho) {
6978
7025
  start2 = { x: start2.x, y: start2.y + offset };
6979
7026
  end = { x: end.x, y: end.y + offset };
6980
7027
  const midX = (start2.x + end.x) / 2;
6981
7028
  return [start2, { x: midX, y: start2.y }, { x: midX, y: end.y }, end];
6982
7029
  }
6983
- const nrm = opts.baseNormal ?? unitNormal(start2, end);
7030
+ const nrm = (_b2 = opts.baseNormal) != null ? _b2 : unitNormal(start2, end);
6984
7031
  start2 = { x: start2.x + nrm.x * offset, y: start2.y + nrm.y * offset };
6985
7032
  end = { x: end.x + nrm.x * offset, y: end.y + nrm.y * offset };
6986
7033
  return [start2, end];
6987
7034
  }
6988
7035
  function getArrowAnchor(aid) {
7036
+ var _a2, _b2, _c, _d, _e2, _f, _g;
6989
7037
  if (arrowAnchor.has(aid)) return arrowAnchor.get(aid);
6990
7038
  if (arrowAnchorGuard.has(aid)) return approxArrowCenter(aid);
6991
7039
  arrowAnchorGuard.add(aid);
6992
7040
  const w = arrowWiring.get(aid);
6993
- if (!w?.fromId || !w?.toId) {
7041
+ if (!(w == null ? void 0 : w.fromId) || !(w == null ? void 0 : w.toId)) {
6994
7042
  const fallback = approxArrowCenter(aid);
6995
7043
  arrowAnchor.set(aid, fallback);
6996
7044
  arrowAnchorGuard.delete(aid);
6997
7045
  return fallback;
6998
7046
  }
6999
7047
  const is1 = renderable.has(w.fromId) && renderable.has(w.toId);
7000
- const offset = is1 ? lanes.get(aid) ?? 0 : 0;
7048
+ const offset = is1 ? (_a2 = lanes.get(aid)) != null ? _a2 : 0 : 0;
7001
7049
  const baseNormal = is1 ? baseNormalForPair(w.fromId, w.toId, nodes) : null;
7002
7050
  const points = buildPathBetween(w.fromId, w.toId, { ortho: is1 ? ortho : false, offset, baseNormal });
7003
7051
  const mid = polylineMidpoint(points);
7004
- const label = nodes[aid]?.data?.label ?? nodes[aid]?.data?.name ?? aid;
7052
+ const label = (_g = (_f = (_c = (_b2 = nodes[aid]) == null ? void 0 : _b2.data) == null ? void 0 : _c.label) != null ? _f : (_e2 = (_d = nodes[aid]) == null ? void 0 : _d.data) == null ? void 0 : _e2.name) != null ? _g : aid;
7005
7053
  arrowPath.set(aid, { points: points.map((p) => ({ ...p })), mid, kind: is1 ? "m1" : "m2", label, laneOffset: offset, baseNormal, ctrl: null });
7006
7054
  arrowAnchor.set(aid, mid);
7007
7055
  arrowAnchorGuard.delete(aid);
@@ -7010,11 +7058,14 @@ var DiagramoBundle = (() => {
7010
7058
  for (const a of arrowsValid) getArrowAnchor(a.id);
7011
7059
  function bundleCurvesForM2() {
7012
7060
  const curveGap = 16, curveCap = 60;
7013
- const endpointKey = (id2) => nodes[id2]?.isArrow ? `a:${id2}` : `n:${id2}`;
7061
+ const endpointKey = (id2) => {
7062
+ var _a2;
7063
+ return ((_a2 = nodes[id2]) == null ? void 0 : _a2.isArrow) ? `a:${id2}` : `n:${id2}`;
7064
+ };
7014
7065
  const groups = /* @__PURE__ */ new Map();
7015
7066
  for (const aid of arrowsValid.filter((a) => !(renderable.has(a.from) && renderable.has(a.to))).map((a) => a.id).sort()) {
7016
7067
  const w = arrowWiring.get(aid);
7017
- if (!w?.fromId || !w?.toId) continue;
7068
+ if (!(w == null ? void 0 : w.fromId) || !(w == null ? void 0 : w.toId)) continue;
7018
7069
  const pts = buildPathBetween(w.fromId, w.toId, { ortho: false, offset: 0, baseNormal: null });
7019
7070
  const A2 = pts[0], B = pts[pts.length - 1];
7020
7071
  const key = endpointKey(w.fromId) + "->" + endpointKey(w.toId);
@@ -7059,18 +7110,23 @@ var DiagramoBundle = (() => {
7059
7110
  });
7060
7111
  }
7061
7112
  const visibleEdges = arrowsValid.map((a) => {
7113
+ var _a2, _b2;
7062
7114
  const p = arrowPath.get(a.id);
7063
- const kind = p?.kind || (renderable.has(a.from) && renderable.has(a.to) ? "m1" : "m2");
7064
- return { id: a.id, from: a.from, to: a.to, points: p?.points || [], ctrl: p?.ctrl || null, mid: p?.mid || approxArrowCenter(a.id), kind, label: p?.label || a.id, laneOffset: p?.laneOffset ?? 0, baseNormal: p?.baseNormal ?? null };
7115
+ const kind = (p == null ? void 0 : p.kind) || (renderable.has(a.from) && renderable.has(a.to) ? "m1" : "m2");
7116
+ return { id: a.id, from: a.from, to: a.to, points: (p == null ? void 0 : p.points) || [], ctrl: (p == null ? void 0 : p.ctrl) || null, mid: (p == null ? void 0 : p.mid) || approxArrowCenter(a.id), kind, label: (p == null ? void 0 : p.label) || a.id, laneOffset: (_a2 = p == null ? void 0 : p.laneOffset) != null ? _a2 : 0, baseNormal: (_b2 = p == null ? void 0 : p.baseNormal) != null ? _b2 : null };
7065
7117
  });
7066
7118
  visibleEdges.sort((a, b) => a.kind === b.kind ? 0 : a.kind === "m1" ? -1 : 1);
7067
7119
  const edgeLayer = scene.append("g").attr("class", "edgeLayer");
7068
- edgeLayer.selectAll("path").data(visibleEdges).join("path").attr("class", (d) => d.kind === "m2" ? "edge m2" : "edge").attr("marker-end", `url(#${arrowHeadId})`).attr("d", (d) => d.kind === "m2" && d.ctrl && (d.points?.length || 0) >= 2 ? quadToD(d.points[0], d.ctrl, d.points[d.points.length - 1]) : pathToD(d.points));
7120
+ edgeLayer.selectAll("path").data(visibleEdges).join("path").attr("class", (d) => d.kind === "m2" ? "edge m2" : "edge").attr("marker-end", `url(#${arrowHeadId})`).attr("d", (d) => {
7121
+ var _a2;
7122
+ return d.kind === "m2" && d.ctrl && (((_a2 = d.points) == null ? void 0 : _a2.length) || 0) >= 2 ? quadToD(d.points[0], d.ctrl, d.points[d.points.length - 1]) : pathToD(d.points);
7123
+ });
7069
7124
  function labelPos(d) {
7125
+ var _a2;
7070
7126
  const pts = d.points || [];
7071
7127
  const chordNormal = pts.length >= 2 ? unitNormal(pts[0], pts[pts.length - 1]) : { x: 0, y: -1 };
7072
7128
  const nrm = d.kind === "m1" && d.baseNormal ? d.baseNormal : chordNormal;
7073
- const off = d.laneOffset ?? 0;
7129
+ const off = (_a2 = d.laneOffset) != null ? _a2 : 0;
7074
7130
  const sign = off === 0 ? 1 : Math.sign(off);
7075
7131
  const mag = (d.kind === "m2" ? 18 : 14) + Math.min(10, Math.abs(off));
7076
7132
  return { x: d.mid.x + nrm.x * sign * mag, y: d.mid.y + nrm.y * sign * mag, nrm };
@@ -7083,7 +7139,16 @@ var DiagramoBundle = (() => {
7083
7139
  });
7084
7140
  nudgePoints(labelPoints, 16, 24);
7085
7141
  const labelById = new Map(labelPoints.map((p) => [p.id, p]));
7086
- edgeLayer.selectAll("text").data(visibleEdges).join("text").attr("class", "edgeLabel").attr("x", (d) => labelById.get(d.id)?.x ?? d.mid.x).attr("y", (d) => labelById.get(d.id)?.y ?? d.mid.y).text((d) => d.label ?? d.id);
7142
+ edgeLayer.selectAll("text").data(visibleEdges).join("text").attr("class", "edgeLabel").attr("x", (d) => {
7143
+ var _a2, _b2;
7144
+ return (_b2 = (_a2 = labelById.get(d.id)) == null ? void 0 : _a2.x) != null ? _b2 : d.mid.x;
7145
+ }).attr("y", (d) => {
7146
+ var _a2, _b2;
7147
+ return (_b2 = (_a2 = labelById.get(d.id)) == null ? void 0 : _a2.y) != null ? _b2 : d.mid.y;
7148
+ }).text((d) => {
7149
+ var _a2;
7150
+ return (_a2 = d.label) != null ? _a2 : d.id;
7151
+ });
7087
7152
  const compLayer = scene.append("g").attr("class", "compoundLayer");
7088
7153
  const compG = compLayer.selectAll("g.compound").data(allCompounds.map((id2) => nodes[id2])).join("g").attr("class", "compound").attr("transform", (d) => `translate(${d.cx - d.w / 2}, ${d.cy - d.h / 2})`);
7089
7154
  compG.append("rect").attr("class", "outer").attr("rx", 14).attr("ry", 14).attr("width", (d) => d.w).attr("height", (d) => d.h);
@@ -7097,10 +7162,11 @@ var DiagramoBundle = (() => {
7097
7162
  if (showGlyphs) {
7098
7163
  const glyphLayer = scene.append("g").attr("class", "glyphLayer");
7099
7164
  const glyphData = arrowNodes.map((aid) => {
7165
+ var _a2, _b2, _c, _d;
7100
7166
  const p = arrowPath.get(aid);
7101
7167
  const mid = arrowAnchor.get(aid) || approxArrowCenter(aid);
7102
- const lbl = nodes[aid]?.data?.label ?? aid;
7103
- const nrm = p?.points?.length ? segmentAtHalf(p.points).nrm : { x: 0, y: -1 };
7168
+ const lbl = (_c = (_b2 = (_a2 = nodes[aid]) == null ? void 0 : _a2.data) == null ? void 0 : _b2.label) != null ? _c : aid;
7169
+ const nrm = ((_d = p == null ? void 0 : p.points) == null ? void 0 : _d.length) ? segmentAtHalf(p.points).nrm : { x: 0, y: -1 };
7104
7170
  const h = simpleHash(aid);
7105
7171
  const sgn = h & 1 ? 1 : -1;
7106
7172
  return { id: aid, x: mid.x, y: mid.y, label: lbl, dir: { x: nrm.x * sgn, y: nrm.y * sgn } };
@@ -7122,26 +7188,27 @@ var DiagramoBundle = (() => {
7122
7188
  return { svg, zoomLayer, scene, status, fit: () => fitToView(svg, zoomLayer, scene, host, zoomBehavior, true), arrowHeadId };
7123
7189
  }
7124
7190
  function normalizeRenderOptions(options = {}, el = null) {
7125
- const ds = el?.dataset || {};
7191
+ var _a, _b, _c, _d;
7192
+ const ds = (el == null ? void 0 : el.dataset) || {};
7126
7193
  const boolFrom = (a, b, fallback) => {
7127
- const v = a ?? b;
7194
+ const v = a != null ? a : b;
7128
7195
  if (v === void 0 || v === null || v === "") return fallback;
7129
7196
  return !(v === false || v === "false" || v === "0" || v === "off" || v === "no");
7130
7197
  };
7131
7198
  const numFrom = (a, b, fallback) => {
7132
- const v = a ?? b;
7199
+ const v = a != null ? a : b;
7133
7200
  const n = Number(v);
7134
7201
  return Number.isFinite(n) && n > 0 ? n : fallback;
7135
7202
  };
7136
7203
  return {
7137
- mode: options.mode ?? ds.diagramoMode ?? "auto",
7204
+ mode: (_b = (_a = options.mode) != null ? _a : ds.diagramoMode) != null ? _b : "auto",
7138
7205
  zoom: boolFrom(options.zoom, ds.diagramoZoom, false),
7139
7206
  ortho: boolFrom(options.ortho, ds.diagramoOrtho, false),
7140
7207
  wiring: boolFrom(options.wiring, ds.diagramoWiring, false),
7141
7208
  glyphs: boolFrom(options.glyphs, ds.diagramoGlyphs, false),
7142
7209
  height: numFrom(options.height, ds.diagramoHeight, 360),
7143
- observeResize: options.observeResize ?? true,
7144
- replaceSource: options.replaceSource ?? true
7210
+ observeResize: (_c = options.observeResize) != null ? _c : true,
7211
+ replaceSource: (_d = options.replaceSource) != null ? _d : true
7145
7212
  };
7146
7213
  }
7147
7214
  function renderSource(source, host, options = {}) {
@@ -7155,8 +7222,9 @@ var DiagramoBundle = (() => {
7155
7222
  return { host, compiled, fit: view.fit, rerender: (nextOptions = {}) => renderSource(source, host, { ...opts, ...nextOptions }) };
7156
7223
  }
7157
7224
  function renderElement(el, options = {}) {
7225
+ var _a, _b;
7158
7226
  if (!(el instanceof Element)) throw new Error("renderElement expects a DOM element");
7159
- const source = options.source ?? el.textContent ?? "";
7227
+ const source = (_b = (_a = options.source) != null ? _a : el.textContent) != null ? _b : "";
7160
7228
  const opts = normalizeRenderOptions(options, el);
7161
7229
  let host = el;
7162
7230
  if (opts.replaceSource && el.tagName === "PRE") {
@@ -7197,20 +7265,13 @@ var DiagramoBundle = (() => {
7197
7265
  renderAll,
7198
7266
  autoRender
7199
7267
  };
7268
+ var diagramo_default = Diagramo;
7200
7269
 
7201
- // browser-entry.js
7270
+ // src/browser-entry.js
7202
7271
  var globalApi = {
7203
- version: VERSION,
7204
- parseSexpr,
7205
- compileAst,
7206
- compileSource,
7207
- emitCoreDoc,
7208
- emitNCFDoc,
7209
- renderSource,
7210
- renderElement,
7211
- renderAll,
7212
- autoRender,
7213
- Diagramo
7272
+ ...diagramo_exports,
7273
+ default: diagramo_default,
7274
+ Diagramo: diagramo_default
7214
7275
  };
7215
7276
  if (typeof window !== "undefined") {
7216
7277
  window.Diagramo = globalApi;