markdown-design-doc-viewer-embed 1.5.0 → 1.5.2

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/README.ja.md CHANGED
@@ -78,6 +78,7 @@ viewer.destroy();
78
78
  | `tableTreeHighlight` | `true` | 木構造で表示した表の行の親子をハイライトします。 |
79
79
  | `frontMatter` | `true` | front matter を(設計書のヘッダ、または表として)表示します。 |
80
80
  | `headingNumbers` | `true` | 紐付いた見出しに `autonumber` の番号を表示します。 |
81
+ | `messageWrapWidth` | `30` | シーケンス図の矢印のラベルをこの文字数(全角は 2 文字と数える)で改行します。`0` にすると改行しません。 |
81
82
  | `onOpenLink` | `openLinkInNewTab` | `(href) => void`: 設計書のリンク(ビューアがスクロールする `#見出し` 以外)を開きます。既定では http(s) と mailto のリンクを新しいタブで開き、ほかは何もしません。 |
82
83
  | `onRevealLine` | | `(line) => void`: ビューアでダブルクリックした Markdown の行(0 始まり)で呼ばれます(エディタでその行を表示するなど)。ないときはダブルクリックしても何もしません。 |
83
84
 
package/README.md CHANGED
@@ -78,6 +78,7 @@ viewer.destroy();
78
78
  | `tableTreeHighlight` | `true` | Highlights the parent and children of a row of a table shown as a tree. |
79
79
  | `frontMatter` | `true` | Shows the front matter (as the header of a design document, or as a table). |
80
80
  | `headingNumbers` | `true` | Shows the `autonumber` numbers on the linked headings. |
81
+ | `messageWrapWidth` | `30` | Breaks the labels of the arrows of the sequence diagrams into lines at this many characters (a full-width one counts as 2). `0` does not break them. |
81
82
  | `onOpenLink` | `openLinkInNewTab` | `(href) => void`: opens a link of the document (other than `#heading`, which the viewer scrolls to). By default, http(s) and mailto links open in a new tab, and the others do nothing. |
82
83
  | `onRevealLine` | | `(line) => void`: called with the line (0-based) of the Markdown double-clicked in the viewer, e.g. to show it in an editor. Without it, a double-click does nothing. |
83
84
 
