Skip to content

Commit 0334f89

Browse files
committed
Enable graphviz.
* Both `.docogen` and `markdown` support! * Currently only support on linux platform, windows version will be patch up in upcoming days.
1 parent 89a3414 commit 0334f89

File tree

12 files changed

+283
-50
lines changed

12 files changed

+283
-50
lines changed

install_dep.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
#!/bin/bash
22

33
<<COMMENT1
4-
Use to automatically install MikTex dependency for docoGen
4+
Use to automatically install dependencies for docoGen
5+
* MiKTeX
6+
* graphviz
7+
Welcome to support different platform installation!
58
COMMENT1
69

710
if [[ "$OSTYPE" == "linux-gnu" ]]; then
811
echo "Linux platform detected. Installing..."
12+
# =========== Install MiKTeX for LaTeX support ===========
913
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys D6BC243565B2087BC3F897C9277A7293F59E4889
1014
echo "deb http://miktex.org/download/ubuntu xenial universe" | sudo tee /etc/apt/sources.list.d/miktex.list
1115
sudo apt update && sudo apt install miktex
1216
# install tex dependencies
1317
sudo apt install texlive texstudio texlive-latex-extra
18+
# =========== Install graphviz for graph support ===========
19+
sudo apt install graphviz
1420
elif [[ "$OSTYPE" == "darwin"* ]]; then
1521
# Mac OSX
1622
echo "Not Support MacOS script now"

lib/docogen-graphviz.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
const exec = require('child_process').exec,
2+
rs = require('randomstring'),
3+
path = require('path'),
4+
fs = require('fs'),
5+
os = require('os');
6+
7+
const gviz = {};
8+
9+
/*
10+
Available graphviz type:
11+
canon cmap cmapx cmapx_np dot eps fig gd gd2
12+
gif gv imap imap_np ismap jpe jpeg jpg pdf pic
13+
plain plain-ext png pov ps ps2 svg svgz tk vml
14+
vmlz vrml wbmp x11 xdot xdot1.2 xdot1.4 xlib
15+
*/
16+
17+
gviz.drawRaw = function(raw,option,cb){
18+
let tmp = 'drawFile-'+rs.generate(12).toString() ;
19+
option =
20+
{
21+
type : option.type || 'png',
22+
dest : option.dest || os.tmpdir(),
23+
output: option.output || tmp
24+
};
25+
let tmpf = tmp + '.dot'
26+
let tmpr = option.output + '.' + option.type
27+
// Write file
28+
fs.writeFile(path.join(option.dest,tmpf),raw,(err) => {
29+
if(err){
30+
cb(1,`Can't not write file in ${option.dest}\nPlease check out the permission or your input!`)
31+
//console.error(`Can't not write file in ${option.dest}\nPlease check out the permission or your input!`)
32+
}
33+
else{
34+
// detect os
35+
if(os.type() == "Windows_NT"){
36+
cb(1,`Currently not support graphviz function on ${os.type()}!`)
37+
//console.error(`Currently not support graphviz function on ${os.type()}!`)
38+
}
39+
else if(os.type() == "Linux"){
40+
// Linux
41+
// Generate the result
42+
p = exec(`dot -T${option.type} ${path.join(option.dest,tmpf)} -o ${path.join(option.dest,tmpr)}`,(err,stdout,stderr) => {
43+
44+
if(err){
45+
cb(1,`Error: ${stderr}`)
46+
//console.log(`Error: ${stderr}`)
47+
}
48+
else{
49+
console.log(`Success!\nYour result has been stored in ${path.join(option.dest,tmpr)}\nAnd the source file is temporarily stored in ${path.join(os.tmpdir(),tmpf)}\n`)
50+
cb(0,{ tmpf: path.join(option.dest,tmpf), result: path.join(option.dest,tmpr)})
51+
}
52+
});
53+
}
54+
else{
55+
// FIXME: Other platform
56+
cb(1,`Currently not support graphviz function on ${os.type()}!`)
57+
// console.error(`Currently not support graphviz function on ${os.type()}!`)
58+
}
59+
60+
}
61+
})
62+
}
63+
64+
gviz.drawFile = function(file,option,cb){
65+
let tmp = 'drawFile-'+rs.generate(12).toString()
66+
option =
67+
{
68+
type : option.type || 'png',
69+
dest : option.dest || os.tmpdir(),
70+
output: option.output || tmp
71+
};
72+
let tmpr = option.output + '.' + option.type
73+
// detect os
74+
if(os.type() == "Windows_NT"){
75+
cb(1,`Currently not support graphviz function on ${os.type()}!`)
76+
}
77+
else if(os.type() == "Linux"){
78+
// Linux
79+
// Generate the result
80+
p = exec(`dot -T${option.type} ${file} -o ${path.join(option.dest,tmpr)}`,(err,stdout,stderr) => {
81+
if(err)
82+
cb(1,`Error: ${stderr}`)
83+
else{
84+
console.log(`Success!\nYour result has been stored in ${path.join(option.dest,tmpr)}\n`)
85+
cb(0,{ result: path.join(option.dest,tmpr)})
86+
}
87+
});
88+
}
89+
else{
90+
// FIXME: Other platform
91+
cb(1,`Currently not support graphviz function on ${os.type()}!`)
92+
}
93+
}
94+
module.exports = gviz;

