Skip to content

Commit 557ff98

Browse files
committed
A first version that does create an PDF
1 parent 8e58534 commit 557ff98

File tree

6 files changed

+980
-38
lines changed

6 files changed

+980
-38
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
2-
*.tgz
2+
*.tgz
3+
README.pdf

bin/markdown-to-pdf.js

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#!/usr/bin/env node
22

3-
const toc = require('markdown-toc')
43
const fs = require('fs')
54
const meow = require('meow')
65

@@ -138,12 +137,15 @@ const addToc = cli.flags.toc
138137

139138
const keepHtml = cli.flags.keepHtml !== undefined
140139

141-
const htmlFile = cli.flags.keepHtml || destination.replace(/\.md$/, '.html')
140+
const htmlFile = cli.flags.keepHtml || destination.replace(/\.pdf/, '.html')
141+
142+
console.log(htmlFile)
142143

143144
if (!isHtml(htmlFile)) {
144145
showErrorAndHelp('html file must be end with .html')
145146
}
146147

148+
// TODO: no print
147149
const cliOptions = {
148150
source,
149151
destination,
@@ -157,6 +159,134 @@ const cliOptions = {
157159

158160
console.log(cliOptions)
159161

162+
// TODO: move to be separate lib file
163+
160164
//
161165
// TODO: do stuff
162166
//
167+
const { Remarkable } = require('remarkable')
168+
const path = require('path')
169+
const puppeteer = require('puppeteer')
170+
const toc = require('markdown-toc')
171+
//
172+
const hljs = require('highlight.js')
173+
174+
function addTocToMarkdown(markdown, tocOptions) {
175+
return toc.insert(markdown, tocOptions) //{open: '', close: ''});
176+
}
177+
178+
function markdownToHtml(markdown) {
179+
// Actual default values
180+
return new Remarkable({
181+
html: true,
182+
highlight: function(str, lang) {
183+
if (lang && hljs.getLanguage(lang)) {
184+
try {
185+
return hljs.highlight(lang, str).value
186+
// eslint-disable-next-line no-empty
187+
} catch (err) {}
188+
}
189+
190+
try {
191+
return hljs.highlightAuto(str).value
192+
// eslint-disable-next-line no-empty
193+
} catch (err) {}
194+
195+
return '' // use external default escaping
196+
},
197+
})
198+
.use(remarkable => {
199+
remarkable.renderer.rules.heading_open = function(tokens, idx) {
200+
return (
201+
'<h' +
202+
tokens[idx].hLevel +
203+
' id=' +
204+
toc.slugify(tokens[idx + 1].content) +
205+
'>'
206+
)
207+
}
208+
})
209+
.render(markdown)
210+
}
211+
212+
function createPdf(htmlPath, pdfPath, options) {
213+
// Write html to a temp file
214+
let browser
215+
let page
216+
217+
return puppeteer
218+
.launch({ headless: true })
219+
.then(newBrowser => {
220+
browser = newBrowser
221+
return browser.newPage()
222+
})
223+
.then(p => {
224+
page = p
225+
return page.goto('file:' + path.resolve(htmlPath), {
226+
waitUntil: 'networkidle2',
227+
})
228+
})
229+
.then(() => {
230+
const pdfOptions = {
231+
margin: options.margin,
232+
path: pdfPath,
233+
displayHeaderFooter: false,
234+
printBackground: true,
235+
format: options.format,
236+
}
237+
238+
console.log('pdfOptions', pdfOptions)
239+
240+
return page.pdf(pdfOptions)
241+
})
242+
.then(() => {
243+
return browser.close()
244+
})
245+
}
246+
247+
let markdown = fs.readFileSync(source, 'utf-8')
248+
249+
// TODO: compress CSS
250+
const cssStyleFiles = [
251+
path.join(__dirname, '../styles/github-markdown-css.css'),
252+
path.join(__dirname, '../styles/default.css'),
253+
path.join(__dirname, '../node_modules/highlight.js/styles/github.css'),
254+
]
255+
256+
const cssStyle = cssStyleFiles
257+
.map(file => fs.readFileSync(file, 'utf-8').replace(/\r\n/g, '\n'))
258+
.join('\n')
259+
260+
if (addToc) {
261+
markdown = addTocToMarkdown(markdown, {
262+
indent: '\t',
263+
maxdepth,
264+
})
265+
}
266+
267+
const htmlContent = markdownToHtml(markdown)
268+
269+
const html = `
270+
<!DOCTYPE html>
271+
<html>
272+
<head>
273+
<meta charset="utf-8" />
274+
<style>${cssStyle}</style>
275+
</head>
276+
<body class="markdown-body">
277+
${htmlContent}
278+
</body>
279+
</html>
280+
`
281+
282+
// TODO: html in memory if possible?
283+
fs.writeFileSync(htmlFile, html)
284+
285+
createPdf(htmlFile, destination, {
286+
margin,
287+
format,
288+
}).then(() => {
289+
if (!keepHtml) {
290+
fs.unlinkSync(htmlFile)
291+
}
292+
})

0 commit comments

Comments
 (0)