4

I'm looking for a way to automatically have my computer generate and print PDF files from a folder full of markdown files.

So, every morning at 5AM I'd want my computer look at my /markdown-files folder, create a bunch of PDFs to go into a /PDF-folder and also run the printer so the pages are waiting for me.

There are a couple of requirements that might make this a bit tricky:

  1. The PDFs should have the file title at the top of each page
  2. The page needs to be A4
  3. The lines should be double spaced at least.

I used to use WKPDF to generate PDFs, but it no longer works on Yosemite.

nohillside
  • 92,308
  • 39
  • 198
  • 242
CGP Grey
  • 415
  • 2
  • 7
  • 15

4 Answers4

5

You can do this with Markdown.pl and htmldoc(1), both of which can be installed with Homebrew. The basic flow for making a PDF is:

markdown foo.markdown | htmldoc --no-toc --no-title -f foo.pdf -

As for your filename-per-page, you coul incorporate echo to add it as an HTML element:

echo $(markdown foo.markdown) "<p>foo</p>" | htmldoc --no-toc --no-title -f foo.pdf -

And for printing, the lpr(1) command will send a file to your default printer.

Tying this altogether:

for filename in `ls *.markdown`;
do
    echo $(markdown "$filename") "<p>$filename</p>" | 
        htmldoc --no-toc --no-title -f "${filename}.pdf" -
    lpr "${filename}.pdf"
done
nohillside
  • 92,308
  • 39
  • 198
  • 242
Drew Stephens
  • 188
  • 1
  • 7
  • Thanks for your help. I've played with htmldoc and can see how to get it to do what I want, but you'll have to forgive me, because I'm not sure where to *put* that piece of code to actually have it run at a particular time. – CGP Grey Jan 27 '15 at 21:52
  • 1
    Edit: Hazel to the rescue! – CGP Grey Jan 27 '15 at 21:57
  • 1
    Great! I would have suggested a cronjob, but [Hazel](http://www.noodlesoft.com/hazel.php) is much friendlier. – Drew Stephens Jan 27 '15 at 22:05
  • There is still one problem: this loop just prints the first file over and over, not all the files once. for filename in `ls *.md`; do echo $(markdown $filename) "

    $filename

    " | htmldoc --no-toc --no-title --fontspacing 3 --size a4 -f ${filename}.pdf -lpr ${filename}.pdf done
    – CGP Grey Jan 27 '15 at 22:18
  • 1
    I think I just realized that this is my own dumb fault for having pipes in my file names. – CGP Grey Jan 27 '15 at 22:49
  • That assessment of your filename character choices is correct. – Drew Stephens Jan 27 '15 at 22:56
  • I can see there is still a problem: instead of creating and printing 'my filename.pdf' it's trying to do 'my.pdf' and 'filename.pdf' – CGP Grey Jan 28 '15 at 07:04
  • Put double quotes around `$filename` wherever it is used as an argument to a command to overcome this. It should then also work with pipes in the name. – nohillside Jan 28 '15 at 12:29
  • Isn't this answer an example of ["you should never parse `ls` output"](http://mywiki.wooledge.org/ParsingLs)? So instead of `\`ls *.markdown\`` should be just `*.markdown` (with a [glob](https://en.wikipedia.org/wiki/Glob_(programming)) *). PS Also, it's a better practice to use `$(command)` instead of backticks `\`command\``. – andrybak Jan 30 '15 at 09:12
  • Attempting to install html doc on el capitan yields: htmldoc: This formula either does not compile or function as expected on OS X versions newer than Yosemite due to an upstream incompatibility. Error: An unsatisfied requirement failed this build. – CGP Grey Nov 13 '15 at 05:29
  • @CGPGrey Yeah, building it from [source (left sidebar)](https://www.msweet.org/projects.php?Z1) fails…but changing a single line makes it work. On line 1385, cast that 0 to a boolean: `cinfo.quantize_colors = (boolean)0;`. Then with a `./configure && make`, it builds & runs for me (the output program is htmldoc/htmldoc) – Drew Stephens Nov 13 '15 at 13:09
2

Here's a solution that uses LaTeX to generate the PDF. If you have long-form text in the Markdown files and would like to optimize for typographic readability (and I suspect you do), LaTeX tends to do a much better job compared to HTML engines.

It uses pandoc as an intermediary between Markdown and LaTeX, and also produces the PDF for you.

Main script

#!/bin/bash

md-dir="MARKDOWN_DIRECTORY_HERE"
pdf-dir="PDF_DIRECTORY_HERE"

cd "${md-dir}"
for filename in *.md; do
    target-pdf="${pdf-dir}/${filename}.pdf"
    pandoc "${filename}" -t latex --latex-engine=xelatex -V geometry=a4paper -V fontsize=11pt -V listings -V header-includes="\usepackage{fancyhdr}\pagestyle{fancyplain}\cfoot{}\rhead{\thepage}\lhead{\texttt{\lstinline/${filename}/}}" -V header-includes="\linespread{2.0}" -o "${target-pdf}"
    echo "produced ${filename}.pdf"
    lpr "${target-pdf}"
done

Required setup

  1. Get pandoc from Homebrew: brew install pandoc
  2. Install the minimal version of LaTeX called BasicTeX

Testing if you got the setup correct

You should be able to run in a new Terminal window (with bash)

echo "test" | pandoc -t latex --latex-engine=xelatex -o test.pdf

and get a valid test.pdf document with just the word "test"

Customizations

There's a lot you can tweak with the LaTeX settings from the command line

  1. tweak the line spacing by changing the \linespread{2.0} multiplier
  2. adjust markings by replacing geometry=a4paper with geometry=a4paper,left=XXmm,right=XXmm,top=XXmm,bottom=XXmm
  3. change font size by chaining 11pt to either 10pt or 12pt, and everything should scale accordingly
  4. change the main font by adding another argument to pandoc: -V mainfont="NAME OF FONT". You can also set monofont this way.
Tim Lin
  • 121
  • 2
-1

I have not used WKPDF, but its author suggests a method by which it can be made to work in Yosemite: https://github.com/plessl/wkpdf/wiki/How-to-install-on-MacOS-10.10-Yosemite

-1

You could use PhantomJS. It's not as straight forward as WKPDF for PDF generation since it has a wider range of features, but works fine.

UloPe
  • 101
  • 2