forked from mermaidjs/mermaid.cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
123 lines (107 loc) · 4.2 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env node
const commander = require('commander')
const chalk = require('chalk')
const fs = require('fs')
const path = require('path')
const puppeteer = require('puppeteer')
const pkg = require('./package.json')
const error = message => {
console.log(chalk.red(`\n${message}\n`))
process.exit(1)
}
const checkConfigFile = file => {
if (!fs.existsSync(file)) {
error(`Configuration file "${file}" doesn't exist`)
}
}
commander
.version(pkg.version)
.option('-t, --theme [theme]', 'Theme of the chart, could be default, forest, dark or neutral. Optional. Default: default', /^default|forest|dark|neutral$/, 'default')
.option('-w, --width [width]', 'Width of the page. Optional. Default: 800', /^\d+$/, '800')
.option('-H, --height [height]', 'Height of the page. Optional. Default: 600', /^\d+$/, '600')
.option('-i, --input <input>', 'Input mermaid file. Required.')
.option('-o, --output [output]', 'Output file. It should be either svg, png or pdf. Optional. Default: input + ".svg"')
.option('-b, --backgroundColor [backgroundColor]', 'Background color. Example: transparent, red, \'#F0F0F0\'. Optional. Default: white')
.option('-c, --configFile [configFile]', 'JSON configuration file for mermaid. Optional')
.option('-C, --cssFile [cssFile]', 'CSS file for the page. Optional')
.option('-p --puppeteerConfigFile [puppeteerConfigFile]', 'JSON configuration file for puppeteer. Optional')
.parse(process.argv)
let { theme, width, height, input, output, backgroundColor, configFile, cssFile, puppeteerConfigFile } = commander
// check input file
if (!input) {
error('Please specify input file: -i <input>')
}
if (!fs.existsSync(input)) {
error(`Input file "${input}" doesn't exist`)
}
// check output file
if (!output) {
output = input + '.svg'
}
if (!/\.(?:svg|png|pdf)$/.test(output)) {
error(`Output file must end with ".svg", ".png" or ".pdf"`)
}
const outputDir = path.dirname(output)
if (!fs.existsSync(outputDir)) {
error(`Output directory "${outputDir}/" doesn't exist`)
}
// check config files
let mermaidConfig = { theme }
if (configFile) {
checkConfigFile(configFile)
mermaidConfig = Object.assign(mermaidConfig, JSON.parse(fs.readFileSync(configFile, 'utf-8')))
}
let puppeteerConfig = {}
if (puppeteerConfigFile) {
checkConfigFile(puppeteerConfigFile)
puppeteerConfig = JSON.parse(fs.readFileSync(puppeteerConfigFile, 'utf-8'))
}
// check cssFile
let myCSS
if (cssFile) {
if (!fs.existsSync(cssFile)) {
error(`CSS file "${cssFile}" doesn't exist`)
}
myCSS = fs.readFileSync(cssFile, 'utf-8')
}
// normalize args
width = parseInt(width)
height = parseInt(height)
backgroundColor = backgroundColor || 'white';
(async () => {
const browser = await puppeteer.launch(puppeteerConfig)
const page = await browser.newPage()
page.setViewport({ width, height })
await page.goto(`file://${path.join(__dirname, 'index.html')}`)
await page.evaluate(`document.body.style.background = '${backgroundColor}'`)
const definition = fs.readFileSync(input, 'utf-8')
await page.$eval('#container', (container, definition, mermaidConfig, myCSS) => {
container.innerHTML = definition
window.mermaid.initialize(mermaidConfig)
if (myCSS) {
const head = window.document.head || window.document.getElementsByTagName('head')[0]
const style = document.createElement('style')
style.type = 'text/css'
if (style.styleSheet) {
style.styleSheet.cssText = myCSS
} else {
style.appendChild(document.createTextNode(myCSS))
}
head.appendChild(style)
}
window.mermaid.init(undefined, container)
}, definition, mermaidConfig, myCSS)
if (output.endsWith('svg')) {
const svg = await page.$eval('#container', container => container.innerHTML)
fs.writeFileSync(output, svg)
} else if (output.endsWith('png')) {
const clip = await page.$eval('svg', svg => {
const react = svg.getBoundingClientRect()
return { x: react.left, y: react.top, width: react.width, height: react.height }
})
await page.screenshot({ path: output, clip, omitBackground: backgroundColor === 'transparent' })
} else { // pdf
await page.pdf({ path: output, printBackground: backgroundColor !== 'transparent' })
}
browser.close()
})()