xdeb.org

Create a PDF from Markdown workflow with BBEdit and MultiMarkdown

 BBEdit Markdown preview

I use BBEdit for more or less everything I write. When I write text documents I use Markdown to format the document. If I need to send the document to a customer I generate a nicely formatted PDF. I can’t stand ugly typography so I want my PDF documents to look at least decent.

BBEdit has had Markdown support for a long time and with version 10.5 (as of this writing still in beta) there are some very good improvements. It still has the old original markdown.pl built in but with 10.5 you can specify your favourite Markdown implementation as a preview filter. Simply add a symlink to it in ~/Library/Application Support/BBEdit/Preview Filters/. Then open up a BBEdit preview window for a Markdown document and select your filter.

For non web use I think MultiMarkdown is the best version around. A easy way to get MultiMarkdown is to install it with Homebrew. MultiMarkdown has support for adding metadata to a document, including a link to a CSS file. I use this stationery for new documents in BBEdit.

File: ~/Library/Application Support/BBEdit/Stationery/Multimarkdown

Title: <#title#>  
Author: Fredrik Jonsson  
Date: <#date#>  
CSS: markdown.css  
Quotes Language: swedish  


# <#title#>

<#text#>

Some version back, maybe 10.0, BBEdit made it possible to add your own CSS for previews. This is the preview CSS for markdown that I use. By naming it “DefaultCSS_Markdown.css” BBEdit will use it by default. This CSS is also used when I generate a PDF.

File: ~/Library/Application Support/BBEdit/Preview CSS/DefaultCSS_Markdown.css

html {
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
  line-height: 1.5em;
  font-family: "Garamond Premier Pro", Times, serif;
  text-rendering: optimizeLegibility;
}

h1 {
  font-size: 2em;
  /* Sets the line height to 2 units of vertical rhythm */
  line-height: 1.5em; /* 3rem / 2em = 1.5em */
  /* Sets 1 unit of vertical rhythm on the top and bottom margins. */
  margin-top: 0.75em; /* 1.5rem / 2em = .75em */
  margin-bottom: 0.75em;
}

h2 {
  font-size: 1.5em;
  line-height: 2em; /* 3rem / 1.5em = 2em */
  margin-top: 1em; /* 1.5rem / 1.5em = 1em */
  margin-bottom: 1em;
}

h3 {
  font-size: 1.17em;
  line-height: 1.282em; /* 1.5rem / 1.17em = 1.282em */
  margin-top: 1.282em;
  margin-bottom: 1.282em;
}

h4 {
  font-size: 1em;
  line-height: 1.5em; /* 1.5rem / 1em = 1.5em */
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}

h5 {
  font-size: 0.83em;
  line-height: 1.807em; /* 1.5rem / 0.83em = 1.807em */
  margin-top: 1.807em;
  margin-bottom: 1.807em;
}

h6 {
  font-size: 0.75em;
  line-height: 2em; /* 1.5rem / .75em = 2em */
  margin-top: 2em;
  margin-bottom: 2em;
}

p,
pre {
  /* Sets 1 unit of vertical rhythm on the top and bottom margin. */
  margin: 1.5em 0;
}

pre,
code,
kbd,
samp,
tt,
var {
  line-height: 1.5em;
}

ul {
  margin-left: 0;
  padding-left: 1em;
}
ol {
  margin-left: 0;
  padding-left: 1.5em;
}

dt {
  font-weight: bold;
}
dd {
  margin: 0;
  padding: 0 0 0.5em 0;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
th, td {
  padding: 0 0 0 1.5em;
}
th:first-child, td:first-child {
  padding-left: 0;
}

So now we have nice previews generated by MultiMarkdown and styled with our own CSS. If it was possible to print from BBEdits preview window we would be done here. Unfortunately while it’s technically possible to print it is not useful since there is no concept of pages and page breaks can, and will, happen in the middle of a line of text.

I have loked around for solutions and the most mentioned is LaTeX (advanced typesetting system). I’m sure it work well when you have installed all the parts and got it running. LaTex demands the installation of Gigabytes of files and to just print a PDF that seams bit of a overkill for me.

The wkhtmltopdf utility looked promising and seems to work well with a lot of neat features for creating PDF. I could however never get nice typography output with wkhtmltopdf. The same document printed via Safari looked a lot better so I decided to use Safari.

The following solution is not fully automated, if you need that try wkhtmltopdf instead. I only need to do a few PDF every month so for me that’s a small problem. The following script will use MultiMarkdown to generate a html file in the same directory as the original Markdown document and then open that file in Safari where you can print to a PDF.

The script will put a symlink named “markdown.css” to the DefaultCSS_Markdown.css file in the same directory as well. If you look in the stationery I add a link to markdown.css in it. This way I don’t need to put in some long cumbersome path for the CSS in my Markdown document.

File: ~/Library/Application Support/BBEdit/Scripts/mmd2html2pdf

#!/usr/bin/env bash
#
# Script to make it easier to create a PDF from Markdown in BBEdit 10.
# It will use the saved file on disk so remember to save before running this script.

# Set some variables.
CSS_PATH="${HOME}/Library/Application Support/BBEdit/Preview CSS/DefaultCSS_Markdown.css"
DOC_DIR="${BB_DOC_PATH%/*}"
HTML_PATH="${BB_DOC_PATH%\.*}.html"
PDF_PATH="${BB_DOC_PATH%\.*}.pdf"

# Create a symlink in the document directory to the default preview CSS for Markdown.
ln -s "${CSS_PATH}" "${DOC_DIR}/markdown.css" 2>/dev/null

# Create a HTML file with multimarkdown.
multimarkdown --nolabels --smart --output="${HTML_PATH}" "${BB_DOC_PATH}"

# Open the HTML file in Safari
open -a Safari "${HTML_PATH}"

# Wait for the page to load completely.
sleep 1

# Open the print dialog in Safari.
osascript -e 'tell Application "Safari" to print front window with print dialog' 2>/dev/null