UNPKG

5.04 kBJavaScriptView Raw
1#!/usr/bin/env node
2'use strict';
3
4function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
5
6const commander = require('commander');
7const chalk = require('chalk');
8const fs = require('fs');
9const path = require('path');
10const puppeteer = require('puppeteer');
11
12const pkg = require('./package.json');
13
14const error = message => {
15 console.log(chalk.red(`\n${message}\n`));
16 process.exit(1);
17};
18
19const checkConfigFile = file => {
20 if (!fs.existsSync(file)) {
21 error(`Configuration file "${file}" doesn't exist`);
22 } else if (!/\.(?:json)$/.test(file)) {
23 error(`Config file must end with ".json"`);
24 }
25};
26
27commander.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);
28
29let { theme, width, height, input, output, backgroundColor, configFile, cssFile, puppeteerConfigFile } = commander;
30
31// check input file
32if (!input) {
33 error('Please specify input file: -i <input>');
34}
35if (!fs.existsSync(input)) {
36 error(`Input file "${input}" doesn't exist`);
37}
38
39// check output file
40if (!output) {
41 output = input + '.svg';
42}
43if (!/\.(?:svg|png|pdf)$/.test(output)) {
44 error(`Output file must end with ".svg", ".png" or ".pdf"`);
45}
46const outputDir = path.dirname(output);
47if (!fs.existsSync(outputDir)) {
48 error(`Output directory "${outputDir}/" doesn't exist`);
49}
50
51// check config files
52let mermaidConfig = { theme };
53if (configFile) {
54 checkConfigFile(configFile);
55 mermaidConfig = Object.assign(mermaidConfig, JSON.parse(fs.readFileSync(configFile, 'utf-8')));
56}
57let puppeteerConfig = {};
58if (puppeteerConfigFile) {
59 checkConfigFile(puppeteerConfigFile);
60 puppeteerConfig = JSON.parse(fs.readFileSync(puppeteerConfigFile, 'utf-8'));
61}
62
63// check cssFile
64let myCSS;
65if (cssFile) {
66 if (!fs.existsSync(cssFile)) {
67 error(`CSS file "${cssFile}" doesn't exist`);
68 } else if (!/\.(?:css)$/.test(cssFile)) {
69 error(`CSS file must end with ".css"`);
70 }
71 myCSS = fs.readFileSync(cssFile, 'utf-8');
72}
73
74// normalize args
75width = parseInt(width);
76height = parseInt(height);
77backgroundColor = backgroundColor || 'white';
78
79_asyncToGenerator(function* () {
80 const browser = yield puppeteer.launch(puppeteerConfig);
81 const page = yield browser.newPage();
82 page.setViewport({ width, height });
83 yield page.goto(`file://${path.join(__dirname, 'index.html')}`);
84 yield page.evaluate(`document.body.style.background = '${backgroundColor}'`);
85 const definition = fs.readFileSync(input, 'utf-8');
86
87 yield page.$eval('#container', function (container, definition, mermaidConfig, myCSS) {
88 container.innerHTML = definition;
89 window.mermaid.initialize(mermaidConfig);
90
91 if (myCSS) {
92 const head = window.document.head || window.document.getElementsByTagName('head')[0];
93 const style = document.createElement('style');
94 style.type = 'text/css';
95 if (style.styleSheet) {
96 style.styleSheet.cssText = myCSS;
97 } else {
98 style.appendChild(document.createTextNode(myCSS));
99 }
100 head.appendChild(style);
101 }
102
103 window.mermaid.init(undefined, container);
104 }, definition, mermaidConfig, myCSS);
105
106 if (output.endsWith('svg')) {
107 const svg = yield page.$eval('#container', function (container) {
108 return container.innerHTML;
109 });
110 fs.writeFileSync(output, svg);
111 } else if (output.endsWith('png')) {
112 const clip = yield page.$eval('svg', function (svg) {
113 const react = svg.getBoundingClientRect();
114 return { x: react.left, y: react.top, width: react.width, height: react.height };
115 });
116 yield page.screenshot({ path: output, clip, omitBackground: backgroundColor === 'transparent' });
117 } else {
118 // pdf
119 yield page.pdf({ path: output, printBackground: backgroundColor !== 'transparent' });
120 }
121
122 browser.close();
123})();