@mermaid-js/mermaid-cli 9.1.7 → 9.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mermaid-js/mermaid-cli",
3
- "version": "9.1.7",
3
+ "version": "9.3.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,13 +10,12 @@
10
10
  "mmdc": "./src/cli.js"
11
11
  },
12
12
  "engines": {
13
- "node": ">=14.1.0"
13
+ "node": "^14.13 || >=16.0"
14
14
  },
15
15
  "exports": "./src/index.js",
16
16
  "scripts": {
17
- "upgrade": "yarn-upgrade-all && sh copy_modules.sh",
18
- "prepare": "sh copy_modules.sh",
19
- "prepack": "sh copy_modules.sh",
17
+ "prepare": "vite build",
18
+ "prepack": "vite build",
20
19
  "test": "standard && yarn node --experimental-vm-modules $(yarn bin jest)",
21
20
  "lint": "standard",
22
21
  "lint-fix": "standard --fix"
@@ -24,20 +23,22 @@
24
23
  "dependencies": {
25
24
  "chalk": "^5.0.1",
26
25
  "commander": "^9.0.0",
27
- "puppeteer": "^18.0.5"
26
+ "puppeteer": "^19.0.0"
28
27
  },
29
28
  "devDependencies": {
30
29
  "@fortawesome/fontawesome-free-webfonts": "^1.0.9",
31
- "mermaid": "^9.1.2",
30
+ "@mermaid-js/mermaid-mindmap": "^9.2.2",
31
+ "mermaid": "^9.2.2",
32
32
  "jest": "^29.0.1",
33
33
  "standard": "^17.0.0",
34
+ "vite": "^4.0.3",
35
+ "vite-plugin-singlefile": "^0.13.1",
36
+ "vite-svg-loader": "^4.0.0",
34
37
  "yarn-upgrade-all": "^0.7.0"
35
38
  },
36
39
  "files": [
37
40
  "src/",
38
- "mermaid.min.js",
39
- "index.html",
40
- "fontawesome/*"
41
+ "dist/"
41
42
  ],
42
43
  "jest": {
43
44
  "moduleNameMapper": {
@@ -46,7 +47,7 @@
46
47
  },
47
48
  "standard": {
48
49
  "ignore": [
49
- "mermaid.min.js"
50
+ "/dist/"
50
51
  ]
51
52
  }
52
53
  }
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'
@@ -60,23 +60,40 @@ const getInputData = async inputFile => new Promise((resolve, reject) => {
60
60
  })
61
61
  })
62
62
 
