@diagrammo/dgmo 0.2.7 → 0.2.9

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/index.cjs CHANGED
@@ -218,6 +218,7 @@ function measureIndent(line3) {
218
218
  function parseSequenceDgmo(content) {
219
219
  const result = {
220
220
  title: null,
221
+ titleLineNumber: null,
221
222
  participants: [],
222
223
  messages: [],
223
224
  elements: [],
@@ -321,6 +322,7 @@ function parseSequenceDgmo(content) {
321
322
  }
322
323
  if (key === "title") {
323
324
  result.title = value;
325
+ result.titleLineNumber = lineNumber;
324
326
  continue;
325
327
  }
326
328
  result.options[key] = value;
@@ -550,22 +552,19 @@ function parseSequenceDgmo(content) {
550
552
  const notePosition = noteSingleMatch[1]?.toLowerCase() || "right";
551
553
  let noteParticipant = noteSingleMatch[2] || null;
552
554
  if (!noteParticipant) {
553
- if (!lastMsgFrom) {
554
- result.error = `Line ${lineNumber}: note requires a preceding message`;
555
- return result;
556
- }
555
+ if (!lastMsgFrom) continue;
557
556
  noteParticipant = lastMsgFrom;
558
557
  }
559
558
  if (!result.participants.some((p) => p.id === noteParticipant)) {
560
- result.error = `Line ${lineNumber}: note references unknown participant '${noteParticipant}'`;
561
- return result;
559
+ continue;
562
560
  }
563
561
  const note = {
564
562
  kind: "note",
565
563
  text: noteSingleMatch[3].trim(),
566
564
  position: notePosition,
567
565
  participantId: noteParticipant,
568
- lineNumber
566
+ lineNumber,
567
+ endLineNumber: lineNumber
569
568
  };
570
569
  currentContainer().push(note);
571
570
  continue;
@@ -575,15 +574,11 @@ function parseSequenceDgmo(content) {
575
574
  const notePosition = noteMultiMatch[1]?.toLowerCase() || "right";
576
575
  let noteParticipant = noteMultiMatch[2] || null;
577
576
  if (!noteParticipant) {
578
- if (!lastMsgFrom) {
579
- result.error = `Line ${lineNumber}: note requires a preceding message`;
580
- return result;
581
- }
577
+ if (!lastMsgFrom) continue;
582
578
  noteParticipant = lastMsgFrom;
583
579
  }
584
580
  if (!result.participants.some((p) => p.id === noteParticipant)) {
585
- result.error = `Line ${lineNumber}: note references unknown participant '${noteParticipant}'`;
586
- return result;
581
+ continue;
587
582
  }
588
583
  const noteLines = [];
589
584
  while (i + 1 < lines.length) {
@@ -595,16 +590,15 @@ function parseSequenceDgmo(content) {
595
590
  noteLines.push(nextTrimmed);
596
591
  i++;
597
592
  }
598
- if (noteLines.length === 0) {
599
- result.error = `Line ${lineNumber}: multi-line note has no content \u2014 add indented lines or use 'note: text'`;
600
- return result;
601
- }
593
+ if (noteLines.length === 0) continue;
602
594
  const note = {
603
595
  kind: "note",
604
596
  text: noteLines.join("\n"),
605
597
  position: notePosition,
606
598
  participantId: noteParticipant,
607
- lineNumber
599
+ lineNumber,
600
+ endLineNumber: i + 1
601
+ // i has advanced past the body lines (1-based)
608
602
  };
609
603
  currentContainer().push(note);
610
604
  continue;
@@ -652,7 +646,7 @@ var init_parser = __esm({
652
646
  ARROW_RETURN_PATTERN = /^(.+?)\s*<-\s*(.+)$/;
653
647
  UML_RETURN_PATTERN = /^(\w+\([^)]*\))\s*:\s*(.+)$/;
654
648
  NOTE_SINGLE = /^note(?:\s+(right|left)\s+of\s+(\S+))?\s*:\s*(.+)$/i;
655
- NOTE_MULTI = /^note(?:\s+(right|left)\s+of\s+(\S+))?\s*$/i;
649
+ NOTE_MULTI = /^note(?:\s+(right|left)\s+of\s+([^\s:]+))?\s*:?\s*$/i;
656
650
  }
657
651
  });
658
652
 
@@ -997,6 +991,7 @@ function parseFlowchart(content, palette) {
997
991
  }
998
992
  if (key === "title") {
999
993
  result.title = value;
994
+ result.titleLineNumber = lineNumber;
1000
995
  continue;
1001
996
  }
1002
997
  if (key === "direction") {
@@ -2433,7 +2428,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
2433
2428
  const scaledH = diagramH * scale;
2434
2429
  const offsetX = (width - scaledW) / 2;
2435
2430
  const offsetY = (height - scaledH) / 2;
2436
- const svg = d3Selection.select(container).append("svg").attr("width", width).attr("height", height).style("background", palette.bg).style("font-family", FONT_FAMILY);
2431
+ const svg = d3Selection.select(container).append("svg").attr("width", width).attr("height", height).style("font-family", FONT_FAMILY);
2437
2432
  const defs = svg.append("defs");
2438
2433
  defs.append("marker").attr("id", "fc-arrow").attr("viewBox", `0 0 ${ARROWHEAD_W} ${ARROWHEAD_H}`).attr("refX", ARROWHEAD_W).attr("refY", ARROWHEAD_H / 2).attr("markerWidth", ARROWHEAD_W).attr("markerHeight", ARROWHEAD_H).attr("orient", "auto").append("polygon").attr("points", `0,0 ${ARROWHEAD_W},${ARROWHEAD_H / 2} 0,${ARROWHEAD_H}`).attr("fill", palette.textMuted);
2439
2434
  const edgeColors = /* @__PURE__ */ new Set();
@@ -2446,7 +2441,17 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
2446
2441
  }
2447
2442
  const mainG = svg.append("g").attr("transform", `translate(${offsetX}, ${offsetY}) scale(${scale})`);
2448
2443
  if (graph.title) {
2449
- mainG.append("text").attr("x", diagramW / 2).attr("y", TITLE_FONT_SIZE).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", "bold").attr("class", "fc-title").text(graph.title);
2444
+ const titleEl = mainG.append("text").attr("x", diagramW / 2).attr("y", TITLE_FONT_SIZE).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", "bold").attr("class", "fc-title chart-title").style("cursor", onClickItem && graph.titleLineNumber ? "pointer" : "default").text(graph.title);
2445
+ if (graph.titleLineNumber) {
2446
+ titleEl.attr("data-line-number", graph.titleLineNumber);
2447
+ if (onClickItem) {
2448
+ titleEl.on("click", () => onClickItem(graph.titleLineNumber)).on("mouseenter", function() {
2449
+ d3Selection.select(this).attr("opacity", 0.7);
2450
+ }).on("mouseleave", function() {
2451
+ d3Selection.select(this).attr("opacity", 1);
2452
+ });
2453
+ }
2454
+ }
2450
2455
  }
2451
2456
  const contentG = mainG.append("g").attr("transform", `translate(0, ${titleOffset})`);
2452
2457
  for (const group of layout.groups) {
@@ -2480,7 +2485,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
2480
2485
  }
2481
2486
  }
2482
2487
  for (const node of layout.nodes) {
2483
- const nodeG = contentG.append("g").attr("transform", `translate(${node.x}, ${node.y})`).attr("class", "fc-node").attr("data-line-number", String(node.lineNumber));
2488
+ const nodeG = contentG.append("g").attr("transform", `translate(${node.x}, ${node.y})`).attr("class", "fc-node").attr("data-line-number", String(node.lineNumber)).attr("data-node-id", node.id);
2484
2489
  if (onClickItem) {
2485
2490
  nodeG.style("cursor", "pointer").on("click", () => {
2486
2491
  onClickItem(node.lineNumber);
@@ -2564,14 +2569,16 @@ __export(renderer_exports, {
2564
2569
  });
2565
2570
  function parseInlineMarkdown(text) {
2566
2571
  const spans = [];
2567
- const regex = /\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`|\[(.+?)\]\((.+?)\)|([^*`[]+)/g;
2572
+ const regex = /\*\*(.+?)\*\*|__(.+?)__|\*(.+?)\*|_(.+?)_|`(.+?)`|\[(.+?)\]\((.+?)\)|([^*_`[]+)/g;
2568
2573
  let match;
2569
2574
  while ((match = regex.exec(text)) !== null) {
2570
2575
  if (match[1]) spans.push({ text: match[1], bold: true });
2571
- else if (match[2]) spans.push({ text: match[2], italic: true });
2572
- else if (match[3]) spans.push({ text: match[3], code: true });
2573
- else if (match[4]) spans.push({ text: match[4], href: match[5] });
2574
- else if (match[6]) spans.push({ text: match[6] });
2576
+ else if (match[2]) spans.push({ text: match[2], bold: true });
2577
+ else if (match[3]) spans.push({ text: match[3], italic: true });
2578
+ else if (match[4]) spans.push({ text: match[4], italic: true });
2579
+ else if (match[5]) spans.push({ text: match[5], code: true });
2580
+ else if (match[6]) spans.push({ text: match[6], href: match[7] });
2581
+ else if (match[8]) spans.push({ text: match[8] });
2575
2582
  }
2576
2583
  return spans;
2577
2584
  }
@@ -2970,6 +2977,34 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
2970
2977
  if (elements && elements.length > 0) {
2971
2978
  markBlockSpacing(elements);
2972
2979
  }
2980
+ const NOTE_OFFSET_BELOW = 16;
2981
+ const computeNoteHeight = (text) => {
2982
+ const lines = wrapTextLines(text, NOTE_CHARS_PER_LINE);
2983
+ return lines.length * NOTE_LINE_H + NOTE_PAD_V * 2;
2984
+ };
2985
+ const markNoteSpacing = (els) => {
2986
+ for (let i = 0; i < els.length; i++) {
2987
+ const el = els[i];
2988
+ if (isSequenceNote(el)) {
2989
+ const noteH = computeNoteHeight(el.text);
2990
+ const nextIdx = i + 1 < els.length ? findFirstMsgIndex([els[i + 1]]) : -1;
2991
+ if (nextIdx >= 0) {
2992
+ addExtra(nextIdx, noteH + NOTE_OFFSET_BELOW);
2993
+ }
2994
+ } else if (isSequenceBlock(el)) {
2995
+ markNoteSpacing(el.children);
2996
+ if (el.elseIfBranches) {
2997
+ for (const branch of el.elseIfBranches) {
2998
+ markNoteSpacing(branch.children);
2999
+ }
3000
+ }
3001
+ markNoteSpacing(el.elseChildren);
3002
+ }
3003
+ }
3004
+ };
3005
+ if (elements && elements.length > 0) {
3006
+ markNoteSpacing(elements);
3007
+ }
2973
3008
  const preSectionMsgIndices = [];
2974
3009
  const sectionRegions = [];
2975
3010
  {
@@ -3142,7 +3177,10 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
3142
3177
  `0,0 ${ARROWHEAD_SIZE},${ARROWHEAD_SIZE / 2} 0,${ARROWHEAD_SIZE}`
3143
3178
  ).attr("fill", "none").attr("stroke", palette.text).attr("stroke-width", 1.2);
3144
3179
  if (title) {
3145
- svg.append("text").attr("x", svgWidth / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", 20).attr("font-weight", "bold").text(title);
3180
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", svgWidth / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", 20).attr("font-weight", "bold").text(title);
3181
+ if (parsed.titleLineNumber) {
3182
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
3183
+ }
3146
3184
  }
3147
3185
  for (const group of groups) {
3148
3186
  if (group.participantIds.length === 0) continue;
@@ -3481,8 +3519,8 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
3481
3519
  );
3482
3520
  const isRight = el.position === "right";
3483
3521
  const noteX = isRight ? px + ACTIVATION_WIDTH + NOTE_GAP : px - ACTIVATION_WIDTH - NOTE_GAP - noteW;
3484
- const noteTopY = noteY - noteH / 2;
3485
- const noteG = svg.append("g").attr("class", "note").attr("data-note-toggle", "").attr("data-line-number", String(el.lineNumber));
3522
+ const noteTopY = noteY + NOTE_OFFSET_BELOW;
3523
+ const noteG = svg.append("g").attr("class", "note").attr("data-note-toggle", "").attr("data-line-number", String(el.lineNumber)).attr("data-line-end", String(el.endLineNumber));
3486
3524
  noteG.append("path").attr(
3487
3525
  "d",
3488
3526
  [
@@ -3502,13 +3540,16 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
3502
3540
  `L ${noteX + noteW} ${noteTopY + NOTE_FOLD}`
3503
3541
  ].join(" ")
3504
3542
  ).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 0.75).attr("class", "note-fold");
3505
- const connectorNoteX = isRight ? noteX : noteX + noteW;
3506
- const connectorLifeX = isRight ? px + ACTIVATION_WIDTH / 2 : px - ACTIVATION_WIDTH / 2;
3507
- noteG.append("line").attr("x1", connectorNoteX).attr("y1", noteY).attr("x2", connectorLifeX).attr("y2", noteY).attr("stroke", palette.textMuted).attr("stroke-width", 0.75).attr("stroke-dasharray", "3 2").attr("class", "note-connector");
3508
3543
  wrappedLines.forEach((line3, li) => {
3509
3544
  const textY = noteTopY + NOTE_PAD_V + (li + 1) * NOTE_LINE_H - 3;
3510
- const textEl = noteG.append("text").attr("x", noteX + NOTE_PAD_H).attr("y", textY).attr("fill", palette.text).attr("font-size", NOTE_FONT_SIZE).attr("class", "note-text");
3511
- const spans = parseInlineMarkdown(line3);
3545
+ const isBullet = line3.startsWith("- ");
3546
+ const bulletIndent = isBullet ? 10 : 0;
3547
+ const displayLine = isBullet ? line3.slice(2) : line3;
3548
+ const textEl = noteG.append("text").attr("x", noteX + NOTE_PAD_H + bulletIndent).attr("y", textY).attr("fill", palette.text).attr("font-size", NOTE_FONT_SIZE).attr("class", "note-text");
3549
+ if (isBullet) {
3550
+ noteG.append("text").attr("x", noteX + NOTE_PAD_H).attr("y", textY).attr("fill", palette.text).attr("font-size", NOTE_FONT_SIZE).text("\u2022");
3551
+ }
3552
+ const spans = parseInlineMarkdown(displayLine);
3512
3553
  for (const span of spans) {
3513
3554
  if (span.href) {
3514
3555
  const a = textEl.append("a").attr("href", span.href);
@@ -3729,6 +3770,7 @@ function parseChart(content, palette) {
3729
3770
  }
3730
3771
  if (key === "title") {
3731
3772
  result.title = value;
3773
+ result.titleLineNumber = lineNumber;
3732
3774
  continue;
3733
3775
  }
3734
3776
  if (key === "xlabel") {
@@ -3870,6 +3912,7 @@ function parseEChart(content, palette) {
3870
3912
  }
3871
3913
  if (key === "title") {
3872
3914
  result.title = value;
3915
+ result.titleLineNumber = lineNumber;
3873
3916
  continue;
3874
3917
  }
3875
3918
  if (key === "series") {
@@ -5231,6 +5274,7 @@ function parseD3(content, palette) {
5231
5274
  const result = {
5232
5275
  type: null,
5233
5276
  title: null,
5277
+ titleLineNumber: null,
5234
5278
  orientation: "horizontal",
5235
5279
  periods: [],
5236
5280
  data: [],
@@ -5492,6 +5536,7 @@ function parseD3(content, palette) {
5492
5536
  }
5493
5537
  if (key === "title") {
5494
5538
  result.title = line3.substring(colonIndex + 1).trim();
5539
+ result.titleLineNumber = lineNumber;
5495
5540
  if (result.type === "quadrant") {
5496
5541
  result.quadrantTitleLineNumber = lineNumber;
5497
5542
  }
@@ -5854,7 +5899,17 @@ function renderSlopeChart(container, parsed, palette, isDark, onClickItem, expor
5854
5899
  const g = svg.append("g").attr("transform", `translate(${SLOPE_MARGIN.left},${SLOPE_MARGIN.top})`);
5855
5900
  const tooltip = createTooltip(container, palette, isDark);
5856
5901
  if (title) {
5857
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
5902
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
5903
+ if (parsed.titleLineNumber) {
5904
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
5905
+ if (onClickItem) {
5906
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
5907
+ d3Selection3.select(this).attr("opacity", 0.7);
5908
+ }).on("mouseleave", function() {
5909
+ d3Selection3.select(this).attr("opacity", 1);
5910
+ });
5911
+ }
5912
+ }
5858
5913
  }
5859
5914
  for (const period of periods) {
5860
5915
  const x = xScale(period);
@@ -6063,7 +6118,17 @@ function renderArcDiagram(container, parsed, palette, _isDark, onClickItem, expo
6063
6118
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
6064
6119
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
6065
6120
  if (title) {
6066
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
6121
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
6122
+ if (parsed.titleLineNumber) {
6123
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
6124
+ if (onClickItem) {
6125
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
6126
+ d3Selection3.select(this).attr("opacity", 0.7);
6127
+ }).on("mouseleave", function() {
6128
+ d3Selection3.select(this).attr("opacity", 1);
6129
+ });
6130
+ }
6131
+ }
6067
6132
  }
6068
6133
  const neighbors = /* @__PURE__ */ new Map();
6069
6134
  for (const node of nodes) neighbors.set(node, /* @__PURE__ */ new Set());
@@ -6615,7 +6680,17 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
6615
6680
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
6616
6681
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
6617
6682
  if (title) {
6618
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
6683
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
6684
+ if (parsed.titleLineNumber) {
6685
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
6686
+ if (onClickItem) {
6687
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
6688
+ d3Selection3.select(this).attr("opacity", 0.7);
6689
+ }).on("mouseleave", function() {
6690
+ d3Selection3.select(this).attr("opacity", 1);
6691
+ });
6692
+ }
6693
+ }
6619
6694
  }
6620
6695
  renderEras(
6621
6696
  g,
@@ -6709,7 +6784,17 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
6709
6784
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
6710
6785
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
6711
6786
  if (title) {
6712
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
6787
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
6788
+ if (parsed.titleLineNumber) {
6789
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
6790
+ if (onClickItem) {
6791
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
6792
+ d3Selection3.select(this).attr("opacity", 0.7);
6793
+ }).on("mouseleave", function() {
6794
+ d3Selection3.select(this).attr("opacity", 1);
6795
+ });
6796
+ }
6797
+ }
6713
6798
  }
6714
6799
  renderEras(
6715
6800
  g,
@@ -6832,7 +6917,17 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
6832
6917
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
6833
6918
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
6834
6919
  if (title) {
6835
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
6920
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
6921
+ if (parsed.titleLineNumber) {
6922
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
6923
+ if (onClickItem) {
6924
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
6925
+ d3Selection3.select(this).attr("opacity", 0.7);
6926
+ }).on("mouseleave", function() {
6927
+ d3Selection3.select(this).attr("opacity", 1);
6928
+ });
6929
+ }
6930
+ }
6836
6931
  }
6837
6932
  renderEras(
6838
6933
  g,
@@ -6977,7 +7072,17 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
6977
7072
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
6978
7073
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
6979
7074
  if (title) {
6980
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
7075
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
7076
+ if (parsed.titleLineNumber) {
7077
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
7078
+ if (onClickItem) {
7079
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
7080
+ d3Selection3.select(this).attr("opacity", 0.7);
7081
+ }).on("mouseleave", function() {
7082
+ d3Selection3.select(this).attr("opacity", 1);
7083
+ });
7084
+ }
7085
+ }
6981
7086
  }
6982
7087
  renderEras(
6983
7088
  g,
@@ -7128,7 +7233,17 @@ function renderWordCloud(container, parsed, palette, _isDark, onClickItem, expor
7128
7233
  const rotateFn = getRotateFn(cloudOptions.rotate);
7129
7234
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
7130
7235
  if (title) {
7131
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
7236
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
7237
+ if (parsed.titleLineNumber) {
7238
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
7239
+ if (onClickItem) {
7240
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
7241
+ d3Selection3.select(this).attr("opacity", 0.7);
7242
+ }).on("mouseleave", function() {
7243
+ d3Selection3.select(this).attr("opacity", 1);
7244
+ });
7245
+ }
7246
+ }
7132
7247
  }
7133
7248
  const g = svg.append("g").attr(
7134
7249
  "transform",
@@ -7178,7 +7293,10 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
7178
7293
  const rotateFn = getRotateFn(cloudOptions.rotate);
7179
7294
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
7180
7295
  if (title) {
7181
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
7296
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
7297
+ if (parsed.titleLineNumber) {
7298
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
7299
+ }
7182
7300
  }
7183
7301
  const g = svg.append("g").attr(
7184
7302
  "transform",
@@ -7388,7 +7506,17 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
7388
7506
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
7389
7507
  const tooltip = createTooltip(container, palette, isDark);
7390
7508
  if (title) {
7391
- svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
7509
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
7510
+ if (parsed.titleLineNumber) {
7511
+ titleEl.attr("data-line-number", parsed.titleLineNumber);
7512
+ if (onClickItem) {
7513
+ titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
7514
+ d3Selection3.select(this).attr("opacity", 0.7);
7515
+ }).on("mouseleave", function() {
7516
+ d3Selection3.select(this).attr("opacity", 1);
7517
+ });
7518
+ }
7519
+ }
7392
7520
  }
7393
7521
  const defs = svg.append("defs");
7394
7522
  const pad = 20;
@@ -7566,10 +7694,13 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
7566
7694
  const svg = d3Selection3.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
7567
7695
  const tooltip = createTooltip(container, palette, isDark);
7568
7696
  if (title) {
7569
- const titleText = svg.append("text").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style(
7697
+ const titleText = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style(
7570
7698
  "cursor",
7571
7699
  onClickItem && quadrantTitleLineNumber ? "pointer" : "default"
7572
7700
  ).text(title);
7701
+ if (quadrantTitleLineNumber) {
7702
+ titleText.attr("data-line-number", quadrantTitleLineNumber);
7703
+ }
7573
7704
  if (onClickItem && quadrantTitleLineNumber) {
7574
7705
  titleText.on("click", () => onClickItem(quadrantTitleLineNumber)).on("mouseenter", function() {
7575
7706
  d3Selection3.select(this).attr("opacity", 0.7);