@probelabs/probe 0.6.0-rc118 → 0.6.0-rc119

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.
@@ -42939,7 +42939,7 @@ function tokenize(text) {
42939
42939
  const lexResult = MermaidLexer.tokenize(text);
42940
42940
  return lexResult;
42941
42941
  }
42942
- 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;
42942
+ 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;
42943
42943
  var init_lexer2 = __esm({
42944
42944
  "node_modules/@probelabs/maid/out/diagrams/flowchart/lexer.js"() {
42945
42945
  init_api5();
@@ -42992,6 +42992,8 @@ var init_lexer2 = __esm({
42992
42992
  pattern: /classDef/,
42993
42993
  longer_alt: Identifier
42994
42994
  });
42995
+ ClickKeyword = createToken({ name: "ClickKeyword", pattern: /click/, longer_alt: Identifier });
42996
+ LinkStyleKeyword = createToken({ name: "LinkStyleKeyword", pattern: /linkStyle/, longer_alt: Identifier });
42995
42997
  Ampersand = createToken({
42996
42998
  name: "Ampersand",
42997
42999
  pattern: /&/
@@ -43086,6 +43088,7 @@ var init_lexer2 = __esm({
43086
43088
  DiamondClose = createToken({ name: "DiamondClose", pattern: /\}/ });
43087
43089
  AngleOpen = createToken({ name: "AngleOpen", pattern: />/ });
43088
43090
  AngleLess = createToken({ name: "AngleLess", pattern: /</ });
43091
+ AtSign = createToken({ name: "AtSign", pattern: /@/ });
43089
43092
  Pipe = createToken({ name: "Pipe", pattern: /\|/ });
43090
43093
  ForwardSlash = createToken({ name: "ForwardSlash", pattern: /\// });
43091
43094
  Backslash = createToken({ name: "Backslash", pattern: /\\/ });
@@ -43136,6 +43139,8 @@ var init_lexer2 = __esm({
43136
43139
  ClassDefKeyword,
43137
43140
  ClassKeyword,
43138
43141
  StyleKeyword,
43142
+ ClickKeyword,
43143
+ LinkStyleKeyword,
43139
43144
  Direction,
43140
43145
  // Special multi-char brackets before arrows (some contain > or -)
43141
43146
  DoubleSquareOpen,
@@ -43172,6 +43177,7 @@ var init_lexer2 = __esm({
43172
43177
  DiamondClose,
43173
43178
  AngleOpen,
43174
43179
  AngleLess,
43180
+ AtSign,
43175
43181
  ForwardSlash,
43176
43182
  Backslash,
43177
43183
  Pipe,
@@ -43228,9 +43234,12 @@ var init_parser2 = __esm({
43228
43234
  this.OR([
43229
43235
  { ALT: () => this.SUBRULE(this.nodeStatement) },
43230
43236
  { ALT: () => this.SUBRULE(this.subgraph) },
43237
+ { ALT: () => this.SUBRULE(this.directionStatement) },
43231
43238
  { ALT: () => this.SUBRULE(this.classStatement) },
43232
43239
  { ALT: () => this.SUBRULE(this.styleStatement) },
43233
43240
  { ALT: () => this.SUBRULE(this.classDefStatement) },
43241
+ { ALT: () => this.SUBRULE(this.clickStatement) },
43242
+ { ALT: () => this.SUBRULE(this.linkStyleStatement) },
43234
43243
  { ALT: () => this.CONSUME(Newline) }
43235
43244
  // Empty lines
43236
43245
  ]);
@@ -43266,6 +43275,7 @@ var init_parser2 = __esm({
43266
43275
  this.OPTION(() => {
43267
43276
  this.CONSUME(NumberLiteral, { LABEL: "nodeIdSuffix" });
43268
43277
  });
43278
+ this.OPTION1(() => this.SUBRULE(this.attrObject));
43269
43279
  }
43270
43280
  },
43271
43281
  {
@@ -43282,6 +43292,146 @@ var init_parser2 = __esm({
43282
43292
  this.CONSUME3(Identifier, { LABEL: "nodeClass" });
43283
43293
  });
43284
43294
  });
43295
+ this.attrObject = this.RULE("attrObject", () => {
43296
+ this.CONSUME(AtSign);
43297
+ this.CONSUME(DiamondOpen, { LABEL: "attrLCurly" });
43298
+ this.OPTION(() => {
43299
+ this.SUBRULE(this.attrPair);
43300
+ this.MANY(() => {
43301
+ this.CONSUME(Comma);
43302
+ this.SUBRULE2(this.attrPair);
43303
+ });
43304
+ });
43305
+ this.CONSUME(DiamondClose, { LABEL: "attrRCurly" });
43306
+ });
43307
+ this.attrPair = this.RULE("attrPair", () => {
43308
+ this.CONSUME(Identifier, { LABEL: "attrKey" });
43309
+ this.CONSUME(Colon);
43310
+ this.OR([
43311
+ {
43312
+ GATE: () => {
43313
+ const prev = this.LA(-1);
43314
+ const keyTok = this.LA(-2);
43315
+ return keyTok && /^(shape)$/i.test(String(keyTok.image || ""));
43316
+ },
43317
+ ALT: () => this.SUBRULE(this.attrShapeValue)
43318
+ },
43319
+ { ALT: () => this.CONSUME(QuotedString) },
43320
+ { ALT: () => this.CONSUME2(Identifier) },
43321
+ { ALT: () => this.CONSUME(NumberLiteral) },
43322
+ { ALT: () => this.CONSUME(Text) }
43323
+ ]);
43324
+ });
43325
+ this.attrShapeValue = this.RULE("attrShapeValue", () => {
43326
+ const isKnownShapeId = () => {
43327
+ const la = this.LA(1);
43328
+ if (!la || la.tokenType !== Identifier)
43329
+ return false;
43330
+ const v3 = String(la.image || "").toLowerCase();
43331
+ 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";
43332
+ };
43333
+ const isKnownShapeQuoted = () => {
43334
+ const la = this.LA(1);
43335
+ if (!la || la.tokenType !== QuotedString)
43336
+ return false;
43337
+ const raw = String(la.image || "");
43338
+ const unq = raw.length >= 2 && (raw.startsWith('"') || raw.startsWith("'")) ? raw.slice(1, -1) : raw;
43339
+ const v3 = unq.toLowerCase();
43340
+ 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";
43341
+ };
43342
+ this.OR([
43343
+ { GATE: isKnownShapeId, ALT: () => this.CONSUME(Identifier, { LABEL: "shapeId" }) },
43344
+ { GATE: isKnownShapeQuoted, ALT: () => this.CONSUME(QuotedString, { LABEL: "shapeQuoted" }) },
43345
+ // Fallback: accept any identifier/quoted/number/text so parse continues; semantics will flag unknowns
43346
+ { ALT: () => this.CONSUME2(Identifier) },
43347
+ { ALT: () => this.CONSUME2(QuotedString) },
43348
+ { ALT: () => this.CONSUME(NumberLiteral) },
43349
+ { ALT: () => this.CONSUME(Text) }
43350
+ ]);
43351
+ });
43352
+ this.clickStatement = this.RULE("clickStatement", () => {
43353
+ this.CONSUME(ClickKeyword);
43354
+ this.CONSUME(Identifier, { LABEL: "clickTarget" });
43355
+ this.OR([
43356
+ {
43357
+ GATE: () => this.LA(1).tokenType === Identifier && /^(href)$/i.test(this.LA(1).image || ""),
43358
+ ALT: () => this.SUBRULE(this.clickHref)
43359
+ },
43360
+ {
43361
+ GATE: () => this.LA(1).tokenType === Identifier && /^(call|callback)$/i.test(this.LA(1).image || ""),
43362
+ ALT: () => this.SUBRULE(this.clickCall)
43363
+ }
43364
+ ]);
43365
+ this.OPTION(() => this.CONSUME(Newline));
43366
+ });
43367
+ this.clickHref = this.RULE("clickHref", () => {
43368
+ this.CONSUME(Identifier, { LABEL: "mode" });
43369
+ this.CONSUME(QuotedString, { LABEL: "url" });
43370
+ this.OPTION(() => this.CONSUME2(QuotedString, { LABEL: "tooltip" }));
43371
+ this.OPTION2(() => this.CONSUME2(Identifier, { LABEL: "target" }));
43372
+ });
43373
+ this.clickCall = this.RULE("clickCall", () => {
43374
+ this.CONSUME1(Identifier, { LABEL: "mode" });
43375
+ this.OPTION1(() => {
43376
+ this.CONSUME2(Identifier, { LABEL: "fn" });
43377
+ this.OPTION2(() => {
43378
+ this.CONSUME3(RoundOpen);
43379
+ this.OPTION3(() => {
43380
+ this.OR([
43381
+ { ALT: () => this.CONSUME4(Identifier) },
43382
+ { ALT: () => this.CONSUME5(NumberLiteral) },
43383
+ { ALT: () => this.CONSUME6(Text) }
43384
+ ]);
43385
+ });
43386
+ this.CONSUME7(RoundClose);
43387
+ });
43388
+ });
43389
+ this.OPTION4(() => this.CONSUME8(QuotedString, { LABEL: "tooltip" }));
43390
+ });
43391
+ this.linkStyleStatement = this.RULE("linkStyleStatement", () => {
43392
+ this.CONSUME(LinkStyleKeyword);
43393
+ this.SUBRULE(this.linkStyleIndexList);
43394
+ this.OPTION1(() => this.CONSUME1(Newline));
43395
+ this.SUBRULE(this.linkStylePairs);
43396
+ this.OPTION2(() => this.CONSUME2(Newline));
43397
+ });
43398
+ this.linkStyleIndexList = this.RULE("linkStyleIndexList", () => {
43399
+ this.CONSUME(NumberLiteral, { LABEL: "index" });
43400
+ this.MANY(() => {
43401
+ this.CONSUME(Comma);
43402
+ this.CONSUME2(NumberLiteral, { LABEL: "index" });
43403
+ });
43404
+ });
43405
+ this.linkStylePairs = this.RULE("linkStylePairs", () => {
43406
+ this.SUBRULE(this.linkStylePair);
43407
+ this.MANY(() => {
43408
+ this.CONSUME(Comma);
43409
+ this.OPTION(() => this.CONSUME(Newline));
43410
+ this.SUBRULE2(this.linkStylePair);
43411
+ });
43412
+ });
43413
+ this.linkStylePair = this.RULE("linkStylePair", () => {
43414
+ this.CONSUME1(Identifier, { LABEL: "key" });
43415
+ this.CONSUME(Colon);
43416
+ this.SUBRULE(this.linkStyleValueChunk);
43417
+ });
43418
+ this.linkStyleValueChunk = this.RULE("linkStyleValueChunk", () => {
43419
+ this.AT_LEAST_ONE({
43420
+ GATE: () => {
43421
+ const la = this.LA(1);
43422
+ return la && la.tokenType !== Comma && la.tokenType !== Newline;
43423
+ },
43424
+ DEF: () => {
43425
+ this.OR([
43426
+ { ALT: () => this.CONSUME(ColorValue) },
43427
+ { ALT: () => this.CONSUME(QuotedString) },
43428
+ { ALT: () => this.CONSUME(NumberLiteral) },
43429
+ { ALT: () => this.CONSUME(Identifier) },
43430
+ { ALT: () => this.CONSUME(Text) }
43431
+ ]);
43432
+ }
43433
+ });
43434
+ });
43285
43435
  this.nodeShape = this.RULE("nodeShape", () => {
43286
43436
  this.OR([
43287
43437
  // Square brackets: [text]
@@ -43385,6 +43535,10 @@ var init_parser2 = __esm({
43385
43535
  ]);
43386
43536
  });
43387
43537
  this.link = this.RULE("link", () => {
43538
+ this.OPTION1(() => {
43539
+ this.CONSUME(Identifier, { LABEL: "edgeId" });
43540
+ this.CONSUME(AtSign);
43541
+ });
43388
43542
  this.OR([
43389
43543
  // Arrows with inline text (e.g., -.text.-> or ==text==>)
43390
43544
  {
@@ -43425,7 +43579,7 @@ var init_parser2 = __esm({
43425
43579
  { ALT: () => this.CONSUME(InvalidArrow) }
43426
43580
  // Capture for error
43427
43581
  ]);
43428
- this.OPTION(() => {
43582
+ this.OPTION2(() => {
43429
43583
  this.CONSUME(Pipe);
43430
43584
  this.SUBRULE(this.linkText);
43431
43585
  this.CONSUME2(Pipe);
@@ -43587,26 +43741,66 @@ var init_parser2 = __esm({
43587
43741
  // node_modules/@probelabs/maid/out/diagrams/flowchart/semantics.js
43588
43742
  function analyzeFlowchart(cst, _tokens, opts) {
43589
43743
  const ctx = { errors: [], strict: opts?.strict };
43590
- const v3 = new FlowSemanticsVisitor(ctx);
43744
+ const collector = new NodeIdCollector();
43745
+ collector.visit(cst);
43746
+ const v3 = new FlowSemanticsVisitor(ctx, collector.ids, collector.edgeIds);
43591
43747
  v3.visit(cst);
43592
43748
  return ctx.errors;
43593
43749
  }
43594
- var BaseVisitor, FlowSemanticsVisitor;
43750
+ var BaseVisitor, FlowSemanticsVisitor, NodeIdCollector;
43595
43751
  var init_semantics = __esm({
43596
43752
  "node_modules/@probelabs/maid/out/diagrams/flowchart/semantics.js"() {
43597
43753
  init_parser2();
43598
43754
  BaseVisitor = parserInstance.getBaseCstVisitorConstructorWithDefaults();
43599
43755
  FlowSemanticsVisitor = class extends BaseVisitor {
43600
- constructor(ctx) {
43756
+ constructor(ctx, knownIds, knownEdgeIds) {
43601
43757
  super();
43758
+ this.edgeCount = 0;
43602
43759
  this.validateVisitor();
43603
43760
  this.ctx = ctx;
43761
+ this.knownIds = knownIds;
43762
+ this.knownEdgeIds = knownEdgeIds;
43604
43763
  }
43605
43764
  // Entry point
43606
43765
  diagram(ctx) {
43607
43766
  if (ctx.statement)
43608
43767
  ctx.statement.forEach((s3) => this.visit(s3));
43609
43768
  }
43769
+ classStatement(ctx) {
43770
+ const ids = ctx.Identifier || [];
43771
+ const classNameTok = ctx.className && ctx.className[0];
43772
+ for (const idTok of ids) {
43773
+ if (classNameTok && idTok.startOffset === classNameTok.startOffset)
43774
+ continue;
43775
+ const id = String(idTok.image);
43776
+ if (!(this.knownIds.has(id) || this.knownEdgeIds.has(id))) {
43777
+ this.ctx.errors.push({
43778
+ line: idTok.startLine ?? 1,
43779
+ column: idTok.startColumn ?? 1,
43780
+ severity: "warning",
43781
+ code: "FL-CLASS-TARGET-UNKNOWN",
43782
+ message: `Unknown id '${id}' in class statement.`,
43783
+ hint: "Define the node/link before applying classes, or move the class line after it."
43784
+ });
43785
+ }
43786
+ }
43787
+ }
43788
+ styleStatement(ctx) {
43789
+ const idTok = ctx.Identifier && ctx.Identifier[0];
43790
+ if (idTok) {
43791
+ const id = String(idTok.image);
43792
+ if (!this.knownIds.has(id)) {
43793
+ this.ctx.errors.push({
43794
+ line: idTok.startLine ?? 1,
43795
+ column: idTok.startColumn ?? 1,
43796
+ severity: "warning",
43797
+ code: "FL-STYLE-TARGET-UNKNOWN",
43798
+ message: `Unknown node id '${id}' in style statement.`,
43799
+ hint: "Define the node before styling it, or move the style line after the node definition."
43800
+ });
43801
+ }
43802
+ }
43803
+ }
43610
43804
  statement(ctx) {
43611
43805
  for (const k3 of Object.keys(ctx)) {
43612
43806
  const arr = ctx[k3];
@@ -43618,6 +43812,141 @@ var init_semantics = __esm({
43618
43812
  }
43619
43813
  }
43620
43814
  }
43815
+ clickStatement(ctx) {
43816
+ const href = ctx.clickHref?.[0];
43817
+ const call = !href ? ctx.clickCall?.[0] : void 0;
43818
+ if (href) {
43819
+ const ch = href.children || {};
43820
+ const modeTok2 = ch.mode?.[0];
43821
+ const urlTok = ch.url?.[0];
43822
+ const tipTok = ch.tooltip?.[0];
43823
+ const tgtTok = ch.target?.[0];
43824
+ const mode2 = String(modeTok2?.image || "").toLowerCase();
43825
+ if (mode2 !== "href") {
43826
+ 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()' });
43827
+ return;
43828
+ }
43829
+ if (!urlTok) {
43830
+ 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' });
43831
+ }
43832
+ if (tgtTok && !/^_(blank|self|parent|top)$/i.test(String(tgtTok.image || ""))) {
43833
+ 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" });
43834
+ }
43835
+ return;
43836
+ }
43837
+ if (call) {
43838
+ const ch = call.children || {};
43839
+ const modeTok2 = ch.mode?.[0];
43840
+ const mode2 = String(modeTok2?.image || "").toLowerCase();
43841
+ if (!(mode2 === "call" || mode2 === "callback")) {
43842
+ 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()' });
43843
+ return;
43844
+ }
43845
+ const fnTok = ch.fn?.[0];
43846
+ if (!fnTok) {
43847
+ 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"' });
43848
+ }
43849
+ const tipTok = ch.tooltip?.[0];
43850
+ if (tipTok) {
43851
+ 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()" });
43852
+ }
43853
+ return;
43854
+ }
43855
+ const ids = ctx.Identifier || [];
43856
+ const q3 = ctx.QuotedString || [];
43857
+ const t0 = ids[0];
43858
+ const modeTok = ids[1];
43859
+ const mode = (modeTok?.image || "").toLowerCase();
43860
+ if (!mode) {
43861
+ this.ctx.errors.push({
43862
+ line: t0?.startLine ?? 1,
43863
+ column: t0?.startColumn ?? 1,
43864
+ severity: "error",
43865
+ code: "FL-CLICK-MODE-MISSING",
43866
+ message: "After 'click <id>' specify 'href' or 'call'.",
43867
+ hint: 'Examples: click A href "https://\u2026" "Tip" _blank | click A call doThing() "Tip"'
43868
+ });
43869
+ return;
43870
+ }
43871
+ if (mode === "href") {
43872
+ if (q3.length < 1) {
43873
+ this.ctx.errors.push({
43874
+ line: modeTok.startLine ?? 1,
43875
+ column: modeTok.startColumn ?? 1,
43876
+ severity: "error",
43877
+ code: "FL-CLICK-HREF-URL-MISSING",
43878
+ message: "'click \u2026 href' requires a quoted URL.",
43879
+ hint: 'Example: click A href "https://example.com" "Open" _blank'
43880
+ });
43881
+ }
43882
+ const tgt = ids[2];
43883
+ if (tgt && !/^_(blank|self|parent|top)$/i.test(tgt.image || "")) {
43884
+ this.ctx.errors.push({
43885
+ line: tgt.startLine ?? 1,
43886
+ column: tgt.startColumn ?? 1,
43887
+ severity: "warning",
43888
+ code: "FL-CLICK-TARGET-UNKNOWN",
43889
+ message: `Unknown target '${tgt.image}'. Use _blank/_self/_parent/_top.`,
43890
+ hint: "Example: \u2026 _blank"
43891
+ });
43892
+ }
43893
+ return;
43894
+ }
43895
+ if (mode === "call" || mode === "callback") {
43896
+ const fnTok = ids[2];
43897
+ if (!fnTok) {
43898
+ this.ctx.errors.push({
43899
+ line: modeTok.startLine ?? 1,
43900
+ column: modeTok.startColumn ?? 1,
43901
+ severity: "error",
43902
+ code: "FL-CLICK-CALL-NAME-MISSING",
43903
+ message: "'click \u2026 call' requires a function name.",
43904
+ hint: 'Example: click A call doThing() "Tooltip"'
43905
+ });
43906
+ }
43907
+ return;
43908
+ }
43909
+ this.ctx.errors.push({
43910
+ line: modeTok.startLine ?? 1,
43911
+ column: modeTok.startColumn ?? 1,
43912
+ severity: "error",
43913
+ code: "FL-CLICK-MODE-INVALID",
43914
+ message: `Unknown click mode '${modeTok.image}'. Use 'href' or 'call'.`,
43915
+ hint: 'Examples: href "\u2026" | call fn()'
43916
+ });
43917
+ }
43918
+ linkStyleStatement(ctx) {
43919
+ const idxNode = ctx.linkStyleIndexList?.[0];
43920
+ const pairNode = ctx.linkStylePairs?.[0];
43921
+ const getTokens = (node, name14) => node ? (node.children || {})[name14] || [] : [];
43922
+ const idxToks = getTokens(idxNode, "index");
43923
+ const nums = idxToks.map((t3) => parseInt(t3.image, 10)).filter((n3) => Number.isFinite(n3));
43924
+ if (nums.length === 0) {
43925
+ const anyTok = ctx.LinkStyleKeyword?.[0] || idxToks[0];
43926
+ 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" });
43927
+ return;
43928
+ }
43929
+ const pairChildren = pairNode?.children || {};
43930
+ const pairCount = (pairChildren.linkStylePair || []).length;
43931
+ if (!pairCount) {
43932
+ const firstNum = idxToks[0];
43933
+ 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" });
43934
+ }
43935
+ const seen = /* @__PURE__ */ new Set();
43936
+ for (const n3 of nums) {
43937
+ if (seen.has(n3)) {
43938
+ const numTok = idxToks.find((t3) => parseInt(t3.image, 10) === n3);
43939
+ 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." });
43940
+ }
43941
+ seen.add(n3);
43942
+ }
43943
+ for (const n3 of nums) {
43944
+ if (!(n3 >= 0 && n3 < this.edgeCount)) {
43945
+ const numTok = idxToks.find((t3) => parseInt(t3.image, 10) === n3);
43946
+ 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.` });
43947
+ }
43948
+ }
43949
+ }
43621
43950
  subgraph(ctx) {
43622
43951
  if (ctx.subgraphStatement)
43623
43952
  ctx.subgraphStatement.forEach((s3) => this.visit(s3));
@@ -43650,14 +43979,109 @@ var init_semantics = __esm({
43650
43979
  nodeStatement(ctx) {
43651
43980
  if (ctx.nodeOrParallelGroup)
43652
43981
  ctx.nodeOrParallelGroup.forEach((n3) => this.visit(n3));
43653
- }
43982
+ const linksHere = Array.isArray(ctx.link) ? ctx.link.length : 0;
43983
+ if (linksHere > 0)
43984
+ this.edgeCount += linksHere;
43985
+ }
43986
+ // Edge attribute object statements must target a known edge id
43987
+ // Edge attribute statements are parsed as nodeStatements with a typed attrObject and no links.
43988
+ // If such a line targets a known edge id, treat it as edge-attr at build time; otherwise keep as a node.
43989
+ // 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).
43990
+ // We keep this heuristic conservative to avoid false positives on typed node shapes.
43991
+ // (Validation that applies the attributes happens in the builder.)
43654
43992
  nodeOrParallelGroup(ctx) {
43655
43993
  if (ctx.node)
43656
43994
  ctx.node.forEach((n3) => this.visit(n3));
43657
43995
  }
43658
43996
  node(ctx) {
43997
+ const hasAttr = Array.isArray(ctx.attrObject) && ctx.attrObject.length > 0;
43998
+ const hasShape = Array.isArray(ctx.nodeShape) && ctx.nodeShape.length > 0;
43999
+ if (hasAttr && hasShape) {
44000
+ const tokArr = ctx.attrObject?.[0]?.children?.attrLCurly || [];
44001
+ const tok = tokArr[0];
44002
+ this.ctx.errors.push({
44003
+ line: tok?.startLine ?? 1,
44004
+ column: tok?.startColumn ?? 1,
44005
+ severity: "warning",
44006
+ code: "FL-TYPED-SHAPE-CONFLICT",
44007
+ message: "Both bracket shape and '@{ shape: \u2026 }' provided. Bracket shape will be used.",
44008
+ hint: 'Pick one style: either A[Label] or A@{ shape: rect, label: "Label" }'
44009
+ });
44010
+ }
43659
44011
  if (ctx.nodeShape)
43660
44012
  ctx.nodeShape.forEach((n3) => this.visit(n3));
44013
+ if (hasAttr) {
44014
+ const attr = ctx.attrObject?.[0];
44015
+ const pairs = attr?.children?.attrPair || [];
44016
+ const validKeys = /* @__PURE__ */ new Set(["shape", "label", "padding", "cornerRadius", "icon", "image"]);
44017
+ const shapes = /* @__PURE__ */ new Set(["rect", "round", "rounded", "stadium", "subroutine", "circle", "cylinder", "diamond", "trapezoid", "trapezoidAlt", "parallelogram", "hexagon", "lean-l", "lean-r", "icon", "image"]);
44018
+ for (const p3 of pairs) {
44019
+ const keyTok = p3.children?.attrKey?.[0];
44020
+ const valTok = p3.children?.QuotedString?.[0] || p3.children?.Identifier?.[0] || p3.children?.NumberLiteral?.[0] || p3.children?.Text?.[0];
44021
+ if (!keyTok)
44022
+ continue;
44023
+ const key = keyTok.image;
44024
+ if (!validKeys.has(key)) {
44025
+ this.ctx.errors.push({
44026
+ line: keyTok.startLine ?? 1,
44027
+ column: keyTok.startColumn ?? 1,
44028
+ severity: "warning",
44029
+ code: "FL-TYPED-KEY-UNKNOWN",
44030
+ message: `Unknown typed-shape key '${key}'.`,
44031
+ hint: "Allowed keys: shape, label, padding, cornerRadius, icon, image"
44032
+ });
44033
+ continue;
44034
+ }
44035
+ if (key === "shape" && valTok) {
44036
+ const v3 = String(valTok.image).replace(/^"|"$/g, "");
44037
+ if (!shapes.has(v3)) {
44038
+ this.ctx.errors.push({
44039
+ line: valTok.startLine ?? 1,
44040
+ column: valTok.startColumn ?? 1,
44041
+ severity: "error",
44042
+ code: "FL-TYPED-SHAPE-UNKNOWN",
44043
+ message: `Unknown shape '${v3}' in '@{ shape: \u2026 }'.`,
44044
+ hint: "Use one of: rect, round, stadium, subroutine, circle, cylinder, diamond, trapezoid, parallelogram, hexagon, lean-l, lean-r, icon, image"
44045
+ });
44046
+ } else {
44047
+ const supportedByCli = /* @__PURE__ */ new Set(["rect", "round", "rounded", "diamond", "circle", "cylinder", "stadium", "subroutine", "lean-l", "lean-r"]);
44048
+ if (!supportedByCli.has(v3)) {
44049
+ this.ctx.errors.push({
44050
+ line: valTok.startLine ?? 1,
44051
+ column: valTok.startColumn ?? 1,
44052
+ severity: "error",
44053
+ code: "FL-TYPED-SHAPE-UNSUPPORTED",
44054
+ message: `Typed shape '${v3}' is not supported by current Mermaid CLI.`,
44055
+ hint: 'Use one of: rect, rounded, diamond, circle, cylinder, stadium, subroutine, "lean-l", "lean-r"'
44056
+ });
44057
+ }
44058
+ }
44059
+ }
44060
+ if (key === "label" && valTok && valTok.tokenType?.name !== "QuotedString") {
44061
+ this.ctx.errors.push({
44062
+ line: valTok.startLine ?? 1,
44063
+ column: valTok.startColumn ?? 1,
44064
+ severity: "warning",
44065
+ code: "FL-TYPED-LABEL-NOT-STRING",
44066
+ message: "Typed-shape 'label' should be a quoted string.",
44067
+ hint: 'Example: A@{ shape: rect, label: "Start" }'
44068
+ });
44069
+ }
44070
+ if ((key === "padding" || key === "cornerRadius") && valTok) {
44071
+ const raw = String(valTok.image).replace(/^"|"$/g, "");
44072
+ if (!/^\d+(px)?$/.test(raw)) {
44073
+ this.ctx.errors.push({
44074
+ line: valTok.startLine ?? 1,
44075
+ column: valTok.startColumn ?? 1,
44076
+ severity: "warning",
44077
+ code: "FL-TYPED-NUMERIC-EXPECTED",
44078
+ message: `'${key}' expects a number (optionally with px).`,
44079
+ hint: `Use: ${key}: 8 or ${key}: "8px"`
44080
+ });
44081
+ }
44082
+ }
44083
+ }
44084
+ }
43661
44085
  }
43662
44086
  checkEmptyContent(openTok, contentNodes) {
43663
44087
  if (!contentNodes || contentNodes.length === 0) {
@@ -43793,6 +44217,7 @@ var init_semantics = __esm({
43793
44217
  if (openTok) {
43794
44218
  this.checkEmptyContent(openTok, contentNodes.length ? contentNodes : void 0);
43795
44219
  this.checkDoubleInSingleQuoted(contentNodes);
44220
+ this.checkBackticksInContent(contentNodes);
43796
44221
  this.warnParensInUnquoted(contentNodes);
43797
44222
  if (this.ctx.strict) {
43798
44223
  let quoted = false;
@@ -43821,6 +44246,93 @@ var init_semantics = __esm({
43821
44246
  }
43822
44247
  }
43823
44248
  }
44249
+ checkBackticksInContent(contentNodes) {
44250
+ if (!contentNodes)
44251
+ return;
44252
+ for (const cn of contentNodes) {
44253
+ const ch = cn.children || {};
44254
+ const inspectTok = (tk) => {
44255
+ if (!tk)
44256
+ return false;
44257
+ const img = String(tk.image || "");
44258
+ const idx = img.indexOf("`");
44259
+ if (idx >= 0) {
44260
+ const col = (tk.startColumn ?? 1) + idx;
44261
+ this.ctx.errors.push({
44262
+ line: tk.startLine ?? 1,
44263
+ column: col,
44264
+ severity: "warning",
44265
+ code: "FL-LABEL-BACKTICK",
44266
+ message: "Backticks (`\u2026`) inside node labels are not supported by Mermaid.",
44267
+ hint: 'Remove the backticks or use quotes instead, e.g., "GITHUB_ACTIONS" and "--cli".',
44268
+ length: 1
44269
+ });
44270
+ return true;
44271
+ }
44272
+ return false;
44273
+ };
44274
+ const texts = ch.Text || [];
44275
+ for (const tk of texts) {
44276
+ if (inspectTok(tk))
44277
+ return;
44278
+ }
44279
+ const qs = ch.QuotedString || [];
44280
+ for (const tk of qs) {
44281
+ if (inspectTok(tk))
44282
+ return;
44283
+ }
44284
+ }
44285
+ }
44286
+ };
44287
+ NodeIdCollector = class extends BaseVisitor {
44288
+ constructor() {
44289
+ super();
44290
+ this.ids = /* @__PURE__ */ new Set();
44291
+ this.edgeIds = /* @__PURE__ */ new Set();
44292
+ this.validateVisitor();
44293
+ }
44294
+ node(ctx) {
44295
+ const idTok = ctx.nodeId && ctx.nodeId[0];
44296
+ const idNumTok = ctx.nodeIdNum && ctx.nodeIdNum[0];
44297
+ if (idTok)
44298
+ this.ids.add(String(idTok.image));
44299
+ else if (idNumTok)
44300
+ this.ids.add(String(idNumTok.image));
44301
+ }
44302
+ link(ctx) {
44303
+ const t3 = ctx.edgeId?.[0];
44304
+ if (t3)
44305
+ this.edgeIds.add(String(t3.image));
44306
+ }
44307
+ nodeOrParallelGroup(ctx) {
44308
+ if (ctx.node)
44309
+ ctx.node.forEach((n3) => this.visit(n3));
44310
+ }
44311
+ nodeStatement(ctx) {
44312
+ if (ctx.nodeOrParallelGroup)
44313
+ ctx.nodeOrParallelGroup.forEach((n3) => this.visit(n3));
44314
+ if (ctx.link)
44315
+ ctx.link.forEach((ln) => this.visit(ln));
44316
+ }
44317
+ edgeAttrStatement(ctx) {
44318
+ const t3 = ctx.edgeId?.[0];
44319
+ if (t3)
44320
+ this.edgeIds.add(String(t3.image));
44321
+ }
44322
+ statement(ctx) {
44323
+ for (const k3 of Object.keys(ctx)) {
44324
+ const arr = ctx[k3];
44325
+ if (Array.isArray(arr))
44326
+ arr.forEach((n3) => {
44327
+ if (n3 && typeof n3.name === "string")
44328
+ this.visit(n3);
44329
+ });
44330
+ }
44331
+ }
44332
+ diagram(ctx) {
44333
+ if (ctx.statement)
44334
+ ctx.statement.forEach((s3) => this.visit(s3));
44335
+ }
43824
44336
  };
43825
44337
  }
43826
44338
  });
@@ -43858,11 +44370,29 @@ function detectDoubleInDouble(tokens, opts) {
43858
44370
  byLine.get(ln).push(tk);
43859
44371
  }
43860
44372
  const ends = new Set(opts.scopeEndTokenNames || []);
44373
+ const starts = new Set(opts.scopeStartTokenNames || []);
43861
44374
  for (const [ln, arr] of byLine) {
43862
44375
  for (let i3 = 0; i3 < arr.length; i3++) {
43863
44376
  const t3 = arr[i3];
43864
44377
  if (t3.tokenType?.name !== "QuotedString")
43865
44378
  continue;
44379
+ if (starts.size > 0) {
44380
+ let startIdx = -1;
44381
+ for (let k3 = i3 - 1; k3 >= 0; k3--) {
44382
+ const s3 = arr[k3];
44383
+ if (starts.has(s3.tokenType?.name || "")) {
44384
+ startIdx = k3;
44385
+ break;
44386
+ }
44387
+ }
44388
+ if (startIdx === -1)
44389
+ continue;
44390
+ const sTok = arr[startIdx];
44391
+ const prevTok = arr[startIdx - 1];
44392
+ if (sTok.tokenType?.name === "DiamondOpen" && prevTok?.tokenType?.name === "AtSign") {
44393
+ continue;
44394
+ }
44395
+ }
43866
44396
  for (let j3 = i3 + 1; j3 < arr.length; j3++) {
43867
44397
  const u3 = arr[j3];
43868
44398
  if (ends.size > 0 && ends.has(u3.tokenType?.name || ""))
@@ -44030,8 +44560,9 @@ function mapFlowchartParserError(err, text) {
44030
44560
  length: len
44031
44561
  };
44032
44562
  }
44033
- if (isInRule(err, "nodeStatement") && err.name === "NoViableAltException") {
44034
- if ((err.message || "").includes("[Newline") && (err.message || "").includes("[EOF")) {
44563
+ if (err.name === "NoViableAltException" || err.name === "MismatchedTokenException") {
44564
+ const msg = err.message || "";
44565
+ if (tokType === "Identifier" && msg.includes("Newline") && msg.includes("EOF")) {
44035
44566
  return {
44036
44567
  line,
44037
44568
  column,
@@ -44639,11 +45170,11 @@ function mapStateParserError(err, text) {
44639
45170
  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 };
44640
45171
  }
44641
45172
  if (isInRule(err, "stateBlock") && err.name === "MismatchedTokenException" && expecting(err, "RCurly")) {
44642
- if (/---/.test(ltxt)) {
44643
- 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 };
44644
- }
44645
45173
  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 };
44646
45174
  }
45175
+ if ((err.name === "NoViableAltException" || err.name === "MismatchedTokenException") && tokType === "Dashes" && !isInRule(err, "innerStatement")) {
45176
+ 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 };
45177
+ }
44647
45178
  const dblEsc = (ltxt.match(/\\\"/g) || []).length;
44648
45179
  const dq = (ltxt.match(/\"/g) || []).length - dblEsc;
44649
45180
  if (dq >= 3) {
@@ -44749,9 +45280,60 @@ function validateFlowchart(text, options = {}) {
44749
45280
  "StadiumClose",
44750
45281
  "CylinderClose",
44751
45282
  "HexagonClose"
45283
+ ],
45284
+ scopeStartTokenNames: [
45285
+ "SquareOpen",
45286
+ "RoundOpen",
45287
+ "DiamondOpen",
45288
+ "DoubleSquareOpen",
45289
+ "DoubleRoundOpen",
45290
+ "StadiumOpen",
45291
+ "CylinderOpen",
45292
+ "HexagonOpen"
44752
45293
  ]
44753
45294
  }).filter((e3) => !seenDoubleLines.has(e3.line) && !escapedLinesAll.has(e3.line));
44754
45295
  const errs = escWarn.concat(dbl);
45296
+ const generic = (prevErrors || []).filter((e3) => e3.severity === "error" && !("code" in e3) && typeof e3.message === "string");
45297
+ for (const ge of generic) {
45298
+ const msg = String(ge.message || "");
45299
+ if (msg.includes("Newline") && msg.includes("EOF")) {
45300
+ errs.push({
45301
+ line: ge.line ?? 1,
45302
+ column: ge.column ?? 1,
45303
+ severity: "error",
45304
+ code: "FL-LINK-MISSING",
45305
+ message: "Two nodes on one line must be connected with an arrow.",
45306
+ hint: "Insert --> between nodes, e.g., A --> B."
45307
+ });
45308
+ }
45309
+ }
45310
+ {
45311
+ const lines = text2.split(/\r?\n/);
45312
+ const nodeRef = String.raw`[A-Za-z0-9_]+(?:\[[^\]]*\]|\([^\)]*\)|\{[^}]*\}|\[\[[^\]]*\]\]|\(\([^\)]*\)\))?`;
45313
+ const re = new RegExp(String.raw`^\s*(${nodeRef})\s+(${nodeRef})\s*;?\s*$`);
45314
+ const skipStart = /^(?:\s*)(style|classDef|class|click|linkStyle|subgraph|end|graph|flowchart|direction)\b/;
45315
+ for (let i3 = 0; i3 < lines.length; i3++) {
45316
+ const raw = lines[i3] || "";
45317
+ const ln = i3 + 1;
45318
+ if (!raw.trim())
45319
+ continue;
45320
+ if (skipStart.test(raw))
45321
+ continue;
45322
+ const m3 = re.exec(raw);
45323
+ if (m3) {
45324
+ const idxSecond = raw.indexOf(m3[2]);
45325
+ const col = idxSecond >= 0 ? idxSecond + 1 : 1;
45326
+ errs.push({
45327
+ line: ln,
45328
+ column: col,
45329
+ severity: "error",
45330
+ code: "FL-LINK-MISSING",
45331
+ message: "Two nodes on one line must be connected with an arrow.",
45332
+ hint: "Insert --> between nodes, e.g., A --> B."
45333
+ });
45334
+ }
45335
+ }
45336
+ }
44755
45337
  const dblEsc = (text2.match(/\\\"/g) || []).length;
44756
45338
  const dq = (text2.match(/\"/g) || []).length - dblEsc;
44757
45339
  const sq = (text2.match(/'/g) || []).length;
@@ -44957,7 +45539,7 @@ var init_validate2 = __esm({
44957
45539
  function tokenize3(text) {
44958
45540
  return SequenceLexer.tokenize(text);
44959
45541
  }
44960
- 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;
45542
+ 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;
44961
45543
  var init_lexer4 = __esm({
44962
45544
  "node_modules/@probelabs/maid/out/diagrams/sequence/lexer.js"() {
44963
45545
  init_api5();
@@ -44974,6 +45556,9 @@ var init_lexer4 = __esm({
44974
45556
  RightKeyword = createToken({ name: "RightKeyword", pattern: /right/i, longer_alt: Identifier2 });
44975
45557
  OverKeyword = createToken({ name: "OverKeyword", pattern: /over/i, longer_alt: Identifier2 });
44976
45558
  OfKeyword = createToken({ name: "OfKeyword", pattern: /of/i, longer_alt: Identifier2 });
45559
+ TitleKeyword2 = createToken({ name: "TitleKeyword", pattern: /title/i, longer_alt: Identifier2 });
45560
+ AccTitleKeyword = createToken({ name: "AccTitleKeyword", pattern: /acc_title|accTitle/i, longer_alt: Identifier2 });
45561
+ AccDescrKeyword = createToken({ name: "AccDescrKeyword", pattern: /acc_descr|accDescr/i, longer_alt: Identifier2 });
44977
45562
  ActivateKeyword = createToken({ name: "ActivateKeyword", pattern: /activate/i, longer_alt: Identifier2 });
44978
45563
  DeactivateKeyword = createToken({ name: "DeactivateKeyword", pattern: /deactivate/i, longer_alt: Identifier2 });
44979
45564
  CreateKeyword = createToken({ name: "CreateKeyword", pattern: /create/i, longer_alt: Identifier2 });
@@ -44991,6 +45576,8 @@ var init_lexer4 = __esm({
44991
45576
  EndKeyword2 = createToken({ name: "EndKeyword", pattern: /end/i, longer_alt: Identifier2 });
44992
45577
  LinksKeyword = createToken({ name: "LinksKeyword", pattern: /links/i, longer_alt: Identifier2 });
44993
45578
  LinkKeyword = createToken({ name: "LinkKeyword", pattern: /link/i, longer_alt: Identifier2 });
45579
+ PropertiesKeyword = createToken({ name: "PropertiesKeyword", pattern: /properties/i, longer_alt: Identifier2 });
45580
+ DetailsKeyword = createToken({ name: "DetailsKeyword", pattern: /details/i, longer_alt: Identifier2 });
44994
45581
  BreakKeyword = createToken({ name: "BreakKeyword", pattern: /break/i, longer_alt: Identifier2 });
44995
45582
  BidirAsyncDotted = createToken({ name: "BidirAsyncDotted", pattern: /<<-->>/ });
44996
45583
  BidirAsync = createToken({ name: "BidirAsync", pattern: /<<->>/ });
@@ -45023,6 +45610,9 @@ var init_lexer4 = __esm({
45023
45610
  Newline3,
45024
45611
  // Header/Keywords
45025
45612
  SequenceKeyword,
45613
+ TitleKeyword2,
45614
+ AccTitleKeyword,
45615
+ AccDescrKeyword,
45026
45616
  ParticipantKeyword,
45027
45617
  ActorKeyword,
45028
45618
  AsKeyword,
@@ -45051,6 +45641,8 @@ var init_lexer4 = __esm({
45051
45641
  EndKeyword2,
45052
45642
  LinksKeyword,
45053
45643
  LinkKeyword,
45644
+ PropertiesKeyword,
45645
+ DetailsKeyword,
45054
45646
  // Arrows
45055
45647
  BidirAsyncDotted,
45056
45648
  BidirAsync,
@@ -45102,6 +45694,7 @@ var init_parser4 = __esm({
45102
45694
  });
45103
45695
  this.line = this.RULE("line", () => {
45104
45696
  this.OR([
45697
+ { ALT: () => this.SUBRULE(this.metaStmt) },
45105
45698
  { ALT: () => this.SUBRULE(this.participantDecl) },
45106
45699
  { ALT: () => this.SUBRULE(this.autonumberStmt) },
45107
45700
  { ALT: () => this.SUBRULE(this.noteStmt) },
@@ -45110,6 +45703,8 @@ var init_parser4 = __esm({
45110
45703
  { ALT: () => this.SUBRULE(this.createStmt) },
45111
45704
  { ALT: () => this.SUBRULE(this.destroyStmt) },
45112
45705
  { ALT: () => this.SUBRULE(this.linkStmt) },
45706
+ { ALT: () => this.SUBRULE(this.propertiesStmt) },
45707
+ { ALT: () => this.SUBRULE(this.detailsStmt) },
45113
45708
  { ALT: () => this.SUBRULE(this.altBlock) },
45114
45709
  { ALT: () => this.SUBRULE(this.optBlock) },
45115
45710
  { ALT: () => this.SUBRULE(this.loopBlock) },
@@ -45122,6 +45717,18 @@ var init_parser4 = __esm({
45122
45717
  { ALT: () => this.SUBRULE(this.blankLine) }
45123
45718
  ]);
45124
45719
  });
45720
+ this.metaStmt = this.RULE("metaStmt", () => {
45721
+ this.OR([
45722
+ { ALT: () => this.CONSUME(TitleKeyword2) },
45723
+ { ALT: () => this.CONSUME(AccTitleKeyword) },
45724
+ { ALT: () => this.CONSUME(AccDescrKeyword) }
45725
+ ]);
45726
+ this.OPTION(() => this.SUBRULE(this.lineRemainder));
45727
+ this.OR2([
45728
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45729
+ { ALT: () => this.CONSUME(EOF) }
45730
+ ]);
45731
+ });
45125
45732
  this.blankLine = this.RULE("blankLine", () => {
45126
45733
  this.AT_LEAST_ONE(() => this.CONSUME(Newline3));
45127
45734
  });
@@ -45250,6 +45857,24 @@ var init_parser4 = __esm({
45250
45857
  { ALT: () => this.CONSUME(EOF) }
45251
45858
  ]);
45252
45859
  });
45860
+ this.propertiesStmt = this.RULE("propertiesStmt", () => {
45861
+ this.CONSUME(PropertiesKeyword);
45862
+ this.OPTION(() => this.CONSUME(Colon3));
45863
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45864
+ this.OR2([
45865
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45866
+ { ALT: () => this.CONSUME(EOF) }
45867
+ ]);
45868
+ });
45869
+ this.detailsStmt = this.RULE("detailsStmt", () => {
45870
+ this.CONSUME(DetailsKeyword);
45871
+ this.OPTION(() => this.CONSUME(Colon3));
45872
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45873
+ this.OR2([
45874
+ { ALT: () => this.AT_LEAST_ONE(() => this.CONSUME(Newline3)) },
45875
+ { ALT: () => this.CONSUME(EOF) }
45876
+ ]);
45877
+ });
45253
45878
  this.messageStmt = this.RULE("messageStmt", () => {
45254
45879
  this.SUBRULE(this.actorRef);
45255
45880
  this.SUBRULE(this.arrow);
@@ -45320,7 +45945,7 @@ var init_parser4 = __esm({
45320
45945
  });
45321
45946
  this.parBlock = this.RULE("parBlock", () => {
45322
45947
  this.CONSUME(ParKeyword);
45323
- this.OPTION(() => this.SUBRULE(this.lineRemainder));
45948
+ this.OPTION(() => this.SUBRULE(this.parHeader));
45324
45949
  this.AT_LEAST_ONE(() => this.CONSUME(Newline3));
45325
45950
  this.MANY(() => this.SUBRULE(this.line));
45326
45951
  this.MANY2(() => {
@@ -45335,6 +45960,23 @@ var init_parser4 = __esm({
45335
45960
  { ALT: () => this.CONSUME3(EOF) }
45336
45961
  ]);
45337
45962
  });
45963
+ this.parHeader = this.RULE("parHeader", () => {
45964
+ this.OR([
45965
+ {
45966
+ GATE: () => this.LA(1).tokenType === OverKeyword,
45967
+ ALT: () => {
45968
+ this.CONSUME(OverKeyword);
45969
+ this.SUBRULE(this.actorRef);
45970
+ this.OPTION(() => {
45971
+ this.CONSUME(Comma2);
45972
+ this.SUBRULE2(this.actorRef);
45973
+ });
45974
+ this.OPTION1(() => this.SUBRULE(this.lineRemainder));
45975
+ }
45976
+ },
45977
+ { ALT: () => this.SUBRULE2(this.lineRemainder) }
45978
+ ]);
45979
+ });
45338
45980
  this.criticalBlock = this.RULE("criticalBlock", () => {
45339
45981
  this.CONSUME(CriticalKeyword);
45340
45982
  this.OPTION(() => this.SUBRULE(this.lineRemainder));
@@ -45409,6 +46051,9 @@ var init_parser4 = __esm({
45409
46051
  { ALT: () => this.CONSUME(BreakKeyword) },
45410
46052
  { ALT: () => this.CONSUME(BoxKeyword) },
45411
46053
  { ALT: () => this.CONSUME(EndKeyword2) },
46054
+ { ALT: () => this.CONSUME(TitleKeyword2) },
46055
+ { ALT: () => this.CONSUME(AccTitleKeyword) },
46056
+ { ALT: () => this.CONSUME(AccDescrKeyword) },
45412
46057
  { ALT: () => this.CONSUME(NoteKeyword) },
45413
46058
  { ALT: () => this.CONSUME(LeftKeyword) },
45414
46059
  { ALT: () => this.CONSUME(RightKeyword) },
@@ -45437,27 +46082,201 @@ var init_parser4 = __esm({
45437
46082
  function analyzeSequence(_cst, _tokens) {
45438
46083
  const ctx = { tokens: _tokens };
45439
46084
  const v3 = new SequenceSemanticsVisitor(ctx);
45440
- return [];
45441
- }
45442
- var BaseVisitor3, SequenceSemanticsVisitor;
45443
- var init_semantics3 = __esm({
45444
- "node_modules/@probelabs/maid/out/diagrams/sequence/semantics.js"() {
45445
- init_parser4();
45446
- BaseVisitor3 = parserInstance3.getBaseCstVisitorConstructorWithDefaults();
45447
- SequenceSemanticsVisitor = class extends BaseVisitor3 {
45448
- constructor(ctx) {
45449
- super();
45450
- this.ctx = ctx;
45451
- this.validateVisitor();
45452
- }
45453
- };
45454
- }
45455
- });
45456
-
45457
- // node_modules/@probelabs/maid/out/diagrams/sequence/validate.js
45458
- function validateSequence(text, options = {}) {
45459
- return lintWithChevrotain(text, {
45460
- tokenize: tokenize3,
46085
+ const errs = [];
46086
+ const firstByLine = /* @__PURE__ */ new Map();
46087
+ for (const tk of _tokens) {
46088
+ const ln = tk.startLine ?? 1;
46089
+ const col = tk.startColumn ?? 1;
46090
+ const prev = firstByLine.get(ln);
46091
+ if (!prev || (prev.startColumn ?? Infinity) > col)
46092
+ firstByLine.set(ln, tk);
46093
+ }
46094
+ for (const tok of _tokens) {
46095
+ if (tok.tokenType === TitleKeyword2 || tok.tokenType === AccTitleKeyword || tok.tokenType === AccDescrKeyword) {
46096
+ const isLineStart = firstByLine.get(tok.startLine ?? 1) === tok;
46097
+ if (isLineStart)
46098
+ errs.push({
46099
+ line: tok.startLine ?? 1,
46100
+ column: tok.startColumn ?? 1,
46101
+ severity: "error",
46102
+ code: "SE-META-UNSUPPORTED",
46103
+ message: "Title/accTitle/accDescr are not accepted by current Mermaid CLI for sequence diagrams.",
46104
+ hint: "Remove this line (e.g., 'title \u2026') to match mermaid-cli.",
46105
+ length: tok.image?.length ?? 5
46106
+ });
46107
+ }
46108
+ if (tok.tokenType === PropertiesKeyword && firstByLine.get(tok.startLine ?? 1) === tok) {
46109
+ errs.push({
46110
+ line: tok.startLine ?? 1,
46111
+ column: tok.startColumn ?? 1,
46112
+ severity: "error",
46113
+ code: "SE-PROPERTIES-UNSUPPORTED",
46114
+ message: "'properties' is not accepted by current Mermaid CLI for sequence diagrams.",
46115
+ hint: "Remove the 'properties:' line to match mermaid-cli.",
46116
+ length: tok.image?.length ?? 10
46117
+ });
46118
+ }
46119
+ if (tok.tokenType === DetailsKeyword && firstByLine.get(tok.startLine ?? 1) === tok) {
46120
+ errs.push({
46121
+ line: tok.startLine ?? 1,
46122
+ column: tok.startColumn ?? 1,
46123
+ severity: "error",
46124
+ code: "SE-DETAILS-UNSUPPORTED",
46125
+ message: "'details' is not accepted by current Mermaid CLI for sequence diagrams.",
46126
+ hint: "Remove the 'details:' line to match mermaid-cli.",
46127
+ length: tok.image?.length ?? 7
46128
+ });
46129
+ }
46130
+ }
46131
+ const lines = /* @__PURE__ */ new Map();
46132
+ for (const tk of _tokens) {
46133
+ if (tk.tokenType === Newline3)
46134
+ continue;
46135
+ const ln = tk.startLine ?? 1;
46136
+ (lines.get(ln) || lines.set(ln, []).get(ln)).push(tk);
46137
+ }
46138
+ const events = [];
46139
+ const tokensByLine = Array.from(lines.entries()).sort((a3, b3) => a3[0] - b3[0]);
46140
+ const grabActorRef = (arr, startIdx) => {
46141
+ const parts = [];
46142
+ for (let i3 = startIdx; i3 < arr.length; i3++) {
46143
+ const tk = arr[i3];
46144
+ if (tk.tokenType === Colon3 || tk.tokenType === Newline3)
46145
+ break;
46146
+ if (tk.tokenType === Identifier2 || tk.tokenType === QuotedString3 || tk.tokenType === NumberLiteral3 || tk.tokenType === Text3)
46147
+ parts.push(tk.image);
46148
+ if (tk.tokenType === Async || tk.tokenType === Solid || tk.tokenType === Dotted || tk.tokenType === DottedAsync || tk.tokenType === BidirAsync || tk.tokenType === BidirAsyncDotted)
46149
+ break;
46150
+ }
46151
+ const raw = parts.join(" ").trim();
46152
+ return raw.replace(/^"|"$/g, "");
46153
+ };
46154
+ for (const [ln, arr] of tokensByLine) {
46155
+ if (arr.some((tk) => tk.tokenType === ActivateKeyword)) {
46156
+ const idx = arr.findIndex((tk) => tk.tokenType === ActivateKeyword);
46157
+ const actor = grabActorRef(arr, idx + 1);
46158
+ if (actor)
46159
+ events.push({ kind: "activate", line: ln, actor });
46160
+ continue;
46161
+ }
46162
+ if (arr.some((tk) => tk.tokenType === DeactivateKeyword)) {
46163
+ const idx = arr.findIndex((tk) => tk.tokenType === DeactivateKeyword);
46164
+ const actor = grabActorRef(arr, idx + 1);
46165
+ if (actor)
46166
+ events.push({ kind: "deactivate", line: ln, actor });
46167
+ continue;
46168
+ }
46169
+ if (arr.some((tk) => tk.tokenType === CreateKeyword)) {
46170
+ const idx = arr.findIndex((tk) => tk.tokenType === CreateKeyword);
46171
+ const after = arr.slice(idx + 1);
46172
+ const aidx = after.findIndex((tk) => tk.tokenType === ParticipantKeyword || tk.tokenType === ActorKeyword);
46173
+ const actor = aidx >= 0 ? grabActorRef(after, aidx + 1) : grabActorRef(arr, idx + 1);
46174
+ if (actor)
46175
+ events.push({ kind: "create", line: ln, actor });
46176
+ continue;
46177
+ }
46178
+ const arrowIdx = arr.findIndex((tk) => [Async, DottedAsync, Solid, Dotted, Cross, DottedCross, DottedOpen, Open, BidirAsync, BidirAsyncDotted].includes(tk.tokenType));
46179
+ if (arrowIdx > 0) {
46180
+ const from = grabActorRef(arr, 0);
46181
+ const to = grabActorRef(arr, arrowIdx + 1);
46182
+ if (from || to) {
46183
+ const plusTok = arr.find((tk) => tk.tokenType === Plus);
46184
+ const minusTok = arr.find((tk) => tk.tokenType === Minus);
46185
+ events.push({ kind: "message", line: ln, from, to, plus: Boolean(plusTok), minus: Boolean(minusTok), plusTok, minusTok });
46186
+ }
46187
+ }
46188
+ }
46189
+ const actStack = /* @__PURE__ */ new Map();
46190
+ for (const ev of events) {
46191
+ if (ev.kind === "activate" && ev.actor) {
46192
+ const a3 = actStack.get(ev.actor) || [];
46193
+ a3.push({ line: ev.line });
46194
+ actStack.set(ev.actor, a3);
46195
+ } else if (ev.kind === "deactivate" && ev.actor) {
46196
+ const a3 = actStack.get(ev.actor) || [];
46197
+ a3.pop();
46198
+ actStack.set(ev.actor, a3);
46199
+ } else if (ev.kind === "message" && ev.to) {
46200
+ const target = ev.to;
46201
+ const plus = Boolean(ev.plus);
46202
+ const minus = Boolean(ev.minus);
46203
+ const plusTok = ev.plusTok;
46204
+ const minusTok = ev.minusTok;
46205
+ if (plus) {
46206
+ const a3 = actStack.get(target) || [];
46207
+ if (a3.length > 0) {
46208
+ const col = plusTok?.startColumn ?? 1;
46209
+ 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 });
46210
+ } else {
46211
+ a3.push({ line: ev.line });
46212
+ actStack.set(target, a3);
46213
+ }
46214
+ }
46215
+ if (minus) {
46216
+ const a3 = actStack.get(target) || [];
46217
+ if (a3.length === 0) {
46218
+ const col = minusTok?.startColumn ?? 1;
46219
+ 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 });
46220
+ } else {
46221
+ a3.pop();
46222
+ actStack.set(target, a3);
46223
+ }
46224
+ }
46225
+ }
46226
+ }
46227
+ for (const [actor, arr] of actStack.entries()) {
46228
+ if (arr.length) {
46229
+ const top = arr[arr.length - 1];
46230
+ errs.push({
46231
+ line: top.line,
46232
+ column: 1,
46233
+ severity: "warning",
46234
+ code: "SE-ACTIVATION-UNBALANCED",
46235
+ message: `Unbalanced activation: '${actor}' was activated but not deactivated.`,
46236
+ hint: `Add 'deactivate ${actor}' after the active section.`,
46237
+ length: actor.length
46238
+ });
46239
+ }
46240
+ }
46241
+ for (let i3 = 0; i3 < events.length; i3++) {
46242
+ const ev = events[i3];
46243
+ if (ev.kind === "create" && ev.actor) {
46244
+ const next = events[i3 + 1];
46245
+ if (!(next && next.kind === "message" && (next.from === ev.actor || next.to === ev.actor))) {
46246
+ errs.push({
46247
+ line: ev.line,
46248
+ column: 1,
46249
+ severity: "warning",
46250
+ code: "SE-CREATE-NO-CREATING-MESSAGE",
46251
+ message: `Actor '${ev.actor}' is created but the next line is not a message involving it.`,
46252
+ hint: `Add a creating message to or from '${ev.actor}' immediately after the create line.`,
46253
+ length: ev.actor.length
46254
+ });
46255
+ }
46256
+ }
46257
+ }
46258
+ return errs;
46259
+ }
46260
+ var BaseVisitor3, SequenceSemanticsVisitor;
46261
+ var init_semantics3 = __esm({
46262
+ "node_modules/@probelabs/maid/out/diagrams/sequence/semantics.js"() {
46263
+ init_parser4();
46264
+ init_lexer4();
46265
+ BaseVisitor3 = parserInstance3.getBaseCstVisitorConstructorWithDefaults();
46266
+ SequenceSemanticsVisitor = class extends BaseVisitor3 {
46267
+ constructor(ctx) {
46268
+ super();
46269
+ this.ctx = ctx;
46270
+ this.validateVisitor();
46271
+ }
46272
+ };
46273
+ }
46274
+ });
46275
+
46276
+ // node_modules/@probelabs/maid/out/diagrams/sequence/validate.js
46277
+ function validateSequence(text, options = {}) {
46278
+ return lintWithChevrotain(text, {
46279
+ tokenize: tokenize3,
45461
46280
  parse: parse3,
45462
46281
  analyze: (cst, tokens) => analyzeSequence(cst, tokens),
45463
46282
  mapParserError: (e3, t3) => mapSequenceParserError(e3, t3),
@@ -45552,7 +46371,7 @@ var init_validate3 = __esm({
45552
46371
  function tokenize4(text) {
45553
46372
  return ClassLexer.tokenize(text);
45554
46373
  }
45555
- 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;
46374
+ 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;
45556
46375
  var init_lexer5 = __esm({
45557
46376
  "node_modules/@probelabs/maid/out/diagrams/class/lexer.js"() {
45558
46377
  init_api5();
@@ -45564,6 +46383,7 @@ var init_lexer5 = __esm({
45564
46383
  ClassKw = createToken({ name: "ClassKw", pattern: /class/, longer_alt: Identifier3 });
45565
46384
  AsKw = createToken({ name: "AsKw", pattern: /as/, longer_alt: Identifier3 });
45566
46385
  NoteKw = createToken({ name: "NoteKw", pattern: /note/, longer_alt: Identifier3 });
46386
+ ForKw = createToken({ name: "ForKw", pattern: /for/, longer_alt: Identifier3 });
45567
46387
  RelCompToAgg = createToken({ name: "RelCompToAgg", pattern: /\*--o/ });
45568
46388
  RelAggToComp = createToken({ name: "RelAggToComp", pattern: /o--\*/ });
45569
46389
  RelCompBoth = createToken({ name: "RelCompBoth", pattern: /\*--\*/ });
@@ -45576,6 +46396,9 @@ var init_lexer5 = __esm({
45576
46396
  RelDependency = createToken({ name: "RelDependency", pattern: /\.\.>/ });
45577
46397
  RelRealization = createToken({ name: "RelRealization", pattern: /\.\.\|>/ });
45578
46398
  RelAssociation = createToken({ name: "RelAssociation", pattern: /--/ });
46399
+ RelDependencyLeft = createToken({ name: "RelDependencyLeft", pattern: /<\.\./ });
46400
+ RelRealizationLeft = createToken({ name: "RelRealizationLeft", pattern: /<\|\.\./ });
46401
+ RelExtendsRight = createToken({ name: "RelExtendsRight", pattern: /--\|>/ });
45579
46402
  InvalidRelArrow = createToken({ name: "InvalidRelArrow", pattern: /->(?!>)/ });
45580
46403
  LCurly = createToken({ name: "LCurly", pattern: /\{/ });
45581
46404
  RCurly = createToken({ name: "RCurly", pattern: /\}/ });
@@ -45586,6 +46409,7 @@ var init_lexer5 = __esm({
45586
46409
  Visibility = createToken({ name: "Visibility", pattern: /[+\-#~]/ });
45587
46410
  LTlt = createToken({ name: "LTlt", pattern: /<</ });
45588
46411
  GTgt = createToken({ name: "GTgt", pattern: />>/ });
46412
+ GenericAngle = createToken({ name: "GenericAngle", pattern: /<[^\n\r>]+>/ });
45589
46413
  QuotedString4 = createToken({ name: "QuotedString", pattern: /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/ });
45590
46414
  BacktickName = createToken({ name: "BacktickName", pattern: /`(?:\\.|[^`\\])*`/ });
45591
46415
  SquareOpen2 = createToken({ name: "SquareOpen", pattern: /\[/ });
@@ -45602,6 +46426,7 @@ var init_lexer5 = __esm({
45602
46426
  ClassKw,
45603
46427
  AsKw,
45604
46428
  NoteKw,
46429
+ ForKw,
45605
46430
  Direction2,
45606
46431
  // Relationship ops
45607
46432
  RelCompToAgg,
@@ -45613,6 +46438,9 @@ var init_lexer5 = __esm({
45613
46438
  RelRealization,
45614
46439
  RelDependency,
45615
46440
  RelExtends,
46441
+ RelDependencyLeft,
46442
+ RelRealizationLeft,
46443
+ RelExtendsRight,
45616
46444
  RelComposition,
45617
46445
  RelAggregation,
45618
46446
  RelAssociation,
@@ -45620,6 +46448,7 @@ var init_lexer5 = __esm({
45620
46448
  // Punct
45621
46449
  LTlt,
45622
46450
  GTgt,
46451
+ GenericAngle,
45623
46452
  LCurly,
45624
46453
  RCurly,
45625
46454
  LParen2,
@@ -45665,6 +46494,7 @@ var init_parser5 = __esm({
45665
46494
  { ALT: () => this.SUBRULE(this.directionStmt) },
45666
46495
  { ALT: () => this.SUBRULE(this.classLine) },
45667
46496
  { ALT: () => this.SUBRULE(this.relationStmt) },
46497
+ { ALT: () => this.SUBRULE(this.noteStmt) },
45668
46498
  { ALT: () => this.SUBRULE(this.memberAssignStmt) },
45669
46499
  { ALT: () => this.CONSUME(Newline4) }
45670
46500
  ]);
@@ -45778,6 +46608,18 @@ var init_parser5 = __esm({
45778
46608
  { ALT: () => this.CONSUME(QuotedString4) }
45779
46609
  ]);
45780
46610
  });
46611
+ this.noteStmt = this.RULE("noteStmt", () => {
46612
+ this.CONSUME(NoteKw);
46613
+ this.OPTION(() => this.CONSUME(ForKw));
46614
+ this.SUBRULE(this.classRef);
46615
+ this.OPTION1(() => this.CONSUME(Colon4));
46616
+ this.OR([
46617
+ { ALT: () => this.CONSUME(QuotedString4) },
46618
+ { ALT: () => this.CONSUME(Identifier3) },
46619
+ { ALT: () => this.CONSUME(NumberLiteral4) }
46620
+ ]);
46621
+ this.OPTION2(() => this.CONSUME(Newline4));
46622
+ });
45781
46623
  this.relationOp = this.RULE("relationOp", () => {
45782
46624
  this.OR([
45783
46625
  { ALT: () => this.CONSUME(RelCompToAgg) },
@@ -45787,16 +46629,22 @@ var init_parser5 = __esm({
45787
46629
  { ALT: () => this.CONSUME(LollipopLeft) },
45788
46630
  { ALT: () => this.CONSUME(LollipopRight) },
45789
46631
  { ALT: () => this.CONSUME(RelExtends) },
46632
+ { ALT: () => this.CONSUME(RelExtendsRight) },
45790
46633
  { ALT: () => this.CONSUME(RelComposition) },
45791
46634
  { ALT: () => this.CONSUME(RelAggregation) },
45792
46635
  { ALT: () => this.CONSUME(RelRealization) },
45793
46636
  { ALT: () => this.CONSUME(RelDependency) },
46637
+ { ALT: () => this.CONSUME(RelRealizationLeft) },
46638
+ { ALT: () => this.CONSUME(RelDependencyLeft) },
45794
46639
  { ALT: () => this.CONSUME(RelAssociation) }
45795
46640
  ]);
45796
46641
  });
45797
46642
  this.classRef = this.RULE("classRef", () => {
45798
46643
  this.OR([
45799
- { ALT: () => this.CONSUME(Identifier3) },
46644
+ { ALT: () => {
46645
+ this.CONSUME(Identifier3);
46646
+ this.OPTION(() => this.CONSUME(GenericAngle));
46647
+ } },
45800
46648
  { ALT: () => this.CONSUME(QuotedString4) },
45801
46649
  { ALT: () => this.CONSUME(BacktickName) }
45802
46650
  ]);
@@ -45805,14 +46653,15 @@ var init_parser5 = __esm({
45805
46653
  this.OR([
45806
46654
  { ALT: () => this.CONSUME(QuotedString4) },
45807
46655
  { ALT: () => this.CONSUME(Identifier3) },
45808
- { ALT: () => this.CONSUME(NumberLiteral4) }
46656
+ { ALT: () => this.CONSUME(NumberLiteral4) },
46657
+ { ALT: () => this.CONSUME(GenericAngle) }
45809
46658
  ]);
45810
46659
  });
45811
46660
  this.relationStmt = this.RULE("relationStmt", () => {
45812
46661
  this.SUBRULE(this.classRef);
45813
- this.OPTION1(() => this.CONSUME(QuotedString4));
46662
+ this.OPTION1(() => this.CONSUME(QuotedString4, { LABEL: "leftCard" }));
45814
46663
  this.SUBRULE(this.relationOp);
45815
- this.OPTION2(() => this.CONSUME2(QuotedString4));
46664
+ this.OPTION2(() => this.CONSUME2(QuotedString4, { LABEL: "rightCard" }));
45816
46665
  this.SUBRULE2(this.classRef);
45817
46666
  this.OPTION3(() => {
45818
46667
  this.CONSUME(Colon4);
@@ -45949,7 +46798,7 @@ var init_validate4 = __esm({
45949
46798
  function tokenize5(text) {
45950
46799
  return StateLexer.tokenize(text);
45951
46800
  }
45952
- 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;
46801
+ 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;
45953
46802
  var init_lexer6 = __esm({
45954
46803
  "node_modules/@probelabs/maid/out/diagrams/state/lexer.js"() {
45955
46804
  init_api5();
@@ -45972,6 +46821,8 @@ var init_lexer6 = __esm({
45972
46821
  StyleClassDefKw = createToken({ name: "StyleClassDefKw", pattern: /classDef/, longer_alt: Identifier4 });
45973
46822
  StyleClassKw = createToken({ name: "StyleClassKw", pattern: /class(?!Diagram)/, longer_alt: Identifier4 });
45974
46823
  Start = createToken({ name: "Start", pattern: /\[\*\]/ });
46824
+ HistoryShallow = createToken({ name: "HistoryShallow", pattern: /\[H\]/ });
46825
+ HistoryDeep = createToken({ name: "HistoryDeep", pattern: /\[H\*\]/ });
45975
46826
  Arrow = createToken({ name: "Arrow", pattern: /-->/ });
45976
46827
  InvalidArrow2 = createToken({ name: "InvalidArrow", pattern: /->(?!>)/ });
45977
46828
  Hyphen = createToken({ name: "Hyphen", pattern: /-/ });
@@ -46001,6 +46852,8 @@ var init_lexer6 = __esm({
46001
46852
  AngleAngleOpen,
46002
46853
  AngleAngleClose,
46003
46854
  Start,
46855
+ HistoryDeep,
46856
+ HistoryShallow,
46004
46857
  Arrow,
46005
46858
  InvalidArrow2,
46006
46859
  Dashes,
@@ -46049,8 +46902,7 @@ var init_parser6 = __esm({
46049
46902
  { ALT: () => this.SUBRULE(this.transitionStmt) },
46050
46903
  { ALT: () => this.SUBRULE(this.stateBlock) },
46051
46904
  { ALT: () => this.SUBRULE(this.stateDecl) },
46052
- // Concurrency separator (---) is not supported by mermaid-cli v11; treat as invalid (handled in postLex)
46053
- // { ALT: () => this.CONSUME(t.Dashes) },
46905
+ // '---' only allowed inside state blocks; not at top level
46054
46906
  { ALT: () => this.SUBRULE(this.stateDescriptionStmt) },
46055
46907
  { ALT: () => this.SUBRULE(this.noteStmt) },
46056
46908
  { ALT: () => this.SUBRULE(this.styleStmt) },
@@ -46082,6 +46934,8 @@ var init_parser6 = __esm({
46082
46934
  this.actorRef = this.RULE("actorRef", () => {
46083
46935
  this.OR([
46084
46936
  { ALT: () => this.CONSUME(Start) },
46937
+ { ALT: () => this.CONSUME(HistoryDeep) },
46938
+ { ALT: () => this.CONSUME(HistoryShallow) },
46085
46939
  {
46086
46940
  ALT: () => {
46087
46941
  this.OR2([
@@ -46154,10 +47008,23 @@ var init_parser6 = __esm({
46154
47008
  { ALT: () => this.CONSUME(QuotedString5) }
46155
47009
  ]);
46156
47010
  this.CONSUME(LCurly2);
46157
- this.MANY(() => this.SUBRULE(this.statement));
47011
+ this.MANY(() => this.SUBRULE(this.innerStatement));
46158
47012
  this.CONSUME(RCurly2);
46159
47013
  this.OPTION(() => this.CONSUME(Newline5));
46160
47014
  });
47015
+ this.innerStatement = this.RULE("innerStatement", () => {
47016
+ this.OR([
47017
+ { ALT: () => this.SUBRULE(this.directionStmt) },
47018
+ { ALT: () => this.SUBRULE(this.transitionStmt) },
47019
+ { ALT: () => this.SUBRULE(this.stateBlock) },
47020
+ { ALT: () => this.SUBRULE(this.stateDecl) },
47021
+ { ALT: () => this.CONSUME(Dashes) },
47022
+ { ALT: () => this.SUBRULE(this.stateDescriptionStmt) },
47023
+ { ALT: () => this.SUBRULE(this.noteStmt) },
47024
+ { ALT: () => this.SUBRULE(this.styleStmt) },
47025
+ { ALT: () => this.CONSUME(Newline5) }
47026
+ ]);
47027
+ });
46161
47028
  this.noteStmt = this.RULE("noteStmt", () => {
46162
47029
  this.CONSUME(NoteKw2);
46163
47030
  this.OR([
@@ -46296,6 +47163,72 @@ function validateState(text, _options = {}) {
46296
47163
  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 { ... }" });
46297
47164
  }
46298
47165
  }
47166
+ const stack = [];
47167
+ const pushBlock = (ln) => stack.push({ start: ln, content: [], seps: [] });
47168
+ const top = () => stack[stack.length - 1];
47169
+ for (let i3 = 0; i3 < lines.length; i3++) {
47170
+ const raw = lines[i3] || "";
47171
+ const ln = i3 + 1;
47172
+ if (/^\s*state\b.*\{\s*$/.test(raw)) {
47173
+ pushBlock(ln);
47174
+ continue;
47175
+ }
47176
+ if (/^\s*\}\s*$/.test(raw)) {
47177
+ const blk = stack.pop();
47178
+ if (blk) {
47179
+ 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);
47180
+ const sepIdxs = all.map((x3, i4) => ({ i: i4, x: x3 })).filter((z3) => z3.x.kind === "sep").map((z3) => z3.i);
47181
+ for (const si of sepIdxs) {
47182
+ const sepLn = all[si].ln;
47183
+ let hasBefore = false;
47184
+ for (let k3 = si - 1; k3 >= 0; k3--) {
47185
+ if (all[k3].kind === "sep")
47186
+ break;
47187
+ if (all[k3].kind === "content") {
47188
+ hasBefore = true;
47189
+ break;
47190
+ }
47191
+ }
47192
+ let hasAfter = false;
47193
+ for (let k3 = si + 1; k3 < all.length; k3++) {
47194
+ if (all[k3].kind === "sep")
47195
+ break;
47196
+ if (all[k3].kind === "content") {
47197
+ hasAfter = true;
47198
+ break;
47199
+ }
47200
+ }
47201
+ if (!hasBefore || !hasAfter) {
47202
+ errors.push({
47203
+ line: sepLn,
47204
+ column: 1,
47205
+ severity: "error",
47206
+ code: "ST-CONCURRENCY-MISPLACED",
47207
+ message: "Concurrency separator '---' must be between regions, not at the start or end of a block.",
47208
+ hint: "Place '---' between two sets of state lines inside the same block."
47209
+ });
47210
+ }
47211
+ }
47212
+ }
47213
+ continue;
47214
+ }
47215
+ if (stack.length > 0) {
47216
+ if (/^\s*---\s*$/.test(raw)) {
47217
+ top().seps.push(ln);
47218
+ if (!has2("ST-CONCURRENCY-UNSUPPORTED", ln)) {
47219
+ errors.push({
47220
+ line: ln,
47221
+ column: 1,
47222
+ severity: "error",
47223
+ code: "ST-CONCURRENCY-UNSUPPORTED",
47224
+ message: "Concurrency separator '---' is not supported by Mermaid CLI in state diagrams.",
47225
+ hint: "Remove '---' or split logic into separate composite states."
47226
+ });
47227
+ }
47228
+ } else if (raw.trim() !== "")
47229
+ top().content.push(ln);
47230
+ }
47231
+ }
46299
47232
  return errors;
46300
47233
  }
46301
47234
  });
@@ -46558,6 +47491,10 @@ function computeFixes(text, errors, level = "safe") {
46558
47491
  edits.push(replaceRange(text, at(e3), e3.length ?? 2, "&quot;"));
46559
47492
  continue;
46560
47493
  }
47494
+ if (is("FL-LABEL-BACKTICK", e3)) {
47495
+ edits.push(replaceRange(text, at(e3), e3.length ?? 1, ""));
47496
+ continue;
47497
+ }
46561
47498
  if (is("FL-LABEL-DOUBLE-IN-DOUBLE", e3)) {
46562
47499
  const lineText = lineTextAt(text, e3.line);
46563
47500
  const caret0 = Math.max(0, e3.column - 1);
@@ -46668,8 +47605,24 @@ function computeFixes(text, errors, level = "safe") {
46668
47605
  continue;
46669
47606
  }
46670
47607
  if (is("FL-LINK-MISSING", e3)) {
46671
- if (level === "all")
46672
- edits.push(insertAt(text, at(e3), " --> "));
47608
+ if (level === "all") {
47609
+ const line = e3.line;
47610
+ const lineText = lineTextAt(text, line);
47611
+ if (!/-->/.test(lineText)) {
47612
+ const shapePart = "(?:\\[[^\\]]*\\]|\\([^\\)]*\\)|\\{[^}]*\\}|\\[\\[[^\\]]*\\]\\]|\\(\\([^\\)]*\\)\\))?";
47613
+ const id = "[A-Za-z0-9_]+";
47614
+ const re = new RegExp(`^\\s*(${id}${shapePart})\\s+(${id})`);
47615
+ const m3 = re.exec(lineText);
47616
+ if (m3) {
47617
+ const before = m3[0];
47618
+ const insertIdx = before.length - m3[2].length;
47619
+ const col = insertIdx + 1;
47620
+ edits.push(insertAt(text, { line, column: col }, " --> "));
47621
+ } else {
47622
+ edits.push(insertAt(text, at(e3), " --> "));
47623
+ }
47624
+ }
47625
+ }
46673
47626
  continue;
46674
47627
  }
46675
47628
  if (is("FL-NODE-UNCLOSED-BRACKET", e3)) {
@@ -47288,9 +48241,13 @@ var init_graph_builder = __esm({
47288
48241
  this.edgeCounter = 0;
47289
48242
  this.subgraphs = [];
47290
48243
  this.currentSubgraphStack = [];
48244
+ this.pendingLinkStyles = [];
47291
48245
  this.classStyles = /* @__PURE__ */ new Map();
47292
48246
  this.nodeStyles = /* @__PURE__ */ new Map();
47293
48247
  this.nodeClasses = /* @__PURE__ */ new Map();
48248
+ this.edgeClasses = /* @__PURE__ */ new Map();
48249
+ this.edgeStyles = /* @__PURE__ */ new Map();
48250
+ this.nodeLinks = /* @__PURE__ */ new Map();
47294
48251
  }
47295
48252
  build(cst) {
47296
48253
  this.reset();
@@ -47304,6 +48261,11 @@ var init_graph_builder = __esm({
47304
48261
  }
47305
48262
  const direction = this.extractDirection(cst);
47306
48263
  this.processStatements(cst);
48264
+ for (const [id, link] of this.nodeLinks.entries()) {
48265
+ const node = this.nodes.get(id);
48266
+ if (node)
48267
+ node.link = link;
48268
+ }
47307
48269
  return {
47308
48270
  nodes: Array.from(this.nodes.values()),
47309
48271
  edges: this.edges,
@@ -47321,6 +48283,10 @@ var init_graph_builder = __esm({
47321
48283
  this.classStyles.clear();
47322
48284
  this.nodeStyles.clear();
47323
48285
  this.nodeClasses.clear();
48286
+ this.edgeClasses.clear();
48287
+ this.edgeStyles.clear();
48288
+ this.pendingLinkStyles = [];
48289
+ this.nodeLinks.clear();
47324
48290
  }
47325
48291
  extractDirection(cst) {
47326
48292
  const dirToken = cst.children?.Direction?.[0];
@@ -47354,14 +48320,100 @@ var init_graph_builder = __esm({
47354
48320
  this.processClassAssign(stmt.children.classStatement[0]);
47355
48321
  } else if (stmt.children?.styleStatement) {
47356
48322
  this.processStyle(stmt.children.styleStatement[0]);
48323
+ } else if (stmt.children?.linkStyleStatement) {
48324
+ this.processLinkStyle(stmt.children.linkStyleStatement[0]);
48325
+ } else if (stmt.children?.clickStatement) {
48326
+ this.processClick(stmt.children.clickStatement[0]);
48327
+ } else if (stmt.children?.edgeAttrStatement) {
48328
+ this.processEdgeAttr(stmt.children.edgeAttrStatement[0]);
47357
48329
  }
47358
48330
  }
48331
+ this.applyLinkStyles();
48332
+ }
48333
+ unquote(s3) {
48334
+ if (!s3)
48335
+ return s3;
48336
+ if (s3.startsWith('"') && s3.endsWith('"') || s3.startsWith("'") && s3.endsWith("'"))
48337
+ return s3.slice(1, -1);
48338
+ return s3;
48339
+ }
48340
+ processClick(cst) {
48341
+ const ch = cst.children || {};
48342
+ const tgtTok = ch.clickTarget?.[0];
48343
+ if (!tgtTok)
48344
+ return;
48345
+ const id = tgtTok.image;
48346
+ const link = {};
48347
+ if (ch.clickHref && ch.clickHref[0]) {
48348
+ const hrefCh = ch.clickHref[0].children || {};
48349
+ if (hrefCh.url && hrefCh.url[0])
48350
+ link.href = this.unquote(hrefCh.url[0].image);
48351
+ if (hrefCh.tooltip && hrefCh.tooltip[0])
48352
+ link.tooltip = this.unquote(hrefCh.tooltip[0].image);
48353
+ if (hrefCh.target && hrefCh.target[0])
48354
+ link.target = hrefCh.target[0].image;
48355
+ } else if (ch.clickCall && ch.clickCall[0]) {
48356
+ const callCh = ch.clickCall[0].children || {};
48357
+ if (callCh.fn && callCh.fn[0])
48358
+ link.call = callCh.fn[0].image;
48359
+ if (callCh.tooltip && callCh.tooltip[0])
48360
+ link.tooltip = this.unquote(callCh.tooltip[0].image);
48361
+ } else {
48362
+ const idents = ch.Identifier || [];
48363
+ const texts = ch.Text || [];
48364
+ const quotes = ch.QuotedString || [];
48365
+ const modeTok = idents.find((t3) => /^(href|call|callback)$/i.test(t3.image));
48366
+ const mode = modeTok?.image?.toLowerCase();
48367
+ if (mode === "href") {
48368
+ const urlTok = quotes[0];
48369
+ const tipTok = quotes[1];
48370
+ const targetTok = idents.find((t3) => /^_(blank|self|parent|top)$/i.test(t3.image));
48371
+ if (urlTok)
48372
+ link.href = this.unquote(urlTok.image);
48373
+ if (tipTok)
48374
+ link.tooltip = this.unquote(tipTok.image);
48375
+ if (targetTok)
48376
+ link.target = targetTok.image;
48377
+ } else if (mode === "call" || mode === "callback") {
48378
+ const reserved = /* @__PURE__ */ new Set(["href", "call", "callback", "_blank", "_self", "_parent", "_top"]);
48379
+ const after = idents.filter((t3) => (t3.startOffset ?? 0) > (modeTok?.startOffset ?? -1));
48380
+ const nameTok = after.find((t3) => !reserved.has(t3.image.toLowerCase()));
48381
+ const tstr = texts.map((t3) => t3.image).join(" ").trim();
48382
+ link.call = nameTok ? nameTok.image + (tstr ? ` ${tstr}` : "") : tstr || void 0;
48383
+ const tipTok = quotes[0];
48384
+ if (tipTok)
48385
+ link.tooltip = this.unquote(tipTok.image);
48386
+ }
48387
+ }
48388
+ if (Object.keys(link).length)
48389
+ this.nodeLinks.set(id, { ...this.nodeLinks.get(id) || {}, ...link });
47359
48390
  }
47360
48391
  processNodeStatement(stmt) {
47361
48392
  const groups = stmt.children?.nodeOrParallelGroup;
47362
48393
  const links = stmt.children?.link;
47363
48394
  if (!groups || groups.length === 0)
47364
48395
  return;
48396
+ if ((!links || links.length === 0) && groups.length === 1) {
48397
+ const g0 = groups[0];
48398
+ const nodes = g0.children?.node || [];
48399
+ if (nodes.length === 1) {
48400
+ const n3 = nodes[0];
48401
+ const hasAttr = !!(n3.children.attrObject && n3.children.attrObject.length);
48402
+ const hasShape = !!n3.children?.nodeShape;
48403
+ if (hasAttr && !hasShape) {
48404
+ const idTok = n3.children.nodeId?.[0] || n3.children.Identifier?.[0] || void 0;
48405
+ if (idTok) {
48406
+ const id = idTok.image;
48407
+ const exists = this.edges.some((e3) => e3.id === id);
48408
+ if (exists) {
48409
+ const edgeAttrFake = { children: { edgeId: [{ image: id }], attrObject: n3.children.attrObject } };
48410
+ this.processEdgeAttr(edgeAttrFake);
48411
+ return;
48412
+ }
48413
+ }
48414
+ }
48415
+ }
48416
+ }
47365
48417
  const sourceNodes = this.processNodeGroup(groups[0]);
47366
48418
  if (groups.length > 1 && links && links.length > 0) {
47367
48419
  const targetNodes = this.processNodeGroup(groups[1]);
@@ -47369,7 +48421,7 @@ var init_graph_builder = __esm({
47369
48421
  for (const source of sourceNodes) {
47370
48422
  for (const target of targetNodes) {
47371
48423
  this.edges.push({
47372
- id: `e${this.edgeCounter++}`,
48424
+ id: linkInfo.edgeId || `e${this.edgeCounter++}`,
47373
48425
  source,
47374
48426
  target,
47375
48427
  label: linkInfo.label,
@@ -47385,7 +48437,7 @@ var init_graph_builder = __esm({
47385
48437
  for (const source of targetNodes) {
47386
48438
  for (const target of nextNodes) {
47387
48439
  this.edges.push({
47388
- id: `e${this.edgeCounter++}`,
48440
+ id: nextLink.edgeId || `e${this.edgeCounter++}`,
47389
48441
  source,
47390
48442
  target,
47391
48443
  label: nextLink.label,
@@ -47468,13 +48520,101 @@ var init_graph_builder = __esm({
47468
48520
  if (result.label)
47469
48521
  label = result.label;
47470
48522
  }
48523
+ const attrNode = children.attrObject?.[0];
48524
+ let typedShape;
48525
+ if (attrNode && !shapeNode) {
48526
+ typedShape = this.parseTypedAttrObject(attrNode);
48527
+ if (typedShape.shape) {
48528
+ const m3 = typedShape.shape;
48529
+ if (m3 === "rect")
48530
+ shape = "rectangle";
48531
+ else if (m3 === "round" || m3 === "rounded")
48532
+ shape = "round";
48533
+ else if (m3 === "stadium")
48534
+ shape = "stadium";
48535
+ else if (m3 === "subroutine")
48536
+ shape = "subroutine";
48537
+ else if (m3 === "circle")
48538
+ shape = "circle";
48539
+ else if (m3 === "cylinder")
48540
+ shape = "cylinder";
48541
+ else if (m3 === "diamond")
48542
+ shape = "diamond";
48543
+ else if (m3 === "trapezoid")
48544
+ shape = "trapezoid";
48545
+ else if (m3 === "trapezoidAlt")
48546
+ shape = "trapezoidAlt";
48547
+ else if (m3 === "parallelogram" || m3 === "lean-l" || m3 === "lean-r") {
48548
+ shape = "parallelogram";
48549
+ typedShape.lean = m3 === "lean-l" ? "l" : m3 === "lean-r" ? "r" : void 0;
48550
+ } else if (m3 === "hexagon")
48551
+ shape = "hexagon";
48552
+ else if (m3 === "icon" || m3 === "image")
48553
+ shape = "rectangle";
48554
+ }
48555
+ if (typeof typedShape.label === "string" && typedShape.label.length > 0) {
48556
+ label = typedShape.label;
48557
+ }
48558
+ }
47471
48559
  const clsTok = children.nodeClass?.[0];
47472
48560
  if (clsTok) {
47473
48561
  const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
47474
48562
  set.add(clsTok.image);
47475
48563
  this.nodeClasses.set(id, set);
47476
48564
  }
47477
- return { id, label, shape };
48565
+ const out = { id, label, shape };
48566
+ if (typedShape) {
48567
+ const padding = typedShape.padding;
48568
+ const cornerRadius = typedShape.cornerRadius;
48569
+ const lean = typedShape.lean;
48570
+ const media = typedShape.icon || typedShape.image ? { icon: typedShape.icon, image: typedShape.image } : void 0;
48571
+ out.typed = { padding, cornerRadius, lean, media };
48572
+ }
48573
+ return out;
48574
+ }
48575
+ parseTypedAttrObject(attrNode) {
48576
+ const ch = attrNode.children || {};
48577
+ const pairs = ch.attrPair || [];
48578
+ const out = {};
48579
+ for (const p3 of pairs) {
48580
+ const keyTok = p3.children?.attrKey?.[0];
48581
+ if (!keyTok)
48582
+ continue;
48583
+ const k3 = keyTok.image;
48584
+ const vTok = p3.children?.QuotedString?.[0] || p3.children?.Identifier?.[0] || p3.children?.NumberLiteral?.[0] || p3.children?.Text?.[0];
48585
+ if (!vTok)
48586
+ continue;
48587
+ let raw = vTok.image;
48588
+ if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'"))
48589
+ raw = raw.slice(1, -1);
48590
+ switch (k3) {
48591
+ case "shape":
48592
+ out.shape = raw;
48593
+ break;
48594
+ case "label":
48595
+ out.label = raw;
48596
+ break;
48597
+ case "padding": {
48598
+ const n3 = parseFloat(raw);
48599
+ if (Number.isFinite(n3))
48600
+ out.padding = n3;
48601
+ break;
48602
+ }
48603
+ case "cornerRadius": {
48604
+ const n3 = parseFloat(raw);
48605
+ if (Number.isFinite(n3))
48606
+ out.cornerRadius = n3;
48607
+ break;
48608
+ }
48609
+ case "icon":
48610
+ out.icon = raw;
48611
+ break;
48612
+ case "image":
48613
+ out.image = raw;
48614
+ break;
48615
+ }
48616
+ }
48617
+ return out;
47478
48618
  }
47479
48619
  extractShapeAndLabel(shapeNode) {
47480
48620
  const children = shapeNode.children;
@@ -47593,6 +48733,7 @@ var init_graph_builder = __esm({
47593
48733
  let label;
47594
48734
  let markerStart = "none";
47595
48735
  let markerEnd = "none";
48736
+ const eidTok = children.edgeId?.[0];
47596
48737
  if (children.BiDirectionalArrow) {
47597
48738
  type = "arrow";
47598
48739
  markerStart = "arrow";
@@ -47667,7 +48808,7 @@ var init_graph_builder = __esm({
47667
48808
  };
47668
48809
  label = strip(raw);
47669
48810
  }
47670
- return { type, label, markerStart, markerEnd };
48811
+ return { type, label, markerStart, markerEnd, edgeId: eidTok ? eidTok.image : void 0 };
47671
48812
  }
47672
48813
  processSubgraph(subgraph) {
47673
48814
  const children = subgraph.children;
@@ -47730,12 +48871,15 @@ var init_graph_builder = __esm({
47730
48871
  return;
47731
48872
  const classNameTok = cst.children.className?.[0];
47732
48873
  const className = classNameTok?.image || ids[ids.length - 1].image;
47733
- const nodeIds = classNameTok ? ids.slice(0, -1) : ids.slice(0, -1);
47734
- for (const tok of nodeIds) {
48874
+ const targetIds = classNameTok ? ids.slice(0, -1) : ids.slice(0, -1);
48875
+ for (const tok of targetIds) {
47735
48876
  const id = tok.image;
47736
- const set = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
47737
- set.add(className);
47738
- this.nodeClasses.set(id, set);
48877
+ const nset = this.nodeClasses.get(id) || /* @__PURE__ */ new Set();
48878
+ nset.add(className);
48879
+ this.nodeClasses.set(id, nset);
48880
+ const eset = this.edgeClasses.get(id) || /* @__PURE__ */ new Set();
48881
+ eset.add(className);
48882
+ this.edgeClasses.set(id, eset);
47739
48883
  const node = this.nodes.get(id);
47740
48884
  if (node) {
47741
48885
  node.style = { ...node.style || {}, ...this.computeNodeStyle(id) };
@@ -47781,6 +48925,121 @@ var init_graph_builder = __esm({
47781
48925
  }
47782
48926
  return props;
47783
48927
  }
48928
+ processEdgeAttr(cst) {
48929
+ const eidTok = cst.children.edgeId?.[0];
48930
+ if (!eidTok)
48931
+ return;
48932
+ const id = eidTok.image;
48933
+ const attrNode = cst.children.attrObject?.[0];
48934
+ if (!attrNode)
48935
+ return;
48936
+ const ch = attrNode.children || {};
48937
+ const pairs = ch.attrPair || [];
48938
+ const props = {};
48939
+ for (const p3 of pairs) {
48940
+ const keyTok = p3.children.attrKey?.[0];
48941
+ const vTok = p3.children.QuotedString?.[0] || p3.children.Identifier?.[0] || p3.children.NumberLiteral?.[0] || p3.children.Text?.[0];
48942
+ if (!keyTok || !vTok)
48943
+ continue;
48944
+ let val = vTok.image;
48945
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'"))
48946
+ val = val.slice(1, -1);
48947
+ const k3 = keyTok.image;
48948
+ if (k3 === "animate") {
48949
+ const truthy = /^(true|1|yes|on|fast|slow)$/i.test(val);
48950
+ if (truthy) {
48951
+ props["animation"] = /^slow$/i.test(val) ? "dash 8s linear infinite" : /^fast$/i.test(val) ? "dash 2s linear infinite" : "dash 4s linear infinite";
48952
+ if (!props["stroke-dasharray"])
48953
+ props["stroke-dasharray"] = "5 5";
48954
+ }
48955
+ } else {
48956
+ props[k3] = val;
48957
+ }
48958
+ }
48959
+ const cur = this.edgeStyles.get(id) || {};
48960
+ this.edgeStyles.set(id, { ...cur, ...props });
48961
+ }
48962
+ computeEdgeStyle(edgeId) {
48963
+ const out = {};
48964
+ const classes = this.edgeClasses.get(edgeId);
48965
+ if (classes) {
48966
+ for (const c3 of classes) {
48967
+ const s3 = this.classStyles.get(c3);
48968
+ if (s3)
48969
+ Object.assign(out, this.normalizeStyle(s3));
48970
+ }
48971
+ }
48972
+ const direct = this.edgeStyles.get(edgeId);
48973
+ if (direct)
48974
+ Object.assign(out, this.normalizeStyle(direct));
48975
+ return out;
48976
+ }
48977
+ processLinkStyle(cst) {
48978
+ const ch = cst.children || {};
48979
+ if (ch.linkStyleIndexList && ch.linkStylePairs) {
48980
+ const idxNode = ch.linkStyleIndexList[0];
48981
+ const pairNode = ch.linkStylePairs[0];
48982
+ const idxToks = (idxNode.children || {}).index || [];
48983
+ const indices2 = idxToks.map((t3) => parseInt(t3.image, 10)).filter((n3) => Number.isFinite(n3));
48984
+ const pairs = (pairNode.children || {}).linkStylePair || [];
48985
+ const props2 = {};
48986
+ for (const p3 of pairs) {
48987
+ const pch = p3.children || {};
48988
+ const keyTok = pch.key?.[0];
48989
+ const vTok = pch.valueColor?.[0] || pch.valueQuoted?.[0] || pch.valueNum?.[0] || pch.valueId?.[0] || pch.valueText?.[0];
48990
+ if (!keyTok || !vTok)
48991
+ continue;
48992
+ let val = vTok.image;
48993
+ if (vTok.tokenType?.name === "QuotedString" && (val.startsWith('"') || val.startsWith("'"))) {
48994
+ val = val.slice(1, -1);
48995
+ }
48996
+ props2[keyTok.image] = val;
48997
+ }
48998
+ this.pendingLinkStyles.push({ indices: indices2, props: props2 });
48999
+ return;
49000
+ }
49001
+ const nums = cst.children?.NumberLiteral || [];
49002
+ const indices = nums.map((n3) => parseInt(n3.image, 10)).filter((n3) => Number.isFinite(n3));
49003
+ const props = this.collectStyleProps(cst);
49004
+ this.pendingLinkStyles.push({ indices, props });
49005
+ }
49006
+ applyLinkStyles() {
49007
+ if (!this.pendingLinkStyles.length || !this.edges.length)
49008
+ return;
49009
+ const normalize = (s3) => {
49010
+ const out = {};
49011
+ for (const [kRaw, vRaw] of Object.entries(s3)) {
49012
+ const k3 = kRaw.trim().toLowerCase();
49013
+ const v3 = vRaw.trim();
49014
+ if (k3 === "stroke")
49015
+ out.stroke = v3;
49016
+ else if (k3 === "stroke-width") {
49017
+ const num = parseFloat(v3);
49018
+ if (!Number.isNaN(num))
49019
+ out.strokeWidth = num;
49020
+ } else if (k3 === "opacity" || k3 === "stroke-opacity") {
49021
+ const num = parseFloat(v3);
49022
+ if (!Number.isNaN(num))
49023
+ out.strokeOpacity = num;
49024
+ } else if (k3 === "stroke-dasharray")
49025
+ out.dasharray = v3;
49026
+ }
49027
+ return out;
49028
+ };
49029
+ for (const cmd of this.pendingLinkStyles) {
49030
+ const style = normalize(cmd.props);
49031
+ for (const idx of cmd.indices) {
49032
+ if (idx >= 0 && idx < this.edges.length) {
49033
+ const e3 = this.edges[idx];
49034
+ e3.style = { ...e3.style || {}, stroke: style.stroke ?? e3.style?.stroke, strokeWidth: style.strokeWidth ?? e3.style?.strokeWidth, strokeOpacity: style.strokeOpacity ?? e3.style?.strokeOpacity };
49035
+ if (style.dasharray)
49036
+ e3.dasharray = style.dasharray;
49037
+ if (style.animation)
49038
+ e3.animation = style.animation;
49039
+ }
49040
+ }
49041
+ }
49042
+ }
47784
49043
  computeNodeStyle(nodeId) {
47785
49044
  const out = {};
47786
49045
  const classes = this.nodeClasses.get(nodeId);
@@ -55532,8 +56791,10 @@ var init_layout = __esm({
55532
56791
  marginy: 20
55533
56792
  };
55534
56793
  if (hasClusters && (dir === "LR" || dir === "RL")) {
55535
- graphConfig.ranker = "longest-path";
56794
+ graphConfig.ranker = "network-simplex";
55536
56795
  graphConfig.acyclicer = "greedy";
56796
+ nodesep += 40;
56797
+ ranksep = Math.max(30, ranksep - 20);
55537
56798
  }
55538
56799
  if (hasClusters) {
55539
56800
  graphConfig.compound = true;
@@ -55546,7 +56807,9 @@ var init_layout = __esm({
55546
56807
  }
55547
56808
  }
55548
56809
  for (const node of graph.nodes) {
55549
- const dimensions = this.calculateNodeDimensions(node.label, node.shape);
56810
+ const providedW = node.width;
56811
+ const providedH = node.height;
56812
+ const dimensions = providedW && providedH ? { width: providedW, height: providedH } : this.calculateNodeDimensions(node.label, node.shape);
55550
56813
  g3.setNode(node.id, {
55551
56814
  width: dimensions.width,
55552
56815
  height: dimensions.height,
@@ -55670,7 +56933,7 @@ var init_layout = __esm({
55670
56933
  const inX = end.x + (rankdir === "LR" ? -PAD : PAD);
55671
56934
  const startOut = { x: srcSg ? outX : start.x, y: start.y };
55672
56935
  const endPre = { x: dstSg ? inX : end.x, y: end.y };
55673
- const alpha = 0.68;
56936
+ const alpha = 0.72;
55674
56937
  const midX = startOut.x + (endPre.x - startOut.x) * alpha;
55675
56938
  const m1 = { x: midX, y: startOut.y };
55676
56939
  const m22 = { x: midX, y: endPre.y };
@@ -55867,6 +57130,11 @@ function buildSharedCss(opts = {}) {
55867
57130
  .edge-path { stroke: ${edgeStroke}; stroke-width: 2px; fill: none; }
55868
57131
  .edge-label-bg { fill: rgba(232,232,232, 0.8); opacity: 0.5; }
55869
57132
  .edge-label-text { fill: #333; font-family: ${fontFamily}; font-size: ${Math.max(10, fontSize - 2)}px; }
57133
+ .edge-marker { stroke: ${edgeStroke}; }
57134
+ .edge-marker-fill { fill: ${edgeStroke}; }
57135
+
57136
+ /* Basic stroke dash animation used by flowchart link animation presets */
57137
+ @keyframes dash { to { stroke-dashoffset: -1000; } }
55870
57138
 
55871
57139
  /* Cluster (flowchart + sequence blocks) */
55872
57140
  .cluster-bg { fill: #ffffde; }
@@ -55881,15 +57149,77 @@ function buildSharedCss(opts = {}) {
55881
57149
  /* Sequence-specific add-ons (safe for flowcharts too) */
55882
57150
  .actor-rect { fill: #eaeaea; stroke: #666; stroke-width: 1.5px; }
55883
57151
  .actor-label { fill: #111; font-family: ${fontFamily}; font-size: 16px; }
55884
- .lifeline { stroke: #999; stroke-width: 0.5px; }
57152
+ .lifeline { stroke: #999; stroke-width: 1px; }
55885
57153
  .activation { fill: #f4f4f4; stroke: #666; stroke-width: 1px; }
55886
57154
  .msg-line { stroke: #333; stroke-width: 1.5px; fill: none; }
55887
57155
  .msg-line.dotted { stroke-dasharray: 2 2; }
55888
57156
  .msg-line.thick { stroke-width: 3px; }
57157
+ .openhead { fill: none; stroke: #333; stroke-width: 1.5px; }
57158
+ .crosshead path { stroke: #333; stroke-width: 1.5px; }
55889
57159
  .msg-label { fill: #333; font-family: ${fontFamily}; font-size: 12px; dominant-baseline: middle; }
55890
57160
  .msg-label-bg { fill: #ffffff; stroke: #cccccc; stroke-width: 1px; rx: 3; }
57161
+
57162
+ /* State overlays */
57163
+ .lane-divider { stroke: #aaaaaa; stroke-width: 1px; stroke-dasharray: 4 3; }
57164
+ .end-double { stroke: #3f3f3f; stroke-width: 1px; fill: none; }
55891
57165
  `;
55892
57166
  }
57167
+ function applyFlowLikeTheme(svg, theme) {
57168
+ if (!theme)
57169
+ return svg;
57170
+ let out = svg;
57171
+ if (theme.nodeBkg || theme.nodeBorder) {
57172
+ out = out.replace(/\.node-shape\s*\{[^}]*\}/, (m3) => {
57173
+ let rule = m3;
57174
+ if (theme.nodeBkg)
57175
+ rule = rule.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeBkg)};`);
57176
+ if (theme.nodeBorder)
57177
+ rule = rule.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.nodeBorder)};`);
57178
+ return rule;
57179
+ });
57180
+ }
57181
+ if (theme.nodeTextColor) {
57182
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeTextColor)};`));
57183
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.nodeTextColor)};`));
57184
+ }
57185
+ if (theme.edgeLabelTextColor) {
57186
+ const c3 = String(theme.edgeLabelTextColor);
57187
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
57188
+ }
57189
+ if (theme.lineColor) {
57190
+ out = out.replace(/\.edge-path\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
57191
+ }
57192
+ if (theme.arrowheadColor) {
57193
+ out = out.replace(/\.edge-marker\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57194
+ 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)}; }`));
57195
+ out = out.replace(/\.openhead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57196
+ out = out.replace(/\.crosshead path\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57197
+ }
57198
+ if (theme.clusterBkg)
57199
+ out = out.replace(/\.cluster-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterBkg)};`));
57200
+ if (theme.clusterBorder)
57201
+ out = out.replace(/\.cluster-border\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.clusterBorder)};`));
57202
+ if (theme.clusterTextColor)
57203
+ out = out.replace(/\.cluster-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterTextColor)};`));
57204
+ if (theme.clusterTitleBg || theme.clusterTitleBackground) {
57205
+ const c3 = String(theme.clusterTitleBg || theme.clusterTitleBackground);
57206
+ out = out.replace(/\.cluster-title-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
57207
+ }
57208
+ if (theme.fontFamily) {
57209
+ const f3 = String(theme.fontFamily);
57210
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
57211
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
57212
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${f3};`));
57213
+ }
57214
+ if (theme.fontSize) {
57215
+ const s3 = String(theme.fontSize);
57216
+ out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${s3}px;`));
57217
+ const sub = Math.max(10, Number(theme.fontSize) - 2);
57218
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${sub}px;`));
57219
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/font-size:\s*[^;]+;/, `font-size: ${sub}px;`));
57220
+ }
57221
+ return out;
57222
+ }
55893
57223
  var init_styles = __esm({
55894
57224
  "node_modules/@probelabs/maid/out/renderer/styles.js"() {
55895
57225
  }
@@ -56073,6 +57403,8 @@ var init_svg_generator = __esm({
56073
57403
  };
56074
57404
  const bgs = [];
56075
57405
  for (const sg of order) {
57406
+ if (sg.id && sg.id.includes("__lane"))
57407
+ continue;
56076
57408
  const x3 = sg.x + padX;
56077
57409
  const y2 = sg.y + padY;
56078
57410
  bgs.push(blockBackground(x3, y2, sg.width, sg.height, 0));
@@ -56110,7 +57442,7 @@ var init_svg_generator = __esm({
56110
57442
  edgeStroke: this.arrowStroke
56111
57443
  });
56112
57444
  const css = `<style>${sharedCss}</style>`;
56113
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
57445
+ 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}">
56114
57446
  ${bg}
56115
57447
  ${css}
56116
57448
  ${elements.join("\n ")}
@@ -56163,13 +57495,17 @@ var init_svg_generator = __esm({
56163
57495
  const stroke = node.style?.stroke ?? void 0;
56164
57496
  const fill = node.style?.fill ?? void 0;
56165
57497
  const styleAttr = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
57498
+ const typed = node.typed;
57499
+ const innerPad = Math.max(0, typed?.padding ?? 10);
56166
57500
  switch (node.shape) {
56167
57501
  case "rectangle":
56168
57502
  shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
56169
57503
  break;
56170
- case "round":
56171
- shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="5" ry="5" />`;
57504
+ case "round": {
57505
+ const rx = Math.max(0, typed?.cornerRadius ?? 5);
57506
+ shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="${rx}" ry="${rx}" />`;
56172
57507
  break;
57508
+ }
56173
57509
  case "stadium":
56174
57510
  const radius = node.height / 2;
56175
57511
  shape = `<rect class="node-shape" ${styleAttr} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="${radius}" ry="${radius}" />`;
@@ -56213,16 +57549,18 @@ var init_svg_generator = __esm({
56213
57549
  }
56214
57550
  case "parallelogram": {
56215
57551
  const skew = node.width * 0.15;
56216
- const points = [
57552
+ const leftLean = typed?.lean === "l";
57553
+ const points = (leftLean ? [
57554
+ `${x3},${y2}`,
57555
+ `${x3 + node.width - skew},${y2}`,
57556
+ `${x3 + node.width},${y2 + node.height}`,
57557
+ `${x3 + skew},${y2 + node.height}`
57558
+ ] : [
56217
57559
  `${x3 + skew},${y2}`,
56218
- // top-left
56219
57560
  `${x3 + node.width},${y2}`,
56220
- // top-right
56221
57561
  `${x3 + node.width - skew},${y2 + node.height}`,
56222
- // bottom-right
56223
57562
  `${x3},${y2 + node.height}`
56224
- // bottom-left
56225
- ].join(" ");
57563
+ ]).join(" ");
56226
57564
  shape = `<polygon class="node-shape" ${styleAttr} points="${points}" />`;
56227
57565
  break;
56228
57566
  }
@@ -56292,11 +57630,33 @@ var init_svg_generator = __esm({
56292
57630
  const s3 = this.buildNodeStyleAttrs({ stroke, strokeWidth, fill });
56293
57631
  shape = `<rect ${s3} x="${x3}" y="${y2}" width="${node.width}" height="${node.height}" rx="0" ry="0" />`;
56294
57632
  }
56295
- const text = this.generateWrappedText(node.label, cx, labelCenterY, node.width - 20);
56296
- return `<g id="${node.id}">
57633
+ const text = this.generateWrappedText(node.label, cx, labelCenterY, node.width - innerPad * 2);
57634
+ let media = "";
57635
+ if (typed?.media?.image) {
57636
+ const iw = Math.min(24, Math.max(12, node.height - 10));
57637
+ const ih = iw;
57638
+ const ix = x3 + 4;
57639
+ const iy = y2 + (node.height - ih) / 2;
57640
+ media = `<image xlink:href="${this.escapeXml(typed.media.image)}" x="${ix}" y="${iy}" width="${iw}" height="${ih}" />`;
57641
+ }
57642
+ const baseGroup = `<g id="${node.id}">
56297
57643
  ${shape}
57644
+ ${media}
56298
57645
  ${text}
56299
57646
  </g>`;
57647
+ const link = node.link;
57648
+ if (link && link.href) {
57649
+ const tt = link.tooltip ? `<title>${this.escapeXml(link.tooltip)}</title>` : "";
57650
+ const tgt = link.target ? ` target="${this.escapeXml(link.target)}" rel="noopener noreferrer"` : "";
57651
+ return `<a xlink:href="${this.escapeXml(link.href)}"${tgt} class="node-link">${tt}${baseGroup}</a>`;
57652
+ }
57653
+ if (link && link.tooltip) {
57654
+ return `<g class="node-call">
57655
+ <title>${this.escapeXml(link.tooltip)}</title>
57656
+ ${baseGroup}
57657
+ </g>`;
57658
+ }
57659
+ return baseGroup;
56300
57660
  }
56301
57661
  generateWrappedText(text, x3, y2, maxWidth) {
56302
57662
  if (text.includes("<")) {
@@ -56534,16 +57894,31 @@ var init_svg_generator = __esm({
56534
57894
  }
56535
57895
  const pathData = pathParts.join(" ");
56536
57896
  let edgeElement = `<path class="edge-path" d="${pathData}" stroke-linecap="round" stroke-linejoin="round"`;
57897
+ const styleStroke = edge.style?.stroke;
57898
+ const styleStrokeWidth = edge.style?.strokeWidth;
57899
+ const styleStrokeOpacity = edge.style?.strokeOpacity;
57900
+ if (edge.dasharray)
57901
+ strokeDasharray = String(edge.dasharray);
57902
+ const anim = edge.animation;
57903
+ if (!strokeDasharray && anim)
57904
+ strokeDasharray = "5 5";
56537
57905
  if (strokeDasharray) {
56538
57906
  edgeElement += ` stroke-dasharray="${strokeDasharray}"`;
56539
57907
  }
56540
- const startMarkUrl = mStart === "arrow" ? "url(#arrow)" : mStart === "circle" ? "url(#circle-marker)" : mStart === "cross" ? "url(#cross-marker)" : "";
56541
- const endMarkUrl = mEnd === "arrow" ? "url(#arrow)" : mEnd === "circle" ? "url(#circle-marker)" : mEnd === "cross" ? "url(#cross-marker)" : markerEnd || "";
56542
- if (startMarkUrl && mStart !== "arrow")
56543
- edgeElement += ` marker-start="${startMarkUrl}"`;
56544
- if (endMarkUrl && mEnd !== "arrow")
56545
- edgeElement += ` marker-end="${endMarkUrl}"`;
56546
- edgeElement += " />";
57908
+ if (styleStrokeWidth != null) {
57909
+ edgeElement += ` stroke-width="${styleStrokeWidth}"`;
57910
+ } else {
57911
+ if (strokeWidth && strokeWidth !== 1.5)
57912
+ edgeElement += ` stroke-width="${strokeWidth}"`;
57913
+ }
57914
+ if (styleStrokeOpacity != null) {
57915
+ edgeElement += ` stroke-opacity="${styleStrokeOpacity}"`;
57916
+ }
57917
+ if (styleStroke) {
57918
+ edgeElement += ` stroke="${styleStroke}"`;
57919
+ }
57920
+ const inlineAnim = anim ? ` style="animation:${anim}"` : "";
57921
+ edgeElement += inlineAnim + " />";
56547
57922
  if (edge.label) {
56548
57923
  const pos = this.pointAtRatio(points, 0.55);
56549
57924
  const text = this.escapeXml(edge.label);
@@ -56564,14 +57939,15 @@ var init_svg_generator = __esm({
56564
57939
  const uyl = vyl / vlenl;
56565
57940
  const nxl = -uyl;
56566
57941
  const nyl = uxl;
56567
- const triLenL = 8;
56568
- const triWL = 6;
57942
+ const ow = styleStrokeWidth != null ? styleStrokeWidth : strokeWidth;
57943
+ const triLenL = Math.max(6, Math.min(14, 6 + (ow - 1.5) * 3));
57944
+ const triWL = Math.max(5, Math.min(12, 5 + (ow - 1.5) * 2.5));
56569
57945
  const p1xL = boundaryEnd.x, p1yL = boundaryEnd.y;
56570
57946
  const baseXL = boundaryEnd.x - uxl * triLenL;
56571
57947
  const baseYL = boundaryEnd.y - uyl * triLenL;
56572
57948
  const p2xL = baseXL + nxl * (triWL / 2), p2yL = baseYL + nyl * (triWL / 2);
56573
57949
  const p3xL = baseXL - nxl * (triWL / 2), p3yL = baseYL - nyl * (triWL / 2);
56574
- overlay2 += triangleAtEnd(prevEndL, boundaryEnd, this.arrowStroke);
57950
+ overlay2 += triangleAtEnd(prevEndL, boundaryEnd, styleStroke || this.arrowStroke, triLenL, triWL);
56575
57951
  if (mStart === "arrow" && points.length >= 2) {
56576
57952
  const firstLeg = points[1];
56577
57953
  const svx = boundaryStart.x - firstLeg.x;
@@ -56583,7 +57959,7 @@ var init_svg_generator = __esm({
56583
57959
  const sny = sux;
56584
57960
  const sbaseX = boundaryStart.x - sux * triLenL;
56585
57961
  const sbaseY = boundaryStart.y - suy * triLenL;
56586
- overlay2 += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
57962
+ overlay2 += triangleAtStart(boundaryStart, firstLeg, styleStroke || this.arrowStroke, triLenL, triWL);
56587
57963
  }
56588
57964
  const pathGroup = `<g>
56589
57965
  ${edgeElement}
@@ -56602,15 +57978,16 @@ var init_svg_generator = __esm({
56602
57978
  const uy = vy / vlen;
56603
57979
  const nx = -uy;
56604
57980
  const ny = ux;
56605
- const triLen = 8;
56606
- const triW = 6;
57981
+ const ow2 = styleStrokeWidth != null ? styleStrokeWidth : strokeWidth;
57982
+ const triLen = Math.max(6, Math.min(14, 6 + (ow2 - 1.5) * 3));
57983
+ const triW = Math.max(5, Math.min(12, 5 + (ow2 - 1.5) * 2.5));
56607
57984
  const p1x = boundaryEnd.x, p1y = boundaryEnd.y;
56608
57985
  const baseX = boundaryEnd.x - ux * triLen;
56609
57986
  const baseY = boundaryEnd.y - uy * triLen;
56610
57987
  const p2x = baseX + nx * (triW / 2), p2y = baseY + ny * (triW / 2);
56611
57988
  const p3x = baseX - nx * (triW / 2), p3y = baseY - ny * (triW / 2);
56612
57989
  if (mEnd === "arrow")
56613
- overlay += triangleAtEnd(prevEnd, boundaryEnd, this.arrowStroke);
57990
+ overlay += triangleAtEnd(prevEnd, boundaryEnd, styleStroke || this.arrowStroke, triLen, triW);
56614
57991
  if (mStart === "arrow" && points.length >= 2) {
56615
57992
  const firstLeg = points[1];
56616
57993
  const svx = boundaryStart.x - firstLeg.x;
@@ -56620,8 +57997,19 @@ var init_svg_generator = __esm({
56620
57997
  const suy = svy / slen;
56621
57998
  const snx = -suy;
56622
57999
  const sny = sux;
56623
- overlay += triangleAtStart(boundaryStart, firstLeg, this.arrowStroke);
56624
- }
58000
+ overlay += triangleAtStart(boundaryStart, firstLeg, styleStroke || this.arrowStroke, triLen, triW);
58001
+ }
58002
+ const owStroke = styleStroke || this.arrowStroke;
58003
+ const addCircle = (at2) => `<circle cx="${at2.x}" cy="${at2.y}" r="4.5" fill="none" stroke="${owStroke}" stroke-width="${ow2}" />`;
58004
+ 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>`;
58005
+ if (mEnd === "circle")
58006
+ overlay += addCircle(boundaryEnd);
58007
+ if (mEnd === "cross")
58008
+ overlay += addCross(boundaryEnd);
58009
+ if (mStart === "circle")
58010
+ overlay += addCircle(boundaryStart);
58011
+ if (mStart === "cross")
58012
+ overlay += addCross(boundaryStart);
56625
58013
  if (overlay) {
56626
58014
  const grouped = `<g>${edgeElement}
56627
58015
  ${overlay}</g>`;
@@ -56747,6 +58135,16 @@ ${overlay}</g>`;
56747
58135
  { x: node.x, y: node.y + node.height }
56748
58136
  ];
56749
58137
  switch (shape) {
58138
+ case "round": {
58139
+ const poly = [
58140
+ { x: node.x, y: node.y },
58141
+ { x: node.x + node.width, y: node.y },
58142
+ { x: node.x + node.width, y: node.y + node.height },
58143
+ { x: node.x, y: node.y + node.height }
58144
+ ];
58145
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58146
+ return hit || this.nearestPointOnPolygon(p22, poly);
58147
+ }
56750
58148
  case "circle": {
56751
58149
  const cx = node.x + node.width / 2;
56752
58150
  const cy = node.y + node.height / 2;
@@ -56757,7 +58155,8 @@ ${overlay}</g>`;
56757
58155
  const cx = node.x + node.width / 2;
56758
58156
  const cy = node.y + node.height / 2;
56759
58157
  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 }];
56760
- return this.linePolygonIntersection(p1, p22, poly);
58158
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58159
+ return hit || this.nearestPointOnPolygon(p22, poly);
56761
58160
  }
56762
58161
  case "hexagon": {
56763
58162
  const s3 = Math.max(10, node.width * 0.2);
@@ -56769,7 +58168,8 @@ ${overlay}</g>`;
56769
58168
  { x: node.x + s3, y: node.y + node.height },
56770
58169
  { x: node.x, y: node.y + node.height / 2 }
56771
58170
  ];
56772
- return this.linePolygonIntersection(p1, p22, poly);
58171
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58172
+ return hit || this.nearestPointOnPolygon(p22, poly);
56773
58173
  }
56774
58174
  case "parallelogram": {
56775
58175
  const o3 = Math.min(node.width * 0.25, node.height * 0.6);
@@ -56779,7 +58179,8 @@ ${overlay}</g>`;
56779
58179
  { x: node.x + node.width - o3, y: node.y + node.height },
56780
58180
  { x: node.x, y: node.y + node.height }
56781
58181
  ];
56782
- return this.linePolygonIntersection(p1, p22, poly);
58182
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58183
+ return hit || this.nearestPointOnPolygon(p22, poly);
56783
58184
  }
56784
58185
  case "trapezoid": {
56785
58186
  const o3 = Math.min(node.width * 0.2, node.height * 0.5);
@@ -56789,7 +58190,8 @@ ${overlay}</g>`;
56789
58190
  { x: node.x + node.width, y: node.y + node.height },
56790
58191
  { x: node.x, y: node.y + node.height }
56791
58192
  ];
56792
- return this.linePolygonIntersection(p1, p22, poly);
58193
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58194
+ return hit || this.nearestPointOnPolygon(p22, poly);
56793
58195
  }
56794
58196
  case "trapezoidAlt": {
56795
58197
  const o3 = Math.min(node.width * 0.2, node.height * 0.5);
@@ -56799,7 +58201,8 @@ ${overlay}</g>`;
56799
58201
  { x: node.x + node.width - o3, y: node.y + node.height },
56800
58202
  { x: node.x + o3, y: node.y + node.height }
56801
58203
  ];
56802
- return this.linePolygonIntersection(p1, p22, poly);
58204
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58205
+ return hit || this.nearestPointOnPolygon(p22, poly);
56803
58206
  }
56804
58207
  case "stadium": {
56805
58208
  const r3 = Math.min(node.height / 2, node.width / 2);
@@ -56827,10 +58230,13 @@ ${overlay}</g>`;
56827
58230
  }
56828
58231
  return best;
56829
58232
  };
56830
- return pick(left, right);
58233
+ const hit = pick(left, right);
58234
+ return hit || this.nearestPointOnPolygon(p22, rect);
56831
58235
  }
56832
58236
  default: {
56833
- return this.linePolygonIntersection(p1, p22, rectPoly());
58237
+ const poly = rectPoly();
58238
+ const hit = this.linePolygonIntersection(p1, p22, poly);
58239
+ return hit || this.nearestPointOnPolygon(p22, poly);
56834
58240
  }
56835
58241
  }
56836
58242
  }
@@ -56870,6 +58276,30 @@ ${overlay}</g>`;
56870
58276
  }
56871
58277
  return best;
56872
58278
  }
58279
+ // Fallback helpers when lines are colinear or miss due to smoothing
58280
+ nearestPointOnSegment(p3, a3, b3) {
58281
+ const abx = b3.x - a3.x, aby = b3.y - a3.y;
58282
+ const ab2 = abx * abx + aby * aby || 1;
58283
+ const apx = p3.x - a3.x, apy = p3.y - a3.y;
58284
+ let t3 = (apx * abx + apy * aby) / ab2;
58285
+ t3 = Math.max(0, Math.min(1, t3));
58286
+ return { x: a3.x + abx * t3, y: a3.y + aby * t3 };
58287
+ }
58288
+ nearestPointOnPolygon(to, poly) {
58289
+ let best = poly[0];
58290
+ let bestD = Infinity;
58291
+ for (let i3 = 0; i3 < poly.length; i3++) {
58292
+ const a3 = poly[i3];
58293
+ const b3 = poly[(i3 + 1) % poly.length];
58294
+ const p3 = this.nearestPointOnSegment(to, a3, b3);
58295
+ const d3 = (p3.x - to.x) * (p3.x - to.x) + (p3.y - to.y) * (p3.y - to.y);
58296
+ if (d3 < bestD) {
58297
+ bestD = d3;
58298
+ best = p3;
58299
+ }
58300
+ }
58301
+ return { x: best.x, y: best.y };
58302
+ }
56873
58303
  segmentIntersection(p3, p22, q3, q22) {
56874
58304
  const r3 = { x: p22.x - p3.x, y: p22.y - p3.y };
56875
58305
  const s3 = { x: q22.x - q3.x, y: q22.y - q3.y };
@@ -57124,16 +58554,15 @@ var init_pie_renderer = __esm({
57124
58554
  }
57125
58555
  });
57126
58556
 
57127
- // node_modules/@probelabs/maid/out/renderer/sequence-builder.js
58557
+ // node_modules/@probelabs/maid/out/diagrams/sequence/cst-utils.js
57128
58558
  function textFromTokens(tokens) {
57129
58559
  if (!tokens || tokens.length === 0)
57130
58560
  return "";
57131
58561
  const parts = [];
57132
58562
  for (const t3 of tokens) {
57133
- const img = t3.image;
57134
- if (!img)
57135
- continue;
57136
- if (t3.tokenType && t3.tokenType.name === "QuotedString") {
58563
+ const img = t3.image ?? "";
58564
+ const name14 = t3.tokenType?.name;
58565
+ if (name14 === "QuotedString") {
57137
58566
  if (img.startsWith('"') && img.endsWith('"'))
57138
58567
  parts.push(img.slice(1, -1));
57139
58568
  else if (img.startsWith("'") && img.endsWith("'"))
@@ -57147,6 +58576,8 @@ function textFromTokens(tokens) {
57147
58576
  return parts.join(" ").replace(/\s+/g, " ").trim();
57148
58577
  }
57149
58578
  function actorRefToText(refCst) {
58579
+ if (!refCst)
58580
+ return "";
57150
58581
  const ch = refCst.children || {};
57151
58582
  const toks = [];
57152
58583
  ["Identifier", "QuotedString", "NumberLiteral", "Text"].forEach((k3) => {
@@ -57171,39 +58602,20 @@ function lineRemainderToText(lineRem) {
57171
58602
  "Comma",
57172
58603
  "Colon",
57173
58604
  "LParen",
57174
- "RParen",
57175
- "AndKeyword",
57176
- "ElseKeyword",
57177
- "OptKeyword",
57178
- "OptionKeyword",
57179
- "LoopKeyword",
57180
- "ParKeyword",
57181
- "RectKeyword",
57182
- "CriticalKeyword",
57183
- "BreakKeyword",
57184
- "BoxKeyword",
57185
- "EndKeyword",
57186
- "NoteKeyword",
57187
- "LeftKeyword",
57188
- "RightKeyword",
57189
- "OverKeyword",
57190
- "OfKeyword",
57191
- "AutonumberKeyword",
57192
- "OffKeyword",
57193
- "LinkKeyword",
57194
- "LinksKeyword",
57195
- "CreateKeyword",
57196
- "DestroyKeyword",
57197
- "ParticipantKeyword",
57198
- "ActorKeyword",
57199
- "ActivateKeyword",
57200
- "DeactivateKeyword"
58605
+ "RParen"
57201
58606
  ];
57202
58607
  for (const k3 of order)
57203
58608
  ch[k3]?.forEach((t3) => toks.push(t3));
57204
58609
  toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
57205
- return textFromTokens(toks) || void 0;
58610
+ const txt = textFromTokens(toks);
58611
+ return txt || void 0;
57206
58612
  }
58613
+ var init_cst_utils = __esm({
58614
+ "node_modules/@probelabs/maid/out/diagrams/sequence/cst-utils.js"() {
58615
+ }
58616
+ });
58617
+
58618
+ // node_modules/@probelabs/maid/out/renderer/sequence-builder.js
57207
58619
  function canonicalId(raw) {
57208
58620
  const t3 = raw.trim().replace(/\s+/g, "_");
57209
58621
  return t3;
@@ -57250,11 +58662,26 @@ function buildSequenceModel(text) {
57250
58662
  const byDisplay = /* @__PURE__ */ new Map();
57251
58663
  const events = [];
57252
58664
  let autonumber = { on: false };
58665
+ let title;
58666
+ let accTitle;
58667
+ let accDescr;
57253
58668
  const diagramChildren = cst.children || {};
57254
58669
  const lines = diagramChildren.line || [];
57255
58670
  const openBlocks = [];
57256
58671
  function processLineNode(ln) {
57257
58672
  const ch = ln.children || {};
58673
+ if (ch.metaStmt) {
58674
+ const m3 = ch.metaStmt[0];
58675
+ const mch = m3.children || {};
58676
+ const value = lineRemainderToText(mch.lineRemainder?.[0]) || "";
58677
+ if (mch.TitleKeyword)
58678
+ title = value;
58679
+ if (mch.AccTitleKeyword)
58680
+ accTitle = value;
58681
+ if (mch.AccDescrKeyword)
58682
+ accDescr = value;
58683
+ return;
58684
+ }
57258
58685
  if (ch.participantDecl) {
57259
58686
  const decl = ch.participantDecl[0];
57260
58687
  const dch = decl.children || {};
@@ -57353,8 +58780,8 @@ function buildSequenceModel(text) {
57353
58780
  handledBlock = true;
57354
58781
  const bnode = ch[spec.key][0];
57355
58782
  const bch = bnode.children || {};
57356
- const title = lineRemainderToText(bch.lineRemainder?.[0]);
57357
- const block = { type: spec.type, title, branches: spec.branchKeys ? [] : void 0 };
58783
+ const title2 = lineRemainderToText(bch.lineRemainder?.[0]);
58784
+ const block = { type: spec.type, title: title2, branches: spec.branchKeys ? [] : void 0 };
57358
58785
  openBlocks.push(block);
57359
58786
  events.push({ kind: "block-start", block });
57360
58787
  if (spec.branchKeys) {
@@ -57365,8 +58792,8 @@ function buildSequenceModel(text) {
57365
58792
  if (branchTokArr && branchTokArr.length) {
57366
58793
  const lr = (lrArr || []).slice(1);
57367
58794
  for (let i3 = 0; i3 < branchTokArr.length; i3++) {
57368
- const title2 = lr[i3] ? lineRemainderToText(lr[i3]) : void 0;
57369
- const br = { kind: spec.branchKeys[0].kind, title: title2 };
58795
+ const title22 = lr[i3] ? lineRemainderToText(lr[i3]) : void 0;
58796
+ const br = { kind: spec.branchKeys[0].kind, title: title22 };
57370
58797
  block.branches.push(br);
57371
58798
  events.push({ kind: "block-branch", block, branch: br });
57372
58799
  }
@@ -57426,13 +58853,17 @@ function buildSequenceModel(text) {
57426
58853
  return {
57427
58854
  participants: Array.from(participantsMap.values()),
57428
58855
  events,
57429
- autonumber: autonumber.on === true || autonumber.on === false ? autonumber : { on: false }
58856
+ autonumber: autonumber.on === true || autonumber.on === false ? autonumber : { on: false },
58857
+ title,
58858
+ accTitle,
58859
+ accDescr
57430
58860
  };
57431
58861
  }
57432
58862
  var init_sequence_builder = __esm({
57433
58863
  "node_modules/@probelabs/maid/out/renderer/sequence-builder.js"() {
57434
58864
  init_lexer4();
57435
58865
  init_parser4();
58866
+ init_cst_utils();
57436
58867
  }
57437
58868
  });
57438
58869
 
@@ -57528,7 +58959,7 @@ function layoutSequence(model) {
57528
58959
  if (start != null) {
57529
58960
  const p3 = col.get(actor);
57530
58961
  if (p3) {
57531
- activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(r3) - yForRow(start) });
58962
+ activations.push({ actor, x: p3.x + p3.width / 2 - 3, y: yForRow(start) - ROW_H / 2, width: 6, height: yForRow(r3) - yForRow(start) });
57532
58963
  }
57533
58964
  }
57534
58965
  actStack.set(actor, arr);
@@ -57638,7 +59069,7 @@ function layoutSequence(model) {
57638
59069
  const start = arr.pop();
57639
59070
  const p3 = col.get(actor);
57640
59071
  if (p3)
57641
- activations.push({ actor, x: p3.x + p3.width / 2 - 4, y: yForRow(start) - ROW_H / 2, width: 8, height: yForRow(lastRow) - yForRow(start) });
59072
+ activations.push({ actor, x: p3.x + p3.width / 2 - 3, y: yForRow(start) - ROW_H / 2, width: 6, height: yForRow(lastRow) - yForRow(start) });
57642
59073
  }
57643
59074
  }
57644
59075
  return { width, height, participants, lifelines, messages, notes, blocks, activations };
@@ -57650,14 +59081,14 @@ var init_sequence_layout = __esm({
57650
59081
  MARGIN_X = 24;
57651
59082
  MARGIN_Y = 24;
57652
59083
  ACTOR_FONT_SIZE = 16;
57653
- ACTOR_H = 32;
59084
+ ACTOR_H = 30;
57654
59085
  LIFELINE_GAP = 4;
57655
59086
  ACTOR_PAD_X = 12;
57656
59087
  COL_MIN = 110;
57657
59088
  ROW_H = 36;
57658
59089
  NOTE_W = 160;
57659
59090
  NOTE_PAD = 8;
57660
- BLOCK_PAD = 8;
59091
+ BLOCK_PAD = 12;
57661
59092
  TITLE_EXTRA_TOP = 12;
57662
59093
  }
57663
59094
  });
@@ -57677,6 +59108,18 @@ function renderSequence(model, opts = {}) {
57677
59108
  edgeStroke: "#555555"
57678
59109
  });
57679
59110
  svgParts.push(` <style>${sharedCss}</style>`);
59111
+ const accTitle = model.accTitle || model.title || void 0;
59112
+ const accDesc = model.accDescr || void 0;
59113
+ if (accTitle)
59114
+ svgParts.push(` <title>${escapeXml(accTitle)}</title>`);
59115
+ if (accDesc)
59116
+ svgParts.push(` <desc>${escapeXml(accDesc)}</desc>`);
59117
+ if (model.title) {
59118
+ const t3 = escapeXml(model.title);
59119
+ const tW = Math.max(20, measureText(model.title, 16));
59120
+ const xMid = width / 2;
59121
+ svgParts.push(` <text class="node-label" x="${xMid}" y="0" text-anchor="middle" font-size="16">${t3}</text>`);
59122
+ }
57680
59123
  for (const p3 of layout.participants)
57681
59124
  drawParticipant(svgParts, p3);
57682
59125
  for (const b3 of layout.blocks)
@@ -57700,14 +59143,14 @@ function renderSequence(model, opts = {}) {
57700
59143
  for (const b3 of layout.blocks) {
57701
59144
  const title = b3.title ? `${b3.type}: ${b3.title}` : b3.type;
57702
59145
  const branches = (b3.branches || []).map((br) => ({ y: br.y, title: br.title }));
57703
- svgParts.push(blockOverlay(b3.x, b3.y, b3.width, b3.height, title, branches, 0, "left", "left", 0));
59146
+ 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));
57704
59147
  }
57705
59148
  for (const p3 of layout.participants)
57706
59149
  drawParticipantBottom(svgParts, p3, layout);
57707
59150
  svgParts.push("</svg>");
57708
59151
  let svg = svgParts.join("\n");
57709
59152
  if (opts.theme)
57710
- svg = applySequenceTheme(svg, opts.theme);
59153
+ svg = applySequenceTheme(applyFlowLikeTheme(svg, opts.theme), opts.theme);
57711
59154
  return svg;
57712
59155
  }
57713
59156
  function drawParticipant(out, p3) {
@@ -57731,9 +59174,9 @@ function drawMessage(out, m3) {
57731
59174
  const start = { x: x1, y: y2 };
57732
59175
  const end = { x: x22, y: y2 };
57733
59176
  if (m3.endMarker === "arrow")
57734
- out.push(" " + triangleAtEnd(start, end));
59177
+ out.push(" " + triangleAtEnd(start, end, void 0, 9, 7));
57735
59178
  if (m3.startMarker === "arrow")
57736
- out.push(" " + triangleAtStart(start, end));
59179
+ out.push(" " + triangleAtStart(start, end, void 0, 9, 7));
57737
59180
  if (m3.endMarker === "open")
57738
59181
  out.push(` <circle class="openhead" cx="${x22}" cy="${y2}" r="4" />`);
57739
59182
  if (m3.startMarker === "open")
@@ -57757,8 +59200,8 @@ function drawMessageLabel(out, m3, label, _counter) {
57757
59200
  const h3 = 16;
57758
59201
  const w3 = Math.max(20, measureText(label, 12) + 10);
57759
59202
  const x3 = xMid - w3 / 2;
57760
- const y2 = m3.y - 10 - h3 / 2;
57761
- out.push(` <rect class="msg-label-bg" x="${x3}" y="${y2}" width="${w3}" height="${h3}" rx="0"/>`);
59203
+ const y2 = m3.y - 14 - h3 / 2;
59204
+ out.push(` <rect class="msg-label-bg" x="${x3}" y="${y2}" width="${w3}" height="${h3}" rx="3"/>`);
57762
59205
  out.push(` <text class="msg-label" x="${xMid}" y="${y2 + h3 / 2}" text-anchor="middle">${escapeXml(label)}</text>`);
57763
59206
  }
57764
59207
  function drawNote(out, n3) {
@@ -57769,18 +59212,12 @@ function drawNote(out, n3) {
57769
59212
  }
57770
59213
  function applySequenceTheme(svg, theme) {
57771
59214
  let out = svg;
57772
- if (theme.actorBkg)
57773
- out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorBkg)};`));
57774
- if (theme.actorBorder)
57775
- out = out.replace(/\.actor-rect\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.actorBorder)};`));
57776
- if (theme.actorTextColor)
57777
- out = out.replace(/\.actor-label\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.actorTextColor)};`));
57778
59215
  if (theme.lifelineColor)
57779
59216
  out = out.replace(/\.lifeline\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lifelineColor)};`));
57780
59217
  if (theme.lineColor)
57781
59218
  out = out.replace(/\.msg-line\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.lineColor)};`));
57782
59219
  if (theme.arrowheadColor) {
57783
- out = out.replace(/\.arrowhead\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.arrowheadColor)};`));
59220
+ out = out.replace(/(<path d=\"M[0-9.,\s-]+Z\" fill=\")[^\"]+(\")/g, (_m2, p1, p22) => `${p1}${String(theme.arrowheadColor)}${p22}`);
57784
59221
  out = out.replace(/\.openhead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57785
59222
  out = out.replace(/\.crosshead\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.arrowheadColor)};`));
57786
59223
  }
@@ -57806,6 +59243,329 @@ var init_sequence_renderer = __esm({
57806
59243
  }
57807
59244
  });
57808
59245
 
59246
+ // node_modules/@probelabs/maid/out/renderer/state-builder.js
59247
+ function textFromTokens2(tokens) {
59248
+ if (!tokens || tokens.length === 0)
59249
+ return "";
59250
+ const parts = [];
59251
+ for (const t3 of tokens) {
59252
+ const img = t3.image ?? "";
59253
+ if (t3.tokenType && t3.tokenType.name === "QuotedString") {
59254
+ if (img.startsWith('"') && img.endsWith('"'))
59255
+ parts.push(img.slice(1, -1));
59256
+ else if (img.startsWith("'") && img.endsWith("'"))
59257
+ parts.push(img.slice(1, -1));
59258
+ else
59259
+ parts.push(img);
59260
+ } else {
59261
+ parts.push(img);
59262
+ }
59263
+ }
59264
+ return parts.join(" ").replace(/\s+/g, " ").trim();
59265
+ }
59266
+ function actorRefToId(ref, ctx = {}) {
59267
+ if (!ref)
59268
+ return { id: "", kind: "simple" };
59269
+ const ch = ref.children || {};
59270
+ if (ch.Start) {
59271
+ const kind = ctx.isTarget ? "end" : "start";
59272
+ return { id: `__${kind}_${ch.Start[0].startOffset ?? 0}`, kind };
59273
+ }
59274
+ if (ch.HistoryDeep)
59275
+ return { id: `__histdeep_${ch.HistoryDeep[0].startOffset ?? 0}`, label: "H*", kind: "history-deep" };
59276
+ if (ch.HistoryShallow)
59277
+ return { id: `__hist_${ch.HistoryShallow[0].startOffset ?? 0}`, label: "H", kind: "history" };
59278
+ let special;
59279
+ if (ch.AngleAngleOpen && ch.Identifier && ch.AngleAngleClose) {
59280
+ const k3 = String(ch.Identifier[0].image).toLowerCase();
59281
+ if (k3 === "choice")
59282
+ special = "choice";
59283
+ else if (k3 === "fork")
59284
+ special = "fork";
59285
+ else if (k3 === "join")
59286
+ special = "join";
59287
+ }
59288
+ const toks = [];
59289
+ ch.Identifier?.forEach((t3) => toks.push(t3));
59290
+ ch.QuotedString?.forEach((t3) => toks.push(t3));
59291
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59292
+ const txt = textFromTokens2(toks) || "";
59293
+ const id = txt.trim().replace(/\s+/g, "_");
59294
+ return { id, label: txt, kind: special || "simple" };
59295
+ }
59296
+ function buildStateModel(text) {
59297
+ const { tokens } = tokenize5(text);
59298
+ parserInstance5.input = tokens;
59299
+ const cst = parserInstance5.diagram();
59300
+ let direction = "TD";
59301
+ const nodes = /* @__PURE__ */ new Map();
59302
+ const transitions = [];
59303
+ const composites = [];
59304
+ const lanes = [];
59305
+ const stack = [];
59306
+ const diagramChildren = cst.children || {};
59307
+ const stmts = diagramChildren.statement || [];
59308
+ function ensureNode(def) {
59309
+ const ex = nodes.get(def.id);
59310
+ if (ex)
59311
+ return ex;
59312
+ nodes.set(def.id, def);
59313
+ const parentCtx = stack[stack.length - 1];
59314
+ if (parentCtx) {
59315
+ const parent = parentCtx.id;
59316
+ const laneId = `${parent}__lane${parentCtx.lane}`;
59317
+ let laneSg = composites.find((c3) => c3.id === laneId);
59318
+ if (!laneSg) {
59319
+ if (!composites.find((c3) => c3.id === parent))
59320
+ composites.push({ id: parent, label: parent, nodes: [], parent: stack.length > 1 ? stack[stack.length - 2].id : void 0 });
59321
+ composites.push({ id: laneId, label: void 0, nodes: [], parent });
59322
+ lanes.push({ parentId: parent, id: laneId, nodes: [] });
59323
+ }
59324
+ laneSg = composites.find((c3) => c3.id === laneId);
59325
+ if (!laneSg.nodes.includes(def.id))
59326
+ laneSg.nodes.push(def.id);
59327
+ const laneRec = lanes.find((l3) => l3.id === laneId);
59328
+ if (laneRec && !laneRec.nodes.includes(def.id))
59329
+ laneRec.nodes.push(def.id);
59330
+ def.parent = laneId;
59331
+ }
59332
+ return def;
59333
+ }
59334
+ function visitStatement(node) {
59335
+ const ch = node.children || {};
59336
+ if (ch.directionStmt) {
59337
+ const d3 = ch.directionStmt[0].children.Direction?.[0]?.image || "TD";
59338
+ direction = d3;
59339
+ return;
59340
+ }
59341
+ if (ch.stateDecl) {
59342
+ const n3 = ch.stateDecl[0];
59343
+ const dch = n3.children || {};
59344
+ if (dch.QuotedString && dch.AsKw && dch.Identifier) {
59345
+ const label = dch.QuotedString[0].image.slice(1, -1);
59346
+ const id = dch.Identifier[0].image;
59347
+ ensureNode({ id, label, kind: "simple" });
59348
+ } else if (dch.Identifier) {
59349
+ const id = dch.Identifier[0].image;
59350
+ ensureNode({ id, label: id, kind: "simple" });
59351
+ }
59352
+ return;
59353
+ }
59354
+ if (ch.stateBlock) {
59355
+ const b3 = ch.stateBlock[0];
59356
+ const bch = b3.children || {};
59357
+ const idTok = bch.Identifier?.[0] || bch.QuotedString?.[0];
59358
+ const idRaw = idTok ? idTok.image.startsWith('"') ? idTok.image.slice(1, -1) : idTok.image : `__state_${b3.location ?? Math.random()}`;
59359
+ const id = idRaw.replace(/\s+/g, "_");
59360
+ ensureNode({ id, label: idRaw, kind: "composite" });
59361
+ if (!composites.find((c3) => c3.id === id))
59362
+ composites.push({ id, label: idRaw, nodes: [], parent: stack.length ? stack[stack.length - 1].id : void 0 });
59363
+ stack.push({ id, lane: 0 });
59364
+ const inner = bch.innerStatement || [];
59365
+ for (const s3 of inner)
59366
+ visitStatement(s3);
59367
+ stack.pop();
59368
+ return;
59369
+ }
59370
+ if (ch.transitionStmt) {
59371
+ const t3 = ch.transitionStmt[0];
59372
+ const tch = t3.children || {};
59373
+ const left = actorRefToId(tch.actorRef?.[0], { isTarget: false });
59374
+ const right = actorRefToId(tch.actorRef?.[1], { isTarget: true });
59375
+ if (left.id)
59376
+ ensureNode({ id: left.id, label: left.label || left.id, kind: left.kind });
59377
+ if (right.id)
59378
+ ensureNode({ id: right.id, label: right.label || right.id, kind: right.kind });
59379
+ let label;
59380
+ if (tch.Colon && tch.labelText) {
59381
+ const toks = [];
59382
+ tch.labelText.forEach((lt) => {
59383
+ const ch2 = lt.children || {};
59384
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => ch2[k3]?.forEach((tt) => toks.push(tt)));
59385
+ });
59386
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59387
+ label = textFromTokens2(toks);
59388
+ }
59389
+ if (left.id && right.id)
59390
+ transitions.push({ source: left.id, target: right.id, label });
59391
+ return;
59392
+ }
59393
+ if (node.name === "innerStatement") {
59394
+ const ich = node.children || {};
59395
+ if (ich.Dashes && ich.Dashes.length && stack.length) {
59396
+ stack[stack.length - 1].lane += 1;
59397
+ return;
59398
+ }
59399
+ }
59400
+ if (ch.noteStmt) {
59401
+ const n3 = ch.noteStmt[0];
59402
+ const nch = n3.children || {};
59403
+ const txtToks = [];
59404
+ const targetRef = nch.actorRef?.[0];
59405
+ const target = actorRefToId(targetRef);
59406
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => nch[k3]?.forEach((tk) => txtToks.push(tk)));
59407
+ const text2 = textFromTokens2(txtToks);
59408
+ if (target.id && text2) {
59409
+ const noteId = `__note_${(n3.location ?? Math.random()).toString().slice(2)}`;
59410
+ ensureNode({ id: noteId, label: text2, kind: "simple" });
59411
+ ensureNode({ id: target.id, label: target.label || target.id, kind: target.kind });
59412
+ transitions.push({ source: noteId, target: target.id, label: void 0 });
59413
+ }
59414
+ return;
59415
+ }
59416
+ if (ch.stateDescriptionStmt) {
59417
+ const s3 = ch.stateDescriptionStmt[0];
59418
+ const sch = s3.children || {};
59419
+ const nameTok = sch.Identifier?.[0] || sch.QuotedString?.[0];
59420
+ if (nameTok) {
59421
+ const raw = nameTok.image.startsWith('"') ? nameTok.image.slice(1, -1) : nameTok.image;
59422
+ const id = raw.replace(/\s+/g, "_");
59423
+ const labelToks = [];
59424
+ ["QuotedString", "Identifier", "NumberLiteral", "LabelChunk"].forEach((k3) => sch[k3]?.forEach((tt) => labelToks.push(tt)));
59425
+ const lbl = textFromTokens2(labelToks);
59426
+ ensureNode({ id, label: lbl || raw, kind: "simple" });
59427
+ }
59428
+ return;
59429
+ }
59430
+ for (const key of Object.keys(ch)) {
59431
+ const arr = ch[key];
59432
+ if (Array.isArray(arr))
59433
+ arr.forEach((n3) => visitStatement(n3));
59434
+ }
59435
+ }
59436
+ for (const st of stmts)
59437
+ visitStatement(st);
59438
+ return {
59439
+ direction,
59440
+ nodes: Array.from(nodes.values()),
59441
+ transitions,
59442
+ composites,
59443
+ lanes
59444
+ };
59445
+ }
59446
+ var init_state_builder = __esm({
59447
+ "node_modules/@probelabs/maid/out/renderer/state-builder.js"() {
59448
+ init_lexer6();
59449
+ init_parser6();
59450
+ }
59451
+ });
59452
+
59453
+ // node_modules/@probelabs/maid/out/renderer/state-renderer.js
59454
+ function toGraph(model) {
59455
+ const nodes = [];
59456
+ const edges = [];
59457
+ const subgraphs = [];
59458
+ for (const s3 of model.nodes) {
59459
+ let shape = "rectangle";
59460
+ let label = s3.label || s3.id;
59461
+ if (s3.kind === "start") {
59462
+ shape = "circle";
59463
+ label = "";
59464
+ } else if (s3.kind === "end") {
59465
+ shape = "circle";
59466
+ label = "";
59467
+ } else if (s3.kind === "history") {
59468
+ shape = "circle";
59469
+ label = "H";
59470
+ } else if (s3.kind === "history-deep") {
59471
+ shape = "circle";
59472
+ label = "H*";
59473
+ } else if (s3.kind === "choice") {
59474
+ shape = "diamond";
59475
+ } else if (s3.kind === "fork" || s3.kind === "join") {
59476
+ shape = "rectangle";
59477
+ }
59478
+ const node = { id: s3.id, label, shape };
59479
+ if (s3.kind === "fork" || s3.kind === "join") {
59480
+ node.width = 80;
59481
+ node.height = 8;
59482
+ }
59483
+ nodes.push(node);
59484
+ }
59485
+ for (const t3 of model.transitions) {
59486
+ 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" });
59487
+ }
59488
+ for (const c3 of model.composites) {
59489
+ subgraphs.push({ id: c3.id, label: c3.label, nodes: c3.nodes, parent: c3.parent });
59490
+ }
59491
+ const laneGroups = (model.lanes || []).slice();
59492
+ return { graph: { nodes, edges, subgraphs, direction: model.direction }, laneGroups };
59493
+ }
59494
+ function renderState(model) {
59495
+ var _a16;
59496
+ const { graph, laneGroups } = toGraph(model);
59497
+ const layout = new DagreLayoutEngine().layout(graph);
59498
+ let svg = new SVGRenderer().render(layout);
59499
+ const byId = Object.fromEntries(layout.nodes.map((n3) => [n3.id, { x: n3.x, y: n3.y, width: n3.width, height: n3.height }]));
59500
+ 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 }]));
59501
+ const overlays = [];
59502
+ const groupByParent = {};
59503
+ for (const lg of laneGroups) {
59504
+ const parent = subById[lg.parentId];
59505
+ if (!parent)
59506
+ continue;
59507
+ const members = lg.nodes.map((id) => byId[id]).filter(Boolean);
59508
+ if (!members.length)
59509
+ continue;
59510
+ (groupByParent[_a16 = lg.parentId] || (groupByParent[_a16] = [])).push({ id: lg.id, nodes: members });
59511
+ }
59512
+ const laneIndex = (id) => {
59513
+ const m3 = /(.*)__lane(\d+)/.exec(id);
59514
+ return m3 ? parseInt(m3[2], 10) : Number.POSITIVE_INFINITY;
59515
+ };
59516
+ for (const pid of Object.keys(groupByParent)) {
59517
+ const parent = subById[pid];
59518
+ if (!parent)
59519
+ continue;
59520
+ const lanes = groupByParent[pid].slice();
59521
+ if (lanes.every((l3) => /__lane\d+/.test(l3.id)))
59522
+ lanes.sort((a3, b3) => laneIndex(a3.id) - laneIndex(b3.id));
59523
+ else if (graph.direction === "LR" || graph.direction === "RL")
59524
+ lanes.sort((a3, b3) => Math.min(...a3.nodes.map((n3) => n3.x)) - Math.min(...b3.nodes.map((n3) => n3.x)));
59525
+ else
59526
+ lanes.sort((a3, b3) => Math.min(...a3.nodes.map((n3) => n3.y)) - Math.min(...b3.nodes.map((n3) => n3.y)));
59527
+ for (let i3 = 1; i3 < lanes.length; i3++) {
59528
+ const prev = lanes[i3 - 1];
59529
+ const next = lanes[i3];
59530
+ if (graph.direction === "LR" || graph.direction === "RL") {
59531
+ const prevMaxX = Math.max(...prev.nodes.map((n3) => n3.x + n3.width));
59532
+ const nextMinX = Math.min(...next.nodes.map((n3) => n3.x));
59533
+ const x3 = Math.max(parent.x, Math.min(parent.x + parent.width, (prevMaxX + nextMinX) / 2));
59534
+ overlays.push(`<line class="lane-divider" x1="${x3}" y1="${parent.y + 14}" x2="${x3}" y2="${parent.y + parent.height}" />`);
59535
+ } else {
59536
+ const prevMaxY = Math.max(...prev.nodes.map((n3) => n3.y + n3.height));
59537
+ const nextMinY = Math.min(...next.nodes.map((n3) => n3.y));
59538
+ const y2 = Math.max(parent.y + 14, Math.min(parent.y + parent.height, (prevMaxY + nextMinY) / 2));
59539
+ overlays.push(`<line class="lane-divider" x1="${parent.x}" y1="${y2}" x2="${parent.x + parent.width}" y2="${y2}" />`);
59540
+ }
59541
+ }
59542
+ }
59543
+ for (const n3 of layout.nodes) {
59544
+ const src = (model.nodes || []).find((nn) => nn.id === n3.id);
59545
+ if (!src || src.kind !== "end")
59546
+ continue;
59547
+ const cx = n3.x + n3.width / 2;
59548
+ const cy = n3.y + n3.height / 2;
59549
+ const r3 = Math.max(1, Math.min(n3.width, n3.height) / 2 - 3);
59550
+ overlays.push(`<circle class="end-double" cx="${cx}" cy="${cy}" r="${r3}" fill="none" />`);
59551
+ }
59552
+ if (overlays.length) {
59553
+ svg = svg.replace("</svg>", `<g class="state-overlays">${overlays.join("\n")}</g></svg>`);
59554
+ }
59555
+ if (!/<style>/.test(svg)) {
59556
+ const css = buildSharedCss();
59557
+ svg = svg.replace("<svg ", `<svg `).replace("</svg>", `<style>${css}</style></svg>`);
59558
+ }
59559
+ return svg;
59560
+ }
59561
+ var init_state_renderer = __esm({
59562
+ "node_modules/@probelabs/maid/out/renderer/state-renderer.js"() {
59563
+ init_layout();
59564
+ init_svg_generator();
59565
+ init_styles();
59566
+ }
59567
+ });
59568
+
57809
59569
  // node_modules/@probelabs/maid/out/core/frontmatter.js
57810
59570
  function parseFrontmatter(input) {
57811
59571
  const text = input.startsWith("\uFEFF") ? input.slice(1) : input;
@@ -57928,6 +59688,443 @@ var init_frontmatter = __esm({
57928
59688
  }
57929
59689
  });
57930
59690
 
59691
+ // node_modules/@probelabs/maid/out/renderer/class-builder.js
59692
+ function textFromTokens3(tokens) {
59693
+ if (!tokens || tokens.length === 0)
59694
+ return "";
59695
+ const parts = [];
59696
+ for (const t3 of tokens) {
59697
+ const img = t3.image ?? "";
59698
+ if (t3.tokenType && t3.tokenType.name === "QuotedString") {
59699
+ if (img.startsWith('"') && img.endsWith('"'))
59700
+ parts.push(img.slice(1, -1));
59701
+ else if (img.startsWith("'") && img.endsWith("'"))
59702
+ parts.push(img.slice(1, -1));
59703
+ else
59704
+ parts.push(img);
59705
+ } else {
59706
+ parts.push(img);
59707
+ }
59708
+ }
59709
+ return parts.join(" ").replace(/\s+/g, " ").trim();
59710
+ }
59711
+ function classRefToText(refCst) {
59712
+ if (!refCst)
59713
+ return "";
59714
+ const ch = refCst.children || {};
59715
+ const toks = [];
59716
+ ["Identifier", "QuotedString", "BacktickName"].forEach((k3) => {
59717
+ const arr = ch[k3];
59718
+ arr?.forEach((t3) => toks.push(t3));
59719
+ });
59720
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59721
+ return textFromTokens3(toks);
59722
+ }
59723
+ function memberLineToText(member) {
59724
+ const ch = member.children || {};
59725
+ const toks = [];
59726
+ const order = ["Visibility", "Identifier", "QuotedString", "LParen", "RParen", "Comma", "Colon", "NumberLiteral"];
59727
+ for (const k3 of order)
59728
+ ch[k3]?.forEach((t3) => toks.push(t3));
59729
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59730
+ const txt = textFromTokens3(toks);
59731
+ const isMethod = /(\)\s*:|\)$)/.test(txt) || /\(/.test(txt);
59732
+ return { text: txt, isMethod };
59733
+ }
59734
+ function canonicalId2(raw) {
59735
+ return raw.trim().replace(/\s+/g, "_");
59736
+ }
59737
+ function buildClassModel(text) {
59738
+ const { tokens } = tokenize4(text);
59739
+ parserInstance4.input = tokens;
59740
+ const cst = parserInstance4.diagram();
59741
+ const classes = /* @__PURE__ */ new Map();
59742
+ const relations = [];
59743
+ const notes = [];
59744
+ let direction = "TD";
59745
+ function ensureClass(idRaw, display) {
59746
+ const id = canonicalId2(idRaw);
59747
+ const existing = classes.get(id);
59748
+ if (existing)
59749
+ return existing;
59750
+ const def = { id, display: display || idRaw, attributes: [], methods: [] };
59751
+ classes.set(id, def);
59752
+ return def;
59753
+ }
59754
+ const diagramChildren = cst.children || {};
59755
+ const stmts = diagramChildren.statement || [];
59756
+ for (const st of stmts) {
59757
+ const ch = st.children || {};
59758
+ if (ch.directionStmt) {
59759
+ const d3 = ch.directionStmt[0].children.Direction?.[0]?.image || "TD";
59760
+ if (d3 === "TB")
59761
+ direction = "TB";
59762
+ else if (d3 === "BT")
59763
+ direction = "BT";
59764
+ else if (d3 === "LR")
59765
+ direction = "LR";
59766
+ else if (d3 === "RL")
59767
+ direction = "RL";
59768
+ else
59769
+ direction = "TD";
59770
+ continue;
59771
+ }
59772
+ if (ch.classLine) {
59773
+ const node = ch.classLine[0];
59774
+ const nch = node.children || {};
59775
+ const name14 = classRefToText(nch.classRef?.[0]);
59776
+ const def = ensureClass(name14);
59777
+ if (nch.LTlt && nch.Identifier && nch.GTgt) {
59778
+ def.stereotype = nch.Identifier[0].image;
59779
+ }
59780
+ if (nch.LCurly && nch.memberLineStmt) {
59781
+ const lines = nch.memberLineStmt;
59782
+ for (const m3 of lines) {
59783
+ const mm = memberLineToText(m3.children.memberLine?.[0]);
59784
+ if (!mm.text)
59785
+ continue;
59786
+ (mm.isMethod ? def.methods : def.attributes).push(mm.text);
59787
+ }
59788
+ }
59789
+ continue;
59790
+ }
59791
+ if (ch.memberAssignStmt) {
59792
+ const node = ch.memberAssignStmt[0];
59793
+ const nch = node.children || {};
59794
+ const clsName = classRefToText(nch.classRef?.[0]);
59795
+ const def = ensureClass(clsName);
59796
+ const mm = memberLineToText(nch.memberLine?.[0]);
59797
+ if (mm.text)
59798
+ (mm.isMethod ? def.methods : def.attributes).push(mm.text);
59799
+ continue;
59800
+ }
59801
+ if (ch.noteStmt) {
59802
+ const node = ch.noteStmt[0];
59803
+ const nch = node.children || {};
59804
+ const target = classRefToText(nch.classRef?.[0]);
59805
+ const labelToks = [];
59806
+ ["QuotedString", "Identifier", "NumberLiteral"].forEach((k3) => nch[k3]?.forEach((t3) => labelToks.push(t3)));
59807
+ const text2 = textFromTokens3(labelToks);
59808
+ if (target && text2)
59809
+ notes.push({ target: canonicalId2(target), text: text2 });
59810
+ continue;
59811
+ }
59812
+ if (ch.relationStmt) {
59813
+ const node = ch.relationStmt[0];
59814
+ const rch = node.children || {};
59815
+ const leftName = classRefToText(rch.classRef?.[0]);
59816
+ const rightName = classRefToText(rch.classRef?.[1]);
59817
+ const left = ensureClass(leftName).id;
59818
+ const right = ensureClass(rightName).id;
59819
+ const leftCardTok = rch.leftCard?.[0];
59820
+ const rightCardTok = rch.rightCard?.[0];
59821
+ const leftCard = leftCardTok?.image ? leftCardTok.image.slice(1, -1) : void 0;
59822
+ const rightCard = rightCardTok?.image ? rightCardTok.image.slice(1, -1) : void 0;
59823
+ let label;
59824
+ if (rch.labelText) {
59825
+ const toks = [];
59826
+ rch.labelText.forEach((lt) => {
59827
+ const ch2 = lt.children || {};
59828
+ ["QuotedString", "Identifier", "NumberLiteral", "GenericAngle"].forEach((k3) => {
59829
+ ch2[k3]?.forEach((t3) => toks.push(t3));
59830
+ });
59831
+ });
59832
+ toks.sort((a3, b3) => (a3.startOffset ?? 0) - (b3.startOffset ?? 0));
59833
+ label = textFromTokens3(toks);
59834
+ }
59835
+ const relMap = [
59836
+ { key: "RelAssociation", kind: "association" },
59837
+ { key: "RelDependency", kind: "dependency" },
59838
+ { key: "RelRealization", kind: "realization" },
59839
+ { key: "RelExtends", kind: "extends" },
59840
+ { key: "RelAggregation", kind: "aggregation" },
59841
+ { key: "RelComposition", kind: "composition" },
59842
+ { key: "RelDependencyLeft", kind: "dependency" },
59843
+ { key: "RelRealizationLeft", kind: "realization" },
59844
+ { key: "RelExtendsRight", kind: "extends" },
59845
+ { key: "RelAggBoth", kind: "aggregation-both" },
59846
+ { key: "RelCompBoth", kind: "composition-both" },
59847
+ { key: "RelAggToComp", kind: "aggregation-to-comp" },
59848
+ { key: "RelCompToAgg", kind: "composition-to-agg" },
59849
+ { key: "LollipopLeft", kind: "lollipop-left" },
59850
+ { key: "LollipopRight", kind: "lollipop-right" }
59851
+ ];
59852
+ let kind = "association";
59853
+ for (const m3 of relMap) {
59854
+ if (rch[m3.key]) {
59855
+ kind = m3.kind;
59856
+ break;
59857
+ }
59858
+ }
59859
+ let src = left, dst = right;
59860
+ if (rch.RelExtends || rch.RelDependencyLeft || rch.RelRealizationLeft || rch.LollipopLeft) {
59861
+ src = right;
59862
+ dst = left;
59863
+ }
59864
+ const rel = { source: src, target: dst, kind, label, leftCard, rightCard };
59865
+ relations.push(rel);
59866
+ continue;
59867
+ }
59868
+ }
59869
+ return {
59870
+ direction,
59871
+ classes: Array.from(classes.values()),
59872
+ relations,
59873
+ notes
59874
+ };
59875
+ }
59876
+ var init_class_builder = __esm({
59877
+ "node_modules/@probelabs/maid/out/renderer/class-builder.js"() {
59878
+ init_lexer5();
59879
+ init_parser5();
59880
+ }
59881
+ });
59882
+
59883
+ // node_modules/@probelabs/maid/out/renderer/class-renderer.js
59884
+ function classNodeSize(def, fontSize = 14) {
59885
+ const title = def.stereotype ? `\xAB${def.stereotype}\xBB ${def.display}` : def.display;
59886
+ const attrLines = def.attributes.slice();
59887
+ const methodLines = def.methods.slice();
59888
+ const lineH = Math.max(16, Math.round(fontSize * 1.1));
59889
+ const padX = 12, padY = 10;
59890
+ const titleW = measureText(title, fontSize + 1) + padX * 2;
59891
+ const attrsW = Math.max(0, ...attrLines.map((t3) => measureText(t3, fontSize))) + padX * 2;
59892
+ const methodsW = Math.max(0, ...methodLines.map((t3) => measureText(t3, fontSize))) + padX * 2;
59893
+ const width = Math.max(120, titleW, attrsW, methodsW);
59894
+ const sepH = (attrLines.length ? 6 : 0) + (methodLines.length ? 6 : 0);
59895
+ const height = padY * 2 + lineH + attrLines.length * lineH + (methodLines.length ? 6 : 0) + (attrLines.length ? 6 : 0) + methodLines.length * lineH;
59896
+ return { width, height, title, attrLines, methodLines };
59897
+ }
59898
+ function triangleOpenAt(points, color, length = 10, width = 8, atEnd = true) {
59899
+ const [a3, b3] = atEnd ? points : [points[1], points[0]];
59900
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59901
+ const len = Math.hypot(vx, vy) || 1;
59902
+ const ux = vx / len, uy = vy / len;
59903
+ const nx = -uy, ny = ux;
59904
+ const tip = { x: b3.x, y: b3.y };
59905
+ const base = { x: b3.x - ux * length, y: b3.y - uy * length };
59906
+ const p22 = { x: base.x + nx * (width / 2), y: base.y + ny * (width / 2) };
59907
+ const p3 = { x: base.x - nx * (width / 2), y: base.y - ny * (width / 2) };
59908
+ 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" />`;
59909
+ }
59910
+ function triangleHollowAt(points, color, length = 12, width = 10, atEnd = true) {
59911
+ const [a3, b3] = atEnd ? points : [points[1], points[0]];
59912
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59913
+ const len = Math.hypot(vx, vy) || 1;
59914
+ const ux = vx / len, uy = vy / len;
59915
+ const nx = -uy, ny = ux;
59916
+ const tip = { x: b3.x, y: b3.y };
59917
+ const base = { x: b3.x - ux * length, y: b3.y - uy * length };
59918
+ const p22 = { x: base.x + nx * (width / 2), y: base.y + ny * (width / 2) };
59919
+ const p3 = { x: base.x - nx * (width / 2), y: base.y - ny * (width / 2) };
59920
+ const d3 = `M${tip.x},${tip.y} L${p22.x},${p22.y} L${p3.x},${p3.y} Z`;
59921
+ return `<path class="edge-marker" d="${d3}" fill="white" stroke="${color}" />`;
59922
+ }
59923
+ function diamondAt(points, color, filled, size = 10, atStart = true) {
59924
+ const [a3, b3] = atStart ? points : [points[1], points[0]];
59925
+ const vx = b3.x - a3.x, vy = b3.y - a3.y;
59926
+ const len = Math.hypot(vx, vy) || 1;
59927
+ const ux = vx / len, uy = vy / len;
59928
+ const nx = -uy, ny = ux;
59929
+ const center = { x: a3.x, y: a3.y };
59930
+ const pTip = { x: center.x - ux * size, y: center.y - uy * size };
59931
+ const pLeft = { x: center.x + nx * (size / 1.4), y: center.y + ny * (size / 1.4) };
59932
+ const pRight = { x: center.x - nx * (size / 1.4), y: center.y - ny * (size / 1.4) };
59933
+ const pBack = { x: center.x + ux * size, y: center.y + uy * size };
59934
+ const d3 = `M${pTip.x},${pTip.y} L${pLeft.x},${pLeft.y} L${pBack.x},${pBack.y} L${pRight.x},${pRight.y} Z`;
59935
+ 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}"/>`;
59936
+ }
59937
+ function polyline(points, cls, dashed = false, stroke = "#555", strokeWidth = 2) {
59938
+ const d3 = points.map((p3) => `${p3.x},${p3.y}`).join(" ");
59939
+ const dash = dashed ? ` stroke-dasharray="4 3"` : "";
59940
+ return `<polyline class="edge-path ${cls}" points="${d3}" fill="none"${dash}/>`;
59941
+ }
59942
+ function renderClass(model, opts = {}) {
59943
+ const nodes = [];
59944
+ const nodeSizeInfo = {};
59945
+ for (const c3 of model.classes) {
59946
+ const sz = classNodeSize(c3);
59947
+ nodeSizeInfo[c3.id] = sz;
59948
+ nodes.push({ id: c3.id, label: c3.display, shape: "rectangle", width: sz.width, height: sz.height });
59949
+ }
59950
+ const edges = model.relations.map((r3, i3) => ({ id: `e${i3}`, source: r3.source, target: r3.target, type: "open" }));
59951
+ const graph = { nodes, edges, direction: model.direction };
59952
+ const layoutEngine = new DagreLayoutEngine();
59953
+ const layout = layoutEngine.layout(graph);
59954
+ const width = Math.ceil(layout.width + 40);
59955
+ const height = Math.ceil(layout.height + 40);
59956
+ const parts = [];
59957
+ 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}">`);
59958
+ const sharedCss = buildSharedCss();
59959
+ parts.push(`<style>${sharedCss}
59960
+ .class-title { font-weight: 600; }
59961
+ .class-divider { stroke: #aaa; stroke-width: 1; }
59962
+ .class-member { font-size: 12px; }
59963
+ </style>`);
59964
+ for (const n3 of layout.nodes) {
59965
+ const info = nodeSizeInfo[n3.id];
59966
+ const x3 = n3.x, y2 = n3.y, w3 = n3.width, h3 = n3.height;
59967
+ const title = info.title;
59968
+ const attrs = info.attrLines;
59969
+ const methods = info.methodLines;
59970
+ const lineH = 16;
59971
+ const padX = 12;
59972
+ const padY = 10;
59973
+ let cy = y2 + padY + lineH;
59974
+ parts.push(` <g transform="translate(${x3},${y2})">`);
59975
+ parts.push(` <rect class="node-shape" width="${w3}" height="${h3}" rx="0"/>`);
59976
+ parts.push(` <text class="node-label class-title" x="${w3 / 2}" y="${padY + 12}" text-anchor="middle" dominant-baseline="middle">${escapeXml(title)}</text>`);
59977
+ let yCursor = padY + 18;
59978
+ if (attrs.length) {
59979
+ parts.push(` <line class="class-divider" x1="0" y1="${yCursor}" x2="${w3}" y2="${yCursor}"/>`);
59980
+ yCursor += 8;
59981
+ for (const a3 of attrs) {
59982
+ parts.push(` <text class="node-label class-member" x="${padX}" y="${yCursor}" dominant-baseline="hanging">${escapeXml(a3)}</text>`);
59983
+ yCursor += lineH;
59984
+ }
59985
+ }
59986
+ if (methods.length) {
59987
+ parts.push(` <line class="class-divider" x1="0" y1="${yCursor}" x2="${w3}" y2="${yCursor}"/>`);
59988
+ yCursor += 8;
59989
+ for (const m3 of methods) {
59990
+ parts.push(` <text class="node-label class-member" x="${padX}" y="${yCursor}" dominant-baseline="hanging">${escapeXml(m3)}</text>`);
59991
+ yCursor += lineH;
59992
+ }
59993
+ }
59994
+ parts.push(" </g>");
59995
+ }
59996
+ const edgeColor = "#555";
59997
+ for (let i3 = 0; i3 < layout.edges.length; i3++) {
59998
+ const e3 = layout.edges[i3];
59999
+ const rel = model.relations[i3];
60000
+ const pts = e3.points;
60001
+ const dashed = rel.kind === "dependency" || rel.kind === "realization";
60002
+ parts.push(polyline(pts, "edge-path", dashed, edgeColor, 2));
60003
+ const placeEndpoint = (pt, next, text, side) => {
60004
+ const vx = next.x - pt.x;
60005
+ const vy = next.y - pt.y;
60006
+ const vlen = Math.hypot(vx, vy) || 1;
60007
+ const ux = vx / vlen;
60008
+ const uy = vy / vlen;
60009
+ const nx = -uy;
60010
+ const ny = ux;
60011
+ const away = -6;
60012
+ const perp = 8;
60013
+ const x3 = pt.x + ux * away + nx * perp;
60014
+ const y2 = pt.y + uy * away + ny * perp;
60015
+ const anchor = side === "start" ? "end" : "start";
60016
+ parts.push(`<text class="edge-label-text" x="${x3}" y="${y2}" text-anchor="${anchor}">${escapeXml(text)}</text>`);
60017
+ };
60018
+ if (rel.leftCard && pts.length >= 2)
60019
+ placeEndpoint(pts[0], pts[1], rel.leftCard, "start");
60020
+ if (rel.rightCard && pts.length >= 2) {
60021
+ const a3 = pts[pts.length - 1];
60022
+ const b3 = pts[pts.length - 2];
60023
+ placeEndpoint(a3, b3, rel.rightCard, "end");
60024
+ }
60025
+ if (rel.label) {
60026
+ const mid = pts[Math.floor(pts.length / 2)];
60027
+ const words = String(rel.label).split(/\s+/);
60028
+ const lines = [];
60029
+ let cur = "";
60030
+ const maxW = 200;
60031
+ for (const w3 of words) {
60032
+ const test = cur ? cur + " " + w3 : w3;
60033
+ if (measureText(test, 12) <= maxW)
60034
+ cur = test;
60035
+ else {
60036
+ if (cur)
60037
+ lines.push(cur);
60038
+ cur = w3;
60039
+ }
60040
+ }
60041
+ if (cur)
60042
+ lines.push(cur);
60043
+ const dy = 14;
60044
+ let y0 = mid.y - (lines.length - 1) * dy / 2 - 10;
60045
+ 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>`);
60046
+ }
60047
+ const pStart = [pts[0], pts[1] ?? pts[0]];
60048
+ const pEnd = [pts[pts.length - 2] ?? pts[pts.length - 1], pts[pts.length - 1]];
60049
+ switch (rel.kind) {
60050
+ case "extends":
60051
+ parts.push(triangleHollowAt(pEnd, edgeColor, 12, 10, true));
60052
+ break;
60053
+ case "realization":
60054
+ parts.push(triangleHollowAt(pEnd, edgeColor, 12, 10, true));
60055
+ break;
60056
+ case "dependency":
60057
+ parts.push(triangleOpenAt(pEnd, edgeColor, 10, 7, true));
60058
+ break;
60059
+ case "aggregation":
60060
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
60061
+ break;
60062
+ case "composition":
60063
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
60064
+ break;
60065
+ case "aggregation-both":
60066
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
60067
+ parts.push(diamondAt(pEnd, edgeColor, false, 8, false));
60068
+ break;
60069
+ case "composition-both":
60070
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
60071
+ parts.push(diamondAt(pEnd, edgeColor, true, 8, false));
60072
+ break;
60073
+ case "aggregation-to-comp":
60074
+ parts.push(diamondAt(pStart, edgeColor, false, 8, true));
60075
+ parts.push(diamondAt(pEnd, edgeColor, true, 8, false));
60076
+ break;
60077
+ case "composition-to-agg":
60078
+ parts.push(diamondAt(pStart, edgeColor, true, 8, true));
60079
+ parts.push(diamondAt(pEnd, edgeColor, false, 8, false));
60080
+ break;
60081
+ case "lollipop-left":
60082
+ parts.push(`<circle class="edge-marker" cx="${pStart[0].x}" cy="${pStart[0].y}" r="5" fill="white" stroke="${edgeColor}" />`);
60083
+ break;
60084
+ case "lollipop-right":
60085
+ parts.push(`<circle class="edge-marker" cx="${pEnd[1].x}" cy="${pEnd[1].y}" r="5" fill="white" stroke="${edgeColor}" />`);
60086
+ break;
60087
+ case "association":
60088
+ default:
60089
+ break;
60090
+ }
60091
+ }
60092
+ const noteW = 140, noteH = 44, dx = 20;
60093
+ const byId = Object.fromEntries(layout.nodes.map((n3) => [n3.id, n3]));
60094
+ const seenAnchorCount = {};
60095
+ const notes = model.notes || [];
60096
+ for (const note of notes) {
60097
+ const anchor = byId[note.target];
60098
+ if (!anchor)
60099
+ continue;
60100
+ const count = seenAnchorCount[note.target] = (seenAnchorCount[note.target] || 0) + 1;
60101
+ const nx = anchor.x + anchor.width + dx;
60102
+ let ny = anchor.y + (count - 1) * (noteH + 8);
60103
+ 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));
60104
+ let guard = 0;
60105
+ while (overlaps(nx, ny) && guard < 50) {
60106
+ ny += noteH + 6;
60107
+ guard++;
60108
+ }
60109
+ parts.push(` <g class="note" transform="translate(${nx},${ny})">`);
60110
+ parts.push(` <rect width="${noteW}" height="${noteH}" rx="0"/>`);
60111
+ parts.push(` <text class="note-text" x="${noteW / 2}" y="${noteH / 2 + 4}" text-anchor="middle">${escapeXml(note.text)}</text>`);
60112
+ parts.push(" </g>");
60113
+ const ax = anchor.x + anchor.width;
60114
+ const ay = anchor.y + 16;
60115
+ parts.push(`<line x1="${ax}" y1="${ay}" x2="${nx}" y2="${ny + noteH / 2}" stroke="#999" stroke-dasharray="4 3"/>`);
60116
+ }
60117
+ parts.push("</svg>");
60118
+ return parts.join("\n");
60119
+ }
60120
+ var init_class_renderer = __esm({
60121
+ "node_modules/@probelabs/maid/out/renderer/class-renderer.js"() {
60122
+ init_layout();
60123
+ init_styles();
60124
+ init_utils4();
60125
+ }
60126
+ });
60127
+
57931
60128
  // node_modules/@probelabs/maid/out/renderer/dot-renderer.js
57932
60129
  var init_dot_renderer = __esm({
57933
60130
  "node_modules/@probelabs/maid/out/renderer/dot-renderer.js"() {
@@ -58011,6 +60208,10 @@ function applyFlowchartTheme(svg, theme) {
58011
60208
  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)}"`);
58012
60209
  out = out.replace(/(<circle cx="4\.5" cy="4\.5" r="4\.5"[^>]*)(fill="[^"]*")/g, (_m2, p1) => `${p1}fill="${String(theme.arrowheadColor)}"`);
58013
60210
  }
60211
+ if (theme.edgeLabelTextColor) {
60212
+ const c3 = String(theme.edgeLabelTextColor);
60213
+ out = out.replace(/\.edge-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${c3};`));
60214
+ }
58014
60215
  if (theme.clusterBkg) {
58015
60216
  out = out.replace(/\.cluster-bg\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterBkg)};`));
58016
60217
  }
@@ -58020,6 +60221,12 @@ function applyFlowchartTheme(svg, theme) {
58020
60221
  if (theme.clusterTextColor) {
58021
60222
  out = out.replace(/\.cluster-label-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.clusterTextColor)};`));
58022
60223
  }
60224
+ if (theme.noteBkg)
60225
+ out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteBkg)};`));
60226
+ if (theme.noteBorder)
60227
+ out = out.replace(/\.note\s*\{[^}]*\}/, (m3) => m3.replace(/stroke:\s*[^;]+;/, `stroke: ${String(theme.noteBorder)};`));
60228
+ if (theme.noteTextColor)
60229
+ out = out.replace(/\.note-text\s*\{[^}]*\}/, (m3) => m3.replace(/fill:\s*[^;]+;/, `fill: ${String(theme.noteTextColor)};`));
58023
60230
  if (theme.fontFamily)
58024
60231
  out = out.replace(/\.node-label\s*\{[^}]*\}/, (m3) => m3.replace(/font-family:\s*[^;]+;/, `font-family: ${String(theme.fontFamily)};`));
58025
60232
  if (theme.fontSize)
@@ -58042,7 +60249,12 @@ var init_renderer = __esm({
58042
60249
  init_pie_renderer();
58043
60250
  init_sequence_builder();
58044
60251
  init_sequence_renderer();
60252
+ init_styles();
60253
+ init_state_builder();
60254
+ init_state_renderer();
58045
60255
  init_frontmatter();
60256
+ init_class_builder();
60257
+ init_class_renderer();
58046
60258
  init_layout();
58047
60259
  init_svg_generator();
58048
60260
  init_dot_renderer();
@@ -58177,7 +60389,31 @@ var init_renderer = __esm({
58177
60389
  return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
58178
60390
  }
58179
60391
  }
58180
- const errorSvg = this.generateErrorSvg("Unsupported diagram type. Rendering supports flowchart, pie, and sequence for now.");
60392
+ if (/^classDiagram\b/.test(firstLine)) {
60393
+ try {
60394
+ const model = buildClassModel(content);
60395
+ const svg = renderClass(model, { theme });
60396
+ const themed = theme ? applyFlowLikeTheme(svg, theme) : svg;
60397
+ return { svg: themed, graph: { nodes: [], edges: [], direction: model.direction }, errors: [] };
60398
+ } catch (e3) {
60399
+ const msg = e3?.message || "Class render error";
60400
+ const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "CLASS_RENDER" }];
60401
+ return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
60402
+ }
60403
+ }
60404
+ if (/^stateDiagram(?:-v2)?\b/.test(firstLine)) {
60405
+ try {
60406
+ const model = buildStateModel(content);
60407
+ const svg = renderState(model);
60408
+ const themed = theme ? applyFlowLikeTheme(svg, theme) : svg;
60409
+ return { svg: themed, graph: { nodes: [], edges: [], direction: model.direction }, errors: [] };
60410
+ } catch (e3) {
60411
+ const msg = e3?.message || "State render error";
60412
+ const err = [{ line: 1, column: 1, message: msg, severity: "error", code: "STATE_RENDER" }];
60413
+ return { svg: this.generateErrorSvg(msg), graph: { nodes: [], edges: [], direction: "TD" }, errors: err };
60414
+ }
60415
+ }
60416
+ const errorSvg = this.generateErrorSvg("Unsupported diagram type. Rendering supports flowchart, pie, sequence, class, and state.");
58181
60417
  return {
58182
60418
  svg: errorSvg,
58183
60419
  graph: { nodes: [], edges: [], direction: "TD" },