@probelabs/probe 0.6.0-rc118 → 0.6.0-rc120

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.
@@ -42720,7 +42720,7 @@ function tokenize(text) {
42720
42720
  const lexResult = MermaidLexer.tokenize(text);
42721
42721
  return lexResult;
42722
42722
  }
42723
- var Identifier, NumberLiteral, FlowchartKeyword, GraphKeyword, Direction, SubgraphKeyword, EndKeyword, ClassKeyword, StyleKeyword, ClassDefKeyword, Ampersand, Comma, Semicolon, Colon, TripleColon, BiDirectionalArrow, CircleEndLine, CrossEndLine, DottedArrowRight, DottedArrowLeft, ThickArrowRight, ThickArrowLeft, ArrowRight, ArrowLeft, DottedLine, ThickLine, Line, TwoDashes, InvalidArrow, DoubleSquareOpen, DoubleSquareClose, DoubleRoundOpen, DoubleRoundClose, HexagonOpen, HexagonClose, StadiumOpen, StadiumClose, CylinderOpen, CylinderClose, SquareOpen, SquareClose, RoundOpen, RoundClose, DiamondOpen, DiamondClose, AngleOpen, AngleLess, Pipe, ForwardSlash, Backslash, QuotedString, MultilineText, Comment, ColorValue, Text, WhiteSpace, Newline, allTokens, MermaidLexer;
42723
+ var Identifier, NumberLiteral, FlowchartKeyword, GraphKeyword, Direction, SubgraphKeyword, EndKeyword, ClassKeyword, StyleKeyword, ClassDefKeyword, ClickKeyword, LinkStyleKeyword, Ampersand, Comma, Semicolon, Colon, TripleColon, BiDirectionalArrow, CircleEndLine, CrossEndLine, DottedArrowRight, DottedArrowLeft, ThickArrowRight, ThickArrowLeft, ArrowRight, ArrowLeft, DottedLine, ThickLine, Line, TwoDashes, InvalidArrow, DoubleSquareOpen, DoubleSquareClose, DoubleRoundOpen, DoubleRoundClose, HexagonOpen, HexagonClose, StadiumOpen, StadiumClose, CylinderOpen, CylinderClose, SquareOpen, SquareClose, RoundOpen, RoundClose, DiamondOpen, DiamondClose, AngleOpen, AngleLess, AtSign, Pipe, ForwardSlash, Backslash, QuotedString, MultilineText, Comment, ColorValue, Text, WhiteSpace, Newline, allTokens, MermaidLexer;
42724
42724
  var init_lexer2 = __esm({
42725
42725
  "node_modules/@probelabs/maid/out/diagrams/flowchart/lexer.js"() {
42726
42726
  init_api5();
@@ -42773,6 +42773,8 @@ var init_lexer2 = __esm({
42773
42773
  pattern: /classDef/,
42774
42774
  longer_alt: Identifier
42775
42775
  });
42776
+ ClickKeyword = createToken({ name: "ClickKeyword", pattern: /click/, longer_alt: Identifier });
42777
+ LinkStyleKeyword = createToken({ name: "LinkStyleKeyword", pattern: /linkStyle/, longer_alt: Identifier });
42776
42778
  Ampersand = createToken({
42777
42779
  name: "Ampersand",
42778
42780
  pattern: /&/
@@ -42867,6 +42869,7 @@ var init_lexer2 = __esm({
42867
42869
  DiamondClose = createToken({ name: "DiamondClose", pattern: /\}/ });
42868
42870
  AngleOpen = createToken({ name: "AngleOpen", pattern: />/ });
42869
42871
  AngleLess = createToken({ name: "AngleLess", pattern: /</ });
42872
+ AtSign = createToken({ name: "AtSign", pattern: /@/ });
42870
42873
  Pipe = createToken({ name: "Pipe", pattern: /\|/ });
42871
42874
  ForwardSlash = createToken({ name: "ForwardSlash", pattern: /\// });
42872
42875
  Backslash = createToken({ name: "Backslash", pattern: /\\/ });
@@ -42917,6 +42920,8 @@ var init_lexer2 = __esm({
42917
42920
  ClassDefKeyword,
42918
42921
  ClassKeyword,
42919
42922
  StyleKeyword,
42923
+ ClickKeyword,
42924
+ LinkStyleKeyword,
42920
42925
  Direction,
42921
42926
  // Special multi-char brackets before arrows (some contain > or -)
42922
42927
  DoubleSquareOpen,
@@ -42953,6 +42958,7 @@ var init_lexer2 = __esm({
42953
42958
  DiamondClose,
42954
42959
  AngleOpen,
42955
42960
  AngleLess,
42961
+ AtSign,
42956
42962
  ForwardSlash,
42957
42963
  Backslash,
42958
42964
  Pipe,
@@ -43009,9 +43015,12 @@ var init_parser2 = __esm({
43009
43015
  this.OR([
43010
43016
  { ALT: () => this.SUBRULE(this.nodeStatement) },
43011
43017
  { ALT: () => this.SUBRULE(this.subgraph) },
43018
+ { ALT: () => this.SUBRULE(this.directionStatement) },
43012
43019
  { ALT: () => this.SUBRULE(this.classStatement) },
43013
43020
  { ALT: () => this.SUBRULE(this.styleStatement) },
43014
43021
  { ALT: () => this.SUBRULE(this.classDefStatement) },
43022
+ { ALT: () => this.SUBRULE(this.clickStatement) },
43023
+ { ALT: () => this.SUBRULE(this.linkStyleStatement) },
43015
43024
  { ALT: () => this.CONSUME(Newline) }
43016
43025
  // Empty lines
43017
43026
  ]);
@@ -43047,6 +43056,7 @@ var init_parser2 = __esm({
43047
43056
  this.OPTION(() => {
43048
43057
  this.CONSUME(NumberLiteral, { LABEL: "nodeIdSuffix" });
43049
43058
  });
43059
+ this.OPTION1(() => this.SUBRULE(this.attrObject));
43050
43060
  }
43051
43061
  },
43052
43062
  {
@@ -43063,6 +43073,146 @@ var init_parser2 = __esm({
43063
43073
  this.CONSUME3(Identifier, { LABEL: "nodeClass" });
43064
43074
  });
43065
43075
  });
43076
+ this.attrObject = this.RULE("attrObject", () => {
43077
+ this.CONSUME(AtSign);
43078
+ this.CONSUME(DiamondOpen, { LABEL: "attrLCurly" });
43079
+ this.OPTION(() => {
43080
+ this.SUBRULE(this.attrPair);
43081
+ this.MANY(() => {
43082
+ this.CONSUME(Comma);
43083
+ this.SUBRULE2(this.attrPair);
43084
+ });
43085
+ });
43086
+ this.CONSUME(DiamondClose, { LABEL: "attrRCurly" });
43087
+ });
43088
+ this.attrPair = this.RULE("attrPair", () => {
43089
+ this.CONSUME(Identifier, { LABEL: "attrKey" });
43090
+ this.CONSUME(Colon);
43091
+ this.OR([
43092
+ {
43093
+ GATE: () => {
43094
+ const prev = this.LA(-1);
43095
+ const keyTok = this.LA(-2);
43096
+ return keyTok && /^(shape)$/i.test(String(keyTok.image || ""));
43097
+ },
43098
+ ALT: () => this.SUBRULE(this.attrShapeValue)
43099
+ },
43100
+ { ALT: () => this.CONSUME(QuotedString) },
43101
+ { ALT: () => this.CONSUME2(Identifier) },
43102
+ { ALT: () => this.CONSUME(NumberLiteral) },
43103
+ { ALT: () => this.CONSUME(Text) }
43104
+ ]);
43105
+ });
43106
+ this.attrShapeValue = this.RULE("attrShapeValue", () => {
43107
+ const isKnownShapeId = () => {
43108
+ const la = this.LA(1);
43109
+ if (!la || la.tokenType !== Identifier)
43110
+ return false;
43111
+ const v3 = String(la.image || "").toLowerCase();
43112
+ return v3 === "rect" || v3 === "round" || v3 === "rounded" || v3 === "stadium" || v3 === "subroutine" || v3 === "circle" || v3 === "cylinder" || v3 === "diamond" || v3 === "trapezoid" || v3 === "trapezoidalt" || v3 === "parallelogram" || v3 === "hexagon" || v3 === "lean-l" || v3 === "lean-r" || v3 === "icon" || v3 === "image";
43113
+ };
43114
+ const isKnownShapeQuoted = () => {
43115
+ const la = this.LA(1);
43116
+ if (!la || la.tokenType !== QuotedString)
43117
+ return false;
43118
+ const raw = String(la.image || "");
43119
+ const unq = raw.length >= 2 && (raw.startsWith('"') || raw.startsWith("'")) ? raw.slice(1, -1) : raw;
43120
+ const v3 = unq.toLowerCase();
43121
+ return v3 === "rect" || v3 === "round" || v3 === "rounded" || v3 === "stadium" || v3 === "subroutine" || v3 === "circle" || v3 === "cylinder" || v3 === "diamond" || v3 === "trapezoid" || v3 === "trapezoidalt" || v3 === "parallelogram" || v3 === "hexagon" || v3 === "lean-l" || v3 === "lean-r" || v3 === "icon" || v3 === "image";
43122
+ };
43123
+ this.OR([
43124
+ { GATE: isKnownShapeId, ALT: () => this.CONSUME(Identifier, { LABEL: "shapeId" }) },
43125
+ { GATE: isKnownShapeQuoted, ALT: () => this.CONSUME(QuotedString, { LABEL: "shapeQuoted" }) },
43126
+ // Fallback: accept any identifier/quoted/number/text so parse continues; semantics will flag unknowns
43127
+ { ALT: () => this.CONSUME2(Identifier) },
43128
+ { ALT: () => this.CONSUME2(QuotedString) },
43129
+ { ALT: () => this.CONSUME(NumberLiteral) },
43130
+ { ALT: () => this.CONSUME(Text) }
43131
+ ]);
43132
+ });
43133
+ this.clickStatement = this.RULE("clickStatement", () => {
43134
+ this.CONSUME(ClickKeyword);
43135
+ this.CONSUME(Identifier, { LABEL: "clickTarget" });
43136
+ this.OR([
43137
+ {
43138
+ GATE: () => this.LA(1).tokenType === Identifier && /^(href)$/i.test(this.LA(1).image || ""),
43139
+ ALT: () => this.SUBRULE(this.clickHref)
43140
+ },
43141
+ {
43142
+ GATE: () => this.LA(1).tokenType === Identifier && /^(call|callback)$/i.test(this.LA(1).image || ""),
43143
+ ALT: () => this.SUBRULE(this.clickCall)
43144
+ }
43145
+ ]);
43146
+ this.OPTION(() => this.CONSUME(Newline));
43147
+ });
43148
+ this.clickHref = this.RULE("clickHref", () => {
43149
+ this.CONSUME(Identifier, { LABEL: "mode" });
43150
+ this.CONSUME(QuotedString, { LABEL: "url" });
43151
+ this.OPTION(() => this.CONSUME2(QuotedString, { LABEL: "tooltip" }));
43152
+ this.OPTION2(() => this.CONSUME2(Identifier, { LABEL: "target" }));
43153
+ });
43154
+ this.clickCall = this.RULE("clickCall", () => {
43155
+ this.CONSUME1(Identifier, { LABEL: "mode" });
43156
+ this.OPTION1(() => {
43157
+ this.CONSUME2(Identifier, { LABEL: "fn" });
43158
+ this.OPTION2(() => {
43159
+ this.CONSUME3(RoundOpen);
43160
+ this.OPTION3(() => {
43161
+ this.OR([
43162
+ { ALT: () => this.CONSUME4(Identifier) },
43163
+ { ALT: () => this.CONSUME5(NumberLiteral) },
43164
+ { ALT: () => this.CONSUME6(Text) }
43165
+ ]);
43166
+ });
43167
+ this.CONSUME7(RoundClose);
43168
+ });
43169
+ });
43170
+ this.OPTION4(() => this.CONSUME8(QuotedString, { LABEL: "tooltip" }));
43171
+ });
43172
+ this.linkStyleStatement = this.RULE("linkStyleStatement", () => {
43173
+ this.CONSUME(LinkStyleKeyword);
43174
+ this.SUBRULE(this.linkStyleIndexList);
43175
+ this.OPTION1(() => this.CONSUME1(Newline));
43176
+ this.SUBRULE(this.linkStylePairs);
43177
+ this.OPTION2(() => this.CONSUME2(Newline));
43178
+ });
43179
+ this.linkStyleIndexList = this.RULE("linkStyleIndexList", () => {
43180
+ this.CONSUME(NumberLiteral, { LABEL: "index" });
43181
+ this.MANY(() => {
43182
+ this.CONSUME(Comma);
43183
+ this.CONSUME2(NumberLiteral, { LABEL: "index" });
43184
+ });
43185
+ });
43186
+ this.linkStylePairs = this.RULE("linkStylePairs", () => {
43187
+ this.SUBRULE(this.linkStylePair);
43188
+ this.MANY(() => {
43189
+ this.CONSUME(Comma);
43190
+ this.OPTION(() => this.CONSUME(Newline));
43191
+ this.SUBRULE2(this.linkStylePair);
43192
+ });
43193
+ });
43194
+ this.linkStylePair = this.RULE("linkStylePair", () => {
43195
+ this.CONSUME1(Identifier, { LABEL: "key" });
43196
+ this.CONSUME(Colon);
43197
+ this.SUBRULE(this.linkStyleValueChunk);
43198
+ });
43199
+ this.linkStyleValueChunk = this.RULE("linkStyleValueChunk", () => {
43200
+ this.AT_LEAST_ONE({
43201
+ GATE: () => {
43202
+ const la = this.LA(1);
43203
+ return la && la.tokenType !== Comma && la.tokenType !== Newline;
43204
+ },
43205
+ DEF: () => {
43206
+ this.OR([
43207
+ { ALT: () => this.CONSUME(ColorValue) },
43208
+ { ALT: () => this.CONSUME(QuotedString) },
43209
+ { ALT: () => this.CONSUME(NumberLiteral) },
43210
+ { ALT: () => this.CONSUME(Identifier) },
43211
+ { ALT: () => this.CONSUME(Text) }
43212
+ ]);
43213
+ }
43214
+ });
43215
+ });
43066
43216
  this.nodeShape = this.RULE("nodeShape", () => {
43067
43217
  this.OR([
43068
43218
  // Square brackets: [text]
@@ -43166,6 +43316,10 @@ var init_parser2 = __esm({
43166
43316
  ]);
43167
43317
  });
43168
43318
  this.link = this.RULE("link", () => {
43319
+ this.OPTION1(() => {
43320
+ this.CONSUME(Identifier, { LABEL: "edgeId" });
43321
+ this.CONSUME(AtSign);
43322
+ });
43169
43323
  this.OR([
43170
43324
  // Arrows with inline text (e.g., -.text.-> or ==text==>)
43171
43325
  {
@@ -43206,7 +43360,7 @@ var init_parser2 = __esm({
43206
43360
  { ALT: () => this.CONSUME(InvalidArrow) }
43207
43361
  // Capture for error
43208
43362
  ]);
43209
- this.OPTION(() => {
43363
+ this.OPTION2(() => {
43210
43364
  this.CONSUME(Pipe);
43211
43365
  this.SUBRULE(this.linkText);
43212
43366
  this.CONSUME2(Pipe);
@@ -43368,26 +43522,66 @@ var init_parser2 = __esm({
43368
43522
  // node_modules/@probelabs/maid/out/diagrams/flowchart/semantics.js
43369
43523
  function analyzeFlowchart(cst, _tokens, opts) {
43370
43524
  const ctx = { errors: [], strict: opts?.strict };
43371
- const v3 = new FlowSemanticsVisitor(ctx);
43525
+ const collector = new NodeIdCollector();
43526
+ collector.visit(cst);
43527
+ const v3 = new FlowSemanticsVisitor(ctx, collector.ids, collector.edgeIds);
43372
43528
  v3.visit(cst);
43373
43529
  return ctx.errors;
43374
43530
  }
43375
- var BaseVisitor, FlowSemanticsVisitor;
43531
+ var BaseVisitor, FlowSemanticsVisitor, NodeIdCollector;
43376
43532
  var init_semantics = __esm({
43377
43533
  "node_modules/@probelabs/maid/out/diagrams/flowchart/semantics.js"() {
43378
43534
  init_parser2();
43379
43535
  BaseVisitor = parserInstance.getBaseCstVisitorConstructorWithDefaults();
43380
43536
  FlowSemanticsVisitor = class extends BaseVisitor {
43381
- constructor(ctx) {
43537
+ constructor(ctx, knownIds, knownEdgeIds) {
43382
43538
  super();
43539
+ this.edgeCount = 0;
43383
43540
  this.validateVisitor();
43384
43541
  this.ctx = ctx;
43542
+ this.knownIds = knownIds;
43543
+ this.knownEdgeIds = knownEdgeIds;
43385
43544
  }
43386
43545
  // Entry point
43387
43546
  diagram(ctx) {
43388
43547
  if (ctx.statement)
43389
43548
  ctx.statement.forEach((s3) => this.visit(s3));
43390
43549
  }
43550
+ classStatement(ctx) {
43551
+ const ids = ctx.Identifier || [];
43552
+ const classNameTok = ctx.className && ctx.className[0];
43553
+ for (const idTok of ids) {
43554
+ if (classNameTok && idTok.startOffset === classNameTok.startOffset)
43555
+ continue;
43556
+ const id = String(idTok.image);
43557
+ if (!(this.knownIds.has(id) || this.knownEdgeIds.has(id))) {
43558
+ this.ctx.errors.push({
43559
+ line: idTok.startLine ?? 1,
43560
+ column: idTok.startColumn ?? 1,
43561
+ severity: "warning",
43562
+ code: "FL-CLASS-TARGET-UNKNOWN",
43563
+ message: `Unknown id '${id}' in class statement.`,
43564
+ hint: "Define the node/link before applying classes, or move the class line after it."
43565
+ });
43566
+ }
43567
+ }
43568
+ }
43569
+ styleStatement(ctx) {
43570
+ const idTok = ctx.Identifier && ctx.Identifier[0];
43571
+ if (idTok) {
43572
+ const id = String(idTok.image);
43573
+ if (!this.knownIds.has(id)) {
43574
+ this.ctx.errors.push({
43575
+ line: idTok.startLine ?? 1,
43576
+ column: idTok.startColumn ?? 1,
43577
+ severity: "warning",
43578
+ code: "FL-STYLE-TARGET-UNKNOWN",
43579
+ message: `Unknown node id '${id}' in style statement.`,
43580
+ hint: "Define the node before styling it, or move the style line after the node definition."
43581
+ });
43582
+ }
43583
+ }
43584
+ }
43391
43585
  statement(ctx) {
43392
43586
  for (const k3 of Object.keys(ctx)) {
43393
43587
  const arr = ctx[k3];
@@ -43399,6 +43593,141 @@ var init_semantics = __esm({
43399
43593
  }
43400
43594
  }
43401
43595
  }
43596
+ clickStatement(ctx) {
43597
+ const href = ctx.clickHref?.[0];
43598
+ const call = !href ? ctx.clickCall?.[0] : void 0;
43599
+ if (href) {
43600
+ const ch = href.children || {};
43601
+ const modeTok2 = ch.mode?.[0];
43602
+ const urlTok = ch.url?.[0];
43603
+ const tipTok = ch.tooltip?.[0];
43604
+ const tgtTok = ch.target?.[0];
43605
+ const mode2 = String(modeTok2?.image || "").toLowerCase();
43606
+ if (mode2 !== "href") {
43607
+ this.ctx.errors.push({ line: modeTok2?.startLine ?? 1, column: modeTok2?.startColumn ?? 1, severity: "error", code: "FL-CLICK-MODE-INVALID", message: `Unknown click mode '${modeTok2?.image}'. Use 'href' or 'call'.`, hint: 'Examples: href "\u2026" | call fn()' });
43608
+ return;
43609
+ }
43610
+ if (!urlTok) {
43611
+ this.ctx.errors.push({ line: modeTok2?.startLine ?? 1, column: modeTok2?.startColumn ?? 1, severity: "error", code: "FL-CLICK-HREF-URL-MISSING", message: "'click \u2026 href' requires a quoted URL.", hint: 'Example: click A href "https://example.com" "Open" _blank' });
43612
+ }
43613
+ if (tgtTok && !/^_(blank|self|parent|top)$/i.test(String(tgtTok.image || ""))) {
43614
+ this.ctx.errors.push({ line: tgtTok.startLine ?? 1, column: tgtTok.startColumn ?? 1, severity: "warning", code: "FL-CLICK-TARGET-UNKNOWN", message: `Unknown target '${tgtTok.image}'. Use _blank/_self/_parent/_top.`, hint: "Example: \u2026 _blank" });
43615
+ }
43616
+ return;
43617
+ }
43618
+ if (call) {
43619
+ const ch = call.children || {};
43620
+ const modeTok2 = ch.mode?.[0];
43621
+ const mode2 = String(modeTok2?.image || "").toLowerCase();
43622
+ if (!(mode2 === "call" || mode2 === "callback")) {
43623
+ this.ctx.errors.push({ line: modeTok2?.startLine ?? 1, column: modeTok2?.startColumn ?? 1, severity: "error", code: "FL-CLICK-MODE-INVALID", message: `Unknown click mode '${modeTok2?.image}'. Use 'href' or 'call'.`, hint: 'Examples: href "\u2026" | call fn()' });
43624
+ return;
43625
+ }
43626
+ const fnTok = ch.fn?.[0];
43627
+ if (!fnTok) {
43628
+ this.ctx.errors.push({ line: modeTok2?.startLine ?? 1, column: modeTok2?.startColumn ?? 1, severity: "error", code: "FL-CLICK-CALL-NAME-MISSING", message: "'click \u2026 call' requires a function name.", hint: 'Example: click A call doThing() "Tooltip"' });
43629
+ }
43630
+ const tipTok = ch.tooltip?.[0];
43631
+ if (tipTok) {
43632
+ this.ctx.errors.push({ line: tipTok.startLine ?? 1, column: tipTok.startColumn ?? 1, severity: "error", code: "FL-CLICK-CALL-EXTRA-TEXT", message: "Tooltip/text after 'call()' is not supported by Mermaid CLI.", hint: "Use: click A call doThing()" });
43633
+ }
43634
+ return;
43635
+ }
43636
+ const ids = ctx.Identifier || [];
43637
+ const q3 = ctx.QuotedString || [];
43638
+ const t0 = ids[0];
43639
+ const modeTok = ids[1];
43640
+ const mode = (modeTok?.image || "").toLowerCase();
43641
+ if (!mode) {
43642
+ this.ctx.errors.push({
43643
+ line: t0?.startLine ?? 1,
43644
+ column: t0?.startColumn ?? 1,
43645
+ severity: "error",
43646
+ code: "FL-CLICK-MODE-MISSING",
43647
+ message: "After 'click <id>' specify 'href' or 'call'.",
43648
+ hint: 'Examples: click A href "https://\u2026" "Tip" _blank | click A call doThing() "Tip"'
43649
+ });
43650
+ return;
43651
+ }
43652
+ if (mode === "href") {
43653
+ if (q3.length < 1) {
43654
+ this.ctx.errors.push({
43655
+ line: modeTok.startLine ?? 1,
43656
+ column: modeTok.startColumn ?? 1,
43657
+ severity: "error",
43658
+ code: "FL-CLICK-HREF-URL-MISSING",
43659
+ message: "'click \u2026 href' requires a quoted URL.",
43660
+ hint: 'Example: click A href "https://example.com" "Open" _blank'
43661
+ });
43662
+ }
43663
+ const tgt = ids[2];
43664
+ if (tgt && !/^_(blank|self|parent|top)$/i.test(tgt.image || "")) {
43665
+ this.ctx.errors.push({
43666
+ line: tgt.startLine ?? 1,
43667
+ column: tgt.startColumn ?? 1,
43668
+ severity: "warning",
43669
+ code: "FL-CLICK-TARGET-UNKNOWN",
43670
+ message: `Unknown target '${tgt.image}'. Use _blank/_self/_parent/_top.`,
43671
+ hint: "Example: \u2026 _blank"
43672
+ });
43673
+ }
43674
+ return;
43675
+ }
43676
+ if (mode === "call" || mode === "callback") {
43677
+ const fnTok = ids[2];
43678
+ if (!fnTok) {
43679
+ this.ctx.errors.push({
43680
+ line: modeTok.startLine ?? 1,
43681
+ column: modeTok.startColumn ?? 1,
43682
+ severity: "error",
43683
+ code: "FL-CLICK-CALL-NAME-MISSING",
43684
+ message: "'click \u2026 call' requires a function name.",
43685
+ hint: 'Example: click A call doThing() "Tooltip"'
43686
+ });
43687
+ }
43688
+ return;
43689
+ }
43690
+ this.ctx.errors.push({
43691
+ line: modeTok.startLine ?? 1,
43692
+ column: modeTok.startColumn ?? 1,
43693
+ severity: "error",
43694
+ code: "FL-CLICK-MODE-INVALID",
43695
+ message: `Unknown click mode '${modeTok.image}'. Use 'href' or 'call'.`,
43696
+ hint: 'Examples: href "\u2026" | call fn()'
43697
+ });
43698
+ }
43699
+ linkStyleStatement(ctx) {
43700
+ const idxNode = ctx.linkStyleIndexList?.[0];
43701
+ const pairNode = ctx.linkStylePairs?.[0];
43702
+ const getTokens = (node, name14) => node ? (node.children || {})[name14] || [] : [];
43703
+ const idxToks = getTokens(idxNode, "index");
43704
+ const nums = idxToks.map((t3) => parseInt(t3.image, 10)).filter((n3) => Number.isFinite(n3));
43705
+ if (nums.length === 0) {
43706
+ const anyTok = ctx.LinkStyleKeyword?.[0] || idxToks[0];
43707
+ this.ctx.errors.push({ line: anyTok?.startLine ?? 1, column: anyTok?.startColumn ?? 1, severity: "error", code: "FL-LINKSTYLE-NO-INDICES", message: "'linkStyle' requires one or more link indices (comma separated).", hint: "Example: linkStyle 0,1 stroke:#f66,stroke-width:2px" });
43708
+ return;
43709
+ }
43710
+ const pairChildren = pairNode?.children || {};
43711
+ const pairCount = (pairChildren.linkStylePair || []).length;
43712
+ if (!pairCount) {
43713
+ const firstNum = idxToks[0];
43714
+ this.ctx.errors.push({ line: firstNum?.startLine ?? 1, column: firstNum?.startColumn ?? 1, severity: "error", code: "FL-LINKSTYLE-MISSING-STYLE", message: "Missing style declarations after indices.", hint: "Example: linkStyle 0 stroke:#f00,stroke-width:2px" });
43715
+ }
43716
+ const seen = /* @__PURE__ */ new Set();
43717
+ for (const n3 of nums) {
43718
+ if (seen.has(n3)) {
43719
+ const numTok = idxToks.find((t3) => parseInt(t3.image, 10) === n3);
43720
+ this.ctx.errors.push({ line: numTok?.startLine ?? 1, column: numTok?.startColumn ?? 1, severity: "warning", code: "FL-LINKSTYLE-DUPLICATE-INDEX", message: `Duplicate linkStyle index ${n3}.`, hint: "Remove duplicates." });
43721
+ }
43722
+ seen.add(n3);
43723
+ }
43724
+ for (const n3 of nums) {
43725
+ if (!(n3 >= 0 && n3 < this.edgeCount)) {
43726
+ const numTok = idxToks.find((t3) => parseInt(t3.image, 10) === n3);
43727
+ this.ctx.errors.push({ line: numTok?.startLine ?? 1, column: numTok?.startColumn ?? 1, severity: "error", code: "FL-LINKSTYLE-INDEX-OUT-OF-RANGE", message: `linkStyle index ${n3} is out of range (0..${Math.max(0, this.edgeCount - 1)}).`, hint: `Use an index between 0 and ${Math.max(0, this.edgeCount - 1)} or add more links first.` });
43728
+ }
43729
+ }
43730
+ }
43402
43731
  subgraph(ctx) {
43403
43732
  if (ctx.subgraphStatement)
43404
43733
  ctx.subgraphStatement.forEach((s3) => this.visit(s3));
@@ -43431,14 +43760,109 @@ var init_semantics = __esm({
43431
43760
  nodeStatement(ctx) {
43432
43761
  if (ctx.nodeOrParallelGroup)
43433
43762
  ctx.nodeOrParallelGroup.forEach((n3) => this.visit(n3));
43434
- }
43763
+ const linksHere = Array.isArray(ctx.link) ? ctx.link.length : 0;
43764
+ if (linksHere > 0)
43765
+ this.edgeCount += linksHere;
43766
+ }
43767
+ // Edge attribute object statements must target a known edge id
43768
+ // Edge attribute statements are parsed as nodeStatements with a typed attrObject and no links.
43769
+ // If such a line targets a known edge id, treat it as edge-attr at build time; otherwise keep as a node.
43770
+ // Here we only surface an error when it looks like an edge-attr targeting an unknown edge id (id starts with 'e' and no link).
43771
+ // We keep this heuristic conservative to avoid false positives on typed node shapes.
43772
+ // (Validation that applies the attributes happens in the builder.)
43435
43773
  nodeOrParallelGroup(ctx) {
43436
43774
  if (ctx.node)
43437
43775
  ctx.node.forEach((n3) => this.visit(n3));
43438
43776
  }
43439
43777
  node(ctx) {
43778
+ const hasAttr = Array.isArray(ctx.attrObject) && ctx.attrObject.length > 0;
43779
+ const hasShape = Array.isArray(ctx.nodeShape) && ctx.nodeShape.length > 0;
43780
+ if (hasAttr && hasShape) {
43781
+ const tokArr = ctx.attrObject?.[0]?.children?.attrLCurly || [];
43782
+ const tok = tokArr[0];
43783
+ this.ctx.errors.push({
43784
+ line: tok?.startLine ?? 1,
43785
+ column: tok?.startColumn ?? 1,
43786
+ severity: "warning",
43787
+ code: "FL-TYPED-SHAPE-CONFLICT",
43788
+ message: "Both bracket shape and '@{ shape: \u2026 }' provided. Bracket shape will be used.",
43789
+ hint: 'Pick one style: either A[Label] or A@{ shape: rect, label: "Label" }'
43790
+ });
43791
+ }
43440
43792
  if (ctx.nodeShape)
43441
43793
  ctx.nodeShape.forEach((n3) => this.visit(n3));
43794
+ if (hasAttr) {
43795
+ const attr = ctx.attrObject?.[0];
43796
+ const pairs = attr?.children?.attrPair || [];
43797
+ const validKeys = /* @__PURE__ */ new Set(["shape", "label", "padding", "cornerRadius", "icon", "image"]);
43798
+ const shapes = /* @__PURE__ */ new Set(["rect", "round", "rounded", "stadium", "subroutine", "circle", "cylinder", "diamond", "trapezoid", "trapezoidAlt", "parallelogram", "hexagon", "lean-l", "lean-r", "icon", "image"]);
43799
+ for (const p3 of pairs) {
43800
+ const keyTok = p3.children?.attrKey?.[0];
43801
+ const valTok = p3.children?.QuotedString?.[0] || p3.children?.Identifier?.[0] || p3.children?.NumberLiteral?.[0] || p3.children?.Text?.[0];
43802
+ if (!keyTok)
43803
+ continue;
43804
+ const key = keyTok.image;
43805
+ if (!validKeys.has(key)) {
43806
+ this.ctx.errors.push({
43807
+ line: keyTok.startLine ?? 1,
43808
+ column: keyTok.startColumn ?? 1,
43809
+ severity: "warning",
43810
+ code: "FL-TYPED-KEY-UNKNOWN",
43811
+ message: `Unknown typed-shape key '${key}'.`,
43812
+ hint: "Allowed keys: shape, label, padding, cornerRadius, icon, image"
43813
+ });
43814
+ continue;
43815
+ }
43816
+ if (key === "shape" && valTok) {
43817
+ const v3 = String(valTok.image).replace(/^"|"$/g, "");
43818
+ if (!shapes.has(v3)) {
43819
+ this.ctx.errors.push({
43820
+ line: valTok.startLine ?? 1,
43821
+ column: valTok.startColumn ?? 1,
43822
+ severity: "error",
43823
+ code: "FL-TYPED-SHAPE-UNKNOWN",
43824
+ message: `Unknown shape '${v3}' in '@{ shape: \u2026 }'.`,
43825
+ hint: "Use one of: rect, round, stadium, subroutine, circle, cylinder, diamond, trapezoid, parallelogram, hexagon, lean-l, lean-r, icon, image"
43826
+ });
43827
+ } else {
43828
+ const supportedByCli = /* @__PURE__ */ new Set(["rect", "round", "rounded", "diamond", "circle", "cylinder", "stadium", "subroutine", "lean-l", "lean-r"]);
43829
+ if (!supportedByCli.has(v3)) {
43830
+ this.ctx.errors.push({
43831
+ line: valTok.startLine ?? 1,
43832
+ column: valTok.startColumn ?? 1,
43833
+ severity: "error",
43834
+ code: "FL-TYPED-SHAPE-UNSUPPORTED",
43835
+ message: `Typed shape '${v3}' is not supported by current Mermaid CLI.`,
43836
+ hint: 'Use one of: rect, rounded, diamond, circle, cylinder, stadium, subroutine, "lean-l", "lean-r"'
43837
+ });
43838
+ }
43839
+ }
43840
+ }
43841
+ if (key === "label" && valTok && valTok.tokenType?.name !== "QuotedString") {
43842
+ this.ctx.errors.push({
43843
+ line: valTok.startLine ?? 1,
43844
+ column: valTok.startColumn ?? 1,
43845
+ severity: "warning",
43846
+ code: "FL-TYPED-LABEL-NOT-STRING",
43847
+ message: "Typed-shape 'label' should be a quoted string.",
43848
+ hint: 'Example: A@{ shape: rect, label: "Start" }'
43849
+ });
43850
+ }
43851
+ if ((key === "padding" || key === "cornerRadius") && valTok) {
43852
+ const raw = String(valTok.image).replace(/^"|"$/g, "");
43853
+ if (!/^\d+(px)?$/.test(raw)) {
43854
+ this.ctx.errors.push({
43855
+ line: valTok.startLine ?? 1,
43856
+ column: valTok.startColumn ?? 1,
43857
+ severity: "warning",
43858
+ code: "FL-TYPED-NUMERIC-EXPECTED",
43859
+ message: `'${key}' expects a number (optionally with px).`,
43860
+ hint: `Use: ${key}: 8 or ${key}: "8px"`
43861
+ });
43862
+ }
43863
+ }
43864
+ }
43865
+ }
43442
43866
  }
43443
43867
  checkEmptyContent(openTok, contentNodes) {
43444
43868
  if (!contentNodes || contentNodes.length === 0) {
@@ -43574,6 +43998,7 @@ var init_semantics = __esm({
43574
43998
  if (openTok) {
43575
43999
  this.checkEmptyContent(openTok, contentNodes.length ? contentNodes : void 0);
43576
44000
  this.checkDoubleInSingleQuoted(contentNodes);
44001
+ this.checkBackticksInContent(contentNodes);
43577
44002
  this.warnParensInUnquoted(contentNodes);
43578
44003
  if (this.ctx.strict) {
43579
44004
  let quoted = false;
@@ -43602,6 +44027,93 @@ var init_semantics = __esm({
43602
44027
  }
43603
44028
  }
43604
44029
  }
44030
+ checkBackticksInContent(contentNodes) {
44031
+ if (!contentNodes)
44032
+ return;
44033
+ for (const cn of contentNodes) {
44034
+ const ch = cn.children || {};
44035
+ const inspectTok = (tk) => {
44036
+ if (!tk)
44037
+ return false;
44038
+ const img = String(tk.image || "");
44039
+ const idx = img.indexOf("`");
44040
+ if (idx >= 0) {
44041
+ const col = (tk.startColumn ?? 1) + idx;
44042
+ this.ctx.errors.push({
44043
+ line: tk.startLine ?? 1,
44044
+ column: col,
44045
+ severity: "warning",
44046
+ code: "FL-LABEL-BACKTICK",
44047
+ message: "Backticks (`\u2026`) inside node labels are not supported by Mermaid.",
44048
+ hint: 'Remove the backticks or use quotes instead, e.g., "GITHUB_ACTIONS" and "--cli".',
44049
+ length: 1
44050
+ });
44051
+ return true;
44052
+ }
44053
+ return false;
44054
+ };
44055
+ const texts = ch.Text || [];
44056
+ for (const tk of texts) {
44057
+ if (inspectTok(tk))
44058
+ return;
44059
+ }
44060
+ const qs = ch.QuotedString || [];
44061
+ for (const tk of qs) {
44062
+ if (inspectTok(tk))
44063
+ return;
44064
+ }
44065
+ }
44066
+ }
44067
+ };
44068
+ NodeIdCollector = class extends BaseVisitor {
44069
+ constructor() {
44070
+ super();
44071
+ this.ids = /* @__PURE__ */ new Set();
44072
+ this.edgeIds = /* @__PURE__ */ new Set();
44073
+ this.validateVisitor();
44074
+ }
44075
+ node(ctx) {
44076
+ const idTok = ctx.nodeId && ctx.nodeId[0];
44077
+ const idNumTok = ctx.nodeIdNum && ctx.nodeIdNum[0];
44078
+ if (idTok)
44079
+ this.ids.add(String(idTok.image));
44080
+ else if (idNumTok)
44081
+ this.ids.add(String(idNumTok.image));
44082
+ }
44083
+ link(ctx) {
44084
+ const t3 = ctx.edgeId?.[0];
44085
+ if (t3)
44086
+ this.edgeIds.add(String(t3.image));
44087
+ }
44088
+ nodeOrParallelGroup(ctx) {
44089
+ if (ctx.node)
44090
+ ctx.node.forEach((n3) => this.visit(n3));
44091
+ }
44092
+ nodeStatement(ctx) {
44093
+ if (ctx.nodeOrParallelGroup)
44094
+ ctx.nodeOrParallelGroup.forEach((n3) => this.visit(n3));
44095
+ if (ctx.link)
44096
+ ctx.link.forEach((ln) => this.visit(ln));
44097
+ }
44098
+ edgeAttrStatement(ctx) {
44099
+ const t3 = ctx.edgeId?.[0];
44100
+ if (t3)
44101
+ this.edgeIds.add(String(t3.image));
44102
+ }
44103
+ statement(ctx) {
44104
+ for (const k3 of Object.keys(ctx)) {
44105
+ const arr = ctx[k3];
44106
+ if (Array.isArray(arr))
44107
+ arr.forEach((n3) => {
44108
+ if (n3 && typeof n3.name === "string")
44109
+ this.visit(n3);
44110
+ });
44111
+ }
44112
+ }
44113
+ diagram(ctx) {
44114
+ if (ctx.statement)
44115
+ ctx.statement.forEach((s3) => this.visit(s3));
44116
+ }
43605
44117
  };
43606
44118
  }
43607
44119
  });
@@ -43639,11 +44151,29 @@ function detectDoubleInDouble(tokens, opts) {
43639
44151
  byLine.get(ln).push(tk);
43640
44152
  }
43641
44153
  const ends = new Set(opts.scopeEndTokenNames || []);
44154
+ const starts = new Set(opts.scopeStartTokenNames || []);
43642
44155
  for (const [ln, arr] of byLine) {
43643
44156
  for (let i3 = 0; i3 < arr.length; i3++) {
43644
44157
  const t3 = arr[i3];
43645
44158
  if (t3.tokenType?.name !== "QuotedString")
43646
44159
  continue;
44160
+ if (starts.size > 0) {
44161
+ let startIdx = -1;
44162
+ for (let k3 = i3 - 1; k3 >= 0; k3--) {
44163
+ const s3 = arr[k3];
44164
+ if (starts.has(s3.tokenType?.name || "")) {
44165
+ startIdx = k3;
44166
+ break;
44167
+ }
44168
+ }
44169
+ if (startIdx === -1)
44170
+ continue;
44171
+ const sTok = arr[startIdx];
44172
+ const prevTok = arr[startIdx - 1];
44173
+ if (sTok.tokenType?.name === "DiamondOpen" && prevTok?.tokenType?.name === "AtSign") {
44174
+ continue;
44175
+ }
44176
+ }
43647
44177
  for (let j3 = i3 + 1; j3 < arr.length; j3++) {
43648
44178
  const u3 = arr[j3];
43649
44179
  if (ends.size > 0 && ends.has(u3.tokenType?.name || ""))
@@ -43811,8 +44341,9 @@ function mapFlowchartParserError(err, text) {
43811
44341
  length: len
43812
44342
  };
43813
44343
  }
43814
- if (isInRule(err, "nodeStatement") && err.name === "NoViableAltException") {
43815
- if ((err.message || "").includes("[Newline") && (err.message || "").includes("[EOF")) {
44344
+ if (err.name === "NoViableAltException" || err.name === "MismatchedTokenException") {
44345
+ const msg = err.message || "";
44346
+ if (tokType === "Identifier" && msg.includes("Newline") && msg.includes("EOF")) {
43816
44347
  return {
43817
44348
  line,
43818
44349
  column,
@@ -44420,11 +44951,11 @@ function mapStateParserError(err, text) {
44420
44951
  return { line, column, severity: "error", code: "ST-NOTE-MALFORMED", message: "Malformed note: missing colon before note text.", hint: "Example: Note right of A: message", length: len };
44421
44952
  }
44422
44953
  if (isInRule(err, "stateBlock") && err.name === "MismatchedTokenException" && expecting(err, "RCurly")) {
44423
- if (/---/.test(ltxt)) {
44424
- return { line, column, severity: "error", code: "ST-CONCURRENCY-UNSUPPORTED", message: "Concurrency separator '---' is not supported in Mermaid state diagrams.", hint: "Use separate states or regions without '---'.", length: len };
44425
- }
44426
44954
  return { line, column, severity: "error", code: "ST-BLOCK-MISSING-RBRACE", message: "Missing '}' to close a state block.", hint: "Close the block: state Foo { ... }", length: len };
44427
44955
  }
44956
+ if ((err.name === "NoViableAltException" || err.name === "MismatchedTokenException") && tokType === "Dashes" && !isInRule(err, "innerStatement")) {
44957
+ return { line, column, severity: "error", code: "ST-CONCURRENCY-OUTSIDE-BLOCK", message: "'---' is only allowed inside 'state { \u2026 }' blocks.", hint: "Move '---' inside a composite state block: state A { \u2026 --- \u2026 }", length: len };
44958
+ }
44428
44959
  const dblEsc = (ltxt.match(/\\\"/g) || []).length;
44429
44960
  const dq = (ltxt.match(/\"/g) || []).length - dblEsc;
44430
44961
  if (dq >= 3) {
@@ -44530,9 +45061,60 @@ function validateFlowchart(text, options = {}) {
44530
45061
  "StadiumClose",
44531
45062
  "CylinderClose",
44532
45063
  "HexagonClose"
45064
+ ],
45065
+ scopeStartTokenNames: [
45066
+ "SquareOpen",
45067
+ "RoundOpen",
45068
+ "DiamondOpen",
45069
+ "DoubleSquareOpen",
45070
+ "DoubleRoundOpen",
45071
+ "StadiumOpen",
45072
+ "CylinderOpen",
45073
+ "HexagonOpen"
44533
45074
  ]
44534
45075
  }).filter((e3) => !seenDoubleLines.has(e3.line) && !escapedLinesAll.has(e3.line));
44535
45076
  const errs = escWarn.concat(dbl);
45077
+ const generic = (prevErrors || []).filter((e3) => e3.severity === "error" && !("code" in e3) && typeof e3.message === "string");
45078
+ for (const ge of generic) {
45079
+ const msg = String(ge.message || "");
45080
+ if (msg.includes("Newline") && msg.includes("EOF")) {
45081
+ errs.push({
45082
+ line: ge.line ?? 1,
45083
+ column: ge.column ?? 1,
45084
+ severity: "error",
45085
+ code: "FL-LINK-MISSING",
45086
+ message: "Two nodes on one line must be connected with an arrow.",
45087
+ hint: "Insert --> between nodes, e.g., A --> B."
45088
+ });
45089
+ }
45090
+ }
45091
+ {
45092
+ const lines = text2.split(/\r?\n/);
45093
+ const nodeRef = String.raw`[A-Za-z0-9_]+(?:\[[^\]]*\]|\([^\)]*\)|\{[^}]*\}|\[\[[^\]]*\]\]|\(\([^\)]*\)\))?`;
45094
+ const re = new RegExp(String.raw`^\s*(${nodeRef})\s+(${nodeRef})\s*;?\s*$`);
45095
+ const skipStart = /^(?:\s*)(style|classDef|class|click|linkStyle|subgraph|end|graph|flowchart|direction)\b/;
45096
+ for (let i3 = 0; i3 < lines.length; i3++) {
45097
+ const raw = lines[i3] || "";
45098
+ const ln = i3 + 1;
45099
+ if (!raw.trim())
45100
+ continue;
45101
+ if (skipStart.test(raw))
45102
+ continue;
45103
+ const m3 = re.exec(raw);
45104
+ if (m3) {
45105
+ const idxSecond = raw.indexOf(m3[2]);
45106
+ const col = idxSecond >= 0 ? idxSecond + 1 : 1;
45107
+ errs.push({
45108
+ line: ln,
45109
+ column: col,
45110
+ severity: "error",
45111
+ code: "FL-LINK-MISSING",
45112
+ message: "Two nodes on one line must be connected with an arrow.",
45113
+ hint: "Insert --> between nodes, e.g., A --> B."
45114
+ });
45115
+ }
45116
+ }
45117
+ }
44536
45118
  const dblEsc = (text2.match(/\\\"/g) || []).length;
44537
45119
  const dq = (text2.match(/\"/g) || []).length - dblEsc;
44538
45120
  const sq = (text2.match(/'/g) || []).length;
@@ -44738,7 +45320,7 @@ var init_validate2 = __esm({
44738
45320
  function tokenize3(text) {
44739
45321
  return SequenceLexer.tokenize(text);
44740
45322
  }
44741
- var Identifier2, NumberLiteral3, SequenceKeyword, ParticipantKeyword, ActorKeyword, AsKeyword, AutonumberKeyword, OffKeyword, NoteKeyword, LeftKeyword, RightKeyword, OverKeyword, OfKeyword, ActivateKeyword, DeactivateKeyword, CreateKeyword, DestroyKeyword, AltKeyword, ElseKeyword, OptionKeyword, OptKeyword, LoopKeyword, ParKeyword, AndKeyword, RectKeyword, CriticalKeyword, BoxKeyword, EndKeyword2, LinksKeyword, LinkKeyword, BreakKeyword, BidirAsyncDotted, BidirAsync, DottedAsync, Async, Dotted, Solid, DottedCross, Cross, DottedOpen, Open, Plus, Minus, Comma2, Colon3, LParen, RParen, QuotedString3, Comment3, WhiteSpace3, Newline3, Text3, allTokens3, SequenceLexer;
45323
+ var Identifier2, NumberLiteral3, SequenceKeyword, ParticipantKeyword, ActorKeyword, AsKeyword, AutonumberKeyword, OffKeyword, NoteKeyword, LeftKeyword, RightKeyword, OverKeyword, OfKeyword, TitleKeyword2, AccTitleKeyword, AccDescrKeyword, ActivateKeyword, DeactivateKeyword, CreateKeyword, DestroyKeyword, AltKeyword, ElseKeyword, OptionKeyword, OptKeyword, LoopKeyword, ParKeyword, AndKeyword, RectKeyword, CriticalKeyword, BoxKeyword, EndKeyword2, LinksKeyword, LinkKeyword, PropertiesKeyword, DetailsKeyword, BreakKeyword, BidirAsyncDotted, BidirAsync, DottedAsync, Async, Dotted, Solid, DottedCross, Cross, DottedOpen, Open, Plus, Minus, Comma2, Colon3, LParen, RParen, QuotedString3, Comment3, WhiteSpace3, Newline3, Text3, allTokens3, SequenceLexer;
44742
45324
  var init_lexer4 = __esm({
44743
45325
  "node_modules/@probelabs/maid/out/diagrams/sequence/lexer.js"() {
44744
45326
  init_api5();
@@ -44755,6 +45337,9 @@ var init_lexer4 = __esm({
44755
45337
  RightKeyword = createToken({ name: "RightKeyword", pattern: /right/i, longer_alt: Identifier2 });
44756
45338
  OverKeyword = createToken({ name: "OverKeyword", pattern: /over/i, longer_alt: Identifier2 });
44757
45339
  OfKeyword = createToken({ name: "OfKeyword", pattern: /of/i, longer_alt: Identifier2 });
45340
+ TitleKeyword2 = createToken({ name: "TitleKeyword", pattern: /title/i, longer_alt: Identifier2 });
45341
+ AccTitleKeyword = createToken({ name: "AccTitleKeyword", pattern: /acc_title|accTitle/i, longer_alt: Identifier2 });
45342
+ AccDescrKeyword = createToken({ name: "AccDescrKeyword", pattern: /acc_descr|accDescr/i, longer_alt: Identifier2 });
44758
45343
  ActivateKeyword = createToken({ name: "ActivateKeyword", pattern: /activate/i, longer_alt: Identifier2 });
44759
45344
  DeactivateKeyword = createToken({ name: "DeactivateKeyword", pattern: /deactivate/i, longer_alt: Identifier2 });
44760
45345
  CreateKeyword = createToken({ name: "CreateKeyword", pattern: /create/i, longer_alt: Identifier2 });
@@ -44772,6 +45357,8 @@ var init_lexer4 = __esm({
44772
45357
  EndKeyword2 = createToken({ name: "EndKeyword", pattern: /end/i, longer_alt: Identifier2 });
44773
45358
  LinksKeyword = createToken({ name: "LinksKeyword", pattern: /links/i, longer_alt: Identifier2 });
44774
45359
  LinkKeyword = createToken({ name: "LinkKeyword", pattern: /link/i, longer_alt: Identifier2 });
45360
+ PropertiesKeyword = createToken({ name: "PropertiesKeyword", pattern: /properties/i, longer_alt: Identifier2 });
45361
+ DetailsKeyword = createToken({ name: "DetailsKeyword", pattern: /details/i, longer_alt: Identifier2 });
44775
45362
  BreakKeyword = createToken({ name: "BreakKeyword", pattern: /break/i, longer_alt: Identifier2 });
44776
45363
  BidirAsyncDotted = createToken({ name: "BidirAsyncDotted", pattern: /<<-->>/ });
44777
45364
  BidirAsync = createToken({ name: "BidirAsync", pattern: /<<->>/ });
@@ -44804,6 +45391,9 @@ var init_lexer4 = __esm({
44804
45391
  Newline3,
44805
45392
  // Header/Keywords
44806
45393
  SequenceKeyword,
45394
+ TitleKeyword2,
45395
+ AccTitleKeyword,
45396
+ AccDescrKeyword,
44807
45397
  ParticipantKeyword,
44808
45398
  ActorKeyword,
44809
45399
  AsKeyword,
@@ -44832,6 +45422,8 @@ var init_lexer4 = __esm({
44832
45422
  EndKeyword2,
44833
45423
  LinksKeyword,
44834
45424
  LinkKeyword,
45425
+ PropertiesKeyword,
45426
+ DetailsKeyword,
44835
45427
  // Arrows
44836
45428
  BidirAsyncDotted,
44837
45429
  BidirAsync,
@@ -44883,6 +45475,7 @@ var init_parser4 = __esm({
44883
45475
  });
44884
45476
  this.line = this.RULE("line", () => {
44885
45477
  this.OR([
45478
+ { ALT: () => this.SUBRULE(this.metaStmt) },
44886
45479
  { ALT: () => this.SUBRULE(this.participantDecl) },
44887
45480
  { ALT: () => this.SUBRULE(this.autonumberStmt) },
44888
45481
  { ALT: () => this.SUBRULE(this.noteStmt) },
@@ -44891,6 +45484,8 @@ var init_parser4 = __esm({
44891
45484
  { ALT: () => this.SUBRULE(this.createStmt) },
44892
45485
  { ALT: () => this.SUBRULE(this.destroyStmt) },
44893
45486
  { ALT: () => this.SUBRULE(this.linkStmt) },
45487
+ { ALT: () => this.SUBRULE(this.propertiesStmt) },
45488
+ { ALT: () => this.SUBRULE(this.detailsStmt) },
44894
45489
  { ALT: () => this.SUBRULE(this.altBlock) },
44895
45490
  { ALT: () => this.SUBRULE(this.optBlock) },
44896
45491
  { ALT: () => this.SUBRULE(this.loopBlock) },
@@ -44903,6 +45498,18 @@ var init_parser4 = __esm({
44903
45498
  { ALT: () => this.SUBRULE(this.blankLine) }
44904
45499
  ]);
44905
45500
  });
45501
+ this.metaStmt = this.RULE("metaStmt", () => {
45502
+ this.OR([
45503
+ { ALT: () => this.CONSUME(TitleKeyword2) },
45504
+ { ALT: () => this.CONSUME(AccTitleKeyword) },
45505
+ { ALT: () => this.CONSUME(AccDescrKeyword) }
45506
+ ]);
45507
+ this.OPTION(() => this.SUBRULE(this.lineRemainder));
45508
+ this.OR2([
45509
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45510
+ { ALT: () => this.CONSUME(EOF) }
45511
+ ]);
45512
+ });
44906
45513
  this.blankLine = this.RULE("blankLine", () => {
44907
45514
  this.AT_LEAST_ONE(() => this.CONSUME(Newline3));
44908
45515
  });
@@ -45031,6 +45638,24 @@ var init_parser4 = __esm({
45031
45638
  { ALT: () => this.CONSUME(EOF) }
45032
45639
  ]);
45033
45640
  });
45641
+ this.propertiesStmt = this.RULE("propertiesStmt", () => {
45642
+ this.CONSUME(PropertiesKeyword);
45643
+ this.OPTION(() => this.CONSUME(Colon3));
45644
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45645
+ this.OR2([
45646
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45647
+ { ALT: () => this.CONSUME(EOF) }
45648
+ ]);
45649
+ });
45650
+ this.detailsStmt = this.RULE("detailsStmt", () => {
45651
+ this.CONSUME(DetailsKeyword);
45652
+ this.OPTION(() => this.CONSUME(Colon3));
45653
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45654
+ this.OR2([
45655
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45656
+ { ALT: () => this.CONSUME(EOF) }
45657
+ ]);
45658
+ });
45034
45659
  this.messageStmt = this.RULE("messageStmt", () => {
45035
45660
  this.SUBRULE(this.actorRef);
45036
45661
  this.SUBRULE(this.arrow);
@@ -45101,7 +45726,7 @@ var init_parser4 = __esm({
45101
45726
  });
45102
45727
  this.parBlock = this.RULE("parBlock", () => {
45103
45728
  this.CONSUME(ParKeyword);
45104
- this.OPTION(() => this.SUBRULE(this.lineRemainder));
45729
+ this.OPTION(() => this.SUBRULE(this.parHeader));
45105
45730
  this.AT_LEAST_ONE(() => this.CONSUME(Newline3));
45106
45731
  this.MANY(() => this.SUBRULE(this.line));
45107
45732
  this.MANY2(() => {
@@ -45116,6 +45741,23 @@ var init_parser4 = __esm({
45116
45741
  { ALT: () => this.CONSUME3(EOF) }
45117
45742
  ]);
45118
45743
  });
45744
+ this.parHeader = this.RULE("parHeader", () => {
45745
+ this.OR([
45746
+ {
45747
+ GATE: () => this.LA(1).tokenType === OverKeyword,
45748
+ ALT: () => {
45749
+ this.CONSUME(OverKeyword);
45750
+ this.SUBRULE(this.actorRef);
45751
+ this.OPTION(() => {
45752
+ this.CONSUME(Comma2);
45753
+ this.SUBRULE2(this.actorRef);
45754
+ });
45755
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45756
+ }
45757
+ },
45758
+ { ALT: () => this.SUBRULE2(this.lineRemainder) }
45759
+ ]);
45760
+ });
45119
45761
  this.criticalBlock = this.RULE("criticalBlock", () => {
45120
45762
  this.CONSUME(CriticalKeyword);
45121
45763
  this.OPTION(() => this.SUBRULE(this.lineRemainder));
@@ -45190,6 +45832,9 @@ var init_parser4 = __esm({
45190
45832
  { ALT: () => this.CONSUME(BreakKeyword) },
45191
45833
  { ALT: () => this.CONSUME(BoxKeyword) },
45192
45834
  { ALT: () => this.CONSUME(EndKeyword2) },
45835
+ { ALT: () => this.CONSUME(TitleKeyword2) },
45836
+ { ALT: () => this.CONSUME(AccTitleKeyword) },
45837
+ { ALT: () => this.CONSUME(AccDescrKeyword) },
45193
45838
  { ALT: () => this.CONSUME(NoteKeyword) },
45194
45839
  { ALT: () => this.CONSUME(LeftKeyword) },
45195
45840
  { ALT: () => this.CONSUME(RightKeyword) },
@@ -45218,12 +45863,186 @@ var init_parser4 = __esm({
45218
45863
  function analyzeSequence(_cst, _tokens) {
45219
45864
  const ctx = { tokens: _tokens };
45220
45865
  const v3 = new SequenceSemanticsVisitor(ctx);
45221
- return [];
45866
+ const errs = [];
45867
+ const firstByLine = /* @__PURE__ */ new Map();
45868
+ for (const tk of _tokens) {
45869
+ const ln = tk.startLine ?? 1;
45870
+ const col = tk.startColumn ?? 1;
45871
+ const prev = firstByLine.get(ln);
45872
+ if (!prev || (prev.startColumn ?? Infinity) > col)
45873
+ firstByLine.set(ln, tk);
45874
+ }
45875
+ for (const tok of _tokens) {
45876
+ if (tok.tokenType === TitleKeyword2 || tok.tokenType === AccTitleKeyword || tok.tokenType === AccDescrKeyword) {
45877
+ const isLineStart = firstByLine.get(tok.startLine ?? 1) === tok;
45878
+ if (isLineStart)
45879
+ errs.push({
45880
+ line: tok.startLine ?? 1,
45881
+ column: tok.startColumn ?? 1,
45882
+ severity: "error",
45883
+ code: "SE-META-UNSUPPORTED",
45884
+ message: "Title/accTitle/accDescr are not accepted by current Mermaid CLI for sequence diagrams.",
45885
+ hint: "Remove this line (e.g., 'title \u2026') to match mermaid-cli.",
45886
+ length: tok.image?.length ?? 5
45887
+ });
45888
+ }
45889
+ if (tok.tokenType === PropertiesKeyword && firstByLine.get(tok.startLine ?? 1) === tok) {
45890
+ errs.push({
45891
+ line: tok.startLine ?? 1,
45892
+ column: tok.startColumn ?? 1,
45893
+ severity: "error",
45894
+ code: "SE-PROPERTIES-UNSUPPORTED",
45895
+ message: "'properties' is not accepted by current Mermaid CLI for sequence diagrams.",
45896
+ hint: "Remove the 'properties:' line to match mermaid-cli.",
45897
+ length: tok.image?.length ?? 10
45898
+ });
45899
+ }
45900
+ if (tok.tokenType === DetailsKeyword && firstByLine.get(tok.startLine ?? 1) === tok) {
45901
+ errs.push({
45902
+ line: tok.startLine ?? 1,
45903
+ column: tok.startColumn ?? 1,
45904
+ severity: "error",
45905
+ code: "SE-DETAILS-UNSUPPORTED",
45906
+ message: "'details' is not accepted by current Mermaid CLI for sequence diagrams.",
45907
+ hint: "Remove the 'details:' line to match mermaid-cli.",
45908
+ length: tok.image?.length ?? 7
45909
+ });
45910
+ }
45911
+ }
45912
+ const lines = /* @__PURE__ */ new Map();
45913
+ for (const tk of _tokens) {
45914
+ if (tk.tokenType === Newline3)
45915
+ continue;
45916
+ const ln = tk.startLine ?? 1;
45917
+ (lines.get(ln) || lines.set(ln, []).get(ln)).push(tk);
45918
+ }
45919
+ const events = [];
45920
+ const tokensByLine = Array.from(lines.entries()).sort((a3, b3) => a3[0] - b3[0]);
45921
+ const grabActorRef = (arr, startIdx) => {
45922
+ const parts = [];
45923
+ for (let i3 = startIdx; i3 < arr.length; i3++) {
45924
+ const tk = arr[i3];
45925
+ if (tk.tokenType === Colon3 || tk.tokenType === Newline3)
45926
+ break;
45927
+ if (tk.tokenType === Identifier2 || tk.tokenType === QuotedString3 || tk.tokenType === NumberLiteral3 || tk.tokenType === Text3)
45928
+ parts.push(tk.image);
45929
+ if (tk.tokenType === Async || tk.tokenType === Solid || tk.tokenType === Dotted || tk.tokenType === DottedAsync || tk.tokenType === BidirAsync || tk.tokenType === BidirAsyncDotted)
45930
+ break;
45931
+ }
45932
+ const raw = parts.join(" ").trim();
45933
+ return raw.replace(/^"|"$/g, "");
45934
+ };
45935
+ for (const [ln, arr] of tokensByLine) {
45936
+ if (arr.some((tk) => tk.tokenType === ActivateKeyword)) {
45937
+ const idx = arr.findIndex((tk) => tk.tokenType === ActivateKeyword);
45938
+ const actor = grabActorRef(arr, idx + 1);
45939
+ if (actor)
45940
+ events.push({ kind: "activate", line: ln, actor });
45941
+ continue;
45942
+ }
45943
+ if (arr.some((tk) => tk.tokenType === DeactivateKeyword)) {
45944
+ const idx = arr.findIndex((tk) => tk.tokenType === DeactivateKeyword);
45945
+ const actor = grabActorRef(arr, idx + 1);
45946
+ if (actor)
45947
+ events.push({ kind: "deactivate", line: ln, actor });
45948
+ continue;
45949
+ }
45950
+ if (arr.some((tk) => tk.tokenType === CreateKeyword)) {
45951
+ const idx = arr.findIndex((tk) => tk.tokenType === CreateKeyword);
45952
+ const after = arr.slice(idx + 1);
45953
+ const aidx = after.findIndex((tk) => tk.tokenType === ParticipantKeyword || tk.tokenType === ActorKeyword);
45954
+ const actor = aidx >= 0 ? grabActorRef(after, aidx + 1) : grabActorRef(arr, idx + 1);
45955
+ if (actor)
45956
+ events.push({ kind: "create", line: ln, actor });
45957
+ continue;
45958
+ }
45959
+ const arrowIdx = arr.findIndex((tk) => [Async, DottedAsync, Solid, Dotted, Cross, DottedCross, DottedOpen, Open, BidirAsync, BidirAsyncDotted].includes(tk.tokenType));
45960
+ if (arrowIdx > 0) {
45961
+ const from = grabActorRef(arr, 0);
45962
+ const to = grabActorRef(arr, arrowIdx + 1);
45963
+ if (from || to) {
45964
+ const plusTok = arr.find((tk) => tk.tokenType === Plus);
45965
+ const minusTok = arr.find((tk) => tk.tokenType === Minus);
45966
+ events.push({ kind: "message", line: ln, from, to, plus: Boolean(plusTok), minus: Boolean(minusTok), plusTok, minusTok });
45967
+ }
45968
+ }
45969
+ }
45970
+ const actStack = /* @__PURE__ */ new Map();
45971
+ for (const ev of events) {
45972
+ if (ev.kind === "activate" && ev.actor) {
45973
+ const a3 = actStack.get(ev.actor) || [];
45974
+ a3.push({ line: ev.line });
45975
+ actStack.set(ev.actor, a3);
45976
+ } else if (ev.kind === "deactivate" && ev.actor) {
45977
+ const a3 = actStack.get(ev.actor) || [];
45978
+ a3.pop();
45979
+ actStack.set(ev.actor, a3);
45980
+ } else if (ev.kind === "message" && ev.to) {
45981
+ const target = ev.to;
45982
+ const plus = Boolean(ev.plus);
45983
+ const minus = Boolean(ev.minus);
45984
+ const plusTok = ev.plusTok;
45985
+ const minusTok = ev.minusTok;
45986
+ if (plus) {
45987
+ const a3 = actStack.get(target) || [];
45988
+ if (a3.length > 0) {
45989
+ const col = plusTok?.startColumn ?? 1;
45990
+ errs.push({ line: ev.line, column: col, severity: "warning", code: "SE-ACTIVATION-ALREADY-ACTIVE", message: `Message indicates '+ (activate)' but '${target}' is already active.`, hint: `Remove '+' or deactivate first: deactivate ${target}`, length: 1 });
45991
+ } else {
45992
+ a3.push({ line: ev.line });
45993
+ actStack.set(target, a3);
45994
+ }
45995
+ }
45996
+ if (minus) {
45997
+ const a3 = actStack.get(target) || [];
45998
+ if (a3.length === 0) {
45999
+ const col = minusTok?.startColumn ?? 1;
46000
+ errs.push({ line: ev.line, column: col, severity: "warning", code: "SE-DEACTIVATE-NO-ACTIVE", message: `Message indicates '- (deactivate)' but '${target}' is not active.`, hint: `Remove '-' or ensure 'activate ${target}' occurred before.`, length: 1 });
46001
+ } else {
46002
+ a3.pop();
46003
+ actStack.set(target, a3);
46004
+ }
46005
+ }
46006
+ }
46007
+ }
46008
+ for (const [actor, arr] of actStack.entries()) {
46009
+ if (arr.length) {
46010
+ const top = arr[arr.length - 1];
46011
+ errs.push({
46012
+ line: top.line,
46013
+ column: 1,
46014
+ severity: "warning",
46015
+ code: "SE-ACTIVATION-UNBALANCED",
46016
+ message: `Unbalanced activation: '${actor}' was activated but not deactivated.`,
46017
+ hint: `Add 'deactivate ${actor}' after the active section.`,
46018
+ length: actor.length
46019
+ });
46020
+ }
46021
+ }
46022
+ for (let i3 = 0; i3 < events.length; i3++) {
46023
+ const ev = events[i3];
46024
+ if (ev.kind === "create" && ev.actor) {
46025
+ const next = events[i3 + 1];
46026
+ if (!(next && next.kind === "message" && (next.from === ev.actor || next.to === ev.actor))) {
46027
+ errs.push({
46028
+ line: ev.line,
46029
+ column: 1,
46030
+ severity: "warning",
46031
+ code: "SE-CREATE-NO-CREATING-MESSAGE",
46032
+ message: `Actor '${ev.actor}' is created but the next line is not a message involving it.`,
46033
+ hint: `Add a creating message to or from '${ev.actor}' immediately after the create line.`,
46034
+ length: ev.actor.length
46035
+ });
46036
+ }
46037
+ }
46038
+ }
46039
+ return errs;
45222
46040
  }
45223
46041
  var BaseVisitor3, SequenceSemanticsVisitor;
45224
46042
  var init_semantics3 = __esm({
45225
46043
  "node_modules/@probelabs/maid/out/diagrams/sequence/semantics.js"() {
45226
46044
  init_parser4();
46045
+ init_lexer4();
45227
46046
  BaseVisitor3 = parserInstance3.getBaseCstVisitorConstructorWithDefaults();
45228
46047
  SequenceSemanticsVisitor = class extends BaseVisitor3 {
45229
46048
  constructor(ctx) {
@@ -45333,7 +46152,7 @@ var init_validate3 = __esm({
45333
46152
  function tokenize4(text) {
45334
46153
  return ClassLexer.tokenize(text);
45335
46154
  }
45336
- var Identifier3, NumberLiteral4, ClassDiagramKeyword, DirectionKw, Direction2, ClassKw, AsKw, NoteKw, RelCompToAgg, RelAggToComp, RelCompBoth, RelAggBoth, LollipopLeft, LollipopRight, RelExtends, RelComposition, RelAggregation, RelDependency, RelRealization, RelAssociation, InvalidRelArrow, LCurly, RCurly, LParen2, RParen2, Colon4, Comma3, Visibility, LTlt, GTgt, QuotedString4, BacktickName, SquareOpen2, SquareClose2, Comment4, WhiteSpace4, Newline4, allTokens4, ClassLexer;
46155
+ var Identifier3, NumberLiteral4, ClassDiagramKeyword, DirectionKw, Direction2, ClassKw, AsKw, NoteKw, ForKw, RelCompToAgg, RelAggToComp, RelCompBoth, RelAggBoth, LollipopLeft, LollipopRight, RelExtends, RelComposition, RelAggregation, RelDependency, RelRealization, RelAssociation, RelDependencyLeft, RelRealizationLeft, RelExtendsRight, InvalidRelArrow, LCurly, RCurly, LParen2, RParen2, Colon4, Comma3, Visibility, LTlt, GTgt, GenericAngle, QuotedString4, BacktickName, SquareOpen2, SquareClose2, Comment4, WhiteSpace4, Newline4, allTokens4, ClassLexer;
45337
46156
  var init_lexer5 = __esm({
45338
46157
  "node_modules/@probelabs/maid/out/diagrams/class/lexer.js"() {
45339
46158
  init_api5();
@@ -45345,6 +46164,7 @@ var init_lexer5 = __esm({
45345
46164
  ClassKw = createToken({ name: "ClassKw", pattern: /class/, longer_alt: Identifier3 });
45346
46165
  AsKw = createToken({ name: "AsKw", pattern: /as/, longer_alt: Identifier3 });
45347
46166
  NoteKw = createToken({ name: "NoteKw", pattern: /note/, longer_alt: Identifier3 });
46167
+ ForKw = createToken({ name: "ForKw", pattern: /for/, longer_alt: Identifier3 });
45348
46168
  RelCompToAgg = createToken({ name: "RelCompToAgg", pattern: /\*--o/ });
45349
46169
  RelAggToComp = createToken({ name: "RelAggToComp", pattern: /o--\*/ });
45350
46170
  RelCompBoth = createToken({ name: "RelCompBoth", pattern: /\*--\*/ });
@@ -45357,6 +46177,9 @@ var init_lexer5 = __esm({
45357
46177
  RelDependency = createToken({ name: "RelDependency", pattern: /\.\.>/ });
45358
46178
  RelRealization = createToken({ name: "RelRealization", pattern: /\.\.\|>/ });
45359
46179
  RelAssociation = createToken({ name: "RelAssociation", pattern: /--/ });
46180
+ RelDependencyLeft = createToken({ name: "RelDependencyLeft", pattern: /<\.\./ });
46181
+ RelRealizationLeft = createToken({ name: "RelRealizationLeft", pattern: /<\|\.\./ });
46182
+ RelExtendsRight = createToken({ name: "RelExtendsRight", pattern: /--\|>/ });
45360
46183
  InvalidRelArrow = createToken({ name: "InvalidRelArrow", pattern: /->(?!>)/ });
45361
46184
  LCurly = createToken({ name: "LCurly", pattern: /\{/ });
45362
46185
  RCurly = createToken({ name: "RCurly", pattern: /\}/ });
@@ -45367,6 +46190,7 @@ var init_lexer5 = __esm({
45367
46190
  Visibility = createToken({ name: "Visibility", pattern: /[+\-#~]/ });
45368
46191
  LTlt = createToken({ name: "LTlt", pattern: /<</ });
45369
46192
  GTgt = createToken({ name: "GTgt", pattern: />>/ });
46193
+ GenericAngle = createToken({ name: "GenericAngle", pattern: /<[^\n\r>]+>/ });
45370
46194
  QuotedString4 = createToken({ name: "QuotedString", pattern: /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/ });
45371
46195
  BacktickName = createToken({ name: "BacktickName", pattern: /`(?:\\.|[^`\\])*`/ });
45372
46196
  SquareOpen2 = createToken({ name: "SquareOpen", pattern: /\[/ });
@@ -45383,6 +46207,7 @@ var init_lexer5 = __esm({
45383
46207
  ClassKw,
45384
46208
  AsKw,
45385
46209
  NoteKw,
46210
+ ForKw,
45386
46211
  Direction2,
45387
46212
  // Relationship ops
45388
46213
  RelCompToAgg,
@@ -45394,6 +46219,9 @@ var init_lexer5 = __esm({
45394
46219
  RelRealization,
45395
46220
  RelDependency,
45396
46221
  RelExtends,
46222
+ RelDependencyLeft,
46223
+ RelRealizationLeft,
46224
+ RelExtendsRight,
45397
46225
  RelComposition,
45398
46226
  RelAggregation,
45399
46227
  RelAssociation,
@@ -45401,6 +46229,7 @@ var init_lexer5 = __esm({
45401
46229
  // Punct
45402
46230
  LTlt,
45403
46231
  GTgt,
46232
+ GenericAngle,
45404
46233
  LCurly,
45405
46234
  RCurly,
45406
46235
  LParen2,
@@ -45446,6 +46275,7 @@ var init_parser5 = __esm({
45446
46275
  { ALT: () => this.SUBRULE(this.directionStmt) },
45447
46276
  { ALT: () => this.SUBRULE(this.classLine) },
45448
46277
  { ALT: () => this.SUBRULE(this.relationStmt) },
46278
+ { ALT: () => this.SUBRULE(this.noteStmt) },
45449
46279
  { ALT: () => this.SUBRULE(this.memberAssignStmt) },
45450
46280
  { ALT: () => this.CONSUME(Newline4) }
45451
46281
  ]);
@@ -45559,6 +46389,18 @@ var init_parser5 = __esm({
45559
46389
  { ALT: () => this.CONSUME(QuotedString4) }
45560
46390
  ]);
45561
46391
  });
46392
+ this.noteStmt = this.RULE("noteStmt", () => {
46393
+ this.CONSUME(NoteKw);
46394
+ this.OPTION(() => this.CONSUME(ForKw));
46395
+ this.SUBRULE(this.classRef);
46396
+ this.OPTION1(() => this.CONSUME(Colon4));
46397
+ this.OR([
46398
+ { ALT: () => this.CONSUME(QuotedString4) },
46399
+ { ALT: () => this.CONSUME(Identifier3) },
46400
+ { ALT: () => this.CONSUME(NumberLiteral4) }
46401
+ ]);
46402
+ this.OPTION2(() => this.CONSUME(Newline4));
46403
+ });
45562
46404
  this.relationOp = this.RULE("relationOp", () => {
45563
46405
  this.OR([
45564
46406
  { ALT: () => this.CONSUME(RelCompToAgg) },
@@ -45568,16 +46410,22 @@ var init_parser5 = __esm({
45568
46410
  { ALT: () => this.CONSUME(LollipopLeft) },
45569
46411
  { ALT: () => this.CONSUME(LollipopRight) },
45570
46412
  { ALT: () => this.CONSUME(RelExtends) },
46413
+ { ALT: () => this.CONSUME(RelExtendsRight) },
45571
46414
  { ALT: () => this.CONSUME(RelComposition) },
45572
46415
  { ALT: () => this.CONSUME(RelAggregation) },
45573
46416
  { ALT: () => this.CONSUME(RelRealization) },
45574
46417
  { ALT: () => this.CONSUME(RelDependency) },
46418
+ { ALT: () => this.CONSUME(RelRealizationLeft) },
46419
+ { ALT: () => this.CONSUME(RelDependencyLeft) },
45575
46420
  { ALT: () => this.CONSUME(RelAssociation) }
45576
46421
  ]);
45577
46422
  });
45578
46423
  this.classRef = this.RULE("classRef", () => {
45579
46424
  this.OR([
45580
- { ALT: () => this.CONSUME(Identifier3) },
46425
+ { ALT: () => {
46426
+ this.CONSUME(Identifier3);
46427
+ this.OPTION(() => this.CONSUME(GenericAngle));
46428
+ } },
45581
46429
  { ALT: () => this.CONSUME(QuotedString4) },
45582
46430
  { ALT: () => this.CONSUME(BacktickName) }
45583
46431
  ]);
@@ -45586,14 +46434,15 @@ var init_parser5 = __esm({
45586
46434
  this.OR([
45587
46435
  { ALT: () => this.CONSUME(QuotedString4) },
45588
46436
  { ALT: () => this.CONSUME(Identifier3) },
45589
- { ALT: () => this.CONSUME(NumberLiteral4) }
46437
+ { ALT: () => this.CONSUME(NumberLiteral4) },
46438
+ { ALT: () => this.CONSUME(GenericAngle) }
45590
46439
  ]);
45591
46440
  });
45592
46441
  this.relationStmt = this.RULE("relationStmt", () => {
45593
46442
  this.SUBRULE(this.classRef);
45594
- this.OPTION1(() => this.CONSUME(QuotedString4));
46443
+ this.OPTION1(() => this.CONSUME(QuotedString4, { LABEL: "leftCard" }));
45595
46444
  this.SUBRULE(this.relationOp);
45596
- this.OPTION2(() => this.CONSUME2(QuotedString4));
46445
+ this.OPTION2(() => this.CONSUME2(QuotedString4, { LABEL: "rightCard" }));
45597
46446
  this.SUBRULE2(this.classRef);
45598
46447
  this.OPTION3(() => {
45599
46448
  this.CONSUME(Colon4);
@@ -45730,7 +46579,7 @@ var init_validate4 = __esm({
45730
46579
  function tokenize5(text) {
45731
46580
  return StateLexer.tokenize(text);
45732
46581
  }
45733
- var Identifier4, NumberLiteral5, StateDiagramV2, StateDiagram, StateKw, AsKw2, DirectionKw2, Direction3, NoteKw2, LeftKw, RightKw, OfKw, OverKw, AngleAngleOpen, AngleAngleClose, Dashes, StyleClassDefKw, StyleClassKw, Start, Arrow, InvalidArrow2, Hyphen, LCurly2, RCurly2, Colon5, Comma4, QuotedString5, Comment5, WhiteSpace5, Newline5, LabelChunk, allTokens5, StateLexer;
46582
+ var Identifier4, NumberLiteral5, StateDiagramV2, StateDiagram, StateKw, AsKw2, DirectionKw2, Direction3, NoteKw2, LeftKw, RightKw, OfKw, OverKw, AngleAngleOpen, AngleAngleClose, Dashes, StyleClassDefKw, StyleClassKw, Start, HistoryShallow, HistoryDeep, Arrow, InvalidArrow2, Hyphen, LCurly2, RCurly2, Colon5, Comma4, QuotedString5, Comment5, WhiteSpace5, Newline5, LabelChunk, allTokens5, StateLexer;
45734
46583
  var init_lexer6 = __esm({
45735
46584
  "node_modules/@probelabs/maid/out/diagrams/state/lexer.js"() {
45736
46585
  init_api5();
@@ -45753,6 +46602,8 @@ var init_lexer6 = __esm({
45753
46602
  StyleClassDefKw = createToken({ name: "StyleClassDefKw", pattern: /classDef/, longer_alt: Identifier4 });
45754
46603
  StyleClassKw = createToken({ name: "StyleClassKw", pattern: /class(?!Diagram)/, longer_alt: Identifier4 });
45755
46604
  Start = createToken({ name: "Start", pattern: /\[\*\]/ });
46605
+ HistoryShallow = createToken({ name: "HistoryShallow", pattern: /\[H\]/ });
46606
+ HistoryDeep = createToken({ name: "HistoryDeep", pattern: /\[H\*\]/ });
45756
46607
  Arrow = createToken({ name: "Arrow", pattern: /-->/ });
45757
46608
  InvalidArrow2 = createToken({ name: "InvalidArrow", pattern: /->(?!>)/ });
45758
46609
  Hyphen = createToken({ name: "Hyphen", pattern: /-/ });
@@ -45782,6 +46633,8 @@ var init_lexer6 = __esm({
45782
46633
  AngleAngleOpen,
45783
46634
  AngleAngleClose,
45784
46635
  Start,
46636
+ HistoryDeep,
46637
+ HistoryShallow,
45785
46638
  Arrow,
45786
46639
  InvalidArrow2,
45787
46640
  Dashes,
@@ -45830,8 +46683,7 @@ var init_parser6 = __esm({
45830
46683
  { ALT: () => this.SUBRULE(this.transitionStmt) },
45831
46684
  { ALT: () => this.SUBRULE(this.stateBlock) },
45832
46685
  { ALT: () => this.SUBRULE(this.stateDecl) },
45833
- // Concurrency separator (---) is not supported by mermaid-cli v11; treat as invalid (handled in postLex)
45834
- // { ALT: () => this.CONSUME(t.Dashes) },
46686
+ // '---' only allowed inside state blocks; not at top level
45835
46687
  { ALT: () => this.SUBRULE(this.stateDescriptionStmt) },
45836
46688
  { ALT: () => this.SUBRULE(this.noteStmt) },
45837
46689
  { ALT: () => this.SUBRULE(this.styleStmt) },
@@ -45863,6 +46715,8 @@ var init_parser6 = __esm({
45863
46715
  this.actorRef = this.RULE("actorRef", () => {
45864
46716
  this.OR([
45865
46717
  { ALT: () => this.CONSUME(Start) },
46718
+ { ALT: () => this.CONSUME(HistoryDeep) },
46719
+ { ALT: () => this.CONSUME(HistoryShallow) },
45866
46720
  {
45867
46721
  ALT: () => {
45868
46722
  this.OR2([
@@ -45935,10 +46789,23 @@ var init_parser6 = __esm({
45935
46789
  { ALT: () => this.CONSUME(QuotedString5) }
45936
46790
  ]);
45937
46791
  this.CONSUME(LCurly2);
45938
- this.MANY(() => this.SUBRULE(this.statement));
46792
+ this.MANY(() => this.SUBRULE(this.innerStatement));
45939
46793
  this.CONSUME(RCurly2);
45940
46794
  this.OPTION(() => this.CONSUME(Newline5));
45941
46795
  });
46796
+ this.innerStatement = this.RULE("innerStatement", () => {
46797
+ this.OR([
46798
+ { ALT: () => this.SUBRULE(this.directionStmt) },
46799
+ { ALT: () => this.SUBRULE(this.transitionStmt) },
46800
+ { ALT: () => this.SUBRULE(this.stateBlock) },
46801
+ { ALT: () => this.SUBRULE(this.stateDecl) },
46802
+ { ALT: () => this.CONSUME(Dashes) },
46803
+ { ALT: () => this.SUBRULE(this.stateDescriptionStmt) },
46804
+ { ALT: () => this.SUBRULE(this.noteStmt) },
46805
+ { ALT: () => this.SUBRULE(this.styleStmt) },
46806
+ { ALT: () => this.CONSUME(Newline5) }
46807
+ ]);
46808
+ });
45942
46809
  this.noteStmt = this.RULE("noteStmt", () => {
45943
46810
  this.CONSUME(NoteKw2);
45944
46811
  this.OR([
@@ -46077,6 +46944,72 @@ function validateState(text, _options = {}) {
46077
46944
  errors.push({ line: Math.max(1, lines.length), column: 1, severity: "error", code: "ST-BLOCK-MISSING-RBRACE", message: "Missing '}' to close a state block.", hint: "Close the block: state Foo { ... }" });
46078
46945
  }
46079
46946
  }
46947
+ const stack = [];
46948
+ const pushBlock = (ln) => stack.push({ start: ln, content: [], seps: [] });
46949
+ const top = () => stack[stack.length - 1];
46950
+ for (let i3 = 0; i3 < lines.length; i3++) {
46951
+ const raw = lines[i3] || "";
46952
+ const ln = i3 + 1;
46953
+ if (/^\s*state\b.*\{\s*$/.test(raw)) {
46954
+ pushBlock(ln);
46955
+ continue;
46956
+ }
46957
+ if (/^\s*\}\s*$/.test(raw)) {
46958
+ const blk = stack.pop();
46959
+ if (blk) {
46960
+ const all = [...blk.content.map((l3) => ({ ln: l3, kind: "content" })), ...blk.seps.map((l3) => ({ ln: l3, kind: "sep" }))].sort((a3, b3) => a3.ln - b3.ln);
46961
+ const sepIdxs = all.map((x3, i4) => ({ i: i4, x: x3 })).filter((z3) => z3.x.kind === "sep").map((z3) => z3.i);
46962
+ for (const si of sepIdxs) {
46963
+ const sepLn = all[si].ln;
46964
+ let hasBefore = false;
46965
+ for (let k3 = si - 1; k3 >= 0; k3--) {
46966
+ if (all[k3].kind === "sep")
46967
+ break;
46968
+ if (all[k3].kind === "content") {
46969
+ hasBefore = true;
46970
+ break;
46971
+ }
46972
+ }
46973
+ let hasAfter = false;
46974
+ for (let k3 = si + 1; k3 < all.length; k3++) {
46975
+ if (all[k3].kind === "sep")
46976
+ break;
46977
+ if (all[k3].kind === "content") {
46978
+ hasAfter = true;
46979
+ break;
46980
+ }
46981
+ }
46982
+ if (!hasBefore || !hasAfter) {
46983
+ errors.push({
46984
+ line: sepLn,
46985
+ column: 1,
46986
+ severity: "error",
46987
+ code: "ST-CONCURRENCY-MISPLACED",
46988
+ message: "Concurrency separator '---' must be between regions, not at the start or end of a block.",
46989
+ hint: "Place '---' between two sets of state lines inside the same block."
46990
+ });
46991
+ }
46992
+ }
46993
+ }
46994
+ continue;
46995
+ }
46996
+ if (stack.length > 0) {
46997
+ if (/^\s*---\s*$/.test(raw)) {
46998
+ top().seps.push(ln);
46999
+ if (!has2("ST-CONCURRENCY-UNSUPPORTED", ln)) {
47000
+ errors.push({
47001
+ line: ln,
47002
+ column: 1,
47003
+ severity: "error",
47004
+ code: "ST-CONCURRENCY-UNSUPPORTED",
47005
+ message: "Concurrency separator '---' is not supported by Mermaid CLI in state diagrams.",
47006
+ hint: "Remove '---' or split logic into separate composite states."
47007
+ });
47008
+ }
47009
+ } else if (raw.trim() !== "")
47010
+ top().content.push(ln);
47011
+ }
47012
+ }
46080
47013
  return errors;
46081
47014
  }
46082
47015
  });
@@ -46339,6 +47272,10 @@ function computeFixes(text, errors, level = "safe") {
46339
47272
  edits.push(replaceRange(text, at(e3), e3.length ?? 2, "&quot;"));
46340
47273
  continue;
46341
47274
  }
47275
+ if (is("FL-LABEL-BACKTICK", e3)) {
47276
+ edits.push(replaceRange(text, at(e3), e3.length ?? 1, ""));
47277
+ continue;
47278
+ }
46342
47279
  if (is("FL-LABEL-DOUBLE-IN-DOUBLE", e3)) {
46343
47280
  const lineText = lineTextAt(text, e3.line);
46344
47281
  const caret0 = Math.max(0, e3.column - 1);
@@ -46449,8 +47386,24 @@ function computeFixes(text, errors, level = "safe") {
46449
47386
  continue;
46450
47387
  }
46451
47388
  if (is("FL-LINK-MISSING", e3)) {
46452
- if (level === "all")
46453
- edits.push(insertAt(text, at(e3), " --> "));
47389
+ if (level === "all") {
47390
+ const line = e3.line;
47391
+ const lineText = lineTextAt(text, line);
47392
+ if (!/-->/.test(lineText)) {
47393
+ const shapePart = "(?:\\[[^\\]]*\\]|\\([^\\)]*\\)|\\{[^}]*\\}|\\[\\[[^\\]]*\\]\\]|\\(\\([^\\)]*\\)\\))?";
47394
+ const id = "[A-Za-z0-9_]+";
47395
+ const re = new RegExp(`^\\s*(${id}${shapePart})\\s+(${id})`);
47396
+ const m3 = re.exec(lineText);
47397
+ if (m3) {
47398
+ const before = m3[0];
47399
+ const insertIdx = before.length - m3[2].length;
47400
+ const col = insertIdx + 1;
47401
+ edits.push(insertAt(text, { line, column: col }, " --> "));
47402
+ } else {
47403
+ edits.push(insertAt(text, at(e3), " --> "));
47404
+ }
47405
+ }
47406
+ }
46454
47407
  continue;
46455
47408
  }
46456
47409
  if (is("FL-NODE-UNCLOSED-BRACKET", e3)) {
@@ -47069,9 +48022,13 @@ var init_graph_builder = __esm({
47069
48022
  this.edgeCounter = 0;
47070
48023
  this.subgraphs = [];
47071
48024
  this.currentSubgraphStack = [];
48025
+ this.pendingLinkStyles = [];
47072
48026
  this.classStyles = /* @__PURE__ */ new Map();
47073
48027
  this.nodeStyles = /* @__PURE__ */ new Map();
47074
48028
  this.nodeClasses = /* @__PURE__ */ new Map();
48029
+ this.edgeClasses = /* @__PURE__ */ new Map();
48030
+ this.edgeStyles = /* @__PURE__ */ new Map();
48031
+ this.nodeLinks = /* @__PURE__ */ new Map();
47075
48032
  }
47076
48033
  build(cst) {
47077
48034
  this.reset();
@@ -47085,6 +48042,11 @@ var init_graph_builder = __esm({
47085
48042
  }
47086
48043
  const direction = this.extractDirection(cst);
47087
48044
  this.processStatements(cst);
48045
+ for (const [id, link] of this.nodeLinks.entries()) {
48046
+ const node = this.nodes.get(id);
48047
+ if (node)
48048
+ node.link = link;
48049
+ }
47088
48050
  return {
47089
48051
  nodes: Array.from(this.nodes.values()),
47090
48052
  edges: this.edges,
@@ -47102,6 +48064,10 @@ var init_graph_builder = __esm({
47102
48064
  this.classStyles.clear();
47103
48065
  this.nodeStyles.clear();
47104
48066
  this.nodeClasses.clear();
48067
+ this.edgeClasses.clear();
48068
+ this.edgeStyles.clear();
48069
+ this.pendingLinkStyles = [];
48070
+ this.nodeLinks.clear();
47105
48071
  }
47106
48072
  extractDirection(cst) {
47107
48073
  const dirToken = cst.children?.Direction?.[0];
@@ -47135,14 +48101,100 @@ var init_graph_builder = __esm({
47135
48101
  this.processClassAssign(stmt.children.classStatement[0]);
47136
48102
  } else if (stmt.children?.styleStatement) {
47137
48103
  this.processStyle(stmt.children.styleStatement[0]);
48104
+ } else if (stmt.children?.linkStyleStatement) {
48105
+ this.processLinkStyle(stmt.children.linkStyleStatement[0]);
48106
+ } else if (stmt.children?.clickStatement) {
48107
+ this.processClick(stmt.children.clickStatement[0]);
48108
+ } else if (stmt.children?.edgeAttrStatement) {
48109
+ this.processEdgeAttr(stmt.children.edgeAttrStatement[0]);
47138
48110
  }
47139
48111
  }
48112
+ this.applyLinkStyles();
48113
+ }
48114
+ unquote(s3) {
48115
+ if (!s3)
48116
+ return s3;
48117
+ if (s3.startsWith('"') && s3.endsWith('"') || s3.startsWith("'") && s3.endsWith("'"))
48118
+ return s3.slice(1, -1);
48119
+ return s3;
48120
+ }
48121
+ processClick(cst) {
48122
+ const ch = cst.children || {};
48123
+ const tgtTok = ch.clickTarget?.[0];
48124
+ if (!tgtTok)
48125
+ return;
48126
+ const id = tgtTok.image;
48127
+ const link = {};
48128
+ if (ch.clickHref && ch.clickHref[0]) {
48129
+ const hrefCh = ch.clickHref[0].children || {};
48130
+ if (hrefCh.url && hrefCh.url[0])
48131
+ link.href = this.unquote(hrefCh.url[0].image);
48132
+ if (hrefCh.tooltip && hrefCh.tooltip[0])
48133
+ link.tooltip = this.unquote(hrefCh.tooltip[0].image);
48134
+ if (hrefCh.target && hrefCh.target[0])
48135
+ link.target = hrefCh.target[0].image;
48136
+ } else if (ch.clickCall && ch.clickCall[0]) {
48137
+ const callCh = ch.clickCall[0].children || {};
48138
+ if (callCh.fn && callCh.fn[0])
48139
+ link.call = callCh.fn[0].image;
48140
+ if (callCh.tooltip && callCh.tooltip[0])
48141
+ link.tooltip = this.unquote(callCh.tooltip[0].image);
48142
+ } else {
48143
+ const idents = ch.Identifier || [];
48144
+ const texts = ch.Text || [];
48145
+ const quotes = ch.QuotedString || [];
48146
+ const modeTok = idents.find((t3) => /^(href|call|callback)$/i.test(t3.image));
48147
+ const mode = modeTok?.image?.toLowerCase();
48148
+ if (mode === "href") {
48149
+ const urlTok = quotes[0];
48150
+ const tipTok = quotes[1];
48151
+ const targetTok = idents.find((t3) => /^_(blank|self|parent|top)$/i.test(t3.image));
48152
+ if (urlTok)
48153
+ link.href = this.unquote(urlTok.image);
48154
+ if (tipTok)
48155
+ link.tooltip = this.unquote(tipTok.image);
48156
+ if (targetTok)
48157
+ link.target = targetTok.image;
48158
+ } else if (mode === "call" || mode === "callback") {
48159
+ const reserved = /* @__PURE__ */ new Set(["href", "call", "callback", "_blank", "_self", "_parent", "_top"]);
48160
+ const after = idents.filter((t3) => (t3.startOffset ?? 0) > (modeTok?.startOffset ?? -1));
48161
+ const nameTok = after.find((t3) => !reserved.has(t3.image.toLowerCase()));
48162
+ const tstr = texts.map((t3) => t3.image).join(" ").trim();
48163
+ link.call = nameTok ? nameTok.image + (tstr ? ` ${tstr}` : "") : tstr || void 0;
48164
+ const tipTok = quotes[0];
48165
+ if (tipTok)
48166
+ link.tooltip = this.unquote(tipTok.image);
48167
+ }
48168
+ }
48169
+ if (Object.keys(link).length)
48170
+ this.nodeLinks.set(id, { ...this.nodeLinks.get(id) || {}, ...link });
47140
48171
  }
47141
48172
  processNodeStatement(stmt) {
47142
48173
  const groups = stmt.children?.nodeOrParallelGroup;
47143
48174
  const links = stmt.children?.link;
47144
48175
  if (!groups || groups.length === 0)
47145
48176
  return;
48177
+ if ((!links || links.length === 0) && groups.length === 1) {
48178
+ const g0 = groups[0];
48179
+ const nodes = g0.children?.node || [];
48180
+ if (nodes.length === 1) {
48181
+ const n3 = nodes[0];
48182
+ const hasAttr = !!(n3.children.attrObject && n3.children.attrObject.length);
48183
+ const hasShape = !!n3.children?.nodeShape;
48184
+ if (hasAttr && !hasShape) {
48185
+ const idTok = n3.children.nodeId?.[0] || n3.children.Identifier?.[0] || void 0;
48186
+ if (idTok) {
48187
+ const id = idTok.image;
48188
+ const exists = this.edges.some((e3) => e3.id === id);
48189
+ if (exists) {
48190
+ const edgeAttrFake = { children: { edgeId: [{ image: id }], attrObject: n3.children.attrObject } };
48191
+ this.processEdgeAttr(edgeAttrFake);
48192
+ return;
48193
+ }
48194
+ }
48195
+ }
48196
+ }
48197
+ }
47146
48198
  const sourceNodes = this.processNodeGroup(groups[0]);
47147
48199
  if (groups.length > 1 && links && links.length > 0) {
47148
48200
  const targetNodes = this.processNodeGroup(groups[1]);
@@ -47150,7 +48202,7 @@ var init_graph_builder = __esm({
47150
48202
  for (const source of sourceNodes) {
47151
48203
  for (const target of targetNodes) {
47152
48204
  this.edges.push({
47153
- id: `e${this.edgeCounter++}`,
48205
+ id: linkInfo.edgeId || `e${this.edgeCounter++}`,
47154
48206
  source,
47155
48207
  target,
47156
48208
  label: linkInfo.label,
@@ -47166,7 +48218,7 @@ var init_graph_builder = __esm({
47166
48218
  for (const source of targetNodes) {
47167
48219
  for (const target of nextNodes) {
47168
48220
  this.edges.push({
47169
- id: `e${this.edgeCounter++}`,
48221
+ id: nextLink.edgeId || `e${this.edgeCounter++}`,
47170
48222
  source,
47171
48223
  target,
47172
48224
  label: nextLink.label,
@@ -47249,13 +48301,101 @@ var init_graph_builder = __esm({
47249
48301
  if (result.label)
47250
48302
  label = result.label;
47251
48303
  }
48304
+ const attrNode = children.attrObject?.[0];
48305
+ let typedShape;
48306
+ if (attrNode && !shapeNode) {
48307
+ typedShape = this.parseTypedAttrObject(attrNode);
48308
+ if (typedShape.shape) {
48309
+ const m3 = typedShape.shape;
48310
+ if (m3 === "rect")
48311
+ shape = "rectangle";
48312
+ else if (m3 === "round" || m3 === "rounded")
48313
+ shape = "round";
48314
+ else if (m3 === "stadium")
48315
+ shape = "stadium";
48316
+ else if (m3 === "subroutine")
48317
+ shape = "subroutine";
48318
+ else if (m3 === "circle")
48319
+ shape = "circle";
48320
+ else if (m3 === "cylinder")
48321
+ shape = "cylinder";
48322
+ else if (m3 === "diamond")
48323
+ shape = "diamond";
48324
+ else if (m3 === "trapezoid")
48325
+ shape = "trapezoid";
48326
+ else if (m3 === "trapezoidAlt")
48327
+ shape = "trapezoidAlt";
48328
+ else if (m3 === "parallelogram" || m3 === "lean-l" || m3 === "lean-r") {
48329
+ shape = "parallelogram";
48330
+ typedShape.lean = m3 === "lean-l" ? "l" : m3 === "lean-r" ? "r" : void 0;
48331
+ } else if (m3 === "hexagon")
48332
+ shape = "hexagon";
48333
+ else if (m3 === "icon" || m3 === "image")
48334
+ shape = "rectangle";
48335
+ }
48336
+ if (typeof typedShape.label === "string" && typedShape.label.length > 0) {
48337
+ label = typedShape.label;
48338
+ }
48339
+ }
47252
48340
  const clsTok = children.nodeClass?.[0];
47253
48341
  if (clsTok) {
47254
48342
  const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
47255
48343
  set.add(clsTok.image);
47256
48344
  this.nodeClasses.set(id, set);
47257
48345
  }
47258
- return { id, label, shape };
48346
+ const out = { id, label, shape };
48347
+ if (typedShape) {
48348
+ const padding = typedShape.padding;
48349
+ const cornerRadius = typedShape.cornerRadius;
48350
+ const lean = typedShape.lean;
48351
+ const media = typedShape.icon || typedShape.image ? { icon: typedShape.icon, image: typedShape.image } : void 0;
48352
+ out.typed = { padding, cornerRadius, lean, media };
48353
+ }
48354
+ return out;
48355
+ }
48356
+ parseTypedAttrObject(attrNode) {
48357
+ const ch = attrNode.children || {};
48358
+ const pairs = ch.attrPair || [];
48359
+ const out = {};
48360
+ for (const p3 of pairs) {
48361
+ const keyTok = p3.children?.attrKey?.[0];
48362
+ if (!keyTok)
48363
+ continue;
48364
+ const k3 = keyTok.image;
48365
+ const vTok = p3.children?.QuotedString?.[0] || p3.children?.Identifier?.[0] || p3.children?.NumberLiteral?.[0] || p3.children?.Text?.[0];
48366
+ if (!vTok)
48367
+ continue;
48368
+ let raw = vTok.image;
48369
+ if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'"))
48370
+ raw = raw.slice(1, -1);
48371
+ switch (k3) {
48372
+ case "shape":
48373
+ out.shape = raw;
48374
+ break;
48375
+ case "label":
48376
+ out.label = raw;
48377
+ break;
48378
+ case "padding": {
48379
+ const n3 = parseFloat(raw);
48380
+ if (Number.isFinite(n3))
48381
+ out.padding = n3;
48382
+ break;
48383
+ }
48384
+ case "cornerRadius": {
48385
+ const n3 = parseFloat(raw);
48386
+ if (Number.isFinite(n3))
48387
+ out.cornerRadius = n3;
48388
+ break;
48389
+ }
48390
+ case "icon":
48391
+ out.icon = raw;
48392
+ break;
48393
+ case "image":
48394
+ out.image = raw;
48395
+ break;
48396
+ }
48397
+ }
48398
+ return out;
47259
48399
  }
47260
48400
  extractShapeAndLabel(shapeNode) {
47261
48401
  const children = shapeNode.children;
@@ -47374,6 +48514,7 @@ var init_graph_builder = __esm({
47374
48514
  let label;
47375
48515
  let markerStart = "none";
47376
48516
  let markerEnd = "none";
48517
+ const eidTok = children.edgeId?.[0];
47377
48518
  if (children.BiDirectionalArrow) {
47378
48519
  type = "arrow";
47379
48520
  markerStart = "arrow";
@@ -47448,7 +48589,7 @@ var init_graph_builder = __esm({
47448
48589
  };
47449
48590
  label = strip(raw);
47450
48591
  }
47451
- return { type, label, markerStart, markerEnd };
48592
+ return { type, label, markerStart, markerEnd, edgeId: eidTok ? eidTok.image : void 0 };
47452
48593
  }
47453
48594
  processSubgraph(subgraph) {
47454
48595
  const children = subgraph.children;
@@ -47511,12 +48652,15 @@ var init_graph_builder = __esm({
47511
48652
  return;
47512
48653
  const classNameTok = cst.children.className?.[0];
47513
48654
  const className = classNameTok?.image || ids[ids.length - 1].image;
47514
- const nodeIds = classNameTok ? ids.slice(0, -1) : ids.slice(0, -1);
47515
- for (const tok of nodeIds) {
48655
+ const targetIds = classNameTok ? ids.slice(0, -1) : ids.slice(0, -1);
48656
+ for (const tok of targetIds) {
47516
48657
  const id = tok.image;
47517
- const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
47518
- set.add(className);
47519
- this.nodeClasses.set(id, set);
48658
+ const nset = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
48659
+ nset.add(className);
48660
+ this.nodeClasses.set(id, nset);
48661
+ const eset = this.edgeClasses.get(id) || /* @__PURE__ */ new Set();
48662
+ eset.add(className);
48663
+ this.edgeClasses.set(id, eset);
47520
48664
  const node = this.nodes.get(id);
47521
48665
  if (node) {
47522
48666
  node.style = { ...node.style || {}, ...this.computeNodeStyle(id) };
@@ -47562,6 +48706,121 @@ var init_graph_builder = __esm({
47562
48706
  }
47563
48707
  return props;
47564
48708
  }
48709
+ processEdgeAttr(cst) {
48710
+ const eidTok = cst.children.edgeId?.[0];
48711
+ if (!eidTok)
48712
+ return;
48713
+ const id = eidTok.image;
48714
+ const attrNode = cst.children.attrObject?.[0];
48715
+ if (!attrNode)
48716
+ return;
48717
+ const ch = attrNode.children || {};
48718
+ const pairs = ch.attrPair || [];
48719
+ const props = {};
48720
+ for (const p3 of pairs) {
48721
+ const keyTok = p3.children.attrKey?.[0];
48722
+ const vTok = p3.children.QuotedString?.[0] || p3.children.Identifier?.[0] || p3.children.NumberLiteral?.[0] || p3.children.Text?.[0];
48723
+ if (!keyTok || !vTok)
48724
+ continue;
48725
+ let val = vTok.image;
48726
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'"))
48727
+ val = val.slice(1, -1);
48728
+ const k3 = keyTok.image;
48729
+ if (k3 === "animate") {
48730
+ const truthy = /^(true|1|yes|on|fast|slow)$/i.test(val);
48731
+ if (truthy) {
48732
+ props["animation"] = /^slow$/i.test(val) ? "dash 8s linear infinite" : /^fast$/i.test(val) ? "dash 2s linear infinite" : "dash 4s linear infinite";
48733
+ if (!props["stroke-dasharray"])
48734
+ props["stroke-dasharray"] = "5 5";
48735
+ }
48736
+ } else {
48737
+ props[k3] = val;
48738
+ }
48739
+ }
48740
+ const cur = this.edgeStyles.get(id) || {};
48741
+ this.edgeStyles.set(id, { ...cur, ...props });
48742
+ }
48743
+ computeEdgeStyle(edgeId) {
48744
+ const out = {};
48745
+ const classes = this.edgeClasses.get(edgeId);
48746
+ if (classes) {
48747
+ for (const c3 of classes) {
48748
+ const s3 = this.classStyles.get(c3);
48749
+ if (s3)
48750
+ Object.assign(out, this.normalizeStyle(s3));
48751
+ }
48752
+ }
48753
+ const direct = this.edgeStyles.get(edgeId);
48754
+ if (direct)
48755
+ Object.assign(out, this.normalizeStyle(direct));
48756
+ return out;
48757
+ }
48758
+ processLinkStyle(cst) {
48759
+ const ch = cst.children || {};
48760
+ if (ch.linkStyleIndexList && ch.linkStylePairs) {
48761
+ const idxNode = ch.linkStyleIndexList[0];
48762
+ const pairNode = ch.linkStylePairs[0];
48763
+ const idxToks = (idxNode.children || {}).index || [];
48764
+ const indices2 = idxToks.map((t3) => parseInt(t3.image, 10)).filter((n3) => Number.isFinite(n3));
48765
+ const pairs = (pairNode.children || {}).linkStylePair || [];
48766
+ const props2 = {};
48767
+ for (const p3 of pairs) {
48768
+ const pch = p3.children || {};
48769
+ const keyTok = pch.key?.[0];
48770
+ const vTok = pch.valueColor?.[0] || pch.valueQuoted?.[0] || pch.valueNum?.[0] || pch.valueId?.[0] || pch.valueText?.[0];
48771
+ if (!keyTok || !vTok)
48772
+ continue;
48773
+ let val = vTok.image;
48774
+ if (vTok.tokenType?.name === "QuotedString" && (val.startsWith('"') || val.startsWith("'"))) {
48775
+ val = val.slice(1, -1);
48776
+ }
48777
+ props2[keyTok.image] = val;
48778
+ }
48779
+ this.pendingLinkStyles.push({ indices: indices2, props: props2 });
48780
+ return;
48781
+ }
48782
+ const nums = cst.children?.NumberLiteral || [];
48783
+ const indices = nums.map((n3) => parseInt(n3.image, 10)).filter((n3) => Number.isFinite(n3));
48784
+ const props = this.collectStyleProps(cst);
48785
+ this.pendingLinkStyles.push({ indices, props });
48786
+ }
48787
+ applyLinkStyles() {
48788
+ if (!this.pendingLinkStyles.length || !this.edges.length)
48789
+ return;
48790
+ const normalize = (s3) => {
48791
+ const out = {};
48792
+ for (const [kRaw, vRaw] of Object.entries(s3)) {
48793
+ const k3 = kRaw.trim().toLowerCase();
48794
+ const v3 = vRaw.trim();
48795
+ if (k3 === "stroke")
48796
+ out.stroke = v3;
48797
+ else if (k3 === "stroke-width") {
48798
+ const num = parseFloat(v3);
48799
+ if (!Number.isNaN(num))
48800
+ out.strokeWidth = num;
48801
+ } else if (k3 === "opacity" || k3 === "stroke-opacity") {
48802
+ const num = parseFloat(v3);
48803
+ if (!Number.isNaN(num))
48804
+ out.strokeOpacity = num;
48805
+ } else if (k3 === "stroke-dasharray")
48806
+ out.dasharray = v3;
48807
+ }
48808
+ return out;
48809
+ };
48810
+ for (const cmd of this.pendingLinkStyles) {
48811
+ const style = normalize(cmd.props);
48812
+ for (const idx of cmd.indices) {
48813
+ if (idx >= 0 && idx < this.edges.length) {
48814
+ const e3 = this.edges[idx];
48815
+ e3.style = { ...e3.style || {}, stroke: style.stroke ?? e3.style?.stroke, strokeWidth: style.strokeWidth ?? e3.style?.strokeWidth, strokeOpacity: style.strokeOpacity ?? e3.style?.strokeOpacity };
48816
+ if (style.dasharray)
48817
+ e3.dasharray = style.dasharray;
48818
+ if (style.animation)
48819
+ e3.animation = style.animation;
48820
+ }
48821
+ }
48822
+ }
48823
+ }
47565
48824
  computeNodeStyle(nodeId) {
47566
48825
  const out = {};
47567
48826
  const classes = this.nodeClasses.get(nodeId);
@@ -55313,8 +56572,10 @@ var init_layout = __esm({
55313
56572
  marginy: 20
55314
56573
  };
55315
56574
  if (hasClusters && (dir === "LR" || dir === "RL")) {
55316
- graphConfig.ranker = "longest-path";
56575
+ graphConfig.ranker = "network-simplex";
55317
56576
  graphConfig.acyclicer = "greedy";
56577
+ nodesep += 40;
56578
+ ranksep = Math.max(30, ranksep - 20);
55318
56579
  }
55319
56580
  if (hasClusters) {
55320
56581
  graphConfig.compound = true;
@@ -55327,7 +56588,9 @@ var init_layout = __esm({
55327
56588
  }
55328
56589
  }
55329
56590
  for (const node of graph.nodes) {
55330
- const dimensions = this.calculateNodeDimensions(node.label, node.shape);
56591
+ const providedW = node.width;
56592
+ const providedH = node.height;
56593
+ const dimensions = providedW && providedH ? { width: providedW, height: providedH } : this.calculateNodeDimensions(node.label, node.shape);
55331
56594
  g3.setNode(node.id, {
55332
56595
  width: dimensions.width,
55333
56596
  height: dimensions.height,
@@ -55451,7 +56714,7 @@ var init_layout = __esm({
55451
56714
  const inX = end.x + (rankdir === "LR" ? -PAD : PAD);
55452
56715
  const startOut = { x: srcSg ? outX : start.x, y: start.y };
55453
56716
  const endPre = { x: dstSg ? inX : end.x, y: end.y };
55454
- const alpha = 0.68;
56717
+ const alpha = 0.72;
55455
56718
  const midX = startOut.x + (endPre.x - startOut.x) * alpha;
55456
56719
  const m1 = { x: midX, y: startOut.y };
55457
56720
  const m22 = { x: midX, y: endPre.y };
@@ -55648,6 +56911,11 @@ function buildSharedCss(opts = {}) {
55648
56911
  .edge-path { stroke: ${edgeStroke}; stroke-width: 2px; fill: none; }
55649
56912
  .edge-label-bg { fill: rgba(232,232,232, 0.8); opacity: 0.5; }
55650
56913
  .edge-label-text { fill: #333; font-family: ${fontFamily}; font-size: ${Math.max(10, fontSize - 2)}px; }
56914
+ .edge-marker { stroke: ${edgeStroke}; }
56915
+ .edge-marker-fill { fill: ${edgeStroke}; }
56916
+
56917
+ /* Basic stroke dash animation used by flowchart link animation presets */
56918
+ @keyframes dash { to { stroke-dashoffset: -1000; } }
55651
56919
 
55652
56920
  /* Cluster (flowchart + sequence blocks) */
55653
56921
  .cluster-bg { fill: #ffffde; }
@@ -55662,15 +56930,77 @@ function buildSharedCss(opts = {}) {
55662
56930
  /* Sequence-specific add-ons (safe for flowcharts too) */
55663
56931
  .actor-rect { fill: #eaeaea; stroke: #666; stroke-width: 1.5px; }
55664
56932
  .actor-label { fill: #111; font-family: ${fontFamily}; font-size: 16px; }
55665
- .lifeline { stroke: #999; stroke-width: 0.5px; }
56933
+ .lifeline { stroke: #999; stroke-width: 1px; }
55666
56934
  .activation { fill: #f4f4f4; stroke: #666; stroke-width: 1px; }
55667
56935
  .msg-line { stroke: #333; stroke-width: 1.5px; fill: none; }
55668
56936
  .msg-line.dotted { stroke-dasharray: 2 2; }
55669
56937
  .msg-line.thick { stroke-width: 3px; }
56938
+ .openhead { fill: none; stroke: #333; stroke-width: 1.5px; }
56939
+ .crosshead path { stroke: #333; stroke-width: 1.5px; }
55670
56940
  .msg-label { fill: #333; font-family: ${fontFamily}; font-size: 12px; dominant-baseline: middle; }
55671
56941
  .msg-label-bg { fill: #ffffff; stroke: #cccccc; stroke-width: 1px; rx: 3; }
56942
+
56943
+ /* State overlays */
56944
+ .lane-divider { stroke: #aaaaaa; stroke-width: 1px; stroke-dasharray: 4 3; }
56945
+ .end-double { stroke: #3f3f3f; stroke-width: 1px; fill: none; }
55672
56946
  `;
55673
56947
  }
56948
+ function applyFlowLikeTheme(svg, theme) {
56949
+ if (!theme)
56950
+ return svg;
56951
+ let out = svg;
56952
+ if (theme.nodeBkg || theme.nodeBorder) {
56953
+ out = out.replace(/\.node-shape\s*\{[^}]*\}/, (m3) => {
56954
+ let rule = m3;
56955
+ if (theme.nodeBkg)
56956
+ rule = rule.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeBkg)};`);
56957
+ if (theme.nodeBorder)
56958
+ rule = rule.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.nodeBorder)};`);
56959
+ return rule;
56960
+ });
56961
+ }
56962
+ if (theme.nodeTextColor) {
56963
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeTextColor)};`));
56964
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeTextColor)};`));
56965
+ }
56966
+ if (theme.edgeLabelTextColor) {
56967
+ const c3 = String(theme.edgeLabelTextColor);
56968
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
56969
+ }
56970
+ if (theme.lineColor) {
56971
+ out = out.replace(/\.edge-path\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
56972
+ }
56973
+ if (theme.arrowheadColor) {
56974
+ out = out.replace(/\.edge-marker\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
56975
+ out = out.replace(/\.edge-marker-fill\s*\{[^}]*\}/, (m3) => m3.includes("fill:") ? m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.arrowheadColor)};`) : m3.replace(/\}/, ` fill: ${String(theme.arrowheadColor)}; }`));
56976
+ out = out.replace(/\.openhead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
56977
+ out = out.replace(/\.crosshead path\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
56978
+ }
56979
+ if (theme.clusterBkg)
56980
+ out = out.replace(/\.cluster-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterBkg)};`));
56981
+ if (theme.clusterBorder)
56982
+ out = out.replace(/\.cluster-border\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.clusterBorder)};`));
56983
+ if (theme.clusterTextColor)
56984
+ out = out.replace(/\.cluster-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterTextColor)};`));
56985
+ if (theme.clusterTitleBg || theme.clusterTitleBackground) {
56986
+ const c3 = String(theme.clusterTitleBg || theme.clusterTitleBackground);
56987
+ out = out.replace(/\.cluster-title-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
56988
+ }
56989
+ if (theme.fontFamily) {
56990
+ const f3 = String(theme.fontFamily);
56991
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
56992
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
56993
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
56994
+ }
56995
+ if (theme.fontSize) {
56996
+ const s3 = String(theme.fontSize);
56997
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${s3}px;`));
56998
+ const sub = Math.max(10, Number(theme.fontSize) - 2);
56999
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${sub}px;`));
57000
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${sub}px;`));
57001
+ }
57002
+ return out;
57003
+ }
55674
57004
  var init_styles = __esm({
55675
57005
  "node_modules/@probelabs/maid/out/renderer/styles.js"() {
55676
57006
  }
@@ -55854,6 +57184,8 @@ var init_svg_generator = __esm({
55854
57184
  };
55855
57185
  const bgs = [];
55856
57186
  for (const sg of order) {
57187
+ if (sg.id && sg.id.includes("__lane"))
57188
+ continue;
55857
57189
  const x3 = sg.x + padX;
55858
57190
  const y2 = sg.y + padY;
55859
57191
  bgs.push(blockBackground(x3, y2, sg.width, sg.height, 0));
@@ -55891,7 +57223,7 @@ var init_svg_generator = __esm({
55891
57223
  edgeStroke: this.arrowStroke
55892
57224
  });
55893
57225
  const css = `<style>${sharedCss}</style>`;
55894
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
57226
+ return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
55895
57227
  ${bg}
55896
57228
  ${css}
55897
57229
  ${elements.join("\n ")}
@@ -55944,13 +57276,17 @@ var init_svg_generator = __esm({
55944
57276
  const stroke = node.style?.stroke ?? void 0;
55945
57277
  const fill = node.style?.fill ?? void 0;
55946
57278
  const styleAttr = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
57279
+ const typed = node.typed;
57280
+ const innerPad = Math.max(0, typed?.padding ?? 10);
55947
57281
  switch (node.shape) {
55948
57282
  case "rectangle":
55949
57283
  shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
55950
57284
  break;
55951
- case "round":
55952
- shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="5" ry="5" />`;
57285
+ case "round": {
57286
+ const rx = Math.max(0, typed?.cornerRadius ?? 5);
57287
+ shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="${rx}" ry="${rx}" />`;
55953
57288
  break;
57289
+ }
55954
57290
  case "stadium":
55955
57291
  const radius = node.height / 2;
55956
57292
  shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="${radius}" ry="${radius}" />`;
@@ -55994,16 +57330,18 @@ var init_svg_generator = __esm({
55994
57330
  }
55995
57331
  case "parallelogram": {
55996
57332
  const skew = node.width * 0.15;
55997
- const points = [
57333
+ const leftLean = typed?.lean === "l";
57334
+ const points = (leftLean ? [
57335
+ `${x3},${y2}`,
57336
+ `${x3 + node.width - skew},${y2}`,
57337
+ `${x3 + node.width},${y2 + node.height}`,
57338
+ `${x3 + skew},${y2 + node.height}`
57339
+ ] : [
55998
57340
  `${x3 + skew},${y2}`,
55999
- // top-left
56000
57341
  `${x3 + node.width},${y2}`,
56001
- // top-right
56002
57342
  `${x3 + node.width - skew},${y2 + node.height}`,
56003
- // bottom-right
56004
57343
  `${x3},${y2 + node.height}`
56005
- // bottom-left
56006
- ].join(" ");
57344
+ ]).join(" ");
56007
57345
  shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
56008
57346
  break;
56009
57347
  }
@@ -56073,11 +57411,33 @@ var init_svg_generator = __esm({
56073
57411
  const s3 = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
56074
57412
  shape = `<rect ${s3} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
56075
57413
  }
56076
- const text = this.generateWrappedText(node.label, cx, labelCenterY, node.width - 20);
56077
- return `<g id="${node.id}">
57414
+ const text = this.generateWrappedText(node.label, cx, labelCenterY, node.width - innerPad * 2);
57415
+ let media = "";
57416
+ if (typed?.media?.image) {
57417
+ const iw = Math.min(24, Math.max(12, node.height - 10));
57418
+ const ih = iw;
57419
+ const ix = x3 + 4;
57420
+ const iy = y2 + (node.height - ih) / 2;
57421
+ media = `<image xlink:href="${this.escapeXml(typed.media.image)}" x="${ix}" y="${iy}" width="${iw}" height="${ih}" />`;
57422
+ }
57423
+ const baseGroup = `<g id="${node.id}">
56078
57424
  ${shape}
57425
+ ${media}
56079
57426
  ${text}
56080
57427
  </g>`;
57428
+ const link = node.link;
57429
+ if (link && link.href) {
57430
+ const tt = link.tooltip ? `<title>${this.escapeXml(link.tooltip)}</title>` : "";
57431
+ const tgt = link.target ? ` target="${this.escapeXml(link.target)}" rel="noopener noreferrer"` : "";
57432
+ return `<a xlink:href="${this.escapeXml(link.href)}"${tgt} class="node-link">${tt}${baseGroup}</a>`;
57433
+ }
57434
+ if (link && link.tooltip) {
57435
+ return `<g class="node-call">
57436
+ <title>${this.escapeXml(link.tooltip)}</title>
57437
+ ${baseGroup}
57438
+ </g>`;
57439
+ }
57440
+ return baseGroup;
56081
57441
  }
56082
57442
  generateWrappedText(text, x3, y2, maxWidth) {
56083
57443
  if (text.includes("<")) {
@@ -56315,16 +57675,31 @@ var init_svg_generator = __esm({
56315
57675
  }
56316
57676
  const pathData = pathParts.join(" ");
56317
57677
  let edgeElement = `<path class="edge-path" d="${pathData}" stroke-linecap="round" stroke-linejoin="round"`;
57678
+ const styleStroke = edge.style?.stroke;
57679
+ const styleStrokeWidth = edge.style?.strokeWidth;
57680
+ const styleStrokeOpacity = edge.style?.strokeOpacity;
57681
+ if (edge.dasharray)
57682
+ strokeDasharray = String(edge.dasharray);
57683
+ const anim = edge.animation;
57684
+ if (!strokeDasharray && anim)
57685
+ strokeDasharray = "5 5";
56318
57686
  if (strokeDasharray) {
56319
57687
  edgeElement += ` stroke-dasharray="${strokeDasharray}"`;
56320
57688
  }
56321
- const startMarkUrl = mStart === "arrow" ? "url(#arrow)" : mStart === "circle" ? "url(#circle-marker)" : mStart === "cross" ? "url(#cross-marker)" : "";
56322
- const endMarkUrl = mEnd === "arrow" ? "url(#arrow)" : mEnd === "circle" ? "url(#circle-marker)" : mEnd === "cross" ? "url(#cross-marker)" : markerEnd || "";
56323
- if (startMarkUrl && mStart !== "arrow")
56324
- edgeElement += ` marker-start="${startMarkUrl}"`;
56325
- if (endMarkUrl && mEnd !== "arrow")
56326
- edgeElement += ` marker-end="${endMarkUrl}"`;
56327
- edgeElement += " />";
57689
+ if (styleStrokeWidth != null) {
57690
+ edgeElement += ` stroke-width="${styleStrokeWidth}"`;
57691
+ } else {
57692
+ if (strokeWidth && strokeWidth !== 1.5)
57693
+ edgeElement += ` stroke-width="${strokeWidth}"`;
57694
+ }
57695
+ if (styleStrokeOpacity != null) {
57696
+ edgeElement += ` stroke-opacity="${styleStrokeOpacity}"`;
57697
+ }
57698
+ if (styleStroke) {
57699
+ edgeElement += ` stroke="${styleStroke}"`;
57700
+ }
57701
+ const inlineAnim = anim ? ` style="animation:${anim}"` : "";
57702
+ edgeElement += inlineAnim + " />";
56328
57703
  if (edge.label) {
56329
57704
  const pos = this.pointAtRatio(points, 0.55);
56330
57705
  const text = this.escapeXml(edge.label);
@@ -56345,14 +57720,15 @@ var init_svg_generator = __esm({
56345
57720
  const uyl = vyl / vlenl;
56346
57721
  const nxl = -uyl;
56347
57722
  const nyl = uxl;
56348
- const triLenL = 8;
56349
- const triWL = 6;
57723
+ const ow = styleStrokeWidth != null ? styleStrokeWidth : strokeWidth;
57724
+ const triLenL = Math.max(6, Math.min(14, 6 + (ow - 1.5) * 3));
57725
+ const triWL = Math.max(5, Math.min(12, 5 + (ow - 1.5) * 2.5));
56350
57726
  const p1xL = boundaryEnd.x, p1yL = boundaryEnd.y;
56351
57727
  const baseXL = boundaryEnd.x - uxl * triLenL;
56352
57728
  const baseYL = boundaryEnd.y - uyl * triLenL;
56353
57729
  const p2xL = baseXL + nxl * (triWL / 2), p2yL = baseYL + nyl * (triWL / 2);
56354
57730
  const p3xL = baseXL - nxl * (triWL / 2), p3yL = baseYL - nyl * (triWL / 2);
56355
- overlay2 += triangleAtEnd(prevEndL, boundaryEnd, this.arrowStroke);
57731
+ overlay2 += triangleAtEnd(prevEndL, boundaryEnd, styleStroke || this.arrowStroke, triLenL, triWL);
56356
57732
  if (mStart === "arrow" && points.length >= 2) {
56357
57733
  const firstLeg = points[1];
56358
57734
  const svx = boundaryStart.x - firstLeg.x;
@@ -56364,7 +57740,7 @@ var init_svg_generator = __esm({
56364
57740
  const sny = sux;
56365
57741
  const sbaseX = boundaryStart.x - sux * triLenL;
56366
57742
  const sbaseY = boundaryStart.y - suy * triLenL;
56367
- overlay2 += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
57743
+ overlay2 += triangleAtStart(boundaryStart, firstLeg, styleStroke || this.arrowStroke, triLenL, triWL);
56368
57744
  }
56369
57745
  const pathGroup = `<g>
56370
57746
  ${edgeElement}
@@ -56383,15 +57759,16 @@ var init_svg_generator = __esm({
56383
57759
  const uy = vy / vlen;
56384
57760
  const nx = -uy;
56385
57761
  const ny = ux;
56386
- const triLen = 8;
56387
- const triW = 6;
57762
+ const ow2 = styleStrokeWidth != null ? styleStrokeWidth : strokeWidth;
57763
+ const triLen = Math.max(6, Math.min(14, 6 + (ow2 - 1.5) * 3));
57764
+ const triW = Math.max(5, Math.min(12, 5 + (ow2 - 1.5) * 2.5));
56388
57765
  const p1x = boundaryEnd.x, p1y = boundaryEnd.y;
56389
57766
  const baseX = boundaryEnd.x - ux * triLen;
56390
57767
  const baseY = boundaryEnd.y - uy * triLen;
56391
57768
  const p2x = baseX + nx * (triW / 2), p2y = baseY + ny * (triW / 2);
56392
57769
  const p3x = baseX - nx * (triW / 2), p3y = baseY - ny * (triW / 2);
56393
57770
  if (mEnd === "arrow")
56394
- overlay += triangleAtEnd(prevEnd, boundaryEnd, this.arrowStroke);
57771
+ overlay += triangleAtEnd(prevEnd, boundaryEnd, styleStroke || this.arrowStroke, triLen, triW);
56395
57772
  if (mStart === "arrow" && points.length >= 2) {
56396
57773
  const firstLeg = points[1];
56397
57774
  const svx = boundaryStart.x - firstLeg.x;
@@ -56401,8 +57778,19 @@ var init_svg_generator = __esm({
56401
57778
  const suy = svy / slen;
56402
57779
  const snx = -suy;
56403
57780
  const sny = sux;
56404
- overlay += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
56405
- }
57781
+ overlay += triangleAtStart(boundaryStart, firstLeg, styleStroke || this.arrowStroke, triLen, triW);
57782
+ }
57783
+ const owStroke = styleStroke || this.arrowStroke;
57784
+ const addCircle = (at2) => `<circle cx="${at2.x}" cy="${at2.y}" r="4.5" fill="none" stroke="${owStroke}" stroke-width="${ow2}" />`;
57785
+ const addCross = (at2) => `<g transform="translate(${at2.x},${at2.y})"><path d="M -4 -4 L 4 4" stroke="${owStroke}" stroke-width="${ow2}"/><path d="M -4 4 L 4 -4" stroke="${owStroke}" stroke-width="${ow2}"/></g>`;
57786
+ if (mEnd === "circle")
57787
+ overlay += addCircle(boundaryEnd);
57788
+ if (mEnd === "cross")
57789
+ overlay += addCross(boundaryEnd);
57790
+ if (mStart === "circle")
57791
+ overlay += addCircle(boundaryStart);
57792
+ if (mStart === "cross")
57793
+ overlay += addCross(boundaryStart);
56406
57794
  if (overlay) {
56407
57795
  const grouped = `<g>${edgeElement}
56408
57796
  ${overlay}</g>`;
@@ -56528,6 +57916,16 @@ ${overlay}</g>`;
56528
57916
  { x: node.x, y: node.y + node.height }
56529
57917
  ];
56530
57918
  switch (shape) {
57919
+ case "round": {
57920
+ const poly = [
57921
+ { x: node.x, y: node.y },
57922
+ { x: node.x + node.width, y: node.y },
57923
+ { x: node.x + node.width, y: node.y + node.height },
57924
+ { x: node.x, y: node.y + node.height }
57925
+ ];
57926
+ const hit = this.linePolygonIntersection(p1, p22, poly);
57927
+ return hit || this.nearestPointOnPolygon(p22, poly);
57928
+ }
56531
57929
  case "circle": {
56532
57930
  const cx = node.x + node.width / 2;
56533
57931
  const cy = node.y + node.height / 2;
@@ -56538,7 +57936,8 @@ ${overlay}</g>`;
56538
57936
  const cx = node.x + node.width / 2;
56539
57937
  const cy = node.y + node.height / 2;
56540
57938
  const poly = [{ x: cx, y: node.y }, { x: node.x + node.width, y: cy }, { x: cx, y: node.y + node.height }, { x: node.x, y: cy }];
56541
- return this.linePolygonIntersection(p1, p22, poly);
57939
+ const hit = this.linePolygonIntersection(p1, p22, poly);
57940
+ return hit || this.nearestPointOnPolygon(p22, poly);
56542
57941
  }
56543
57942
  case "hexagon": {
56544
57943
  const s3 = Math.max(10, node.width * 0.2);
@@ -56550,7 +57949,8 @@ ${overlay}</g>`;
56550
57949
  { x: node.x + s3, y: node.y + node.height },
56551
57950
  { x: node.x, y: node.y + node.height / 2 }
56552
57951
  ];
56553
- return this.linePolygonIntersection(p1, p22, poly);
57952
+ const hit = this.linePolygonIntersection(p1, p22, poly);
57953
+ return hit || this.nearestPointOnPolygon(p22, poly);
56554
57954
  }
56555
57955
  case "parallelogram": {
56556
57956
  const o3 = Math.min(node.width * 0.25, node.height * 0.6);
@@ -56560,7 +57960,8 @@ ${overlay}</g>`;
56560
57960
  { x: node.x + node.width - o3, y: node.y + node.height },
56561
57961
  { x: node.x, y: node.y + node.height }
56562
57962
  ];
56563
- return this.linePolygonIntersection(p1, p22, poly);
57963
+ const hit = this.linePolygonIntersection(p1, p22, poly);
57964
+ return hit || this.nearestPointOnPolygon(p22, poly);
56564
57965
  }
56565
57966
  case "trapezoid": {
56566
57967
  const o3 = Math.min(node.width * 0.2, node.height * 0.5);
@@ -56570,7 +57971,8 @@ ${overlay}</g>`;
56570
57971
  { x: node.x + node.width, y: node.y + node.height },
56571
57972
  { x: node.x, y: node.y + node.height }
56572
57973
  ];
56573
- return this.linePolygonIntersection(p1, p22, poly);
57974
+ const hit = this.linePolygonIntersection(p1, p22, poly);
57975
+ return hit || this.nearestPointOnPolygon(p22, poly);
56574
57976
  }
56575
57977
  case "trapezoidAlt": {
56576
57978
  const o3 = Math.min(node.width * 0.2, node.height * 0.5);
@@ -56580,7 +57982,8 @@ ${overlay}</g>`;
56580
57982
  { x: node.x + node.width - o3, y: node.y + node.height },
56581
57983
  { x: node.x + o3, y: node.y + node.height }
56582
57984
  ];
56583
- return this.linePolygonIntersection(p1, p22, poly);
57985
+ const hit = this.linePolygonIntersection(p1, p22, poly);
57986
+ return hit || this.nearestPointOnPolygon(p22, poly);
56584
57987
  }
56585
57988
  case "stadium": {
56586
57989
  const r3 = Math.min(node.height / 2, node.width / 2);
@@ -56608,10 +58011,13 @@ ${overlay}</g>`;
56608
58011
  }
56609
58012
  return best;
56610
58013
  };
56611
- return pick(left, right);
58014
+ const hit = pick(left, right);
58015
+ return hit || this.nearestPointOnPolygon(p22, rect);
56612
58016
  }
56613
58017
  default: {
56614
- return this.linePolygonIntersection(p1, p22, rectPoly());
58018
+ const poly = rectPoly();
58019
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58020
+ return hit || this.nearestPointOnPolygon(p22, poly);
56615
58021
  }
56616
58022
  }
56617
58023
  }
@@ -56651,6 +58057,30 @@ ${overlay}</g>`;
56651
58057
  }
56652
58058
  return best;
56653
58059
  }
58060
+ // Fallback helpers when lines are colinear or miss due to smoothing
58061
+ nearestPointOnSegment(p3, a3, b3) {
58062
+ const abx = b3.x - a3.x, aby = b3.y - a3.y;
58063
+ const ab2 = abx * abx + aby * aby || 1;
58064
+ const apx = p3.x - a3.x, apy = p3.y - a3.y;
58065
+ let t3 = (apx * abx + apy * aby) / ab2;
58066
+ t3 = Math.max(0, Math.min(1, t3));
58067
+ return { x: a3.x + abx * t3, y: a3.y + aby * t3 };
58068
+ }
58069
+ nearestPointOnPolygon(to, poly) {
58070
+ let best = poly[0];
58071
+ let bestD = Infinity;
58072
+ for (let i3 = 0; i3 < poly.length; i3++) {
58073
+ const a3 = poly[i3];
58074
+ const b3 = poly[(i3 + 1) % poly.length];
58075
+ const p3 = this.nearestPointOnSegment(to, a3, b3);
58076
+ const d3 = (p3.x - to.x) * (p3.x - to.x) + (p3.y - to.y) * (p3.y - to.y);
58077
+ if (d3 < bestD) {
58078
+ bestD = d3;
58079
+ best = p3;
58080
+ }
58081
+ }
58082
+ return { x: best.x, y: best.y };
58083
+ }
56654
58084
  segmentIntersection(p3, p22, q3, q22) {
56655
58085
  const r3 = { x: p22.x - p3.x, y: p22.y - p3.y };
56656
58086
  const s3 = { x: q22.x - q3.x, y: q22.y - q3.y };
@@ -56905,16 +58335,15 @@ var init_pie_renderer = __esm({
56905
58335
  }
56906
58336
  });
56907
58337
 
56908
- // node_modules/@probelabs/maid/out/renderer/sequence-builder.js
58338
+ // node_modules/@probelabs/maid/out/diagrams/sequence/cst-utils.js
56909
58339
  function textFromTokens(tokens) {
56910
58340
  if (!tokens || tokens.length === 0)
56911
58341
  return "";
56912
58342
  const parts = [];
56913
58343
  for (const t3 of tokens) {
56914
- const img = t3.image;
56915
- if (!img)
56916
- continue;
56917
- if (t3.tokenType && t3.tokenType.name === "QuotedString") {
58344
+ const img = t3.image ?? "";
58345
+ const name14 = t3.tokenType?.name;
58346
+ if (name14 === "QuotedString") {
56918
58347
  if (img.startsWith('"') && img.endsWith('"'))
56919
58348
  parts.push(img.slice(1, -1));
56920
58349
  else if (img.startsWith("'") && img.endsWith("'"))
@@ -56928,6 +58357,8 @@ function textFromTokens(tokens) {
56928
58357
  return parts.join(" ").replace(/\s+/g, " ").trim();
56929
58358
  }
56930
58359
  function actorRefToText(refCst) {
58360
+ if (!refCst)
58361
+ return "";
56931
58362
  const ch = refCst.children || {};
56932
58363
  const toks = [];
56933
58364
  ["Identifier", "QuotedString", "NumberLiteral", "Text"].forEach((k3) => {
@@ -56952,39 +58383,20 @@ function lineRemainderToText(lineRem) {
56952
58383
  "Comma",
56953
58384
  "Colon",
56954
58385
  "LParen",
56955
- "RParen",
56956
- "AndKeyword",
56957
- "ElseKeyword",
56958
- "OptKeyword",
56959
- "OptionKeyword",
56960
- "LoopKeyword",
56961
- "ParKeyword",
56962
- "RectKeyword",
56963
- "CriticalKeyword",
56964
- "BreakKeyword",
56965
- "BoxKeyword",
56966
- "EndKeyword",
56967
- "NoteKeyword",
56968
- "LeftKeyword",
56969
- "RightKeyword",
56970
- "OverKeyword",
56971
- "OfKeyword",
56972
- "AutonumberKeyword",
56973
- "OffKeyword",
56974
- "LinkKeyword",
56975
- "LinksKeyword",
56976
- "CreateKeyword",
56977
- "DestroyKeyword",
56978
- "ParticipantKeyword",
56979
- "ActorKeyword",
56980
- "ActivateKeyword",
56981
- "DeactivateKeyword"
58386
+ "RParen"
56982
58387
  ];
56983
58388
  for (const k3 of order)
56984
58389
  ch[k3]?.forEach((t3) => toks.push(t3));
56985
58390
  toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
56986
- return textFromTokens(toks) || void 0;
58391
+ const txt = textFromTokens(toks);
58392
+ return txt || void 0;
56987
58393
  }
58394
+ var init_cst_utils = __esm({
58395
+ "node_modules/@probelabs/maid/out/diagrams/sequence/cst-utils.js"() {
58396
+ }
58397
+ });
58398
+
58399
+ // node_modules/@probelabs/maid/out/renderer/sequence-builder.js
56988
58400
  function canonicalId(raw) {
56989
58401
  const t3 = raw.trim().replace(/\s+/g, "_");
56990
58402
  return t3;
@@ -57031,11 +58443,26 @@ function buildSequenceModel(text) {
57031
58443
  const byDisplay = /* @__PURE__ */ new Map();
57032
58444
  const events = [];
57033
58445
  let autonumber = { on: false };
58446
+ let title;
58447
+ let accTitle;
58448
+ let accDescr;
57034
58449
  const diagramChildren = cst.children || {};
57035
58450
  const lines = diagramChildren.line || [];
57036
58451
  const openBlocks = [];
57037
58452
  function processLineNode(ln) {
57038
58453
  const ch = ln.children || {};
58454
+ if (ch.metaStmt) {
58455
+ const m3 = ch.metaStmt[0];
58456
+ const mch = m3.children || {};
58457
+ const value = lineRemainderToText(mch.lineRemainder?.[0]) || "";
58458
+ if (mch.TitleKeyword)
58459
+ title = value;
58460
+ if (mch.AccTitleKeyword)
58461
+ accTitle = value;
58462
+ if (mch.AccDescrKeyword)
58463
+ accDescr = value;
58464
+ return;
58465
+ }
57039
58466
  if (ch.participantDecl) {
57040
58467
  const decl = ch.participantDecl[0];
57041
58468
  const dch = decl.children || {};
@@ -57134,8 +58561,8 @@ function buildSequenceModel(text) {
57134
58561
  handledBlock = true;
57135
58562
  const bnode = ch[spec.key][0];
57136
58563
  const bch = bnode.children || {};
57137
- const title = lineRemainderToText(bch.lineRemainder?.[0]);
57138
- const block = { type: spec.type, title, branches: spec.branchKeys ? [] : void 0 };
58564
+ const title2 = lineRemainderToText(bch.lineRemainder?.[0]);
58565
+ const block = { type: spec.type, title: title2, branches: spec.branchKeys ? [] : void 0 };
57139
58566
  openBlocks.push(block);
57140
58567
  events.push({ kind: "block-start", block });
57141
58568
  if (spec.branchKeys) {
@@ -57146,8 +58573,8 @@ function buildSequenceModel(text) {
57146
58573
  if (branchTokArr && branchTokArr.length) {
57147
58574
  const lr = (lrArr || []).slice(1);
57148
58575
  for (let i3 = 0; i3 < branchTokArr.length; i3++) {
57149
- const title2 = lr[i3] ? lineRemainderToText(lr[i3]) : void 0;
57150
- const br = { kind: spec.branchKeys[0].kind, title: title2 };
58576
+ const title22 = lr[i3] ? lineRemainderToText(lr[i3]) : void 0;
58577
+ const br = { kind: spec.branchKeys[0].kind, title: title22 };
57151
58578
  block.branches.push(br);
57152
58579
  events.push({ kind: "block-branch", block, branch: br });
57153
58580
  }
@@ -57207,13 +58634,17 @@ function buildSequenceModel(text) {
57207
58634
  return {
57208
58635
  participants: Array.from(participantsMap.values()),
57209
58636
  events,
57210
- autonumber: autonumber.on === true || autonumber.on === false ? autonumber : { on: false }
58637
+ autonumber: autonumber.on === true || autonumber.on === false ? autonumber : { on: false },
58638
+ title,
58639
+ accTitle,
58640
+ accDescr
57211
58641
  };
57212
58642
  }
57213
58643
  var init_sequence_builder = __esm({
57214
58644
  "node_modules/@probelabs/maid/out/renderer/sequence-builder.js"() {
57215
58645
  init_lexer4();
57216
58646
  init_parser4();
58647
+ init_cst_utils();
57217
58648
  }
57218
58649
  });
57219
58650
 
@@ -57309,7 +58740,7 @@ function layoutSequence(model) {
57309
58740
  if (start != null) {
57310
58741
  const p3 = col.get(actor);
57311
58742
  if (p3) {
57312
- activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(r3) - yForRow(start) });
58743
+ activations.push({ actor, x: p3.x + p3.width / 2 - 3, y: yForRow(start) - ROW_H / 2, width: 6, height: yForRow(r3) - yForRow(start) });
57313
58744
  }
57314
58745
  }
57315
58746
  actStack.set(actor, arr);
@@ -57419,7 +58850,7 @@ function layoutSequence(model) {
57419
58850
  const start = arr.pop();
57420
58851
  const p3 = col.get(actor);
57421
58852
  if (p3)
57422
- activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(lastRow) - yForRow(start) });
58853
+ activations.push({ actor, x: p3.x + p3.width / 2 - 3, y: yForRow(start) - ROW_H / 2, width: 6, height: yForRow(lastRow) - yForRow(start) });
57423
58854
  }
57424
58855
  }
57425
58856
  return { width, height, participants, lifelines, messages, notes, blocks, activations };
@@ -57431,14 +58862,14 @@ var init_sequence_layout = __esm({
57431
58862
  MARGIN_X = 24;
57432
58863
  MARGIN_Y = 24;
57433
58864
  ACTOR_FONT_SIZE = 16;
57434
- ACTOR_H = 32;
58865
+ ACTOR_H = 30;
57435
58866
  LIFELINE_GAP = 4;
57436
58867
  ACTOR_PAD_X = 12;
57437
58868
  COL_MIN = 110;
57438
58869
  ROW_H = 36;
57439
58870
  NOTE_W = 160;
57440
58871
  NOTE_PAD = 8;
57441
- BLOCK_PAD = 8;
58872
+ BLOCK_PAD = 12;
57442
58873
  TITLE_EXTRA_TOP = 12;
57443
58874
  }
57444
58875
  });
@@ -57458,6 +58889,18 @@ function renderSequence(model, opts = {}) {
57458
58889
  edgeStroke: "#555555"
57459
58890
  });
57460
58891
  svgParts.push(` <style>${sharedCss}</style>`);
58892
+ const accTitle = model.accTitle || model.title || void 0;
58893
+ const accDesc = model.accDescr || void 0;
58894
+ if (accTitle)
58895
+ svgParts.push(` <title>${escapeXml(accTitle)}</title>`);
58896
+ if (accDesc)
58897
+ svgParts.push(` <desc>${escapeXml(accDesc)}</desc>`);
58898
+ if (model.title) {
58899
+ const t3 = escapeXml(model.title);
58900
+ const tW = Math.max(20, measureText(model.title, 16));
58901
+ const xMid = width / 2;
58902
+ svgParts.push(` <text class="node-label" x="${xMid}" y="0" text-anchor="middle" font-size="16">${t3}</text>`);
58903
+ }
57461
58904
  for (const p3 of layout.participants)
57462
58905
  drawParticipant(svgParts, p3);
57463
58906
  for (const b3 of layout.blocks)
@@ -57481,14 +58924,14 @@ function renderSequence(model, opts = {}) {
57481
58924
  for (const b3 of layout.blocks) {
57482
58925
  const title = b3.title ? `${b3.type}: ${b3.title}` : b3.type;
57483
58926
  const branches = (b3.branches || []).map((br) => ({ y: br.y, title: br.title }));
57484
- svgParts.push(blockOverlay(b3.x, b3.y, b3.width, b3.height, title, branches, 0, "left", "left", 0));
58927
+ svgParts.push(blockOverlay(b3.x, b3.y, b3.width, b3.height, title, branches.map((br) => ({ ...br, y: br.y + 0.5 })), 8, "left", "left", 0));
57485
58928
  }
57486
58929
  for (const p3 of layout.participants)
57487
58930
  drawParticipantBottom(svgParts, p3, layout);
57488
58931
  svgParts.push("</svg>");
57489
58932
  let svg = svgParts.join("\n");
57490
58933
  if (opts.theme)
57491
- svg = applySequenceTheme(svg, opts.theme);
58934
+ svg = applySequenceTheme(applyFlowLikeTheme(svg, opts.theme), opts.theme);
57492
58935
  return svg;
57493
58936
  }
57494
58937
  function drawParticipant(out, p3) {
@@ -57512,9 +58955,9 @@ function drawMessage(out, m3) {
57512
58955
  const start = { x: x1, y: y2 };
57513
58956
  const end = { x: x22, y: y2 };
57514
58957
  if (m3.endMarker === "arrow")
57515
- out.push(" " + triangleAtEnd(start, end));
58958
+ out.push(" " + triangleAtEnd(start, end, void 0, 9, 7));
57516
58959
  if (m3.startMarker === "arrow")
57517
- out.push(" " + triangleAtStart(start, end));
58960
+ out.push(" " + triangleAtStart(start, end, void 0, 9, 7));
57518
58961
  if (m3.endMarker === "open")
57519
58962
  out.push(` <circle class="openhead" cx="${x22}" cy="${y2}" r="4" />`);
57520
58963
  if (m3.startMarker === "open")
@@ -57538,8 +58981,8 @@ function drawMessageLabel(out, m3, label, _counter) {
57538
58981
  const h3 = 16;
57539
58982
  const w3 = Math.max(20, measureText(label, 12) + 10);
57540
58983
  const x3 = xMid - w3 / 2;
57541
- const y2 = m3.y - 10 - h3 / 2;
57542
- out.push(` <rect class="msg-label-bg" x="${x3}" y="${y2}" width="${w3}" height="${h3}" rx="0"/>`);
58984
+ const y2 = m3.y - 14 - h3 / 2;
58985
+ out.push(` <rect class="msg-label-bg" x="${x3}" y="${y2}" width="${w3}" height="${h3}" rx="3"/>`);
57543
58986
  out.push(` <text class="msg-label" x="${xMid}" y="${y2 + h3 / 2}" text-anchor="middle">${escapeXml(label)}</text>`);
57544
58987
  }
57545
58988
  function drawNote(out, n3) {
@@ -57550,18 +58993,12 @@ function drawNote(out, n3) {
57550
58993
  }
57551
58994
  function applySequenceTheme(svg, theme) {
57552
58995
  let out = svg;
57553
- if (theme.actorBkg)
57554
- out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorBkg)};`));
57555
- if (theme.actorBorder)
57556
- out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.actorBorder)};`));
57557
- if (theme.actorTextColor)
57558
- out = out.replace(/\.actor-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorTextColor)};`));
57559
58996
  if (theme.lifelineColor)
57560
58997
  out = out.replace(/\.lifeline\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lifelineColor)};`));
57561
58998
  if (theme.lineColor)
57562
58999
  out = out.replace(/\.msg-line\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
57563
59000
  if (theme.arrowheadColor) {
57564
- out = out.replace(/\.arrowhead\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.arrowheadColor)};`));
59001
+ out = out.replace(/(<path d=\"M[0-9.,\s-]+Z\" fill=\")[^\"]+(\")/g, (_m2, p1, p22) => `${p1}${String(theme.arrowheadColor)}${p22}`);
57565
59002
  out = out.replace(/\.openhead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57566
59003
  out = out.replace(/\.crosshead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57567
59004
  }
@@ -57587,6 +59024,329 @@ var init_sequence_renderer = __esm({
57587
59024
  }
57588
59025
  });
57589
59026
 
59027
+ // node_modules/@probelabs/maid/out/renderer/state-builder.js
59028
+ function textFromTokens2(tokens) {
59029
+ if (!tokens || tokens.length === 0)
59030
+ return "";
59031
+ const parts = [];
59032
+ for (const t3 of tokens) {
59033
+ const img = t3.image ?? "";
59034
+ if (t3.tokenType && t3.tokenType.name === "QuotedString") {
59035
+ if (img.startsWith('"') && img.endsWith('"'))
59036
+ parts.push(img.slice(1, -1));
59037
+ else if (img.startsWith("'") && img.endsWith("'"))
59038
+ parts.push(img.slice(1, -1));
59039
+ else
59040
+ parts.push(img);
59041
+ } else {
59042
+ parts.push(img);
59043
+ }
59044
+ }
59045
+ return parts.join(" ").replace(/\s+/g, " ").trim();
59046
+ }
59047
+ function actorRefToId(ref, ctx = {}) {
59048
+ if (!ref)
59049
+ return { id: "", kind: "simple" };
59050
+ const ch = ref.children || {};
59051
+ if (ch.Start) {
59052
+ const kind = ctx.isTarget ? "end" : "start";
59053
+ return { id: `__${kind}_${ch.Start[0].startOffset ?? 0}`, kind };
59054
+ }
59055
+ if (ch.HistoryDeep)
59056
+ return { id: `__histdeep_${ch.HistoryDeep[0].startOffset ?? 0}`, label: "H*", kind: "history-deep" };
59057
+ if (ch.HistoryShallow)
59058
+ return { id: `__hist_${ch.HistoryShallow[0].startOffset ?? 0}`, label: "H", kind: "history" };
59059
+ let special;
59060
+ if (ch.AngleAngleOpen && ch.Identifier && ch.AngleAngleClose) {
59061
+ const k3 = String(ch.Identifier[0].image).toLowerCase();
59062
+ if (k3 === "choice")
59063
+ special = "choice";
59064
+ else if (k3 === "fork")
59065
+ special = "fork";
59066
+ else if (k3 === "join")
59067
+ special = "join";
59068
+ }
59069
+ const toks = [];
59070
+ ch.Identifier?.forEach((t3) => toks.push(t3));
59071
+ ch.QuotedString?.forEach((t3) => toks.push(t3));
59072
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59073
+ const txt = textFromTokens2(toks) || "";
59074
+ const id = txt.trim().replace(/\s+/g, "_");
59075
+ return { id, label: txt, kind: special || "simple" };
59076
+ }
59077
+ function buildStateModel(text) {
59078
+ const { tokens } = tokenize5(text);
59079
+ parserInstance5.input = tokens;
59080
+ const cst = parserInstance5.diagram();
59081
+ let direction = "TD";
59082
+ const nodes = /* @__PURE__ */ new Map();
59083
+ const transitions = [];
59084
+ const composites = [];
59085
+ const lanes = [];
59086
+ const stack = [];
59087
+ const diagramChildren = cst.children || {};
59088
+ const stmts = diagramChildren.statement || [];
59089
+ function ensureNode(def) {
59090
+ const ex = nodes.get(def.id);
59091
+ if (ex)
59092
+ return ex;
59093
+ nodes.set(def.id, def);
59094
+ const parentCtx = stack[stack.length - 1];
59095
+ if (parentCtx) {
59096
+ const parent = parentCtx.id;
59097
+ const laneId = `${parent}__lane${parentCtx.lane}`;
59098
+ let laneSg = composites.find((c3) => c3.id === laneId);
59099
+ if (!laneSg) {
59100
+ if (!composites.find((c3) => c3.id === parent))
59101
+ composites.push({ id: parent, label: parent, nodes: [], parent: stack.length > 1 ? stack[stack.length - 2].id : void 0 });
59102
+ composites.push({ id: laneId, label: void 0, nodes: [], parent });
59103
+ lanes.push({ parentId: parent, id: laneId, nodes: [] });
59104
+ }
59105
+ laneSg = composites.find((c3) => c3.id === laneId);
59106
+ if (!laneSg.nodes.includes(def.id))
59107
+ laneSg.nodes.push(def.id);
59108
+ const laneRec = lanes.find((l3) => l3.id === laneId);
59109
+ if (laneRec && !laneRec.nodes.includes(def.id))
59110
+ laneRec.nodes.push(def.id);
59111
+ def.parent = laneId;
59112
+ }
59113
+ return def;
59114
+ }
59115
+ function visitStatement(node) {
59116
+ const ch = node.children || {};
59117
+ if (ch.directionStmt) {
59118
+ const d3 = ch.directionStmt[0].children.Direction?.[0]?.image || "TD";
59119
+ direction = d3;
59120
+ return;
59121
+ }
59122
+ if (ch.stateDecl) {
59123
+ const n3 = ch.stateDecl[0];
59124
+ const dch = n3.children || {};
59125
+ if (dch.QuotedString && dch.AsKw && dch.Identifier) {
59126
+ const label = dch.QuotedString[0].image.slice(1, -1);
59127
+ const id = dch.Identifier[0].image;
59128
+ ensureNode({ id, label, kind: "simple" });
59129
+ } else if (dch.Identifier) {
59130
+ const id = dch.Identifier[0].image;
59131
+ ensureNode({ id, label: id, kind: "simple" });
59132
+ }
59133
+ return;
59134
+ }
59135
+ if (ch.stateBlock) {
59136
+ const b3 = ch.stateBlock[0];
59137
+ const bch = b3.children || {};
59138
+ const idTok = bch.Identifier?.[0] || bch.QuotedString?.[0];
59139
+ const idRaw = idTok ? idTok.image.startsWith('"') ? idTok.image.slice(1, -1) : idTok.image : `__state_${b3.location ?? Math.random()}`;
59140
+ const id = idRaw.replace(/\s+/g, "_");
59141
+ ensureNode({ id, label: idRaw, kind: "composite" });
59142
+ if (!composites.find((c3) => c3.id === id))
59143
+ composites.push({ id, label: idRaw, nodes: [], parent: stack.length ? stack[stack.length - 1].id : void 0 });
59144
+ stack.push({ id, lane: 0 });
59145
+ const inner = bch.innerStatement || [];
59146
+ for (const s3 of inner)
59147
+ visitStatement(s3);
59148
+ stack.pop();
59149
+ return;
59150
+ }
59151
+ if (ch.transitionStmt) {
59152
+ const t3 = ch.transitionStmt[0];
59153
+ const tch = t3.children || {};
59154
+ const left = actorRefToId(tch.actorRef?.[0], { isTarget: false });
59155
+ const right = actorRefToId(tch.actorRef?.[1], { isTarget: true });
59156
+ if (left.id)
59157
+ ensureNode({ id: left.id, label: left.label || left.id, kind: left.kind });
59158
+ if (right.id)
59159
+ ensureNode({ id: right.id, label: right.label || right.id, kind: right.kind });
59160
+ let label;
59161
+ if (tch.Colon && tch.labelText) {
59162
+ const toks = [];
59163
+ tch.labelText.forEach((lt) => {
59164
+ const ch2 = lt.children || {};
59165
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => ch2[k3]?.forEach((tt) => toks.push(tt)));
59166
+ });
59167
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59168
+ label = textFromTokens2(toks);
59169
+ }
59170
+ if (left.id && right.id)
59171
+ transitions.push({ source: left.id, target: right.id, label });
59172
+ return;
59173
+ }
59174
+ if (node.name === "innerStatement") {
59175
+ const ich = node.children || {};
59176
+ if (ich.Dashes && ich.Dashes.length && stack.length) {
59177
+ stack[stack.length - 1].lane += 1;
59178
+ return;
59179
+ }
59180
+ }
59181
+ if (ch.noteStmt) {
59182
+ const n3 = ch.noteStmt[0];
59183
+ const nch = n3.children || {};
59184
+ const txtToks = [];
59185
+ const targetRef = nch.actorRef?.[0];
59186
+ const target = actorRefToId(targetRef);
59187
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => nch[k3]?.forEach((tk) => txtToks.push(tk)));
59188
+ const text2 = textFromTokens2(txtToks);
59189
+ if (target.id && text2) {
59190
+ const noteId = `__note_${(n3.location ?? Math.random()).toString().slice(2)}`;
59191
+ ensureNode({ id: noteId, label: text2, kind: "simple" });
59192
+ ensureNode({ id: target.id, label: target.label || target.id, kind: target.kind });
59193
+ transitions.push({ source: noteId, target: target.id, label: void 0 });
59194
+ }
59195
+ return;
59196
+ }
59197
+ if (ch.stateDescriptionStmt) {
59198
+ const s3 = ch.stateDescriptionStmt[0];
59199
+ const sch = s3.children || {};
59200
+ const nameTok = sch.Identifier?.[0] || sch.QuotedString?.[0];
59201
+ if (nameTok) {
59202
+ const raw = nameTok.image.startsWith('"') ? nameTok.image.slice(1, -1) : nameTok.image;
59203
+ const id = raw.replace(/\s+/g, "_");
59204
+ const labelToks = [];
59205
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => sch[k3]?.forEach((tt) => labelToks.push(tt)));
59206
+ const lbl = textFromTokens2(labelToks);
59207
+ ensureNode({ id, label: lbl || raw, kind: "simple" });
59208
+ }
59209
+ return;
59210
+ }
59211
+ for (const key of Object.keys(ch)) {
59212
+ const arr = ch[key];
59213
+ if (Array.isArray(arr))
59214
+ arr.forEach((n3) => visitStatement(n3));
59215
+ }
59216
+ }
59217
+ for (const st of stmts)
59218
+ visitStatement(st);
59219
+ return {
59220
+ direction,
59221
+ nodes: Array.from(nodes.values()),
59222
+ transitions,
59223
+ composites,
59224
+ lanes
59225
+ };
59226
+ }
59227
+ var init_state_builder = __esm({
59228
+ "node_modules/@probelabs/maid/out/renderer/state-builder.js"() {
59229
+ init_lexer6();
59230
+ init_parser6();
59231
+ }
59232
+ });
59233
+
59234
+ // node_modules/@probelabs/maid/out/renderer/state-renderer.js
59235
+ function toGraph(model) {
59236
+ const nodes = [];
59237
+ const edges = [];
59238
+ const subgraphs = [];
59239
+ for (const s3 of model.nodes) {
59240
+ let shape = "rectangle";
59241
+ let label = s3.label || s3.id;
59242
+ if (s3.kind === "start") {
59243
+ shape = "circle";
59244
+ label = "";
59245
+ } else if (s3.kind === "end") {
59246
+ shape = "circle";
59247
+ label = "";
59248
+ } else if (s3.kind === "history") {
59249
+ shape = "circle";
59250
+ label = "H";
59251
+ } else if (s3.kind === "history-deep") {
59252
+ shape = "circle";
59253
+ label = "H*";
59254
+ } else if (s3.kind === "choice") {
59255
+ shape = "diamond";
59256
+ } else if (s3.kind === "fork" || s3.kind === "join") {
59257
+ shape = "rectangle";
59258
+ }
59259
+ const node = { id: s3.id, label, shape };
59260
+ if (s3.kind === "fork" || s3.kind === "join") {
59261
+ node.width = 80;
59262
+ node.height = 8;
59263
+ }
59264
+ nodes.push(node);
59265
+ }
59266
+ for (const t3 of model.transitions) {
59267
+ edges.push({ id: `${t3.source}->${t3.target}-${Math.random().toString(36).slice(2, 7)}`, source: t3.source, target: t3.target, label: t3.label, type: "arrow", markerEnd: "arrow" });
59268
+ }
59269
+ for (const c3 of model.composites) {
59270
+ subgraphs.push({ id: c3.id, label: c3.label, nodes: c3.nodes, parent: c3.parent });
59271
+ }
59272
+ const laneGroups = (model.lanes || []).slice();
59273
+ return { graph: { nodes, edges, subgraphs, direction: model.direction }, laneGroups };
59274
+ }
59275
+ function renderState(model) {
59276
+ var _a16;
59277
+ const { graph, laneGroups } = toGraph(model);
59278
+ const layout = new DagreLayoutEngine().layout(graph);
59279
+ let svg = new SVGRenderer().render(layout);
59280
+ const byId = Object.fromEntries(layout.nodes.map((n3) => [n3.id, { x: n3.x, y: n3.y, width: n3.width, height: n3.height }]));
59281
+ const subById = Object.fromEntries((layout.subgraphs || []).map((s3) => [s3.id, { x: s3.x, y: s3.y, width: s3.width, height: s3.height, label: s3.label }]));
59282
+ const overlays = [];
59283
+ const groupByParent = {};
59284
+ for (const lg of laneGroups) {
59285
+ const parent = subById[lg.parentId];
59286
+ if (!parent)
59287
+ continue;
59288
+ const members = lg.nodes.map((id) => byId[id]).filter(Boolean);
59289
+ if (!members.length)
59290
+ continue;
59291
+ (groupByParent[_a16 = lg.parentId] || (groupByParent[_a16] = [])).push({ id: lg.id, nodes: members });
59292
+ }
59293
+ const laneIndex = (id) => {
59294
+ const m3 = /(.*)__lane(\d+)/.exec(id);
59295
+ return m3 ? parseInt(m3[2], 10) : Number.POSITIVE_INFINITY;
59296
+ };
59297
+ for (const pid of Object.keys(groupByParent)) {
59298
+ const parent = subById[pid];
59299
+ if (!parent)
59300
+ continue;
59301
+ const lanes = groupByParent[pid].slice();
59302
+ if (lanes.every((l3) => /__lane\d+/.test(l3.id)))
59303
+ lanes.sort((a3, b3) => laneIndex(a3.id) - laneIndex(b3.id));
59304
+ else if (graph.direction === "LR" || graph.direction === "RL")
59305
+ lanes.sort((a3, b3) => Math.min(...a3.nodes.map((n3) => n3.x)) - Math.min(...b3.nodes.map((n3) => n3.x)));
59306
+ else
59307
+ lanes.sort((a3, b3) => Math.min(...a3.nodes.map((n3) => n3.y)) - Math.min(...b3.nodes.map((n3) => n3.y)));
59308
+ for (let i3 = 1; i3 < lanes.length; i3++) {
59309
+ const prev = lanes[i3 - 1];
59310
+ const next = lanes[i3];
59311
+ if (graph.direction === "LR" || graph.direction === "RL") {
59312
+ const prevMaxX = Math.max(...prev.nodes.map((n3) => n3.x + n3.width));
59313
+ const nextMinX = Math.min(...next.nodes.map((n3) => n3.x));
59314
+ const x3 = Math.max(parent.x, Math.min(parent.x + parent.width, (prevMaxX + nextMinX) / 2));
59315
+ overlays.push(`<line class="lane-divider" x1="${x3}" y1="${parent.y + 14}" x2="${x3}" y2="${parent.y + parent.height}" />`);
59316
+ } else {
59317
+ const prevMaxY = Math.max(...prev.nodes.map((n3) => n3.y + n3.height));
59318
+ const nextMinY = Math.min(...next.nodes.map((n3) => n3.y));
59319
+ const y2 = Math.max(parent.y + 14, Math.min(parent.y + parent.height, (prevMaxY + nextMinY) / 2));
59320
+ overlays.push(`<line class="lane-divider" x1="${parent.x}" y1="${y2}" x2="${parent.x + parent.width}" y2="${y2}" />`);
59321
+ }
59322
+ }
59323
+ }
59324
+ for (const n3 of layout.nodes) {
59325
+ const src = (model.nodes || []).find((nn) => nn.id === n3.id);
59326
+ if (!src || src.kind !== "end")
59327
+ continue;
59328
+ const cx = n3.x + n3.width / 2;
59329
+ const cy = n3.y + n3.height / 2;
59330
+ const r3 = Math.max(1, Math.min(n3.width, n3.height) / 2 - 3);
59331
+ overlays.push(`<circle class="end-double" cx="${cx}" cy="${cy}" r="${r3}" fill="none" />`);
59332
+ }
59333
+ if (overlays.length) {
59334
+ svg = svg.replace("</svg>", `<g class="state-overlays">${overlays.join("\n")}</g></svg>`);
59335
+ }
59336
+ if (!/<style>/.test(svg)) {
59337
+ const css = buildSharedCss();
59338
+ svg = svg.replace("<svg ", `<svg `).replace("</svg>", `<style>${css}</style></svg>`);
59339
+ }
59340
+ return svg;
59341
+ }
59342
+ var init_state_renderer = __esm({
59343
+ "node_modules/@probelabs/maid/out/renderer/state-renderer.js"() {
59344
+ init_layout();
59345
+ init_svg_generator();
59346
+ init_styles();
59347
+ }
59348
+ });
59349
+
57590
59350
  // node_modules/@probelabs/maid/out/core/frontmatter.js
57591
59351
  function parseFrontmatter(input) {
57592
59352
  const text = input.startsWith("\uFEFF") ? input.slice(1) : input;
@@ -57709,6 +59469,443 @@ var init_frontmatter = __esm({
57709
59469
  }
57710
59470
  });
57711
59471
 
59472
+ // node_modules/@probelabs/maid/out/renderer/class-builder.js
59473
+ function textFromTokens3(tokens) {
59474
+ if (!tokens || tokens.length === 0)
59475
+ return "";
59476
+ const parts = [];
59477
+ for (const t3 of tokens) {
59478
+ const img = t3.image ?? "";
59479
+ if (t3.tokenType && t3.tokenType.name === "QuotedString") {
59480
+ if (img.startsWith('"') && img.endsWith('"'))
59481
+ parts.push(img.slice(1, -1));
59482
+ else if (img.startsWith("'") && img.endsWith("'"))
59483
+ parts.push(img.slice(1, -1));
59484
+ else
59485
+ parts.push(img);
59486
+ } else {
59487
+ parts.push(img);
59488
+ }
59489
+ }
59490
+ return parts.join(" ").replace(/\s+/g, " ").trim();
59491
+ }
59492
+ function classRefToText(refCst) {
59493
+ if (!refCst)
59494
+ return "";
59495
+ const ch = refCst.children || {};
59496
+ const toks = [];
59497
+ ["Identifier", "QuotedString", "BacktickName"].forEach((k3) => {
59498
+ const arr = ch[k3];
59499
+ arr?.forEach((t3) => toks.push(t3));
59500
+ });
59501
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59502
+ return textFromTokens3(toks);
59503
+ }
59504
+ function memberLineToText(member) {
59505
+ const ch = member.children || {};
59506
+ const toks = [];
59507
+ const order = ["Visibility", "Identifier", "QuotedString", "LParen", "RParen", "Comma", "Colon", "NumberLiteral"];
59508
+ for (const k3 of order)
59509
+ ch[k3]?.forEach((t3) => toks.push(t3));
59510
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59511
+ const txt = textFromTokens3(toks);
59512
+ const isMethod = /(\)\s*:|\)$)/.test(txt) || /\(/.test(txt);
59513
+ return { text: txt, isMethod };
59514
+ }
59515
+ function canonicalId2(raw) {
59516
+ return raw.trim().replace(/\s+/g, "_");
59517
+ }
59518
+ function buildClassModel(text) {
59519
+ const { tokens } = tokenize4(text);
59520
+ parserInstance4.input = tokens;
59521
+ const cst = parserInstance4.diagram();
59522
+ const classes = /* @__PURE__ */ new Map();
59523
+ const relations = [];
59524
+ const notes = [];
59525
+ let direction = "TD";
59526
+ function ensureClass(idRaw, display) {
59527
+ const id = canonicalId2(idRaw);
59528
+ const existing = classes.get(id);
59529
+ if (existing)
59530
+ return existing;
59531
+ const def = { id, display: display || idRaw, attributes: [], methods: [] };
59532
+ classes.set(id, def);
59533
+ return def;
59534
+ }
59535
+ const diagramChildren = cst.children || {};
59536
+ const stmts = diagramChildren.statement || [];
59537
+ for (const st of stmts) {
59538
+ const ch = st.children || {};
59539
+ if (ch.directionStmt) {
59540
+ const d3 = ch.directionStmt[0].children.Direction?.[0]?.image || "TD";
59541
+ if (d3 === "TB")
59542
+ direction = "TB";
59543
+ else if (d3 === "BT")
59544
+ direction = "BT";
59545
+ else if (d3 === "LR")
59546
+ direction = "LR";
59547
+ else if (d3 === "RL")
59548
+ direction = "RL";
59549
+ else
59550
+ direction = "TD";
59551
+ continue;
59552
+ }
59553
+ if (ch.classLine) {
59554
+ const node = ch.classLine[0];
59555
+ const nch = node.children || {};
59556
+ const name14 = classRefToText(nch.classRef?.[0]);
59557
+ const def = ensureClass(name14);
59558
+ if (nch.LTlt && nch.Identifier && nch.GTgt) {
59559
+ def.stereotype = nch.Identifier[0].image;
59560
+ }
59561
+ if (nch.LCurly && nch.memberLineStmt) {
59562
+ const lines = nch.memberLineStmt;
59563
+ for (const m3 of lines) {
59564
+ const mm = memberLineToText(m3.children.memberLine?.[0]);
59565
+ if (!mm.text)
59566
+ continue;
59567
+ (mm.isMethod ? def.methods : def.attributes).push(mm.text);
59568
+ }
59569
+ }
59570
+ continue;
59571
+ }
59572
+ if (ch.memberAssignStmt) {
59573
+ const node = ch.memberAssignStmt[0];
59574
+ const nch = node.children || {};
59575
+ const clsName = classRefToText(nch.classRef?.[0]);
59576
+ const def = ensureClass(clsName);
59577
+ const mm = memberLineToText(nch.memberLine?.[0]);
59578
+ if (mm.text)
59579
+ (mm.isMethod ? def.methods : def.attributes).push(mm.text);
59580
+ continue;
59581
+ }
59582
+ if (ch.noteStmt) {
59583
+ const node = ch.noteStmt[0];
59584
+ const nch = node.children || {};
59585
+ const target = classRefToText(nch.classRef?.[0]);
59586
+ const labelToks = [];
59587
+ ["QuotedString", "Identifier", "NumberLiteral"].forEach((k3) => nch[k3]?.forEach((t3) => labelToks.push(t3)));
59588
+ const text2 = textFromTokens3(labelToks);
59589
+ if (target && text2)
59590
+ notes.push({ target: canonicalId2(target), text: text2 });
59591
+ continue;
59592
+ }
59593
+ if (ch.relationStmt) {
59594
+ const node = ch.relationStmt[0];
59595
+ const rch = node.children || {};
59596
+ const leftName = classRefToText(rch.classRef?.[0]);
59597
+ const rightName = classRefToText(rch.classRef?.[1]);
59598
+ const left = ensureClass(leftName).id;
59599
+ const right = ensureClass(rightName).id;
59600
+ const leftCardTok = rch.leftCard?.[0];
59601
+ const rightCardTok = rch.rightCard?.[0];
59602
+ const leftCard = leftCardTok?.image ? leftCardTok.image.slice(1, -1) : void 0;
59603
+ const rightCard = rightCardTok?.image ? rightCardTok.image.slice(1, -1) : void 0;
59604
+ let label;
59605
+ if (rch.labelText) {
59606
+ const toks = [];
59607
+ rch.labelText.forEach((lt) => {
59608
+ const ch2 = lt.children || {};
59609
+ ["QuotedString", "Identifier", "NumberLiteral", "GenericAngle"].forEach((k3) => {
59610
+ ch2[k3]?.forEach((t3) => toks.push(t3));
59611
+ });
59612
+ });
59613
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59614
+ label = textFromTokens3(toks);
59615
+ }
59616
+ const relMap = [
59617
+ { key: "RelAssociation", kind: "association" },
59618
+ { key: "RelDependency", kind: "dependency" },
59619
+ { key: "RelRealization", kind: "realization" },
59620
+ { key: "RelExtends", kind: "extends" },
59621
+ { key: "RelAggregation", kind: "aggregation" },
59622
+ { key: "RelComposition", kind: "composition" },
59623
+ { key: "RelDependencyLeft", kind: "dependency" },
59624
+ { key: "RelRealizationLeft", kind: "realization" },
59625
+ { key: "RelExtendsRight", kind: "extends" },
59626
+ { key: "RelAggBoth", kind: "aggregation-both" },
59627
+ { key: "RelCompBoth", kind: "composition-both" },
59628
+ { key: "RelAggToComp", kind: "aggregation-to-comp" },
59629
+ { key: "RelCompToAgg", kind: "composition-to-agg" },
59630
+ { key: "LollipopLeft", kind: "lollipop-left" },
59631
+ { key: "LollipopRight", kind: "lollipop-right" }
59632
+ ];
59633
+ let kind = "association";
59634
+ for (const m3 of relMap) {
59635
+ if (rch[m3.key]) {
59636
+ kind = m3.kind;
59637
+ break;
59638
+ }
59639
+ }
59640
+ let src = left, dst = right;
59641
+ if (rch.RelExtends || rch.RelDependencyLeft || rch.RelRealizationLeft || rch.LollipopLeft) {
59642
+ src = right;
59643
+ dst = left;
59644
+ }
59645
+ const rel = { source: src, target: dst, kind, label, leftCard, rightCard };
59646
+ relations.push(rel);
59647
+ continue;
59648
+ }
59649
+ }
59650
+ return {
59651
+ direction,
59652
+ classes: Array.from(classes.values()),
59653
+ relations,
59654
+ notes
59655
+ };
59656
+ }
59657
+ var init_class_builder = __esm({
59658
+ "node_modules/@probelabs/maid/out/renderer/class-builder.js"() {
59659
+ init_lexer5();
59660
+ init_parser5();
59661
+ }
59662
+ });
59663
+
59664
+ // node_modules/@probelabs/maid/out/renderer/class-renderer.js
59665
+ function classNodeSize(def, fontSize = 14) {
59666
+ const title = def.stereotype ? `\xAB${def.stereotype}\xBB ${def.display}` : def.display;
59667
+ const attrLines = def.attributes.slice();
59668
+ const methodLines = def.methods.slice();
59669
+ const lineH = Math.max(16, Math.round(fontSize * 1.1));
59670
+ const padX = 12, padY = 10;
59671
+ const titleW = measureText(title, fontSize + 1) + padX * 2;
59672
+ const attrsW = Math.max(0, ...attrLines.map((t3) => measureText(t3, fontSize))) + padX * 2;
59673
+ const methodsW = Math.max(0, ...methodLines.map((t3) => measureText(t3, fontSize))) + padX * 2;
59674
+ const width = Math.max(120, titleW, attrsW, methodsW);
59675
+ const sepH = (attrLines.length ? 6 : 0) + (methodLines.length ? 6 : 0);
59676
+ const height = padY * 2 + lineH + attrLines.length * lineH + (methodLines.length ? 6 : 0) + (attrLines.length ? 6 : 0) + methodLines.length * lineH;
59677
+ return { width, height, title, attrLines, methodLines };
59678
+ }
59679
+ function triangleOpenAt(points, color, length = 10, width = 8, atEnd = true) {
59680
+ const [a3, b3] = atEnd ? points : [points[1], points[0]];
59681
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59682
+ const len = Math.hypot(vx, vy) || 1;
59683
+ const ux = vx / len, uy = vy / len;
59684
+ const nx = -uy, ny = ux;
59685
+ const tip = { x: b3.x, y: b3.y };
59686
+ const base = { x: b3.x - ux * length, y: b3.y - uy * length };
59687
+ const p22 = { x: base.x + nx * (width / 2), y: base.y + ny * (width / 2) };
59688
+ const p3 = { x: base.x - nx * (width / 2), y: base.y - ny * (width / 2) };
59689
+ return `<path class="edge-marker" d="M${tip.x},${tip.y} L${p22.x},${p22.y} M${tip.x},${tip.y} L${p3.x},${p3.y}" stroke="${color}" fill="none" />`;
59690
+ }
59691
+ function triangleHollowAt(points, color, length = 12, width = 10, atEnd = true) {
59692
+ const [a3, b3] = atEnd ? points : [points[1], points[0]];
59693
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59694
+ const len = Math.hypot(vx, vy) || 1;
59695
+ const ux = vx / len, uy = vy / len;
59696
+ const nx = -uy, ny = ux;
59697
+ const tip = { x: b3.x, y: b3.y };
59698
+ const base = { x: b3.x - ux * length, y: b3.y - uy * length };
59699
+ const p22 = { x: base.x + nx * (width / 2), y: base.y + ny * (width / 2) };
59700
+ const p3 = { x: base.x - nx * (width / 2), y: base.y - ny * (width / 2) };
59701
+ const d3 = `M${tip.x},${tip.y} L${p22.x},${p22.y} L${p3.x},${p3.y} Z`;
59702
+ return `<path class="edge-marker" d="${d3}" fill="white" stroke="${color}" />`;
59703
+ }
59704
+ function diamondAt(points, color, filled, size = 10, atStart = true) {
59705
+ const [a3, b3] = atStart ? points : [points[1], points[0]];
59706
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59707
+ const len = Math.hypot(vx, vy) || 1;
59708
+ const ux = vx / len, uy = vy / len;
59709
+ const nx = -uy, ny = ux;
59710
+ const center = { x: a3.x, y: a3.y };
59711
+ const pTip = { x: center.x - ux * size, y: center.y - uy * size };
59712
+ const pLeft = { x: center.x + nx * (size / 1.4), y: center.y + ny * (size / 1.4) };
59713
+ const pRight = { x: center.x - nx * (size / 1.4), y: center.y - ny * (size / 1.4) };
59714
+ const pBack = { x: center.x + ux * size, y: center.y + uy * size };
59715
+ const d3 = `M${pTip.x},${pTip.y} L${pLeft.x},${pLeft.y} L${pBack.x},${pBack.y} L${pRight.x},${pRight.y} Z`;
59716
+ return filled ? `<path class="edge-marker edge-marker-fill" d="${d3}" fill="${color}" stroke="${color}"/>` : `<path class="edge-marker" d="${d3}" fill="white" stroke="${color}"/>`;
59717
+ }
59718
+ function polyline(points, cls, dashed = false, stroke = "#555", strokeWidth = 2) {
59719
+ const d3 = points.map((p3) => `${p3.x},${p3.y}`).join(" ");
59720
+ const dash = dashed ? ` stroke-dasharray="4 3"` : "";
59721
+ return `<polyline class="edge-path ${cls}" points="${d3}" fill="none"${dash}/>`;
59722
+ }
59723
+ function renderClass(model, opts = {}) {
59724
+ const nodes = [];
59725
+ const nodeSizeInfo = {};
59726
+ for (const c3 of model.classes) {
59727
+ const sz = classNodeSize(c3);
59728
+ nodeSizeInfo[c3.id] = sz;
59729
+ nodes.push({ id: c3.id, label: c3.display, shape: "rectangle", width: sz.width, height: sz.height });
59730
+ }
59731
+ const edges = model.relations.map((r3, i3) => ({ id: `e${i3}`, source: r3.source, target: r3.target, type: "open" }));
59732
+ const graph = { nodes, edges, direction: model.direction };
59733
+ const layoutEngine = new DagreLayoutEngine();
59734
+ const layout = layoutEngine.layout(graph);
59735
+ const width = Math.ceil(layout.width + 40);
59736
+ const height = Math.ceil(layout.height + 40);
59737
+ const parts = [];
59738
+ parts.push(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="${Math.min(0, -20)} ${Math.min(0, -20)} ${width} ${height}">`);
59739
+ const sharedCss = buildSharedCss();
59740
+ parts.push(`<style>${sharedCss}
59741
+ .class-title { font-weight: 600; }
59742
+ .class-divider { stroke: #aaa; stroke-width: 1; }
59743
+ .class-member { font-size: 12px; }
59744
+ </style>`);
59745
+ for (const n3 of layout.nodes) {
59746
+ const info = nodeSizeInfo[n3.id];
59747
+ const x3 = n3.x, y2 = n3.y, w3 = n3.width, h3 = n3.height;
59748
+ const title = info.title;
59749
+ const attrs = info.attrLines;
59750
+ const methods = info.methodLines;
59751
+ const lineH = 16;
59752
+ const padX = 12;
59753
+ const padY = 10;
59754
+ let cy = y2 + padY + lineH;
59755
+ parts.push(` <g transform="translate(${x3},${y2})">`);
59756
+ parts.push(` <rect class="node-shape" width="${w3}" height="${h3}" rx="0"/>`);
59757
+ parts.push(` <text class="node-label class-title" x="${w3 / 2}" y="${padY + 12}" text-anchor="middle" dominant-baseline="middle">${escapeXml(title)}</text>`);
59758
+ let yCursor = padY + 18;
59759
+ if (attrs.length) {
59760
+ parts.push(` <line class="class-divider" x1="0" y1="${yCursor}" x2="${w3}" y2="${yCursor}"/>`);
59761
+ yCursor += 8;
59762
+ for (const a3 of attrs) {
59763
+ parts.push(` <text class="node-label class-member" x="${padX}" y="${yCursor}" dominant-baseline="hanging">${escapeXml(a3)}</text>`);
59764
+ yCursor += lineH;
59765
+ }
59766
+ }
59767
+ if (methods.length) {
59768
+ parts.push(` <line class="class-divider" x1="0" y1="${yCursor}" x2="${w3}" y2="${yCursor}"/>`);
59769
+ yCursor += 8;
59770
+ for (const m3 of methods) {
59771
+ parts.push(` <text class="node-label class-member" x="${padX}" y="${yCursor}" dominant-baseline="hanging">${escapeXml(m3)}</text>`);
59772
+ yCursor += lineH;
59773
+ }
59774
+ }
59775
+ parts.push(" </g>");
59776
+ }
59777
+ const edgeColor = "#555";
59778
+ for (let i3 = 0; i3 < layout.edges.length; i3++) {
59779
+ const e3 = layout.edges[i3];
59780
+ const rel = model.relations[i3];
59781
+ const pts = e3.points;
59782
+ const dashed = rel.kind === "dependency" || rel.kind === "realization";
59783
+ parts.push(polyline(pts, "edge-path", dashed, edgeColor, 2));
59784
+ const placeEndpoint = (pt, next, text, side) => {
59785
+ const vx = next.x - pt.x;
59786
+ const vy = next.y - pt.y;
59787
+ const vlen = Math.hypot(vx, vy) || 1;
59788
+ const ux = vx / vlen;
59789
+ const uy = vy / vlen;
59790
+ const nx = -uy;
59791
+ const ny = ux;
59792
+ const away = -6;
59793
+ const perp = 8;
59794
+ const x3 = pt.x + ux * away + nx * perp;
59795
+ const y2 = pt.y + uy * away + ny * perp;
59796
+ const anchor = side === "start" ? "end" : "start";
59797
+ parts.push(`<text class="edge-label-text" x="${x3}" y="${y2}" text-anchor="${anchor}">${escapeXml(text)}</text>`);
59798
+ };
59799
+ if (rel.leftCard && pts.length >= 2)
59800
+ placeEndpoint(pts[0], pts[1], rel.leftCard, "start");
59801
+ if (rel.rightCard && pts.length >= 2) {
59802
+ const a3 = pts[pts.length - 1];
59803
+ const b3 = pts[pts.length - 2];
59804
+ placeEndpoint(a3, b3, rel.rightCard, "end");
59805
+ }
59806
+ if (rel.label) {
59807
+ const mid = pts[Math.floor(pts.length / 2)];
59808
+ const words = String(rel.label).split(/\s+/);
59809
+ const lines = [];
59810
+ let cur = "";
59811
+ const maxW = 200;
59812
+ for (const w3 of words) {
59813
+ const test = cur ? cur + " " + w3 : w3;
59814
+ if (measureText(test, 12) <= maxW)
59815
+ cur = test;
59816
+ else {
59817
+ if (cur)
59818
+ lines.push(cur);
59819
+ cur = w3;
59820
+ }
59821
+ }
59822
+ if (cur)
59823
+ lines.push(cur);
59824
+ const dy = 14;
59825
+ let y0 = mid.y - (lines.length - 1) * dy / 2 - 10;
59826
+ parts.push(`<text class="edge-label-text" x="${mid.x}" y="${y0}" text-anchor="middle">` + lines.map((ln, i4) => `<tspan x="${mid.x}" dy="${i4 === 0 ? 0 : dy}">${escapeXml(ln)}</tspan>`).join("") + `</text>`);
59827
+ }
59828
+ const pStart = [pts[0], pts[1] ?? pts[0]];
59829
+ const pEnd = [pts[pts.length - 2] ?? pts[pts.length - 1], pts[pts.length - 1]];
59830
+ switch (rel.kind) {
59831
+ case "extends":
59832
+ parts.push(triangleHollowAt(pEnd, edgeColor, 12, 10, true));
59833
+ break;
59834
+ case "realization":
59835
+ parts.push(triangleHollowAt(pEnd, edgeColor, 12, 10, true));
59836
+ break;
59837
+ case "dependency":
59838
+ parts.push(triangleOpenAt(pEnd, edgeColor, 10, 7, true));
59839
+ break;
59840
+ case "aggregation":
59841
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
59842
+ break;
59843
+ case "composition":
59844
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
59845
+ break;
59846
+ case "aggregation-both":
59847
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
59848
+ parts.push(diamondAt(pEnd, edgeColor, false, 8, false));
59849
+ break;
59850
+ case "composition-both":
59851
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
59852
+ parts.push(diamondAt(pEnd, edgeColor, true, 8, false));
59853
+ break;
59854
+ case "aggregation-to-comp":
59855
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
59856
+ parts.push(diamondAt(pEnd, edgeColor, true, 8, false));
59857
+ break;
59858
+ case "composition-to-agg":
59859
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
59860
+ parts.push(diamondAt(pEnd, edgeColor, false, 8, false));
59861
+ break;
59862
+ case "lollipop-left":
59863
+ parts.push(`<circle class="edge-marker" cx="${pStart[0].x}" cy="${pStart[0].y}" r="5" fill="white" stroke="${edgeColor}" />`);
59864
+ break;
59865
+ case "lollipop-right":
59866
+ parts.push(`<circle class="edge-marker" cx="${pEnd[1].x}" cy="${pEnd[1].y}" r="5" fill="white" stroke="${edgeColor}" />`);
59867
+ break;
59868
+ case "association":
59869
+ default:
59870
+ break;
59871
+ }
59872
+ }
59873
+ const noteW = 140, noteH = 44, dx = 20;
59874
+ const byId = Object.fromEntries(layout.nodes.map((n3) => [n3.id, n3]));
59875
+ const seenAnchorCount = {};
59876
+ const notes = model.notes || [];
59877
+ for (const note of notes) {
59878
+ const anchor = byId[note.target];
59879
+ if (!anchor)
59880
+ continue;
59881
+ const count = seenAnchorCount[note.target] = (seenAnchorCount[note.target] || 0) + 1;
59882
+ const nx = anchor.x + anchor.width + dx;
59883
+ let ny = anchor.y + (count - 1) * (noteH + 8);
59884
+ const overlaps = (x3, y2) => layout.nodes.some((n3) => !(x3 + noteW < n3.x || x3 > n3.x + n3.width || y2 + noteH < n3.y || y2 > n3.y + n3.height));
59885
+ let guard = 0;
59886
+ while (overlaps(nx, ny) && guard < 50) {
59887
+ ny += noteH + 6;
59888
+ guard++;
59889
+ }
59890
+ parts.push(` <g class="note" transform="translate(${nx},${ny})">`);
59891
+ parts.push(` <rect width="${noteW}" height="${noteH}" rx="0"/>`);
59892
+ parts.push(` <text class="note-text" x="${noteW / 2}" y="${noteH / 2 + 4}" text-anchor="middle">${escapeXml(note.text)}</text>`);
59893
+ parts.push(" </g>");
59894
+ const ax = anchor.x + anchor.width;
59895
+ const ay = anchor.y + 16;
59896
+ parts.push(`<line x1="${ax}" y1="${ay}" x2="${nx}" y2="${ny + noteH / 2}" stroke="#999" stroke-dasharray="4 3"/>`);
59897
+ }
59898
+ parts.push("</svg>");
59899
+ return parts.join("\n");
59900
+ }
59901
+ var init_class_renderer = __esm({
59902
+ "node_modules/@probelabs/maid/out/renderer/class-renderer.js"() {
59903
+ init_layout();
59904
+ init_styles();
59905
+ init_utils4();
59906
+ }
59907
+ });
59908
+
57712
59909
  // node_modules/@probelabs/maid/out/renderer/dot-renderer.js
57713
59910
  var init_dot_renderer = __esm({
57714
59911
  "node_modules/@probelabs/maid/out/renderer/dot-renderer.js"() {
@@ -57792,6 +59989,10 @@ function applyFlowchartTheme(svg, theme) {
57792
59989
  out = out.replace(/(<path d="M0,0 L0,[0-9.]+ L[0-9.]+,[0-9.]+ z"[^>]*)(fill="[^"]*")/g, (_m2, p1) => `${p1}fill="${String(theme.arrowheadColor)}"`);
57793
59990
  out = out.replace(/(<circle cx="4\.5" cy="4\.5" r="4\.5"[^>]*)(fill="[^"]*")/g, (_m2, p1) => `${p1}fill="${String(theme.arrowheadColor)}"`);
57794
59991
  }
59992
+ if (theme.edgeLabelTextColor) {
59993
+ const c3 = String(theme.edgeLabelTextColor);
59994
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
59995
+ }
57795
59996
  if (theme.clusterBkg) {
57796
59997
  out = out.replace(/\.cluster-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterBkg)};`));
57797
59998
  }
@@ -57801,6 +60002,12 @@ function applyFlowchartTheme(svg, theme) {
57801
60002
  if (theme.clusterTextColor) {
57802
60003
  out = out.replace(/\.cluster-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterTextColor)};`));
57803
60004
  }
60005
+ if (theme.noteBkg)
60006
+ out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteBkg)};`));
60007
+ if (theme.noteBorder)
60008
+ out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.noteBorder)};`));
60009
+ if (theme.noteTextColor)
60010
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteTextColor)};`));
57804
60011
  if (theme.fontFamily)
57805
60012
  out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${String(theme.fontFamily)};`));
57806
60013
  if (theme.fontSize)
@@ -57823,7 +60030,12 @@ var init_renderer = __esm({
57823
60030
  init_pie_renderer();
57824
60031
  init_sequence_builder();
57825
60032
  init_sequence_renderer();
60033
+ init_styles();
60034
+ init_state_builder();
60035
+ init_state_renderer();
57826
60036
  init_frontmatter();
60037
+ init_class_builder();
60038
+ init_class_renderer();
57827
60039
  init_layout();
57828
60040
  init_svg_generator();
57829
60041
  init_dot_renderer();
@@ -57958,7 +60170,31 @@ var init_renderer = __esm({
57958
60170
  return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
57959
60171
  }
57960
60172
  }
57961
- const errorSvg = this.generateErrorSvg("Unsupported diagram type. Rendering supports flowchart, pie, and sequence for now.");
60173
+ if (/^classDiagram\b/.test(firstLine)) {
60174
+ try {
60175
+ const model = buildClassModel(content);
60176
+ const svg = renderClass(model, { theme });
60177
+ const themed = theme ? applyFlowLikeTheme(svg, theme) : svg;
60178
+ return { svg: themed, graph: { nodes: [], edges: [], direction: model.direction }, errors: [] };
60179
+ } catch (e3) {
60180
+ const msg = e3?.message || "Class render error";
60181
+ const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "CLASS_RENDER" }];
60182
+ return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
60183
+ }
60184
+ }
60185
+ if (/^stateDiagram(?:-v2)?\b/.test(firstLine)) {
60186
+ try {
60187
+ const model = buildStateModel(content);
60188
+ const svg = renderState(model);
60189
+ const themed = theme ? applyFlowLikeTheme(svg, theme) : svg;
60190
+ return { svg: themed, graph: { nodes: [], edges: [], direction: model.direction }, errors: [] };
60191
+ } catch (e3) {
60192
+ const msg = e3?.message || "State render error";
60193
+ const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "STATE_RENDER" }];
60194
+ return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
60195
+ }
60196
+ }
60197
+ const errorSvg = this.generateErrorSvg("Unsupported diagram type. Rendering supports flowchart, pie, sequence, class, and state.");
57962
60198
  return {
57963
60199
  svg: errorSvg,
57964
60200
  graph: { nodes: [], edges: [], direction: "TD" },
@@ -58352,13 +60588,14 @@ async function validateMermaidDiagram(diagram) {
58352
60588
  };
58353
60589
  }
58354
60590
  const result = validate(diagram);
58355
- if (result.errors && result.errors.length === 0) {
60591
+ const actualErrors = (result.errors || []).filter((err) => err.severity === "error");
60592
+ if (actualErrors.length === 0) {
58356
60593
  return {
58357
60594
  isValid: true,
58358
60595
  diagramType: result.type || "unknown"
58359
60596
  };
58360
60597
  } else {
58361
- const errorMessages = (result.errors || []).map((err) => {
60598
+ const errorMessages = actualErrors.map((err) => {
58362
60599
  const location = err.line ? `line ${err.line}${err.column ? `:${err.column}` : ""}` : "";
58363
60600
  return location ? `${location} - ${err.message}` : err.message;
58364
60601
  });
@@ -58367,8 +60604,8 @@ async function validateMermaidDiagram(diagram) {
58367
60604
  diagramType: result.type || "unknown",
58368
60605
  error: errorMessages[0] || "Validation failed",
58369
60606
  detailedError: errorMessages.join("\n"),
58370
- errors: result.errors || []
58371
- // Include raw maid errors for AI fixing
60607
+ errors: actualErrors
60608
+ // Include only actual errors for AI fixing
58372
60609
  };
58373
60610
  }
58374
60611
  } catch (error2) {
@@ -59256,10 +61493,19 @@ var init_client2 = __esm({
59256
61493
  if (this.debug) {
59257
61494
  console.error(`[MCP] Calling ${toolName} with args:`, args);
59258
61495
  }
59259
- const result = await clientInfo.client.callTool({
59260
- name: tool3.originalName,
59261
- arguments: args
61496
+ const timeout = this.config?.settings?.timeout || 3e4;
61497
+ const timeoutPromise = new Promise((_2, reject2) => {
61498
+ setTimeout(() => {
61499
+ reject2(new Error(`MCP tool call timeout after ${timeout}ms`));
61500
+ }, timeout);
59262
61501
  });
61502
+ const result = await Promise.race([
61503
+ clientInfo.client.callTool({
61504
+ name: tool3.originalName,
61505
+ arguments: args
61506
+ }),
61507
+ timeoutPromise
61508
+ ]);
59263
61509
  return result;
59264
61510
  } catch (error2) {
59265
61511
  console.error(`[MCP] Error calling tool ${toolName}:`, error2);
@@ -59673,11 +61919,39 @@ var init_ProbeAgent = __esm({
59673
61919
  this.mcpServers = options.mcpServers || null;
59674
61920
  this.mcpBridge = null;
59675
61921
  this.initializeModel();
61922
+ }
61923
+ /**
61924
+ * Initialize the agent asynchronously (must be called after constructor)
61925
+ * This method initializes MCP and merges MCP tools into the tool list
61926
+ */
61927
+ async initialize() {
59676
61928
  if (this.enableMcp) {
59677
- this.initializeMCP().catch((error2) => {
61929
+ try {
61930
+ await this.initializeMCP();
61931
+ if (this.mcpBridge) {
61932
+ const mcpTools = this.mcpBridge.mcpTools || {};
61933
+ for (const [toolName, toolImpl] of Object.entries(mcpTools)) {
61934
+ this.toolImplementations[toolName] = toolImpl;
61935
+ }
61936
+ }
61937
+ if (this.debug) {
61938
+ const allToolNames = Object.keys(this.toolImplementations);
61939
+ const nativeToolCount = allToolNames.filter((name14) => !this.mcpBridge?.mcpTools?.[name14]).length;
61940
+ const mcpToolCount = allToolNames.length - nativeToolCount;
61941
+ console.error("\n[DEBUG] ========================================");
61942
+ console.error("[DEBUG] All Tools Initialized");
61943
+ console.error(`[DEBUG] Native tools: ${nativeToolCount}, MCP tools: ${mcpToolCount}`);
61944
+ console.error("[DEBUG] Available tools:");
61945
+ for (const toolName of allToolNames) {
61946
+ const isMCP = this.mcpBridge?.mcpTools?.[toolName] ? " (MCP)" : "";
61947
+ console.error(`[DEBUG] - ${toolName}${isMCP}`);
61948
+ }
61949
+ console.error("[DEBUG] ========================================\n");
61950
+ }
61951
+ } catch (error2) {
59678
61952
  console.error("[MCP] Failed to initialize MCP:", error2);
59679
61953
  this.mcpBridge = null;
59680
- });
61954
+ }
59681
61955
  }
59682
61956
  }
59683
61957
  /**
@@ -59904,20 +62178,40 @@ var init_ProbeAgent = __esm({
59904
62178
  }
59905
62179
  }
59906
62180
  /**
59907
- * Extract directory paths from listFiles tool output
62181
+ * Extract directory paths from tool output (both listFiles and extract tool)
59908
62182
  * @param {string} content - Tool output content
59909
62183
  * @returns {string[]} - Array of directory paths
59910
62184
  */
59911
62185
  extractListFilesDirectories(content) {
59912
62186
  const directories = [];
59913
- const dirPattern = /^([^\n:]+):\s*$/gm;
62187
+ const fileHeaderPattern = /^File:\s+(.+)$/gm;
59914
62188
  let match;
62189
+ while ((match = fileHeaderPattern.exec(content)) !== null) {
62190
+ const filePath = match[1].trim();
62191
+ const dir = (0, import_path10.dirname)(filePath);
62192
+ if (dir && dir !== ".") {
62193
+ directories.push(dir);
62194
+ if (this.debug) {
62195
+ console.log(`[DEBUG] Extracted directory context from File header: ${dir}`);
62196
+ }
62197
+ }
62198
+ }
62199
+ const dirPattern = /^(\/[^\n:]+|[A-Z]:\\[^\n:]+|\.\.?(?:\/[^\n:]+)?):\s*$/gm;
59915
62200
  while ((match = dirPattern.exec(content)) !== null) {
59916
62201
  const dirPath = match[1].trim();
59917
- if (dirPath && dirPath.length > 0) {
59918
- directories.push(dirPath);
59919
- if (this.debug) {
59920
- console.log(`[DEBUG] Extracted directory context from listFiles: ${dirPath}`);
62202
+ const hasInvalidChars = /\s/.test(dirPath);
62203
+ const isValidPath = !hasInvalidChars && (dirPath.startsWith("/") || // Unix absolute path
62204
+ /^[A-Z]:\\/.test(dirPath) || // Windows absolute path (C:\)
62205
+ dirPath === "." || // Current directory
62206
+ dirPath === ".." || // Parent directory
62207
+ dirPath.startsWith("./") && dirPath.length > 2 && !dirPath.includes(" ") || // ./something (no spaces)
62208
+ dirPath.startsWith("../") && dirPath.length > 3 && !dirPath.includes(" "));
62209
+ if (isValidPath) {
62210
+ if (!directories.includes(dirPath)) {
62211
+ directories.push(dirPath);
62212
+ if (this.debug) {
62213
+ console.log(`[DEBUG] Extracted directory context from listFiles: ${dirPath}`);
62214
+ }
59921
62215
  }
59922
62216
  }
59923
62217
  }