@diagrammo/dgmo 0.8.23 → 0.8.26

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.
Files changed (78) hide show
  1. package/.claude/commands/dgmo.md +43 -431
  2. package/.cursorrules +2 -2
  3. package/.windsurfrules +2 -2
  4. package/AGENTS.md +8 -5
  5. package/dist/cli.cjs +119 -114
  6. package/dist/editor.cjs +0 -2
  7. package/dist/editor.cjs.map +1 -1
  8. package/dist/editor.js +0 -2
  9. package/dist/editor.js.map +1 -1
  10. package/dist/highlight.cjs +0 -2
  11. package/dist/highlight.cjs.map +1 -1
  12. package/dist/highlight.js +0 -2
  13. package/dist/highlight.js.map +1 -1
  14. package/dist/index.cjs +719 -281
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +105 -18
  17. package/dist/index.d.ts +105 -18
  18. package/dist/index.js +709 -280
  19. package/dist/index.js.map +1 -1
  20. package/dist/internal.cjs +348 -51
  21. package/dist/internal.cjs.map +1 -1
  22. package/dist/internal.d.cts +93 -5
  23. package/dist/internal.d.ts +93 -5
  24. package/dist/internal.js +334 -38
  25. package/dist/internal.js.map +1 -1
  26. package/docs/guide/chart-area.md +17 -17
  27. package/docs/guide/chart-bar-stacked.md +12 -12
  28. package/docs/guide/chart-doughnut.md +10 -10
  29. package/docs/guide/chart-funnel.md +9 -9
  30. package/docs/guide/chart-heatmap.md +10 -10
  31. package/docs/guide/chart-kanban.md +2 -0
  32. package/docs/guide/chart-line.md +19 -19
  33. package/docs/guide/chart-multi-line.md +16 -16
  34. package/docs/guide/chart-pie.md +11 -11
  35. package/docs/guide/chart-polar-area.md +10 -10
  36. package/docs/guide/chart-radar.md +9 -9
  37. package/docs/guide/chart-scatter.md +24 -27
  38. package/docs/guide/index.md +3 -3
  39. package/docs/language-reference.md +46 -25
  40. package/fonts/Inter-Bold.ttf +0 -0
  41. package/fonts/Inter-Regular.ttf +0 -0
  42. package/fonts/LICENSE-Inter.txt +92 -0
  43. package/gallery/fixtures/bar-stacked.dgmo +12 -6
  44. package/gallery/fixtures/heatmap.dgmo +12 -6
  45. package/gallery/fixtures/multi-line.dgmo +11 -7
  46. package/gallery/fixtures/quadrant.dgmo +8 -8
  47. package/gallery/fixtures/scatter.dgmo +12 -12
  48. package/package.json +10 -3
  49. package/src/boxes-and-lines/parser.ts +13 -2
  50. package/src/boxes-and-lines/renderer.ts +22 -13
  51. package/src/chart-type-scoring.ts +162 -0
  52. package/src/chart-types.ts +437 -0
  53. package/src/cli.ts +147 -66
  54. package/src/completion.ts +0 -4
  55. package/src/d3.ts +40 -2
  56. package/src/dgmo-router.ts +85 -130
  57. package/src/editor/keywords.ts +0 -2
  58. package/src/fonts.ts +3 -2
  59. package/src/gantt/parser.ts +5 -1
  60. package/src/index.ts +24 -1
  61. package/src/infra/parser.ts +1 -1
  62. package/src/internal.ts +6 -2
  63. package/src/journey-map/layout.ts +8 -6
  64. package/src/journey-map/parser.ts +5 -1
  65. package/src/kanban/parser.ts +5 -1
  66. package/src/org/collapse.ts +1 -4
  67. package/src/org/parser.ts +1 -1
  68. package/src/org/renderer.ts +26 -17
  69. package/src/sequence/parser.ts +2 -2
  70. package/src/sequence/participant-inference.ts +0 -1
  71. package/src/sequence/renderer.ts +95 -263
  72. package/src/sharing.ts +0 -1
  73. package/src/sitemap/parser.ts +1 -1
  74. package/src/tech-radar/layout.ts +1 -2
  75. package/src/tech-radar/shared.ts +1 -37
  76. package/src/utils/tag-groups.ts +35 -5
  77. package/src/wireframe/parser.ts +3 -1
  78. package/src/tech-radar/index.ts +0 -14