package/index.js CHANGED
@@ -14447,6 +14447,8 @@ var bundle_l10n_ja_default = {
14447
14447
  "neo: rounder shapes, with shadows on flowchart nodes. classic: flat, without shadows.": "neo: \u89D2\u304C\u4E38\u304F\u3001\u30D5\u30ED\u30FC\u30C1\u30E3\u30FC\u30C8\u306E\u30CE\u30FC\u30C9\u306B\u5F71\u304C\u4ED8\u304D\u307E\u3059\u3002classic: \u5E73\u5766\u3067\u3001\u5F71\u306F\u4ED8\u304D\u307E\u305B\u3093\u3002",
14448
14448
  "Side-by-Side Width (px)": "\u6A2A\u4E26\u3073\u306B\u3059\u308B\u5E45 (px)",
14449
14449
  "Shows the diagrams beside their step descriptions when the preview is at least this wide.": "\u30D7\u30EC\u30D3\u30E5\u30FC\u306E\u5E45\u304C\u3053\u308C\u4EE5\u4E0A\u306E\u3068\u304D\u3001\u56F3\u3068\u51E6\u7406\u6982\u8981\u3092\u6A2A\u306B\u4E26\u3079\u307E\u3059\u3002",
14450
+ "Arrow Label Width": "\u77E2\u5370\u306E\u30E9\u30D9\u30EB\u306E\u5E45",
14451
+ "Breaks the labels of the arrows of the sequence diagrams into lines at this many characters (a full-width one counts as 2). 0: not broken.": "\u30B7\u30FC\u30B1\u30F3\u30B9\u56F3\u306E\u77E2\u5370\u306E\u30E9\u30D9\u30EB\u3092\u3053\u306E\u6587\u5B57\u6570\uFF08\u5168\u89D2\u306F 2 \u6587\u5B57\u3068\u6570\u3048\u308B\uFF09\u3067\u6539\u884C\u3057\u307E\u3059\u30020 \u306B\u3059\u308B\u3068\u6539\u884C\u3057\u307E\u305B\u3093\u3002",
14450
14452
  "Table of Contents": "\u76EE\u6B21",
14451
14453
  "Shown when hovering the right edge of the preview.": "\u30D7\u30EC\u30D3\u30E5\u30FC\u306E\u53F3\u7AEF\u306B\u30DE\u30A6\u30B9\u3092\u4E57\u305B\u308B\u3068\u958B\u304D\u307E\u3059\u3002",
14452
14454
  "Heading Numbers": "\u898B\u51FA\u3057\u306E\u756A\u53F7",
@@ -14571,9 +14573,10 @@ var bundle_l10n_ja_default = {
14571
14573
  "@goto is ignored because the next line is not a note.": "\u6B21\u306E\u884C\u304C\u30CE\u30FC\u30C8\u3067\u306F\u306A\u3044\u305F\u3081\u3001@goto \u306F\u7121\u8996\u3055\u308C\u307E\u3059\u3002",
14572
14574
  "@goto is ignored because @anchor makes the note a label. A note is a label or a jump, not both.": "@anchor \u3067\u30CE\u30FC\u30C8\u3092\u30E9\u30D9\u30EB\u306B\u3057\u3066\u3044\u308B\u305F\u3081\u3001@goto \u306F\u7121\u8996\u3055\u308C\u307E\u3059\u30021 \u3064\u306E\u30CE\u30FC\u30C8\u306F\u30E9\u30D9\u30EB\u304B\u30B8\u30E3\u30F3\u30D7\u306E\u3069\u3061\u3089\u304B\u3067\u3059\u3002",
14573
14575
  'Label "{0}" is already defined in the sequence diagram.': "\u30E9\u30D9\u30EB\u300C{0}\u300D\u306F\u30B7\u30FC\u30B1\u30F3\u30B9\u56F3\u3067\u3059\u3067\u306B\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u307E\u3059\u3002",
14574
- '@goto target label "{0}" was not found in the sequence diagram.': "@goto \u3067\u6307\u5B9A\u3057\u305F\u30E9\u30D9\u30EB\u300C{0}\u300D\u304C\u30B7\u30FC\u30B1\u30F3\u30B9\u56F3\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002",
14576
+ '@goto target label "{0}" was not found in the sequence diagrams of the document.': "@goto \u3067\u6307\u5B9A\u3057\u305F\u30E9\u30D9\u30EB\u300C{0}\u300D\u304C\u6587\u66F8\u306E\u30B7\u30FC\u30B1\u30F3\u30B9\u56F3\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002",
14577
+ '@goto target label "{0}" is defined in more than one other sequence diagram. Name the label to jump to uniquely with @anchor.': "@goto \u3067\u6307\u5B9A\u3057\u305F\u30E9\u30D9\u30EB\u300C{0}\u300D\u306F\u307B\u304B\u306E\u8907\u6570\u306E\u30B7\u30FC\u30B1\u30F3\u30B9\u56F3\u3067\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30B8\u30E3\u30F3\u30D7\u5148\u306E\u30E9\u30D9\u30EB\u306B @anchor \u3067\u4E00\u610F\u306A\u540D\u524D\u3092\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\u3002",
14575
14578
  "Make the next note (or section of a block) a label that notes can jump to.": "\u76F4\u5F8C\u306E\u30CE\u30FC\u30C8\uFF08\u307E\u305F\u306F\u30D6\u30ED\u30C3\u30AF\u306E\u5206\u5C90\uFF09\u3092\u3001\u30CE\u30FC\u30C8\u304B\u3089\u79FB\u52D5\u3067\u304D\u308B\u30E9\u30D9\u30EB\u306B\u3057\u307E\u3059\u3002",
14576
- "Make the next note jump to a label.": "\u76F4\u5F8C\u306E\u30CE\u30FC\u30C8\u3092\u3001\u30E9\u30D9\u30EB\u3078\u79FB\u52D5\u3059\u308B\u30CE\u30FC\u30C8\u306B\u3057\u307E\u3059\u3002",
14579
+ "Make the next note jump to a label of this or another sequence diagram of the document.": "\u76F4\u5F8C\u306E\u30CE\u30FC\u30C8\u3092\u3001\u3053\u306E\u56F3\u307E\u305F\u306F\u6587\u66F8\u306E\u307B\u304B\u306E\u30B7\u30FC\u30B1\u30F3\u30B9\u56F3\u306E\u30E9\u30D9\u30EB\u3078\u79FB\u52D5\u3059\u308B\u30CE\u30FC\u30C8\u306B\u3057\u307E\u3059\u3002",
14577
14580
  "Go to {0}": "{0} \u3078\u79FB\u52D5",
14578
14581
  "Back to the note you jumped from": "\u79FB\u52D5\u5143\u306E\u30CE\u30FC\u30C8\u306B\u623B\u308B"
14579
14582
  };
@@ -20230,20 +20233,16 @@ function noteJumpWording(t) {
20230
20233
  strayGoto: t("@goto is ignored because the next line is not a note."),
20231
20234
  gotoOnLabel: t("@goto is ignored because @anchor makes the note a label. A note is a label or a jump, not both."),
20232
20235
  duplicateAnchor: (name) => t('Label "{0}" is already defined in the sequence diagram.', name),
20233
- gotoNotFound: (name) => t('@goto target label "{0}" was not found in the sequence diagram.', name),
20236
+ gotoNotFound: (name) => t('@goto target label "{0}" was not found in the sequence diagrams of the document.', name),
20237
+ gotoAmbiguous: (name) => t('@goto target label "{0}" is defined in more than one other sequence diagram. Name the label to jump to uniquely with @anchor.', name),
20234
20238
  anchorDoc: t("Make the next note (or section of a block) a label that notes can jump to."),
20235
- gotoDoc: t("Make the next note jump to a label."),
20239
+ gotoDoc: t("Make the next note jump to a label of this or another sequence diagram of the document."),
20236
20240
  // `{0}` is filled in by the webview.
20237
20241
  gotoTitle: t("Go to {0}"),
20238
20242
  backTitle: t("Back to the note you jumped from")
20239
20243
  };
20240
20244
  }
20241
20245
 
