@mermaid-js/mermaid-cli 9.4.0 → 10.0.2
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/dist/index.html +592 -589
- package/dist-types/src/cli.d.ts +3 -0
- package/dist-types/src/cli.d.ts.map +1 -0
- package/dist-types/src/index.d.ts +110 -0
- package/dist-types/src/index.d.ts.map +1 -0
- package/package.json +11 -6
- package/src/index.js +109 -36
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options to pass to {@link parseMMD }
|
|
3
|
+
*/
|
|
4
|
+
export type ParseMDDOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* - Puppeteer viewport (e.g. `width`, `height`, `deviceScaleFactor`)
|
|
7
|
+
*/
|
|
8
|
+
viewport?: puppeteer.Viewport | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* - Background color.
|
|
11
|
+
*/
|
|
12
|
+
backgroundColor?: string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* - Mermaid config.
|
|
15
|
+
*/
|
|
16
|
+
mermaidConfig?: any;
|
|
17
|
+
/**
|
|
18
|
+
* - Optional CSS text.
|
|
19
|
+
*/
|
|
20
|
+
myCSS?: string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* - If set, scale PDF to fit chart.
|
|
23
|
+
*/
|
|
24
|
+
pdfFit?: boolean | undefined;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Markdown image properties
|
|
28
|
+
* Used to create an markdown image that looks like ``
|
|
29
|
+
*/
|
|
30
|
+
export type MarkdownImageProps = {
|
|
31
|
+
/**
|
|
32
|
+
* - Path to image.
|
|
33
|
+
*/
|
|
34
|
+
url: string;
|
|
35
|
+
/**
|
|
36
|
+
* - Image alt text, required.
|
|
37
|
+
*/
|
|
38
|
+
alt: string;
|
|
39
|
+
/**
|
|
40
|
+
* - Optional image title text.
|
|
41
|
+
*/
|
|
42
|
+
title?: string | null | undefined;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Renders a mermaid diagram or mermaid markdown file.
|
|
46
|
+
*
|
|
47
|
+
* @param {`${string}.${"md" | "markdown"}` | string | undefined} input - If this ends with `.md`/`.markdown`,
|
|
48
|
+
* path to a markdown file containing mermaid.
|
|
49
|
+
* If this is a string, loads the mermaid definition from the given file.
|
|
50
|
+
* If this is `undefined`, loads the mermaid definition from stdin.
|
|
51
|
+
* @param {`${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}`} output - Path to the output file.
|
|
52
|
+
* @param {Object} [opts] - Options
|
|
53
|
+
* @param {import("puppeteer").LaunchOptions} [opts.puppeteerConfig] - Puppeteer launch options.
|
|
54
|
+
* @param {boolean} [opts.quiet] - If set, suppress log output.
|
|
55
|
+
* @param {"svg" | "png" | "pdf"} [opts.outputFormat] - Mermaid output format.
|
|
56
|
+
* Defaults to `output` extension. Overrides `output` extension if set.
|
|
57
|
+
* @param {ParseMDDOptions} [opts.parseMMDOptions] - Options to pass to {@link parseMMDOptions}.
|
|
58
|
+
*/
|
|
59
|
+
export function run(input: `${string}.${"md" | "markdown"}` | string | undefined, output: `${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}`, { puppeteerConfig, quiet, outputFormat, parseMMDOptions }?: {
|
|
60
|
+
puppeteerConfig?: puppeteer.LaunchOptions | undefined;
|
|
61
|
+
quiet?: boolean | undefined;
|
|
62
|
+
outputFormat?: "svg" | "png" | "pdf" | undefined;
|
|
63
|
+
parseMMDOptions?: ParseMDDOptions | undefined;
|
|
64
|
+
} | undefined): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Render a mermaid diagram.
|
|
67
|
+
*
|
|
68
|
+
* @param {import("puppeteer").Browser} browser - Puppeteer Browser
|
|
69
|
+
* @param {string} definition - Mermaid diagram definition
|
|
70
|
+
* @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
|
|
71
|
+
* @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
|
|
72
|
+
* @returns {Promise<{title: string | null, desc: string | null, data: Buffer}>} The output file in bytes,
|
|
73
|
+
* with optional metadata.
|
|
74
|
+
*/
|
|
75
|
+
export function renderMermaid(browser: import("puppeteer").Browser, definition: string, outputFormat: "svg" | "png" | "pdf", { viewport, backgroundColor, mermaidConfig, myCSS, pdfFit }?: ParseMDDOptions | undefined): Promise<{
|
|
76
|
+
title: string | null;
|
|
77
|
+
desc: string | null;
|
|
78
|
+
data: Buffer;
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* @typedef {Object} ParseMDDOptions Options to pass to {@link parseMMD}
|
|
82
|
+
* @property {import("puppeteer").Viewport} [viewport] - Puppeteer viewport (e.g. `width`, `height`, `deviceScaleFactor`)
|
|
83
|
+
* @property {string | "transparent"} [backgroundColor] - Background color.
|
|
84
|
+
* @property {Parameters<import("mermaid")["default"]["initialize"]>[0]} [mermaidConfig] - Mermaid config.
|
|
85
|
+
* @property {CSSStyleDeclaration["cssText"]} [myCSS] - Optional CSS text.
|
|
86
|
+
* @property {boolean} [pdfFit] - If set, scale PDF to fit chart.
|
|
87
|
+
*/
|
|
88
|
+
/**
|
|
89
|
+
* Parse and render a mermaid diagram.
|
|
90
|
+
*
|
|
91
|
+
* @deprecated Prefer {@link renderMermaid}, as it also returns useful metadata.
|
|
92
|
+
*
|
|
93
|
+
* @param {import("puppeteer").Browser} browser - Puppeteer Browser
|
|
94
|
+
* @param {string} definition - Mermaid diagram definition
|
|
95
|
+
* @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
|
|
96
|
+
* @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
|
|
97
|
+
*
|
|
98
|
+
* @returns {Promise<Buffer>} The output file in bytes.
|
|
99
|
+
*/
|
|
100
|
+
export function parseMMD(browser: import("puppeteer").Browser, definition: string, outputFormat: "svg" | "png" | "pdf", opt?: ParseMDDOptions | undefined): Promise<Buffer>;
|
|
101
|
+
export function cli(): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Prints an error to stderr, then closes with exit code 1
|
|
104
|
+
*
|
|
105
|
+
* @param {string} message - The message to print to `stderr`.
|
|
106
|
+
* @returns {never} Quits Node.JS, so never returns.
|
|
107
|
+
*/
|
|
108
|
+
export function error(message: string): never;
|
|
109
|
+
import puppeteer from 'puppeteer';
|
|
110
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SA4Xc,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;AAzSD;;;;;;;;;GASG;AACH,uCAPW,OAAO,WAAW,EAAE,OAAO,cAC3B,MAAM,gBACN,KAAK,GAAG,KAAK,GAAG,KAAK,8FAEnB,QAAQ;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAC,CAwJ9E;AAzLD;;;;;;;GAOG;AAEH;;;;;;;;;;;GAWG;AACH,kCAPW,OAAO,WAAW,EAAE,OAAO,cAC3B,MAAM,gBACN,KAAK,GAAG,KAAK,GAAG,KAAK,sCAGnB,QAAQ,MAAM,CAAC,CAK3B;AAhHD,qCAsFC;AA9KD;;;;;GAKG;AACH,+BAHW,MAAM,GACJ,KAAK,CAKjB;sBAnBqB,WAAW"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mermaid-js/mermaid-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.2",
|
|
4
4
|
"description": "Command-line interface for mermaid",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "git@github.com:mermaid-js/mermaid-cli.git",
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
"node": "^14.13 || >=16.0"
|
|
14
14
|
},
|
|
15
15
|
"exports": "./src/index.js",
|
|
16
|
+
"types": "./dist-types/src/index.d.ts",
|
|
16
17
|
"scripts": {
|
|
17
|
-
"prepare": "vite build",
|
|
18
|
-
"prepack": "vite build",
|
|
18
|
+
"prepare": "tsc && vite build",
|
|
19
|
+
"prepack": "tsc && vite build",
|
|
19
20
|
"test": "standard && yarn node --experimental-vm-modules $(yarn bin jest)",
|
|
20
21
|
"lint": "standard",
|
|
21
22
|
"lint-fix": "standard --fix"
|
|
@@ -28,9 +29,11 @@
|
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"@fortawesome/fontawesome-free-webfonts": "^1.0.9",
|
|
30
31
|
"@mermaid-js/mermaid-mindmap": "^9.2.2",
|
|
31
|
-
"
|
|
32
|
+
"@tsconfig/node14": "^1.0.3",
|
|
32
33
|
"jest": "^29.0.1",
|
|
34
|
+
"mermaid": "^10.0.0",
|
|
33
35
|
"standard": "^17.0.0",
|
|
36
|
+
"typescript": "^5.0.1-rc",
|
|
34
37
|
"vite": "^4.0.3",
|
|
35
38
|
"vite-plugin-singlefile": "^0.13.1",
|
|
36
39
|
"vite-svg-loader": "^4.0.0",
|
|
@@ -38,7 +41,8 @@
|
|
|
38
41
|
},
|
|
39
42
|
"files": [
|
|
40
43
|
"src/",
|
|
41
|
-
"dist/"
|
|
44
|
+
"dist/",
|
|
45
|
+
"dist-types/"
|
|
42
46
|
],
|
|
43
47
|
"jest": {
|
|
44
48
|
"moduleNameMapper": {
|
|
@@ -47,7 +51,8 @@
|
|
|
47
51
|
},
|
|
48
52
|
"standard": {
|
|
49
53
|
"ignore": [
|
|
50
|
-
"/dist/"
|
|
54
|
+
"/dist/",
|
|
55
|
+
"/dist-types/"
|
|
51
56
|
]
|
|
52
57
|
}
|
|
53
58
|
}
|
package/src/index.js
CHANGED
|
@@ -10,23 +10,48 @@ import { createRequire } from 'module'
|
|
|
10
10
|
const require = createRequire(import.meta.url)
|
|
11
11
|
const pkg = require('../package.json')
|
|
12
12
|
// __dirname is not available in ESM modules by default
|
|
13
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
13
|
+
const __dirname = url.fileURLToPath(new url.URL('.', import.meta.url))
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Prints an error to stderr, then closes with exit code 1
|
|
17
|
+
*
|
|
18
|
+
* @param {string} message - The message to print to `stderr`.
|
|
19
|
+
* @returns {never} Quits Node.JS, so never returns.
|
|
20
|
+
*/
|
|
15
21
|
const error = message => {
|
|
16
22
|
console.error(chalk.red(`\n${message}\n`))
|
|
17
23
|
process.exit(1)
|
|
18
24
|
}
|
|
19
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Prints a warning to stderr.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} message - The message to print to `stderr`.
|
|
30
|
+
*/
|
|
20
31
|
const warn = message => {
|
|
21
32
|
console.warn(chalk.yellow(`\n${message}\n`))
|
|
22
33
|
}
|
|
23
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Checks if the given file exists.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} file - The file to check.
|
|
39
|
+
* @returns {never | void} If the file doesn't exist, closes Node.JS with
|
|
40
|
+
* exit code 1.
|
|
41
|
+
*/
|
|
24
42
|
const checkConfigFile = file => {
|
|
25
43
|
if (!fs.existsSync(file)) {
|
|
26
44
|
error(`Configuration file "${file}" doesn't exist`)
|
|
27
45
|
}
|
|
28
46
|
}
|
|
29
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Gets the data in the given file.
|
|
50
|
+
*
|
|
51
|
+
* @param {string | undefined} inputFile - The file to read.
|
|
52
|
+
* If `undefined`, reads from `stdin` instead.
|
|
53
|
+
* @returns {Promise<string>} The contents of `inputFile` parsed as `utf8`.
|
|
54
|
+
*/
|
|
30
55
|
const getInputData = async inputFile => new Promise((resolve, reject) => {
|
|
31
56
|
// if an input file has been specified using '-i', it takes precedence over
|
|
32
57
|
// piping from stdin
|
|
@@ -42,7 +67,7 @@ const getInputData = async inputFile => new Promise((resolve, reject) => {
|
|
|
42
67
|
|
|
43
68
|
let data = ''
|
|
44
69
|
process.stdin.on('readable', function () {
|
|
45
|
-
const chunk =
|
|
70
|
+
const chunk = process.stdin.read()
|
|
46
71
|
|
|
47
72
|
if (chunk !== null) {
|
|
48
73
|
data += chunk
|
|
@@ -165,11 +190,11 @@ async function cli () {
|
|
|
165
190
|
|
|
166
191
|
/**
|
|
167
192
|
* @typedef {Object} ParseMDDOptions Options to pass to {@link parseMMD}
|
|
168
|
-
* @property {puppeteer.Viewport} [viewport] - Puppeteer viewport (e.g. `width`, `height`, `deviceScaleFactor`)
|
|
193
|
+
* @property {import("puppeteer").Viewport} [viewport] - Puppeteer viewport (e.g. `width`, `height`, `deviceScaleFactor`)
|
|
169
194
|
* @property {string | "transparent"} [backgroundColor] - Background color.
|
|
170
|
-
* @property {Parameters<import("mermaid")
|
|
195
|
+
* @property {Parameters<import("mermaid")["default"]["initialize"]>[0]} [mermaidConfig] - Mermaid config.
|
|
171
196
|
* @property {CSSStyleDeclaration["cssText"]} [myCSS] - Optional CSS text.
|
|
172
|
-
* @property {boolean} pdfFit - If set, scale PDF to fit chart.
|
|
197
|
+
* @property {boolean} [pdfFit] - If set, scale PDF to fit chart.
|
|
173
198
|
*/
|
|
174
199
|
|
|
175
200
|
/**
|
|
@@ -177,26 +202,26 @@ async function cli () {
|
|
|
177
202
|
*
|
|
178
203
|
* @deprecated Prefer {@link renderMermaid}, as it also returns useful metadata.
|
|
179
204
|
*
|
|
180
|
-
* @param {puppeteer.Browser} browser - Puppeteer Browser
|
|
205
|
+
* @param {import("puppeteer").Browser} browser - Puppeteer Browser
|
|
181
206
|
* @param {string} definition - Mermaid diagram definition
|
|
182
207
|
* @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
|
|
183
208
|
* @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
|
|
184
209
|
*
|
|
185
210
|
* @returns {Promise<Buffer>} The output file in bytes.
|
|
186
211
|
*/
|
|
187
|
-
async function parseMMD (
|
|
188
|
-
const { data } = await renderMermaid(
|
|
212
|
+
async function parseMMD (browser, definition, outputFormat, opt) {
|
|
213
|
+
const { data } = await renderMermaid(browser, definition, outputFormat, opt)
|
|
189
214
|
return data
|
|
190
215
|
}
|
|
191
216
|
|
|
192
217
|
/**
|
|
193
218
|
* Render a mermaid diagram.
|
|
194
219
|
*
|
|
195
|
-
* @param {puppeteer.Browser} browser - Puppeteer Browser
|
|
220
|
+
* @param {import("puppeteer").Browser} browser - Puppeteer Browser
|
|
196
221
|
* @param {string} definition - Mermaid diagram definition
|
|
197
222
|
* @param {"svg" | "png" | "pdf"} outputFormat - Mermaid output format.
|
|
198
223
|
* @param {ParseMDDOptions} [opt] - Options, see {@link ParseMDDOptions} for details.
|
|
199
|
-
* @returns {Promise<{title
|
|
224
|
+
* @returns {Promise<{title: string | null, desc: string | null, data: Buffer}>} The output file in bytes,
|
|
200
225
|
* with optional metadata.
|
|
201
226
|
*/
|
|
202
227
|
async function renderMermaid (browser, definition, outputFormat, { viewport, backgroundColor = 'white', mermaidConfig = {}, myCSS, pdfFit } = {}) {
|
|
@@ -209,31 +234,57 @@ async function renderMermaid (browser, definition, outputFormat, { viewport, bac
|
|
|
209
234
|
await page.setViewport(viewport)
|
|
210
235
|
}
|
|
211
236
|
const mermaidHTMLPath = path.join(__dirname, '..', 'dist', 'index.html')
|
|
212
|
-
await page.goto(url.pathToFileURL(mermaidHTMLPath))
|
|
237
|
+
await page.goto(url.pathToFileURL(mermaidHTMLPath).href)
|
|
213
238
|
await page.$eval('body', (body, backgroundColor) => {
|
|
214
239
|
body.style.background = backgroundColor
|
|
215
240
|
}, backgroundColor)
|
|
216
241
|
const metadata = await page.$eval('#container', async (container, definition, mermaidConfig, myCSS, backgroundColor) => {
|
|
242
|
+
/**
|
|
243
|
+
* Checks to see if the given object is one of Mermaid's DetailedErrors.
|
|
244
|
+
*
|
|
245
|
+
* @param {unknown} error - The error to check
|
|
246
|
+
* @returns {error is import("mermaid").DetailedError} Returns `true` is the `error`
|
|
247
|
+
* is a `Mermaid.DetailedError`.
|
|
248
|
+
* @see https://github.com/mermaid-js/mermaid/blob/v10.0.1/packages/mermaid/src/utils.ts#L927-L930
|
|
249
|
+
*/
|
|
250
|
+
function isDetailedError (error) {
|
|
251
|
+
return typeof error === 'object' && error !== null && 'str' in error
|
|
252
|
+
}
|
|
253
|
+
|
|
217
254
|
container.textContent = definition
|
|
218
255
|
|
|
219
|
-
/**
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
256
|
+
/**
|
|
257
|
+
* @typedef {Object} GlobalThisWithMermaid
|
|
258
|
+
* We've already imported these modules in our `index.html` file, so that they
|
|
259
|
+
* get correctly bundled.
|
|
260
|
+
* @property {import("mermaid")["default"]} mermaid Already imported mermaid instance
|
|
261
|
+
* @property {import("@mermaid-js/mermaid-mindmap")} mermaidMindmap Already imported mermaid-mindmap plugin
|
|
262
|
+
*/
|
|
263
|
+
const { mermaid, mermaidMindmap } = /** @type {GlobalThisWithMermaid & typeof globalThis} */ (globalThis)
|
|
223
264
|
|
|
224
265
|
await mermaid.registerExternalDiagrams([mermaidMindmap])
|
|
225
266
|
|
|
226
267
|
mermaid.initialize(mermaidConfig)
|
|
227
268
|
// should throw an error if mmd diagram is invalid
|
|
228
269
|
try {
|
|
229
|
-
await mermaid.
|
|
270
|
+
await mermaid.run({
|
|
271
|
+
nodes: [
|
|
272
|
+
/**
|
|
273
|
+
* @type {HTMLElement} We know this is a `HTMLElement`, since we
|
|
274
|
+
* control the input HTML file
|
|
275
|
+
*/ (container)
|
|
276
|
+
],
|
|
277
|
+
suppressErrors: false
|
|
278
|
+
})
|
|
230
279
|
} catch (error) {
|
|
231
280
|
if (error instanceof Error) {
|
|
232
281
|
// mermaid-js doesn't currently throws JS Errors, but let's leave this
|
|
233
282
|
// here in case it does in the future
|
|
234
283
|
throw error
|
|
284
|
+
} else if (isDetailedError(error)) {
|
|
285
|
+
throw new Error(error.message)
|
|
235
286
|
} else {
|
|
236
|
-
throw new Error(
|
|
287
|
+
throw new Error(`Unknown mermaid render error: ${error}`)
|
|
237
288
|
}
|
|
238
289
|
}
|
|
239
290
|
|
|
@@ -324,13 +375,18 @@ async function renderMermaid (browser, definition, outputFormat, { viewport, bac
|
|
|
324
375
|
}
|
|
325
376
|
}
|
|
326
377
|
|
|
378
|
+
/**
|
|
379
|
+
* @typedef {object} MarkdownImageProps Markdown image properties
|
|
380
|
+
* Used to create an markdown image that looks like ``
|
|
381
|
+
* @property {string} url - Path to image.
|
|
382
|
+
* @property {string} alt - Image alt text, required.
|
|
383
|
+
* @property {string | null} [title] - Optional image title text.
|
|
384
|
+
*/
|
|
385
|
+
|
|
327
386
|
/**
|
|
328
387
|
* Creates a markdown image syntax.
|
|
329
388
|
*
|
|
330
|
-
* @param {
|
|
331
|
-
* @param {string} params.url - Path to image.
|
|
332
|
-
* @param {string} params.alt - Image alt text, required.
|
|
333
|
-
* @param {string} [params.title] - Image title text.
|
|
389
|
+
* @param {MarkdownImageProps} params - Parameters.
|
|
334
390
|
* @returns {``} The markdown image text.
|
|
335
391
|
*/
|
|
336
392
|
function markdownImage ({ url, title, alt }) {
|
|
@@ -347,19 +403,24 @@ function markdownImage ({ url, title, alt }) {
|
|
|
347
403
|
/**
|
|
348
404
|
* Renders a mermaid diagram or mermaid markdown file.
|
|
349
405
|
*
|
|
350
|
-
* @param {`${string}.${"md" | "markdown"}` | string}
|
|
406
|
+
* @param {`${string}.${"md" | "markdown"}` | string | undefined} input - If this ends with `.md`/`.markdown`,
|
|
351
407
|
* path to a markdown file containing mermaid.
|
|
352
408
|
* If this is a string, loads the mermaid definition from the given file.
|
|
353
409
|
* If this is `undefined`, loads the mermaid definition from stdin.
|
|
354
410
|
* @param {`${string}.${"md" | "markdown" | "svg" | "png" | "pdf"}`} output - Path to the output file.
|
|
355
411
|
* @param {Object} [opts] - Options
|
|
356
|
-
* @param {puppeteer.LaunchOptions} [opts.puppeteerConfig] - Puppeteer launch options.
|
|
412
|
+
* @param {import("puppeteer").LaunchOptions} [opts.puppeteerConfig] - Puppeteer launch options.
|
|
357
413
|
* @param {boolean} [opts.quiet] - If set, suppress log output.
|
|
358
414
|
* @param {"svg" | "png" | "pdf"} [opts.outputFormat] - Mermaid output format.
|
|
359
415
|
* Defaults to `output` extension. Overrides `output` extension if set.
|
|
360
416
|
* @param {ParseMDDOptions} [opts.parseMMDOptions] - Options to pass to {@link parseMMDOptions}.
|
|
361
417
|
*/
|
|
362
418
|
async function run (input, output, { puppeteerConfig = {}, quiet = false, outputFormat, parseMMDOptions } = {}) {
|
|
419
|
+
/**
|
|
420
|
+
* Logs the given message to stdout, unless `quiet` is set to `true`.
|
|
421
|
+
*
|
|
422
|
+
* @param {string} message - The message to maybe log.
|
|
423
|
+
*/
|
|
363
424
|
const info = message => {
|
|
364
425
|
if (!quiet) {
|
|
365
426
|
console.info(message)
|
|
@@ -367,32 +428,39 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
|
|
|
367
428
|
}
|
|
368
429
|
|
|
369
430
|
// 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]*$/
|
|
431
|
+
const mermaidChartsInMarkdown = /^[^\S\n]*```(?:mermaid)([^\S\n]*\r?\n([\s\S]*?))```[^\S\n]*$/
|
|
371
432
|
const mermaidChartsInMarkdownRegexGlobal = new RegExp(mermaidChartsInMarkdown, 'gm')
|
|
372
433
|
const browser = await puppeteer.launch(puppeteerConfig)
|
|
373
434
|
try {
|
|
374
435
|
if (!outputFormat) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
436
|
+
const outputFormatFromFilename =
|
|
437
|
+
/**
|
|
438
|
+
* @type {"md" | "markdown" | "svg" | "png" | "pdf"}
|
|
439
|
+
*/ (path.extname(output).replace('.', ''))
|
|
440
|
+
if (outputFormatFromFilename === 'md' || outputFormatFromFilename === 'markdown') {
|
|
441
|
+
// fallback to svg in case no outputFormat is given and output file is MD
|
|
442
|
+
outputFormat = 'svg'
|
|
443
|
+
} else {
|
|
444
|
+
outputFormat = outputFormatFromFilename
|
|
445
|
+
}
|
|
380
446
|
}
|
|
381
447
|
if (!/(?:svg|png|pdf)$/.test(outputFormat)) {
|
|
382
448
|
throw new Error('Output format must be one of "svg", "png" or "pdf"')
|
|
383
449
|
}
|
|
384
450
|
|
|
385
451
|
const definition = await getInputData(input)
|
|
386
|
-
if (/\.(md|markdown)$/.test(input)) {
|
|
452
|
+
if (input && /\.(md|markdown)$/.test(input)) {
|
|
387
453
|
const imagePromises = []
|
|
388
454
|
for (const mermaidCodeblockMatch of definition.matchAll(mermaidChartsInMarkdownRegexGlobal)) {
|
|
389
455
|
const mermaidDefinition = mermaidCodeblockMatch[1]
|
|
390
456
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
457
|
+
/** Output can be either a template image file, or a `.md` output file.
|
|
458
|
+
* If it is a template image file, use that to created numbered diagrams
|
|
459
|
+
* I.e. if "out.png", use "out-1.png", "out-2.png", etc
|
|
460
|
+
* If it is an output `.md` file, use that to base .svg numbered diagrams on
|
|
461
|
+
* I.e. if "out.md". use "out-1.svg", "out-2.svg", etc
|
|
462
|
+
* @type {string}
|
|
463
|
+
*/
|
|
396
464
|
const outputFile = output.replace(
|
|
397
465
|
/(\.(md|markdown|png|svg|pdf))$/,
|
|
398
466
|
`-${imagePromises.length + 1}$1`
|
|
@@ -424,7 +492,12 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
|
|
|
424
492
|
if (/\.(md|markdown)$/.test(output)) {
|
|
425
493
|
const outDefinition = definition.replace(mermaidChartsInMarkdownRegexGlobal, (_mermaidMd) => {
|
|
426
494
|
// pop first image from front of array
|
|
427
|
-
const { url, title, alt } =
|
|
495
|
+
const { url, title, alt } =
|
|
496
|
+
/**
|
|
497
|
+
* @type {MarkdownImageProps} We use the same regex,
|
|
498
|
+
* so we will never try to get too many objects from the array.
|
|
499
|
+
* (aka `images.shift()` will never return `undefined`)
|
|
500
|
+
*/ (images.shift())
|
|
428
501
|
return markdownImage({ url, title, alt: alt || 'diagram' })
|
|
429
502
|
})
|
|
430
503
|
await fs.promises.writeFile(output, outDefinition, 'utf-8')
|