63
+ /**
64
+ * Commander parser that converts a string to an integer.
65
+ *
66
+ * @param {string} value - The value from commander.
67
+ * @param {*} _unused - Unused.
68
+ * @returns {number} The value parsed as a number.
69
+ * @throws {InvalidArgumentError} If the arg is not valid.
70
+ * @see https://github.com/tj/commander.js/wiki/Class:-Option#argparserfn
71
+ */
72
+ function parseCommanderInt (value, _unused) {
73
+ const parsedValue = parseInt(value, 10)
74
+ if (isNaN(parsedValue) || parsedValue < 1) {
75
+ throw new InvalidArgumentError('Not an positive integer.')
76
+ }
77
+ return parsedValue
78
+ }
79
+
63
80
  async function cli () {
64
81
  const commander = new Command()
65
82
  commander
66
83
  .version(pkg.version)
67
- .option('-t, --theme [theme]', 'Theme of the chart, could be default, forest, dark or neutral. Optional. Default: default', /^default|forest|dark|neutral$/, 'default')
68
- .option('-w, --width [width]', 'Width of the page. Optional. Default: 800', /^\d+$/, '800')
69
- .option('-H, --height [height]', 'Height of the page. Optional. Default: 600', /^\d+$/, '600')
84
+ .addOption(new Option('-t, --theme [theme]', 'Theme of the chart').choices(['default', 'forest', 'dark', 'neutral']).default('default'))
85
+ .addOption(new Option('-w, --width [width]', 'Width of the page').argParser(parseCommanderInt).default(800))
86
+ .addOption(new Option('-H, --height [height]', 'Height of the page').argParser(parseCommanderInt).default(600))
70
87
  .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. Required.')
71
88
  .option('-o, --output [output]', 'Output file. It should be either md, svg, png or pdf. Optional. Default: input + ".svg"')
72
- .option('-e, --outputFormat <format>', 'Output format for the generated image. It should be either svg, png or pdf. Optional. Default: output file extension')
73
- .option('-b, --backgroundColor [backgroundColor]', 'Background color for pngs/svgs (not pdfs). Example: transparent, red, \'#F0F0F0\'. Optional. Default: white')
74
- .option('-c, --configFile [configFile]', 'JSON configuration file for mermaid. Optional')
75
- .option('-C, --cssFile [cssFile]', 'CSS file for the page. Optional')
76
- .option('-s, --scale [scale]', 'Puppeteer scale factor, default 1. Optional')
89
+ .addOption(new Option('-e, --outputFormat [format]', 'Output format for the generated image.').choices(['svg', 'png', 'pdf']).default(null, 'Loaded from the output file extension'))
90
+ .addOption(new Option('-b, --backgroundColor [backgroundColor]', 'Background color for pngs/svgs (not pdfs). Example: transparent, red, \'#F0F0F0\'.').default('white'))
91
+ .option('-c, --configFile [configFile]', 'JSON configuration file for mermaid.')
92
+ .option('-C, --cssFile [cssFile]', 'CSS file for the page.')
93
+ .addOption(new Option('-s, --scale [scale]', 'Puppeteer scale factor').argParser(parseCommanderInt).default(1))
77
94
  .option('-f, --pdfFit [pdfFit]', 'Scale PDF to fit chart')
78
95
  .option('-q, --quiet', 'Suppress log output')
79
- .option('-p --puppeteerConfigFile [puppeteerConfigFile]', 'JSON configuration file for puppeteer. Optional')
96
+ .option('-p --puppeteerConfigFile [puppeteerConfigFile]', 'JSON configuration file for puppeteer.')
80
97
  .parse(process.argv)
81
98
 
82
99
  const options = commander.opts()
@@ -98,7 +115,11 @@ async function cli () {
98
115
  // if an input file is defined, it should take precedence, otherwise, input is
99
116
  // coming from stdin and just name the file out.svg, if it hasn't been
100
117
  // specified with the '-o' option
101
- output = input ? (input + '.svg') : 'out.svg'
118
+ if (outputFormat) {
119
+ output = input ? (`${input}.${outputFormat}`) : `out.${outputFormat}`
120
+ } else {
121
+ output = input ? (`${input}.svg`) : 'out.svg'
122
+ }
102
123
  }
103
124
  if (!/\.(?:svg|png|pdf|md)$/.test(output)) {
104
125
  error('Output file must end with ".md", ".svg", ".png" or ".pdf"')
@@ -129,19 +150,13 @@ async function cli () {
129
150
  myCSS = fs.readFileSync(cssFile, 'utf-8')
130
151
  }
131
152
 
132
- // normalize args
133
- width = parseInt(width)
134
- height = parseInt(height)
135
- backgroundColor = backgroundColor || 'white'
136
- const deviceScaleFactor = parseInt(scale || 1, 10)
137
-
138
153
  await run(
139
154
  input, output, {
140
155
  puppeteerConfig,
141
156
  quiet,
142
157
  outputFormat,
143
158
  parseMMDOptions: {
144
- mermaidConfig, backgroundColor, myCSS, pdfFit, viewport: { width, height, deviceScaleFactor }
159
+ mermaidConfig, backgroundColor, myCSS, pdfFit, viewport: { width, height, deviceScaleFactor: scale }
145
160
  }
146
161
  }
147
162
  )
@@ -185,21 +200,32 @@ async function parseMMD (...args) {
185
200
  */
186
201
  async function renderMermaid (browser, definition, outputFormat, { viewport, backgroundColor = 'white', mermaidConfig = {}, myCSS, pdfFit } = {}) {
187
202
  const page = await browser.newPage()
203
+ page.on('console', (msg) => {
204
+ console.log(msg.text())
205
+ })
188
206
  try {
189
207
  if (viewport) {
190
208
  await page.setViewport(viewport)
191
209
  }
192
- const mermaidHTMLPath = path.join(__dirname, '..', 'index.html')
210
+ const mermaidHTMLPath = path.join(__dirname, '..', 'dist', 'index.html')
193
211
  await page.goto(url.pathToFileURL(mermaidHTMLPath))
194
212
  await page.$eval('body', (body, backgroundColor) => {
195
213
  body.style.background = backgroundColor
196
214
  }, backgroundColor)
197
- const metadata = await page.$eval('#container', (container, definition, mermaidConfig, myCSS, backgroundColor) => {
215
+ const metadata = await page.$eval('#container', async (container, definition, mermaidConfig, myCSS, backgroundColor) => {
198
216
  container.textContent = definition
199
- window.mermaid.initialize(mermaidConfig)
217
+
218
+ /** @type {import("mermaid")} Already imported mermaid instance */
219
+ const mermaid = globalThis.mermaid
220
+ /** @type {import("@mermaid-js/mermaid-mindmap")} */
221
+ const mermaidMindmap = globalThis.mermaidMindmap
222
+
223
+ await mermaid.registerExternalDiagrams([mermaidMindmap])
224
+
225
+ mermaid.initialize(mermaidConfig)
200
226
  // should throw an error if mmd diagram is invalid
201
227
  try {
202
- window.mermaid.initThrowsErrors(undefined, container)
228
+ await mermaid.initThrowsErrorsAsync(undefined, container)
203
229
  } catch (error) {
204
230
  if (error instanceof Error) {
205
231
  // mermaid-js doesn't currently throws JS Errors, but let's leave this
@@ -338,7 +364,8 @@ async function run (input, output, { puppeteerConfig = {}, quiet = false, output
338
364
  }
339
365
  }
340
366
 
341
- const mermaidChartsInMarkdown = /^\s*```(?:mermaid)(\r?\n([\s\S]*?))```\s*$/
367
+ // TODO: should we use a Markdown parser like remark instead of rolling our own parser?
368
+ const mermaidChartsInMarkdown = /^[^\S\n]*```(?:mermaid)(\r?\n([\s\S]*?))```[^\S\n]*$/
342
369
  const mermaidChartsInMarkdownRegexGlobal = new RegExp(mermaidChartsInMarkdown, 'gm')
343
370
  const browser = await puppeteer.launch(puppeteerConfig)
344
371
  try {
@@ -1,9 +0,0 @@
1
- @font-face {
2
- font-family: 'Font Awesome 5 Brands';
3
- font-style: normal;
4
- font-weight: normal;
5
- src: url("../webfonts/fa-brands-400.eot");
6
- src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); }
7
-
8
- .fab {
9
- font-family: 'Font Awesome 5 Brands'; }
@@ -1,10 +0,0 @@
1
- @font-face {
2
- font-family: 'Font Awesome 5 Free';
3
- font-style: normal;
4
- font-weight: 400;
5
- src: url("../webfonts/fa-regular-400.eot");
6
- src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); }
7
-
8
- .far {
9
- font-family: 'Font Awesome 5 Free';
10
- font-weight: 400; }
@@ -1,11 +0,0 @@
1
- @font-face {
2
- font-family: 'Font Awesome 5 Free';
3
- font-style: normal;
4
- font-weight: 900;
5
- src: url("../webfonts/fa-solid-900.eot");
6
- src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); }
7
-
8
- .fa,
9
- .fas {
10
- font-family: 'Font Awesome 5 Free';
11
- font-weight: 900; }