@mermaid-js/mermaid-cli 9.2.2 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -23
- package/dist/index.html +802 -507
- package/package.json +5 -5
- package/src/index.js +53 -36
- /package/dist/assets/{fa-brands-400.ce2af7e2.svg → fa-brands-400-ce2af7e2.svg} +0 -0
- /package/dist/assets/{fa-regular-400.e519b693.svg → fa-regular-400-e519b693.svg} +0 -0
- /package/dist/assets/{fa-solid-900.3e918c25.svg → fa-solid-900-3e918c25.svg} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mermaid-js/mermaid-cli",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.4.0",
|
|
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": "
|
|
13
|
+
"node": "^14.13 || >=16.0"
|
|
14
14
|
},
|
|
15
15
|
"exports": "./src/index.js",
|
|
16
16
|
"scripts": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"chalk": "^5.0.1",
|
|
25
|
-
"commander": "^
|
|
25
|
+
"commander": "^10.0.0",
|
|
26
26
|
"puppeteer": "^19.0.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"mermaid": "^9.2.2",
|
|
32
32
|
"jest": "^29.0.1",
|
|
33
33
|
"standard": "^17.0.0",
|
|
34
|
-
"vite": "^
|
|
34
|
+
"vite": "^4.0.3",
|
|
35
35
|
"vite-plugin-singlefile": "^0.13.1",
|
|
36
|
-
"vite-svg-loader": "^
|
|
36
|
+
"vite-svg-loader": "^4.0.0",
|
|
37
37
|
"yarn-upgrade-all": "^0.7.0"
|
|
38
38
|
},
|
|
39
39
|
"files": [
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Command } from 'commander'
|
|
1
|
+
import { Command, Option, InvalidArgumentError } from 'commander'
|
|
2
2
|
import chalk from 'chalk'
|
|
3
3
|
import fs from 'fs'
|
|
4
4
|
import path from 'path'
|
|
@@ -18,7 +18,7 @@ const error = message => {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const warn = message => {
|
|
21
|
-
console.
|
|
21
|
+
console.warn(chalk.yellow(`\n${message}\n`))
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const checkConfigFile = file => {
|
|
@@ -27,8 +27,6 @@ const checkConfigFile = file => {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
const inputPipedFromStdin = () => fs.fstatSync(0).isFIFO()
|
|
31
|
-
|
|
32
30
|
const getInputData = async inputFile => new Promise((resolve, reject) => {
|
|
33
31
|
// if an input file has been specified using '-i', it takes precedence over
|
|
34
32
|
// piping from stdin
|
|
@@ -60,23 +58,40 @@ const getInputData = async inputFile => new Promise((resolve, reject) => {
|
|
|
60
58
|
})
|
|
61
59
|
})
|
|
62
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Commander parser that converts a string to an integer.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} value - The value from commander.
|
|
65
|
+
* @param {*} _unused - Unused.
|
|
66
|
+
* @returns {number} The value parsed as a number.
|
|
67
|
+
* @throws {InvalidArgumentError} If the arg is not valid.
|
|
68
|
+
* @see https://github.com/tj/commander.js/wiki/Class:-Option#argparserfn
|
|
69
|
+
*/
|
|
70
|
+
function parseCommanderInt (value, _unused) {
|
|
71
|
+
const parsedValue = parseInt(value, 10)
|
|
72
|
+
if (isNaN(parsedValue) || parsedValue < 1) {
|
|
73
|
+
throw new InvalidArgumentError('Not an positive integer.')
|
|
74
|
+
}
|
|
75
|
+
return parsedValue
|
|
76
|
+
}
|
|
77
|
+
|
|
63
78
|
async function cli () {
|
|
64
79
|
const commander = new Command()
|
|
65
80
|
commander
|
|
66
81
|
.version(pkg.version)
|
|
67
|
-
.
|
|
68
|
-
.
|
|
69
|
-
.
|
|
70
|
-
.option('-i, --input <input>', 'Input mermaid file. Files ending in .md will be treated as Markdown and all charts (e.g. ```mermaid (...)```) will be extracted and generated.
|
|
82
|
+
.addOption(new Option('-t, --theme [theme]', 'Theme of the chart').choices(['default', 'forest', 'dark', 'neutral']).default('default'))
|
|
83
|
+
.addOption(new Option('-w, --width [width]', 'Width of the page').argParser(parseCommanderInt).default(800))
|
|
84
|
+
.addOption(new Option('-H, --height [height]', 'Height of the page').argParser(parseCommanderInt).default(600))
|
|
85
|
+
.option('-i, --input <input>', 'Input mermaid file. Files ending in .md will be treated as Markdown and all charts (e.g. ```mermaid (...)```) will be extracted and generated. Use `-` to read from stdin.')
|
|
71
86
|
.option('-o, --output [output]', 'Output file. It should be either md, svg, png or pdf. Optional. Default: input + ".svg"')
|
|
72
|
-
.
|
|
73
|
-
.
|
|
74
|
-
.option('-c, --configFile [configFile]', 'JSON configuration file for mermaid.
|
|
75
|
-
.option('-C, --cssFile [cssFile]', 'CSS file for the page.
|
|
76
|
-
.
|
|
87
|
+
.addOption(new Option('-e, --outputFormat [format]', 'Output format for the generated image.').choices(['svg', 'png', 'pdf']).default(null, 'Loaded from the output file extension'))
|
|
88
|
+
.addOption(new Option('-b, --backgroundColor [backgroundColor]', 'Background color for pngs/svgs (not pdfs). Example: transparent, red, \'#F0F0F0\'.').default('white'))
|
|
89
|
+
.option('-c, --configFile [configFile]', 'JSON configuration file for mermaid.')
|
|
90
|
+
.option('-C, --cssFile [cssFile]', 'CSS file for the page.')
|
|
91
|
+
.addOption(new Option('-s, --scale [scale]', 'Puppeteer scale factor').argParser(parseCommanderInt).default(1))
|
|
77
92
|
.option('-f, --pdfFit [pdfFit]', 'Scale PDF to fit chart')
|
|
78
93
|
.option('-q, --quiet', 'Suppress log output')
|
|
79
|
-
.option('-p --puppeteerConfigFile [puppeteerConfigFile]', 'JSON configuration file for puppeteer.
|
|
94
|
+
.option('-p --puppeteerConfigFile [puppeteerConfigFile]', 'JSON configuration file for puppeteer.')
|
|
80
95
|
.parse(process.argv)
|
|
81
96
|
|
|
82
97
|
const options = commander.opts()
|
|
@@ -84,12 +99,15 @@ async function cli () {
|
|
|
84
99
|
let { theme, width, height, input, output, outputFormat, backgroundColor, configFile, cssFile, puppeteerConfigFile, scale, pdfFit, quiet } = options
|
|
85
100
|
|
|
86
101
|
// check input file
|
|
87
|
-
if (!
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (input
|
|
102
|
+
if (!input) {
|
|
103
|
+
warn('No input file specfied, reading from stdin. ' +
|
|
104
|
+
'If you want to specify an input file, please use `-i <input>.` ' +
|
|
105
|
+
'You can use `-i -` to read from stdin and to suppress this warning.'
|
|
106
|
+
)
|
|
107
|
+
} else if (input === '-') {
|
|
108
|
+
// `--input -` means read from stdin, but suppress the above warning
|
|
109
|
+
input = undefined
|
|
110
|
+
} else if (!fs.existsSync(input)) {
|
|
93
111
|
error(`Input file "${input}" doesn't exist`)
|
|
94
112
|
}
|
|
95
113
|
|
|
@@ -104,8 +122,8 @@ async function cli () {
|
|
|
104
122
|
output = input ? (`${input}.svg`) : 'out.svg'
|
|
105
123
|
}
|
|
106
124
|
}
|
|
107
|
-
if (!/\.(?:svg|png|pdf|md)$/.test(output)) {
|
|
108
|
-
error('Output file must end with ".md", ".svg", ".png" or ".pdf"')
|
|
125
|
+
if (!/\.(?:svg|png|pdf|md|markdown)$/.test(output)) {
|
|
126
|
+
error('Output file must end with ".md"/".markdown", ".svg", ".png" or ".pdf"')
|
|
109
127
|
}
|
|
110
128
|
const outputDir = path.dirname(output)
|
|
111
129
|
if (!fs.existsSync(outputDir)) {
|
|
@@ -133,19 +151,13 @@ async function cli () {
|
|
|
133
151
|
myCSS = fs.readFileSync(cssFile, 'utf-8')
|
|
134
152
|
}
|
|
135
153
|
|
|
136
|
-
// normalize args
|
|
137
|
-
width = parseInt(width)
|
|
138
|
-
height = parseInt(height)
|
|
139
|
-
backgroundColor = backgroundColor || 'white'
|
|
140
|
-
const deviceScaleFactor = parseInt(scale || 1, 10)
|
|
141
|
-
|
|
142
154
|
await run(
|
|
143
155
|
input, output, {
|
|
144
156
|
puppeteerConfig,
|
|
145
157
|
quiet,
|
|
146
158
|
outputFormat,
|
|
147
159
|
parseMMDOptions: {
|
|
148
|
-
mermaidConfig, backgroundColor, myCSS, pdfFit, viewport: { width, height, deviceScaleFactor }
|
|
160
|
+
mermaidConfig, backgroundColor, myCSS, pdfFit, viewport: { width, height, deviceScaleFactor: scale }
|
|
149
161
|
}
|
|
150
162
|
}
|
|
151
163
|
)
|
|
@@ -335,10 +347,11 @@ function markdownImage ({ url, title, alt }) {
|
|
|
335
347
|
/**
|
|
336
348
|
* Renders a mermaid diagram or mermaid markdown file.
|
|
337
349
|
*
|
|
338
|
-
* @param {`${string}
|
|
350
|
+
* @param {`${string}.${"md" | "markdown"}` | string} [input] - If this ends with `.md`/`.markdown`,
|
|
351
|
+
* path to a markdown file containing mermaid.
|
|
339
352
|
* If this is a string, loads the mermaid definition from the given file.
|
|
340
353
|
* If this is `undefined`, loads the mermaid definition from stdin.
|
|
341
|
-
* @param {`${string}.${"md" | "svg" | "png" | "pdf"}`} output - Path to the output file.
|
|
354
|
+
* @param {`${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}`} output - Path to the output file.
|
|
342
355
|
* @param {Object} [opts] - Options
|
|
343
356
|
* @param {puppeteer.LaunchOptions} [opts.puppeteerConfig] - Puppeteer launch options.
|
|
344
357
|
* @param {boolean} [opts.quiet] - If set, suppress log output.
|
|
@@ -353,14 +366,15 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
|
|
|
353
366
|
}
|
|
354
367
|
}
|
|
355
368
|
|
|
356
|
-
|
|
369
|
+
// TODO: should we use a Markdown parser like remark instead of rolling our own parser?
|
|
370
|
+
const mermaidChartsInMarkdown = /^[^\S\n]*```(?:mermaid)(\r?\n([\s\S]*?))```[^\S\n]*$/
|
|
357
371
|
const mermaidChartsInMarkdownRegexGlobal = new RegExp(mermaidChartsInMarkdown, 'gm')
|
|
358
372
|
const browser = await puppeteer.launch(puppeteerConfig)
|
|
359
373
|
try {
|
|
360
374
|
if (!outputFormat) {
|
|
361
375
|
outputFormat = path.extname(output).replace('.', '')
|
|
362
376
|
}
|
|
363
|
-
if (outputFormat === 'md') {
|
|
377
|
+
if (outputFormat === 'md' || outputFormat === 'markdown') {
|
|
364
378
|
// fallback to svg in case no outputFormat is given and output file is MD
|
|
365
379
|
outputFormat = 'svg'
|
|
366
380
|
}
|
|
@@ -369,7 +383,7 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
|
|
|
369
383
|
}
|
|
370
384
|
|
|
371
385
|
const definition = await getInputData(input)
|
|
372
|
-
if (/\.md$/.test(input)) {
|
|
386
|
+
if (/\.(md|markdown)$/.test(input)) {
|
|
373
387
|
const imagePromises = []
|
|
374
388
|
for (const mermaidCodeblockMatch of definition.matchAll(mermaidChartsInMarkdownRegexGlobal)) {
|
|
375
389
|
const mermaidDefinition = mermaidCodeblockMatch[1]
|
|
@@ -379,7 +393,10 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
|
|
|
379
393
|
// I.e. if "out.png", use "out-1.png", "out-2.png", etc
|
|
380
394
|
// If it is an output `.md` file, use that to base .svg numbered diagrams on
|
|
381
395
|
// I.e. if "out.md". use "out-1.svg", "out-2.svg", etc
|
|
382
|
-
const outputFile = output.replace(
|
|
396
|
+
const outputFile = output.replace(
|
|
397
|
+
/(\.(md|markdown|png|svg|pdf))$/,
|
|
398
|
+
`-${imagePromises.length + 1}$1`
|
|
399
|
+
).replace(/\.(md|markdown)$/, `.${outputFormat}`)
|
|
383
400
|
const outputFileRelative = `./${path.relative(path.dirname(path.resolve(output)), path.resolve(outputFile))}`
|
|
384
401
|
|
|
385
402
|
const imagePromise = (async () => {
|
|
@@ -404,7 +421,7 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
|
|
|
404
421
|
|
|
405
422
|
const images = await Promise.all(imagePromises)
|
|
406
423
|
|
|
407
|
-
if (/\.md$/.test(output)) {
|
|
424
|
+
if (/\.(md|markdown)$/.test(output)) {
|
|
408
425
|
const outDefinition = definition.replace(mermaidChartsInMarkdownRegexGlobal, (_mermaidMd) => {
|
|
409
426
|
// pop first image from front of array
|
|
410
427
|
const { url, title, alt } = images.shift()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|