lib/docogen-latex-engine.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const fs = require('fs');
77
const os = require('os');
88

99
const utils = require('./docogen-util');
10+
const gviz = require('./docogen-graphviz')
1011
const latex_engine = {};
1112

1213
latex_engine.trans2latex = function(jsObj){
@@ -290,6 +291,48 @@ function append_article(concater,items,depth){
290291
concater += `\n\\end{tcolorbox}`;
291292
}
292293
break;
294+
case "graphviz":
295+
concater += `${items[index].content[c_index].name}\n\n`;
296+
for(var t_index in items[index].content[c_index].data){
297+
if(items[index].content[c_index].data[t_index].src != undefined && items[index].content[c_index].data[t_index].src != ""){
298+
if(items[index].content[c_index].data[t_index].size == "") items[index].content[c_index].data[t_index].size = 1;
299+
// generate from file
300+
let result = 'drawFile-'+rs.generate(12).toString();
301+
gviz.drawFile(items[index].content[c_index].data[t_index].src,{output:result,dest:os.tmpdir(),type:'png'},(err,msg) => {
302+
if(err)
303+
console.log(msg)
304+
else{
305+
console.log(`Result image: ${msg.result}\n\n`)
306+
}
307+
});
308+
// Append the filename on it
309+
concater += `\\begin{figure}[H]\n\\begin{${items[index].content[c_index].data[t_index].align}}\n`;
310+
concater += `\\includegraphics[width=${items[index].content[c_index].data[t_index].size}\\textwidth]{${path.join(os.tmpdir(),result+'.png')}}\n`;
311+
concater += `\\caption{${items[index].content[c_index].data[t_index].caption}}\n`;
312+
concater += `\\end{${items[index].content[c_index].data[t_index].align}}\n\\end{figure}\n\n`;
313+
}
314+
else if(items[index].content[c_index].data[t_index].raw != ""){
315+
// draw from raw
316+
let result = 'drawFile-'+rs.generate(12).toString();
317+
gviz.drawRaw(items[index].content[c_index].data[t_index].raw,{output:result,dest:os.tmpdir(),type:'png'},(err,msg) => {
318+
if(err)
319+
console.log(msg)
320+
else{
321+
if(err)
322+
console.log(msg)
323+
else{
324+
console.log(`Temp file: ${msg.tmpf}\nResult image: ${msg.result}\n\n`)
325+
}
326+
}
327+
})
328+
// Append the filename on it
329+
concater += `\\begin{figure}[H]\n\\begin{${items[index].content[c_index].data[t_index].align}}\n`;
330+
concater += `\\includegraphics[width=${items[index].content[c_index].data[t_index].size}\\textwidth]{${path.join(os.tmpdir(),result+'.png')}}\n`;
331+
concater += `\\caption{${items[index].content[c_index].data[t_index].caption}}\n`;
332+
concater += `\\end{${items[index].content[c_index].data[t_index].align}}\n\\end{figure}\n\n`;
333+
}
334+
}
335+
break;
293336
default:
294337
// not match
295338
break;

lib/docogen-md-engine.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,14 @@ function parse_data(type,ast_obj_array){
525525
data_element = nested_ex(ast_obj_array.children[1].children[index].children)
526526
}
527527
break;
528+
case "graphviz":
529+
// use
530+
console.log("Raw Graphviz Info: " + ast_obj_array.children[1].children[index].children[0].raw)
531+
if(ast_obj_array.children[1].children[index].children != undefined && ast_obj_array.children[1].children[index].children.length > 1){
532+
// Parse the elements
533+
data_element = nested_ex(ast_obj_array.children[1].children[index].children)
534+
}
535+
break;
528536
case "web-restful-api":
529537
if(ast_obj_array.children[1].children[index].children != undefined && ast_obj_array.children[1].children[index].children.length > 1){
530538
// Parse the elements

lib/docogen-util.js

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,55 +5,16 @@ const path = require('path'),
55

66
const utils = {}
77

8-
// Resolve the relative path (code section)
9-
utils.resolve_code = function(jsObj,dirname){
10-
if(jsObj.length == 0){
11-
return jsObj;
12-
}
13-
for(var index in jsObj){
14-
// content array
15-
if(jsObj[index].content != undefined){
16-
for(var c_index in jsObj[index].content){
17-
// "code" type in data section
18-
if(jsObj[index].content[c_index].type == "code"){
19-
for(var d_index in jsObj[index].content[c_index].data){
20-
// only relative need to be done, default value is rel
21-
jsObj[index].content[c_index].data[d_index].flag == (jsObj[index].content[c_index].data[d_index].flag == undefined) ? "rel" : jsObj[index].content[c_index].data[d_index].flag;
22-
// only need to deal with relative path
23-
if(jsObj[index].content[c_index].data[d_index].flag == "rel")
24-
if(jsObj[index].content[c_index].data[d_index].src != undefined || jsObj[index].content[c_index].data[d_index].src != ""){
25-
// resolve the path
26-
console.log(`Inside Before: ${jsObj[index].content[c_index].data[d_index].src}`)
27-
jsObj[index].content[c_index].data[d_index].src = path.resolve(dirname,jsObj[index].content[c_index].data[d_index].src)
28-
// If os version is Windows, need to replace again!
29-
if(os.type() == "Windows_NT"){
30-
jsObj[index].content[c_index].data[d_index].src = jsObj[index].content[c_index].data[d_index].src.replace(/\\/g,'/');
31-
}
32-
console.log(`Inside After: ${jsObj[index].content[c_index].data[d_index].src}`)
33-
}
34-
}
35-
}
36-
// subarticle (nested)
37-
if(jsObj[index].content[c_index].subarticle != undefined && jsObj[index].content[c_index].subarticle.length > 0){
38-
jsObj[index].content[c_index].subarticle = this.resolve_code(jsObj[index].content[c_index].subarticle,dirname);
39-
}
40-
}
41-
}
42-
}
43-
44-
return jsObj;
45-
}
46-
47-
// Resolve the relative path (figure section)
48-
utils.resolve_figure = function(jsObj,dirname){
8+
// Resolve the relative path
9+
utils.resolve = function(jsObj,dirname){
4910
if(jsObj.length == 0){
5011
return jsObj;
5112
}
5213
for(var index in jsObj){
5314
// inside figure
5415
if(jsObj[index].content != undefined){
5516
for(var c_index in jsObj[index].content){
56-
// outside figure
17+
// "figure" section
5718
if(jsObj[index].content[c_index].figure != undefined && jsObj[index].content[c_index].figure.length > 0){
5819
for(var f_index in jsObj[index].content[c_index].figure){
5920
// only relative need to be done, default value is rel
@@ -70,6 +31,7 @@ utils.resolve_figure = function(jsObj,dirname){
7031
}
7132
}
7233
}
34+
// "figure" in data section
7335
if(jsObj[index].content[c_index].type == "figure"){
7436
for(var d_index in jsObj[index].content[c_index].data){
7537
// only relative need to be done, default value is rel
@@ -86,9 +48,47 @@ utils.resolve_figure = function(jsObj,dirname){
8648
}
8749
}
8850
}
51+
// "Code" in data section
52+
if(jsObj[index].content[c_index].type == "code"){
53+
for(var d_index in jsObj[index].content[c_index].data){
54+
// only relative need to be done, default value is rel
55+
jsObj[index].content[c_index].data[d_index].flag == (jsObj[index].content[c_index].data[d_index].flag == undefined) ? "rel" : jsObj[index].content[c_index].data[d_index].flag;
56+
// only need to deal with relative path
57+
if(jsObj[index].content[c_index].data[d_index].flag == "rel")
58+
if(jsObj[index].content[c_index].data[d_index].src != undefined || jsObj[index].content[c_index].data[d_index].src != ""){
59+
// resolve the path
60+
console.log(`Inside Before: ${jsObj[index].content[c_index].data[d_index].src}`)
61+
jsObj[index].content[c_index].data[d_index].src = path.resolve(dirname,jsObj[index].content[c_index].data[d_index].src)
62+
// If os version is Windows, need to replace again!
63+
if(os.type() == "Windows_NT"){
64+
jsObj[index].content[c_index].data[d_index].src = jsObj[index].content[c_index].data[d_index].src.replace(/\\/g,'/');
65+
}
66+
console.log(`Inside After: ${jsObj[index].content[c_index].data[d_index].src}`)
67+
}
68+
}
69+
}
70+
// "Graphviz" in data section
71+
if(jsObj[index].content[c_index].type == "graphviz"){
72+
for(var d_index in jsObj[index].content[c_index].data){
73+
// only relative need to be done, default value is rel
74+
jsObj[index].content[c_index].data[d_index].flag == (jsObj[index].content[c_index].data[d_index].flag == undefined) ? "rel" : jsObj[index].content[c_index].data[d_index].flag;
75+
// only need to deal with relative path
76+
if(jsObj[index].content[c_index].data[d_index].flag == "rel")
77+
if(jsObj[index].content[c_index].data[d_index].src != undefined || jsObj[index].content[c_index].data[d_index].src != ""){
78+
// resolve the path
79+
console.log(`Inside Before: ${jsObj[index].content[c_index].data[d_index].src}`)
80+
jsObj[index].content[c_index].data[d_index].src = path.resolve(dirname,jsObj[index].content[c_index].data[d_index].src)
81+
// If os version is Windows, need to replace again!
82+
if(os.type() == "Windows_NT"){
83+
jsObj[index].content[c_index].data[d_index].src = jsObj[index].content[c_index].data[d_index].src.replace(/\\/g,'/');
84+
}
85+
console.log(`Inside After: ${jsObj[index].content[c_index].data[d_index].src}`)
86+
}
87+
}
88+
}
8989
// subarticle (nested)
9090
if(jsObj[index].content[c_index].subarticle != undefined && jsObj[index].content[c_index].subarticle.length > 0){
91-
jsObj[index].content[c_index].subarticle = this.resolve_figure(jsObj[index].content[c_index].subarticle,dirname);
91+
jsObj[index].content[c_index].subarticle = this.resolve(jsObj[index].content[c_index].subarticle,dirname);
9292
}
9393
}
9494
}

main.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ const os = require('os');
99

1010
const latex_engine = require('./lib/docogen-latex-engine');
1111
const md_engine = require('./lib/docogen-md-engine');
12+
const gviz = require('./lib/docogen-graphviz');
1213
const utils = require('./lib/docogen-util');
14+
1315
const docogen = {};
1416

1517
docogen.generate_latexpdf = function(src,dest,options,cb){
@@ -275,18 +277,15 @@ docogen.merge_docogen_promise = function(src_arr,options){
275277
docogen.resolve_rel = function(jsObj,dirname){
276278
// resolving the path from rel to abs
277279
if(os.type() == "Windows_NT"){
278-
jsObj.article = utils.resolve_figure(jsObj.article,dirname.substring(0,dirname.lastIndexOf('\\')));
279-
jsObj.article = utils.resolve_code(jsObj.article,dirname.substring(0,dirname.lastIndexOf('\\')));
280+
jsObj.article = utils.resolve(jsObj.article,dirname.substring(0,dirname.lastIndexOf('\\')));
280281
}
281282
else if(os.type() == "Linux"){
282283
// Linux
283-
jsObj.article = utils.resolve_figure(jsObj.article,dirname.substring(0,dirname.lastIndexOf('/')));
284-
jsObj.article = utils.resolve_code(jsObj.article,dirname.substring(0,dirname.lastIndexOf('/')));
284+
jsObj.article = utils.resolve(jsObj.article,dirname.substring(0,dirname.lastIndexOf('/')));
285285
}
286286
else{
287287
// FIXME: Other platform, currently use linux
288-
jsObj.article = utils.resolve_figure(jsObj.article,dirname.substring(0,dirname.lastIndexOf('/')));
289-
jsObj.article = utils.resolve_code(jsObj.article,dirname.substring(0,dirname.lastIndexOf('/')));
288+
jsObj.article = utils.resolve(jsObj.article,dirname.substring(0,dirname.lastIndexOf('/')));
290289
}
291290

292291
return jsObj
@@ -336,6 +335,9 @@ docogen.merge_docogen_ex_promise = function(src_path,options){
336335
// Utils exports
337336
docogen.utils = utils;
338337

338+
// Graphviz exports
339+
docogen.gviz = gviz;
340+
339341
// Export for markdown engine
340342
docogen.md2docogen = md_engine.md2docogen;
341343

test/dest/docogen-latex-fromMD.pdf

30.2 KB
Binary file not shown.

test/dest/docogen-latex.pdf

29.7 KB
Binary file not shown.

test/dotfile/graphviz.dot

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
digraph G {
2+
one -> two;
3+
one -> three;
4+
one -> four;
5+
four -> five -> six;
6+
five -> one;
7+
six -> two;
8+
}

test/graphviz.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const docogen = require('../main')
2+
3+
docogen.gviz.drawRaw('digraph G {\n\
4+
\tone -> two;\n\
5+
\tone -> three;\n\
6+
\tone -> four;\
7+
\n}\n', {} , (err,msg) => {
8+
if(err)
9+
console.log(msg)
10+
else{
11+
console.log(`Temp file: ${msg.tmpf}\nResult image: ${msg.result}\n\n`)
12+
}
13+
});
14+
15+
docogen.gviz.drawFile('dotfile/graphviz.dot',{},(err,msg) => {
16+
if(err)
17+
console.log(msg)
18+
else{
19+
console.log(`Result image: ${msg.result}\n\n`)
20+
}
21+
});

0 commit comments

Comments
 (0)