Created
October 5, 2020 05:34
-
-
Save raylee/58574b095ead1a1cedbb5dd6e22edae3 to your computer and use it in GitHub Desktop.
Convert markdown to pdf using goldmark and wkhtmltopdf.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"flag" | |
"io/ioutil" | |
"log" | |
"path" | |
"github.com/yuin/goldmark" | |
"github.com/yuin/goldmark/extension" | |
"github.com/yuin/goldmark/parser" | |
"github.com/yuin/goldmark/renderer/html" | |
pdf "github.com/SebastiaanKlippert/go-wkhtmltopdf" | |
) | |
const DisableSandboxing = true | |
// mdtohtml uses goldmark to render the source from markdown to html | |
func mdtohtml(source []byte) []byte { | |
md := goldmark.New( | |
goldmark.WithExtensions( | |
extension.GFM, | |
// extension.NewLinkify(), | |
extension.Footnote, | |
extension.NewTable(), | |
extension.DefinitionList, | |
extension.NewTypographer(), | |
), | |
goldmark.WithParserOptions( | |
parser.WithAutoHeadingID(), | |
), | |
goldmark.WithRendererOptions( | |
html.WithHardWraps(), | |
html.WithUnsafe(), | |
), | |
) | |
var buf bytes.Buffer | |
if err := md.Convert(source, &buf); err != nil { | |
panic(err) | |
} | |
return buf.Bytes() | |
} | |
// htmltopdf uses go-wkhtmltopdf to render the source html as a pdf | |
func htmltopdf(source []byte) []byte { | |
// Create new PDF generator | |
pdfg, err := pdf.NewPDFGenerator() | |
if err != nil { | |
log.Fatal(err) | |
} | |
pdfg.Dpi.Set(600) | |
pdfg.Orientation.Set(pdf.OrientationPortrait) | |
pdfg.Grayscale.Set(false) | |
pdfg.PageSize.Set(pdf.PageSizeLetter) | |
page := pdf.NewPageReader(bytes.NewReader(source)) | |
// page.FooterRight.Set("[page]") | |
// page.FooterFontSize.Set(8) | |
// page.Zoom.Set(0.95) | |
if DisableSandboxing { | |
page.Allow.Set(".") | |
page.EnableLocalFileAccess.Set(true) | |
} | |
pdfg.AddPage(page) | |
// Create PDF document in internal buffer | |
if err = pdfg.Create(); err != nil { | |
log.Fatal(err) | |
} | |
return pdfg.Buffer().Bytes() | |
} | |
var ( | |
savehtml = flag.Bool("html", false, "preserve the html intermediate representation") | |
) | |
func SetExt(filename, newext string) string { | |
ext := path.Ext(filename) | |
return filename[0:len(filename)-len(ext)] + newext | |
} | |
func main() { | |
flag.Parse() | |
files := flag.Args() | |
for _, fn := range files { | |
md, _ := ioutil.ReadFile(fn) | |
html := mdtohtml(md) | |
if *savehtml { | |
ioutil.WriteFile(SetExt(fn, ".html"), html, 0644) | |
} | |
pdf := htmltopdf(html) | |
ioutil.WriteFile(SetExt(fn, ".pdf"), pdf, 0644) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requires wkhtmltopdf installed as a binary in $PATH.