1 | #!/usr/bin/env node
|
2 | const commander = require('commander')
|
3 | const chalk = require('chalk')
|
4 | const fs = require('fs')
|
5 | const path = require('path')
|
6 | const puppeteer = require('puppeteer')
|
7 |
|
8 | const pkg = require('./package.json')
|
9 |
|
10 | const error = (message) => {
|
11 | console.log(chalk.red(`\n${message}\n`))
|
12 | process.exit(1)
|
13 | }
|
14 |
|
15 | commander
|
16 | .version(pkg.version)
|
17 | .option('-t, --theme [name]', 'Theme of the chart, could be default, forest, dark or neutral. Optional. Default: default', /^default|forest|dark|neutral$/, 'default')
|
18 | .option('-w, --width [width]', 'Width of the page. Optional. Default: 800', /^\d+$/, '800')
|
19 | .option('-H, --height [height]', 'Height of the page. Optional. Default: 600', /^\d+$/, '600')
|
20 | .option('-i, --input <input>', 'Input mermaid file. Required.')
|
21 | .option('-o, --output [output]', 'Output image file. It should be either svg or png. Optional. Default: input + ".svg"')
|
22 | .parse(process.argv)
|
23 |
|
24 | let { theme, width, height, input, output } = commander
|
25 |
|
26 |
|
27 | if (!input) {
|
28 | error('Please specify input file: -i <input>')
|
29 | }
|
30 | if (!fs.existsSync(input)) {
|
31 | error(`Input file "${input}" doesn't exist`)
|
32 | }
|
33 |
|
34 |
|
35 | if (!output) {
|
36 | output = input + '.svg'
|
37 | }
|
38 | if (!/\.(?:svg|png)$/.test(output)) {
|
39 | error(`Output file must end with ".svg" or ".png"`)
|
40 | }
|
41 | const outputDir = path.dirname(output)
|
42 | if (!fs.existsSync(outputDir)) {
|
43 | error(`Output directory "${outputDir}/" doesn't exist`)
|
44 | }
|
45 |
|
46 |
|
47 | width = parseInt(width)
|
48 | height = parseInt(height)
|
49 |
|
50 | ;(async () => {
|
51 | const browser = await puppeteer.launch()
|
52 | const page = await browser.newPage()
|
53 | page.setViewport({ width, height })
|
54 | await page.goto(`file://${path.join(__dirname, 'index.html')}`)
|
55 |
|
56 | const definition = fs.readFileSync(input, 'utf-8')
|
57 | await page.$eval('#container', (container, definition, theme) => {
|
58 | container.innerHTML = definition
|
59 | window.mermaid_config = { theme }
|
60 | window.mermaid.init(undefined, container)
|
61 | }, definition, theme)
|
62 |
|
63 | if (output.endsWith('svg')) {
|
64 | const svg = await page.$eval('#container', container => container.innerHTML)
|
65 | fs.writeFileSync(output, svg)
|
66 | } else {
|
67 | const clip = await page.$eval('svg', svg => {
|
68 | const react = svg.getBoundingClientRect()
|
69 | return { x: react.left, y: react.top, width: react.width, height: react.height }
|
70 | })
|
71 | await page.screenshot({ path: output, clip })
|
72 | }
|
73 |
|
74 | browser.close()
|
75 | })()
|