@diagrammo/dgmo 0.36.0 → 0.37.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/auto.mjs CHANGED
@@ -16681,6 +16681,7 @@ function parseInfra(content) {
16681
16681
  let currentGroup = null;
16682
16682
  let currentTagGroup = null;
16683
16683
  let baseIndent = 0;
16684
+ let firstLineConsumed = false;
16684
16685
  function finishCurrentNode() {
16685
16686
  if (!currentNode) return;
16686
16687
  const key = currentNode.id;
@@ -16688,7 +16689,8 @@ function parseInfra(content) {
16688
16689
  if (existing) {
16689
16690
  const incomingDisplay = displayName(currentNode.label);
16690
16691
  const existingDisplay = displayName(existing.label);
16691
- if (incomingDisplay !== existingDisplay) {
16692
+ const isAliasRef = nameAliasMap.get(currentNode.label) === key;
16693
+ if (incomingDisplay !== existingDisplay && !isAliasRef) {
16692
16694
  result.diagnostics.push(
16693
16695
  makeDgmoError(
16694
16696
  currentNode.lineNumber,
@@ -16754,19 +16756,22 @@ function parseInfra(content) {
16754
16756
  if (indent === 0 && currentNode && !trimmed.startsWith("-")) {
16755
16757
  finishCurrentNode();
16756
16758
  }
16757
- const firstLineResult = parseFirstLine(trimmed);
16758
- if (firstLineResult) {
16759
- if (firstLineResult.chartType !== "infra") {
16760
- setError(
16761
- lineNumber,
16762
- `Expected chart type 'infra', got '${firstLineResult.chartType}'`
16763
- );
16764
- }
16765
- if (firstLineResult.title) {
16766
- result.title = firstLineResult.title;
16767
- result.titleLineNumber = lineNumber;
16759
+ if (!firstLineConsumed) {
16760
+ firstLineConsumed = true;
16761
+ const firstLineResult = parseFirstLine(trimmed);
16762
+ if (firstLineResult) {
16763
+ if (firstLineResult.chartType !== "infra") {
16764
+ setError(
16765
+ lineNumber,
16766
+ `Expected chart type 'infra', got '${firstLineResult.chartType}'`
16767
+ );
16768
+ }
16769
+ if (firstLineResult.title) {
16770
+ result.title = firstLineResult.title;
16771
+ result.titleLineNumber = lineNumber;
16772
+ }
16773
+ continue;
16768
16774
  }
16769
- continue;
16770
16775
  }
16771
16776
  if (/^direction-tb$/i.test(trimmed)) {
16772
16777
  result.direction = "TB";
@@ -16832,18 +16837,20 @@ function parseInfra(content) {
16832
16837
  if (compMatch) {
16833
16838
  finishCurrentNode();
16834
16839
  finishCurrentTagGroup();
16835
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
16840
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
16841
+ const rawName = (qname ?? uname ?? "").trim();
16836
16842
  const peeled = peelInfraDecorations(rawName, lineNumber);
16837
16843
  const name = peeled.label;
16838
- const rest = compMatch[3] || "";
16844
+ const alias = asAlias ?? peeled.alias;
16845
+ const rest = meta ?? "";
16839
16846
  const { tags } = extractPipeMetadata(rest);
16840
16847
  warnUnknownMetaKeys(
16841
16848
  tags,
16842
16849
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
16843
16850
  (msg) => warn2(lineNumber, msg)
16844
16851
  );
16845
- const id = nodeId2(name);
16846
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
16852
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
16853
+ if (alias) nameAliasMap.set(alias, id);
16847
16854
  const isEdge = EDGE_NODE_NAMES.has(id.toLowerCase());
16848
16855
  currentNode = {
16849
16856
  id,
@@ -16927,18 +16934,20 @@ function parseInfra(content) {
16927
16934
  const compMatch = trimmed.match(COMPONENT_RE);
16928
16935
  if (compMatch) {
16929
16936
  finishCurrentTagGroup();
16930
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
16937
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
16938
+ const rawName = (qname ?? uname ?? "").trim();
16931
16939
  const peeled = peelInfraDecorations(rawName, lineNumber);
16932
16940
  const name = peeled.label;
16933
- const rest = compMatch[3] || "";
16941
+ const alias = asAlias ?? peeled.alias;
16942
+ const rest = meta ?? "";
16934
16943
  const { tags: nodeTags } = extractPipeMetadata(rest);
16935
16944
  warnUnknownMetaKeys(
16936
16945
  nodeTags,
16937
16946
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
16938
16947
  (msg) => warn2(lineNumber, msg)
16939
16948
  );
16940
- const id = nodeId2(name);
16941
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
16949
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
16950
+ if (alias) nameAliasMap.set(alias, id);
16942
16951
  const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
16943
16952
  currentNode = {
16944
16953
  id,
@@ -17129,6 +17138,11 @@ function parseInfra(content) {
17129
17138
  }
17130
17139
  continue;
17131
17140
  }
17141
+ if (currentNode && tagAliasSet.has(normalizeName(key))) {
17142
+ const mut = nodeMutableTags.get(currentNode.id);
17143
+ if (mut) mut[tagAttrKey(key)] = rawVal;
17144
+ continue;
17145
+ }
17132
17146
  if (!INFRA_BEHAVIOR_KEYS.has(key) && !EDGE_ONLY_KEYS.has(key)) {
17133
17147
  const allKeys = [...INFRA_BEHAVIOR_KEYS, ...EDGE_ONLY_KEYS];
17134
17148
  const hint = suggest(key, allKeys);
@@ -17194,18 +17208,20 @@ function parseInfra(content) {
17194
17208
  finishCurrentNode();
17195
17209
  const compMatch = trimmed.match(COMPONENT_RE);
17196
17210
  if (compMatch) {
17197
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
17211
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
17212
+ const rawName = (qname ?? uname ?? "").trim();
17198
17213
  const peeled = peelInfraDecorations(rawName, lineNumber);
17199
17214
  const name = peeled.label;
17200
- const rest = compMatch[3] || "";
17215
+ const alias = asAlias ?? peeled.alias;
17216
+ const rest = meta ?? "";
17201
17217
  const { tags: nodeTags } = extractPipeMetadata(rest);
17202
17218
  warnUnknownMetaKeys(
17203
17219
  nodeTags,
17204
17220
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
17205
17221
  (msg) => warn2(lineNumber, msg)
17206
17222
  );
17207
- const id = nodeId2(name);
17208
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
17223
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
17224
+ if (alias) nameAliasMap.set(alias, id);
17209
17225
  const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
17210
17226
  currentNode = {
17211
17227
  id,
@@ -17227,18 +17243,20 @@ function parseInfra(content) {
17227
17243
  finishCurrentNode();
17228
17244
  finishCurrentTagGroup();
17229
17245
  currentGroup = null;
17230
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
17246
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
17247
+ const rawName = (qname ?? uname ?? "").trim();
17231
17248
  const peeled = peelInfraDecorations(rawName, lineNumber);
17232
17249
  const name = peeled.label;
17233
- const rest = compMatch[3] || "";
17250
+ const alias = asAlias ?? peeled.alias;
17251
+ const rest = meta ?? "";
17234
17252
  const { tags } = extractPipeMetadata(rest);
17235
17253
  warnUnknownMetaKeys(
17236
17254
  tags,
17237
17255
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
17238
17256
  (msg) => warn2(lineNumber, msg)
17239
17257
  );
17240
- const id = nodeId2(name);
17241
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
17258
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
17259
+ if (alias) nameAliasMap.set(alias, id);
17242
17260
  currentNode = {
17243
17261
  id,
17244
17262
  label: name,
@@ -17438,7 +17456,7 @@ var init_parser15 = __esm({
17438
17456
  DEPRECATED_FANOUT_RE = /\bx(\d+)\s*$/;
17439
17457
  GROUP_RE = /^\[([^\]]+)\]\s*(?:as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*)?((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17440
17458
  TAG_VALUE_RE = /^(\w[\w\s]+?)\s*$/;
17441
- COMPONENT_RE = /^(?:"([^"]+)"|([a-zA-Z_][\w -]*?))\s*((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17459
+ COMPONENT_RE = /^(?:"(?<qname>[^"]+)"|(?<uname>[a-zA-Z_][\w -]*?))(?:\s+as\s+(?<alias>[A-Za-z][A-Za-z0-9_]{0,11}))?\s*(?<meta>(?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17442
17460
  PIPE_META_RE = /[|,]\s*(\w+)\s*:\s*([^|,]+)/g;
17443
17461
  SAMELINE_META_RE = /(?:^|[\s,])(\w+)\s*:\s*([^,]+?)(?=\s*,|\s*$)/g;
17444
17462
  PROPERTY_RE = /^([\w-]+):\s*(.+)$/;
@@ -18922,8 +18940,8 @@ function parseMap(content, palette) {
18922
18940
  continue;
18923
18941
  }
18924
18942
  if (open.route && indent > open.route.indent) {
18925
- const leg = parseLeg(trimmed, lineNumber, open.route.route.style);
18926
- open.route.route.legs.push(leg);
18943
+ const leg = parseLeg(trimmed, lineNumber);
18944
+ if (leg) open.route.route.legs.push(leg);
18927
18945
  continue;
18928
18946
  }
18929
18947
  if (open.poi && indent > open.poi.indent) {
@@ -18952,6 +18970,14 @@ function parseMap(content, palette) {
18952
18970
  Object.assign(open.poi.poi.meta, split.meta);
18953
18971
  continue;
18954
18972
  }
18973
+ if (split.name) {
18974
+ const src = open.poi.poi.alias ?? poiName(open.poi.poi.pos) ?? "the poi";
18975
+ pushError(
18976
+ lineNumber,
18977
+ `Malformed hub edge: "${trimmed}" \u2014 an indented line under a poi is an edge from "${src}" and needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\`). For a standalone place, declare it at the top level. (\xA724B.5)`
18978
+ );
18979
+ continue;
18980
+ }
18955
18981
  }
18956
18982
  closeBlocks();
18957
18983
  const firstWord = trimmed.split(/\s+/)[0];
@@ -19200,31 +19226,44 @@ function parseMap(content, palette) {
19200
19226
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
19201
19227
  const originLabel = meta["label"];
19202
19228
  const originValue = meta["value"];
19203
- const style = meta["style"] === "arc" ? "arc" : "straight";
19229
+ if (meta["style"] !== void 0) {
19230
+ pushError(
19231
+ line11,
19232
+ "route header no longer takes `style:` \u2014 set leg shape with the arrow glyph instead (`~\u2026~>` for an arc leg, `-\u2026->` for a straight one). (\xA724B.6)"
19233
+ );
19234
+ }
19204
19235
  const route = {
19205
19236
  origin: pos,
19206
19237
  ...split.alias !== void 0 && { originAlias: split.alias },
19207
19238
  ...originLabel !== void 0 && { originLabel },
19208
19239
  ...originValue !== void 0 && { originValue },
19209
19240
  originTags: tags,
19210
- style,
19211
19241
  legs: [],
19212
19242
  lineNumber: line11
19213
19243
  };
19214
19244
  routes.push(route);
19215
19245
  open.route = { route, indent };
19216
19246
  }
19217
- function parseLeg(trimmed, line11, headerStyle) {
19218
- let arrowStyle = "straight";
19219
- let label;
19220
- let rest = trimmed;
19247
+ function parseLeg(trimmed, line11) {
19221
19248
  const m = trimmed.match(LEG_ARROW_RE);
19222
- if (m) {
19223
- const arr = classifyArrow(m[1], line11);
19224
- arrowStyle = arr.style;
19225
- label = arr.label;
19226
- rest = m[2];
19249
+ if (!m) {
19250
+ pushError(
19251
+ line11,
19252
+ `Malformed route leg: "${trimmed}" \u2014 a leg needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\` / \`~label~> dest\`). (\xA724B.6)`
19253
+ );
19254
+ return null;
19227
19255
  }
19256
+ const arr = classifyArrow(m[1], line11);
19257
+ if (!arr.directed) {
19258
+ pushError(
19259
+ line11,
19260
+ `A route leg is directional \u2014 "${trimmed}" uses an undirected glyph; use \`-> \` (straight) or \`~> \` (arc). (\xA724B.6)`
19261
+ );
19262
+ return null;
19263
+ }
19264
+ const arrowStyle = arr.style;
19265
+ const label = arr.label;
19266
+ const rest = m[2];
19228
19267
  const split = splitNameAndMeta(
19229
19268
  rest,
19230
19269
  registry(),
@@ -19240,10 +19279,9 @@ function parseMap(content, palette) {
19240
19279
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
19241
19280
  const value = meta["value"];
19242
19281
  const destLabel = meta["label"];
19243
- const style = arrowStyle === "arc" || headerStyle === "arc" ? "arc" : "straight";
19244
19282
  return {
19245
19283
  ...label !== void 0 && { label },
19246
- style,
19284
+ style: arrowStyle,
19247
19285
  ...value !== void 0 && { value },
19248
19286
  dest: pos,
19249
19287
  ...split.alias !== void 0 && { destAlias: split.alias },
@@ -53745,13 +53783,15 @@ function layoutMap(resolvedIn, data, size, opts) {
53745
53783
  labelY: lp.y
53746
53784
  };
53747
53785
  const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
53786
+ const routeVal = Number(leg.value);
53748
53787
  legs.push({
53749
53788
  d: legPath(a, b, bow.curved, bow.offset),
53750
- width: routeWidthFor(Number(leg.value)),
53789
+ width: routeWidthFor(routeVal),
53751
53790
  color: lineColor(leg.tags) ?? mix(palette.text, palette.bg, 72),
53752
53791
  arrow: true,
53753
53792
  fromId: leg.fromId,
53754
53793
  toId: leg.toId,
53794
+ ...Number.isFinite(routeVal) && routeVal > 0 && { value: routeVal },
53755
53795
  ...Object.keys(leg.tags).length > 0 && { tags: leg.tags },
53756
53796
  lineNumber: leg.lineNumber,
53757
53797
  ...leg.label !== void 0 && {
@@ -53798,6 +53838,7 @@ function layoutMap(resolvedIn, data, size, opts) {
53798
53838
  labelY: lp.y
53799
53839
  };
53800
53840
  const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
53841
+ const edgeVal = Number(e.meta["value"]);
53801
53842
  legs.push({
53802
53843
  d: legPath(a, b, bow.curved, bow.offset),
53803
53844
  width: widthFor(e),
@@ -53805,6 +53846,7 @@ function layoutMap(resolvedIn, data, size, opts) {
53805
53846
  arrow: e.directed,
53806
53847
  fromId: e.fromId,
53807
53848
  toId: e.toId,
53849
+ ...Number.isFinite(edgeVal) && edgeVal > 0 && { value: edgeVal },
53808
53850
  ...Object.keys(e.tags).length > 0 && { tags: e.tags },
53809
53851
  lineNumber: e.lineNumber,
53810
53852
  ...e.label !== void 0 && {
@@ -53962,18 +54004,49 @@ function layoutMap(resolvedIn, data, size, opts) {
53962
54004
  const SHORT_HOP_MAX = Math.max(46, Math.min(width, height) * 0.11);
53963
54005
  const STEP = 4;
53964
54006
  const HOP_GAP = 9;
54007
+ const CLEAR_STEP = 6;
54008
+ const CLEAR_MAX = SHORT_HOP_MAX * 3;
54009
+ const CLEAR_TOL = CLEAR_STEP;
54010
+ const clearanceAt = (px, py, ox, oy) => {
54011
+ const baseAng = Math.atan2(oy, ox);
54012
+ let minClear = CLEAR_MAX;
54013
+ for (let k = -2; k <= 2; k++) {
54014
+ const a = baseAng + k * Math.PI / 4;
54015
+ const rx = Math.cos(a);
54016
+ const ry = Math.sin(a);
54017
+ let d = CLEAR_STEP;
54018
+ for (; d <= CLEAR_MAX; d += CLEAR_STEP) {
54019
+ const qx = px + rx * d;
54020
+ const qy = py + ry * d;
54021
+ if (qx < FIT_PAD || qy < topPad || qx > width - FIT_PAD || qy > height - FIT_PAD)
54022
+ break;
54023
+ if (fillAt(qx, qy) !== water) break;
54024
+ }
54025
+ if (d < minClear) minClear = d;
54026
+ }
54027
+ return minClear;
54028
+ };
53965
54029
  const tryShortHopCallout = (cx, cy, fill2, name, value, font = FONT2, gap = HOP_GAP, maxLen = SHORT_HOP_MAX) => {
53966
54030
  const chipW = stackW(name, value, font);
53967
54031
  const chipH = stackH(value !== void 0, font);
54032
+ const D = Math.SQRT1_2;
53968
54033
  const dirs = [
53969
54034
  [0, -1],
53970
- // north (over Canada)
54035
+ // north
53971
54036
  [0, 1],
53972
- // south (over Mexico / Gulf)
54037
+ // south
53973
54038
  [1, 0],
53974
- // east (Atlantic)
53975
- [-1, 0]
53976
- // west (Pacific)
54039
+ // east
54040
+ [-1, 0],
54041
+ // west
54042
+ [D, -D],
54043
+ // NE
54044
+ [D, D],
54045
+ // SE
54046
+ [-D, -D],
54047
+ // NW
54048
+ [-D, D]
54049
+ // SW
53977
54050
  ];
53978
54051
  let best = null;
53979
54052
  for (const [dx, dy] of dirs) {
@@ -54023,13 +54096,16 @@ function layoutMap(resolvedIn, data, size, opts) {
54023
54096
  (p) => segmentRectOverlap(cx, cy, innerX, innerY, p)
54024
54097
  ))
54025
54098
  continue;
54026
- if (best === null || len < best.len)
54099
+ const clear = clearanceAt(ccx, ccy, dx, dy);
54100
+ const better = best === null || clear > best.clear + CLEAR_TOL || clear >= best.clear - CLEAR_TOL && len < best.len;
54101
+ if (better)
54027
54102
  best = {
54028
54103
  x: ccx,
54029
54104
  y: ccy,
54030
54105
  rect,
54031
54106
  leader: [cx, cy, innerX, innerY],
54032
- len
54107
+ len,
54108
+ clear
54033
54109
  };
54034
54110
  }
54035
54111
  return best ? { x: best.x, y: best.y, rect: best.rect, leader: best.leader } : null;
@@ -54690,6 +54766,9 @@ function layoutMap(resolvedIn, data, size, opts) {
54690
54766
  const nx = -dy / len;
54691
54767
  const ny = dx / len;
54692
54768
  const perp = labelH + 2;
54769
+ const stroke2 = lg.width ?? W_MIN;
54770
+ const clearW = stroke2 / 2 + labelH / 2 + 3;
54771
+ const offList = stroke2 >= 4 ? [clearW, -clearW, clearW + perp, -(clearW + perp), 0] : [0, perp, -perp, 2 * perp, -2 * perp];
54693
54772
  const pm = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
54694
54773
  lg.d
54695
54774
  );
@@ -54709,7 +54788,7 @@ function layoutMap(resolvedIn, data, size, opts) {
54709
54788
  return [a.cx + dx * t, a.cy + dy * t];
54710
54789
  };
54711
54790
  const candidates = [];
54712
- for (const off of [0, perp, -perp, 2 * perp, -2 * perp])
54791
+ for (const off of offList)
54713
54792
  for (const t of T_LIST) {
54714
54793
  const [bx, by] = pointAt(t);
54715
54794
  candidates.push([bx + nx * off, by + ny * off - 4]);
@@ -55460,6 +55539,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
55460
55539
  }
55461
55540
  }
55462
55541
  wireSync(p, leg.lineNumber);
55542
+ if (leg.value !== void 0) {
55543
+ p.attr("data-value", leg.value);
55544
+ p.append("title").text(
55545
+ leg.label !== void 0 ? `${leg.label}: ${leg.value}` : `${leg.value}`
55546
+ );
55547
+ }
55463
55548
  if (arrowTri) {
55464
55549
  gLegs.append("path").attr("d", arrowTri).attr("fill", leg.color).attr("stroke", leg.color).attr("stroke-width", 1).attr("stroke-linejoin", "round").attr("data-from-id", leg.fromId).attr("data-to-id", leg.toId);
55465
55550
  }
@@ -64509,7 +64594,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
64509
64594
 
64510
64595
  // src/auto/index.ts
64511
64596
  init_safe_href();
64512
- var VERSION = "0.36.0";
64597
+ var VERSION = "0.37.0";
64513
64598
  var DEFAULTS = {
64514
64599
  theme: "auto",
64515
64600
  palette: "slate",