UNPKG

2.88 kBJavaScriptView Raw
1#!/usr/bin/env node
2const commander = require('commander')
3const chalk = require('chalk')
4const fs = require('fs')
5const path = require('path')
6const puppeteer = require('puppeteer')
7
8const pkg = require('./package.json')
9
10const error = (message) => {
11 console.log(chalk.red(`\n${message}\n`))
12 process.exit(1)
13}
14
15commander
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 file. It should be either svg, png or pdf. Optional. Default: input + ".svg"')
22 .option('-b, --backgroundColor [backgroundColor]', 'Background color. Example: transparent, red, \'#F0F0F0\'. Optional. Default: white')
23 .parse(process.argv)
24
25let { theme, width, height, input, output, backgroundColor } = commander
26
27// check input file
28if (!input) {
29 error('Please specify input file: -i <input>')
30}
31if (!fs.existsSync(input)) {
32 error(`Input file "${input}" doesn't exist`)
33}
34
35// check output file
36if (!output) {
37 output = input + '.svg'
38}
39if (!/\.(?:svg|png|pdf)$/.test(output)) {
40 error(`Output file must end with ".svg", ".png" or ".pdf"`)
41}
42const outputDir = path.dirname(output)
43if (!fs.existsSync(outputDir)) {
44 error(`Output directory "${outputDir}/" doesn't exist`)
45}
46
47// normalize args
48width = parseInt(width)
49height = parseInt(height)
50backgroundColor = backgroundColor || 'white'
51
52;(async () => {
53 const browser = await puppeteer.launch()
54 const page = await browser.newPage()
55 page.setViewport({ width, height })
56 await page.goto(`file://${path.join(__dirname, 'index.html')}`)
57
58 await page.evaluate(`document.body.style.background = '${backgroundColor}'`)
59
60 const definition = fs.readFileSync(input, 'utf-8')
61 await page.$eval('#container', (container, definition, theme) => {
62 container.innerHTML = definition
63 window.mermaid_config = { theme }
64 window.mermaid.init(undefined, container)
65 }, definition, theme)
66
67 if (output.endsWith('svg')) {
68 const svg = await page.$eval('#container', container => container.innerHTML)
69 fs.writeFileSync(output, svg)
70 } else if (output.endsWith('png')) {
71 const clip = await page.$eval('svg', svg => {
72 const react = svg.getBoundingClientRect()
73 return { x: react.left, y: react.top, width: react.width, height: react.height }
74 })
75 await page.screenshot({ path: output, clip, omitBackground: backgroundColor === 'transparent' })
76 } else { // pdf
77 await page.pdf({ path: output, printBackground: backgroundColor !== 'transparent' })
78 }
79
80 browser.close()
81})()