package/dist/internal.cjs CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,19 +30,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
30
- // src/internal.ts
31
- var internal_exports = {};
32
- __export(internal_exports, {
33
- buildNoteMessageMap: () => buildNoteMessageMap,
34
- collectNoteLineNumbers: () => collectNoteLineNumbers,
35
- computeCardArchive: () => computeCardArchive,
36
- computeCardMove: () => computeCardMove,
37
- groupMessagesBySection: () => groupMessagesBySection,
38
- isArchiveColumn: () => isArchiveColumn,
39
- parseDataRowValues: () => parseDataRowValues
40
- });
41
- module.exports = __toCommonJS(internal_exports);
42
-
43
33
  // src/utils/parsing.ts
44
34
  function normalizeNumericToken(token) {
45
35
  if (!token.includes(",") && !token.includes("_")) return null;
@@ -63,10 +53,15 @@ function normalizeNumericToken(token) {
63
53
  return sign + unsigned.replace(/_/g, "");
64
54
  return null;
65
55
  }
56
+ var init_parsing = __esm({
57
+ "src/utils/parsing.ts"() {
58
+ "use strict";
59
+ }
60
+ });
66
61
 
67
62
  // src/chart.ts
68
- function parseDataRowValues(line, options) {
69
- const segments = line.split(",");
63
+ function parseDataRowValues(line2, options) {
64
+ const segments = line2.split(",");
70
65
  const normalized = [];
71
66
  for (let i = 0; i < segments.length; i++) {
72
67
  const seg = segments[i].trim();
@@ -143,9 +138,14 @@ function parseDataRowValues(line, options) {
143
138
  if (!label) return null;
144
139
  return { label, values: [num] };
145
140
  }
141
+ var init_chart = __esm({
142
+ "src/chart.ts"() {
143
+ "use strict";
144
+ init_parsing();
145
+ }
146
+ });
146
147
 
147
148
  // src/kanban/mutations.ts
148
- var ARCHIVE_COLUMN_NAME = "archive";
149
149
  function computeCardMove(content, parsed, cardId, targetColumnId, targetIndex) {
150
150
  let sourceCard = null;
151
151
  let sourceColumn = null;
@@ -249,9 +249,13 @@ function computeCardArchive(content, parsed, cardId) {
249
249
  function isArchiveColumn(name) {
250
250
  return name.toLowerCase() === ARCHIVE_COLUMN_NAME;
251
251
  }
252
-
253
- // src/sequence/renderer.ts
254
- var d3Selection = __toESM(require("d3-selection"), 1);
252
+ var ARCHIVE_COLUMN_NAME;
253
+ var init_mutations = __esm({
254
+ "src/kanban/mutations.ts"() {
255
+ "use strict";
256
+ ARCHIVE_COLUMN_NAME = "archive";
257
+ }
258
+ });
255
259
 
256
260
  // src/sequence/parser.ts
257
261
  function isSequenceBlock(el) {
@@ -263,24 +267,13 @@ function isSequenceSection(el) {
263
267
  function isSequenceNote(el) {
264
268
  return "kind" in el && el.kind === "note";
265
269
  }
270
+ var init_parser = __esm({
271
+ "src/sequence/parser.ts"() {
272
+ "use strict";
273
+ }
274
+ });
266
275
 
267
276
  // src/sequence/renderer.ts
268
- var PARTICIPANT_GAP = 160;
269
- var PARTICIPANT_BOX_WIDTH = 120;
270
- var NOTE_MAX_W = 200;
271
- var NOTE_FOLD = 10;
272
- var NOTE_PAD_H = 8;
273
- var NOTE_GAP = 15;
274
- var NOTE_CHAR_W = 6;
275
- var NOTE_CHARS_PER_LINE = Math.floor(
276
- (NOTE_MAX_W - NOTE_PAD_H * 2 - NOTE_FOLD) / NOTE_CHAR_W
277
- );
278
- var ACTIVATION_WIDTH = 10;
279
- var NOTE_LANE_MAX = PARTICIPANT_GAP - ACTIVATION_WIDTH - NOTE_GAP;
280
- var LABEL_CHAR_WIDTH = 7.5;
281
- var LABEL_MAX_CHARS = Math.floor(
282
- (PARTICIPANT_BOX_WIDTH - 10) / LABEL_CHAR_WIDTH
283
- );
284
277
  function groupMessagesBySection(elements, messages) {
285
278
  const groups = [];
286
279
  let currentGroup = null;
@@ -321,6 +314,180 @@ function groupMessagesBySection(elements, messages) {
321
314
  }
322
315
  return groups;
323
316
  }
317
+ function buildRenderSequence(messages) {
318
+ const steps = [];
319
+ const stack = [];
320
+ for (let mi = 0; mi < messages.length; mi++) {
321
+ const msg = messages[mi];
322
+ while (stack.length > 0) {
323
+ const top = stack[stack.length - 1];
324
+ if (top.to === msg.from) break;
325
+ stack.pop();
326
+ steps.push({
327
+ type: "return",
328
+ from: top.to,
329
+ to: top.from,
330
+ label: "",
331
+ messageIndex: top.messageIndex
332
+ });
333
+ }
334
+ steps.push({
335
+ type: "call",
336
+ from: msg.from,
337
+ to: msg.to,
338
+ label: msg.label,
339
+ messageIndex: mi,
340
+ ...msg.async ? { async: true } : {}
341
+ });
342
+ if (msg.async) {
343
+ continue;
344
+ }
345
+ if (msg.from === msg.to) {
346
+ steps.push({
347
+ type: "return",
348
+ from: msg.to,
349
+ to: msg.from,
350
+ label: "",
351
+ messageIndex: mi
352
+ });
353
+ } else {
354
+ stack.push({
355
+ from: msg.from,
356
+ to: msg.to,
357
+ messageIndex: mi
358
+ });
359
+ }
360
+ }
361
+ while (stack.length > 0) {
362
+ const top = stack.pop();
363
+ steps.push({
364
+ type: "return",
365
+ from: top.to,
366
+ to: top.from,
367
+ label: "",
368
+ messageIndex: top.messageIndex
369
+ });
370
+ }
371
+ return steps;
372
+ }
373
+ function computeActivations(steps) {
374
+ const activations = [];
375
+ const stacks = /* @__PURE__ */ new Map();
376
+ const getStack = (id) => {
377
+ if (!stacks.has(id)) stacks.set(id, []);
378
+ return stacks.get(id);
379
+ };
380
+ for (let i = 0; i < steps.length; i++) {
381
+ const step = steps[i];
382
+ if (step.type === "call") {
383
+ const s = getStack(step.to);
384
+ s.push(i);
385
+ } else {
386
+ const s = getStack(step.from);
387
+ if (s.length > 0) {
388
+ const startIdx = s.pop();
389
+ activations.push({
390
+ participantId: step.from,
391
+ startStep: startIdx,
392
+ endStep: i,
393
+ depth: s.length
394
+ });
395
+ }
396
+ }
397
+ }
398
+ return activations;
399
+ }
400
+ function applyPositionOverrides(participants) {
401
+ if (!participants.some((p) => p.position !== void 0)) return participants;
402
+ const total = participants.length;
403
+ const positioned = [];
404
+ const unpositioned = [];
405
+ for (const p of participants) {
406
+ if (p.position !== void 0) {
407
+ let idx = p.position < 0 ? total + p.position : p.position;
408
+ idx = Math.max(0, Math.min(total - 1, idx));
409
+ positioned.push({ participant: p, index: idx });
410
+ } else {
411
+ unpositioned.push(p);
412
+ }
413
+ }
414
+ positioned.sort((a, b) => a.index - b.index);
415
+ const result = new Array(total).fill(null);
416
+ const usedIndices = /* @__PURE__ */ new Set();
417
+ for (const { participant, index } of positioned) {
418
+ let idx = index;
419
+ if (usedIndices.has(idx)) {
420
+ for (let offset = 1; offset < total; offset++) {
421
+ if (idx + offset < total && !usedIndices.has(idx + offset)) {
422
+ idx = idx + offset;
423
+ break;
424
+ }
425
+ if (idx - offset >= 0 && !usedIndices.has(idx - offset)) {
426
+ idx = idx - offset;
427
+ break;
428
+ }
429
+ }
430
+ }
431
+ result[idx] = participant;
432
+ usedIndices.add(idx);
433
+ }
434
+ let uIdx = 0;
435
+ for (let i = 0; i < total; i++) {
436
+ if (result[i] === null) {
437
+ result[i] = unpositioned[uIdx++];
438
+ }
439
+ }
440
+ return result;
441
+ }
442
+ function applyGroupOrdering(participants, groups, messages = []) {
443
+ if (groups.length === 0) return participants;
444
+ const idToGroup = /* @__PURE__ */ new Map();
445
+ for (const group of groups) {
446
+ for (const id of group.participantIds) {
447
+ idToGroup.set(id, group);
448
+ }
449
+ }
450
+ const appearanceOrder = [];
451
+ const seen = /* @__PURE__ */ new Set();
452
+ for (const msg of messages) {
453
+ for (const id of [msg.from, msg.to]) {
454
+ if (!seen.has(id)) {
455
+ seen.add(id);
456
+ appearanceOrder.push(id);
457
+ }
458
+ }
459
+ }
460
+ for (const p of participants) {
461
+ if (!seen.has(p.id)) {
462
+ seen.add(p.id);
463
+ appearanceOrder.push(p.id);
464
+ }
465
+ }
466
+ const result = [];
467
+ const placed = /* @__PURE__ */ new Set();
468
+ const placedGroups = /* @__PURE__ */ new Set();
469
+ for (const id of appearanceOrder) {
470
+ if (placed.has(id)) continue;
471
+ const group = idToGroup.get(id);
472
+ if (group && !placedGroups.has(group)) {
473
+ placedGroups.add(group);
474
+ for (const gid of group.participantIds) {
475
+ const p = participants.find((pp) => pp.id === gid);
476
+ if (p && !placed.has(gid)) {
477
+ result.push(p);
478
+ placed.add(gid);
479
+ }
480
+ }
481
+ } else if (!group) {
482
+ const p = participants.find((pp) => pp.id === id);
483
+ if (p) {
484
+ result.push(p);
485
+ placed.add(id);
486
+ }
487
+ }
488
+ }
489
+ return result;
490
+ }
324
491
  function buildNoteMessageMap(elements) {
325
492
  const map = /* @__PURE__ */ new Map();
326
493
  let lastMessageLine = -1;
@@ -347,34 +514,164 @@ function buildNoteMessageMap(elements) {
347
514
  walk(elements);
348
515
  return map;
349
516
  }
350
- function collectNoteLineNumbers(elements) {
351
- const result = [];
352
- const walk = (els) => {
353
- for (const el of els) {
354
- if (isSequenceNote(el)) {
355
- result.push(el.lineNumber);
356
- } else if (isSequenceBlock(el)) {
357
- walk(el.children);
358
- if (el.elseIfBranches) {
359
- for (const branch of el.elseIfBranches) {
360
- walk(branch.children);
517
+ var d3Selection, PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, NOTE_MAX_W, NOTE_FOLD, NOTE_PAD_H, NOTE_GAP, NOTE_CHAR_W, NOTE_CHARS_PER_LINE, ACTIVATION_WIDTH, NOTE_LANE_MAX, LABEL_CHAR_WIDTH, LABEL_MAX_CHARS;
518
+ var init_renderer = __esm({
519
+ "src/sequence/renderer.ts"() {
520
+ "use strict";
521
+ d3Selection = __toESM(require("d3-selection"), 1);
522
+ init_parser();
523
+ PARTICIPANT_GAP = 160;
524
+ PARTICIPANT_BOX_WIDTH = 120;
525
+ NOTE_MAX_W = 200;
526
+ NOTE_FOLD = 10;
527
+ NOTE_PAD_H = 8;
528
+ NOTE_GAP = 15;
529
+ NOTE_CHAR_W = 6;
530
+ NOTE_CHARS_PER_LINE = Math.floor(
531
+ (NOTE_MAX_W - NOTE_PAD_H * 2 - NOTE_FOLD) / NOTE_CHAR_W
532
+ );
533
+ ACTIVATION_WIDTH = 10;
534
+ NOTE_LANE_MAX = PARTICIPANT_GAP - ACTIVATION_WIDTH - NOTE_GAP;
535
+ LABEL_CHAR_WIDTH = 7.5;
536
+ LABEL_MAX_CHARS = Math.floor(
537
+ (PARTICIPANT_BOX_WIDTH - 10) / LABEL_CHAR_WIDTH
538
+ );
539
+ }
540
+ });
541
+
542
+ // src/d3.ts
543
+ function orderArcNodes(links, order, groups) {
544
+ const nodeSet = /* @__PURE__ */ new Set();
545
+ for (const link of links) {
546
+ nodeSet.add(link.source);
547
+ nodeSet.add(link.target);
548
+ }
549
+ const allNodes = Array.from(nodeSet);
550
+ if (order === "name") {
551
+ return allNodes.slice().sort((a, b) => a.localeCompare(b));
552
+ }
553
+ if (order === "degree") {
554
+ const degree = /* @__PURE__ */ new Map();
555
+ for (const node of allNodes) degree.set(node, 0);
556
+ for (const link of links) {
557
+ degree.set(link.source, degree.get(link.source) + link.value);
558
+ degree.set(link.target, degree.get(link.target) + link.value);
559
+ }
560
+ return allNodes.slice().sort((a, b) => {
561
+ const diff = degree.get(b) - degree.get(a);
562
+ return diff !== 0 ? diff : a.localeCompare(b);
563
+ });
564
+ }
565
+ if (order === "group") {
566
+ if (groups.length > 0) {
567
+ const ordered = [];
568
+ const placed = /* @__PURE__ */ new Set();
569
+ for (const group of groups) {
570
+ for (const node of group.nodes) {
571
+ if (!placed.has(node)) {
572
+ ordered.push(node);
573
+ placed.add(node);
361
574
  }
362
575
  }
363
- walk(el.elseChildren);
364
576
  }
577
+ for (const node of allNodes) {
578
+ if (!placed.has(node)) {
579
+ ordered.push(node);
580
+ placed.add(node);
581
+ }
582
+ }
583
+ return ordered;
365
584
  }
366
- };
367
- walk(elements);
368
- return result;
585
+ const adj = /* @__PURE__ */ new Map();
586
+ for (const node of allNodes) adj.set(node, /* @__PURE__ */ new Set());
587
+ for (const link of links) {
588
+ adj.get(link.source).add(link.target);
589
+ adj.get(link.target).add(link.source);
590
+ }
591
+ const degree = /* @__PURE__ */ new Map();
592
+ for (const node of allNodes) degree.set(node, 0);
593
+ for (const link of links) {
594
+ degree.set(link.source, degree.get(link.source) + link.value);
595
+ degree.set(link.target, degree.get(link.target) + link.value);
596
+ }
597
+ const visited = /* @__PURE__ */ new Set();
598
+ const components = [];
599
+ const remaining = new Set(allNodes);
600
+ while (remaining.size > 0) {
601
+ let root = "";
602
+ let maxDeg = -1;
603
+ for (const node of remaining) {
604
+ if (degree.get(node) > maxDeg) {
605
+ maxDeg = degree.get(node);
606
+ root = node;
607
+ }
608
+ }
609
+ const component = [];
610
+ const queue = [root];
611
+ visited.add(root);
612
+ remaining.delete(root);
613
+ while (queue.length > 0) {
614
+ const curr = queue.shift();
615
+ component.push(curr);
616
+ for (const neighbor of adj.get(curr)) {
617
+ if (!visited.has(neighbor)) {
618
+ visited.add(neighbor);
619
+ remaining.delete(neighbor);
620
+ queue.push(neighbor);
621
+ }
622
+ }
623
+ }
624
+ components.push(component);
625
+ }
626
+ components.sort((a, b) => b.length - a.length);
627
+ return components.flat();
628
+ }
629
+ return allNodes;
369
630
  }
631
+ var d3Scale, d3Selection2, d3Shape, d3Array, import_d3_cloud;
632
+ var init_d3 = __esm({
633
+ "src/d3.ts"() {
634
+ "use strict";
635
+ d3Scale = __toESM(require("d3-scale"), 1);
636
+ d3Selection2 = __toESM(require("d3-selection"), 1);
637
+ d3Shape = __toESM(require("d3-shape"), 1);
638
+ d3Array = __toESM(require("d3-array"), 1);
639
+ import_d3_cloud = __toESM(require("d3-cloud"), 1);
640
+ }
641
+ });
642
+
643
+ // src/internal.ts
644
+ var internal_exports = {};
645
+ __export(internal_exports, {
646
+ applyGroupOrdering: () => applyGroupOrdering,
647
+ applyPositionOverrides: () => applyPositionOverrides,
648
+ buildNoteMessageMap: () => buildNoteMessageMap,
649
+ buildRenderSequence: () => buildRenderSequence,
650
+ computeActivations: () => computeActivations,
651
+ computeCardArchive: () => computeCardArchive,
652
+ computeCardMove: () => computeCardMove,
653
+ groupMessagesBySection: () => groupMessagesBySection,
654
+ isArchiveColumn: () => isArchiveColumn,
655
+ orderArcNodes: () => orderArcNodes,
656
+ parseDataRowValues: () => parseDataRowValues
657
+ });
658
+ module.exports = __toCommonJS(internal_exports);
659
+ init_chart();
660
+ init_mutations();
661
+ init_renderer();
662
+ init_d3();
370
663
  // Annotate the CommonJS export names for ESM import in node:
371
664
  0 && (module.exports = {
665
+ applyGroupOrdering,
666
+ applyPositionOverrides,
372
667
  buildNoteMessageMap,
373
- collectNoteLineNumbers,
668
+ buildRenderSequence,
669
+ computeActivations,
374
670
  computeCardArchive,
375
671
  computeCardMove,
376
672
  groupMessagesBySection,
377
673
  isArchiveColumn,
674
+ orderArcNodes,
378
675
  parseDataRowValues
379
676
  });
380
677
  //# sourceMappingURL=internal.cjs.map