-
Notifications
You must be signed in to change notification settings - Fork 254
/
index.js
144 lines (123 loc) · 4.54 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
var fs = require('fs')
var path = require('path')
var childProcess = require('child_process')
var through = require('through2')
var extend = require('extend')
var { Remarkable } = require('remarkable')
var hljs = require('highlight.js')
var tmp = require('tmp')
var duplexer = require('duplexer')
var streamft = require('stream-from-to')
tmp.setGracefulCleanup()
function markdownpdf (opts) {
opts = opts || {}
opts.cwd = opts.cwd ? path.resolve(opts.cwd) : process.cwd()
opts.phantomPath = opts.phantomPath || require('phantomjs-prebuilt').path
opts.runningsPath = opts.runningsPath ? path.resolve(opts.runningsPath) : path.join(__dirname, 'runnings.js')
opts.cssPath = opts.cssPath ? path.resolve(opts.cssPath) : path.join(__dirname, 'css', 'pdf.css')
opts.highlightCssPath = opts.highlightCssPath ? path.resolve(opts.highlightCssPath) : path.join(__dirname, 'css', 'highlight.css')
opts.paperFormat = opts.paperFormat || 'A4'
opts.paperOrientation = opts.paperOrientation || 'portrait'
opts.paperBorder = opts.paperBorder || '2cm'
opts.renderDelay = opts.renderDelay == null ? 0 : opts.renderDelay
opts.loadTimeout = opts.loadTimeout == null ? 10000 : opts.loadTimeout
opts.preProcessMd = opts.preProcessMd || function () { return through() }
opts.preProcessHtml = opts.preProcessHtml || function () { return through() }
opts.remarkable = extend({ breaks: true }, opts.remarkable)
opts.remarkable.preset = opts.remarkable.preset || 'default'
opts.remarkable.plugins = opts.remarkable.plugins || []
opts.remarkable.syntax = opts.remarkable.syntax || []
var md = ''
var mdToHtml = through(
function transform (chunk, enc, cb) {
md += chunk
cb()
},
function flush (cb) {
var self = this
var mdParser = new Remarkable(opts.remarkable.preset, extend({
highlight: function (str, language) {
if (language && hljs.getLanguage(language)) {
try {
return hljs.highlight(str, { language }).value
} catch (err) {}
}
try {
return hljs.highlightAuto(str).value
} catch (err) {}
return ''
}
}, opts.remarkable))
opts.remarkable.plugins.forEach(function (plugin) {
if (plugin && typeof plugin === 'function') {
mdParser.use(plugin)
}
})
opts.remarkable.syntax.forEach(function (rule) {
try {
mdParser.core.ruler.enable([rule])
} catch (err) {}
try {
mdParser.block.ruler.enable([rule])
} catch (err) {}
try {
mdParser.inline.ruler.enable([rule])
} catch (err) {}
})
self.push(mdParser.render(md))
self.push(null)
}
)
var inputStream = through()
var outputStream = through()
// Stop input stream emitting data events until we're ready to read them
inputStream.pause()
// Create tmp file to save HTML for phantom to process
tmp.file({ postfix: '.html' }, function (err, tmpHtmlPath, tmpHtmlFd) {
if (err) return outputStream.emit('error', err)
fs.closeSync(tmpHtmlFd)
// Create tmp file to save PDF to
tmp.file({ postfix: '.pdf' }, function (err, tmpPdfPath, tmpPdfFd) {
if (err) return outputStream.emit('error', err)
fs.closeSync(tmpPdfFd)
var htmlToTmpHtmlFile = fs.createWriteStream(tmpHtmlPath)
htmlToTmpHtmlFile.on('finish', function () {
// Invoke phantom to generate the PDF
var childArgs = [
path.join(__dirname, 'phantom', 'render.js'),
tmpHtmlPath,
tmpPdfPath,
opts.cwd,
opts.runningsPath,
opts.cssPath,
opts.highlightCssPath,
opts.paperFormat,
opts.paperOrientation,
typeof opts.paperBorder === 'object' ? JSON.stringify(opts.paperBorder) : opts.paperBorder,
opts.renderDelay,
opts.loadTimeout
]
childProcess.execFile(opts.phantomPath, childArgs, function (err, stdout, stderr) {
// if (stdout) console.log(stdout)
// if (stderr) console.error(stderr)
if (err) return outputStream.emit('error', err)
fs.createReadStream(tmpPdfPath).pipe(outputStream)
})
})
// Setup the pipeline
inputStream
.pipe(opts.preProcessMd())
.pipe(mdToHtml)
.pipe(opts.preProcessHtml())
.pipe(htmlToTmpHtmlFile)
inputStream.resume()
})
})
return extend(
duplexer(inputStream, outputStream),
streamft(function () {
return markdownpdf(opts)
})
)
}
module.exports = markdownpdf