@zenuml/core 4.2.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
@@ -10877,10 +10877,22 @@ class FragmentAltVM extends FragmentVM {
10877
10877
  }
10878
10878
  }
10879
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
+
10880
10891
  class FragmentSingleBlockVM extends FragmentVM {
10881
- constructor(statement, fragment, runtime) {
10892
+ constructor(statement, fragment, runtime, kind) {
10882
10893
  super(statement, runtime);
10883
10894
  this.fragment = fragment;
10895
+ this.kind = kind;
10884
10896
  }
10885
10897
  measure(top, origin) {
10886
10898
  const commentHeight = this.measureComment(this.fragment);
@@ -10901,37 +10913,6 @@ class FragmentSingleBlockVM extends FragmentVM {
10901
10913
  }
10902
10914
  }
10903
10915
 
10904
- class FragmentCriticalVM extends FragmentSingleBlockVM {
10905
- kind = "critical";
10906
- }
10907
-
10908
- class FragmentLoopVM extends FragmentSingleBlockVM {
10909
- kind = "loop";
10910
- }
10911
-
10912
- class FragmentOptVM extends FragmentSingleBlockVM {
10913
- kind = "opt";
10914
- }
10915
-
10916
- class FragmentParVM extends FragmentSingleBlockVM {
10917
- kind = "par";
10918
- }
10919
-
10920
- class FragmentRefVM extends FragmentVM {
10921
- kind = "ref";
10922
- measure(top) {
10923
- const context = this.context?.ref?.() || this.context;
10924
- const commentHeight = this.measureComment(context);
10925
- const headerHeight = this.metrics.fragmentHeaderHeight;
10926
- const height = commentHeight + headerHeight + this.metrics.fragmentPaddingBottom;
10927
- return { top, height, kind: this.kind };
10928
- }
10929
- }
10930
-
10931
- class FragmentSectionVM extends FragmentSingleBlockVM {
10932
- kind = "section";
10933
- }
10934
-
10935
10916
  class FragmentTryCatchVM extends FragmentVM {
10936
10917
  constructor(statement, tcf, runtime) {
10937
10918
  super(statement, runtime);
@@ -11061,25 +11042,11 @@ const createStatementVM = (statement, runtime) => {
11061
11042
  if (statement.divider?.()) {
11062
11043
  return new DividerStatementVM(statement, runtime);
11063
11044
  }
11064
- const loop = statement.loop?.();
11065
- if (loop) {
11066
- return new FragmentLoopVM(statement, loop, runtime);
11067
- }
11068
- const opt = statement.opt?.();
11069
- if (opt) {
11070
- return new FragmentOptVM(statement, opt, runtime);
11071
- }
11072
- const par = statement.par?.();
11073
- if (par) {
11074
- return new FragmentParVM(statement, par, runtime);
11075
- }
11076
- const section = statement.section?.();
11077
- if (section) {
11078
- return new FragmentSectionVM(statement, section, runtime);
11079
- }
11080
- const critical = statement.critical?.();
11081
- if (critical) {
11082
- 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
+ }
11083
11050
  }
11084
11051
  const tcf = statement.tcf?.();
11085
11052
  if (tcf) {
@@ -13657,6 +13624,69 @@ async function checkOne(input) {
13657
13624
  errors
13658
13625
  };
13659
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
+ }
13660
13690
  async function main() {
13661
13691
  if (!globalThis.OffscreenCanvas && typeof document === "undefined") {
13662
13692
  try {
@@ -13760,146 +13790,6 @@ async function main() {
13760
13790
  process.stdout.write(JSON.stringify(ast, null, 2) + "\n");
13761
13791
  process.exit(0);
13762
13792
  }
13763
- const isMdMode = args.md || expandedInputs.some((f) => f !== "-" && /\.(?:md|markdown)$/i.test(f));
13764
- if (isMdMode) {
13765
- if (expandedInputs.length > 1) {
13766
- process.stderr.write(
13767
- "Error: --md mode supports only a single input file.\n"
13768
- );
13769
- process.exit(1);
13770
- }
13771
- const inputArg = expandedInputs[0];
13772
- if (args.md && inputArg !== "-") {
13773
- const ext = extname(inputArg).toLowerCase();
13774
- if (ext !== ".md" && ext !== ".markdown") {
13775
- process.stderr.write(
13776
- `Error: --md flag requires a .md or .markdown input file, got: ${inputArg}
13777
- `
13778
- );
13779
- process.exit(1);
13780
- }
13781
- }
13782
- let mdContent;
13783
- try {
13784
- mdContent = await readCode(inputArg);
13785
- } catch (err) {
13786
- process.stderr.write(`Error: ${err.message}
13787
- `);
13788
- process.exit(1);
13789
- }
13790
- const effectiveFormat = args.outputFormat ?? "svg";
13791
- if (effectiveFormat !== "svg" && effectiveFormat !== "png") {
13792
- process.stderr.write(
13793
- `Error: Unsupported output format: "${effectiveFormat}". Use "svg" or "png".
13794
- `
13795
- );
13796
- process.exit(1);
13797
- }
13798
- let imageDir;
13799
- let mdOutputPath;
13800
- if (args.output && args.output !== "-") {
13801
- const resolvedOutput = resolve(args.output);
13802
- imageDir = dirname(resolvedOutput);
13803
- mdOutputPath = resolvedOutput;
13804
- } else if (args.output === "-") {
13805
- if (inputArg !== "-") {
13806
- imageDir = dirname(resolve(inputArg));
13807
- } else {
13808
- imageDir = process.cwd();
13809
- }
13810
- mdOutputPath = "-";
13811
- } else {
13812
- if (inputArg !== "-") {
13813
- const resolvedInput = resolve(inputArg);
13814
- const inputDir = dirname(resolvedInput);
13815
- const ext = extname(inputArg);
13816
- const stem = basename(inputArg, ext);
13817
- imageDir = inputDir;
13818
- mdOutputPath = join(inputDir, `${stem}-rendered.md`);
13819
- } else {
13820
- imageDir = process.cwd();
13821
- mdOutputPath = "-";
13822
- }
13823
- }
13824
- let imageStem;
13825
- if (inputArg !== "-") {
13826
- const ext = extname(inputArg);
13827
- imageStem = basename(inputArg, ext);
13828
- } else if (mdOutputPath !== "-") {
13829
- const ext = extname(mdOutputPath);
13830
- imageStem = basename(mdOutputPath, ext);
13831
- } else {
13832
- imageStem = "diagram";
13833
- }
13834
- const blocks = extractZenumlBlocks(mdContent);
13835
- const effectiveScale = args.scale ?? 2;
13836
- const effectiveTheme = args.theme;
13837
- const renderOptions = {};
13838
- if (effectiveTheme) {
13839
- renderOptions.theme = effectiveTheme;
13840
- }
13841
- const imageFiles = /* @__PURE__ */ new Map();
13842
- for (const block of blocks) {
13843
- if (block.empty) continue;
13844
- const imageFilename = `${imageStem}-zenuml-${block.index}.${effectiveFormat}`;
13845
- const imageFilePath = join(imageDir, imageFilename);
13846
- let svg;
13847
- let svgWidth;
13848
- let svgHeight;
13849
- try {
13850
- const result = renderToSvg(block.code, renderOptions);
13851
- svg = result.svg;
13852
- svgWidth = result.width;
13853
- svgHeight = result.height;
13854
- } catch (err) {
13855
- process.stderr.write(
13856
- `Error: Failed to render zenuml block ${block.index}: ${err.message}
13857
- `
13858
- );
13859
- process.exit(1);
13860
- }
13861
- mkdirSync(imageDir, { recursive: true });
13862
- if (effectiveFormat === "png") {
13863
- const pngBuffer = await rasterizeToPng(
13864
- svg,
13865
- svgWidth,
13866
- svgHeight,
13867
- effectiveScale
13868
- );
13869
- writeFileSync(imageFilePath, pngBuffer);
13870
- } else {
13871
- writeFileSync(imageFilePath, svg, "utf-8");
13872
- }
13873
- if (!args.quiet) {
13874
- process.stderr.write(`Wrote ${imageFilePath}
13875
- `);
13876
- }
13877
- imageFiles.set(block.index, imageFilename);
13878
- }
13879
- let outputMd = mdContent;
13880
- const sortedBlocks = [...blocks].reverse();
13881
- for (const block of sortedBlocks) {
13882
- const altText = block.title || `diagram ${block.index + 1}`;
13883
- if (block.empty) {
13884
- outputMd = outputMd.replace(block.raw, "");
13885
- } else {
13886
- const imageFilename = imageFiles.get(block.index);
13887
- const replacement = `![${altText}](${imageFilename})`;
13888
- outputMd = outputMd.replace(block.raw, replacement);
13889
- }
13890
- }
13891
- if (mdOutputPath === "-") {
13892
- process.stdout.write(outputMd);
13893
- } else {
13894
- mkdirSync(dirname(mdOutputPath), { recursive: true });
13895
- writeFileSync(mdOutputPath, outputMd, "utf-8");
13896
- if (!args.quiet) {
13897
- process.stderr.write(`Wrote ${mdOutputPath}
13898
- `);
13899
- }
13900
- }
13901
- process.exit(0);
13902
- }
13903
13793
  let configScale;
13904
13794
  let configTheme;
13905
13795
  let configOutputFormat;
@@ -13917,99 +13807,30 @@ async function main() {
13917
13807
  );
13918
13808
  process.exit(1);
13919
13809
  }
13920
- if (args.watch) {
13921
- const renderForWatch = async (inputArg) => {
13922
- await renderOneFile(inputArg, args, {
13923
- configScale,
13924
- configTheme,
13925
- configOutputFormat});
13926
- };
13927
- const renderMdForWatch = async (inputArg) => {
13928
- let mdContent;
13929
- try {
13930
- mdContent = readFileSync(resolve(inputArg), "utf-8");
13931
- } catch {
13932
- throw new Error(`Cannot read input file: ${resolve(inputArg)}`);
13933
- }
13934
- const effectiveFormat = args.outputFormat ?? "svg";
13935
- if (effectiveFormat !== "svg" && effectiveFormat !== "png") {
13936
- throw new Error(
13937
- `Unsupported output format: "${effectiveFormat}". Use "svg" or "png".`
13938
- );
13939
- }
13940
- let mdOutputPath;
13941
- let imageDir;
13942
- if (args.output && args.output !== "-") {
13943
- const resolvedOutput = resolve(args.output);
13944
- imageDir = dirname(resolvedOutput);
13945
- mdOutputPath = resolvedOutput;
13946
- } else if (args.output === "-") {
13947
- imageDir = dirname(resolve(inputArg));
13948
- mdOutputPath = "-";
13949
- } else {
13950
- const resolvedInput = resolve(inputArg);
13951
- const inputDir = dirname(resolvedInput);
13952
- const ext2 = extname(inputArg);
13953
- const stem = basename(inputArg, ext2);
13954
- imageDir = inputDir;
13955
- mdOutputPath = join(inputDir, `${stem}-rendered.md`);
13956
- }
13957
- const ext = extname(inputArg);
13958
- const imageStem = basename(inputArg, ext);
13959
- const blocks = extractZenumlBlocks(mdContent);
13960
- const effectiveScale = args.scale ?? configScale ?? 2;
13961
- const imageFiles = /* @__PURE__ */ new Map();
13962
- for (const block of blocks) {
13963
- if (block.empty) continue;
13964
- const imageFilename = `${imageStem}-zenuml-${block.index}.${effectiveFormat}`;
13965
- const imageFilePath = join(imageDir, imageFilename);
13966
- const result = renderToSvg(block.code);
13967
- const { svg, width: svgWidth, height: svgHeight } = result;
13968
- mkdirSync(imageDir, { recursive: true });
13969
- if (effectiveFormat === "png") {
13970
- const pngBuffer = await rasterizeToPng(
13971
- svg,
13972
- svgWidth,
13973
- svgHeight,
13974
- effectiveScale
13975
- );
13976
- writeFileSync(imageFilePath, pngBuffer);
13977
- } else {
13978
- writeFileSync(imageFilePath, svg, "utf-8");
13979
- }
13980
- imageFiles.set(block.index, imageFilename);
13981
- }
13982
- let outputMd = mdContent;
13983
- const sortedBlocks = [...blocks].reverse();
13984
- for (const block of sortedBlocks) {
13985
- const altText = block.title || `diagram ${block.index + 1}`;
13986
- if (block.empty) {
13987
- outputMd = outputMd.replace(block.raw, "");
13988
- } else {
13989
- const imageFilename = imageFiles.get(block.index);
13990
- const replacement = `![${altText}](${imageFilename})`;
13991
- outputMd = outputMd.replace(block.raw, replacement);
13992
- }
13993
- }
13994
- if (mdOutputPath === "-") {
13995
- process.stdout.write(outputMd);
13996
- } else {
13997
- mkdirSync(dirname(mdOutputPath), { recursive: true });
13998
- writeFileSync(mdOutputPath, outputMd, "utf-8");
13999
- }
14000
- };
14001
- const hasMdInputs = expandedInputs.some(
14002
- (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"
14003
13820
  );
14004
- const renderMdFnForWatch = hasMdInputs ? renderMdForWatch : void 0;
14005
- const watchHandle = await startWatchMode(
14006
- expandedInputs,
14007
- renderForWatch,
14008
- void 0,
14009
- void 0,
14010
- void 0,
14011
- 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
+ `
14012
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);
14013
13834
  process.on("SIGINT", () => {
14014
13835
  watchHandle.shutdown();
14015
13836
  process.exit(0);
@@ -14018,16 +13839,26 @@ async function main() {
14018
13839
  });
14019
13840
  return;
14020
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
+ }
14021
13852
  let rendered = 0;
14022
13853
  let errors = 0;
14023
- for (const inputArg of expandedInputs) {
13854
+ for (const inputArg2 of expandedInputs) {
14024
13855
  if (!args.quiet) {
14025
- const displayName = inputArg === "-" ? "<stdin>" : inputArg;
13856
+ const displayName = inputArg2 === "-" ? "<stdin>" : inputArg2;
14026
13857
  process.stderr.write(`Rendering ${displayName}...
14027
13858
  `);
14028
13859
  }
14029
13860
  try {
14030
- await renderOneFile(inputArg, args, {
13861
+ await renderOneFile(inputArg2, args, {
14031
13862
  configScale,
14032
13863
  configTheme,
14033
13864
  configOutputFormat,
@@ -14036,7 +13867,7 @@ async function main() {
14036
13867
  rendered++;
14037
13868
  } catch (err) {
14038
13869
  errors++;
14039
- process.stderr.write(`Error: ${inputArg}: ${err.message}
13870
+ process.stderr.write(`Error: ${inputArg2}: ${err.message}
14040
13871
  `);
14041
13872
  }
14042
13873
  }