@mermaid-js/mermaid-cli 10.9.0 → 11.1.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,5 +1,5 @@
1
1
  /**
2
- * Options to pass to {@link parseMMD }
2
+ * Options to pass to {@link parseMMD}
3
3
  */
4
4
  export type ParseMDDOptions = {
5
5
  /**
@@ -52,7 +52,7 @@ export type MarkdownImageProps = {
52
52
  * path to a markdown file containing mermaid.
53
53
  * If this is a string, loads the mermaid definition from the given file.
54
54
  * If this is `undefined`, loads the mermaid definition from stdin.
55
- * @param {`${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}`} output - Path to the output file.
55
+ * @param {`${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}` | "/dev/stdout"} output - Path to the output file.
56
56
  * @param {Object} [opts] - Options
57
57
  * @param {import("puppeteer").LaunchOptions} [opts.puppeteerConfig] - Puppeteer launch options.
58
58
  * @param {boolean} [opts.quiet] - If set, suppress log output.
@@ -60,27 +60,12 @@ export type MarkdownImageProps = {
60
60
  * Defaults to `output` extension. Overrides `output` extension if set.
61
61
  * @param {ParseMDDOptions} [opts.parseMMDOptions] - Options to pass to {@link parseMMDOptions}.
62
62
  */
63
- export function run(input: `${string}.${"md" | "markdown"}` | string | undefined, output: `${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}`, { puppeteerConfig, quiet, outputFormat, parseMMDOptions }?: {
63
+ export function run(input: `${string}.${"md" | "markdown"}` | string | undefined, output: `${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}` | "/dev/stdout", { puppeteerConfig, quiet, outputFormat, parseMMDOptions }?: {
64
64
  puppeteerConfig?: puppeteer.LaunchOptions | undefined;
65
65
  quiet?: boolean | undefined;
66
66
  outputFormat?: "svg" | "png" | "pdf" | undefined;
67
67
  parseMMDOptions?: ParseMDDOptions | undefined;
68
68
  } | undefined): Promise<void>;
69
- /**
70
- * Render a mermaid diagram.
71
- *
72
- * @param {import("puppeteer").Browser} browser - Puppeteer Browser
73
- * @param {string} definition - Mermaid diagram definition
74
- * @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
75
- * @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
76
- * @returns {Promise<{title: string | null, desc: string | null, data: Buffer}>} The output file in bytes,
77
- * with optional metadata.
78
- */
79
- export function renderMermaid(browser: import("puppeteer").Browser, definition: string, outputFormat: "svg" | "png" | "pdf", { viewport, backgroundColor, mermaidConfig, myCSS, pdfFit, svgId }?: ParseMDDOptions | undefined): Promise<{
80
- title: string | null;
81
- desc: string | null;
82
- data: Buffer;
83
- }>;
84
69
  /**
85
70
  * @typedef {Object} ParseMDDOptions Options to pass to {@link parseMMD}
86
71
  * @property {import("puppeteer").Viewport} [viewport] - Puppeteer viewport (e.g. `width`, `height`, `deviceScaleFactor`)
@@ -91,18 +76,20 @@ export function renderMermaid(browser: import("puppeteer").Browser, definition:
91
76
  * @property {string} [svgId] - The id attribute for the SVG element to be rendered.
92
77
  */
93
78
  /**
94
- * Parse and render a mermaid diagram.
95
- *
96
- * @deprecated Prefer {@link renderMermaid}, as it also returns useful metadata.
79
+ * Render a mermaid diagram.
97
80
  *
98
81
  * @param {import("puppeteer").Browser} browser - Puppeteer Browser
99
82
  * @param {string} definition - Mermaid diagram definition
100
83
  * @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
101
84
  * @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
102
- *
103
- * @returns {Promise<Buffer>} The output file in bytes.
85
+ * @returns {Promise<{title: string | null, desc: string | null, data: Uint8Array}>} The output file in bytes,
86
+ * with optional metadata.
104
87
  */
105
- export function parseMMD(browser: import("puppeteer").Browser, definition: string, outputFormat: "svg" | "png" | "pdf", opt?: ParseMDDOptions | undefined): Promise<Buffer>;
88
+ export function renderMermaid(browser: import("puppeteer").Browser, definition: string, outputFormat: "svg" | "png" | "pdf", { viewport, backgroundColor, mermaidConfig, myCSS, pdfFit, svgId }?: ParseMDDOptions | undefined): Promise<{
89
+ title: string | null;
90
+ desc: string | null;
91
+ data: Uint8Array;
92
+ }>;
106
93
  export function cli(): Promise<void>;
107
94
  /**
108
95
  * Prints an error to stderr, then closes with exit code 1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SA2Wc,MAAM;;;;SACN,MAAM;;;;;;AAqBpB;;;;;;;;;;;;;;GAcG;AACH,2BAZW,GAAG,MAAM,IAAI,IAAI,GAAG,UAAU,EAAE,GAAG,MAAM,GAAG,SAAS,UAIrD,GAAG,MAAM,IAAI,IAAI,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,EAAE;;;;;8BAwGlE;AA1QD;;;;;;;;;GASG;AACH,uCAPW,OAAO,WAAW,EAAE,OAAO,cAC3B,MAAM,gBACN,KAAK,GAAG,KAAK,GAAG,KAAK,qGAEnB,QAAQ;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAC,CAyH9E;AA3JD;;;;;;;;GAQG;AAEH;;;;;;;;;;;GAWG;AACH,kCAPW,OAAO,WAAW,EAAE,OAAO,cAC3B,MAAM,gBACN,KAAK,GAAG,KAAK,GAAG,KAAK,sCAGnB,QAAQ,MAAM,CAAC,CAK3B;AA3HD,qCAgGC;AApLD;;;;;GAKG;AACH,+BAHW,MAAM,GACJ,KAAK,CAKjB;sBA1BqB,WAAW"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAuWc,MAAM;;;;SACN,MAAM;;;;;;AAqBpB;;;;;;;;;;;;;;GAcG;AACH,2BAZW,GAAG,MAAM,IAAI,IAAI,GAAG,UAAU,EAAE,GAAG,MAAM,GAAG,SAAS,UAIrD,GAAG,MAAM,IAAI,IAAI,GAAG,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,EAAE,GAAG,aAAa;;;;;8BAsHlF;AApSD;;;;;;;;GAQG;AAEH;;;;;;;;;GASG;AACH,uCAPW,OAAO,WAAW,EAAE,OAAO,cAC3B,MAAM,gBACN,KAAK,GAAG,KAAK,GAAG,KAAK,qGAEnB,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAC,CAAC,CA2HlF;AAzPD,qCA2GC;AA/LD;;;;;GAKG;AACH,+BAHW,MAAM,GACJ,KAAK,CAKjB;sBA1BqB,WAAW"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mermaid-js/mermaid-cli",
3
- "version": "10.9.0",
3
+ "version": "11.1.1",
4
4
  "description": "Command-line interface for mermaid",
5
5
  "license": "MIT",
6
6
  "repository": "git@github.com:mermaid-js/mermaid-cli.git",
@@ -10,7 +10,7 @@
10
10
  "mmdc": "./src/cli.js"
11
11
  },
12
12
  "engines": {
13
- "node": "^14.13 || >=16.0"
13
+ "node": "^18.19 || >=20.0"
14
14
  },
15
15
  "exports": {
16
16
  ".": {
@@ -24,21 +24,26 @@
24
24
  "scripts": {
25
25
  "prepare": "tsc && vite build",
26
26
  "prepack": "tsc && vite build",
27
- "test": "standard && yarn node --experimental-vm-modules $(yarn bin jest)",
27
+ "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" npx jest",
28
28
  "lint": "standard",
29
29
  "lint-fix": "standard --fix"
30
30
  },
31
31
  "dependencies": {
32
32
  "chalk": "^5.0.1",
33
- "commander": "^10.0.0",
34
- "mermaid": "^10.8.0",
35
- "puppeteer": "^19.0.0"
33
+ "commander": "^12.1.0",
34
+ "mermaid": "^11.0.2"
35
+ },
36
+ "peerDependencies": {
37
+ "puppeteer": "^23"
36
38
  },
37
39
  "devDependencies": {
38
- "@fortawesome/fontawesome-free": "^5.6.0",
40
+ "@fortawesome/fontawesome-free": "^6.5.2",
41
+ "@mermaid-js/layout-elk": "^0.1.2",
39
42
  "@mermaid-js/mermaid-zenuml": "^0.2.0",
40
- "@tsconfig/node14": "^14.1.0",
43
+ "@tsconfig/node18": "^18.2.4",
44
+ "@types/node": "~18.19.31",
41
45
  "jest": "^29.0.1",
46
+ "puppeteer": "^23.1.1",
42
47
  "standard": "^17.0.0",
43
48
  "typescript": "^5.0.1-rc",
44
49
  "vite": "^4.0.3",
@@ -61,5 +66,6 @@
61
66
  "/dist/",
62
67
  "/dist-types/"
63
68
  ]
64
- }
69
+ },
70
+ "packageManager": "npm@10.8.1"
65
71
  }
package/src/index.js CHANGED
@@ -111,7 +111,7 @@ async function cli () {
111
111
  .addOption(new Option('-w, --width [width]', 'Width of the page').argParser(parseCommanderInt).default(800))
112
112
  .addOption(new Option('-H, --height [height]', 'Height of the page').argParser(parseCommanderInt).default(600))
113
113
  .option('-i, --input <input>', 'Input mermaid file. Files ending in .md will be treated as Markdown and all charts (e.g. ```mermaid (...)``` or :::mermaid (...):::) will be extracted and generated. Use `-` to read from stdin.')
114
- .option('-o, --output [output]', 'Output file. It should be either md, svg, png or pdf. Optional. Default: input + ".svg"')
114
+ .option('-o, --output [output]', 'Output file. It should be either md, svg, png, pdf or use `-` to output to stdout. Optional. Default: input + ".svg"')
115
115
  .addOption(new Option('-e, --outputFormat [format]', 'Output format for the generated image.').choices(['svg', 'png', 'pdf']).default(null, 'Loaded from the output file extension'))
116
116
  .addOption(new Option('-b, --backgroundColor [backgroundColor]', 'Background color for pngs/svgs (not pdfs). Example: transparent, red, \'#F0F0F0\'.').default('white'))
117
117
  .option('-c, --configFile [configFile]', 'JSON configuration file for mermaid.')
@@ -150,12 +150,24 @@ async function cli () {
150
150
  } else {
151
151
  output = input ? (`${input}.svg`) : 'out.svg'
152
152
  }
153
- }
154
- if (!/\.(?:svg|png|pdf|md|markdown)$/.test(output)) {
153
+ } else if (output === '-') {
154
+ // `--output -` means write to stdout.
155
+ output = '/dev/stdout'
156
+ quiet = true
157
+
158
+ if (!outputFormat) {
159
+ outputFormat = 'svg'
160
+ warn('No output format specified, using svg. ' +
161
+ 'If you want to specify an output format and supress this warning, ' +
162
+ 'please use `-e <format>.` '
163
+ )
164
+ }
165
+ } else if (!/\.(?:svg|png|pdf|md|markdown)$/.test(output)) {
155
166
  error('Output file must end with ".md"/".markdown", ".svg", ".png" or ".pdf"')
156
167
  }
168
+
157
169
  const outputDir = path.dirname(output)
158
- if (!fs.existsSync(outputDir)) {
170
+ if (output !== '/dev/stdout' && !fs.existsSync(outputDir)) {
159
171
  error(`Output directory "${outputDir}/" doesn't exist`)
160
172
  }
161
173
 
@@ -165,15 +177,14 @@ async function cli () {
165
177
  checkConfigFile(configFile)
166
178
  mermaidConfig = Object.assign(mermaidConfig, JSON.parse(fs.readFileSync(configFile, 'utf-8')))
167
179
  }
168
- // @ts-expect-error Setting headless to `1` is not officially supported
180
+
169
181
  let puppeteerConfig = /** @type {import('puppeteer').PuppeteerLaunchOptions} */ ({
170
182
  /*
171
- * `headless: 1` is not officially supported, but setting this to any
172
- * non-`true` truthy value doesn't change any behavior, but it hides the
173
- * Puppeteer old Headless deprecation warning,
174
- * see https://github.com/argos-ci/jest-puppeteer/issues/553#issuecomment-1561826456
183
+ * `headless: 'shell'` is not officially supported in Puppeteer v19, v20, v21,
184
+ * but still works. In Puppeteer v22, it uses the `chrome-headless-shell` package,
185
+ * which is much faster than the regular headless mode.
175
186
  */
176
- headless: 1
187
+ headless: 'shell'
177
188
  })
178
189
  if (puppeteerConfigFile) {
179
190
  checkConfigFile(puppeteerConfigFile)
@@ -211,23 +222,6 @@ async function cli () {
211
222
  * @property {string} [svgId] - The id attribute for the SVG element to be rendered.
212
223
  */
213
224
 
214
- /**
215
- * Parse and render a mermaid diagram.
216
- *
217
- * @deprecated Prefer {@link renderMermaid}, as it also returns useful metadata.
218
- *
219
- * @param {import("puppeteer").Browser} browser - Puppeteer Browser
220
- * @param {string} definition - Mermaid diagram definition
221
- * @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
222
- * @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
223
- *
224
- * @returns {Promise<Buffer>} The output file in bytes.
225
- */
226
- async function parseMMD (browser, definition, outputFormat, opt) {
227
- const { data } = await renderMermaid(browser, definition, outputFormat, opt)
228
- return data
229
- }
230
-
231
225
  /**
232
226
  * Render a mermaid diagram.
233
227
  *
@@ -235,13 +229,13 @@ async function parseMMD (browser, definition, outputFormat, opt) {
235
229
  * @param {string} definition - Mermaid diagram definition
236
230
  * @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
237
231
  * @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
238
- * @returns {Promise<{title: string | null, desc: string | null, data: Buffer}>} The output file in bytes,
232
+ * @returns {Promise<{title: string | null, desc: string | null, data: Uint8Array}>} The output file in bytes,
239
233
  * with optional metadata.
240
234
  */
241
235
  async function renderMermaid (browser, definition, outputFormat, { viewport, backgroundColor = 'white', mermaidConfig = {}, myCSS, pdfFit, svgId } = {}) {
242
236
  const page = await browser.newPage()
243
237
  page.on('console', (msg) => {
244
- console.log(msg.text())
238
+ console.warn(msg.text())
245
239
  })
246
240
  try {
247
241
  if (viewport) {
@@ -262,10 +256,12 @@ async function renderMermaid (browser, definition, outputFormat, { viewport, bac
262
256
  * so that they get correctly bundled.
263
257
  * @property {import("mermaid")["default"]} mermaid Already imported mermaid instance
264
258
  * @property {import("@mermaid-js/mermaid-zenuml")["default"]} zenuml Already imported mermaid-zenuml instance
259
+ * @property {import("@mermaid-js/layout-elk")["default"]} elkLayouts Already imported mermaid-elkLayouts instance
265
260
  */
266
- const { mermaid, zenuml } = /** @type {GlobalThisWithMermaid & typeof globalThis} */ (globalThis)
261
+ const { mermaid, zenuml, elkLayouts } = /** @type {GlobalThisWithMermaid & typeof globalThis} */ (globalThis)
267
262
 
268
263
  await mermaid.registerExternalDiagrams([zenuml])
264
+ mermaid.registerLayoutLoaders(elkLayouts)
269
265
  mermaid.initialize({ startOnLoad: false, ...mermaidConfig })
270
266
  // should throw an error if mmd diagram is invalid
271
267
  const { svg: svgText } = await mermaid.render(svgId || 'my-svg', definition, container)
@@ -390,7 +386,7 @@ function markdownImage ({ url, title, alt }) {
390
386
  * path to a markdown file containing mermaid.
391
387
  * If this is a string, loads the mermaid definition from the given file.
392
388
  * If this is `undefined`, loads the mermaid definition from stdin.
393
- * @param {`${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}`} output - Path to the output file.
389
+ * @param {`${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}` | "/dev/stdout"} output - Path to the output file.
394
390
  * @param {Object} [opts] - Options
395
391
  * @param {import("puppeteer").LaunchOptions} [opts.puppeteerConfig] - Puppeteer launch options.
396
392
  * @param {boolean} [opts.quiet] - If set, suppress log output.
@@ -413,7 +409,11 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
413
409
  // TODO: should we use a Markdown parser like remark instead of rolling our own parser?
414
410
  const mermaidChartsInMarkdown = /^[^\S\n]*[`:]{3}(?:mermaid)([^\S\n]*\r?\n([\s\S]*?))[`:]{3}[^\S\n]*$/
415
411
  const mermaidChartsInMarkdownRegexGlobal = new RegExp(mermaidChartsInMarkdown, 'gm')
416
- const browser = await puppeteer.launch(puppeteerConfig)
412
+ /**
413
+ * @type {puppeteer.Browser | undefined}
414
+ * Lazy-loaded browser instance, only created when needed.
415
+ */
416
+ let browser
417
417
  try {
418
418
  if (!outputFormat) {
419
419
  const outputFormatFromFilename =
@@ -433,8 +433,15 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
433
433
 
434
434
  const definition = await getInputData(input)
435
435
  if (input && /\.(md|markdown)$/.test(input)) {
436
+ if (output === '/dev/stdout') {
437
+ throw new Error('Cannot use `stdout` with markdown input')
438
+ }
439
+
436
440
  const imagePromises = []
437
441
  for (const mermaidCodeblockMatch of definition.matchAll(mermaidChartsInMarkdownRegexGlobal)) {
442
+ if (browser === undefined) {
443
+ browser = await puppeteer.launch(puppeteerConfig)
444
+ }
438
445
  const mermaidDefinition = mermaidCodeblockMatch[2]
439
446
 
440
447
  /** Output can be either a template image file, or a `.md` output file.
@@ -488,12 +495,15 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
488
495
  }
489
496
  } else {
490
497
  info('Generating single mermaid chart')
491
- const data = await parseMMD(browser, definition, outputFormat, parseMMDOptions)
492
- await fs.promises.writeFile(output, data)
498
+ browser = await puppeteer.launch(puppeteerConfig)
499
+ const { data } = await renderMermaid(browser, definition, outputFormat, parseMMDOptions)
500
+ await output !== '/dev/stdout'
501
+ ? fs.promises.writeFile(output, data)
502
+ : process.stdout.write(data)
493
503
  }
494
504
  } finally {
495
- await browser.close()
505
+ await browser?.close?.()
496
506
  }
497
507
  }
498
508
 
499
- export { run, renderMermaid, parseMMD, cli, error }
509
+ export { run, renderMermaid, cli, error }