@zenuml/core 4.1.0 → 4.2.1

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.
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import antlr4 from 'antlr4';
3
3
  import { marked } from 'marked';
4
- import { mkdirSync, writeFileSync, readFileSync, statSync, watch } from 'node:fs';
5
- import { resolve, dirname, extname, basename, join } from 'node:path';
4
+ import { readFileSync, statSync, mkdirSync, writeFileSync, watch } from 'node:fs';
5
+ import { resolve, join, dirname, basename, extname } from 'node:path';
6
6
 
7
7
  // Generated from java-escape by ANTLR 4.11.1
8
8
  // jshint ignore: start
@@ -2738,7 +2738,7 @@ class sequenceParser extends antlr4.Parser {
2738
2738
 
2739
2739
 
2740
2740
  returnAsyncMessage() {
2741
- let localctx = new ReturnAsyncMessageContext$2(this, this._ctx, this.state);
2741
+ let localctx = new ReturnAsyncMessageContext$3(this, this._ctx, this.state);
2742
2742
  this.enterRule(localctx, 30, sequenceParser.RULE_returnAsyncMessage);
2743
2743
  var _la = 0; // Token type
2744
2744
  try {
@@ -5800,7 +5800,7 @@ let RetContext$3 = class RetContext extends antlr4.ParserRuleContext {
5800
5800
  };
5801
5801
 
5802
5802
  returnAsyncMessage() {
5803
- return this.getTypedRuleContext(ReturnAsyncMessageContext$2,0);
5803
+ return this.getTypedRuleContext(ReturnAsyncMessageContext$3,0);
5804
5804
  };
5805
5805
 
5806
5806
  enterRule(listener) {
@@ -5820,7 +5820,7 @@ let RetContext$3 = class RetContext extends antlr4.ParserRuleContext {
5820
5820
 
5821
5821
 
5822
5822
 
5823
- let ReturnAsyncMessageContext$2 = class ReturnAsyncMessageContext extends antlr4.ParserRuleContext {
5823
+ let ReturnAsyncMessageContext$3 = class ReturnAsyncMessageContext extends antlr4.ParserRuleContext {
5824
5824
 
5825
5825
  constructor(parser, parent, invokingState) {
5826
5826
  if(parent===undefined) {
@@ -8714,7 +8714,7 @@ sequenceParser.WidthContext = WidthContext;
8714
8714
  sequenceParser.EmojiContext = EmojiContext;
8715
8715
  sequenceParser.BlockContext = BlockContext;
8716
8716
  sequenceParser.RetContext = RetContext$3;
8717
- sequenceParser.ReturnAsyncMessageContext = ReturnAsyncMessageContext$2;
8717
+ sequenceParser.ReturnAsyncMessageContext = ReturnAsyncMessageContext$3;
8718
8718
  sequenceParser.DividerContext = DividerContext$1;
8719
8719
  sequenceParser.DividerNoteContext = DividerNoteContext;
8720
8720
  sequenceParser.StatContext = StatContext$3;
@@ -8779,6 +8779,10 @@ const blankParticipant = {
8779
8779
  };
8780
8780
  let Participant$1 = class Participant {
8781
8781
  name;
8782
+ // Fields the renderer-facing ParticipantView (ir/contract.ts) exposes are
8783
+ // public; they were already fully exposed via ToValue(), so the previous
8784
+ // `private` was inconsistent encapsulation. `width` stays private — it is not
8785
+ // part of ParticipantView.
8782
8786
  stereotype;
8783
8787
  width;
8784
8788
  groupId;
@@ -9204,7 +9208,7 @@ const seqParser$7 = sequenceParser;
9204
9208
  const CreationContext$6 = seqParser$7.CreationContext;
9205
9209
  const MessageContext$6 = seqParser$7.MessageContext;
9206
9210
  const AsyncMessageContext$2 = seqParser$7.AsyncMessageContext;
9207
- const ReturnAsyncMessageContext$1 = seqParser$7.ReturnAsyncMessageContext;
9211
+ const ReturnAsyncMessageContext$2 = seqParser$7.ReturnAsyncMessageContext;
9208
9212
  const RetMessageContext = seqParser$7.RetContext;
9209
9213
 
9210
9214
  CreationContext$6.prototype.Assignee = function () {
@@ -9264,12 +9268,12 @@ AsyncMessageContext$2.prototype.Owner = function () {
9264
9268
  return this.To() || getOwnerFromAncestor(this.parentCtx);
9265
9269
  };
9266
9270
 
9267
- ReturnAsyncMessageContext$1.prototype.To = function () {
9271
+ ReturnAsyncMessageContext$2.prototype.To = function () {
9268
9272
  const toCtx = this.to();
9269
9273
  return toCtx?.name?.()?.getFormattedText() || toCtx?.getFormattedText();
9270
9274
  };
9271
9275
 
9272
- ReturnAsyncMessageContext$1.prototype.Owner = function () {
9276
+ ReturnAsyncMessageContext$2.prototype.Owner = function () {
9273
9277
  return this.To() || getOwnerFromAncestor(this.parentCtx);
9274
9278
  };
9275
9279
 
@@ -9386,13 +9390,13 @@ RefContext.prototype.Participants = function() {
9386
9390
  return this.name().slice(1) ?? [];
9387
9391
  };
9388
9392
 
9389
- const ParserRuleContext = antlr4.ParserRuleContext;
9393
+ const ParserRuleContext$1 = antlr4.ParserRuleContext;
9390
9394
  const StatContext$2 = sequenceParser.StatContext;
9391
9395
  const ProgContext = sequenceParser.ProgContext;
9392
9396
  const MessageContext$4 = sequenceParser.MessageContext;
9393
9397
  const CreationContext$4 = sequenceParser.CreationContext;
9394
9398
 
9395
- ParserRuleContext.prototype.Origin = function () {
9399
+ ParserRuleContext$1.prototype.Origin = function () {
9396
9400
  let ctx = this.parentCtx;
9397
9401
  while (ctx && !(ctx instanceof StatContext$2 || ctx instanceof ProgContext)) {
9398
9402
  ctx = this.parentCtx;
@@ -9438,8 +9442,8 @@ function formatParameter(param) {
9438
9442
  if (param.namedParameter?.()) {
9439
9443
  const namedParam = param.namedParameter();
9440
9444
  if (namedParam) {
9441
- const expr = namedParam.expr();
9442
- const value = expr ? expr.getFormattedText() : "";
9445
+ const expr2 = namedParam.expr();
9446
+ const value = expr2 ? expr2.getFormattedText() : "";
9443
9447
  return `${namedParam.ID().getText()}=${value}`;
9444
9448
  }
9445
9449
  }
@@ -9449,8 +9453,9 @@ function formatParameter(param) {
9449
9453
  return `${decl.type().getText()} ${decl.ID().getText()}`;
9450
9454
  }
9451
9455
  }
9452
- if (param.expr?.()) {
9453
- return param.expr().getFormattedText();
9456
+ const expr = param.expr?.();
9457
+ if (expr) {
9458
+ return expr.getFormattedText();
9454
9459
  }
9455
9460
  return param.getFormattedText();
9456
9461
  }
@@ -9462,6 +9467,7 @@ const ParametersContext = sequenceParser.ParametersContext;
9462
9467
  const AsyncMessageContext$1 = sequenceParser.AsyncMessageContext;
9463
9468
  const CreationContext$3 = sequenceParser.CreationContext;
9464
9469
  const RetContext$1 = sequenceParser.RetContext;
9470
+ const ReturnAsyncMessageContext$1 = sequenceParser.ReturnAsyncMessageContext;
9465
9471
  MessageContext$3.prototype.SignatureText = function() {
9466
9472
  return this.messageBody()?.func()?.signature()?.map((s) => s?.getFormattedText()).join(".") ?? "";
9467
9473
  };
@@ -9482,7 +9488,7 @@ CreationContext$3.prototype.isParamValid = function() {
9482
9488
  RetContext$1.prototype.SignatureText = function() {
9483
9489
  return this.asyncMessage()?.content()?.getFormattedText() ?? this.returnAsyncMessage()?.content()?.getFormattedText() ?? this.expr()?.getFormattedText() ?? "";
9484
9490
  };
9485
- sequenceParser.ReturnAsyncMessageContext.prototype.SignatureText = function() {
9491
+ ReturnAsyncMessageContext$1.prototype.SignatureText = function() {
9486
9492
  return this.content()?.getFormattedText() ?? "";
9487
9493
  };
9488
9494
  ParametersContext.prototype.getFormattedText = function() {
@@ -9557,46 +9563,47 @@ LoopContext.prototype.Statements = function() {
9557
9563
  };
9558
9564
 
9559
9565
  const seqParser$1 = sequenceParser;
9560
- const CreationContext = seqParser$1.CreationContext;
9561
9566
  const StatContext$1 = seqParser$1.StatContext;
9567
+ const CreationContext = seqParser$1.CreationContext;
9562
9568
  const MessageContext = seqParser$1.MessageContext;
9563
9569
  const AsyncMessageContext = seqParser$1.AsyncMessageContext;
9564
9570
  const ReturnAsyncMessageContext = seqParser$1.ReturnAsyncMessageContext;
9565
9571
  const RetContext = seqParser$1.RetContext;
9566
9572
  CreationContext.prototype.From = function() {
9567
9573
  if (this.parentCtx instanceof StatContext$1) {
9568
- return this.ClosestAncestorStat().Origin();
9574
+ return this.ClosestAncestorStat()?.Origin();
9569
9575
  }
9570
9576
  return void 0;
9571
9577
  };
9572
9578
  MessageContext.prototype.ProvidedFrom = function() {
9573
- const fromCtx = this.messageBody()?.fromTo()?.from();
9574
- return fromCtx?.name?.()?.getFormattedText() || fromCtx?.getFormattedText();
9579
+ const fromCtx = this.messageBody()?.fromTo?.()?.from?.();
9580
+ return fromCtx?.name?.()?.getFormattedText?.() || fromCtx?.getFormattedText?.();
9575
9581
  };
9576
9582
  MessageContext.prototype.From = function() {
9577
- return this.ProvidedFrom() || this.ClosestAncestorStat().Origin();
9583
+ return this.ProvidedFrom() || this.ClosestAncestorStat()?.Origin();
9578
9584
  };
9579
9585
  AsyncMessageContext.prototype.ProvidedFrom = function() {
9580
9586
  const fromCtx = this.from();
9581
- return fromCtx?.name?.()?.getFormattedText() || fromCtx?.getFormattedText();
9587
+ return fromCtx?.name?.()?.getFormattedText?.() || fromCtx?.getFormattedText?.();
9582
9588
  };
9583
9589
  AsyncMessageContext.prototype.From = function() {
9584
- return this.ProvidedFrom() || this.ClosestAncestorStat().Origin();
9590
+ return this.ProvidedFrom() || this.ClosestAncestorStat()?.Origin();
9585
9591
  };
9586
9592
  ReturnAsyncMessageContext.prototype.ProvidedFrom = function() {
9587
9593
  const fromCtx = this.from();
9588
- return fromCtx?.name?.()?.getFormattedText() || fromCtx?.getFormattedText();
9594
+ return fromCtx?.name?.()?.getFormattedText?.() || fromCtx?.getFormattedText?.();
9589
9595
  };
9590
9596
  ReturnAsyncMessageContext.prototype.From = function() {
9591
- return this.ProvidedFrom() || this.ClosestAncestorStat().Origin();
9597
+ return this.ProvidedFrom() || this.ClosestAncestorStat()?.Origin();
9592
9598
  };
9593
9599
  RetContext.prototype.From = function() {
9594
- return this.asyncMessage()?.From() || this.returnAsyncMessage()?.From() || this.ClosestAncestorStat().Origin();
9600
+ return this.asyncMessage()?.From?.() || this.returnAsyncMessage()?.From?.() || this.ClosestAncestorStat()?.Origin();
9595
9601
  };
9596
9602
 
9597
9603
  const seqParser = sequenceParser;
9598
9604
  const StatContext = seqParser.StatContext;
9599
- antlr4.ParserRuleContext.prototype.ClosestAncestorStat = function() {
9605
+ const ParserRuleContext = antlr4.ParserRuleContext;
9606
+ ParserRuleContext.prototype.ClosestAncestorStat = function() {
9600
9607
  if (this instanceof StatContext) {
9601
9608
  return this;
9602
9609
  }
@@ -9609,7 +9616,7 @@ antlr4.ParserRuleContext.prototype.ClosestAncestorStat = function() {
9609
9616
  }
9610
9617
  return void 0;
9611
9618
  };
9612
- antlr4.ParserRuleContext.prototype.ClosestAncestorBlock = function() {
9619
+ ParserRuleContext.prototype.ClosestAncestorBlock = function() {
9613
9620
  const parentCtx = this.ClosestAncestorStat()?.parentCtx;
9614
9621
  if (parentCtx instanceof seqParser.BlockContext) {
9615
9622
  return parentCtx;
@@ -9920,33 +9927,31 @@ function OrderedParticipants(rootContext) {
9920
9927
  const cached = orderedParticipantsCache.get(rootContext);
9921
9928
  if (cached) return cached;
9922
9929
  const participants = ToCollector.getParticipants(rootContext);
9923
- const participantEntries = Array.from(participants.participants.entries());
9930
+ const participantEntries = participants.Array().map((p) => p.ToValue());
9924
9931
  const allMessages = AllMessages(rootContext);
9925
9932
  const emptyContext = allMessages.length === 0 && participantEntries.length === 0;
9926
9933
  const someMessagesMissFrom = allMessages.some((m) => !m.from);
9927
9934
  const needDefaultStarter = emptyContext || someMessagesMissFrom;
9928
9935
  if (needDefaultStarter) {
9929
- participantEntries.unshift([
9930
- _STARTER_,
9931
- { ...blankParticipant, name: _STARTER_, isStarter: true }
9932
- ]);
9933
- }
9934
- const result = participantEntries.map(
9935
- (entry, index, entries) => {
9936
- const participant = entry[1];
9937
- const previousName = index > 0 ? entries[index - 1][1].name : "";
9938
- return new Participant(
9939
- participant.name,
9940
- previousName,
9941
- participant.label,
9942
- participant.type,
9943
- participant.stereotype,
9944
- participant.color,
9945
- participant.groupId,
9946
- participant.emoji
9947
- );
9948
- }
9949
- );
9936
+ participantEntries.unshift({
9937
+ ...blankParticipant,
9938
+ name: _STARTER_,
9939
+ isStarter: true
9940
+ });
9941
+ }
9942
+ const result = participantEntries.map((participant, index, entries) => {
9943
+ const previousName = index > 0 ? entries[index - 1].name : "";
9944
+ return new Participant(
9945
+ participant.name,
9946
+ previousName,
9947
+ participant.label,
9948
+ participant.type,
9949
+ participant.stereotype,
9950
+ participant.color,
9951
+ participant.groupId,
9952
+ participant.emoji
9953
+ );
9954
+ });
9950
9955
  orderedParticipantsCache.set(rootContext, result);
9951
9956
  return result;
9952
9957
  }
@@ -10045,7 +10050,7 @@ function longestPathTable(graph, gaps) {
10045
10050
  }
10046
10051
  return [tracker.delta, table];
10047
10052
  }
10048
- function freezeCriticalGaps(table, graph, gaps) {
10053
+ function freezeCriticalGaps(table, gaps) {
10049
10054
  let j = table.length - 1;
10050
10055
  while (j > 0) {
10051
10056
  const argument = table[j].argument;
@@ -10082,7 +10087,7 @@ function find_optimal(matrix) {
10082
10087
  return positionsFromTable(table);
10083
10088
  }
10084
10089
  if (table[n - 1].maximum.velocity > 0) {
10085
- freezeCriticalGaps(table, graph, gaps);
10090
+ freezeCriticalGaps(table, gaps);
10086
10091
  } else {
10087
10092
  advanceGaps(gaps, delta);
10088
10093
  }
@@ -10872,10 +10877,22 @@ class FragmentAltVM extends FragmentVM {
10872
10877
  }
10873
10878
  }
10874
10879
 
10880
+ class FragmentRefVM extends FragmentVM {
10881
+ kind = "ref";
10882
+ measure(top) {
10883
+ const context = this.context?.ref?.() || this.context;
10884
+ const commentHeight = this.measureComment(context);
10885
+ const headerHeight = this.metrics.fragmentHeaderHeight;
10886
+ const height = commentHeight + headerHeight + this.metrics.fragmentPaddingBottom;
10887
+ return { top, height, kind: this.kind };
10888
+ }
10889
+ }
10890
+
10875
10891
  class FragmentSingleBlockVM extends FragmentVM {
10876
- constructor(statement, fragment, runtime) {
10892
+ constructor(statement, fragment, runtime, kind) {
10877
10893
  super(statement, runtime);
10878
10894
  this.fragment = fragment;
10895
+ this.kind = kind;
10879
10896
  }
10880
10897
  measure(top, origin) {
10881
10898
  const commentHeight = this.measureComment(this.fragment);
@@ -10896,37 +10913,6 @@ class FragmentSingleBlockVM extends FragmentVM {
10896
10913
  }
10897
10914
  }
10898
10915
 
10899
- class FragmentCriticalVM extends FragmentSingleBlockVM {
10900
- kind = "critical";
10901
- }
10902
-
10903
- class FragmentLoopVM extends FragmentSingleBlockVM {
10904
- kind = "loop";
10905
- }
10906
-
10907
- class FragmentOptVM extends FragmentSingleBlockVM {
10908
- kind = "opt";
10909
- }
10910
-
10911
- class FragmentParVM extends FragmentSingleBlockVM {
10912
- kind = "par";
10913
- }
10914
-
10915
- class FragmentRefVM extends FragmentVM {
10916
- kind = "ref";
10917
- measure(top) {
10918
- const context = this.context?.ref?.() || this.context;
10919
- const commentHeight = this.measureComment(context);
10920
- const headerHeight = this.metrics.fragmentHeaderHeight;
10921
- const height = commentHeight + headerHeight + this.metrics.fragmentPaddingBottom;
10922
- return { top, height, kind: this.kind };
10923
- }
10924
- }
10925
-
10926
- class FragmentSectionVM extends FragmentSingleBlockVM {
10927
- kind = "section";
10928
- }
10929
-
10930
10916
  class FragmentTryCatchVM extends FragmentVM {
10931
10917
  constructor(statement, tcf, runtime) {
10932
10918
  super(statement, runtime);
@@ -11056,25 +11042,11 @@ const createStatementVM = (statement, runtime) => {
11056
11042
  if (statement.divider?.()) {
11057
11043
  return new DividerStatementVM(statement, runtime);
11058
11044
  }
11059
- const loop = statement.loop?.();
11060
- if (loop) {
11061
- return new FragmentLoopVM(statement, loop, runtime);
11062
- }
11063
- const opt = statement.opt?.();
11064
- if (opt) {
11065
- return new FragmentOptVM(statement, opt, runtime);
11066
- }
11067
- const par = statement.par?.();
11068
- if (par) {
11069
- return new FragmentParVM(statement, par, runtime);
11070
- }
11071
- const section = statement.section?.();
11072
- if (section) {
11073
- return new FragmentSectionVM(statement, section, runtime);
11074
- }
11075
- const critical = statement.critical?.();
11076
- if (critical) {
11077
- return new FragmentCriticalVM(statement, critical, runtime);
11045
+ for (const kind of ["loop", "opt", "par", "section", "critical"]) {
11046
+ const fragment = statement[kind]?.();
11047
+ if (fragment) {
11048
+ return new FragmentSingleBlockVM(statement, fragment, runtime, kind);
11049
+ }
11078
11050
  }
11079
11051
  const tcf = statement.tcf?.();
11080
11052
  if (tcf) {
@@ -11520,7 +11492,7 @@ function snapX(x) {
11520
11492
  return x;
11521
11493
  }
11522
11494
  const COMMENT_FONT_ASCENT = 15;
11523
- function buildFragmentGeometry(info, coord, coordinates, verticalCoordinates, allParticipants, measureText, commentHeight = 0, commentText, commentStyle, commentYBase) {
11495
+ function buildFragmentGeometry(info, coord, coordinates, verticalCoordinates, allParticipants, _measureText, commentHeight = 0, commentText, commentStyle, commentYBase) {
11524
11496
  const statNode = info.statNode;
11525
11497
  if (!statNode) return null;
11526
11498
  const fragmentCtx = findFragmentContext(statNode);
@@ -13652,6 +13624,69 @@ async function checkOne(input) {
13652
13624
  errors
13653
13625
  };
13654
13626
  }
13627
+ async function renderMarkdownFile(inputArg, args, config) {
13628
+ const mdContent = await readCode(inputArg);
13629
+ const effectiveFormat = args.outputFormat ?? config.configOutputFormat ?? "svg";
13630
+ if (effectiveFormat !== "svg" && effectiveFormat !== "png") {
13631
+ throw new Error(
13632
+ `Unsupported output format: "${effectiveFormat}". Use "svg" or "png".`
13633
+ );
13634
+ }
13635
+ const inputPath = inputArg === "-" ? void 0 : resolve(inputArg);
13636
+ const outputPath = args.output === "-" ? "-" : args.output ? resolve(args.output) : inputPath ? join(
13637
+ dirname(inputPath),
13638
+ `${basename(inputArg, extname(inputArg))}-rendered.md`
13639
+ ) : "-";
13640
+ const imageDir = outputPath !== "-" ? dirname(outputPath) : inputPath ? dirname(inputPath) : process.cwd();
13641
+ const imageStem = inputPath ? basename(inputArg, extname(inputArg)) : outputPath !== "-" ? basename(outputPath, extname(outputPath)) : "diagram";
13642
+ const renderOptions = {};
13643
+ const effectiveTheme = args.theme ?? config.configTheme;
13644
+ if (effectiveTheme) {
13645
+ renderOptions.theme = effectiveTheme;
13646
+ }
13647
+ const blocks = extractZenumlBlocks(mdContent);
13648
+ const imageFiles = /* @__PURE__ */ new Map();
13649
+ for (const block of blocks) {
13650
+ if (block.empty) continue;
13651
+ const imageFilename = `${imageStem}-zenuml-${block.index}.${effectiveFormat}`;
13652
+ const imageFilePath = join(imageDir, imageFilename);
13653
+ let result;
13654
+ try {
13655
+ result = renderToSvg(block.code, renderOptions);
13656
+ } catch (err) {
13657
+ throw new Error(
13658
+ `Failed to render zenuml block ${block.index}: ${err.message}`
13659
+ );
13660
+ }
13661
+ mkdirSync(imageDir, { recursive: true });
13662
+ const image = effectiveFormat === "png" ? await rasterizeToPng(
13663
+ result.svg,
13664
+ result.width,
13665
+ result.height,
13666
+ args.scale ?? config.configScale ?? 2
13667
+ ) : result.svg;
13668
+ writeFileSync(imageFilePath, image);
13669
+ imageFiles.set(block.index, imageFilename);
13670
+ if (!args.quiet && !args.watch) {
13671
+ process.stderr.write(`Wrote ${imageFilePath}
13672
+ `);
13673
+ }
13674
+ }
13675
+ const outputMd = [...blocks].reverse().reduce((markdown, block) => {
13676
+ const replacement = block.empty ? "" : `![${block.title || `diagram ${block.index + 1}`}](${imageFiles.get(block.index)})`;
13677
+ return markdown.replace(block.raw, replacement);
13678
+ }, mdContent);
13679
+ if (outputPath === "-") {
13680
+ process.stdout.write(outputMd);
13681
+ return;
13682
+ }
13683
+ mkdirSync(dirname(outputPath), { recursive: true });
13684
+ writeFileSync(outputPath, outputMd, "utf-8");
13685
+ if (!args.quiet && !args.watch) {
13686
+ process.stderr.write(`Wrote ${outputPath}
13687
+ `);
13688
+ }
13689
+ }
13655
13690
  async function main() {
13656
13691
  if (!globalThis.OffscreenCanvas && typeof document === "undefined") {
13657
13692
  try {
@@ -13755,146 +13790,6 @@ async function main() {
13755
13790
  process.stdout.write(JSON.stringify(ast, null, 2) + "\n");
13756
13791
  process.exit(0);
13757
13792
  }
13758
- const isMdMode = args.md || expandedInputs.some((f) => f !== "-" && /\.(?:md|markdown)$/i.test(f));
13759
- if (isMdMode) {
13760
- if (expandedInputs.length > 1) {
13761
- process.stderr.write(
13762
- "Error: --md mode supports only a single input file.\n"
13763
- );
13764
- process.exit(1);
13765
- }
13766
- const inputArg = expandedInputs[0];
13767
- if (args.md && inputArg !== "-") {
13768
- const ext = extname(inputArg).toLowerCase();
13769
- if (ext !== ".md" && ext !== ".markdown") {
13770
- process.stderr.write(
13771
- `Error: --md flag requires a .md or .markdown input file, got: ${inputArg}
13772
- `
13773
- );
13774
- process.exit(1);
13775
- }
13776
- }
13777
- let mdContent;
13778
- try {
13779
- mdContent = await readCode(inputArg);
13780
- } catch (err) {
13781
- process.stderr.write(`Error: ${err.message}
13782
- `);
13783
- process.exit(1);
13784
- }
13785
- const effectiveFormat = args.outputFormat ?? "svg";
13786
- if (effectiveFormat !== "svg" && effectiveFormat !== "png") {
13787
- process.stderr.write(
13788
- `Error: Unsupported output format: "${effectiveFormat}". Use "svg" or "png".
13789
- `
13790
- );
13791
- process.exit(1);
13792
- }
13793
- let imageDir;
13794
- let mdOutputPath;
13795
- if (args.output && args.output !== "-") {
13796
- const resolvedOutput = resolve(args.output);
13797
- imageDir = dirname(resolvedOutput);
13798
- mdOutputPath = resolvedOutput;
13799
- } else if (args.output === "-") {
13800
- if (inputArg !== "-") {
13801
- imageDir = dirname(resolve(inputArg));
13802
- } else {
13803
- imageDir = process.cwd();
13804
- }
13805
- mdOutputPath = "-";
13806
- } else {
13807
- if (inputArg !== "-") {
13808
- const resolvedInput = resolve(inputArg);
13809
- const inputDir = dirname(resolvedInput);
13810
- const ext = extname(inputArg);
13811
- const stem = basename(inputArg, ext);
13812
- imageDir = inputDir;
13813
- mdOutputPath = join(inputDir, `${stem}-rendered.md`);
13814
- } else {
13815
- imageDir = process.cwd();
13816
- mdOutputPath = "-";
13817
- }
13818
- }
13819
- let imageStem;
13820
- if (inputArg !== "-") {
13821
- const ext = extname(inputArg);
13822
- imageStem = basename(inputArg, ext);
13823
- } else if (mdOutputPath !== "-") {
13824
- const ext = extname(mdOutputPath);
13825
- imageStem = basename(mdOutputPath, ext);
13826
- } else {
13827
- imageStem = "diagram";
13828
- }
13829
- const blocks = extractZenumlBlocks(mdContent);
13830
- const effectiveScale = args.scale ?? 2;
13831
- const effectiveTheme = args.theme;
13832
- const renderOptions = {};
13833
- if (effectiveTheme) {
13834
- renderOptions.theme = effectiveTheme;
13835
- }
13836
- const imageFiles = /* @__PURE__ */ new Map();
13837
- for (const block of blocks) {
13838
- if (block.empty) continue;
13839
- const imageFilename = `${imageStem}-zenuml-${block.index}.${effectiveFormat}`;
13840
- const imageFilePath = join(imageDir, imageFilename);
13841
- let svg;
13842
- let svgWidth;
13843
- let svgHeight;
13844
- try {
13845
- const result = renderToSvg(block.code, renderOptions);
13846
- svg = result.svg;
13847
- svgWidth = result.width;
13848
- svgHeight = result.height;
13849
- } catch (err) {
13850
- process.stderr.write(
13851
- `Error: Failed to render zenuml block ${block.index}: ${err.message}
13852
- `
13853
- );
13854
- process.exit(1);
13855
- }
13856
- mkdirSync(imageDir, { recursive: true });
13857
- if (effectiveFormat === "png") {
13858
- const pngBuffer = await rasterizeToPng(
13859
- svg,
13860
- svgWidth,
13861
- svgHeight,
13862
- effectiveScale
13863
- );
13864
- writeFileSync(imageFilePath, pngBuffer);
13865
- } else {
13866
- writeFileSync(imageFilePath, svg, "utf-8");
13867
- }
13868
- if (!args.quiet) {
13869
- process.stderr.write(`Wrote ${imageFilePath}
13870
- `);
13871
- }
13872
- imageFiles.set(block.index, imageFilename);
13873
- }
13874
- let outputMd = mdContent;
13875
- const sortedBlocks = [...blocks].reverse();
13876
- for (const block of sortedBlocks) {
13877
- const altText = block.title || `diagram ${block.index + 1}`;
13878
- if (block.empty) {
13879
- outputMd = outputMd.replace(block.raw, "");
13880
- } else {
13881
- const imageFilename = imageFiles.get(block.index);
13882
- const replacement = `![${altText}](${imageFilename})`;
13883
- outputMd = outputMd.replace(block.raw, replacement);
13884
- }
13885
- }
13886
- if (mdOutputPath === "-") {
13887
- process.stdout.write(outputMd);
13888
- } else {
13889
- mkdirSync(dirname(mdOutputPath), { recursive: true });
13890
- writeFileSync(mdOutputPath, outputMd, "utf-8");
13891
- if (!args.quiet) {
13892
- process.stderr.write(`Wrote ${mdOutputPath}
13893
- `);
13894
- }
13895
- }
13896
- process.exit(0);
13897
- }
13898
13793
  let configScale;
13899
13794
  let configTheme;
13900
13795
  let configOutputFormat;
@@ -13912,99 +13807,30 @@ async function main() {
13912
13807
  );
13913
13808
  process.exit(1);
13914
13809
  }
13915
- if (args.watch) {
13916
- const renderForWatch = async (inputArg) => {
13917
- await renderOneFile(inputArg, args, {
13918
- configScale,
13919
- configTheme,
13920
- configOutputFormat});
13921
- };
13922
- const renderMdForWatch = async (inputArg) => {
13923
- let mdContent;
13924
- try {
13925
- mdContent = readFileSync(resolve(inputArg), "utf-8");
13926
- } catch {
13927
- throw new Error(`Cannot read input file: ${resolve(inputArg)}`);
13928
- }
13929
- const effectiveFormat = args.outputFormat ?? "svg";
13930
- if (effectiveFormat !== "svg" && effectiveFormat !== "png") {
13931
- throw new Error(
13932
- `Unsupported output format: "${effectiveFormat}". Use "svg" or "png".`
13933
- );
13934
- }
13935
- let mdOutputPath;
13936
- let imageDir;
13937
- if (args.output && args.output !== "-") {
13938
- const resolvedOutput = resolve(args.output);
13939
- imageDir = dirname(resolvedOutput);
13940
- mdOutputPath = resolvedOutput;
13941
- } else if (args.output === "-") {
13942
- imageDir = dirname(resolve(inputArg));
13943
- mdOutputPath = "-";
13944
- } else {
13945
- const resolvedInput = resolve(inputArg);
13946
- const inputDir = dirname(resolvedInput);
13947
- const ext2 = extname(inputArg);
13948
- const stem = basename(inputArg, ext2);
13949
- imageDir = inputDir;
13950
- mdOutputPath = join(inputDir, `${stem}-rendered.md`);
13951
- }
13952
- const ext = extname(inputArg);
13953
- const imageStem = basename(inputArg, ext);
13954
- const blocks = extractZenumlBlocks(mdContent);
13955
- const effectiveScale = args.scale ?? configScale ?? 2;
13956
- const imageFiles = /* @__PURE__ */ new Map();
13957
- for (const block of blocks) {
13958
- if (block.empty) continue;
13959
- const imageFilename = `${imageStem}-zenuml-${block.index}.${effectiveFormat}`;
13960
- const imageFilePath = join(imageDir, imageFilename);
13961
- const result = renderToSvg(block.code);
13962
- const { svg, width: svgWidth, height: svgHeight } = result;
13963
- mkdirSync(imageDir, { recursive: true });
13964
- if (effectiveFormat === "png") {
13965
- const pngBuffer = await rasterizeToPng(
13966
- svg,
13967
- svgWidth,
13968
- svgHeight,
13969
- effectiveScale
13970
- );
13971
- writeFileSync(imageFilePath, pngBuffer);
13972
- } else {
13973
- writeFileSync(imageFilePath, svg, "utf-8");
13974
- }
13975
- imageFiles.set(block.index, imageFilename);
13976
- }
13977
- let outputMd = mdContent;
13978
- const sortedBlocks = [...blocks].reverse();
13979
- for (const block of sortedBlocks) {
13980
- const altText = block.title || `diagram ${block.index + 1}`;
13981
- if (block.empty) {
13982
- outputMd = outputMd.replace(block.raw, "");
13983
- } else {
13984
- const imageFilename = imageFiles.get(block.index);
13985
- const replacement = `![${altText}](${imageFilename})`;
13986
- outputMd = outputMd.replace(block.raw, replacement);
13987
- }
13988
- }
13989
- if (mdOutputPath === "-") {
13990
- process.stdout.write(outputMd);
13991
- } else {
13992
- mkdirSync(dirname(mdOutputPath), { recursive: true });
13993
- writeFileSync(mdOutputPath, outputMd, "utf-8");
13994
- }
13995
- };
13996
- const hasMdInputs = expandedInputs.some(
13997
- (f) => /\.(?:md|markdown)$/i.test(f)
13810
+ const config = {
13811
+ configScale,
13812
+ configTheme,
13813
+ configOutputFormat,
13814
+ multipleInputs
13815
+ };
13816
+ const isMdMode = args.md || expandedInputs.some((f) => f !== "-" && /\.(?:md|markdown)$/i.test(f));
13817
+ if (isMdMode && multipleInputs) {
13818
+ process.stderr.write(
13819
+ "Error: --md mode supports only a single input file.\n"
13998
13820
  );
13999
- const renderMdFnForWatch = hasMdInputs ? renderMdForWatch : void 0;
14000
- const watchHandle = await startWatchMode(
14001
- expandedInputs,
14002
- renderForWatch,
14003
- void 0,
14004
- void 0,
14005
- void 0,
14006
- renderMdFnForWatch
13821
+ process.exit(1);
13822
+ }
13823
+ const inputArg = expandedInputs[0];
13824
+ if (args.md && inputArg !== "-" && !/\.(?:md|markdown)$/i.test(inputArg)) {
13825
+ process.stderr.write(
13826
+ `Error: --md flag requires a .md or .markdown input file, got: ${inputArg}
13827
+ `
14007
13828
  );
13829
+ process.exit(1);
13830
+ }
13831
+ if (args.watch) {
13832
+ const renderForWatch = (input) => isMdMode ? renderMarkdownFile(input, args, config) : renderOneFile(input, args, config);
13833
+ const watchHandle = await startWatchMode(expandedInputs, renderForWatch);
14008
13834
  process.on("SIGINT", () => {
14009
13835
  watchHandle.shutdown();
14010
13836
  process.exit(0);
@@ -14013,16 +13839,26 @@ async function main() {
14013
13839
  });
14014
13840
  return;
14015
13841
  }
13842
+ if (isMdMode) {
13843
+ try {
13844
+ await renderMarkdownFile(inputArg, args, config);
13845
+ process.exit(0);
13846
+ } catch (err) {
13847
+ process.stderr.write(`Error: ${err.message}
13848
+ `);
13849
+ process.exit(1);
13850
+ }
13851
+ }
14016
13852
  let rendered = 0;
14017
13853
  let errors = 0;
14018
- for (const inputArg of expandedInputs) {
13854
+ for (const inputArg2 of expandedInputs) {
14019
13855
  if (!args.quiet) {
14020
- const displayName = inputArg === "-" ? "<stdin>" : inputArg;
13856
+ const displayName = inputArg2 === "-" ? "<stdin>" : inputArg2;
14021
13857
  process.stderr.write(`Rendering ${displayName}...
14022
13858
  `);
14023
13859
  }
14024
13860
  try {
14025
- await renderOneFile(inputArg, args, {
13861
+ await renderOneFile(inputArg2, args, {
14026
13862
  configScale,
14027
13863
  configTheme,
14028
13864
  configOutputFormat,
@@ -14031,7 +13867,7 @@ async function main() {
14031
13867
  rendered++;
14032
13868
  } catch (err) {
14033
13869
  errors++;
14034
- process.stderr.write(`Error: ${inputArg}: ${err.message}
13870
+ process.stderr.write(`Error: ${inputArg2}: ${err.message}
14035
13871
  `);
14036
13872
  }
14037
13873
  }