@mermaid-js/mermaid-cli 8.12.1 → 8.13.4
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/README.md +1 -0
- package/index.bundle.js +114 -48
- package/mermaid.min.js +2 -33
- package/package.json +6 -5
package/README.md
CHANGED
package/index.bundle.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
"use strict";
|
|
3
3
|
|
|
4
|
-
function
|
|
4
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
5
|
+
|
|
6
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
5
7
|
|
|
6
8
|
process.title = "mmdc";
|
|
9
|
+
|
|
7
10
|
const commander = require('commander');
|
|
11
|
+
|
|
8
12
|
const chalk = require('chalk');
|
|
13
|
+
|
|
9
14
|
const fs = require('fs');
|
|
15
|
+
|
|
10
16
|
const path = require('path');
|
|
17
|
+
|
|
11
18
|
const puppeteer = require('puppeteer');
|
|
12
19
|
|
|
13
20
|
const pkg = require('./package.json');
|
|
@@ -25,13 +32,13 @@ const checkConfigFile = file => {
|
|
|
25
32
|
|
|
26
33
|
const inputPipedFromStdin = () => fs.fstatSync(0).isFIFO();
|
|
27
34
|
|
|
28
|
-
const getInputData = (
|
|
35
|
+
const getInputData = /*#__PURE__*/function () {
|
|
29
36
|
var _ref = _asyncToGenerator(function* (inputFile) {
|
|
30
|
-
return new Promise(
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
31
38
|
// if an input file has been specified using '-i', it takes precedence over
|
|
32
39
|
// piping from stdin
|
|
33
40
|
if (typeof inputFile !== 'undefined') {
|
|
34
|
-
return fs.readFile(inputFile, 'utf-8',
|
|
41
|
+
return fs.readFile(inputFile, 'utf-8', (err, data) => {
|
|
35
42
|
if (err) {
|
|
36
43
|
return reject(err);
|
|
37
44
|
}
|
|
@@ -48,11 +55,9 @@ const getInputData = (() => {
|
|
|
48
55
|
data += chunk;
|
|
49
56
|
}
|
|
50
57
|
});
|
|
51
|
-
|
|
52
58
|
process.stdin.on('error', function (err) {
|
|
53
59
|
reject(err);
|
|
54
60
|
});
|
|
55
|
-
|
|
56
61
|
process.stdin.on('end', function () {
|
|
57
62
|
resolve(data);
|
|
58
63
|
});
|
|
@@ -62,124 +67,179 @@ const getInputData = (() => {
|
|
|
62
67
|
return function getInputData(_x) {
|
|
63
68
|
return _ref.apply(this, arguments);
|
|
64
69
|
};
|
|
65
|
-
}
|
|
70
|
+
}();
|
|
66
71
|
|
|
67
72
|
const convertToValidXML = html => {
|
|
68
|
-
var xml = html;
|
|
69
|
-
|
|
70
73
|
// <br> tags in valid HTML (from innerHTML) look like <br>, but they must look like <br/> to be valid XML (such as SVG)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return xml;
|
|
74
|
+
return html.replace(/<br>/gi, '<br/>');
|
|
74
75
|
};
|
|
75
76
|
|
|
76
|
-
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('-s, --scale [scale]', 'Puppeteer scale factor, default 1. Optional').option('-f, --pdfFit [pdfFit]', 'Scale PDF to fit chart').option('-p --puppeteerConfigFile [puppeteerConfigFile]', 'JSON configuration file for puppeteer. Optional').parse(process.argv);
|
|
77
|
-
|
|
77
|
+
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. Files ending in .md will be treated as Markdown and all charts (e.g. ```mermaid (...)```) will be extracted and generated. 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('-s, --scale [scale]', 'Puppeteer scale factor, default 1. Optional').option('-f, --pdfFit [pdfFit]', 'Scale PDF to fit chart').option('-q, --quiet', 'Suppress log output').option('-p --puppeteerConfigFile [puppeteerConfigFile]', 'JSON configuration file for puppeteer. Optional').parse(process.argv);
|
|
78
78
|
const options = commander.opts();
|
|
79
|
+
let {
|
|
80
|
+
theme,
|
|
81
|
+
width,
|
|
82
|
+
height,
|
|
83
|
+
input,
|
|
84
|
+
output,
|
|
85
|
+
backgroundColor,
|
|
86
|
+
configFile,
|
|
87
|
+
cssFile,
|
|
88
|
+
puppeteerConfigFile,
|
|
89
|
+
scale,
|
|
90
|
+
pdfFit,
|
|
91
|
+
quiet
|
|
92
|
+
} = options; // check input file
|
|
79
93
|
|
|
80
|
-
let { theme, width, height, input, output, backgroundColor, configFile, cssFile, puppeteerConfigFile, scale, pdfFit } = options;
|
|
81
|
-
|
|
82
|
-
// check input file
|
|
83
94
|
if (!(input || inputPipedFromStdin())) {
|
|
84
|
-
|
|
95
|
+
console.log(chalk.red(`\nPlease specify input file: -i <input>\n`));
|
|
96
|
+
commander.help();
|
|
97
|
+
process.exit(1);
|
|
85
98
|
}
|
|
99
|
+
|
|
86
100
|
if (input && !fs.existsSync(input)) {
|
|
87
101
|
error(`Input file "${input}" doesn't exist`);
|
|
88
|
-
}
|
|
102
|
+
} // check output file
|
|
103
|
+
|
|
89
104
|
|
|
90
|
-
// check output file
|
|
91
105
|
if (!output) {
|
|
92
106
|
// if an input file is defined, it should take precedence, otherwise, input is
|
|
93
107
|
// coming from stdin and just name the file out.svg, if it hasn't been
|
|
94
108
|
// specified with the '-o' option
|
|
95
109
|
output = input ? input + '.svg' : 'out.svg';
|
|
96
110
|
}
|
|
111
|
+
|
|
97
112
|
if (!/\.(?:svg|png|pdf)$/.test(output)) {
|
|
98
113
|
error(`Output file must end with ".svg", ".png" or ".pdf"`);
|
|
99
114
|
}
|
|
115
|
+
|
|
100
116
|
const outputDir = path.dirname(output);
|
|
117
|
+
|
|
101
118
|
if (!fs.existsSync(outputDir)) {
|
|
102
119
|
error(`Output directory "${outputDir}/" doesn't exist`);
|
|
103
|
-
}
|
|
120
|
+
} // check config files
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
let mermaidConfig = {
|
|
124
|
+
theme
|
|
125
|
+
};
|
|
104
126
|
|
|
105
|
-
// check config files
|
|
106
|
-
let mermaidConfig = { theme };
|
|
107
127
|
if (configFile) {
|
|
108
128
|
checkConfigFile(configFile);
|
|
109
129
|
mermaidConfig = Object.assign(mermaidConfig, JSON.parse(fs.readFileSync(configFile, 'utf-8')));
|
|
110
130
|
}
|
|
131
|
+
|
|
111
132
|
let puppeteerConfig = {};
|
|
133
|
+
|
|
112
134
|
if (puppeteerConfigFile) {
|
|
113
135
|
checkConfigFile(puppeteerConfigFile);
|
|
114
136
|
puppeteerConfig = JSON.parse(fs.readFileSync(puppeteerConfigFile, 'utf-8'));
|
|
115
|
-
}
|
|
137
|
+
} // check cssFile
|
|
138
|
+
|
|
116
139
|
|
|
117
|
-
// check cssFile
|
|
118
140
|
let myCSS;
|
|
141
|
+
|
|
119
142
|
if (cssFile) {
|
|
120
143
|
if (!fs.existsSync(cssFile)) {
|
|
121
144
|
error(`CSS file "${cssFile}" doesn't exist`);
|
|
122
145
|
}
|
|
146
|
+
|
|
123
147
|
myCSS = fs.readFileSync(cssFile, 'utf-8');
|
|
124
148
|
}
|
|
125
149
|
|
|
126
|
-
|
|
150
|
+
const info = message => {
|
|
151
|
+
if (!quiet) {
|
|
152
|
+
console.info(message);
|
|
153
|
+
}
|
|
154
|
+
}; // normalize args
|
|
155
|
+
|
|
156
|
+
|
|
127
157
|
width = parseInt(width);
|
|
128
158
|
height = parseInt(height);
|
|
129
159
|
backgroundColor = backgroundColor || 'white';
|
|
130
160
|
const deviceScaleFactor = parseInt(scale || 1, 10);
|
|
131
161
|
|
|
132
|
-
const parseMMD = (
|
|
162
|
+
const parseMMD = /*#__PURE__*/function () {
|
|
133
163
|
var _ref2 = _asyncToGenerator(function* (browser, definition, output) {
|
|
134
164
|
const page = yield browser.newPage();
|
|
135
|
-
page.setViewport({
|
|
165
|
+
page.setViewport({
|
|
166
|
+
width,
|
|
167
|
+
height,
|
|
168
|
+
deviceScaleFactor
|
|
169
|
+
});
|
|
136
170
|
yield page.goto(`file://${path.join(__dirname, 'index.html')}`);
|
|
137
171
|
yield page.evaluate(`document.body.style.background = '${backgroundColor}'`);
|
|
138
|
-
const result = yield page.$eval('#container',
|
|
172
|
+
const result = yield page.$eval('#container', (container, definition, mermaidConfig, myCSS) => {
|
|
139
173
|
container.textContent = definition;
|
|
140
174
|
window.mermaid.initialize(mermaidConfig);
|
|
175
|
+
|
|
141
176
|
if (myCSS) {
|
|
142
177
|
const head = window.document.head || window.document.getElementsByTagName('head')[0];
|
|
143
178
|
const style = document.createElement('style');
|
|
144
179
|
style.type = 'text/css';
|
|
180
|
+
|
|
145
181
|
if (style.styleSheet) {
|
|
146
182
|
style.styleSheet.cssText = myCSS;
|
|
147
183
|
} else {
|
|
148
184
|
style.appendChild(document.createTextNode(myCSS));
|
|
149
185
|
}
|
|
186
|
+
|
|
150
187
|
head.appendChild(style);
|
|
151
188
|
}
|
|
152
189
|
|
|
153
190
|
try {
|
|
154
191
|
window.mermaid.init(undefined, container);
|
|
155
|
-
return {
|
|
192
|
+
return {
|
|
193
|
+
status: 'success'
|
|
194
|
+
};
|
|
156
195
|
} catch (error) {
|
|
157
|
-
return {
|
|
196
|
+
return {
|
|
197
|
+
status: 'error',
|
|
198
|
+
error,
|
|
199
|
+
message: error.message
|
|
200
|
+
};
|
|
158
201
|
}
|
|
159
202
|
}, definition, mermaidConfig, myCSS);
|
|
203
|
+
|
|
160
204
|
if (result.status === 'error') {
|
|
161
205
|
error(result.message);
|
|
162
206
|
}
|
|
163
207
|
|
|
164
208
|
if (output.endsWith('svg')) {
|
|
165
|
-
const svg = yield page.$eval('#container',
|
|
166
|
-
return container.innerHTML;
|
|
167
|
-
});
|
|
209
|
+
const svg = yield page.$eval('#container', container => container.innerHTML);
|
|
168
210
|
const svg_xml = convertToValidXML(svg);
|
|
169
211
|
fs.writeFileSync(output, svg_xml);
|
|
170
212
|
} else if (output.endsWith('png')) {
|
|
171
|
-
const clip = yield page.$eval('svg',
|
|
213
|
+
const clip = yield page.$eval('svg', svg => {
|
|
172
214
|
const react = svg.getBoundingClientRect();
|
|
173
|
-
return {
|
|
215
|
+
return {
|
|
216
|
+
x: Math.floor(react.left),
|
|
217
|
+
y: Math.floor(react.top),
|
|
218
|
+
width: Math.ceil(react.width),
|
|
219
|
+
height: Math.ceil(react.height)
|
|
220
|
+
};
|
|
221
|
+
});
|
|
222
|
+
yield page.setViewport({
|
|
223
|
+
width: clip.x + clip.width,
|
|
224
|
+
height: clip.y + clip.height,
|
|
225
|
+
deviceScaleFactor
|
|
226
|
+
});
|
|
227
|
+
yield page.screenshot({
|
|
228
|
+
path: output,
|
|
229
|
+
clip,
|
|
230
|
+
omitBackground: backgroundColor === 'transparent'
|
|
174
231
|
});
|
|
175
|
-
yield page.setViewport({ width: clip.x + clip.width, height: clip.y + clip.height, deviceScaleFactor });
|
|
176
|
-
yield page.screenshot({ path: output, clip, omitBackground: backgroundColor === 'transparent' });
|
|
177
232
|
} else {
|
|
178
233
|
// pdf
|
|
179
234
|
if (pdfFit) {
|
|
180
|
-
const clip = yield page.$eval('svg',
|
|
235
|
+
const clip = yield page.$eval('svg', svg => {
|
|
181
236
|
const react = svg.getBoundingClientRect();
|
|
182
|
-
return {
|
|
237
|
+
return {
|
|
238
|
+
x: react.left,
|
|
239
|
+
y: react.top,
|
|
240
|
+
width: react.width,
|
|
241
|
+
height: react.height
|
|
242
|
+
};
|
|
183
243
|
});
|
|
184
244
|
yield page.pdf({
|
|
185
245
|
path: output,
|
|
@@ -200,22 +260,28 @@ const parseMMD = (() => {
|
|
|
200
260
|
return function parseMMD(_x2, _x3, _x4) {
|
|
201
261
|
return _ref2.apply(this, arguments);
|
|
202
262
|
};
|
|
203
|
-
}
|
|
263
|
+
}();
|
|
204
264
|
|
|
205
265
|
_asyncToGenerator(function* () {
|
|
206
266
|
const browser = yield puppeteer.launch(puppeteerConfig);
|
|
207
267
|
const definition = yield getInputData(input);
|
|
268
|
+
|
|
208
269
|
if (/\.md$/.test(input)) {
|
|
209
270
|
const matches = definition.match(/^```(?:mermaid)(\n([\s\S]*?))```$/gm);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
yield Promise.all(mmdStrings.map(
|
|
215
|
-
|
|
271
|
+
|
|
272
|
+
if (matches !== null) {
|
|
273
|
+
info(`Found ${matches.length} mermaid charts in Markdown input`);
|
|
274
|
+
const mmdStrings = matches.map(str => str.replace(/^```(?:mermaid)(\n([\s\S]*?))```$/, '$1').trim());
|
|
275
|
+
yield Promise.all(mmdStrings.map((mmdString, index) => {
|
|
276
|
+
const output_file = output.replace(/(\..*)$/, `-${index + 1}$1`);
|
|
277
|
+
info(` - ${output_file}`);
|
|
278
|
+
return parseMMD(browser, mmdString, output_file);
|
|
216
279
|
}));
|
|
280
|
+
} else {
|
|
281
|
+
info(`No mermaid charts found in Markdown input`);
|
|
217
282
|
}
|
|
218
283
|
} else {
|
|
284
|
+
info(`Generating single mermaid chart`);
|
|
219
285
|
yield parseMMD(browser, definition, output);
|
|
220
286
|
}
|
|
221
287
|
|