20242
- // src/markdown/htmlTags.ts
20243
- var RAW_TEXT = "script|style|textarea|title";
20244
- var ATTR_RE = /([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
20245
- var decodeAttribute = (md2, value) => md2.utils.unescapeAll(value.replace(/\\/g, "\\\\"));
20246
-
20247
20246
  // src/diagrams/sequence.ts
20248
20247
  var ARROWS = [
20249
20248
  "<<-->>",
@@ -20520,6 +20519,104 @@ function stripStepNumber(heading2) {
20520
20519
  return void 0;
20521
20520
  }
20522
20521
 
20522
+ // src/diagrams/sequenceWrap.ts
20523
+ var DEFAULT_MESSAGE_WRAP_WIDTH = 30;
20524
+ var WIDE_RE = /[ᄀ-ᅟ⺀-〾ぁ-㏿㐀-䶿一-鿿ꀀ-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩\u{1F300}-\u{1F64F}\u{1F680}-\u{1F6FF}\u{1F900}-\u{1FAFF}\u{20000}-\u{3FFFD}]/u;
20525
+ var NO_START = new Set(Array.from("\u3001\u3002\uFF0C\uFF0E\u30FB\uFF1A\uFF1B\uFF1F\uFF01\u309D\u309E\u30FC\u30A1\u30A3\u30A5\u30A7\u30A9\u30C3\u30E3\u30E5\u30E7\u30EE\u30F5\u30F6\u3041\u3043\u3045\u3047\u3049\u3063\u3083\u3085\u3087\u308E\u3095\u3096\uFF09\u3015\uFF3D\uFF5D\u3009\u300B\u300D\u300F\u3011\u3019\u3017\u301F\u2019\u201D\uFF60\xBB,.:;!?)]}"));
20526
+ var NO_END = new Set(Array.from("\uFF08\u3014\uFF3B\uFF5B\u3008\u300A\u300C\u300E\u3010\u3018\u3016\u301D\u2018\u201C\uFF5F\xAB([{"));
20527
+ var KEEP_RE = /<br\s*\/?>|#|;|%%|\$\$|^:?(?:no)?wrap:/i;
20528
+ var TAG_RE = /<\/?[a-z][a-z0-9]*(?:\s[^>]*)?\/?>/;
20529
+ var keepsLabel = (text3) => KEEP_RE.test(text3) || TAG_RE.test(text3);
20530
+ var charWidth = (c) => WIDE_RE.test(c) ? 2 : 1;
20531
+ var textWidth = (text3) => Array.from(text3).reduce((sum, c) => sum + charWidth(c), 0);
20532
+ function canBreakBefore(chars, i) {
20533
+ const before = chars[i - 1];
20534
+ const after = chars[i];
20535
+ if (before === " " || after === " ") {
20536
+ return true;
20537
+ }
20538
+ if (NO_START.has(after) || NO_END.has(before)) {
20539
+ return false;
20540
+ }
20541
+ if (before === "/" && after !== "/") {
20542
+ return true;
20543
+ }
20544
+ return WIDE_RE.test(before) || WIDE_RE.test(after);
20545
+ }
20546
+ function fillLines(chars, limit) {
20547
+ const lines = [];
20548
+ let start = 0;
20549
+ while (start < chars.length) {
20550
+ while (chars[start] === " ") {
20551
+ start++;
20552
+ }
20553
+ if (start >= chars.length) {
20554
+ break;
20555
+ }
20556
+ let width = 0;
20557
+ let end = start;
20558
+ let lastBreak = -1;
20559
+ while (end < chars.length) {
20560
+ if (end > start && canBreakBefore(chars, end)) {
20561
+ lastBreak = end;
20562
+ }
20563
+ const w = charWidth(chars[end]);
20564
+ if (end > start && width + w > limit) {
20565
+ break;
20566
+ }
20567
+ width += w;
20568
+ end++;
20569
+ }
20570
+ const cut = end < chars.length && lastBreak > start ? lastBreak : end;
20571
+ lines.push(chars.slice(start, cut).join("").trimEnd());
20572
+ start = cut;
20573
+ }
20574
+ return lines;
20575
+ }
20576
+ function wrapLabel(text3, maxWidth) {
20577
+ const normalized = text3.replace(/\s+/g, " ").trim();
20578
+ const total = textWidth(normalized);
20579
+ if (maxWidth <= 0 || total <= maxWidth) {
20580
+ return [normalized];
20581
+ }
20582
+ const chars = Array.from(normalized);
20583
+ const count = fillLines(chars, maxWidth).length;
20584
+ for (let limit = Math.ceil(total / count); limit < maxWidth; limit++) {
20585
+ const lines = fillLines(chars, limit);
20586
+ if (lines.length <= count) {
20587
+ return lines;
20588
+ }
20589
+ }
20590
+ return fillLines(chars, maxWidth);
20591
+ }
20592
+ function wrapSequenceMessages(source, maxWidth) {
20593
+ if (!(maxWidth > 0) || !isSequenceDiagram(source)) {
20594
+ return source;
20595
+ }
20596
+ const { messages } = parseSequence(source, 0);
20597
+ const lines = source.split("\n");
20598
+ let changed = false;
20599
+ for (const { line } of messages) {
20600
+ const raw = lines[line];
20601
+ const colon = raw.indexOf(":");
20602
+ const label = raw.slice(colon + 1);
20603
+ const text3 = label.trim();
20604
+ if (keepsLabel(text3) || textWidth(text3) <= maxWidth) {
20605
+ continue;
20606
+ }
20607
+ const lead = /^\s*/.exec(label)[0];
20608
+ const trail = /\s*$/.exec(label)[0];
20609
+ lines[line] = `${raw.slice(0, colon + 1)}${lead}${wrapLabel(text3, maxWidth).join("<br>")}${trail}`;
20610
+ changed = true;
20611
+ }
20612
+ return changed ? lines.join("\n") : source;
20613
+ }
20614
+
20615
+ // src/markdown/htmlTags.ts
20616
+ var RAW_TEXT = "script|style|textarea|title";
20617
+ var ATTR_RE = /([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
20618
+ var decodeAttribute = (md2, value) => md2.utils.unescapeAll(value.replace(/\\/g, "\\\\"));
20619
+
20523
20620
  // src/diagrams/diagramNodes.ts
20524
20621
  function readNodes(lines, start, firstLine, rules, reader) {
20525
20622
  const excluded = reader.excluded ?? /* @__PURE__ */ new Set();
@@ -21618,13 +21715,35 @@ function noteJumps(sequence, marked, translate, warnings) {
21618
21715
  byName.set(anchor.name, { ...anchor });
21619
21716
  }
21620
21717
  }
21621
- for (const note of notes) {
21622
- if (note.goto !== void 0 && !byName.has(note.goto)) {
21623
- warnings.push({ line: note.gotoLine ?? note.line, message: wording.gotoNotFound(note.goto) });
21718
+ return { notes, anchors: [...byName.values()] };
21719
+ }
21720
+ function jumpsBetweenDiagrams(diagrams, translate, warnings) {
21721
+ const wording = noteJumpWording(translate);
21722
+ const byName = /* @__PURE__ */ new Map();
21723
+ for (const diagram of diagrams) {
21724
+ for (const anchor of diagram.anchors ?? []) {
21725
+ const found = byName.get(anchor.name) ?? [];
21726
+ found.push({ diagram, anchor });
21727
+ byName.set(anchor.name, found);
21728
+ }
21729
+ }
21730
+ for (const diagram of diagrams) {
21731
+ const own = new Set(diagram.anchors?.map((a) => a.name));
21732
+ for (const note of diagram.notes ?? []) {
21733
+ if (note.goto === void 0 || own.has(note.goto)) {
21734
+ continue;
21735
+ }
21736
+ const found = byName.get(note.goto) ?? [];
21737
+ if (found.length === 1) {
21738
+ note.gotoDiagram = found[0].diagram.id;
21739
+ found[0].anchor.jumpedFrom = true;
21740
+ continue;
21741
+ }
21742
+ const line = note.gotoLine ?? note.line;
21743
+ warnings.push({ line, message: found.length === 0 ? wording.gotoNotFound(note.goto) : wording.gotoAmbiguous(note.goto) });
21624
21744
  delete note.goto;
21625
21745
  }
21626
21746
  }
21627
- return { notes, anchors: [...byName.values()] };
21628
21747
  }
21629
21748
  function wireframeDiagram(token, index, id, translate, warnings) {
21630
21749
  const { src, options, file, parts } = wireframeOf(token);
@@ -21663,6 +21782,7 @@ function linkDiagrams(tokens, translate = formatMessage) {
21663
21782
  diagrams.push(wireframeDiagram(token, index, diagrams.length, translate, warnings));
21664
21783
  }
21665
21784
  });
21785
+ jumpsBetweenDiagrams(diagrams, translate, warnings);
21666
21786
  const pairedFences = new Set(diagrams.filter((d) => d.paired).map((d) => d.fenceIndex));
21667
21787
  for (const token of tokens) {
21668
21788
  if (token.level === 0 && token.type === "html_block" && LEGACY_END_MARKER_RE.test(token.content)) {
@@ -22069,16 +22189,17 @@ function diagramAttributes(token, env) {
22069
22189
  }))
22070
22190
  };
22071
22191
  const notes = diagram.notes ?? [];
22072
- if (notes.some((n) => n.anchor !== void 0 || n.goto !== void 0)) {
22192
+ if (notes.some((n) => n.anchor !== void 0 || n.goto !== void 0) || diagram.anchors?.some((a) => a.jumpedFrom)) {
22073
22193
  const wording = noteJumpWording(env?.t ?? formatMessage);
22074
- meta.notes = notes.map(({ index, line: line2, text: text3, anchor, goto }) => ({ index, line: line2, text: text3, anchor, goto }));
22075
- meta.anchors = diagram.anchors?.map(({ name, title, occurrence, firstTarget }) => ({ name, title, occurrence, firstTarget }));
22194
+ meta.notes = notes.map(({ index, line: line2, text: text3, anchor, goto, gotoDiagram }) => ({ index, line: line2, text: text3, anchor, goto, gotoDiagram }));
22195
+ meta.anchors = diagram.anchors?.map(({ name, title, occurrence, firstTarget, jumpedFrom }) => ({ name, title, occurrence, firstTarget, jumpedFrom }));
22076
22196
  meta.jumpTitles = { goto: wording.gotoTitle, back: wording.backTitle };
22077
22197
  }
22078
22198
  attrs += ` data-seqnotes-meta="${escapeHtml2(JSON.stringify(meta))}"`;
22079
22199
  }
22080
22200
  return attrs;
22081
22201
  }
22202
+ var mermaidSource = (content, env) => wrapSequenceMessages(content, env?.messageWrapWidth ?? DEFAULT_MESSAGE_WRAP_WIDTH);
22082
22203
  function mermaidFence(md2) {
22083
22204
  const defaultFence = md2.renderer.rules.fence;
22084
22205
  md2.renderer.rules.fence = (tokens, idx, options, env, self) => {
@@ -22086,7 +22207,7 @@ function mermaidFence(md2) {
22086
22207
  if (!isMermaidFence(token)) {
22087
22208
  return defaultFence(tokens, idx, options, env, self);
22088
22209
  }
22089
- return `<div class="seqnotes-mermaid"${diagramAttributes(token, env)}><pre class="seqnotes-mermaid-src">${escapeHtml2(token.content)}</pre></div>
22210
+ return `<div class="seqnotes-mermaid"${diagramAttributes(token, env)}><pre class="seqnotes-mermaid-src">${escapeHtml2(mermaidSource(token.content, env))}</pre></div>
22090
22211
  `;
22091
22212
  };
22092
22213
  }
@@ -25362,6 +25483,96 @@ function restorePlain(root, indexes) {
25362
25483
  });
25363
25484
  }
25364
25485
 
25486
+ // webview/splitter.ts
25487
+ var MIN_SPLIT = 20;
25488
+ var MAX_SPLIT = 80;
25489
+ function applySplit(el, percent) {
25490
+ if (percent === void 0 || !Number.isFinite(percent)) {
25491
+ el.style.removeProperty("--seqnotes-split");
25492
+ return void 0;
25493
+ }
25494
+ percent = Math.min(MAX_SPLIT, Math.max(MIN_SPLIT, percent));
25495
+ el.style.setProperty("--seqnotes-split", `${percent}%`);
25496
+ return percent;
25497
+ }
25498
+ var KEY_STEP = 5;
25499
+ function addSplitter(pair, title, onSplit, signal) {
25500
+ const splitter = document.createElement("div");
25501
+ splitter.className = "seqnotes-splitter";
25502
+ splitter.title = title;
25503
+ splitter.tabIndex = 0;
25504
+ splitter.setAttribute("role", "separator");
25505
+ splitter.setAttribute("aria-orientation", "vertical");
25506
+ splitter.setAttribute("aria-valuemin", String(MIN_SPLIT));
25507
+ splitter.setAttribute("aria-valuemax", String(MAX_SPLIT));
25508
+ const column = pair.querySelector(".seqnotes-seq-col");
25509
+ column?.after(splitter);
25510
+ const current = () => {
25511
+ const width = pair.getBoundingClientRect().width;
25512
+ return width > 0 && column ? column.getBoundingClientRect().width / width * 100 : 0;
25513
+ };
25514
+ const showValue = () => splitter.setAttribute("aria-valuenow", String(Math.round(current())));
25515
+ const split = (percent) => {
25516
+ onSplit(percent);
25517
+ showValue();
25518
+ };
25519
+ splitter.addEventListener(
25520
+ "pointerdown",
25521
+ (e) => {
25522
+ e.preventDefault();
25523
+ splitter.setPointerCapture(e.pointerId);
25524
+ const move = (ev) => {
25525
+ const r = pair.getBoundingClientRect();
25526
+ split((ev.clientX - r.left) / r.width * 100);
25527
+ };
25528
+ const end = () => {
25529
+ splitter.removeEventListener("pointermove", move);
25530
+ splitter.removeEventListener("lostpointercapture", end);
25531
+ };
25532
+ splitter.addEventListener("pointermove", move, { signal });
25533
+ splitter.addEventListener("lostpointercapture", end, { signal });
25534
+ },
25535
+ { signal }
25536
+ );
25537
+ splitter.addEventListener(
25538
+ "dblclick",
25539
+ (e) => {
25540
+ e.stopPropagation();
25541
+ split(void 0);
25542
+ },
25543
+ { signal }
25544
+ );
25545
+ splitter.addEventListener("focus", showValue, { signal });
25546
+ splitter.addEventListener(
25547
+ "keydown",
25548
+ (e) => {
25549
+ let percent;
25550
+ switch (e.key) {
25551
+ case "ArrowLeft":
25552
+ percent = current() - KEY_STEP;
25553
+ break;
25554
+ case "ArrowRight":
25555
+ percent = current() + KEY_STEP;
25556
+ break;
25557
+ case "Home":
25558
+ percent = MIN_SPLIT;
25559
+ break;
25560
+ case "End":
25561
+ percent = MAX_SPLIT;
25562
+ break;
25563
+ case "Enter":
25564
+ percent = void 0;
25565
+ break;
25566
+ default:
25567
+ return;
25568
+ }
25569
+ e.preventDefault();
25570
+ split(percent);
25571
+ },
25572
+ { signal }
25573
+ );
25574
+ }
25575
+
25365
25576
  // webview/toc.ts
25366
25577
  var TOC_CURRENT = "seqnotes-toc-current";
25367
25578
  var TOC_CURRENT_RATIO = 0.2;
@@ -25506,7 +25717,7 @@ var HOVER = "seqnotes-jump-hover";
25506
25717
  var FLASH = "seqnotes-flash";
25507
25718
  var JUMP_ELEMENTS = "svg [data-seqnotes-goto], svg [data-seqnotes-anchor]";
25508
25719
  var FLASH_MS = 1200;
25509
- function textWidth(text3, fontSize2) {
25720
+ function textWidth2(text3, fontSize2) {
25510
25721
  let em = 0;
25511
25722
  for (const c of text3) {
25512
25723
  em += /[ᄀ-ᅟ①-⓿⺀-꓏가-힣豈-﫿︰-﹏＀-⦆¢-₩]/.test(c) ? 1 : 0.6;
@@ -25530,7 +25741,8 @@ function makeBadge(group) {
25530
25741
  if (!(height > 0)) {
25531
25742
  return;
25532
25743
  }
25533
- if (texts.length === 1) {
25744
+ const larger = (t) => textWidth2(t.textContent ?? "", fontSize(t) * BADGE_FONT_SCALE) + height * 0.5;
25745
+ if (texts.length === 1 && larger(texts[0]) <= width) {
25534
25746
  const [text3] = texts;
25535
25747
  text3.style.fontSize = `${fontSize(text3) * BADGE_FONT_SCALE}px`;
25536
25748
  text3.setAttribute("y", String(num(rect, "y") + height / 2));
@@ -25542,7 +25754,7 @@ function makeBadge(group) {
25542
25754
  tspan.removeAttribute("y");
25543
25755
  }
25544
25756
  }
25545
- const textW = Math.max(...texts.map((t) => textWidth(t.textContent ?? "", fontSize(t))));
25757
+ const textW = Math.max(...texts.map((t) => textWidth2(t.textContent ?? "", fontSize(t))));
25546
25758
  const badge = Math.max(height, textW + height * 0.5);
25547
25759
  if (!(badge < width)) {
25548
25760
  return;
@@ -25616,6 +25828,7 @@ function annotateNotes(svg2, meta) {
25616
25828
  if (!notes) {
25617
25829
  return;
25618
25830
  }
25831
+ svg2.setAttribute("data-seqnotes-diagram", String(meta.id));
25619
25832
  const groups = Array.from(svg2.querySelectorAll('g[data-et="note"]'));
25620
25833
  let assigned;
25621
25834
  if (groups.length === notes.length) {
@@ -25644,6 +25857,9 @@ function annotateNotes(svg2, meta) {
25644
25857
  } else if (note.goto !== void 0) {
25645
25858
  group.classList.add("seqnotes-goto");
25646
25859
  group.setAttribute("data-seqnotes-goto", note.goto);
25860
+ if (note.gotoDiagram !== void 0) {
25861
+ group.setAttribute("data-seqnotes-goto-diagram", String(note.gotoDiagram));
25862
+ }
25647
25863
  const title = document.createElementNS(SVG_NS, "title");
25648
25864
  title.textContent = (meta.jumpTitles?.goto ?? "{0}").replace("{0}", note.goto);
25649
25865
  group.prepend(title);
@@ -25669,13 +25885,14 @@ function annotateNotes(svg2, meta) {
25669
25885
  const boxes = blockBoxes(svg2);
25670
25886
  for (const { els, name, fromLabel } of labels) {
25671
25887
  const el = els[0];
25672
- const firstTarget = meta.anchors?.find((a) => a.name === name)?.firstTarget;
25888
+ const anchor = meta.anchors?.find((a) => a.name === name);
25889
+ const firstTarget = anchor?.firstTarget;
25673
25890
  for (const e of els) {
25674
25891
  if (firstTarget !== void 0) {
25675
25892
  e.setAttribute("data-seqnotes-first-target", firstTarget);
25676
25893
  }
25677
25894
  }
25678
- if (notes.some((n) => n.goto === name)) {
25895
+ if (notes.some((n) => n.goto === name) || anchor?.jumpedFrom) {
25679
25896
  focusable(el, name);
25680
25897
  }
25681
25898
  const r = sectionRect(boxes, el, fromLabel);
@@ -25701,6 +25918,17 @@ function setupNoteJumps(root, { scroll, pin, signal }) {
25701
25918
  let hovered = [];
25702
25919
  const svgOf = (el) => el.closest("svg");
25703
25920
  const byAttr = (svg2, attr, name) => Array.from(svg2.querySelectorAll(`[${attr}="${CSS.escape(name)}"]`));
25921
+ const targetSvg = (note) => {
25922
+ const other = note.getAttribute("data-seqnotes-goto-diagram");
25923
+ return other === null ? svgOf(note) : root.querySelector(`svg[data-seqnotes-diagram="${CSS.escape(other)}"]`);
25924
+ };
25925
+ const notesTo = (svg2, name) => {
25926
+ const id = svg2.getAttribute("data-seqnotes-diagram");
25927
+ return byAttr(root, "data-seqnotes-goto", name).filter((n) => {
25928
+ const other = n.getAttribute("data-seqnotes-goto-diagram");
25929
+ return other === null ? svgOf(n) === svg2 : other === id;
25930
+ });
25931
+ };
25704
25932
  function clearHover() {
25705
25933
  hovered.forEach((el) => el.classList.remove(HOVER));
25706
25934
  hovered = [];
@@ -25761,22 +25989,26 @@ function setupNoteJumps(root, { scroll, pin, signal }) {
25761
25989
  }
25762
25990
  }
25763
25991
  function jump(from, keyboard) {
25764
- const svg2 = svgOf(from);
25992
+ const svg2 = targetSvg(from);
25765
25993
  const name = from.getAttribute("data-seqnotes-goto");
25766
25994
  const anchor = svg2 && name !== null ? byAttr(svg2, "data-seqnotes-anchor", name)[0] : void 0;
25767
25995
  if (!svg2 || name === null || !anchor) {
25768
25996
  return;
25769
25997
  }
25998
+ const target = anchor.getAttribute("data-seqnotes-first-target");
25999
+ const pair = anchor.closest(".seqnotes-pair");
26000
+ const sideBySide = pair !== null && isSideBySide(pair);
26001
+ if (sideBySide && svg2 !== svgOf(from)) {
26002
+ scroll.reveal(pair, "start", "auto");
26003
+ }
25770
26004
  scrollColumnTo(anchor, true, scroll);
25771
26005
  const branch = byAttr(svg2, "data-seqnotes-branch", name)[0];
25772
26006
  flash(branch ?? anchor);
25773
26007
  if (branch) {
25774
26008
  flash(anchor);
25775
26009
  }
25776
- const target = anchor.getAttribute("data-seqnotes-first-target");
25777
- const pair = anchor.closest(".seqnotes-pair");
25778
26010
  if (target !== null && pair) {
25779
- pin({ pair, target, kind: "message" }, isSideBySide(pair));
26011
+ pin({ pair, target, kind: "message" }, sideBySide);
25780
26012
  }
25781
26013
  showBack(anchor, from);
25782
26014
  if (keyboard) {
@@ -25789,7 +26021,7 @@ function setupNoteJumps(root, { scroll, pin, signal }) {
25789
26021
  if (!svg2 || name === null) {
25790
26022
  return;
25791
26023
  }
25792
- const notes = byAttr(svg2, "data-seqnotes-goto", name);
26024
+ const notes = notesTo(svg2, name);
25793
26025
  if (notes.length === 0) {
25794
26026
  return;
25795
26027
  }
@@ -25821,8 +26053,9 @@ function setupNoteJumps(root, { scroll, pin, signal }) {
25821
26053
  }
25822
26054
  const goto = el.getAttribute("data-seqnotes-goto");
25823
26055
  const name = goto ?? el.getAttribute("data-seqnotes-anchor");
25824
- const related = [...byAttr(svg2, "data-seqnotes-anchor", name), ...goto !== null ? [] : byAttr(svg2, "data-seqnotes-goto", name)];
25825
- hovered = [el, ...related, ...byAttr(svg2, "data-seqnotes-branch", name)];
26056
+ const labelSvg = goto !== null ? targetSvg(el) : svg2;
26057
+ const related = labelSvg ? [...byAttr(labelSvg, "data-seqnotes-anchor", name), ...byAttr(labelSvg, "data-seqnotes-branch", name)] : [];
26058
+ hovered = [el, ...related, ...goto !== null ? [] : notesTo(svg2, name)];
25826
26059
  hovered.forEach((r) => r.classList.add(HOVER));
25827
26060
  },
25828
26061
  { signal }
@@ -26128,46 +26361,14 @@ function createPreview(ctx) {
26128
26361
  el.classList.toggle("seqnotes-wide", previewWidth() >= splitMinWidth);
26129
26362
  }
26130
26363
  const stopResize = scroll.onResize(applyLayout);
26131
- const MIN_SPLIT = 20;
26132
- const MAX_SPLIT = 80;
26133
26364
  function setSplit(percent) {
26134
- const style = el.style;
26135
- if (percent === void 0) {
26136
- style.removeProperty("--seqnotes-split");
26137
- } else {
26138
- percent = Math.min(MAX_SPLIT, Math.max(MIN_SPLIT, percent));
26139
- style.setProperty("--seqnotes-split", `${percent}%`);
26140
- }
26365
+ const split = applySplit(el, percent);
26141
26366
  const state = ctx.getState();
26142
26367
  if (state) {
26143
- ctx.setState({ ...state, split: percent });
26368
+ ctx.setState({ ...state, split });
26144
26369
  }
26145
26370
  }
26146
26371
  setSplit(ctx.getState()?.split);
26147
- function addSplitter(pair) {
26148
- const splitter = document.createElement("div");
26149
- splitter.className = "seqnotes-splitter";
26150
- splitter.title = titles.seqnotesSplitterTitle ?? "";
26151
- pair.querySelector(".seqnotes-seq-col")?.after(splitter);
26152
- splitter.addEventListener("pointerdown", (e) => {
26153
- e.preventDefault();
26154
- splitter.setPointerCapture(e.pointerId);
26155
- const move = (ev) => {
26156
- const r = pair.getBoundingClientRect();
26157
- setSplit((ev.clientX - r.left) / r.width * 100);
26158
- };
26159
- const up = () => {
26160
- splitter.removeEventListener("pointermove", move);
26161
- splitter.removeEventListener("pointerup", up);
26162
- };
26163
- splitter.addEventListener("pointermove", move);
26164
- splitter.addEventListener("pointerup", up);
26165
- });
26166
- splitter.addEventListener("dblclick", (e) => {
26167
- e.stopPropagation();
26168
- setSplit(void 0);
26169
- });
26170
- }
26171
26372
  let previewTheme = titles.seqnotesTheme === "light" || titles.seqnotesTheme === "dark" ? titles.seqnotesTheme : "auto";
26172
26373
  function isVscodeDark() {
26173
26374
  return !el.classList.contains("vscode-light") && !el.classList.contains("vscode-high-contrast-light");
@@ -26280,8 +26481,13 @@ ${source}`;
26280
26481
  } else {
26281
26482
  const unused = [...meta.messages];
26282
26483
  assigned = groups.map((group) => {
26283
- const label = normalizeLabel(group.slice(0, -1).map((t) => t.textContent ?? "").join(" "));
26284
- const i = unused.findIndex((m) => normalizeLabel(m.text) === label);
26484
+ const lines = group.slice(0, -1).map((t) => t.textContent ?? "");
26485
+ const label = normalizeLabel(lines.join(" "));
26486
+ const compact = compactLabel(lines.join(""));
26487
+ let i = unused.findIndex((m) => normalizeLabel(m.text) === label);
26488
+ if (i < 0) {
26489
+ i = unused.findIndex((m) => compactLabel(m.text) === compact);
26490
+ }
26285
26491
  return i >= 0 ? unused.splice(i, 1)[0] : void 0;
26286
26492
  });
26287
26493
  }
@@ -26463,7 +26669,7 @@ ${source}`;
26463
26669
  root.querySelectorAll(".seqnotes-pair").forEach((pair2) => {
26464
26670
  wrapSections(pair2);
26465
26671
  if (!pair2.classList.contains("seqnotes-pair-stacked")) {
26466
- addSplitter(pair2);
26672
+ addSplitter(pair2, titles.seqnotesSplitterTitle ?? "", setSplit, signal);
26467
26673
  }
26468
26674
  });
26469
26675
  setUpWarnings();
@@ -27218,7 +27424,7 @@ function fetchFrom(baseUrl) {
27218
27424
  }
27219
27425
  };
27220
27426
  }
27221
- var CONTENT_OPTIONS = ["markdown", "baseUrl", "readFile", "resolveResource", "frontMatter", "headingNumbers"];
27427
+ var CONTENT_OPTIONS = ["markdown", "baseUrl", "readFile", "resolveResource", "frontMatter", "headingNumbers", "messageWrapWidth"];
27222
27428
  var VIEW_OPTIONS = ["documentId", "splitMinWidth", "toc", "diagramLook", "limitContentWidth", "stickyTableHeader", "tableTreeHighlight"];
27223
27429
  function createViewer(container, options) {
27224
27430
  let current = { ...options };
@@ -27306,7 +27512,7 @@ function createViewer(container, options) {
27306
27512
  return;
27307
27513
  }
27308
27514
  pending = false;
27309
- html2 = renderDocument(md, markdown, { t, frontMatter: current.frontMatter, headingNumbers: current.headingNumbers, wireframes: wireframes2, resolveResource });
27515
+ html2 = renderDocument(md, markdown, { t, frontMatter: current.frontMatter, headingNumbers: current.headingNumbers, messageWrapWidth: current.messageWrapWidth, wireframes: wireframes2, resolveResource });
27310
27516
  await show(html2);
27311
27517
  }
27312
27518
  rendering = render();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdown-design-doc-viewer-embed",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "The viewer of Markdown Design Doc Viewer to embed in a web app (React or not): design documents in Markdown with their mermaid sequence diagrams, flowcharts, ER and state diagrams and wireframes linked to the steps after them.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/react.js CHANGED
@@ -26,14 +26,14 @@ var DesignDocViewer = forwardRef(function DesignDocViewer2({ className, style, .
26
26
  viewer.current = void 0;
27
27
  };
28
28
  }, [options.lang]);
29
- const { markdown, documentId, baseUrl, readFile, resolveResource, theme, diagramLook, splitMinWidth, toc, limitContentWidth, stickyTableHeader, tableTreeHighlight, frontMatter, headingNumbers } = options;
29
+ const { markdown, documentId, baseUrl, readFile, resolveResource, theme, diagramLook, splitMinWidth, toc, limitContentWidth, stickyTableHeader, tableTreeHighlight, frontMatter, headingNumbers, messageWrapWidth } = options;
30
30
  useEffect(() => {
31
31
  if (created.current) {
32
32
  created.current = false;
33
33
  return;
34
34
  }
35
35
  void viewer.current?.update(viewerOptions());
36
- }, [options.lang, markdown, documentId, baseUrl, readFile, resolveResource, theme, diagramLook, splitMinWidth, toc, limitContentWidth, stickyTableHeader, tableTreeHighlight, frontMatter, headingNumbers, revealing]);
36
+ }, [options.lang, markdown, documentId, baseUrl, readFile, resolveResource, theme, diagramLook, splitMinWidth, toc, limitContentWidth, stickyTableHeader, tableTreeHighlight, frontMatter, headingNumbers, messageWrapWidth, revealing]);
37
37
  useImperativeHandle(ref, () => ({
38
38
  scrollToLine: (line) => viewer.current?.scrollToLine(line),
39
39
  markLine: (line) => viewer.current?.markLine(line)
@@ -40,6 +40,11 @@ export interface ViewerOptions {
40
40
  frontMatter?: boolean;
41
41
  /** Shows the `autonumber` numbers on the linked headings. true by default. */
42
42
  headingNumbers?: boolean;
43
+ /**
44
+ * Breaks the labels of the arrows of the sequence diagrams into lines at this many characters (a full-width one
45
+ * counts as 2). 0 does not break them. 30 by default.
46
+ */
47
+ messageWrapWidth?: number;
43
48
  /**
44
49
  * Opens a link of the document (other than `#heading`, which the viewer scrolls to). By default, http(s) and mailto
45
50
  * links open in a new tab, and the others do nothing.
package/viewer.css CHANGED
@@ -1076,6 +1076,12 @@ html:has(> body[data-seqnotes-theme=dark]:is(.vscode-light, .vscode-high-contras
1076
1076
  .seqnotes-viewer.seqnotes-wide .seqnotes-splitter:active::after {
1077
1077
  background: var(--vscode-sash-hoverBorder, var(--seqnotes-accent));
1078
1078
  }
1079
+ .seqnotes-viewer.seqnotes-wide .seqnotes-splitter:focus {
1080
+ outline: none;
1081
+ }
1082
+ .seqnotes-viewer.seqnotes-wide .seqnotes-splitter:focus-visible::after {
1083
+ background: var(--vscode-focusBorder, var(--seqnotes-accent));
1084
+ }
1079
1085
  .seqnotes-viewer.seqnotes-wide .seqnotes-pair:not(.seqnotes-pair-stacked) > .seqnotes-seq-col {
1080
1086
  align-self: start;
1081
1087
  position: sticky;