Skip to content

Commit 8e58534

Browse files
committed
Implemented markdown-to-pdf cli parsing
1 parent 86b4771 commit 8e58534

File tree

3 files changed

+170
-1
lines changed

3 files changed

+170
-1
lines changed

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ A collection of small handy tools for improving and converting markdown.
2020

2121
Add Github compatible table of content to markdown (Replacing "<!-- toc -->" in source file)
2222

23-
This tools uses [markdown-toc](https://github.com/jonschlinkert/markdown-toc#tocinsert) internally.
23+
This tools uses [markdown-toc](https://github.com/jonschlinkert/markdown-toc) internally.
2424

2525
## CLI
2626

@@ -44,3 +44,9 @@ This tools uses [markdown-toc](https://github.com/jonschlinkert/markdown-toc#toc
4444
--maxdepth=<depth> Use headings whose depth is at most maxdepth (default: 6)
4545
--version Display the application version
4646
```
47+
48+
# markdown-to-pdf
49+
50+
Convert markdown to PDF (and also HTML) with optional table of content.
51+
52+
Inspired by [MDPDF](https://www.npmjs.com/package/mdpdf) and [markdown-pdf](https://www.npmjs.com/package/markdown-pdf). With the improvement that you can generate a table of content (ToC) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc), and the ToC document links works correctly in the PDF even if non-latin-letter like åäö are used.

bin/markdown-to-pdf.js

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env node
2+
3+
const toc = require('markdown-toc')
4+
const fs = require('fs')
5+
const meow = require('meow')
6+
7+
//
8+
// CLI setup
9+
//
10+
const cli = meow(
11+
`
12+
Usage:
13+
$ markdown-to-pdf <source> [<destination>] [<options>]
14+
15+
<source> must be a markdown file, with the extension '.md'.
16+
<destination> must be a PDF file, with the extension '.pdf'
17+
if ommitted it will be named <source>.pdf
18+
19+
20+
Examples:
21+
$ markdown-to-pdf README.md
22+
$ markdown-to-pdf in.md out.pdf --toc
23+
$ markdown-to-pdf in.md out.pdf --toc --save-html out.html
24+
25+
Options:
26+
--border=<size> Border (top, left, bottom, right; default: 20mm)
27+
--border-top=<size> Top border (default: 20mm)
28+
--border-left=<size> Left border (default: 20mm)
29+
--border-bottom=<size> Bottom border (default: 20mm)
30+
--border-right=<size> Right border (default: 20mm)
31+
--format=<format> PDF size format: A0-A6, Legal, Ledger, Letter, Tabloid (Default: A4)
32+
33+
--toc Add table of content where a "toc" html comment is.
34+
--maxdepth=<depth> TOC: Use headings whose depth is at most maxdepth (default: 6)
35+
36+
--keep-html=<file> Keep intermediate HTML to file. if <file> is empty it follows the
37+
38+
--help Display this menu
39+
--version Display the application version
40+
`,
41+
{
42+
description:
43+
'Convert markdown to PDF (and also HTML) with optional table of content.',
44+
flags: {
45+
toc: {
46+
type: 'boolean',
47+
default: false,
48+
},
49+
maxdepth: {
50+
type: 'number',
51+
default: 6,
52+
},
53+
border: {
54+
type: 'string',
55+
default: '20mm',
56+
},
57+
keepHtml: {
58+
type: 'string',
59+
},
60+
format: {
61+
type: 'string',
62+
default: 'A4',
63+
},
64+
},
65+
}
66+
)
67+
68+
function isMarkdown(file) {
69+
return /.+\.md$/.test(file)
70+
}
71+
function isPdf(file) {
72+
return /.+\.pdf$/.test(file)
73+
}
74+
function isHtml(file) {
75+
return /.+\.html$/.test(file)
76+
}
77+
78+
function showErrorAndHelp(error) {
79+
console.error('\nError\n-----\n' + error + '\n')
80+
console.error('\nHelp\n----')
81+
cli.showHelp()
82+
}
83+
84+
const marginCheckRegex = /^[0-9]{1,10}(in|px|cm|mm)$/
85+
86+
function testBorderMargin(name, value) {
87+
if (!marginCheckRegex.test(value)) {
88+
showErrorAndHelp(
89+
`${name} must be number followed by on of the following units px, in, cm, mm.`
90+
)
91+
}
92+
}
93+
94+
const source = cli.input[0]
95+
96+
if (!isMarkdown(source)) {
97+
showErrorAndHelp('<source> not set or not a markdown file (.md)')
98+
}
99+
if (!fs.existsSync(source)) {
100+
showErrorAndHelp('<source> file does not exist')
101+
}
102+
const destination = cli.input[1] || source.replace(/\.md$/, '.pdf')
103+
104+
if (!isPdf(destination)) {
105+
showErrorAndHelp('<destination> must be a PDF file (.pdf)')
106+
}
107+
108+
const maxdepth = cli.flags.maxdepth
109+
110+
if (maxdepth < 1 || maxdepth > 6) {
111+
showErrorAndHelp('<maxdepth> must be between 1 and 6.')
112+
}
113+
114+
const border = cli.flags.border
115+
116+
testBorderMargin('border', border)
117+
118+
const margin = {
119+
top: cli.flags.borderTop || border,
120+
left: cli.flags.borderLeft || border,
121+
right: cli.flags.borderRight || border,
122+
bottom: cli.flags.borderBottom || border,
123+
}
124+
125+
for (const key in margin) {
126+
testBorderMargin('border-' + key, margin[key])
127+
}
128+
129+
const format = cli.flags.format
130+
131+
if (!/^(A[0-6]|Legal|Ledger|Letter|Tabloid)$/.test(format)) {
132+
showErrorAndHelp(
133+
'<format> must be on of the following A0-A6, Legal, Ledger, Letter, Tabloid'
134+
)
135+
}
136+
137+
const addToc = cli.flags.toc
138+
139+
const keepHtml = cli.flags.keepHtml !== undefined
140+
141+
const htmlFile = cli.flags.keepHtml || destination.replace(/\.md$/, '.html')
142+
143+
if (!isHtml(htmlFile)) {
144+
showErrorAndHelp('html file must be end with .html')
145+
}
146+
147+
const cliOptions = {
148+
source,
149+
destination,
150+
maxdepth,
151+
margin,
152+
format,
153+
addToc,
154+
keepHtml,
155+
htmlFile,
156+
}
157+
158+
console.log(cliOptions)
159+
160+
//
161+
// TODO: do stuff
162+
//

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"prettier": "1.18.2"
2727
},
2828
"bin": {
29+
"markdown-to-pdf": "bin/markdown-to-pdf.js",
2930
"markdown-github-toc": "bin/markdown-github-toc.js"
3031
}
3132
}

0 commit comments

Comments
 (0)