@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.
package/cjs/index.cjs CHANGED
@@ -42864,7 +42864,7 @@ function tokenize(text) {
42864
42864
  const lexResult = MermaidLexer.tokenize(text);
42865
42865
  return lexResult;
42866
42866
  }
42867
- 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;
42867
+ 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;
42868
42868
  var init_lexer2 = __esm({
42869
42869
  "node_modules/@probelabs/maid/out/diagrams/flowchart/lexer.js"() {
42870
42870
  init_api5();
@@ -42917,6 +42917,8 @@ var init_lexer2 = __esm({
42917
42917
  pattern: /classDef/,
42918
42918
  longer_alt: Identifier
42919
42919
  });
42920
+ ClickKeyword = createToken({ name: "ClickKeyword", pattern: /click/, longer_alt: Identifier });
42921
+ LinkStyleKeyword = createToken({ name: "LinkStyleKeyword", pattern: /linkStyle/, longer_alt: Identifier });
42920
42922
  Ampersand = createToken({
42921
42923
  name: "Ampersand",
42922
42924
  pattern: /&/
@@ -43011,6 +43013,7 @@ var init_lexer2 = __esm({
43011
43013
  DiamondClose = createToken({ name: "DiamondClose", pattern: /\}/ });
43012
43014
  AngleOpen = createToken({ name: "AngleOpen", pattern: />/ });
43013
43015
  AngleLess = createToken({ name: "AngleLess", pattern: /</ });
43016
+ AtSign = createToken({ name: "AtSign", pattern: /@/ });
43014
43017
  Pipe = createToken({ name: "Pipe", pattern: /\|/ });
43015
43018
  ForwardSlash = createToken({ name: "ForwardSlash", pattern: /\// });
43016
43019
  Backslash = createToken({ name: "Backslash", pattern: /\\/ });
@@ -43061,6 +43064,8 @@ var init_lexer2 = __esm({
43061
43064
  ClassDefKeyword,
43062
43065
  ClassKeyword,
43063
43066
  StyleKeyword,
43067
+ ClickKeyword,
43068
+ LinkStyleKeyword,
43064
43069
  Direction,
43065
43070
  // Special multi-char brackets before arrows (some contain > or -)
43066
43071
  DoubleSquareOpen,
@@ -43097,6 +43102,7 @@ var init_lexer2 = __esm({
43097
43102
  DiamondClose,
43098
43103
  AngleOpen,
43099
43104
  AngleLess,
43105
+ AtSign,
43100
43106
  ForwardSlash,
43101
43107
  Backslash,
43102
43108
  Pipe,
@@ -43153,9 +43159,12 @@ var init_parser2 = __esm({
43153
43159
  this.OR([
43154
43160
  { ALT: () => this.SUBRULE(this.nodeStatement) },
43155
43161
  { ALT: () => this.SUBRULE(this.subgraph) },
43162
+ { ALT: () => this.SUBRULE(this.directionStatement) },
43156
43163
  { ALT: () => this.SUBRULE(this.classStatement) },
43157
43164
  { ALT: () => this.SUBRULE(this.styleStatement) },
43158
43165
  { ALT: () => this.SUBRULE(this.classDefStatement) },
43166
+ { ALT: () => this.SUBRULE(this.clickStatement) },
43167
+ { ALT: () => this.SUBRULE(this.linkStyleStatement) },
43159
43168
  { ALT: () => this.CONSUME(Newline) }
43160
43169
  // Empty lines
43161
43170
  ]);
@@ -43191,6 +43200,7 @@ var init_parser2 = __esm({
43191
43200
  this.OPTION(() => {
43192
43201
  this.CONSUME(NumberLiteral, { LABEL: "nodeIdSuffix" });
43193
43202
  });
43203
+ this.OPTION1(() => this.SUBRULE(this.attrObject));
43194
43204
  }
43195
43205
  },
43196
43206
  {
@@ -43207,6 +43217,146 @@ var init_parser2 = __esm({
43207
43217
  this.CONSUME3(Identifier, { LABEL: "nodeClass" });
43208
43218
  });
43209
43219
  });
43220
+ this.attrObject = this.RULE("attrObject", () => {
43221
+ this.CONSUME(AtSign);
43222
+ this.CONSUME(DiamondOpen, { LABEL: "attrLCurly" });
43223
+ this.OPTION(() => {
43224
+ this.SUBRULE(this.attrPair);
43225
+ this.MANY(() => {
43226
+ this.CONSUME(Comma);
43227
+ this.SUBRULE2(this.attrPair);
43228
+ });
43229
+ });
43230
+ this.CONSUME(DiamondClose, { LABEL: "attrRCurly" });
43231
+ });
43232
+ this.attrPair = this.RULE("attrPair", () => {
43233
+ this.CONSUME(Identifier, { LABEL: "attrKey" });
43234
+ this.CONSUME(Colon);
43235
+ this.OR([
43236
+ {
43237
+ GATE: () => {
43238
+ const prev = this.LA(-1);
43239
+ const keyTok = this.LA(-2);
43240
+ return keyTok && /^(shape)$/i.test(String(keyTok.image || ""));
43241
+ },
43242
+ ALT: () => this.SUBRULE(this.attrShapeValue)
43243
+ },
43244
+ { ALT: () => this.CONSUME(QuotedString) },
43245
+ { ALT: () => this.CONSUME2(Identifier) },
43246
+ { ALT: () => this.CONSUME(NumberLiteral) },
43247
+ { ALT: () => this.CONSUME(Text) }
43248
+ ]);
43249
+ });
43250
+ this.attrShapeValue = this.RULE("attrShapeValue", () => {
43251
+ const isKnownShapeId = () => {
43252
+ const la = this.LA(1);
43253
+ if (!la || la.tokenType !== Identifier)
43254
+ return false;
43255
+ const v3 = String(la.image || "").toLowerCase();
43256
+ 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";
43257
+ };
43258
+ const isKnownShapeQuoted = () => {
43259
+ const la = this.LA(1);
43260
+ if (!la || la.tokenType !== QuotedString)
43261
+ return false;
43262
+ const raw = String(la.image || "");
43263
+ const unq = raw.length >= 2 && (raw.startsWith('"') || raw.startsWith("'")) ? raw.slice(1, -1) : raw;
43264
+ const v3 = unq.toLowerCase();
43265
+ 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";
43266
+ };
43267
+ this.OR([
43268
+ { GATE: isKnownShapeId, ALT: () => this.CONSUME(Identifier, { LABEL: "shapeId" }) },
43269
+ { GATE: isKnownShapeQuoted, ALT: () => this.CONSUME(QuotedString, { LABEL: "shapeQuoted" }) },
43270
+ // Fallback: accept any identifier/quoted/number/text so parse continues; semantics will flag unknowns
43271
+ { ALT: () => this.CONSUME2(Identifier) },
43272
+ { ALT: () => this.CONSUME2(QuotedString) },
43273
+ { ALT: () => this.CONSUME(NumberLiteral) },
43274
+ { ALT: () => this.CONSUME(Text) }
43275
+ ]);
43276
+ });
43277
+ this.clickStatement = this.RULE("clickStatement", () => {
43278
+ this.CONSUME(ClickKeyword);
43279
+ this.CONSUME(Identifier, { LABEL: "clickTarget" });
43280
+ this.OR([
43281
+ {
43282
+ GATE: () => this.LA(1).tokenType === Identifier && /^(href)$/i.test(this.LA(1).image || ""),
43283
+ ALT: () => this.SUBRULE(this.clickHref)
43284
+ },
43285
+ {
43286
+ GATE: () => this.LA(1).tokenType === Identifier && /^(call|callback)$/i.test(this.LA(1).image || ""),
43287
+ ALT: () => this.SUBRULE(this.clickCall)
43288
+ }
43289
+ ]);
43290
+ this.OPTION(() => this.CONSUME(Newline));
43291
+ });
43292
+ this.clickHref = this.RULE("clickHref", () => {
43293
+ this.CONSUME(Identifier, { LABEL: "mode" });
43294
+ this.CONSUME(QuotedString, { LABEL: "url" });
43295
+ this.OPTION(() => this.CONSUME2(QuotedString, { LABEL: "tooltip" }));
43296
+ this.OPTION2(() => this.CONSUME2(Identifier, { LABEL: "target" }));
43297
+ });
43298
+ this.clickCall = this.RULE("clickCall", () => {
43299
+ this.CONSUME1(Identifier, { LABEL: "mode" });
43300
+ this.OPTION1(() => {
43301
+ this.CONSUME2(Identifier, { LABEL: "fn" });
43302
+ this.OPTION2(() => {
43303
+ this.CONSUME3(RoundOpen);
43304
+ this.OPTION3(() => {
43305
+ this.OR([
43306
+ { ALT: () => this.CONSUME4(Identifier) },
43307
+ { ALT: () => this.CONSUME5(NumberLiteral) },
43308
+ { ALT: () => this.CONSUME6(Text) }
43309
+ ]);
43310
+ });
43311
+ this.CONSUME7(RoundClose);
43312
+ });
43313
+ });
43314
+ this.OPTION4(() => this.CONSUME8(QuotedString, { LABEL: "tooltip" }));
43315
+ });
43316
+ this.linkStyleStatement = this.RULE("linkStyleStatement", () => {
43317
+ this.CONSUME(LinkStyleKeyword);
43318
+ this.SUBRULE(this.linkStyleIndexList);
43319
+ this.OPTION1(() => this.CONSUME1(Newline));
43320
+ this.SUBRULE(this.linkStylePairs);
43321
+ this.OPTION2(() => this.CONSUME2(Newline));
43322
+ });
43323
+ this.linkStyleIndexList = this.RULE("linkStyleIndexList", () => {
43324
+ this.CONSUME(NumberLiteral, { LABEL: "index" });
43325
+ this.MANY(() => {
43326
+ this.CONSUME(Comma);
43327
+ this.CONSUME2(NumberLiteral, { LABEL: "index" });
43328
+ });
43329
+ });
43330
+ this.linkStylePairs = this.RULE("linkStylePairs", () => {
43331
+ this.SUBRULE(this.linkStylePair);
43332
+ this.MANY(() => {
43333
+ this.CONSUME(Comma);
43334
+ this.OPTION(() => this.CONSUME(Newline));
43335
+ this.SUBRULE2(this.linkStylePair);
43336
+ });
43337
+ });
43338
+ this.linkStylePair = this.RULE("linkStylePair", () => {
43339
+ this.CONSUME1(Identifier, { LABEL: "key" });
43340
+ this.CONSUME(Colon);
43341
+ this.SUBRULE(this.linkStyleValueChunk);
43342
+ });
43343
+ this.linkStyleValueChunk = this.RULE("linkStyleValueChunk", () => {
43344
+ this.AT_LEAST_ONE({
43345
+ GATE: () => {
43346
+ const la = this.LA(1);
43347
+ return la && la.tokenType !== Comma && la.tokenType !== Newline;
43348
+ },
43349
+ DEF: () => {
43350
+ this.OR([
43351
+ { ALT: () => this.CONSUME(ColorValue) },
43352
+ { ALT: () => this.CONSUME(QuotedString) },
43353
+ { ALT: () => this.CONSUME(NumberLiteral) },
43354
+ { ALT: () => this.CONSUME(Identifier) },
43355
+ { ALT: () => this.CONSUME(Text) }
43356
+ ]);
43357
+ }
43358
+ });
43359
+ });
43210
43360
  this.nodeShape = this.RULE("nodeShape", () => {
43211
43361
  this.OR([
43212
43362
  // Square brackets: [text]
@@ -43310,6 +43460,10 @@ var init_parser2 = __esm({
43310
43460
  ]);
43311
43461
  });
43312
43462
  this.link = this.RULE("link", () => {
43463
+ this.OPTION1(() => {
43464
+ this.CONSUME(Identifier, { LABEL: "edgeId" });
43465
+ this.CONSUME(AtSign);
43466
+ });
43313
43467
  this.OR([
43314
43468
  // Arrows with inline text (e.g., -.text.-> or ==text==>)
43315
43469
  {
@@ -43350,7 +43504,7 @@ var init_parser2 = __esm({
43350
43504
  { ALT: () => this.CONSUME(InvalidArrow) }
43351
43505
  // Capture for error
43352
43506
  ]);
43353
- this.OPTION(() => {
43507
+ this.OPTION2(() => {
43354
43508
  this.CONSUME(Pipe);
43355
43509
  this.SUBRULE(this.linkText);
43356
43510
  this.CONSUME2(Pipe);
@@ -43512,26 +43666,66 @@ var init_parser2 = __esm({
43512
43666
  // node_modules/@probelabs/maid/out/diagrams/flowchart/semantics.js
43513
43667
  function analyzeFlowchart(cst, _tokens, opts) {
43514
43668
  const ctx = { errors: [], strict: opts?.strict };
43515
- const v3 = new FlowSemanticsVisitor(ctx);
43669
+ const collector = new NodeIdCollector();
43670
+ collector.visit(cst);
43671
+ const v3 = new FlowSemanticsVisitor(ctx, collector.ids, collector.edgeIds);
43516
43672
  v3.visit(cst);
43517
43673
  return ctx.errors;
43518
43674
  }
43519
- var BaseVisitor, FlowSemanticsVisitor;
43675
+ var BaseVisitor, FlowSemanticsVisitor, NodeIdCollector;
43520
43676
  var init_semantics = __esm({
43521
43677
  "node_modules/@probelabs/maid/out/diagrams/flowchart/semantics.js"() {
43522
43678
  init_parser2();
43523
43679
  BaseVisitor = parserInstance.getBaseCstVisitorConstructorWithDefaults();
43524
43680
  FlowSemanticsVisitor = class extends BaseVisitor {
43525
- constructor(ctx) {
43681
+ constructor(ctx, knownIds, knownEdgeIds) {
43526
43682
  super();
43683
+ this.edgeCount = 0;
43527
43684
  this.validateVisitor();
43528
43685
  this.ctx = ctx;
43686
+ this.knownIds = knownIds;
43687
+ this.knownEdgeIds = knownEdgeIds;
43529
43688
  }
43530
43689
  // Entry point
43531
43690
  diagram(ctx) {
43532
43691
  if (ctx.statement)
43533
43692
  ctx.statement.forEach((s3) => this.visit(s3));
43534
43693
  }
43694
+ classStatement(ctx) {
43695
+ const ids = ctx.Identifier || [];
43696
+ const classNameTok = ctx.className && ctx.className[0];
43697
+ for (const idTok of ids) {
43698
+ if (classNameTok && idTok.startOffset === classNameTok.startOffset)
43699
+ continue;
43700
+ const id = String(idTok.image);
43701
+ if (!(this.knownIds.has(id) || this.knownEdgeIds.has(id))) {
43702
+ this.ctx.errors.push({
43703
+ line: idTok.startLine ?? 1,
43704
+ column: idTok.startColumn ?? 1,
43705
+ severity: "warning",
43706
+ code: "FL-CLASS-TARGET-UNKNOWN",
43707
+ message: `Unknown id '${id}' in class statement.`,
43708
+ hint: "Define the node/link before applying classes, or move the class line after it."
43709
+ });
43710
+ }
43711
+ }
43712
+ }
43713
+ styleStatement(ctx) {
43714
+ const idTok = ctx.Identifier && ctx.Identifier[0];
43715
+ if (idTok) {
43716
+ const id = String(idTok.image);
43717
+ if (!this.knownIds.has(id)) {
43718
+ this.ctx.errors.push({
43719
+ line: idTok.startLine ?? 1,
43720
+ column: idTok.startColumn ?? 1,
43721
+ severity: "warning",
43722
+ code: "FL-STYLE-TARGET-UNKNOWN",
43723
+ message: `Unknown node id '${id}' in style statement.`,
43724
+ hint: "Define the node before styling it, or move the style line after the node definition."
43725
+ });
43726
+ }
43727
+ }
43728
+ }
43535
43729
  statement(ctx) {
43536
43730
  for (const k3 of Object.keys(ctx)) {
43537
43731
  const arr = ctx[k3];
@@ -43543,6 +43737,141 @@ var init_semantics = __esm({
43543
43737
  }
43544
43738
  }
43545
43739
  }
43740
+ clickStatement(ctx) {
43741
+ const href = ctx.clickHref?.[0];
43742
+ const call = !href ? ctx.clickCall?.[0] : void 0;
43743
+ if (href) {
43744
+ const ch = href.children || {};
43745
+ const modeTok2 = ch.mode?.[0];
43746
+ const urlTok = ch.url?.[0];
43747
+ const tipTok = ch.tooltip?.[0];
43748
+ const tgtTok = ch.target?.[0];
43749
+ const mode2 = String(modeTok2?.image || "").toLowerCase();
43750
+ if (mode2 !== "href") {
43751
+ 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()' });
43752
+ return;
43753
+ }
43754
+ if (!urlTok) {
43755
+ 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' });
43756
+ }
43757
+ if (tgtTok && !/^_(blank|self|parent|top)$/i.test(String(tgtTok.image || ""))) {
43758
+ 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" });
43759
+ }
43760
+ return;
43761
+ }
43762
+ if (call) {
43763
+ const ch = call.children || {};
43764
+ const modeTok2 = ch.mode?.[0];
43765
+ const mode2 = String(modeTok2?.image || "").toLowerCase();
43766
+ if (!(mode2 === "call" || mode2 === "callback")) {
43767
+ 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()' });
43768
+ return;
43769
+ }
43770
+ const fnTok = ch.fn?.[0];
43771
+ if (!fnTok) {
43772
+ 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"' });
43773
+ }
43774
+ const tipTok = ch.tooltip?.[0];
43775
+ if (tipTok) {
43776
+ 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()" });
43777
+ }
43778
+ return;
43779
+ }
43780
+ const ids = ctx.Identifier || [];
43781
+ const q3 = ctx.QuotedString || [];
43782
+ const t0 = ids[0];
43783
+ const modeTok = ids[1];
43784
+ const mode = (modeTok?.image || "").toLowerCase();
43785
+ if (!mode) {
43786
+ this.ctx.errors.push({
43787
+ line: t0?.startLine ?? 1,
43788
+ column: t0?.startColumn ?? 1,
43789
+ severity: "error",
43790
+ code: "FL-CLICK-MODE-MISSING",
43791
+ message: "After 'click <id>' specify 'href' or 'call'.",
43792
+ hint: 'Examples: click A href "https://\u2026" "Tip" _blank | click A call doThing() "Tip"'
43793
+ });
43794
+ return;
43795
+ }
43796
+ if (mode === "href") {
43797
+ if (q3.length < 1) {
43798
+ this.ctx.errors.push({
43799
+ line: modeTok.startLine ?? 1,
43800
+ column: modeTok.startColumn ?? 1,
43801
+ severity: "error",
43802
+ code: "FL-CLICK-HREF-URL-MISSING",
43803
+ message: "'click \u2026 href' requires a quoted URL.",
43804
+ hint: 'Example: click A href "https://example.com" "Open" _blank'
43805
+ });
43806
+ }
43807
+ const tgt = ids[2];
43808
+ if (tgt && !/^_(blank|self|parent|top)$/i.test(tgt.image || "")) {
43809
+ this.ctx.errors.push({
43810
+ line: tgt.startLine ?? 1,
43811
+ column: tgt.startColumn ?? 1,
43812
+ severity: "warning",
43813
+ code: "FL-CLICK-TARGET-UNKNOWN",
43814
+ message: `Unknown target '${tgt.image}'. Use _blank/_self/_parent/_top.`,
43815
+ hint: "Example: \u2026 _blank"
43816
+ });
43817
+ }
43818
+ return;
43819
+ }
43820
+ if (mode === "call" || mode === "callback") {
43821
+ const fnTok = ids[2];
43822
+ if (!fnTok) {
43823
+ this.ctx.errors.push({
43824
+ line: modeTok.startLine ?? 1,
43825
+ column: modeTok.startColumn ?? 1,
43826
+ severity: "error",
43827
+ code: "FL-CLICK-CALL-NAME-MISSING",
43828
+ message: "'click \u2026 call' requires a function name.",
43829
+ hint: 'Example: click A call doThing() "Tooltip"'
43830
+ });
43831
+ }
43832
+ return;
43833
+ }
43834
+ this.ctx.errors.push({
43835
+ line: modeTok.startLine ?? 1,
43836
+ column: modeTok.startColumn ?? 1,
43837
+ severity: "error",
43838
+ code: "FL-CLICK-MODE-INVALID",
43839
+ message: `Unknown click mode '${modeTok.image}'. Use 'href' or 'call'.`,
43840
+ hint: 'Examples: href "\u2026" | call fn()'
43841
+ });
43842
+ }
43843
+ linkStyleStatement(ctx) {
43844
+ const idxNode = ctx.linkStyleIndexList?.[0];
43845
+ const pairNode = ctx.linkStylePairs?.[0];
43846
+ const getTokens = (node, name14) => node ? (node.children || {})[name14] || [] : [];
43847
+ const idxToks = getTokens(idxNode, "index");
43848
+ const nums = idxToks.map((t3) => parseInt(t3.image, 10)).filter((n3) => Number.isFinite(n3));
43849
+ if (nums.length === 0) {
43850
+ const anyTok = ctx.LinkStyleKeyword?.[0] || idxToks[0];
43851
+ 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" });
43852
+ return;
43853
+ }
43854
+ const pairChildren = pairNode?.children || {};
43855
+ const pairCount = (pairChildren.linkStylePair || []).length;
43856
+ if (!pairCount) {
43857
+ const firstNum = idxToks[0];
43858
+ 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" });
43859
+ }
43860
+ const seen = /* @__PURE__ */ new Set();
43861
+ for (const n3 of nums) {
43862
+ if (seen.has(n3)) {
43863
+ const numTok = idxToks.find((t3) => parseInt(t3.image, 10) === n3);
43864
+ 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." });
43865
+ }
43866
+ seen.add(n3);
43867
+ }
43868
+ for (const n3 of nums) {
43869
+ if (!(n3 >= 0 && n3 < this.edgeCount)) {
43870
+ const numTok = idxToks.find((t3) => parseInt(t3.image, 10) === n3);
43871
+ 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.` });
43872
+ }
43873
+ }
43874
+ }
43546
43875
  subgraph(ctx) {
43547
43876
  if (ctx.subgraphStatement)
43548
43877
  ctx.subgraphStatement.forEach((s3) => this.visit(s3));
@@ -43575,14 +43904,109 @@ var init_semantics = __esm({
43575
43904
  nodeStatement(ctx) {
43576
43905
  if (ctx.nodeOrParallelGroup)
43577
43906
  ctx.nodeOrParallelGroup.forEach((n3) => this.visit(n3));
43578
- }
43907
+ const linksHere = Array.isArray(ctx.link) ? ctx.link.length : 0;
43908
+ if (linksHere > 0)
43909
+ this.edgeCount += linksHere;
43910
+ }
43911
+ // Edge attribute object statements must target a known edge id
43912
+ // Edge attribute statements are parsed as nodeStatements with a typed attrObject and no links.
43913
+ // If such a line targets a known edge id, treat it as edge-attr at build time; otherwise keep as a node.
43914
+ // 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).
43915
+ // We keep this heuristic conservative to avoid false positives on typed node shapes.
43916
+ // (Validation that applies the attributes happens in the builder.)
43579
43917
  nodeOrParallelGroup(ctx) {
43580
43918
  if (ctx.node)
43581
43919
  ctx.node.forEach((n3) => this.visit(n3));
43582
43920
  }
43583
43921
  node(ctx) {
43922
+ const hasAttr = Array.isArray(ctx.attrObject) && ctx.attrObject.length > 0;
43923
+ const hasShape = Array.isArray(ctx.nodeShape) && ctx.nodeShape.length > 0;
43924
+ if (hasAttr && hasShape) {
43925
+ const tokArr = ctx.attrObject?.[0]?.children?.attrLCurly || [];
43926
+ const tok = tokArr[0];
43927
+ this.ctx.errors.push({
43928
+ line: tok?.startLine ?? 1,
43929
+ column: tok?.startColumn ?? 1,
43930
+ severity: "warning",
43931
+ code: "FL-TYPED-SHAPE-CONFLICT",
43932
+ message: "Both bracket shape and '@{ shape: \u2026 }' provided. Bracket shape will be used.",
43933
+ hint: 'Pick one style: either A[Label] or A@{ shape: rect, label: "Label" }'
43934
+ });
43935
+ }
43584
43936
  if (ctx.nodeShape)
43585
43937
  ctx.nodeShape.forEach((n3) => this.visit(n3));
43938
+ if (hasAttr) {
43939
+ const attr = ctx.attrObject?.[0];
43940
+ const pairs = attr?.children?.attrPair || [];
43941
+ const validKeys = /* @__PURE__ */ new Set(["shape", "label", "padding", "cornerRadius", "icon", "image"]);
43942
+ const shapes = /* @__PURE__ */ new Set(["rect", "round", "rounded", "stadium", "subroutine", "circle", "cylinder", "diamond", "trapezoid", "trapezoidAlt", "parallelogram", "hexagon", "lean-l", "lean-r", "icon", "image"]);
43943
+ for (const p3 of pairs) {
43944
+ const keyTok = p3.children?.attrKey?.[0];
43945
+ const valTok = p3.children?.QuotedString?.[0] || p3.children?.Identifier?.[0] || p3.children?.NumberLiteral?.[0] || p3.children?.Text?.[0];
43946
+ if (!keyTok)
43947
+ continue;
43948
+ const key = keyTok.image;
43949
+ if (!validKeys.has(key)) {
43950
+ this.ctx.errors.push({
43951
+ line: keyTok.startLine ?? 1,
43952
+ column: keyTok.startColumn ?? 1,
43953
+ severity: "warning",
43954
+ code: "FL-TYPED-KEY-UNKNOWN",
43955
+ message: `Unknown typed-shape key '${key}'.`,
43956
+ hint: "Allowed keys: shape, label, padding, cornerRadius, icon, image"
43957
+ });
43958
+ continue;
43959
+ }
43960
+ if (key === "shape" && valTok) {
43961
+ const v3 = String(valTok.image).replace(/^"|"$/g, "");
43962
+ if (!shapes.has(v3)) {
43963
+ this.ctx.errors.push({
43964
+ line: valTok.startLine ?? 1,
43965
+ column: valTok.startColumn ?? 1,
43966
+ severity: "error",
43967
+ code: "FL-TYPED-SHAPE-UNKNOWN",
43968
+ message: `Unknown shape '${v3}' in '@{ shape: \u2026 }'.`,
43969
+ hint: "Use one of: rect, round, stadium, subroutine, circle, cylinder, diamond, trapezoid, parallelogram, hexagon, lean-l, lean-r, icon, image"
43970
+ });
43971
+ } else {
43972
+ const supportedByCli = /* @__PURE__ */ new Set(["rect", "round", "rounded", "diamond", "circle", "cylinder", "stadium", "subroutine", "lean-l", "lean-r"]);
43973
+ if (!supportedByCli.has(v3)) {
43974
+ this.ctx.errors.push({
43975
+ line: valTok.startLine ?? 1,
43976
+ column: valTok.startColumn ?? 1,
43977
+ severity: "error",
43978
+ code: "FL-TYPED-SHAPE-UNSUPPORTED",
43979
+ message: `Typed shape '${v3}' is not supported by current Mermaid CLI.`,
43980
+ hint: 'Use one of: rect, rounded, diamond, circle, cylinder, stadium, subroutine, "lean-l", "lean-r"'
43981
+ });
43982
+ }
43983
+ }
43984
+ }
43985
+ if (key === "label" && valTok && valTok.tokenType?.name !== "QuotedString") {
43986
+ this.ctx.errors.push({
43987
+ line: valTok.startLine ?? 1,
43988
+ column: valTok.startColumn ?? 1,
43989
+ severity: "warning",
43990
+ code: "FL-TYPED-LABEL-NOT-STRING",
43991
+ message: "Typed-shape 'label' should be a quoted string.",
43992
+ hint: 'Example: A@{ shape: rect, label: "Start" }'
43993
+ });
43994
+ }
43995
+ if ((key === "padding" || key === "cornerRadius") && valTok) {
43996
+ const raw = String(valTok.image).replace(/^"|"$/g, "");
43997
+ if (!/^\d+(px)?$/.test(raw)) {
43998
+ this.ctx.errors.push({
43999
+ line: valTok.startLine ?? 1,
44000
+ column: valTok.startColumn ?? 1,
44001
+ severity: "warning",
44002
+ code: "FL-TYPED-NUMERIC-EXPECTED",
44003
+ message: `'${key}' expects a number (optionally with px).`,
44004
+ hint: `Use: ${key}: 8 or ${key}: "8px"`
44005
+ });
44006
+ }
44007
+ }
44008
+ }
44009
+ }
43586
44010
  }
43587
44011
  checkEmptyContent(openTok, contentNodes) {
43588
44012
  if (!contentNodes || contentNodes.length === 0) {
@@ -43718,6 +44142,7 @@ var init_semantics = __esm({
43718
44142
  if (openTok) {
43719
44143
  this.checkEmptyContent(openTok, contentNodes.length ? contentNodes : void 0);
43720
44144
  this.checkDoubleInSingleQuoted(contentNodes);
44145
+ this.checkBackticksInContent(contentNodes);
43721
44146
  this.warnParensInUnquoted(contentNodes);
43722
44147
  if (this.ctx.strict) {
43723
44148
  let quoted = false;
@@ -43746,6 +44171,93 @@ var init_semantics = __esm({
43746
44171
  }
43747
44172
  }
43748
44173
  }
44174
+ checkBackticksInContent(contentNodes) {
44175
+ if (!contentNodes)
44176
+ return;
44177
+ for (const cn of contentNodes) {
44178
+ const ch = cn.children || {};
44179
+ const inspectTok = (tk) => {
44180
+ if (!tk)
44181
+ return false;
44182
+ const img = String(tk.image || "");
44183
+ const idx = img.indexOf("`");
44184
+ if (idx >= 0) {
44185
+ const col = (tk.startColumn ?? 1) + idx;
44186
+ this.ctx.errors.push({
44187
+ line: tk.startLine ?? 1,
44188
+ column: col,
44189
+ severity: "warning",
44190
+ code: "FL-LABEL-BACKTICK",
44191
+ message: "Backticks (`\u2026`) inside node labels are not supported by Mermaid.",
44192
+ hint: 'Remove the backticks or use quotes instead, e.g., "GITHUB_ACTIONS" and "--cli".',
44193
+ length: 1
44194
+ });
44195
+ return true;
44196
+ }
44197
+ return false;
44198
+ };
44199
+ const texts = ch.Text || [];
44200
+ for (const tk of texts) {
44201
+ if (inspectTok(tk))
44202
+ return;
44203
+ }
44204
+ const qs = ch.QuotedString || [];
44205
+ for (const tk of qs) {
44206
+ if (inspectTok(tk))
44207
+ return;
44208
+ }
44209
+ }
44210
+ }
44211
+ };
44212
+ NodeIdCollector = class extends BaseVisitor {
44213
+ constructor() {
44214
+ super();
44215
+ this.ids = /* @__PURE__ */ new Set();
44216
+ this.edgeIds = /* @__PURE__ */ new Set();
44217
+ this.validateVisitor();
44218
+ }
44219
+ node(ctx) {
44220
+ const idTok = ctx.nodeId && ctx.nodeId[0];
44221
+ const idNumTok = ctx.nodeIdNum && ctx.nodeIdNum[0];
44222
+ if (idTok)
44223
+ this.ids.add(String(idTok.image));
44224
+ else if (idNumTok)
44225
+ this.ids.add(String(idNumTok.image));
44226
+ }
44227
+ link(ctx) {
44228
+ const t3 = ctx.edgeId?.[0];
44229
+ if (t3)
44230
+ this.edgeIds.add(String(t3.image));
44231
+ }
44232
+ nodeOrParallelGroup(ctx) {
44233
+ if (ctx.node)
44234
+ ctx.node.forEach((n3) => this.visit(n3));
44235
+ }
44236
+ nodeStatement(ctx) {
44237
+ if (ctx.nodeOrParallelGroup)
44238
+ ctx.nodeOrParallelGroup.forEach((n3) => this.visit(n3));
44239
+ if (ctx.link)
44240
+ ctx.link.forEach((ln) => this.visit(ln));
44241
+ }
44242
+ edgeAttrStatement(ctx) {
44243
+ const t3 = ctx.edgeId?.[0];
44244
+ if (t3)
44245
+ this.edgeIds.add(String(t3.image));
44246
+ }
44247
+ statement(ctx) {
44248
+ for (const k3 of Object.keys(ctx)) {
44249
+ const arr = ctx[k3];
44250
+ if (Array.isArray(arr))
44251
+ arr.forEach((n3) => {
44252
+ if (n3 && typeof n3.name === "string")
44253
+ this.visit(n3);
44254
+ });
44255
+ }
44256
+ }
44257
+ diagram(ctx) {
44258
+ if (ctx.statement)
44259
+ ctx.statement.forEach((s3) => this.visit(s3));
44260
+ }
43749
44261
  };
43750
44262
  }
43751
44263
  });
@@ -43783,11 +44295,29 @@ function detectDoubleInDouble(tokens, opts) {
43783
44295
  byLine.get(ln).push(tk);
43784
44296
  }
43785
44297
  const ends = new Set(opts.scopeEndTokenNames || []);
44298
+ const starts = new Set(opts.scopeStartTokenNames || []);
43786
44299
  for (const [ln, arr] of byLine) {
43787
44300
  for (let i3 = 0; i3 < arr.length; i3++) {
43788
44301
  const t3 = arr[i3];
43789
44302
  if (t3.tokenType?.name !== "QuotedString")
43790
44303
  continue;
44304
+ if (starts.size > 0) {
44305
+ let startIdx = -1;
44306
+ for (let k3 = i3 - 1; k3 >= 0; k3--) {
44307
+ const s3 = arr[k3];
44308
+ if (starts.has(s3.tokenType?.name || "")) {
44309
+ startIdx = k3;
44310
+ break;
44311
+ }
44312
+ }
44313
+ if (startIdx === -1)
44314
+ continue;
44315
+ const sTok = arr[startIdx];
44316
+ const prevTok = arr[startIdx - 1];
44317
+ if (sTok.tokenType?.name === "DiamondOpen" && prevTok?.tokenType?.name === "AtSign") {
44318
+ continue;
44319
+ }
44320
+ }
43791
44321
  for (let j3 = i3 + 1; j3 < arr.length; j3++) {
43792
44322
  const u3 = arr[j3];
43793
44323
  if (ends.size > 0 && ends.has(u3.tokenType?.name || ""))
@@ -43955,8 +44485,9 @@ function mapFlowchartParserError(err, text) {
43955
44485
  length: len
43956
44486
  };
43957
44487
  }
43958
- if (isInRule(err, "nodeStatement") && err.name === "NoViableAltException") {
43959
- if ((err.message || "").includes("[Newline") && (err.message || "").includes("[EOF")) {
44488
+ if (err.name === "NoViableAltException" || err.name === "MismatchedTokenException") {
44489
+ const msg = err.message || "";
44490
+ if (tokType === "Identifier" && msg.includes("Newline") && msg.includes("EOF")) {
43960
44491
  return {
43961
44492
  line,
43962
44493
  column,
@@ -44564,11 +45095,11 @@ function mapStateParserError(err, text) {
44564
45095
  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 };
44565
45096
  }
44566
45097
  if (isInRule(err, "stateBlock") && err.name === "MismatchedTokenException" && expecting(err, "RCurly")) {
44567
- if (/---/.test(ltxt)) {
44568
- 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 };
44569
- }
44570
45098
  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 };
44571
45099
  }
45100
+ if ((err.name === "NoViableAltException" || err.name === "MismatchedTokenException") && tokType === "Dashes" && !isInRule(err, "innerStatement")) {
45101
+ 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 };
45102
+ }
44572
45103
  const dblEsc = (ltxt.match(/\\\"/g) || []).length;
44573
45104
  const dq = (ltxt.match(/\"/g) || []).length - dblEsc;
44574
45105
  if (dq >= 3) {
@@ -44674,9 +45205,60 @@ function validateFlowchart(text, options = {}) {
44674
45205
  "StadiumClose",
44675
45206
  "CylinderClose",
44676
45207
  "HexagonClose"
45208
+ ],
45209
+ scopeStartTokenNames: [
45210
+ "SquareOpen",
45211
+ "RoundOpen",
45212
+ "DiamondOpen",
45213
+ "DoubleSquareOpen",
45214
+ "DoubleRoundOpen",
45215
+ "StadiumOpen",
45216
+ "CylinderOpen",
45217
+ "HexagonOpen"
44677
45218
  ]
44678
45219
  }).filter((e3) => !seenDoubleLines.has(e3.line) && !escapedLinesAll.has(e3.line));
44679
45220
  const errs = escWarn.concat(dbl);
45221
+ const generic = (prevErrors || []).filter((e3) => e3.severity === "error" && !("code" in e3) && typeof e3.message === "string");
45222
+ for (const ge of generic) {
45223
+ const msg = String(ge.message || "");
45224
+ if (msg.includes("Newline") && msg.includes("EOF")) {
45225
+ errs.push({
45226
+ line: ge.line ?? 1,
45227
+ column: ge.column ?? 1,
45228
+ severity: "error",
45229
+ code: "FL-LINK-MISSING",
45230
+ message: "Two nodes on one line must be connected with an arrow.",
45231
+ hint: "Insert --> between nodes, e.g., A --> B."
45232
+ });
45233
+ }
45234
+ }
45235
+ {
45236
+ const lines = text2.split(/\r?\n/);
45237
+ const nodeRef = String.raw`[A-Za-z0-9_]+(?:\[[^\]]*\]|\([^\)]*\)|\{[^}]*\}|\[\[[^\]]*\]\]|\(\([^\)]*\)\))?`;
45238
+ const re = new RegExp(String.raw`^\s*(${nodeRef})\s+(${nodeRef})\s*;?\s*$`);
45239
+ const skipStart = /^(?:\s*)(style|classDef|class|click|linkStyle|subgraph|end|graph|flowchart|direction)\b/;
45240
+ for (let i3 = 0; i3 < lines.length; i3++) {
45241
+ const raw = lines[i3] || "";
45242
+ const ln = i3 + 1;
45243
+ if (!raw.trim())
45244
+ continue;
45245
+ if (skipStart.test(raw))
45246
+ continue;
45247
+ const m3 = re.exec(raw);
45248
+ if (m3) {
45249
+ const idxSecond = raw.indexOf(m3[2]);
45250
+ const col = idxSecond >= 0 ? idxSecond + 1 : 1;
45251
+ errs.push({
45252
+ line: ln,
45253
+ column: col,
45254
+ severity: "error",
45255
+ code: "FL-LINK-MISSING",
45256
+ message: "Two nodes on one line must be connected with an arrow.",
45257
+ hint: "Insert --> between nodes, e.g., A --> B."
45258
+ });
45259
+ }
45260
+ }
45261
+ }
44680
45262
  const dblEsc = (text2.match(/\\\"/g) || []).length;
44681
45263
  const dq = (text2.match(/\"/g) || []).length - dblEsc;
44682
45264
  const sq = (text2.match(/'/g) || []).length;
@@ -44882,7 +45464,7 @@ var init_validate2 = __esm({
44882
45464
  function tokenize3(text) {
44883
45465
  return SequenceLexer.tokenize(text);
44884
45466
  }
44885
- 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;
45467
+ 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;
44886
45468
  var init_lexer4 = __esm({
44887
45469
  "node_modules/@probelabs/maid/out/diagrams/sequence/lexer.js"() {
44888
45470
  init_api5();
@@ -44899,6 +45481,9 @@ var init_lexer4 = __esm({
44899
45481
  RightKeyword = createToken({ name: "RightKeyword", pattern: /right/i, longer_alt: Identifier2 });
44900
45482
  OverKeyword = createToken({ name: "OverKeyword", pattern: /over/i, longer_alt: Identifier2 });
44901
45483
  OfKeyword = createToken({ name: "OfKeyword", pattern: /of/i, longer_alt: Identifier2 });
45484
+ TitleKeyword2 = createToken({ name: "TitleKeyword", pattern: /title/i, longer_alt: Identifier2 });
45485
+ AccTitleKeyword = createToken({ name: "AccTitleKeyword", pattern: /acc_title|accTitle/i, longer_alt: Identifier2 });
45486
+ AccDescrKeyword = createToken({ name: "AccDescrKeyword", pattern: /acc_descr|accDescr/i, longer_alt: Identifier2 });
44902
45487
  ActivateKeyword = createToken({ name: "ActivateKeyword", pattern: /activate/i, longer_alt: Identifier2 });
44903
45488
  DeactivateKeyword = createToken({ name: "DeactivateKeyword", pattern: /deactivate/i, longer_alt: Identifier2 });
44904
45489
  CreateKeyword = createToken({ name: "CreateKeyword", pattern: /create/i, longer_alt: Identifier2 });
@@ -44916,6 +45501,8 @@ var init_lexer4 = __esm({
44916
45501
  EndKeyword2 = createToken({ name: "EndKeyword", pattern: /end/i, longer_alt: Identifier2 });
44917
45502
  LinksKeyword = createToken({ name: "LinksKeyword", pattern: /links/i, longer_alt: Identifier2 });
44918
45503
  LinkKeyword = createToken({ name: "LinkKeyword", pattern: /link/i, longer_alt: Identifier2 });
45504
+ PropertiesKeyword = createToken({ name: "PropertiesKeyword", pattern: /properties/i, longer_alt: Identifier2 });
45505
+ DetailsKeyword = createToken({ name: "DetailsKeyword", pattern: /details/i, longer_alt: Identifier2 });
44919
45506
  BreakKeyword = createToken({ name: "BreakKeyword", pattern: /break/i, longer_alt: Identifier2 });
44920
45507
  BidirAsyncDotted = createToken({ name: "BidirAsyncDotted", pattern: /<<-->>/ });
44921
45508
  BidirAsync = createToken({ name: "BidirAsync", pattern: /<<->>/ });
@@ -44948,6 +45535,9 @@ var init_lexer4 = __esm({
44948
45535
  Newline3,
44949
45536
  // Header/Keywords
44950
45537
  SequenceKeyword,
45538
+ TitleKeyword2,
45539
+ AccTitleKeyword,
45540
+ AccDescrKeyword,
44951
45541
  ParticipantKeyword,
44952
45542
  ActorKeyword,
44953
45543
  AsKeyword,
@@ -44976,6 +45566,8 @@ var init_lexer4 = __esm({
44976
45566
  EndKeyword2,
44977
45567
  LinksKeyword,
44978
45568
  LinkKeyword,
45569
+ PropertiesKeyword,
45570
+ DetailsKeyword,
44979
45571
  // Arrows
44980
45572
  BidirAsyncDotted,
44981
45573
  BidirAsync,
@@ -45027,6 +45619,7 @@ var init_parser4 = __esm({
45027
45619
  });
45028
45620
  this.line = this.RULE("line", () => {
45029
45621
  this.OR([
45622
+ { ALT: () => this.SUBRULE(this.metaStmt) },
45030
45623
  { ALT: () => this.SUBRULE(this.participantDecl) },
45031
45624
  { ALT: () => this.SUBRULE(this.autonumberStmt) },
45032
45625
  { ALT: () => this.SUBRULE(this.noteStmt) },
@@ -45035,6 +45628,8 @@ var init_parser4 = __esm({
45035
45628
  { ALT: () => this.SUBRULE(this.createStmt) },
45036
45629
  { ALT: () => this.SUBRULE(this.destroyStmt) },
45037
45630
  { ALT: () => this.SUBRULE(this.linkStmt) },
45631
+ { ALT: () => this.SUBRULE(this.propertiesStmt) },
45632
+ { ALT: () => this.SUBRULE(this.detailsStmt) },
45038
45633
  { ALT: () => this.SUBRULE(this.altBlock) },
45039
45634
  { ALT: () => this.SUBRULE(this.optBlock) },
45040
45635
  { ALT: () => this.SUBRULE(this.loopBlock) },
@@ -45047,6 +45642,18 @@ var init_parser4 = __esm({
45047
45642
  { ALT: () => this.SUBRULE(this.blankLine) }
45048
45643
  ]);
45049
45644
  });
45645
+ this.metaStmt = this.RULE("metaStmt", () => {
45646
+ this.OR([
45647
+ { ALT: () => this.CONSUME(TitleKeyword2) },
45648
+ { ALT: () => this.CONSUME(AccTitleKeyword) },
45649
+ { ALT: () => this.CONSUME(AccDescrKeyword) }
45650
+ ]);
45651
+ this.OPTION(() => this.SUBRULE(this.lineRemainder));
45652
+ this.OR2([
45653
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45654
+ { ALT: () => this.CONSUME(EOF) }
45655
+ ]);
45656
+ });
45050
45657
  this.blankLine = this.RULE("blankLine", () => {
45051
45658
  this.AT_LEAST_ONE(() => this.CONSUME(Newline3));
45052
45659
  });
@@ -45175,6 +45782,24 @@ var init_parser4 = __esm({
45175
45782
  { ALT: () => this.CONSUME(EOF) }
45176
45783
  ]);
45177
45784
  });
45785
+ this.propertiesStmt = this.RULE("propertiesStmt", () => {
45786
+ this.CONSUME(PropertiesKeyword);
45787
+ this.OPTION(() => this.CONSUME(Colon3));
45788
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45789
+ this.OR2([
45790
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45791
+ { ALT: () => this.CONSUME(EOF) }
45792
+ ]);
45793
+ });
45794
+ this.detailsStmt = this.RULE("detailsStmt", () => {
45795
+ this.CONSUME(DetailsKeyword);
45796
+ this.OPTION(() => this.CONSUME(Colon3));
45797
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45798
+ this.OR2([
45799
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45800
+ { ALT: () => this.CONSUME(EOF) }
45801
+ ]);
45802
+ });
45178
45803
  this.messageStmt = this.RULE("messageStmt", () => {
45179
45804
  this.SUBRULE(this.actorRef);
45180
45805
  this.SUBRULE(this.arrow);
@@ -45245,7 +45870,7 @@ var init_parser4 = __esm({
45245
45870
  });
45246
45871
  this.parBlock = this.RULE("parBlock", () => {
45247
45872
  this.CONSUME(ParKeyword);
45248
- this.OPTION(() => this.SUBRULE(this.lineRemainder));
45873
+ this.OPTION(() => this.SUBRULE(this.parHeader));
45249
45874
  this.AT_LEAST_ONE(() => this.CONSUME(Newline3));
45250
45875
  this.MANY(() => this.SUBRULE(this.line));
45251
45876
  this.MANY2(() => {
@@ -45260,6 +45885,23 @@ var init_parser4 = __esm({
45260
45885
  { ALT: () => this.CONSUME3(EOF) }
45261
45886
  ]);
45262
45887
  });
45888
+ this.parHeader = this.RULE("parHeader", () => {
45889
+ this.OR([
45890
+ {
45891
+ GATE: () => this.LA(1).tokenType === OverKeyword,
45892
+ ALT: () => {
45893
+ this.CONSUME(OverKeyword);
45894
+ this.SUBRULE(this.actorRef);
45895
+ this.OPTION(() => {
45896
+ this.CONSUME(Comma2);
45897
+ this.SUBRULE2(this.actorRef);
45898
+ });
45899
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45900
+ }
45901
+ },
45902
+ { ALT: () => this.SUBRULE2(this.lineRemainder) }
45903
+ ]);
45904
+ });
45263
45905
  this.criticalBlock = this.RULE("criticalBlock", () => {
45264
45906
  this.CONSUME(CriticalKeyword);
45265
45907
  this.OPTION(() => this.SUBRULE(this.lineRemainder));
@@ -45334,6 +45976,9 @@ var init_parser4 = __esm({
45334
45976
  { ALT: () => this.CONSUME(BreakKeyword) },
45335
45977
  { ALT: () => this.CONSUME(BoxKeyword) },
45336
45978
  { ALT: () => this.CONSUME(EndKeyword2) },
45979
+ { ALT: () => this.CONSUME(TitleKeyword2) },
45980
+ { ALT: () => this.CONSUME(AccTitleKeyword) },
45981
+ { ALT: () => this.CONSUME(AccDescrKeyword) },
45337
45982
  { ALT: () => this.CONSUME(NoteKeyword) },
45338
45983
  { ALT: () => this.CONSUME(LeftKeyword) },
45339
45984
  { ALT: () => this.CONSUME(RightKeyword) },
@@ -45362,12 +46007,186 @@ var init_parser4 = __esm({
45362
46007
  function analyzeSequence(_cst, _tokens) {
45363
46008
  const ctx = { tokens: _tokens };
45364
46009
  const v3 = new SequenceSemanticsVisitor(ctx);
45365
- return [];
46010
+ const errs = [];
46011
+ const firstByLine = /* @__PURE__ */ new Map();
46012
+ for (const tk of _tokens) {
46013
+ const ln = tk.startLine ?? 1;
46014
+ const col = tk.startColumn ?? 1;
46015
+ const prev = firstByLine.get(ln);
46016
+ if (!prev || (prev.startColumn ?? Infinity) > col)
46017
+ firstByLine.set(ln, tk);
46018
+ }
46019
+ for (const tok of _tokens) {
46020
+ if (tok.tokenType === TitleKeyword2 || tok.tokenType === AccTitleKeyword || tok.tokenType === AccDescrKeyword) {
46021
+ const isLineStart = firstByLine.get(tok.startLine ?? 1) === tok;
46022
+ if (isLineStart)
46023
+ errs.push({
46024
+ line: tok.startLine ?? 1,
46025
+ column: tok.startColumn ?? 1,
46026
+ severity: "error",
46027
+ code: "SE-META-UNSUPPORTED",
46028
+ message: "Title/accTitle/accDescr are not accepted by current Mermaid CLI for sequence diagrams.",
46029
+ hint: "Remove this line (e.g., 'title \u2026') to match mermaid-cli.",
46030
+ length: tok.image?.length ?? 5
46031
+ });
46032
+ }
46033
+ if (tok.tokenType === PropertiesKeyword && firstByLine.get(tok.startLine ?? 1) === tok) {
46034
+ errs.push({
46035
+ line: tok.startLine ?? 1,
46036
+ column: tok.startColumn ?? 1,
46037
+ severity: "error",
46038
+ code: "SE-PROPERTIES-UNSUPPORTED",
46039
+ message: "'properties' is not accepted by current Mermaid CLI for sequence diagrams.",
46040
+ hint: "Remove the 'properties:' line to match mermaid-cli.",
46041
+ length: tok.image?.length ?? 10
46042
+ });
46043
+ }
46044
+ if (tok.tokenType === DetailsKeyword && firstByLine.get(tok.startLine ?? 1) === tok) {
46045
+ errs.push({
46046
+ line: tok.startLine ?? 1,
46047
+ column: tok.startColumn ?? 1,
46048
+ severity: "error",
46049
+ code: "SE-DETAILS-UNSUPPORTED",
46050
+ message: "'details' is not accepted by current Mermaid CLI for sequence diagrams.",
46051
+ hint: "Remove the 'details:' line to match mermaid-cli.",
46052
+ length: tok.image?.length ?? 7
46053
+ });
46054
+ }
46055
+ }
46056
+ const lines = /* @__PURE__ */ new Map();
46057
+ for (const tk of _tokens) {
46058
+ if (tk.tokenType === Newline3)
46059
+ continue;
46060
+ const ln = tk.startLine ?? 1;
46061
+ (lines.get(ln) || lines.set(ln, []).get(ln)).push(tk);
46062
+ }
46063
+ const events = [];
46064
+ const tokensByLine = Array.from(lines.entries()).sort((a3, b3) => a3[0] - b3[0]);
46065
+ const grabActorRef = (arr, startIdx) => {
46066
+ const parts = [];
46067
+ for (let i3 = startIdx; i3 < arr.length; i3++) {
46068
+ const tk = arr[i3];
46069
+ if (tk.tokenType === Colon3 || tk.tokenType === Newline3)
46070
+ break;
46071
+ if (tk.tokenType === Identifier2 || tk.tokenType === QuotedString3 || tk.tokenType === NumberLiteral3 || tk.tokenType === Text3)
46072
+ parts.push(tk.image);
46073
+ if (tk.tokenType === Async || tk.tokenType === Solid || tk.tokenType === Dotted || tk.tokenType === DottedAsync || tk.tokenType === BidirAsync || tk.tokenType === BidirAsyncDotted)
46074
+ break;
46075
+ }
46076
+ const raw = parts.join(" ").trim();
46077
+ return raw.replace(/^"|"$/g, "");
46078
+ };
46079
+ for (const [ln, arr] of tokensByLine) {
46080
+ if (arr.some((tk) => tk.tokenType === ActivateKeyword)) {
46081
+ const idx = arr.findIndex((tk) => tk.tokenType === ActivateKeyword);
46082
+ const actor = grabActorRef(arr, idx + 1);
46083
+ if (actor)
46084
+ events.push({ kind: "activate", line: ln, actor });
46085
+ continue;
46086
+ }
46087
+ if (arr.some((tk) => tk.tokenType === DeactivateKeyword)) {
46088
+ const idx = arr.findIndex((tk) => tk.tokenType === DeactivateKeyword);
46089
+ const actor = grabActorRef(arr, idx + 1);
46090
+ if (actor)
46091
+ events.push({ kind: "deactivate", line: ln, actor });
46092
+ continue;
46093
+ }
46094
+ if (arr.some((tk) => tk.tokenType === CreateKeyword)) {
46095
+ const idx = arr.findIndex((tk) => tk.tokenType === CreateKeyword);
46096
+ const after = arr.slice(idx + 1);
46097
+ const aidx = after.findIndex((tk) => tk.tokenType === ParticipantKeyword || tk.tokenType === ActorKeyword);
46098
+ const actor = aidx >= 0 ? grabActorRef(after, aidx + 1) : grabActorRef(arr, idx + 1);
46099
+ if (actor)
46100
+ events.push({ kind: "create", line: ln, actor });
46101
+ continue;
46102
+ }
46103
+ const arrowIdx = arr.findIndex((tk) => [Async, DottedAsync, Solid, Dotted, Cross, DottedCross, DottedOpen, Open, BidirAsync, BidirAsyncDotted].includes(tk.tokenType));
46104
+ if (arrowIdx > 0) {
46105
+ const from = grabActorRef(arr, 0);
46106
+ const to = grabActorRef(arr, arrowIdx + 1);
46107
+ if (from || to) {
46108
+ const plusTok = arr.find((tk) => tk.tokenType === Plus);
46109
+ const minusTok = arr.find((tk) => tk.tokenType === Minus);
46110
+ events.push({ kind: "message", line: ln, from, to, plus: Boolean(plusTok), minus: Boolean(minusTok), plusTok, minusTok });
46111
+ }
46112
+ }
46113
+ }
46114
+ const actStack = /* @__PURE__ */ new Map();
46115
+ for (const ev of events) {
46116
+ if (ev.kind === "activate" && ev.actor) {
46117
+ const a3 = actStack.get(ev.actor) || [];
46118
+ a3.push({ line: ev.line });
46119
+ actStack.set(ev.actor, a3);
46120
+ } else if (ev.kind === "deactivate" && ev.actor) {
46121
+ const a3 = actStack.get(ev.actor) || [];
46122
+ a3.pop();
46123
+ actStack.set(ev.actor, a3);
46124
+ } else if (ev.kind === "message" && ev.to) {
46125
+ const target = ev.to;
46126
+ const plus = Boolean(ev.plus);
46127
+ const minus = Boolean(ev.minus);
46128
+ const plusTok = ev.plusTok;
46129
+ const minusTok = ev.minusTok;
46130
+ if (plus) {
46131
+ const a3 = actStack.get(target) || [];
46132
+ if (a3.length > 0) {
46133
+ const col = plusTok?.startColumn ?? 1;
46134
+ 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 });
46135
+ } else {
46136
+ a3.push({ line: ev.line });
46137
+ actStack.set(target, a3);
46138
+ }
46139
+ }
46140
+ if (minus) {
46141
+ const a3 = actStack.get(target) || [];
46142
+ if (a3.length === 0) {
46143
+ const col = minusTok?.startColumn ?? 1;
46144
+ 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 });
46145
+ } else {
46146
+ a3.pop();
46147
+ actStack.set(target, a3);
46148
+ }
46149
+ }
46150
+ }
46151
+ }
46152
+ for (const [actor, arr] of actStack.entries()) {
46153
+ if (arr.length) {
46154
+ const top = arr[arr.length - 1];
46155
+ errs.push({
46156
+ line: top.line,
46157
+ column: 1,
46158
+ severity: "warning",
46159
+ code: "SE-ACTIVATION-UNBALANCED",
46160
+ message: `Unbalanced activation: '${actor}' was activated but not deactivated.`,
46161
+ hint: `Add 'deactivate ${actor}' after the active section.`,
46162
+ length: actor.length
46163
+ });
46164
+ }
46165
+ }
46166
+ for (let i3 = 0; i3 < events.length; i3++) {
46167
+ const ev = events[i3];
46168
+ if (ev.kind === "create" && ev.actor) {
46169
+ const next = events[i3 + 1];
46170
+ if (!(next && next.kind === "message" && (next.from === ev.actor || next.to === ev.actor))) {
46171
+ errs.push({
46172
+ line: ev.line,
46173
+ column: 1,
46174
+ severity: "warning",
46175
+ code: "SE-CREATE-NO-CREATING-MESSAGE",
46176
+ message: `Actor '${ev.actor}' is created but the next line is not a message involving it.`,
46177
+ hint: `Add a creating message to or from '${ev.actor}' immediately after the create line.`,
46178
+ length: ev.actor.length
46179
+ });
46180
+ }
46181
+ }
46182
+ }
46183
+ return errs;
45366
46184
  }
45367
46185
  var BaseVisitor3, SequenceSemanticsVisitor;
45368
46186
  var init_semantics3 = __esm({
45369
46187
  "node_modules/@probelabs/maid/out/diagrams/sequence/semantics.js"() {
45370
46188
  init_parser4();
46189
+ init_lexer4();
45371
46190
  BaseVisitor3 = parserInstance3.getBaseCstVisitorConstructorWithDefaults();
45372
46191
  SequenceSemanticsVisitor = class extends BaseVisitor3 {
45373
46192
  constructor(ctx) {
@@ -45477,7 +46296,7 @@ var init_validate3 = __esm({
45477
46296
  function tokenize4(text) {
45478
46297
  return ClassLexer.tokenize(text);
45479
46298
  }
45480
- 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;
46299
+ 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;
45481
46300
  var init_lexer5 = __esm({
45482
46301
  "node_modules/@probelabs/maid/out/diagrams/class/lexer.js"() {
45483
46302
  init_api5();
@@ -45489,6 +46308,7 @@ var init_lexer5 = __esm({
45489
46308
  ClassKw = createToken({ name: "ClassKw", pattern: /class/, longer_alt: Identifier3 });
45490
46309
  AsKw = createToken({ name: "AsKw", pattern: /as/, longer_alt: Identifier3 });
45491
46310
  NoteKw = createToken({ name: "NoteKw", pattern: /note/, longer_alt: Identifier3 });
46311
+ ForKw = createToken({ name: "ForKw", pattern: /for/, longer_alt: Identifier3 });
45492
46312
  RelCompToAgg = createToken({ name: "RelCompToAgg", pattern: /\*--o/ });
45493
46313
  RelAggToComp = createToken({ name: "RelAggToComp", pattern: /o--\*/ });
45494
46314
  RelCompBoth = createToken({ name: "RelCompBoth", pattern: /\*--\*/ });
@@ -45501,6 +46321,9 @@ var init_lexer5 = __esm({
45501
46321
  RelDependency = createToken({ name: "RelDependency", pattern: /\.\.>/ });
45502
46322
  RelRealization = createToken({ name: "RelRealization", pattern: /\.\.\|>/ });
45503
46323
  RelAssociation = createToken({ name: "RelAssociation", pattern: /--/ });
46324
+ RelDependencyLeft = createToken({ name: "RelDependencyLeft", pattern: /<\.\./ });
46325
+ RelRealizationLeft = createToken({ name: "RelRealizationLeft", pattern: /<\|\.\./ });
46326
+ RelExtendsRight = createToken({ name: "RelExtendsRight", pattern: /--\|>/ });
45504
46327
  InvalidRelArrow = createToken({ name: "InvalidRelArrow", pattern: /->(?!>)/ });
45505
46328
  LCurly = createToken({ name: "LCurly", pattern: /\{/ });
45506
46329
  RCurly = createToken({ name: "RCurly", pattern: /\}/ });
@@ -45511,6 +46334,7 @@ var init_lexer5 = __esm({
45511
46334
  Visibility = createToken({ name: "Visibility", pattern: /[+\-#~]/ });
45512
46335
  LTlt = createToken({ name: "LTlt", pattern: /<</ });
45513
46336
  GTgt = createToken({ name: "GTgt", pattern: />>/ });
46337
+ GenericAngle = createToken({ name: "GenericAngle", pattern: /<[^\n\r>]+>/ });
45514
46338
  QuotedString4 = createToken({ name: "QuotedString", pattern: /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/ });
45515
46339
  BacktickName = createToken({ name: "BacktickName", pattern: /`(?:\\.|[^`\\])*`/ });
45516
46340
  SquareOpen2 = createToken({ name: "SquareOpen", pattern: /\[/ });
@@ -45527,6 +46351,7 @@ var init_lexer5 = __esm({
45527
46351
  ClassKw,
45528
46352
  AsKw,
45529
46353
  NoteKw,
46354
+ ForKw,
45530
46355
  Direction2,
45531
46356
  // Relationship ops
45532
46357
  RelCompToAgg,
@@ -45538,6 +46363,9 @@ var init_lexer5 = __esm({
45538
46363
  RelRealization,
45539
46364
  RelDependency,
45540
46365
  RelExtends,
46366
+ RelDependencyLeft,
46367
+ RelRealizationLeft,
46368
+ RelExtendsRight,
45541
46369
  RelComposition,
45542
46370
  RelAggregation,
45543
46371
  RelAssociation,
@@ -45545,6 +46373,7 @@ var init_lexer5 = __esm({
45545
46373
  // Punct
45546
46374
  LTlt,
45547
46375
  GTgt,
46376
+ GenericAngle,
45548
46377
  LCurly,
45549
46378
  RCurly,
45550
46379
  LParen2,
@@ -45590,6 +46419,7 @@ var init_parser5 = __esm({
45590
46419
  { ALT: () => this.SUBRULE(this.directionStmt) },
45591
46420
  { ALT: () => this.SUBRULE(this.classLine) },
45592
46421
  { ALT: () => this.SUBRULE(this.relationStmt) },
46422
+ { ALT: () => this.SUBRULE(this.noteStmt) },
45593
46423
  { ALT: () => this.SUBRULE(this.memberAssignStmt) },
45594
46424
  { ALT: () => this.CONSUME(Newline4) }
45595
46425
  ]);
@@ -45703,6 +46533,18 @@ var init_parser5 = __esm({
45703
46533
  { ALT: () => this.CONSUME(QuotedString4) }
45704
46534
  ]);
45705
46535
  });
46536
+ this.noteStmt = this.RULE("noteStmt", () => {
46537
+ this.CONSUME(NoteKw);
46538
+ this.OPTION(() => this.CONSUME(ForKw));
46539
+ this.SUBRULE(this.classRef);
46540
+ this.OPTION1(() => this.CONSUME(Colon4));
46541
+ this.OR([
46542
+ { ALT: () => this.CONSUME(QuotedString4) },
46543
+ { ALT: () => this.CONSUME(Identifier3) },
46544
+ { ALT: () => this.CONSUME(NumberLiteral4) }
46545
+ ]);
46546
+ this.OPTION2(() => this.CONSUME(Newline4));
46547
+ });
45706
46548
  this.relationOp = this.RULE("relationOp", () => {
45707
46549
  this.OR([
45708
46550
  { ALT: () => this.CONSUME(RelCompToAgg) },
@@ -45712,16 +46554,22 @@ var init_parser5 = __esm({
45712
46554
  { ALT: () => this.CONSUME(LollipopLeft) },
45713
46555
  { ALT: () => this.CONSUME(LollipopRight) },
45714
46556
  { ALT: () => this.CONSUME(RelExtends) },
46557
+ { ALT: () => this.CONSUME(RelExtendsRight) },
45715
46558
  { ALT: () => this.CONSUME(RelComposition) },
45716
46559
  { ALT: () => this.CONSUME(RelAggregation) },
45717
46560
  { ALT: () => this.CONSUME(RelRealization) },
45718
46561
  { ALT: () => this.CONSUME(RelDependency) },
46562
+ { ALT: () => this.CONSUME(RelRealizationLeft) },
46563
+ { ALT: () => this.CONSUME(RelDependencyLeft) },
45719
46564
  { ALT: () => this.CONSUME(RelAssociation) }
45720
46565
  ]);
45721
46566
  });
45722
46567
  this.classRef = this.RULE("classRef", () => {
45723
46568
  this.OR([
45724
- { ALT: () => this.CONSUME(Identifier3) },
46569
+ { ALT: () => {
46570
+ this.CONSUME(Identifier3);
46571
+ this.OPTION(() => this.CONSUME(GenericAngle));
46572
+ } },
45725
46573
  { ALT: () => this.CONSUME(QuotedString4) },
45726
46574
  { ALT: () => this.CONSUME(BacktickName) }
45727
46575
  ]);
@@ -45730,14 +46578,15 @@ var init_parser5 = __esm({
45730
46578
  this.OR([
45731
46579
  { ALT: () => this.CONSUME(QuotedString4) },
45732
46580
  { ALT: () => this.CONSUME(Identifier3) },
45733
- { ALT: () => this.CONSUME(NumberLiteral4) }
46581
+ { ALT: () => this.CONSUME(NumberLiteral4) },
46582
+ { ALT: () => this.CONSUME(GenericAngle) }
45734
46583
  ]);
45735
46584
  });
45736
46585
  this.relationStmt = this.RULE("relationStmt", () => {
45737
46586
  this.SUBRULE(this.classRef);
45738
- this.OPTION1(() => this.CONSUME(QuotedString4));
46587
+ this.OPTION1(() => this.CONSUME(QuotedString4, { LABEL: "leftCard" }));
45739
46588
  this.SUBRULE(this.relationOp);
45740
- this.OPTION2(() => this.CONSUME2(QuotedString4));
46589
+ this.OPTION2(() => this.CONSUME2(QuotedString4, { LABEL: "rightCard" }));
45741
46590
  this.SUBRULE2(this.classRef);
45742
46591
  this.OPTION3(() => {
45743
46592
  this.CONSUME(Colon4);
@@ -45874,7 +46723,7 @@ var init_validate4 = __esm({
45874
46723
  function tokenize5(text) {
45875
46724
  return StateLexer.tokenize(text);
45876
46725
  }
45877
- 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;
46726
+ 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;
45878
46727
  var init_lexer6 = __esm({
45879
46728
  "node_modules/@probelabs/maid/out/diagrams/state/lexer.js"() {
45880
46729
  init_api5();
@@ -45897,6 +46746,8 @@ var init_lexer6 = __esm({
45897
46746
  StyleClassDefKw = createToken({ name: "StyleClassDefKw", pattern: /classDef/, longer_alt: Identifier4 });
45898
46747
  StyleClassKw = createToken({ name: "StyleClassKw", pattern: /class(?!Diagram)/, longer_alt: Identifier4 });
45899
46748
  Start = createToken({ name: "Start", pattern: /\[\*\]/ });
46749
+ HistoryShallow = createToken({ name: "HistoryShallow", pattern: /\[H\]/ });
46750
+ HistoryDeep = createToken({ name: "HistoryDeep", pattern: /\[H\*\]/ });
45900
46751
  Arrow = createToken({ name: "Arrow", pattern: /-->/ });
45901
46752
  InvalidArrow2 = createToken({ name: "InvalidArrow", pattern: /->(?!>)/ });
45902
46753
  Hyphen = createToken({ name: "Hyphen", pattern: /-/ });
@@ -45926,6 +46777,8 @@ var init_lexer6 = __esm({
45926
46777
  AngleAngleOpen,
45927
46778
  AngleAngleClose,
45928
46779
  Start,
46780
+ HistoryDeep,
46781
+ HistoryShallow,
45929
46782
  Arrow,
45930
46783
  InvalidArrow2,
45931
46784
  Dashes,
@@ -45974,8 +46827,7 @@ var init_parser6 = __esm({
45974
46827
  { ALT: () => this.SUBRULE(this.transitionStmt) },
45975
46828
  { ALT: () => this.SUBRULE(this.stateBlock) },
45976
46829
  { ALT: () => this.SUBRULE(this.stateDecl) },
45977
- // Concurrency separator (---) is not supported by mermaid-cli v11; treat as invalid (handled in postLex)
45978
- // { ALT: () => this.CONSUME(t.Dashes) },
46830
+ // '---' only allowed inside state blocks; not at top level
45979
46831
  { ALT: () => this.SUBRULE(this.stateDescriptionStmt) },
45980
46832
  { ALT: () => this.SUBRULE(this.noteStmt) },
45981
46833
  { ALT: () => this.SUBRULE(this.styleStmt) },
@@ -46007,6 +46859,8 @@ var init_parser6 = __esm({
46007
46859
  this.actorRef = this.RULE("actorRef", () => {
46008
46860
  this.OR([
46009
46861
  { ALT: () => this.CONSUME(Start) },
46862
+ { ALT: () => this.CONSUME(HistoryDeep) },
46863
+ { ALT: () => this.CONSUME(HistoryShallow) },
46010
46864
  {
46011
46865
  ALT: () => {
46012
46866
  this.OR2([
@@ -46079,10 +46933,23 @@ var init_parser6 = __esm({
46079
46933
  { ALT: () => this.CONSUME(QuotedString5) }
46080
46934
  ]);
46081
46935
  this.CONSUME(LCurly2);
46082
- this.MANY(() => this.SUBRULE(this.statement));
46936
+ this.MANY(() => this.SUBRULE(this.innerStatement));
46083
46937
  this.CONSUME(RCurly2);
46084
46938
  this.OPTION(() => this.CONSUME(Newline5));
46085
46939
  });
46940
+ this.innerStatement = this.RULE("innerStatement", () => {
46941
+ this.OR([
46942
+ { ALT: () => this.SUBRULE(this.directionStmt) },
46943
+ { ALT: () => this.SUBRULE(this.transitionStmt) },
46944
+ { ALT: () => this.SUBRULE(this.stateBlock) },
46945
+ { ALT: () => this.SUBRULE(this.stateDecl) },
46946
+ { ALT: () => this.CONSUME(Dashes) },
46947
+ { ALT: () => this.SUBRULE(this.stateDescriptionStmt) },
46948
+ { ALT: () => this.SUBRULE(this.noteStmt) },
46949
+ { ALT: () => this.SUBRULE(this.styleStmt) },
46950
+ { ALT: () => this.CONSUME(Newline5) }
46951
+ ]);
46952
+ });
46086
46953
  this.noteStmt = this.RULE("noteStmt", () => {
46087
46954
  this.CONSUME(NoteKw2);
46088
46955
  this.OR([
@@ -46221,6 +47088,72 @@ function validateState(text, _options = {}) {
46221
47088
  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 { ... }" });
46222
47089
  }
46223
47090
  }
47091
+ const stack = [];
47092
+ const pushBlock = (ln) => stack.push({ start: ln, content: [], seps: [] });
47093
+ const top = () => stack[stack.length - 1];
47094
+ for (let i3 = 0; i3 < lines.length; i3++) {
47095
+ const raw = lines[i3] || "";
47096
+ const ln = i3 + 1;
47097
+ if (/^\s*state\b.*\{\s*$/.test(raw)) {
47098
+ pushBlock(ln);
47099
+ continue;
47100
+ }
47101
+ if (/^\s*\}\s*$/.test(raw)) {
47102
+ const blk = stack.pop();
47103
+ if (blk) {
47104
+ 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);
47105
+ const sepIdxs = all.map((x3, i4) => ({ i: i4, x: x3 })).filter((z3) => z3.x.kind === "sep").map((z3) => z3.i);
47106
+ for (const si of sepIdxs) {
47107
+ const sepLn = all[si].ln;
47108
+ let hasBefore = false;
47109
+ for (let k3 = si - 1; k3 >= 0; k3--) {
47110
+ if (all[k3].kind === "sep")
47111
+ break;
47112
+ if (all[k3].kind === "content") {
47113
+ hasBefore = true;
47114
+ break;
47115
+ }
47116
+ }
47117
+ let hasAfter = false;
47118
+ for (let k3 = si + 1; k3 < all.length; k3++) {
47119
+ if (all[k3].kind === "sep")
47120
+ break;
47121
+ if (all[k3].kind === "content") {
47122
+ hasAfter = true;
47123
+ break;
47124
+ }
47125
+ }
47126
+ if (!hasBefore || !hasAfter) {
47127
+ errors.push({
47128
+ line: sepLn,
47129
+ column: 1,
47130
+ severity: "error",
47131
+ code: "ST-CONCURRENCY-MISPLACED",
47132
+ message: "Concurrency separator '---' must be between regions, not at the start or end of a block.",
47133
+ hint: "Place '---' between two sets of state lines inside the same block."
47134
+ });
47135
+ }
47136
+ }
47137
+ }
47138
+ continue;
47139
+ }
47140
+ if (stack.length > 0) {
47141
+ if (/^\s*---\s*$/.test(raw)) {
47142
+ top().seps.push(ln);
47143
+ if (!has2("ST-CONCURRENCY-UNSUPPORTED", ln)) {
47144
+ errors.push({
47145
+ line: ln,
47146
+ column: 1,
47147
+ severity: "error",
47148
+ code: "ST-CONCURRENCY-UNSUPPORTED",
47149
+ message: "Concurrency separator '---' is not supported by Mermaid CLI in state diagrams.",
47150
+ hint: "Remove '---' or split logic into separate composite states."
47151
+ });
47152
+ }
47153
+ } else if (raw.trim() !== "")
47154
+ top().content.push(ln);
47155
+ }
47156
+ }
46224
47157
  return errors;
46225
47158
  }
46226
47159
  });
@@ -46483,6 +47416,10 @@ function computeFixes(text, errors, level = "safe") {
46483
47416
  edits.push(replaceRange(text, at(e3), e3.length ?? 2, "&quot;"));
46484
47417
  continue;
46485
47418
  }
47419
+ if (is("FL-LABEL-BACKTICK", e3)) {
47420
+ edits.push(replaceRange(text, at(e3), e3.length ?? 1, ""));
47421
+ continue;
47422
+ }
46486
47423
  if (is("FL-LABEL-DOUBLE-IN-DOUBLE", e3)) {
46487
47424
  const lineText = lineTextAt(text, e3.line);
46488
47425
  const caret0 = Math.max(0, e3.column - 1);
@@ -46593,8 +47530,24 @@ function computeFixes(text, errors, level = "safe") {
46593
47530
  continue;
46594
47531
  }
46595
47532
  if (is("FL-LINK-MISSING", e3)) {
46596
- if (level === "all")
46597
- edits.push(insertAt(text, at(e3), " --> "));
47533
+ if (level === "all") {
47534
+ const line = e3.line;
47535
+ const lineText = lineTextAt(text, line);
47536
+ if (!/-->/.test(lineText)) {
47537
+ const shapePart = "(?:\\[[^\\]]*\\]|\\([^\\)]*\\)|\\{[^}]*\\}|\\[\\[[^\\]]*\\]\\]|\\(\\([^\\)]*\\)\\))?";
47538
+ const id = "[A-Za-z0-9_]+";
47539
+ const re = new RegExp(`^\\s*(${id}${shapePart})\\s+(${id})`);
47540
+ const m3 = re.exec(lineText);
47541
+ if (m3) {
47542
+ const before = m3[0];
47543
+ const insertIdx = before.length - m3[2].length;
47544
+ const col = insertIdx + 1;
47545
+ edits.push(insertAt(text, { line, column: col }, " --> "));
47546
+ } else {
47547
+ edits.push(insertAt(text, at(e3), " --> "));
47548
+ }
47549
+ }
47550
+ }
46598
47551
  continue;
46599
47552
  }
46600
47553
  if (is("FL-NODE-UNCLOSED-BRACKET", e3)) {
@@ -47213,9 +48166,13 @@ var init_graph_builder = __esm({
47213
48166
  this.edgeCounter = 0;
47214
48167
  this.subgraphs = [];
47215
48168
  this.currentSubgraphStack = [];
48169
+ this.pendingLinkStyles = [];
47216
48170
  this.classStyles = /* @__PURE__ */ new Map();
47217
48171
  this.nodeStyles = /* @__PURE__ */ new Map();
47218
48172
  this.nodeClasses = /* @__PURE__ */ new Map();
48173
+ this.edgeClasses = /* @__PURE__ */ new Map();
48174
+ this.edgeStyles = /* @__PURE__ */ new Map();
48175
+ this.nodeLinks = /* @__PURE__ */ new Map();
47219
48176
  }
47220
48177
  build(cst) {
47221
48178
  this.reset();
@@ -47229,6 +48186,11 @@ var init_graph_builder = __esm({
47229
48186
  }
47230
48187
  const direction = this.extractDirection(cst);
47231
48188
  this.processStatements(cst);
48189
+ for (const [id, link] of this.nodeLinks.entries()) {
48190
+ const node = this.nodes.get(id);
48191
+ if (node)
48192
+ node.link = link;
48193
+ }
47232
48194
  return {
47233
48195
  nodes: Array.from(this.nodes.values()),
47234
48196
  edges: this.edges,
@@ -47246,6 +48208,10 @@ var init_graph_builder = __esm({
47246
48208
  this.classStyles.clear();
47247
48209
  this.nodeStyles.clear();
47248
48210
  this.nodeClasses.clear();
48211
+ this.edgeClasses.clear();
48212
+ this.edgeStyles.clear();
48213
+ this.pendingLinkStyles = [];
48214
+ this.nodeLinks.clear();
47249
48215
  }
47250
48216
  extractDirection(cst) {
47251
48217
  const dirToken = cst.children?.Direction?.[0];
@@ -47279,14 +48245,100 @@ var init_graph_builder = __esm({
47279
48245
  this.processClassAssign(stmt.children.classStatement[0]);
47280
48246
  } else if (stmt.children?.styleStatement) {
47281
48247
  this.processStyle(stmt.children.styleStatement[0]);
48248
+ } else if (stmt.children?.linkStyleStatement) {
48249
+ this.processLinkStyle(stmt.children.linkStyleStatement[0]);
48250
+ } else if (stmt.children?.clickStatement) {
48251
+ this.processClick(stmt.children.clickStatement[0]);
48252
+ } else if (stmt.children?.edgeAttrStatement) {
48253
+ this.processEdgeAttr(stmt.children.edgeAttrStatement[0]);
47282
48254
  }
47283
48255
  }
48256
+ this.applyLinkStyles();
48257
+ }
48258
+ unquote(s3) {
48259
+ if (!s3)
48260
+ return s3;
48261
+ if (s3.startsWith('"') && s3.endsWith('"') || s3.startsWith("'") && s3.endsWith("'"))
48262
+ return s3.slice(1, -1);
48263
+ return s3;
48264
+ }
48265
+ processClick(cst) {
48266
+ const ch = cst.children || {};
48267
+ const tgtTok = ch.clickTarget?.[0];
48268
+ if (!tgtTok)
48269
+ return;
48270
+ const id = tgtTok.image;
48271
+ const link = {};
48272
+ if (ch.clickHref && ch.clickHref[0]) {
48273
+ const hrefCh = ch.clickHref[0].children || {};
48274
+ if (hrefCh.url && hrefCh.url[0])
48275
+ link.href = this.unquote(hrefCh.url[0].image);
48276
+ if (hrefCh.tooltip && hrefCh.tooltip[0])
48277
+ link.tooltip = this.unquote(hrefCh.tooltip[0].image);
48278
+ if (hrefCh.target && hrefCh.target[0])
48279
+ link.target = hrefCh.target[0].image;
48280
+ } else if (ch.clickCall && ch.clickCall[0]) {
48281
+ const callCh = ch.clickCall[0].children || {};
48282
+ if (callCh.fn && callCh.fn[0])
48283
+ link.call = callCh.fn[0].image;
48284
+ if (callCh.tooltip && callCh.tooltip[0])
48285
+ link.tooltip = this.unquote(callCh.tooltip[0].image);
48286
+ } else {
48287
+ const idents = ch.Identifier || [];
48288
+ const texts = ch.Text || [];
48289
+ const quotes = ch.QuotedString || [];
48290
+ const modeTok = idents.find((t3) => /^(href|call|callback)$/i.test(t3.image));
48291
+ const mode = modeTok?.image?.toLowerCase();
48292
+ if (mode === "href") {
48293
+ const urlTok = quotes[0];
48294
+ const tipTok = quotes[1];
48295
+ const targetTok = idents.find((t3) => /^_(blank|self|parent|top)$/i.test(t3.image));
48296
+ if (urlTok)
48297
+ link.href = this.unquote(urlTok.image);
48298
+ if (tipTok)
48299
+ link.tooltip = this.unquote(tipTok.image);
48300
+ if (targetTok)
48301
+ link.target = targetTok.image;
48302
+ } else if (mode === "call" || mode === "callback") {
48303
+ const reserved = /* @__PURE__ */ new Set(["href", "call", "callback", "_blank", "_self", "_parent", "_top"]);
48304
+ const after = idents.filter((t3) => (t3.startOffset ?? 0) > (modeTok?.startOffset ?? -1));
48305
+ const nameTok = after.find((t3) => !reserved.has(t3.image.toLowerCase()));
48306
+ const tstr = texts.map((t3) => t3.image).join(" ").trim();
48307
+ link.call = nameTok ? nameTok.image + (tstr ? ` ${tstr}` : "") : tstr || void 0;
48308
+ const tipTok = quotes[0];
48309
+ if (tipTok)
48310
+ link.tooltip = this.unquote(tipTok.image);
48311
+ }
48312
+ }
48313
+ if (Object.keys(link).length)
48314
+ this.nodeLinks.set(id, { ...this.nodeLinks.get(id) || {}, ...link });
47284
48315
  }
47285
48316
  processNodeStatement(stmt) {
47286
48317
  const groups = stmt.children?.nodeOrParallelGroup;
47287
48318
  const links = stmt.children?.link;
47288
48319
  if (!groups || groups.length === 0)
47289
48320
  return;
48321
+ if ((!links || links.length === 0) && groups.length === 1) {
48322
+ const g0 = groups[0];
48323
+ const nodes = g0.children?.node || [];
48324
+ if (nodes.length === 1) {
48325
+ const n3 = nodes[0];
48326
+ const hasAttr = !!(n3.children.attrObject && n3.children.attrObject.length);
48327
+ const hasShape = !!n3.children?.nodeShape;
48328
+ if (hasAttr && !hasShape) {
48329
+ const idTok = n3.children.nodeId?.[0] || n3.children.Identifier?.[0] || void 0;
48330
+ if (idTok) {
48331
+ const id = idTok.image;
48332
+ const exists = this.edges.some((e3) => e3.id === id);
48333
+ if (exists) {
48334
+ const edgeAttrFake = { children: { edgeId: [{ image: id }], attrObject: n3.children.attrObject } };
48335
+ this.processEdgeAttr(edgeAttrFake);
48336
+ return;
48337
+ }
48338
+ }
48339
+ }
48340
+ }
48341
+ }
47290
48342
  const sourceNodes = this.processNodeGroup(groups[0]);
47291
48343
  if (groups.length > 1 && links && links.length > 0) {
47292
48344
  const targetNodes = this.processNodeGroup(groups[1]);
@@ -47294,7 +48346,7 @@ var init_graph_builder = __esm({
47294
48346
  for (const source of sourceNodes) {
47295
48347
  for (const target of targetNodes) {
47296
48348
  this.edges.push({
47297
- id: `e${this.edgeCounter++}`,
48349
+ id: linkInfo.edgeId || `e${this.edgeCounter++}`,
47298
48350
  source,
47299
48351
  target,
47300
48352
  label: linkInfo.label,
@@ -47310,7 +48362,7 @@ var init_graph_builder = __esm({
47310
48362
  for (const source of targetNodes) {
47311
48363
  for (const target of nextNodes) {
47312
48364
  this.edges.push({
47313
- id: `e${this.edgeCounter++}`,
48365
+ id: nextLink.edgeId || `e${this.edgeCounter++}`,
47314
48366
  source,
47315
48367
  target,
47316
48368
  label: nextLink.label,
@@ -47393,13 +48445,101 @@ var init_graph_builder = __esm({
47393
48445
  if (result.label)
47394
48446
  label = result.label;
47395
48447
  }
48448
+ const attrNode = children.attrObject?.[0];
48449
+ let typedShape;
48450
+ if (attrNode && !shapeNode) {
48451
+ typedShape = this.parseTypedAttrObject(attrNode);
48452
+ if (typedShape.shape) {
48453
+ const m3 = typedShape.shape;
48454
+ if (m3 === "rect")
48455
+ shape = "rectangle";
48456
+ else if (m3 === "round" || m3 === "rounded")
48457
+ shape = "round";
48458
+ else if (m3 === "stadium")
48459
+ shape = "stadium";
48460
+ else if (m3 === "subroutine")
48461
+ shape = "subroutine";
48462
+ else if (m3 === "circle")
48463
+ shape = "circle";
48464
+ else if (m3 === "cylinder")
48465
+ shape = "cylinder";
48466
+ else if (m3 === "diamond")
48467
+ shape = "diamond";
48468
+ else if (m3 === "trapezoid")
48469
+ shape = "trapezoid";
48470
+ else if (m3 === "trapezoidAlt")
48471
+ shape = "trapezoidAlt";
48472
+ else if (m3 === "parallelogram" || m3 === "lean-l" || m3 === "lean-r") {
48473
+ shape = "parallelogram";
48474
+ typedShape.lean = m3 === "lean-l" ? "l" : m3 === "lean-r" ? "r" : void 0;
48475
+ } else if (m3 === "hexagon")
48476
+ shape = "hexagon";
48477
+ else if (m3 === "icon" || m3 === "image")
48478
+ shape = "rectangle";
48479
+ }
48480
+ if (typeof typedShape.label === "string" && typedShape.label.length > 0) {
48481
+ label = typedShape.label;
48482
+ }
48483
+ }
47396
48484
  const clsTok = children.nodeClass?.[0];
47397
48485
  if (clsTok) {
47398
48486
  const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
47399
48487
  set.add(clsTok.image);
47400
48488
  this.nodeClasses.set(id, set);
47401
48489
  }
47402
- return { id, label, shape };
48490
+ const out = { id, label, shape };
48491
+ if (typedShape) {
48492
+ const padding = typedShape.padding;
48493
+ const cornerRadius = typedShape.cornerRadius;
48494
+ const lean = typedShape.lean;
48495
+ const media = typedShape.icon || typedShape.image ? { icon: typedShape.icon, image: typedShape.image } : void 0;
48496
+ out.typed = { padding, cornerRadius, lean, media };
48497
+ }
48498
+ return out;
48499
+ }
48500
+ parseTypedAttrObject(attrNode) {
48501
+ const ch = attrNode.children || {};
48502
+ const pairs = ch.attrPair || [];
48503
+ const out = {};
48504
+ for (const p3 of pairs) {
48505
+ const keyTok = p3.children?.attrKey?.[0];
48506
+ if (!keyTok)
48507
+ continue;
48508
+ const k3 = keyTok.image;
48509
+ const vTok = p3.children?.QuotedString?.[0] || p3.children?.Identifier?.[0] || p3.children?.NumberLiteral?.[0] || p3.children?.Text?.[0];
48510
+ if (!vTok)
48511
+ continue;
48512
+ let raw = vTok.image;
48513
+ if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'"))
48514
+ raw = raw.slice(1, -1);
48515
+ switch (k3) {
48516
+ case "shape":
48517
+ out.shape = raw;
48518
+ break;
48519
+ case "label":
48520
+ out.label = raw;
48521
+ break;
48522
+ case "padding": {
48523
+ const n3 = parseFloat(raw);
48524
+ if (Number.isFinite(n3))
48525
+ out.padding = n3;
48526
+ break;
48527
+ }
48528
+ case "cornerRadius": {
48529
+ const n3 = parseFloat(raw);
48530
+ if (Number.isFinite(n3))
48531
+ out.cornerRadius = n3;
48532
+ break;
48533
+ }
48534
+ case "icon":
48535
+ out.icon = raw;
48536
+ break;
48537
+ case "image":
48538
+ out.image = raw;
48539
+ break;
48540
+ }
48541
+ }
48542
+ return out;
47403
48543
  }
47404
48544
  extractShapeAndLabel(shapeNode) {
47405
48545
  const children = shapeNode.children;
@@ -47518,6 +48658,7 @@ var init_graph_builder = __esm({
47518
48658
  let label;
47519
48659
  let markerStart = "none";
47520
48660
  let markerEnd = "none";
48661
+ const eidTok = children.edgeId?.[0];
47521
48662
  if (children.BiDirectionalArrow) {
47522
48663
  type = "arrow";
47523
48664
  markerStart = "arrow";
@@ -47592,7 +48733,7 @@ var init_graph_builder = __esm({
47592
48733
  };
47593
48734
  label = strip(raw);
47594
48735
  }
47595
- return { type, label, markerStart, markerEnd };
48736
+ return { type, label, markerStart, markerEnd, edgeId: eidTok ? eidTok.image : void 0 };
47596
48737
  }
47597
48738
  processSubgraph(subgraph) {
47598
48739
  const children = subgraph.children;
@@ -47655,12 +48796,15 @@ var init_graph_builder = __esm({
47655
48796
  return;
47656
48797
  const classNameTok = cst.children.className?.[0];
47657
48798
  const className = classNameTok?.image || ids[ids.length - 1].image;
47658
- const nodeIds = classNameTok ? ids.slice(0, -1) : ids.slice(0, -1);
47659
- for (const tok of nodeIds) {
48799
+ const targetIds = classNameTok ? ids.slice(0, -1) : ids.slice(0, -1);
48800
+ for (const tok of targetIds) {
47660
48801
  const id = tok.image;
47661
- const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
47662
- set.add(className);
47663
- this.nodeClasses.set(id, set);
48802
+ const nset = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
48803
+ nset.add(className);
48804
+ this.nodeClasses.set(id, nset);
48805
+ const eset = this.edgeClasses.get(id) || /* @__PURE__ */ new Set();
48806
+ eset.add(className);
48807
+ this.edgeClasses.set(id, eset);
47664
48808
  const node = this.nodes.get(id);
47665
48809
  if (node) {
47666
48810
  node.style = { ...node.style || {}, ...this.computeNodeStyle(id) };
@@ -47706,6 +48850,121 @@ var init_graph_builder = __esm({
47706
48850
  }
47707
48851
  return props;
47708
48852
  }
48853
+ processEdgeAttr(cst) {
48854
+ const eidTok = cst.children.edgeId?.[0];
48855
+ if (!eidTok)
48856
+ return;
48857
+ const id = eidTok.image;
48858
+ const attrNode = cst.children.attrObject?.[0];
48859
+ if (!attrNode)
48860
+ return;
48861
+ const ch = attrNode.children || {};
48862
+ const pairs = ch.attrPair || [];
48863
+ const props = {};
48864
+ for (const p3 of pairs) {
48865
+ const keyTok = p3.children.attrKey?.[0];
48866
+ const vTok = p3.children.QuotedString?.[0] || p3.children.Identifier?.[0] || p3.children.NumberLiteral?.[0] || p3.children.Text?.[0];
48867
+ if (!keyTok || !vTok)
48868
+ continue;
48869
+ let val = vTok.image;
48870
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'"))
48871
+ val = val.slice(1, -1);
48872
+ const k3 = keyTok.image;
48873
+ if (k3 === "animate") {
48874
+ const truthy = /^(true|1|yes|on|fast|slow)$/i.test(val);
48875
+ if (truthy) {
48876
+ props["animation"] = /^slow$/i.test(val) ? "dash 8s linear infinite" : /^fast$/i.test(val) ? "dash 2s linear infinite" : "dash 4s linear infinite";
48877
+ if (!props["stroke-dasharray"])
48878
+ props["stroke-dasharray"] = "5 5";
48879
+ }
48880
+ } else {
48881
+ props[k3] = val;
48882
+ }
48883
+ }
48884
+ const cur = this.edgeStyles.get(id) || {};
48885
+ this.edgeStyles.set(id, { ...cur, ...props });
48886
+ }
48887
+ computeEdgeStyle(edgeId) {
48888
+ const out = {};
48889
+ const classes = this.edgeClasses.get(edgeId);
48890
+ if (classes) {
48891
+ for (const c3 of classes) {
48892
+ const s3 = this.classStyles.get(c3);
48893
+ if (s3)
48894
+ Object.assign(out, this.normalizeStyle(s3));
48895
+ }
48896
+ }
48897
+ const direct = this.edgeStyles.get(edgeId);
48898
+ if (direct)
48899
+ Object.assign(out, this.normalizeStyle(direct));
48900
+ return out;
48901
+ }
48902
+ processLinkStyle(cst) {
48903
+ const ch = cst.children || {};
48904
+ if (ch.linkStyleIndexList && ch.linkStylePairs) {
48905
+ const idxNode = ch.linkStyleIndexList[0];
48906
+ const pairNode = ch.linkStylePairs[0];
48907
+ const idxToks = (idxNode.children || {}).index || [];
48908
+ const indices2 = idxToks.map((t3) => parseInt(t3.image, 10)).filter((n3) => Number.isFinite(n3));
48909
+ const pairs = (pairNode.children || {}).linkStylePair || [];
48910
+ const props2 = {};
48911
+ for (const p3 of pairs) {
48912
+ const pch = p3.children || {};
48913
+ const keyTok = pch.key?.[0];
48914
+ const vTok = pch.valueColor?.[0] || pch.valueQuoted?.[0] || pch.valueNum?.[0] || pch.valueId?.[0] || pch.valueText?.[0];
48915
+ if (!keyTok || !vTok)
48916
+ continue;
48917
+ let val = vTok.image;
48918
+ if (vTok.tokenType?.name === "QuotedString" && (val.startsWith('"') || val.startsWith("'"))) {
48919
+ val = val.slice(1, -1);
48920
+ }
48921
+ props2[keyTok.image] = val;
48922
+ }
48923
+ this.pendingLinkStyles.push({ indices: indices2, props: props2 });
48924
+ return;
48925
+ }
48926
+ const nums = cst.children?.NumberLiteral || [];
48927
+ const indices = nums.map((n3) => parseInt(n3.image, 10)).filter((n3) => Number.isFinite(n3));
48928
+ const props = this.collectStyleProps(cst);
48929
+ this.pendingLinkStyles.push({ indices, props });
48930
+ }
48931
+ applyLinkStyles() {
48932
+ if (!this.pendingLinkStyles.length || !this.edges.length)
48933
+ return;
48934
+ const normalize = (s3) => {
48935
+ const out = {};
48936
+ for (const [kRaw, vRaw] of Object.entries(s3)) {
48937
+ const k3 = kRaw.trim().toLowerCase();
48938
+ const v3 = vRaw.trim();
48939
+ if (k3 === "stroke")
48940
+ out.stroke = v3;
48941
+ else if (k3 === "stroke-width") {
48942
+ const num = parseFloat(v3);
48943
+ if (!Number.isNaN(num))
48944
+ out.strokeWidth = num;
48945
+ } else if (k3 === "opacity" || k3 === "stroke-opacity") {
48946
+ const num = parseFloat(v3);
48947
+ if (!Number.isNaN(num))
48948
+ out.strokeOpacity = num;
48949
+ } else if (k3 === "stroke-dasharray")
48950
+ out.dasharray = v3;
48951
+ }
48952
+ return out;
48953
+ };
48954
+ for (const cmd of this.pendingLinkStyles) {
48955
+ const style = normalize(cmd.props);
48956
+ for (const idx of cmd.indices) {
48957
+ if (idx >= 0 && idx < this.edges.length) {
48958
+ const e3 = this.edges[idx];
48959
+ e3.style = { ...e3.style || {}, stroke: style.stroke ?? e3.style?.stroke, strokeWidth: style.strokeWidth ?? e3.style?.strokeWidth, strokeOpacity: style.strokeOpacity ?? e3.style?.strokeOpacity };
48960
+ if (style.dasharray)
48961
+ e3.dasharray = style.dasharray;
48962
+ if (style.animation)
48963
+ e3.animation = style.animation;
48964
+ }
48965
+ }
48966
+ }
48967
+ }
47709
48968
  computeNodeStyle(nodeId) {
47710
48969
  const out = {};
47711
48970
  const classes = this.nodeClasses.get(nodeId);
@@ -55457,8 +56716,10 @@ var init_layout = __esm({
55457
56716
  marginy: 20
55458
56717
  };
55459
56718
  if (hasClusters && (dir === "LR" || dir === "RL")) {
55460
- graphConfig.ranker = "longest-path";
56719
+ graphConfig.ranker = "network-simplex";
55461
56720
  graphConfig.acyclicer = "greedy";
56721
+ nodesep += 40;
56722
+ ranksep = Math.max(30, ranksep - 20);
55462
56723
  }
55463
56724
  if (hasClusters) {
55464
56725
  graphConfig.compound = true;
@@ -55471,7 +56732,9 @@ var init_layout = __esm({
55471
56732
  }
55472
56733
  }
55473
56734
  for (const node of graph.nodes) {
55474
- const dimensions = this.calculateNodeDimensions(node.label, node.shape);
56735
+ const providedW = node.width;
56736
+ const providedH = node.height;
56737
+ const dimensions = providedW && providedH ? { width: providedW, height: providedH } : this.calculateNodeDimensions(node.label, node.shape);
55475
56738
  g3.setNode(node.id, {
55476
56739
  width: dimensions.width,
55477
56740
  height: dimensions.height,
@@ -55595,7 +56858,7 @@ var init_layout = __esm({
55595
56858
  const inX = end.x + (rankdir === "LR" ? -PAD : PAD);
55596
56859
  const startOut = { x: srcSg ? outX : start.x, y: start.y };
55597
56860
  const endPre = { x: dstSg ? inX : end.x, y: end.y };
55598
- const alpha = 0.68;
56861
+ const alpha = 0.72;
55599
56862
  const midX = startOut.x + (endPre.x - startOut.x) * alpha;
55600
56863
  const m1 = { x: midX, y: startOut.y };
55601
56864
  const m22 = { x: midX, y: endPre.y };
@@ -55792,6 +57055,11 @@ function buildSharedCss(opts = {}) {
55792
57055
  .edge-path { stroke: ${edgeStroke}; stroke-width: 2px; fill: none; }
55793
57056
  .edge-label-bg { fill: rgba(232,232,232, 0.8); opacity: 0.5; }
55794
57057
  .edge-label-text { fill: #333; font-family: ${fontFamily}; font-size: ${Math.max(10, fontSize - 2)}px; }
57058
+ .edge-marker { stroke: ${edgeStroke}; }
57059
+ .edge-marker-fill { fill: ${edgeStroke}; }
57060
+
57061
+ /* Basic stroke dash animation used by flowchart link animation presets */
57062
+ @keyframes dash { to { stroke-dashoffset: -1000; } }
55795
57063
 
55796
57064
  /* Cluster (flowchart + sequence blocks) */
55797
57065
  .cluster-bg { fill: #ffffde; }
@@ -55806,15 +57074,77 @@ function buildSharedCss(opts = {}) {
55806
57074
  /* Sequence-specific add-ons (safe for flowcharts too) */
55807
57075
  .actor-rect { fill: #eaeaea; stroke: #666; stroke-width: 1.5px; }
55808
57076
  .actor-label { fill: #111; font-family: ${fontFamily}; font-size: 16px; }
55809
- .lifeline { stroke: #999; stroke-width: 0.5px; }
57077
+ .lifeline { stroke: #999; stroke-width: 1px; }
55810
57078
  .activation { fill: #f4f4f4; stroke: #666; stroke-width: 1px; }
55811
57079
  .msg-line { stroke: #333; stroke-width: 1.5px; fill: none; }
55812
57080
  .msg-line.dotted { stroke-dasharray: 2 2; }
55813
57081
  .msg-line.thick { stroke-width: 3px; }
57082
+ .openhead { fill: none; stroke: #333; stroke-width: 1.5px; }
57083
+ .crosshead path { stroke: #333; stroke-width: 1.5px; }
55814
57084
  .msg-label { fill: #333; font-family: ${fontFamily}; font-size: 12px; dominant-baseline: middle; }
55815
57085
  .msg-label-bg { fill: #ffffff; stroke: #cccccc; stroke-width: 1px; rx: 3; }
57086
+
57087
+ /* State overlays */
57088
+ .lane-divider { stroke: #aaaaaa; stroke-width: 1px; stroke-dasharray: 4 3; }
57089
+ .end-double { stroke: #3f3f3f; stroke-width: 1px; fill: none; }
55816
57090
  `;
55817
57091
  }
57092
+ function applyFlowLikeTheme(svg, theme) {
57093
+ if (!theme)
57094
+ return svg;
57095
+ let out = svg;
57096
+ if (theme.nodeBkg || theme.nodeBorder) {
57097
+ out = out.replace(/\.node-shape\s*\{[^}]*\}/, (m3) => {
57098
+ let rule = m3;
57099
+ if (theme.nodeBkg)
57100
+ rule = rule.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeBkg)};`);
57101
+ if (theme.nodeBorder)
57102
+ rule = rule.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.nodeBorder)};`);
57103
+ return rule;
57104
+ });
57105
+ }
57106
+ if (theme.nodeTextColor) {
57107
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeTextColor)};`));
57108
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeTextColor)};`));
57109
+ }
57110
+ if (theme.edgeLabelTextColor) {
57111
+ const c3 = String(theme.edgeLabelTextColor);
57112
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
57113
+ }
57114
+ if (theme.lineColor) {
57115
+ out = out.replace(/\.edge-path\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
57116
+ }
57117
+ if (theme.arrowheadColor) {
57118
+ out = out.replace(/\.edge-marker\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57119
+ 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)}; }`));
57120
+ out = out.replace(/\.openhead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57121
+ out = out.replace(/\.crosshead path\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57122
+ }
57123
+ if (theme.clusterBkg)
57124
+ out = out.replace(/\.cluster-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterBkg)};`));
57125
+ if (theme.clusterBorder)
57126
+ out = out.replace(/\.cluster-border\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.clusterBorder)};`));
57127
+ if (theme.clusterTextColor)
57128
+ out = out.replace(/\.cluster-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterTextColor)};`));
57129
+ if (theme.clusterTitleBg || theme.clusterTitleBackground) {
57130
+ const c3 = String(theme.clusterTitleBg || theme.clusterTitleBackground);
57131
+ out = out.replace(/\.cluster-title-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
57132
+ }
57133
+ if (theme.fontFamily) {
57134
+ const f3 = String(theme.fontFamily);
57135
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
57136
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
57137
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
57138
+ }
57139
+ if (theme.fontSize) {
57140
+ const s3 = String(theme.fontSize);
57141
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${s3}px;`));
57142
+ const sub = Math.max(10, Number(theme.fontSize) - 2);
57143
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${sub}px;`));
57144
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${sub}px;`));
57145
+ }
57146
+ return out;
57147
+ }
55818
57148
  var init_styles = __esm({
55819
57149
  "node_modules/@probelabs/maid/out/renderer/styles.js"() {
55820
57150
  }
@@ -55998,6 +57328,8 @@ var init_svg_generator = __esm({
55998
57328
  };
55999
57329
  const bgs = [];
56000
57330
  for (const sg of order) {
57331
+ if (sg.id && sg.id.includes("__lane"))
57332
+ continue;
56001
57333
  const x3 = sg.x + padX;
56002
57334
  const y2 = sg.y + padY;
56003
57335
  bgs.push(blockBackground(x3, y2, sg.width, sg.height, 0));
@@ -56035,7 +57367,7 @@ var init_svg_generator = __esm({
56035
57367
  edgeStroke: this.arrowStroke
56036
57368
  });
56037
57369
  const css = `<style>${sharedCss}</style>`;
56038
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
57370
+ 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}">
56039
57371
  ${bg}
56040
57372
  ${css}
56041
57373
  ${elements.join("\n ")}
@@ -56088,13 +57420,17 @@ var init_svg_generator = __esm({
56088
57420
  const stroke = node.style?.stroke ?? void 0;
56089
57421
  const fill = node.style?.fill ?? void 0;
56090
57422
  const styleAttr = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
57423
+ const typed = node.typed;
57424
+ const innerPad = Math.max(0, typed?.padding ?? 10);
56091
57425
  switch (node.shape) {
56092
57426
  case "rectangle":
56093
57427
  shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
56094
57428
  break;
56095
- case "round":
56096
- shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="5" ry="5" />`;
57429
+ case "round": {
57430
+ const rx = Math.max(0, typed?.cornerRadius ?? 5);
57431
+ shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="${rx}" ry="${rx}" />`;
56097
57432
  break;
57433
+ }
56098
57434
  case "stadium":
56099
57435
  const radius = node.height / 2;
56100
57436
  shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="${radius}" ry="${radius}" />`;
@@ -56138,16 +57474,18 @@ var init_svg_generator = __esm({
56138
57474
  }
56139
57475
  case "parallelogram": {
56140
57476
  const skew = node.width * 0.15;
56141
- const points = [
57477
+ const leftLean = typed?.lean === "l";
57478
+ const points = (leftLean ? [
57479
+ `${x3},${y2}`,
57480
+ `${x3 + node.width - skew},${y2}`,
57481
+ `${x3 + node.width},${y2 + node.height}`,
57482
+ `${x3 + skew},${y2 + node.height}`
57483
+ ] : [
56142
57484
  `${x3 + skew},${y2}`,
56143
- // top-left
56144
57485
  `${x3 + node.width},${y2}`,
56145
- // top-right
56146
57486
  `${x3 + node.width - skew},${y2 + node.height}`,
56147
- // bottom-right
56148
57487
  `${x3},${y2 + node.height}`
56149
- // bottom-left
56150
- ].join(" ");
57488
+ ]).join(" ");
56151
57489
  shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
56152
57490
  break;
56153
57491
  }
@@ -56217,11 +57555,33 @@ var init_svg_generator = __esm({
56217
57555
  const s3 = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
56218
57556
  shape = `<rect ${s3} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
56219
57557
  }
56220
- const text = this.generateWrappedText(node.label, cx, labelCenterY, node.width - 20);
56221
- return `<g id="${node.id}">
57558
+ const text = this.generateWrappedText(node.label, cx, labelCenterY, node.width - innerPad * 2);
57559
+ let media = "";
57560
+ if (typed?.media?.image) {
57561
+ const iw = Math.min(24, Math.max(12, node.height - 10));
57562
+ const ih = iw;
57563
+ const ix = x3 + 4;
57564
+ const iy = y2 + (node.height - ih) / 2;
57565
+ media = `<image xlink:href="${this.escapeXml(typed.media.image)}" x="${ix}" y="${iy}" width="${iw}" height="${ih}" />`;
57566
+ }
57567
+ const baseGroup = `<g id="${node.id}">
56222
57568
  ${shape}
57569
+ ${media}
56223
57570
  ${text}
56224
57571
  </g>`;
57572
+ const link = node.link;
57573
+ if (link && link.href) {
57574
+ const tt = link.tooltip ? `<title>${this.escapeXml(link.tooltip)}</title>` : "";
57575
+ const tgt = link.target ? ` target="${this.escapeXml(link.target)}" rel="noopener noreferrer"` : "";
57576
+ return `<a xlink:href="${this.escapeXml(link.href)}"${tgt} class="node-link">${tt}${baseGroup}</a>`;
57577
+ }
57578
+ if (link && link.tooltip) {
57579
+ return `<g class="node-call">
57580
+ <title>${this.escapeXml(link.tooltip)}</title>
57581
+ ${baseGroup}
57582
+ </g>`;
57583
+ }
57584
+ return baseGroup;
56225
57585
  }
56226
57586
  generateWrappedText(text, x3, y2, maxWidth) {
56227
57587
  if (text.includes("<")) {
@@ -56459,16 +57819,31 @@ var init_svg_generator = __esm({
56459
57819
  }
56460
57820
  const pathData = pathParts.join(" ");
56461
57821
  let edgeElement = `<path class="edge-path" d="${pathData}" stroke-linecap="round" stroke-linejoin="round"`;
57822
+ const styleStroke = edge.style?.stroke;
57823
+ const styleStrokeWidth = edge.style?.strokeWidth;
57824
+ const styleStrokeOpacity = edge.style?.strokeOpacity;
57825
+ if (edge.dasharray)
57826
+ strokeDasharray = String(edge.dasharray);
57827
+ const anim = edge.animation;
57828
+ if (!strokeDasharray && anim)
57829
+ strokeDasharray = "5 5";
56462
57830
  if (strokeDasharray) {
56463
57831
  edgeElement += ` stroke-dasharray="${strokeDasharray}"`;
56464
57832
  }
56465
- const startMarkUrl = mStart === "arrow" ? "url(#arrow)" : mStart === "circle" ? "url(#circle-marker)" : mStart === "cross" ? "url(#cross-marker)" : "";
56466
- const endMarkUrl = mEnd === "arrow" ? "url(#arrow)" : mEnd === "circle" ? "url(#circle-marker)" : mEnd === "cross" ? "url(#cross-marker)" : markerEnd || "";
56467
- if (startMarkUrl && mStart !== "arrow")
56468
- edgeElement += ` marker-start="${startMarkUrl}"`;
56469
- if (endMarkUrl && mEnd !== "arrow")
56470
- edgeElement += ` marker-end="${endMarkUrl}"`;
56471
- edgeElement += " />";
57833
+ if (styleStrokeWidth != null) {
57834
+ edgeElement += ` stroke-width="${styleStrokeWidth}"`;
57835
+ } else {
57836
+ if (strokeWidth && strokeWidth !== 1.5)
57837
+ edgeElement += ` stroke-width="${strokeWidth}"`;
57838
+ }
57839
+ if (styleStrokeOpacity != null) {
57840
+ edgeElement += ` stroke-opacity="${styleStrokeOpacity}"`;
57841
+ }
57842
+ if (styleStroke) {
57843
+ edgeElement += ` stroke="${styleStroke}"`;
57844
+ }
57845
+ const inlineAnim = anim ? ` style="animation:${anim}"` : "";
57846
+ edgeElement += inlineAnim + " />";
56472
57847
  if (edge.label) {
56473
57848
  const pos = this.pointAtRatio(points, 0.55);
56474
57849
  const text = this.escapeXml(edge.label);
@@ -56489,14 +57864,15 @@ var init_svg_generator = __esm({
56489
57864
  const uyl = vyl / vlenl;
56490
57865
  const nxl = -uyl;
56491
57866
  const nyl = uxl;
56492
- const triLenL = 8;
56493
- const triWL = 6;
57867
+ const ow = styleStrokeWidth != null ? styleStrokeWidth : strokeWidth;
57868
+ const triLenL = Math.max(6, Math.min(14, 6 + (ow - 1.5) * 3));
57869
+ const triWL = Math.max(5, Math.min(12, 5 + (ow - 1.5) * 2.5));
56494
57870
  const p1xL = boundaryEnd.x, p1yL = boundaryEnd.y;
56495
57871
  const baseXL = boundaryEnd.x - uxl * triLenL;
56496
57872
  const baseYL = boundaryEnd.y - uyl * triLenL;
56497
57873
  const p2xL = baseXL + nxl * (triWL / 2), p2yL = baseYL + nyl * (triWL / 2);
56498
57874
  const p3xL = baseXL - nxl * (triWL / 2), p3yL = baseYL - nyl * (triWL / 2);
56499
- overlay2 += triangleAtEnd(prevEndL, boundaryEnd, this.arrowStroke);
57875
+ overlay2 += triangleAtEnd(prevEndL, boundaryEnd, styleStroke || this.arrowStroke, triLenL, triWL);
56500
57876
  if (mStart === "arrow" && points.length >= 2) {
56501
57877
  const firstLeg = points[1];
56502
57878
  const svx = boundaryStart.x - firstLeg.x;
@@ -56508,7 +57884,7 @@ var init_svg_generator = __esm({
56508
57884
  const sny = sux;
56509
57885
  const sbaseX = boundaryStart.x - sux * triLenL;
56510
57886
  const sbaseY = boundaryStart.y - suy * triLenL;
56511
- overlay2 += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
57887
+ overlay2 += triangleAtStart(boundaryStart, firstLeg, styleStroke || this.arrowStroke, triLenL, triWL);
56512
57888
  }
56513
57889
  const pathGroup = `<g>
56514
57890
  ${edgeElement}
@@ -56527,15 +57903,16 @@ var init_svg_generator = __esm({
56527
57903
  const uy = vy / vlen;
56528
57904
  const nx = -uy;
56529
57905
  const ny = ux;
56530
- const triLen = 8;
56531
- const triW = 6;
57906
+ const ow2 = styleStrokeWidth != null ? styleStrokeWidth : strokeWidth;
57907
+ const triLen = Math.max(6, Math.min(14, 6 + (ow2 - 1.5) * 3));
57908
+ const triW = Math.max(5, Math.min(12, 5 + (ow2 - 1.5) * 2.5));
56532
57909
  const p1x = boundaryEnd.x, p1y = boundaryEnd.y;
56533
57910
  const baseX = boundaryEnd.x - ux * triLen;
56534
57911
  const baseY = boundaryEnd.y - uy * triLen;
56535
57912
  const p2x = baseX + nx * (triW / 2), p2y = baseY + ny * (triW / 2);
56536
57913
  const p3x = baseX - nx * (triW / 2), p3y = baseY - ny * (triW / 2);
56537
57914
  if (mEnd === "arrow")
56538
- overlay += triangleAtEnd(prevEnd, boundaryEnd, this.arrowStroke);
57915
+ overlay += triangleAtEnd(prevEnd, boundaryEnd, styleStroke || this.arrowStroke, triLen, triW);
56539
57916
  if (mStart === "arrow" && points.length >= 2) {
56540
57917
  const firstLeg = points[1];
56541
57918
  const svx = boundaryStart.x - firstLeg.x;
@@ -56545,8 +57922,19 @@ var init_svg_generator = __esm({
56545
57922
  const suy = svy / slen;
56546
57923
  const snx = -suy;
56547
57924
  const sny = sux;
56548
- overlay += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
56549
- }
57925
+ overlay += triangleAtStart(boundaryStart, firstLeg, styleStroke || this.arrowStroke, triLen, triW);
57926
+ }
57927
+ const owStroke = styleStroke || this.arrowStroke;
57928
+ const addCircle = (at2) => `<circle cx="${at2.x}" cy="${at2.y}" r="4.5" fill="none" stroke="${owStroke}" stroke-width="${ow2}" />`;
57929
+ 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>`;
57930
+ if (mEnd === "circle")
57931
+ overlay += addCircle(boundaryEnd);
57932
+ if (mEnd === "cross")
57933
+ overlay += addCross(boundaryEnd);
57934
+ if (mStart === "circle")
57935
+ overlay += addCircle(boundaryStart);
57936
+ if (mStart === "cross")
57937
+ overlay += addCross(boundaryStart);
56550
57938
  if (overlay) {
56551
57939
  const grouped = `<g>${edgeElement}
56552
57940
  ${overlay}</g>`;
@@ -56672,6 +58060,16 @@ ${overlay}</g>`;
56672
58060
  { x: node.x, y: node.y + node.height }
56673
58061
  ];
56674
58062
  switch (shape) {
58063
+ case "round": {
58064
+ const poly = [
58065
+ { x: node.x, y: node.y },
58066
+ { x: node.x + node.width, y: node.y },
58067
+ { x: node.x + node.width, y: node.y + node.height },
58068
+ { x: node.x, y: node.y + node.height }
58069
+ ];
58070
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58071
+ return hit || this.nearestPointOnPolygon(p22, poly);
58072
+ }
56675
58073
  case "circle": {
56676
58074
  const cx = node.x + node.width / 2;
56677
58075
  const cy = node.y + node.height / 2;
@@ -56682,7 +58080,8 @@ ${overlay}</g>`;
56682
58080
  const cx = node.x + node.width / 2;
56683
58081
  const cy = node.y + node.height / 2;
56684
58082
  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 }];
56685
- return this.linePolygonIntersection(p1, p22, poly);
58083
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58084
+ return hit || this.nearestPointOnPolygon(p22, poly);
56686
58085
  }
56687
58086
  case "hexagon": {
56688
58087
  const s3 = Math.max(10, node.width * 0.2);
@@ -56694,7 +58093,8 @@ ${overlay}</g>`;
56694
58093
  { x: node.x + s3, y: node.y + node.height },
56695
58094
  { x: node.x, y: node.y + node.height / 2 }
56696
58095
  ];
56697
- return this.linePolygonIntersection(p1, p22, poly);
58096
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58097
+ return hit || this.nearestPointOnPolygon(p22, poly);
56698
58098
  }
56699
58099
  case "parallelogram": {
56700
58100
  const o3 = Math.min(node.width * 0.25, node.height * 0.6);
@@ -56704,7 +58104,8 @@ ${overlay}</g>`;
56704
58104
  { x: node.x + node.width - o3, y: node.y + node.height },
56705
58105
  { x: node.x, y: node.y + node.height }
56706
58106
  ];
56707
- return this.linePolygonIntersection(p1, p22, poly);
58107
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58108
+ return hit || this.nearestPointOnPolygon(p22, poly);
56708
58109
  }
56709
58110
  case "trapezoid": {
56710
58111
  const o3 = Math.min(node.width * 0.2, node.height * 0.5);
@@ -56714,7 +58115,8 @@ ${overlay}</g>`;
56714
58115
  { x: node.x + node.width, y: node.y + node.height },
56715
58116
  { x: node.x, y: node.y + node.height }
56716
58117
  ];
56717
- return this.linePolygonIntersection(p1, p22, poly);
58118
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58119
+ return hit || this.nearestPointOnPolygon(p22, poly);
56718
58120
  }
56719
58121
  case "trapezoidAlt": {
56720
58122
  const o3 = Math.min(node.width * 0.2, node.height * 0.5);
@@ -56724,7 +58126,8 @@ ${overlay}</g>`;
56724
58126
  { x: node.x + node.width - o3, y: node.y + node.height },
56725
58127
  { x: node.x + o3, y: node.y + node.height }
56726
58128
  ];
56727
- return this.linePolygonIntersection(p1, p22, poly);
58129
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58130
+ return hit || this.nearestPointOnPolygon(p22, poly);
56728
58131
  }
56729
58132
  case "stadium": {
56730
58133
  const r3 = Math.min(node.height / 2, node.width / 2);
@@ -56752,10 +58155,13 @@ ${overlay}</g>`;
56752
58155
  }
56753
58156
  return best;
56754
58157
  };
56755
- return pick(left, right);
58158
+ const hit = pick(left, right);
58159
+ return hit || this.nearestPointOnPolygon(p22, rect);
56756
58160
  }
56757
58161
  default: {
56758
- return this.linePolygonIntersection(p1, p22, rectPoly());
58162
+ const poly = rectPoly();
58163
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58164
+ return hit || this.nearestPointOnPolygon(p22, poly);
56759
58165
  }
56760
58166
  }
56761
58167
  }
@@ -56795,6 +58201,30 @@ ${overlay}</g>`;
56795
58201
  }
56796
58202
  return best;
56797
58203
  }
58204
+ // Fallback helpers when lines are colinear or miss due to smoothing
58205
+ nearestPointOnSegment(p3, a3, b3) {
58206
+ const abx = b3.x - a3.x, aby = b3.y - a3.y;
58207
+ const ab2 = abx * abx + aby * aby || 1;
58208
+ const apx = p3.x - a3.x, apy = p3.y - a3.y;
58209
+ let t3 = (apx * abx + apy * aby) / ab2;
58210
+ t3 = Math.max(0, Math.min(1, t3));
58211
+ return { x: a3.x + abx * t3, y: a3.y + aby * t3 };
58212
+ }
58213
+ nearestPointOnPolygon(to, poly) {
58214
+ let best = poly[0];
58215
+ let bestD = Infinity;
58216
+ for (let i3 = 0; i3 < poly.length; i3++) {
58217
+ const a3 = poly[i3];
58218
+ const b3 = poly[(i3 + 1) % poly.length];
58219
+ const p3 = this.nearestPointOnSegment(to, a3, b3);
58220
+ const d3 = (p3.x - to.x) * (p3.x - to.x) + (p3.y - to.y) * (p3.y - to.y);
58221
+ if (d3 < bestD) {
58222
+ bestD = d3;
58223
+ best = p3;
58224
+ }
58225
+ }
58226
+ return { x: best.x, y: best.y };
58227
+ }
56798
58228
  segmentIntersection(p3, p22, q3, q22) {
56799
58229
  const r3 = { x: p22.x - p3.x, y: p22.y - p3.y };
56800
58230
  const s3 = { x: q22.x - q3.x, y: q22.y - q3.y };
@@ -57049,16 +58479,15 @@ var init_pie_renderer = __esm({
57049
58479
  }
57050
58480
  });
57051
58481
 
57052
- // node_modules/@probelabs/maid/out/renderer/sequence-builder.js
58482
+ // node_modules/@probelabs/maid/out/diagrams/sequence/cst-utils.js
57053
58483
  function textFromTokens(tokens) {
57054
58484
  if (!tokens || tokens.length === 0)
57055
58485
  return "";
57056
58486
  const parts = [];
57057
58487
  for (const t3 of tokens) {
57058
- const img = t3.image;
57059
- if (!img)
57060
- continue;
57061
- if (t3.tokenType && t3.tokenType.name === "QuotedString") {
58488
+ const img = t3.image ?? "";
58489
+ const name14 = t3.tokenType?.name;
58490
+ if (name14 === "QuotedString") {
57062
58491
  if (img.startsWith('"') && img.endsWith('"'))
57063
58492
  parts.push(img.slice(1, -1));
57064
58493
  else if (img.startsWith("'") && img.endsWith("'"))
@@ -57072,6 +58501,8 @@ function textFromTokens(tokens) {
57072
58501
  return parts.join(" ").replace(/\s+/g, " ").trim();
57073
58502
  }
57074
58503
  function actorRefToText(refCst) {
58504
+ if (!refCst)
58505
+ return "";
57075
58506
  const ch = refCst.children || {};
57076
58507
  const toks = [];
57077
58508
  ["Identifier", "QuotedString", "NumberLiteral", "Text"].forEach((k3) => {
@@ -57096,39 +58527,20 @@ function lineRemainderToText(lineRem) {
57096
58527
  "Comma",
57097
58528
  "Colon",
57098
58529
  "LParen",
57099
- "RParen",
57100
- "AndKeyword",
57101
- "ElseKeyword",
57102
- "OptKeyword",
57103
- "OptionKeyword",
57104
- "LoopKeyword",
57105
- "ParKeyword",
57106
- "RectKeyword",
57107
- "CriticalKeyword",
57108
- "BreakKeyword",
57109
- "BoxKeyword",
57110
- "EndKeyword",
57111
- "NoteKeyword",
57112
- "LeftKeyword",
57113
- "RightKeyword",
57114
- "OverKeyword",
57115
- "OfKeyword",
57116
- "AutonumberKeyword",
57117
- "OffKeyword",
57118
- "LinkKeyword",
57119
- "LinksKeyword",
57120
- "CreateKeyword",
57121
- "DestroyKeyword",
57122
- "ParticipantKeyword",
57123
- "ActorKeyword",
57124
- "ActivateKeyword",
57125
- "DeactivateKeyword"
58530
+ "RParen"
57126
58531
  ];
57127
58532
  for (const k3 of order)
57128
58533
  ch[k3]?.forEach((t3) => toks.push(t3));
57129
58534
  toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
57130
- return textFromTokens(toks) || void 0;
58535
+ const txt = textFromTokens(toks);
58536
+ return txt || void 0;
57131
58537
  }
58538
+ var init_cst_utils = __esm({
58539
+ "node_modules/@probelabs/maid/out/diagrams/sequence/cst-utils.js"() {
58540
+ }
58541
+ });
58542
+
58543
+ // node_modules/@probelabs/maid/out/renderer/sequence-builder.js
57132
58544
  function canonicalId(raw) {
57133
58545
  const t3 = raw.trim().replace(/\s+/g, "_");
57134
58546
  return t3;
@@ -57175,11 +58587,26 @@ function buildSequenceModel(text) {
57175
58587
  const byDisplay = /* @__PURE__ */ new Map();
57176
58588
  const events = [];
57177
58589
  let autonumber = { on: false };
58590
+ let title;
58591
+ let accTitle;
58592
+ let accDescr;
57178
58593
  const diagramChildren = cst.children || {};
57179
58594
  const lines = diagramChildren.line || [];
57180
58595
  const openBlocks = [];
57181
58596
  function processLineNode(ln) {
57182
58597
  const ch = ln.children || {};
58598
+ if (ch.metaStmt) {
58599
+ const m3 = ch.metaStmt[0];
58600
+ const mch = m3.children || {};
58601
+ const value = lineRemainderToText(mch.lineRemainder?.[0]) || "";
58602
+ if (mch.TitleKeyword)
58603
+ title = value;
58604
+ if (mch.AccTitleKeyword)
58605
+ accTitle = value;
58606
+ if (mch.AccDescrKeyword)
58607
+ accDescr = value;
58608
+ return;
58609
+ }
57183
58610
  if (ch.participantDecl) {
57184
58611
  const decl = ch.participantDecl[0];
57185
58612
  const dch = decl.children || {};
@@ -57278,8 +58705,8 @@ function buildSequenceModel(text) {
57278
58705
  handledBlock = true;
57279
58706
  const bnode = ch[spec.key][0];
57280
58707
  const bch = bnode.children || {};
57281
- const title = lineRemainderToText(bch.lineRemainder?.[0]);
57282
- const block = { type: spec.type, title, branches: spec.branchKeys ? [] : void 0 };
58708
+ const title2 = lineRemainderToText(bch.lineRemainder?.[0]);
58709
+ const block = { type: spec.type, title: title2, branches: spec.branchKeys ? [] : void 0 };
57283
58710
  openBlocks.push(block);
57284
58711
  events.push({ kind: "block-start", block });
57285
58712
  if (spec.branchKeys) {
@@ -57290,8 +58717,8 @@ function buildSequenceModel(text) {
57290
58717
  if (branchTokArr && branchTokArr.length) {
57291
58718
  const lr = (lrArr || []).slice(1);
57292
58719
  for (let i3 = 0; i3 < branchTokArr.length; i3++) {
57293
- const title2 = lr[i3] ? lineRemainderToText(lr[i3]) : void 0;
57294
- const br = { kind: spec.branchKeys[0].kind, title: title2 };
58720
+ const title22 = lr[i3] ? lineRemainderToText(lr[i3]) : void 0;
58721
+ const br = { kind: spec.branchKeys[0].kind, title: title22 };
57295
58722
  block.branches.push(br);
57296
58723
  events.push({ kind: "block-branch", block, branch: br });
57297
58724
  }
@@ -57351,13 +58778,17 @@ function buildSequenceModel(text) {
57351
58778
  return {
57352
58779
  participants: Array.from(participantsMap.values()),
57353
58780
  events,
57354
- autonumber: autonumber.on === true || autonumber.on === false ? autonumber : { on: false }
58781
+ autonumber: autonumber.on === true || autonumber.on === false ? autonumber : { on: false },
58782
+ title,
58783
+ accTitle,
58784
+ accDescr
57355
58785
  };
57356
58786
  }
57357
58787
  var init_sequence_builder = __esm({
57358
58788
  "node_modules/@probelabs/maid/out/renderer/sequence-builder.js"() {
57359
58789
  init_lexer4();
57360
58790
  init_parser4();
58791
+ init_cst_utils();
57361
58792
  }
57362
58793
  });
57363
58794
 
@@ -57453,7 +58884,7 @@ function layoutSequence(model) {
57453
58884
  if (start != null) {
57454
58885
  const p3 = col.get(actor);
57455
58886
  if (p3) {
57456
- activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(r3) - yForRow(start) });
58887
+ activations.push({ actor, x: p3.x + p3.width / 2 - 3, y: yForRow(start) - ROW_H / 2, width: 6, height: yForRow(r3) - yForRow(start) });
57457
58888
  }
57458
58889
  }
57459
58890
  actStack.set(actor, arr);
@@ -57563,7 +58994,7 @@ function layoutSequence(model) {
57563
58994
  const start = arr.pop();
57564
58995
  const p3 = col.get(actor);
57565
58996
  if (p3)
57566
- activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(lastRow) - yForRow(start) });
58997
+ activations.push({ actor, x: p3.x + p3.width / 2 - 3, y: yForRow(start) - ROW_H / 2, width: 6, height: yForRow(lastRow) - yForRow(start) });
57567
58998
  }
57568
58999
  }
57569
59000
  return { width, height, participants, lifelines, messages, notes, blocks, activations };
@@ -57575,14 +59006,14 @@ var init_sequence_layout = __esm({
57575
59006
  MARGIN_X = 24;
57576
59007
  MARGIN_Y = 24;
57577
59008
  ACTOR_FONT_SIZE = 16;
57578
- ACTOR_H = 32;
59009
+ ACTOR_H = 30;
57579
59010
  LIFELINE_GAP = 4;
57580
59011
  ACTOR_PAD_X = 12;
57581
59012
  COL_MIN = 110;
57582
59013
  ROW_H = 36;
57583
59014
  NOTE_W = 160;
57584
59015
  NOTE_PAD = 8;
57585
- BLOCK_PAD = 8;
59016
+ BLOCK_PAD = 12;
57586
59017
  TITLE_EXTRA_TOP = 12;
57587
59018
  }
57588
59019
  });
@@ -57602,6 +59033,18 @@ function renderSequence(model, opts = {}) {
57602
59033
  edgeStroke: "#555555"
57603
59034
  });
57604
59035
  svgParts.push(` <style>${sharedCss}</style>`);
59036
+ const accTitle = model.accTitle || model.title || void 0;
59037
+ const accDesc = model.accDescr || void 0;
59038
+ if (accTitle)
59039
+ svgParts.push(` <title>${escapeXml(accTitle)}</title>`);
59040
+ if (accDesc)
59041
+ svgParts.push(` <desc>${escapeXml(accDesc)}</desc>`);
59042
+ if (model.title) {
59043
+ const t3 = escapeXml(model.title);
59044
+ const tW = Math.max(20, measureText(model.title, 16));
59045
+ const xMid = width / 2;
59046
+ svgParts.push(` <text class="node-label" x="${xMid}" y="0" text-anchor="middle" font-size="16">${t3}</text>`);
59047
+ }
57605
59048
  for (const p3 of layout.participants)
57606
59049
  drawParticipant(svgParts, p3);
57607
59050
  for (const b3 of layout.blocks)
@@ -57625,14 +59068,14 @@ function renderSequence(model, opts = {}) {
57625
59068
  for (const b3 of layout.blocks) {
57626
59069
  const title = b3.title ? `${b3.type}: ${b3.title}` : b3.type;
57627
59070
  const branches = (b3.branches || []).map((br) => ({ y: br.y, title: br.title }));
57628
- svgParts.push(blockOverlay(b3.x, b3.y, b3.width, b3.height, title, branches, 0, "left", "left", 0));
59071
+ 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));
57629
59072
  }
57630
59073
  for (const p3 of layout.participants)
57631
59074
  drawParticipantBottom(svgParts, p3, layout);
57632
59075
  svgParts.push("</svg>");
57633
59076
  let svg = svgParts.join("\n");
57634
59077
  if (opts.theme)
57635
- svg = applySequenceTheme(svg, opts.theme);
59078
+ svg = applySequenceTheme(applyFlowLikeTheme(svg, opts.theme), opts.theme);
57636
59079
  return svg;
57637
59080
  }
57638
59081
  function drawParticipant(out, p3) {
@@ -57656,9 +59099,9 @@ function drawMessage(out, m3) {
57656
59099
  const start = { x: x1, y: y2 };
57657
59100
  const end = { x: x22, y: y2 };
57658
59101
  if (m3.endMarker === "arrow")
57659
- out.push(" " + triangleAtEnd(start, end));
59102
+ out.push(" " + triangleAtEnd(start, end, void 0, 9, 7));
57660
59103
  if (m3.startMarker === "arrow")
57661
- out.push(" " + triangleAtStart(start, end));
59104
+ out.push(" " + triangleAtStart(start, end, void 0, 9, 7));
57662
59105
  if (m3.endMarker === "open")
57663
59106
  out.push(` <circle class="openhead" cx="${x22}" cy="${y2}" r="4" />`);
57664
59107
  if (m3.startMarker === "open")
@@ -57682,8 +59125,8 @@ function drawMessageLabel(out, m3, label, _counter) {
57682
59125
  const h3 = 16;
57683
59126
  const w3 = Math.max(20, measureText(label, 12) + 10);
57684
59127
  const x3 = xMid - w3 / 2;
57685
- const y2 = m3.y - 10 - h3 / 2;
57686
- out.push(` <rect class="msg-label-bg" x="${x3}" y="${y2}" width="${w3}" height="${h3}" rx="0"/>`);
59128
+ const y2 = m3.y - 14 - h3 / 2;
59129
+ out.push(` <rect class="msg-label-bg" x="${x3}" y="${y2}" width="${w3}" height="${h3}" rx="3"/>`);
57687
59130
  out.push(` <text class="msg-label" x="${xMid}" y="${y2 + h3 / 2}" text-anchor="middle">${escapeXml(label)}</text>`);
57688
59131
  }
57689
59132
  function drawNote(out, n3) {
@@ -57694,18 +59137,12 @@ function drawNote(out, n3) {
57694
59137
  }
57695
59138
  function applySequenceTheme(svg, theme) {
57696
59139
  let out = svg;
57697
- if (theme.actorBkg)
57698
- out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorBkg)};`));
57699
- if (theme.actorBorder)
57700
- out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.actorBorder)};`));
57701
- if (theme.actorTextColor)
57702
- out = out.replace(/\.actor-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorTextColor)};`));
57703
59140
  if (theme.lifelineColor)
57704
59141
  out = out.replace(/\.lifeline\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lifelineColor)};`));
57705
59142
  if (theme.lineColor)
57706
59143
  out = out.replace(/\.msg-line\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
57707
59144
  if (theme.arrowheadColor) {
57708
- out = out.replace(/\.arrowhead\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.arrowheadColor)};`));
59145
+ out = out.replace(/(<path d=\"M[0-9.,\s-]+Z\" fill=\")[^\"]+(\")/g, (_m2, p1, p22) => `${p1}${String(theme.arrowheadColor)}${p22}`);
57709
59146
  out = out.replace(/\.openhead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57710
59147
  out = out.replace(/\.crosshead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57711
59148
  }
@@ -57731,6 +59168,329 @@ var init_sequence_renderer = __esm({
57731
59168
  }
57732
59169
  });
57733
59170
 
59171
+ // node_modules/@probelabs/maid/out/renderer/state-builder.js
59172
+ function textFromTokens2(tokens) {
59173
+ if (!tokens || tokens.length === 0)
59174
+ return "";
59175
+ const parts = [];
59176
+ for (const t3 of tokens) {
59177
+ const img = t3.image ?? "";
59178
+ if (t3.tokenType && t3.tokenType.name === "QuotedString") {
59179
+ if (img.startsWith('"') && img.endsWith('"'))
59180
+ parts.push(img.slice(1, -1));
59181
+ else if (img.startsWith("'") && img.endsWith("'"))
59182
+ parts.push(img.slice(1, -1));
59183
+ else
59184
+ parts.push(img);
59185
+ } else {
59186
+ parts.push(img);
59187
+ }
59188
+ }
59189
+ return parts.join(" ").replace(/\s+/g, " ").trim();
59190
+ }
59191
+ function actorRefToId(ref, ctx = {}) {
59192
+ if (!ref)
59193
+ return { id: "", kind: "simple" };
59194
+ const ch = ref.children || {};
59195
+ if (ch.Start) {
59196
+ const kind = ctx.isTarget ? "end" : "start";
59197
+ return { id: `__${kind}_${ch.Start[0].startOffset ?? 0}`, kind };
59198
+ }
59199
+ if (ch.HistoryDeep)
59200
+ return { id: `__histdeep_${ch.HistoryDeep[0].startOffset ?? 0}`, label: "H*", kind: "history-deep" };
59201
+ if (ch.HistoryShallow)
59202
+ return { id: `__hist_${ch.HistoryShallow[0].startOffset ?? 0}`, label: "H", kind: "history" };
59203
+ let special;
59204
+ if (ch.AngleAngleOpen && ch.Identifier && ch.AngleAngleClose) {
59205
+ const k3 = String(ch.Identifier[0].image).toLowerCase();
59206
+ if (k3 === "choice")
59207
+ special = "choice";
59208
+ else if (k3 === "fork")
59209
+ special = "fork";
59210
+ else if (k3 === "join")
59211
+ special = "join";
59212
+ }
59213
+ const toks = [];
59214
+ ch.Identifier?.forEach((t3) => toks.push(t3));
59215
+ ch.QuotedString?.forEach((t3) => toks.push(t3));
59216
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59217
+ const txt = textFromTokens2(toks) || "";
59218
+ const id = txt.trim().replace(/\s+/g, "_");
59219
+ return { id, label: txt, kind: special || "simple" };
59220
+ }
59221
+ function buildStateModel(text) {
59222
+ const { tokens } = tokenize5(text);
59223
+ parserInstance5.input = tokens;
59224
+ const cst = parserInstance5.diagram();
59225
+ let direction = "TD";
59226
+ const nodes = /* @__PURE__ */ new Map();
59227
+ const transitions = [];
59228
+ const composites = [];
59229
+ const lanes = [];
59230
+ const stack = [];
59231
+ const diagramChildren = cst.children || {};
59232
+ const stmts = diagramChildren.statement || [];
59233
+ function ensureNode(def) {
59234
+ const ex = nodes.get(def.id);
59235
+ if (ex)
59236
+ return ex;
59237
+ nodes.set(def.id, def);
59238
+ const parentCtx = stack[stack.length - 1];
59239
+ if (parentCtx) {
59240
+ const parent = parentCtx.id;
59241
+ const laneId = `${parent}__lane${parentCtx.lane}`;
59242
+ let laneSg = composites.find((c3) => c3.id === laneId);
59243
+ if (!laneSg) {
59244
+ if (!composites.find((c3) => c3.id === parent))
59245
+ composites.push({ id: parent, label: parent, nodes: [], parent: stack.length > 1 ? stack[stack.length - 2].id : void 0 });
59246
+ composites.push({ id: laneId, label: void 0, nodes: [], parent });
59247
+ lanes.push({ parentId: parent, id: laneId, nodes: [] });
59248
+ }
59249
+ laneSg = composites.find((c3) => c3.id === laneId);
59250
+ if (!laneSg.nodes.includes(def.id))
59251
+ laneSg.nodes.push(def.id);
59252
+ const laneRec = lanes.find((l3) => l3.id === laneId);
59253
+ if (laneRec && !laneRec.nodes.includes(def.id))
59254
+ laneRec.nodes.push(def.id);
59255
+ def.parent = laneId;
59256
+ }
59257
+ return def;
59258
+ }
59259
+ function visitStatement(node) {
59260
+ const ch = node.children || {};
59261
+ if (ch.directionStmt) {
59262
+ const d3 = ch.directionStmt[0].children.Direction?.[0]?.image || "TD";
59263
+ direction = d3;
59264
+ return;
59265
+ }
59266
+ if (ch.stateDecl) {
59267
+ const n3 = ch.stateDecl[0];
59268
+ const dch = n3.children || {};
59269
+ if (dch.QuotedString && dch.AsKw && dch.Identifier) {
59270
+ const label = dch.QuotedString[0].image.slice(1, -1);
59271
+ const id = dch.Identifier[0].image;
59272
+ ensureNode({ id, label, kind: "simple" });
59273
+ } else if (dch.Identifier) {
59274
+ const id = dch.Identifier[0].image;
59275
+ ensureNode({ id, label: id, kind: "simple" });
59276
+ }
59277
+ return;
59278
+ }
59279
+ if (ch.stateBlock) {
59280
+ const b3 = ch.stateBlock[0];
59281
+ const bch = b3.children || {};
59282
+ const idTok = bch.Identifier?.[0] || bch.QuotedString?.[0];
59283
+ const idRaw = idTok ? idTok.image.startsWith('"') ? idTok.image.slice(1, -1) : idTok.image : `__state_${b3.location ?? Math.random()}`;
59284
+ const id = idRaw.replace(/\s+/g, "_");
59285
+ ensureNode({ id, label: idRaw, kind: "composite" });
59286
+ if (!composites.find((c3) => c3.id === id))
59287
+ composites.push({ id, label: idRaw, nodes: [], parent: stack.length ? stack[stack.length - 1].id : void 0 });
59288
+ stack.push({ id, lane: 0 });
59289
+ const inner = bch.innerStatement || [];
59290
+ for (const s3 of inner)
59291
+ visitStatement(s3);
59292
+ stack.pop();
59293
+ return;
59294
+ }
59295
+ if (ch.transitionStmt) {
59296
+ const t3 = ch.transitionStmt[0];
59297
+ const tch = t3.children || {};
59298
+ const left = actorRefToId(tch.actorRef?.[0], { isTarget: false });
59299
+ const right = actorRefToId(tch.actorRef?.[1], { isTarget: true });
59300
+ if (left.id)
59301
+ ensureNode({ id: left.id, label: left.label || left.id, kind: left.kind });
59302
+ if (right.id)
59303
+ ensureNode({ id: right.id, label: right.label || right.id, kind: right.kind });
59304
+ let label;
59305
+ if (tch.Colon && tch.labelText) {
59306
+ const toks = [];
59307
+ tch.labelText.forEach((lt) => {
59308
+ const ch2 = lt.children || {};
59309
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => ch2[k3]?.forEach((tt) => toks.push(tt)));
59310
+ });
59311
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59312
+ label = textFromTokens2(toks);
59313
+ }
59314
+ if (left.id && right.id)
59315
+ transitions.push({ source: left.id, target: right.id, label });
59316
+ return;
59317
+ }
59318
+ if (node.name === "innerStatement") {
59319
+ const ich = node.children || {};
59320
+ if (ich.Dashes && ich.Dashes.length && stack.length) {
59321
+ stack[stack.length - 1].lane += 1;
59322
+ return;
59323
+ }
59324
+ }
59325
+ if (ch.noteStmt) {
59326
+ const n3 = ch.noteStmt[0];
59327
+ const nch = n3.children || {};
59328
+ const txtToks = [];
59329
+ const targetRef = nch.actorRef?.[0];
59330
+ const target = actorRefToId(targetRef);
59331
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => nch[k3]?.forEach((tk) => txtToks.push(tk)));
59332
+ const text2 = textFromTokens2(txtToks);
59333
+ if (target.id && text2) {
59334
+ const noteId = `__note_${(n3.location ?? Math.random()).toString().slice(2)}`;
59335
+ ensureNode({ id: noteId, label: text2, kind: "simple" });
59336
+ ensureNode({ id: target.id, label: target.label || target.id, kind: target.kind });
59337
+ transitions.push({ source: noteId, target: target.id, label: void 0 });
59338
+ }
59339
+ return;
59340
+ }
59341
+ if (ch.stateDescriptionStmt) {
59342
+ const s3 = ch.stateDescriptionStmt[0];
59343
+ const sch = s3.children || {};
59344
+ const nameTok = sch.Identifier?.[0] || sch.QuotedString?.[0];
59345
+ if (nameTok) {
59346
+ const raw = nameTok.image.startsWith('"') ? nameTok.image.slice(1, -1) : nameTok.image;
59347
+ const id = raw.replace(/\s+/g, "_");
59348
+ const labelToks = [];
59349
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => sch[k3]?.forEach((tt) => labelToks.push(tt)));
59350
+ const lbl = textFromTokens2(labelToks);
59351
+ ensureNode({ id, label: lbl || raw, kind: "simple" });
59352
+ }
59353
+ return;
59354
+ }
59355
+ for (const key of Object.keys(ch)) {
59356
+ const arr = ch[key];
59357
+ if (Array.isArray(arr))
59358
+ arr.forEach((n3) => visitStatement(n3));
59359
+ }
59360
+ }
59361
+ for (const st of stmts)
59362
+ visitStatement(st);
59363
+ return {
59364
+ direction,
59365
+ nodes: Array.from(nodes.values()),
59366
+ transitions,
59367
+ composites,
59368
+ lanes
59369
+ };
59370
+ }
59371
+ var init_state_builder = __esm({
59372
+ "node_modules/@probelabs/maid/out/renderer/state-builder.js"() {
59373
+ init_lexer6();
59374
+ init_parser6();
59375
+ }
59376
+ });
59377
+
59378
+ // node_modules/@probelabs/maid/out/renderer/state-renderer.js
59379
+ function toGraph(model) {
59380
+ const nodes = [];
59381
+ const edges = [];
59382
+ const subgraphs = [];
59383
+ for (const s3 of model.nodes) {
59384
+ let shape = "rectangle";
59385
+ let label = s3.label || s3.id;
59386
+ if (s3.kind === "start") {
59387
+ shape = "circle";
59388
+ label = "";
59389
+ } else if (s3.kind === "end") {
59390
+ shape = "circle";
59391
+ label = "";
59392
+ } else if (s3.kind === "history") {
59393
+ shape = "circle";
59394
+ label = "H";
59395
+ } else if (s3.kind === "history-deep") {
59396
+ shape = "circle";
59397
+ label = "H*";
59398
+ } else if (s3.kind === "choice") {
59399
+ shape = "diamond";
59400
+ } else if (s3.kind === "fork" || s3.kind === "join") {
59401
+ shape = "rectangle";
59402
+ }
59403
+ const node = { id: s3.id, label, shape };
59404
+ if (s3.kind === "fork" || s3.kind === "join") {
59405
+ node.width = 80;
59406
+ node.height = 8;
59407
+ }
59408
+ nodes.push(node);
59409
+ }
59410
+ for (const t3 of model.transitions) {
59411
+ 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" });
59412
+ }
59413
+ for (const c3 of model.composites) {
59414
+ subgraphs.push({ id: c3.id, label: c3.label, nodes: c3.nodes, parent: c3.parent });
59415
+ }
59416
+ const laneGroups = (model.lanes || []).slice();
59417
+ return { graph: { nodes, edges, subgraphs, direction: model.direction }, laneGroups };
59418
+ }
59419
+ function renderState(model) {
59420
+ var _a16;
59421
+ const { graph, laneGroups } = toGraph(model);
59422
+ const layout = new DagreLayoutEngine().layout(graph);
59423
+ let svg = new SVGRenderer().render(layout);
59424
+ const byId = Object.fromEntries(layout.nodes.map((n3) => [n3.id, { x: n3.x, y: n3.y, width: n3.width, height: n3.height }]));
59425
+ 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 }]));
59426
+ const overlays = [];
59427
+ const groupByParent = {};
59428
+ for (const lg of laneGroups) {
59429
+ const parent = subById[lg.parentId];
59430
+ if (!parent)
59431
+ continue;
59432
+ const members = lg.nodes.map((id) => byId[id]).filter(Boolean);
59433
+ if (!members.length)
59434
+ continue;
59435
+ (groupByParent[_a16 = lg.parentId] || (groupByParent[_a16] = [])).push({ id: lg.id, nodes: members });
59436
+ }
59437
+ const laneIndex = (id) => {
59438
+ const m3 = /(.*)__lane(\d+)/.exec(id);
59439
+ return m3 ? parseInt(m3[2], 10) : Number.POSITIVE_INFINITY;
59440
+ };
59441
+ for (const pid of Object.keys(groupByParent)) {
59442
+ const parent = subById[pid];
59443
+ if (!parent)
59444
+ continue;
59445
+ const lanes = groupByParent[pid].slice();
59446
+ if (lanes.every((l3) => /__lane\d+/.test(l3.id)))
59447
+ lanes.sort((a3, b3) => laneIndex(a3.id) - laneIndex(b3.id));
59448
+ else if (graph.direction === "LR" || graph.direction === "RL")
59449
+ lanes.sort((a3, b3) => Math.min(...a3.nodes.map((n3) => n3.x)) - Math.min(...b3.nodes.map((n3) => n3.x)));
59450
+ else
59451
+ lanes.sort((a3, b3) => Math.min(...a3.nodes.map((n3) => n3.y)) - Math.min(...b3.nodes.map((n3) => n3.y)));
59452
+ for (let i3 = 1; i3 < lanes.length; i3++) {
59453
+ const prev = lanes[i3 - 1];
59454
+ const next = lanes[i3];
59455
+ if (graph.direction === "LR" || graph.direction === "RL") {
59456
+ const prevMaxX = Math.max(...prev.nodes.map((n3) => n3.x + n3.width));
59457
+ const nextMinX = Math.min(...next.nodes.map((n3) => n3.x));
59458
+ const x3 = Math.max(parent.x, Math.min(parent.x + parent.width, (prevMaxX + nextMinX) / 2));
59459
+ overlays.push(`<line class="lane-divider" x1="${x3}" y1="${parent.y + 14}" x2="${x3}" y2="${parent.y + parent.height}" />`);
59460
+ } else {
59461
+ const prevMaxY = Math.max(...prev.nodes.map((n3) => n3.y + n3.height));
59462
+ const nextMinY = Math.min(...next.nodes.map((n3) => n3.y));
59463
+ const y2 = Math.max(parent.y + 14, Math.min(parent.y + parent.height, (prevMaxY + nextMinY) / 2));
59464
+ overlays.push(`<line class="lane-divider" x1="${parent.x}" y1="${y2}" x2="${parent.x + parent.width}" y2="${y2}" />`);
59465
+ }
59466
+ }
59467
+ }
59468
+ for (const n3 of layout.nodes) {
59469
+ const src = (model.nodes || []).find((nn) => nn.id === n3.id);
59470
+ if (!src || src.kind !== "end")
59471
+ continue;
59472
+ const cx = n3.x + n3.width / 2;
59473
+ const cy = n3.y + n3.height / 2;
59474
+ const r3 = Math.max(1, Math.min(n3.width, n3.height) / 2 - 3);
59475
+ overlays.push(`<circle class="end-double" cx="${cx}" cy="${cy}" r="${r3}" fill="none" />`);
59476
+ }
59477
+ if (overlays.length) {
59478
+ svg = svg.replace("</svg>", `<g class="state-overlays">${overlays.join("\n")}</g></svg>`);
59479
+ }
59480
+ if (!/<style>/.test(svg)) {
59481
+ const css = buildSharedCss();
59482
+ svg = svg.replace("<svg ", `<svg `).replace("</svg>", `<style>${css}</style></svg>`);
59483
+ }
59484
+ return svg;
59485
+ }
59486
+ var init_state_renderer = __esm({
59487
+ "node_modules/@probelabs/maid/out/renderer/state-renderer.js"() {
59488
+ init_layout();
59489
+ init_svg_generator();
59490
+ init_styles();
59491
+ }
59492
+ });
59493
+
57734
59494
  // node_modules/@probelabs/maid/out/core/frontmatter.js
57735
59495
  function parseFrontmatter(input) {
57736
59496
  const text = input.startsWith("\uFEFF") ? input.slice(1) : input;
@@ -57853,6 +59613,443 @@ var init_frontmatter = __esm({
57853
59613
  }
57854
59614
  });
57855
59615
 
59616
+ // node_modules/@probelabs/maid/out/renderer/class-builder.js
59617
+ function textFromTokens3(tokens) {
59618
+ if (!tokens || tokens.length === 0)
59619
+ return "";
59620
+ const parts = [];
59621
+ for (const t3 of tokens) {
59622
+ const img = t3.image ?? "";
59623
+ if (t3.tokenType && t3.tokenType.name === "QuotedString") {
59624
+ if (img.startsWith('"') && img.endsWith('"'))
59625
+ parts.push(img.slice(1, -1));
59626
+ else if (img.startsWith("'") && img.endsWith("'"))
59627
+ parts.push(img.slice(1, -1));
59628
+ else
59629
+ parts.push(img);
59630
+ } else {
59631
+ parts.push(img);
59632
+ }
59633
+ }
59634
+ return parts.join(" ").replace(/\s+/g, " ").trim();
59635
+ }
59636
+ function classRefToText(refCst) {
59637
+ if (!refCst)
59638
+ return "";
59639
+ const ch = refCst.children || {};
59640
+ const toks = [];
59641
+ ["Identifier", "QuotedString", "BacktickName"].forEach((k3) => {
59642
+ const arr = ch[k3];
59643
+ arr?.forEach((t3) => toks.push(t3));
59644
+ });
59645
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59646
+ return textFromTokens3(toks);
59647
+ }
59648
+ function memberLineToText(member) {
59649
+ const ch = member.children || {};
59650
+ const toks = [];
59651
+ const order = ["Visibility", "Identifier", "QuotedString", "LParen", "RParen", "Comma", "Colon", "NumberLiteral"];
59652
+ for (const k3 of order)
59653
+ ch[k3]?.forEach((t3) => toks.push(t3));
59654
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59655
+ const txt = textFromTokens3(toks);
59656
+ const isMethod = /(\)\s*:|\)$)/.test(txt) || /\(/.test(txt);
59657
+ return { text: txt, isMethod };
59658
+ }
59659
+ function canonicalId2(raw) {
59660
+ return raw.trim().replace(/\s+/g, "_");
59661
+ }
59662
+ function buildClassModel(text) {
59663
+ const { tokens } = tokenize4(text);
59664
+ parserInstance4.input = tokens;
59665
+ const cst = parserInstance4.diagram();
59666
+ const classes = /* @__PURE__ */ new Map();
59667
+ const relations = [];
59668
+ const notes = [];
59669
+ let direction = "TD";
59670
+ function ensureClass(idRaw, display) {
59671
+ const id = canonicalId2(idRaw);
59672
+ const existing = classes.get(id);
59673
+ if (existing)
59674
+ return existing;
59675
+ const def = { id, display: display || idRaw, attributes: [], methods: [] };
59676
+ classes.set(id, def);
59677
+ return def;
59678
+ }
59679
+ const diagramChildren = cst.children || {};
59680
+ const stmts = diagramChildren.statement || [];
59681
+ for (const st of stmts) {
59682
+ const ch = st.children || {};
59683
+ if (ch.directionStmt) {
59684
+ const d3 = ch.directionStmt[0].children.Direction?.[0]?.image || "TD";
59685
+ if (d3 === "TB")
59686
+ direction = "TB";
59687
+ else if (d3 === "BT")
59688
+ direction = "BT";
59689
+ else if (d3 === "LR")
59690
+ direction = "LR";
59691
+ else if (d3 === "RL")
59692
+ direction = "RL";
59693
+ else
59694
+ direction = "TD";
59695
+ continue;
59696
+ }
59697
+ if (ch.classLine) {
59698
+ const node = ch.classLine[0];
59699
+ const nch = node.children || {};
59700
+ const name14 = classRefToText(nch.classRef?.[0]);
59701
+ const def = ensureClass(name14);
59702
+ if (nch.LTlt && nch.Identifier && nch.GTgt) {
59703
+ def.stereotype = nch.Identifier[0].image;
59704
+ }
59705
+ if (nch.LCurly && nch.memberLineStmt) {
59706
+ const lines = nch.memberLineStmt;
59707
+ for (const m3 of lines) {
59708
+ const mm = memberLineToText(m3.children.memberLine?.[0]);
59709
+ if (!mm.text)
59710
+ continue;
59711
+ (mm.isMethod ? def.methods : def.attributes).push(mm.text);
59712
+ }
59713
+ }
59714
+ continue;
59715
+ }
59716
+ if (ch.memberAssignStmt) {
59717
+ const node = ch.memberAssignStmt[0];
59718
+ const nch = node.children || {};
59719
+ const clsName = classRefToText(nch.classRef?.[0]);
59720
+ const def = ensureClass(clsName);
59721
+ const mm = memberLineToText(nch.memberLine?.[0]);
59722
+ if (mm.text)
59723
+ (mm.isMethod ? def.methods : def.attributes).push(mm.text);
59724
+ continue;
59725
+ }
59726
+ if (ch.noteStmt) {
59727
+ const node = ch.noteStmt[0];
59728
+ const nch = node.children || {};
59729
+ const target = classRefToText(nch.classRef?.[0]);
59730
+ const labelToks = [];
59731
+ ["QuotedString", "Identifier", "NumberLiteral"].forEach((k3) => nch[k3]?.forEach((t3) => labelToks.push(t3)));
59732
+ const text2 = textFromTokens3(labelToks);
59733
+ if (target && text2)
59734
+ notes.push({ target: canonicalId2(target), text: text2 });
59735
+ continue;
59736
+ }
59737
+ if (ch.relationStmt) {
59738
+ const node = ch.relationStmt[0];
59739
+ const rch = node.children || {};
59740
+ const leftName = classRefToText(rch.classRef?.[0]);
59741
+ const rightName = classRefToText(rch.classRef?.[1]);
59742
+ const left = ensureClass(leftName).id;
59743
+ const right = ensureClass(rightName).id;
59744
+ const leftCardTok = rch.leftCard?.[0];
59745
+ const rightCardTok = rch.rightCard?.[0];
59746
+ const leftCard = leftCardTok?.image ? leftCardTok.image.slice(1, -1) : void 0;
59747
+ const rightCard = rightCardTok?.image ? rightCardTok.image.slice(1, -1) : void 0;
59748
+ let label;
59749
+ if (rch.labelText) {
59750
+ const toks = [];
59751
+ rch.labelText.forEach((lt) => {
59752
+ const ch2 = lt.children || {};
59753
+ ["QuotedString", "Identifier", "NumberLiteral", "GenericAngle"].forEach((k3) => {
59754
+ ch2[k3]?.forEach((t3) => toks.push(t3));
59755
+ });
59756
+ });
59757
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59758
+ label = textFromTokens3(toks);
59759
+ }
59760
+ const relMap = [
59761
+ { key: "RelAssociation", kind: "association" },
59762
+ { key: "RelDependency", kind: "dependency" },
59763
+ { key: "RelRealization", kind: "realization" },
59764
+ { key: "RelExtends", kind: "extends" },
59765
+ { key: "RelAggregation", kind: "aggregation" },
59766
+ { key: "RelComposition", kind: "composition" },
59767
+ { key: "RelDependencyLeft", kind: "dependency" },
59768
+ { key: "RelRealizationLeft", kind: "realization" },
59769
+ { key: "RelExtendsRight", kind: "extends" },
59770
+ { key: "RelAggBoth", kind: "aggregation-both" },
59771
+ { key: "RelCompBoth", kind: "composition-both" },
59772
+ { key: "RelAggToComp", kind: "aggregation-to-comp" },
59773
+ { key: "RelCompToAgg", kind: "composition-to-agg" },
59774
+ { key: "LollipopLeft", kind: "lollipop-left" },
59775
+ { key: "LollipopRight", kind: "lollipop-right" }
59776
+ ];
59777
+ let kind = "association";
59778
+ for (const m3 of relMap) {
59779
+ if (rch[m3.key]) {
59780
+ kind = m3.kind;
59781
+ break;
59782
+ }
59783
+ }
59784
+ let src = left, dst = right;
59785
+ if (rch.RelExtends || rch.RelDependencyLeft || rch.RelRealizationLeft || rch.LollipopLeft) {
59786
+ src = right;
59787
+ dst = left;
59788
+ }
59789
+ const rel = { source: src, target: dst, kind, label, leftCard, rightCard };
59790
+ relations.push(rel);
59791
+ continue;
59792
+ }
59793
+ }
59794
+ return {
59795
+ direction,
59796
+ classes: Array.from(classes.values()),
59797
+ relations,
59798
+ notes
59799
+ };
59800
+ }
59801
+ var init_class_builder = __esm({
59802
+ "node_modules/@probelabs/maid/out/renderer/class-builder.js"() {
59803
+ init_lexer5();
59804
+ init_parser5();
59805
+ }
59806
+ });
59807
+
59808
+ // node_modules/@probelabs/maid/out/renderer/class-renderer.js
59809
+ function classNodeSize(def, fontSize = 14) {
59810
+ const title = def.stereotype ? `\xAB${def.stereotype}\xBB ${def.display}` : def.display;
59811
+ const attrLines = def.attributes.slice();
59812
+ const methodLines = def.methods.slice();
59813
+ const lineH = Math.max(16, Math.round(fontSize * 1.1));
59814
+ const padX = 12, padY = 10;
59815
+ const titleW = measureText(title, fontSize + 1) + padX * 2;
59816
+ const attrsW = Math.max(0, ...attrLines.map((t3) => measureText(t3, fontSize))) + padX * 2;
59817
+ const methodsW = Math.max(0, ...methodLines.map((t3) => measureText(t3, fontSize))) + padX * 2;
59818
+ const width = Math.max(120, titleW, attrsW, methodsW);
59819
+ const sepH = (attrLines.length ? 6 : 0) + (methodLines.length ? 6 : 0);
59820
+ const height = padY * 2 + lineH + attrLines.length * lineH + (methodLines.length ? 6 : 0) + (attrLines.length ? 6 : 0) + methodLines.length * lineH;
59821
+ return { width, height, title, attrLines, methodLines };
59822
+ }
59823
+ function triangleOpenAt(points, color, length = 10, width = 8, atEnd = true) {
59824
+ const [a3, b3] = atEnd ? points : [points[1], points[0]];
59825
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59826
+ const len = Math.hypot(vx, vy) || 1;
59827
+ const ux = vx / len, uy = vy / len;
59828
+ const nx = -uy, ny = ux;
59829
+ const tip = { x: b3.x, y: b3.y };
59830
+ const base = { x: b3.x - ux * length, y: b3.y - uy * length };
59831
+ const p22 = { x: base.x + nx * (width / 2), y: base.y + ny * (width / 2) };
59832
+ const p3 = { x: base.x - nx * (width / 2), y: base.y - ny * (width / 2) };
59833
+ 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" />`;
59834
+ }
59835
+ function triangleHollowAt(points, color, length = 12, width = 10, atEnd = true) {
59836
+ const [a3, b3] = atEnd ? points : [points[1], points[0]];
59837
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59838
+ const len = Math.hypot(vx, vy) || 1;
59839
+ const ux = vx / len, uy = vy / len;
59840
+ const nx = -uy, ny = ux;
59841
+ const tip = { x: b3.x, y: b3.y };
59842
+ const base = { x: b3.x - ux * length, y: b3.y - uy * length };
59843
+ const p22 = { x: base.x + nx * (width / 2), y: base.y + ny * (width / 2) };
59844
+ const p3 = { x: base.x - nx * (width / 2), y: base.y - ny * (width / 2) };
59845
+ const d3 = `M${tip.x},${tip.y} L${p22.x},${p22.y} L${p3.x},${p3.y} Z`;
59846
+ return `<path class="edge-marker" d="${d3}" fill="white" stroke="${color}" />`;
59847
+ }
59848
+ function diamondAt(points, color, filled, size = 10, atStart = true) {
59849
+ const [a3, b3] = atStart ? points : [points[1], points[0]];
59850
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59851
+ const len = Math.hypot(vx, vy) || 1;
59852
+ const ux = vx / len, uy = vy / len;
59853
+ const nx = -uy, ny = ux;
59854
+ const center = { x: a3.x, y: a3.y };
59855
+ const pTip = { x: center.x - ux * size, y: center.y - uy * size };
59856
+ const pLeft = { x: center.x + nx * (size / 1.4), y: center.y + ny * (size / 1.4) };
59857
+ const pRight = { x: center.x - nx * (size / 1.4), y: center.y - ny * (size / 1.4) };
59858
+ const pBack = { x: center.x + ux * size, y: center.y + uy * size };
59859
+ const d3 = `M${pTip.x},${pTip.y} L${pLeft.x},${pLeft.y} L${pBack.x},${pBack.y} L${pRight.x},${pRight.y} Z`;
59860
+ 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}"/>`;
59861
+ }
59862
+ function polyline(points, cls, dashed = false, stroke = "#555", strokeWidth = 2) {
59863
+ const d3 = points.map((p3) => `${p3.x},${p3.y}`).join(" ");
59864
+ const dash = dashed ? ` stroke-dasharray="4 3"` : "";
59865
+ return `<polyline class="edge-path ${cls}" points="${d3}" fill="none"${dash}/>`;
59866
+ }
59867
+ function renderClass(model, opts = {}) {
59868
+ const nodes = [];
59869
+ const nodeSizeInfo = {};
59870
+ for (const c3 of model.classes) {
59871
+ const sz = classNodeSize(c3);
59872
+ nodeSizeInfo[c3.id] = sz;
59873
+ nodes.push({ id: c3.id, label: c3.display, shape: "rectangle", width: sz.width, height: sz.height });
59874
+ }
59875
+ const edges = model.relations.map((r3, i3) => ({ id: `e${i3}`, source: r3.source, target: r3.target, type: "open" }));
59876
+ const graph = { nodes, edges, direction: model.direction };
59877
+ const layoutEngine = new DagreLayoutEngine();
59878
+ const layout = layoutEngine.layout(graph);
59879
+ const width = Math.ceil(layout.width + 40);
59880
+ const height = Math.ceil(layout.height + 40);
59881
+ const parts = [];
59882
+ 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}">`);
59883
+ const sharedCss = buildSharedCss();
59884
+ parts.push(`<style>${sharedCss}
59885
+ .class-title { font-weight: 600; }
59886
+ .class-divider { stroke: #aaa; stroke-width: 1; }
59887
+ .class-member { font-size: 12px; }
59888
+ </style>`);
59889
+ for (const n3 of layout.nodes) {
59890
+ const info = nodeSizeInfo[n3.id];
59891
+ const x3 = n3.x, y2 = n3.y, w3 = n3.width, h3 = n3.height;
59892
+ const title = info.title;
59893
+ const attrs = info.attrLines;
59894
+ const methods = info.methodLines;
59895
+ const lineH = 16;
59896
+ const padX = 12;
59897
+ const padY = 10;
59898
+ let cy = y2 + padY + lineH;
59899
+ parts.push(` <g transform="translate(${x3},${y2})">`);
59900
+ parts.push(` <rect class="node-shape" width="${w3}" height="${h3}" rx="0"/>`);
59901
+ parts.push(` <text class="node-label class-title" x="${w3 / 2}" y="${padY + 12}" text-anchor="middle" dominant-baseline="middle">${escapeXml(title)}</text>`);
59902
+ let yCursor = padY + 18;
59903
+ if (attrs.length) {
59904
+ parts.push(` <line class="class-divider" x1="0" y1="${yCursor}" x2="${w3}" y2="${yCursor}"/>`);
59905
+ yCursor += 8;
59906
+ for (const a3 of attrs) {
59907
+ parts.push(` <text class="node-label class-member" x="${padX}" y="${yCursor}" dominant-baseline="hanging">${escapeXml(a3)}</text>`);
59908
+ yCursor += lineH;
59909
+ }
59910
+ }
59911
+ if (methods.length) {
59912
+ parts.push(` <line class="class-divider" x1="0" y1="${yCursor}" x2="${w3}" y2="${yCursor}"/>`);
59913
+ yCursor += 8;
59914
+ for (const m3 of methods) {
59915
+ parts.push(` <text class="node-label class-member" x="${padX}" y="${yCursor}" dominant-baseline="hanging">${escapeXml(m3)}</text>`);
59916
+ yCursor += lineH;
59917
+ }
59918
+ }
59919
+ parts.push(" </g>");
59920
+ }
59921
+ const edgeColor = "#555";
59922
+ for (let i3 = 0; i3 < layout.edges.length; i3++) {
59923
+ const e3 = layout.edges[i3];
59924
+ const rel = model.relations[i3];
59925
+ const pts = e3.points;
59926
+ const dashed = rel.kind === "dependency" || rel.kind === "realization";
59927
+ parts.push(polyline(pts, "edge-path", dashed, edgeColor, 2));
59928
+ const placeEndpoint = (pt, next, text, side) => {
59929
+ const vx = next.x - pt.x;
59930
+ const vy = next.y - pt.y;
59931
+ const vlen = Math.hypot(vx, vy) || 1;
59932
+ const ux = vx / vlen;
59933
+ const uy = vy / vlen;
59934
+ const nx = -uy;
59935
+ const ny = ux;
59936
+ const away = -6;
59937
+ const perp = 8;
59938
+ const x3 = pt.x + ux * away + nx * perp;
59939
+ const y2 = pt.y + uy * away + ny * perp;
59940
+ const anchor = side === "start" ? "end" : "start";
59941
+ parts.push(`<text class="edge-label-text" x="${x3}" y="${y2}" text-anchor="${anchor}">${escapeXml(text)}</text>`);
59942
+ };
59943
+ if (rel.leftCard && pts.length >= 2)
59944
+ placeEndpoint(pts[0], pts[1], rel.leftCard, "start");
59945
+ if (rel.rightCard && pts.length >= 2) {
59946
+ const a3 = pts[pts.length - 1];
59947
+ const b3 = pts[pts.length - 2];
59948
+ placeEndpoint(a3, b3, rel.rightCard, "end");
59949
+ }
59950
+ if (rel.label) {
59951
+ const mid = pts[Math.floor(pts.length / 2)];
59952
+ const words = String(rel.label).split(/\s+/);
59953
+ const lines = [];
59954
+ let cur = "";
59955
+ const maxW = 200;
59956
+ for (const w3 of words) {
59957
+ const test = cur ? cur + " " + w3 : w3;
59958
+ if (measureText(test, 12) <= maxW)
59959
+ cur = test;
59960
+ else {
59961
+ if (cur)
59962
+ lines.push(cur);
59963
+ cur = w3;
59964
+ }
59965
+ }
59966
+ if (cur)
59967
+ lines.push(cur);
59968
+ const dy = 14;
59969
+ let y0 = mid.y - (lines.length - 1) * dy / 2 - 10;
59970
+ 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>`);
59971
+ }
59972
+ const pStart = [pts[0], pts[1] ?? pts[0]];
59973
+ const pEnd = [pts[pts.length - 2] ?? pts[pts.length - 1], pts[pts.length - 1]];
59974
+ switch (rel.kind) {
59975
+ case "extends":
59976
+ parts.push(triangleHollowAt(pEnd, edgeColor, 12, 10, true));
59977
+ break;
59978
+ case "realization":
59979
+ parts.push(triangleHollowAt(pEnd, edgeColor, 12, 10, true));
59980
+ break;
59981
+ case "dependency":
59982
+ parts.push(triangleOpenAt(pEnd, edgeColor, 10, 7, true));
59983
+ break;
59984
+ case "aggregation":
59985
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
59986
+ break;
59987
+ case "composition":
59988
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
59989
+ break;
59990
+ case "aggregation-both":
59991
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
59992
+ parts.push(diamondAt(pEnd, edgeColor, false, 8, false));
59993
+ break;
59994
+ case "composition-both":
59995
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
59996
+ parts.push(diamondAt(pEnd, edgeColor, true, 8, false));
59997
+ break;
59998
+ case "aggregation-to-comp":
59999
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
60000
+ parts.push(diamondAt(pEnd, edgeColor, true, 8, false));
60001
+ break;
60002
+ case "composition-to-agg":
60003
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
60004
+ parts.push(diamondAt(pEnd, edgeColor, false, 8, false));
60005
+ break;
60006
+ case "lollipop-left":
60007
+ parts.push(`<circle class="edge-marker" cx="${pStart[0].x}" cy="${pStart[0].y}" r="5" fill="white" stroke="${edgeColor}" />`);
60008
+ break;
60009
+ case "lollipop-right":
60010
+ parts.push(`<circle class="edge-marker" cx="${pEnd[1].x}" cy="${pEnd[1].y}" r="5" fill="white" stroke="${edgeColor}" />`);
60011
+ break;
60012
+ case "association":
60013
+ default:
60014
+ break;
60015
+ }
60016
+ }
60017
+ const noteW = 140, noteH = 44, dx = 20;
60018
+ const byId = Object.fromEntries(layout.nodes.map((n3) => [n3.id, n3]));
60019
+ const seenAnchorCount = {};
60020
+ const notes = model.notes || [];
60021
+ for (const note of notes) {
60022
+ const anchor = byId[note.target];
60023
+ if (!anchor)
60024
+ continue;
60025
+ const count = seenAnchorCount[note.target] = (seenAnchorCount[note.target] || 0) + 1;
60026
+ const nx = anchor.x + anchor.width + dx;
60027
+ let ny = anchor.y + (count - 1) * (noteH + 8);
60028
+ 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));
60029
+ let guard = 0;
60030
+ while (overlaps(nx, ny) && guard < 50) {
60031
+ ny += noteH + 6;
60032
+ guard++;
60033
+ }
60034
+ parts.push(` <g class="note" transform="translate(${nx},${ny})">`);
60035
+ parts.push(` <rect width="${noteW}" height="${noteH}" rx="0"/>`);
60036
+ parts.push(` <text class="note-text" x="${noteW / 2}" y="${noteH / 2 + 4}" text-anchor="middle">${escapeXml(note.text)}</text>`);
60037
+ parts.push(" </g>");
60038
+ const ax = anchor.x + anchor.width;
60039
+ const ay = anchor.y + 16;
60040
+ parts.push(`<line x1="${ax}" y1="${ay}" x2="${nx}" y2="${ny + noteH / 2}" stroke="#999" stroke-dasharray="4 3"/>`);
60041
+ }
60042
+ parts.push("</svg>");
60043
+ return parts.join("\n");
60044
+ }
60045
+ var init_class_renderer = __esm({
60046
+ "node_modules/@probelabs/maid/out/renderer/class-renderer.js"() {
60047
+ init_layout();
60048
+ init_styles();
60049
+ init_utils4();
60050
+ }
60051
+ });
60052
+
57856
60053
  // node_modules/@probelabs/maid/out/renderer/dot-renderer.js
57857
60054
  var init_dot_renderer = __esm({
57858
60055
  "node_modules/@probelabs/maid/out/renderer/dot-renderer.js"() {
@@ -57936,6 +60133,10 @@ function applyFlowchartTheme(svg, theme) {
57936
60133
  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)}"`);
57937
60134
  out = out.replace(/(<circle cx="4\.5" cy="4\.5" r="4\.5"[^>]*)(fill="[^"]*")/g, (_m2, p1) => `${p1}fill="${String(theme.arrowheadColor)}"`);
57938
60135
  }
60136
+ if (theme.edgeLabelTextColor) {
60137
+ const c3 = String(theme.edgeLabelTextColor);
60138
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
60139
+ }
57939
60140
  if (theme.clusterBkg) {
57940
60141
  out = out.replace(/\.cluster-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterBkg)};`));
57941
60142
  }
@@ -57945,6 +60146,12 @@ function applyFlowchartTheme(svg, theme) {
57945
60146
  if (theme.clusterTextColor) {
57946
60147
  out = out.replace(/\.cluster-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterTextColor)};`));
57947
60148
  }
60149
+ if (theme.noteBkg)
60150
+ out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteBkg)};`));
60151
+ if (theme.noteBorder)
60152
+ out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.noteBorder)};`));
60153
+ if (theme.noteTextColor)
60154
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteTextColor)};`));
57948
60155
  if (theme.fontFamily)
57949
60156
  out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${String(theme.fontFamily)};`));
57950
60157
  if (theme.fontSize)
@@ -57967,7 +60174,12 @@ var init_renderer = __esm({
57967
60174
  init_pie_renderer();
57968
60175
  init_sequence_builder();
57969
60176
  init_sequence_renderer();
60177
+ init_styles();
60178
+ init_state_builder();
60179
+ init_state_renderer();
57970
60180
  init_frontmatter();
60181
+ init_class_builder();
60182
+ init_class_renderer();
57971
60183
  init_layout();
57972
60184
  init_svg_generator();
57973
60185
  init_dot_renderer();
@@ -58102,7 +60314,31 @@ var init_renderer = __esm({
58102
60314
  return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
58103
60315
  }
58104
60316
  }
58105
- const errorSvg = this.generateErrorSvg("Unsupported diagram type. Rendering supports flowchart, pie, and sequence for now.");
60317
+ if (/^classDiagram\b/.test(firstLine)) {
60318
+ try {
60319
+ const model = buildClassModel(content);
60320
+ const svg = renderClass(model, { theme });
60321
+ const themed = theme ? applyFlowLikeTheme(svg, theme) : svg;
60322
+ return { svg: themed, graph: { nodes: [], edges: [], direction: model.direction }, errors: [] };
60323
+ } catch (e3) {
60324
+ const msg = e3?.message || "Class render error";
60325
+ const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "CLASS_RENDER" }];
60326
+ return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
60327
+ }
60328
+ }
60329
+ if (/^stateDiagram(?:-v2)?\b/.test(firstLine)) {
60330
+ try {
60331
+ const model = buildStateModel(content);
60332
+ const svg = renderState(model);
60333
+ const themed = theme ? applyFlowLikeTheme(svg, theme) : svg;
60334
+ return { svg: themed, graph: { nodes: [], edges: [], direction: model.direction }, errors: [] };
60335
+ } catch (e3) {
60336
+ const msg = e3?.message || "State render error";
60337
+ const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "STATE_RENDER" }];
60338
+ return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
60339
+ }
60340
+ }
60341
+ const errorSvg = this.generateErrorSvg("Unsupported diagram type. Rendering supports flowchart, pie, sequence, class, and state.");
58106
60342
  return {
58107
60343
  svg: errorSvg,
58108
60344
  graph: { nodes: [], edges: [], direction: "TD" },
@@ -58496,13 +60732,14 @@ async function validateMermaidDiagram(diagram) {
58496
60732
  };
58497
60733
  }
58498
60734
  const result = validate(diagram);
58499
- if (result.errors && result.errors.length === 0) {
60735
+ const actualErrors = (result.errors || []).filter((err) => err.severity === "error");
60736
+ if (actualErrors.length === 0) {
58500
60737
  return {
58501
60738
  isValid: true,
58502
60739
  diagramType: result.type || "unknown"
58503
60740
  };
58504
60741
  } else {
58505
- const errorMessages = (result.errors || []).map((err) => {
60742
+ const errorMessages = actualErrors.map((err) => {
58506
60743
  const location = err.line ? `line ${err.line}${err.column ? `:${err.column}` : ""}` : "";
58507
60744
  return location ? `${location} - ${err.message}` : err.message;
58508
60745
  });
@@ -58511,8 +60748,8 @@ async function validateMermaidDiagram(diagram) {
58511
60748
  diagramType: result.type || "unknown",
58512
60749
  error: errorMessages[0] || "Validation failed",
58513
60750
  detailedError: errorMessages.join("\n"),
58514
- errors: result.errors || []
58515
- // Include raw maid errors for AI fixing
60751
+ errors: actualErrors
60752
+ // Include only actual errors for AI fixing
58516
60753
  };
58517
60754
  }
58518
60755
  } catch (error2) {
@@ -59400,10 +61637,19 @@ var init_client2 = __esm({
59400
61637
  if (this.debug) {
59401
61638
  console.error(`[MCP] Calling ${toolName} with args:`, args);
59402
61639
  }
59403
- const result = await clientInfo.client.callTool({
59404
- name: tool3.originalName,
59405
- arguments: args
61640
+ const timeout = this.config?.settings?.timeout || 3e4;
61641
+ const timeoutPromise = new Promise((_2, reject2) => {
61642
+ setTimeout(() => {
61643
+ reject2(new Error(`MCP tool call timeout after ${timeout}ms`));
61644
+ }, timeout);
59406
61645
  });
61646
+ const result = await Promise.race([
61647
+ clientInfo.client.callTool({
61648
+ name: tool3.originalName,
61649
+ arguments: args
61650
+ }),
61651
+ timeoutPromise
61652
+ ]);
59407
61653
  return result;
59408
61654
  } catch (error2) {
59409
61655
  console.error(`[MCP] Error calling tool ${toolName}:`, error2);
@@ -59817,11 +62063,39 @@ var init_ProbeAgent = __esm({
59817
62063
  this.mcpServers = options.mcpServers || null;
59818
62064
  this.mcpBridge = null;
59819
62065
  this.initializeModel();
62066
+ }
62067
+ /**
62068
+ * Initialize the agent asynchronously (must be called after constructor)
62069
+ * This method initializes MCP and merges MCP tools into the tool list
62070
+ */
62071
+ async initialize() {
59820
62072
  if (this.enableMcp) {
59821
- this.initializeMCP().catch((error2) => {
62073
+ try {
62074
+ await this.initializeMCP();
62075
+ if (this.mcpBridge) {
62076
+ const mcpTools = this.mcpBridge.mcpTools || {};
62077
+ for (const [toolName, toolImpl] of Object.entries(mcpTools)) {
62078
+ this.toolImplementations[toolName] = toolImpl;
62079
+ }
62080
+ }
62081
+ if (this.debug) {
62082
+ const allToolNames = Object.keys(this.toolImplementations);
62083
+ const nativeToolCount = allToolNames.filter((name14) => !this.mcpBridge?.mcpTools?.[name14]).length;
62084
+ const mcpToolCount = allToolNames.length - nativeToolCount;
62085
+ console.error("\n[DEBUG] ========================================");
62086
+ console.error("[DEBUG] All Tools Initialized");
62087
+ console.error(`[DEBUG] Native tools: ${nativeToolCount}, MCP tools: ${mcpToolCount}`);
62088
+ console.error("[DEBUG] Available tools:");
62089
+ for (const toolName of allToolNames) {
62090
+ const isMCP = this.mcpBridge?.mcpTools?.[toolName] ? " (MCP)" : "";
62091
+ console.error(`[DEBUG] - ${toolName}${isMCP}`);
62092
+ }
62093
+ console.error("[DEBUG] ========================================\n");
62094
+ }
62095
+ } catch (error2) {
59822
62096
  console.error("[MCP] Failed to initialize MCP:", error2);
59823
62097
  this.mcpBridge = null;
59824
- });
62098
+ }
59825
62099
  }
59826
62100
  }
59827
62101
  /**
@@ -60048,20 +62322,40 @@ var init_ProbeAgent = __esm({
60048
62322
  }
60049
62323
  }
60050
62324
  /**
60051
- * Extract directory paths from listFiles tool output
62325
+ * Extract directory paths from tool output (both listFiles and extract tool)
60052
62326
  * @param {string} content - Tool output content
60053
62327
  * @returns {string[]} - Array of directory paths
60054
62328
  */
60055
62329
  extractListFilesDirectories(content) {
60056
62330
  const directories = [];
60057
- const dirPattern = /^([^\n:]+):\s*$/gm;
62331
+ const fileHeaderPattern = /^File:\s+(.+)$/gm;
60058
62332
  let match;
62333
+ while ((match = fileHeaderPattern.exec(content)) !== null) {
62334
+ const filePath = match[1].trim();
62335
+ const dir = (0, import_path9.dirname)(filePath);
62336
+ if (dir && dir !== ".") {
62337
+ directories.push(dir);
62338
+ if (this.debug) {
62339
+ console.log(`[DEBUG] Extracted directory context from File header: ${dir}`);
62340
+ }
62341
+ }
62342
+ }
62343
+ const dirPattern = /^(\/[^\n:]+|[A-Z]:\\[^\n:]+|\.\.?(?:\/[^\n:]+)?):\s*$/gm;
60059
62344
  while ((match = dirPattern.exec(content)) !== null) {
60060
62345
  const dirPath = match[1].trim();
60061
- if (dirPath && dirPath.length > 0) {
60062
- directories.push(dirPath);
60063
- if (this.debug) {
60064
- console.log(`[DEBUG] Extracted directory context from listFiles: ${dirPath}`);
62346
+ const hasInvalidChars = /\s/.test(dirPath);
62347
+ const isValidPath = !hasInvalidChars && (dirPath.startsWith("/") || // Unix absolute path
62348
+ /^[A-Z]:\\/.test(dirPath) || // Windows absolute path (C:\)
62349
+ dirPath === "." || // Current directory
62350
+ dirPath === ".." || // Parent directory
62351
+ dirPath.startsWith("./") && dirPath.length > 2 && !dirPath.includes(" ") || // ./something (no spaces)
62352
+ dirPath.startsWith("../") && dirPath.length > 3 && !dirPath.includes(" "));
62353
+ if (isValidPath) {
62354
+ if (!directories.includes(dirPath)) {
62355
+ directories.push(dirPath);
62356
+ if (this.debug) {
62357
+ console.log(`[DEBUG] Extracted directory context from listFiles: ${dirPath}`);
62358
+ }
60065
62359
  }
60066
62360
  }
60067
62361
  }