Created
December 27, 2015 21:40
-
-
Save stephenjbarr/11c23e99febd19dccfbd to your computer and use it in GitHub Desktop.
modification of John MacFarlane's BayHac 2014 example to output a PDF
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
{-# LANGUAGE OverloadedStrings #-} | |
import Text.Pandoc.Builder | |
import Text.Pandoc | |
import Text.Pandoc.PDF | |
import Data.Monoid ((<>), mempty, mconcat) | |
import Data.Aeson | |
import Control.Applicative | |
import Control.Monad | |
import Control.Monad.IO.Class | |
import qualified Data.ByteString.Lazy as BL | |
import qualified Data.Text as T | |
import Data.List (intersperse) | |
import Data.Either | |
data Station = Station{ | |
address :: String | |
, name :: String | |
, cardsAccepted :: [String] | |
} deriving Show | |
instance FromJSON Station where | |
parseJSON (Object v) = Station <$> | |
v .: "street_address" <*> | |
v .: "station_name" <*> | |
(words <$> (v .:? "cards_accepted" .!= "")) | |
parseJSON _ = mzero | |
createLetter :: [Station] -> Pandoc | |
createLetter stations = doc $ | |
para "Dear Boss:" <> | |
para "Here are the CNG stations that accept Voyager cards:" <> | |
simpleTable [plain "Station", plain "Address", plain "Cards accepted"] | |
(map stationToRow stations) <> | |
para "Your loyal servant," <> | |
plain (image "JohnHancock.png" "" mempty) | |
where | |
stationToRow station = | |
[ plain (text $ name station) | |
, plain (text $ address station) | |
, plain (mconcat $ intersperse linebreak $ map text $ cardsAccepted station) | |
] | |
export :: (MonadIO m) => String -> Pandoc -> m (Either BL.ByteString BL.ByteString) | |
export tmpl pdoc = liftIO $ makePDF "xelatex" writeLaTeX (def { writerStandalone = True, writerTemplate = tmpl}) pdoc | |
getLetter = do | |
json <- BL.readFile "cng_fuel_chicago.json" | |
let letter = case decode json of | |
Just stations -> createLetter [s | s <- stations, | |
"Voyager" `elem` cardsAccepted s] | |
Nothing -> error "Could not decode JSON" | |
return $ letter | |
main :: IO () | |
main = do | |
letter <- getLetter | |
temp <- readFile "template.tex" | |
let str_should_have_something = writeLaTeX (def {writerStandalone = True, writerTemplate = temp}) letter | |
print str_should_have_something | |
mybytes <- export temp letter | |
case mybytes of Right b -> BL.writeFile "mypdf.pdf" b | |
Left _ -> putStrLn "Export error" | |
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
#!/bin/bash | |
wget http://johnmacfarlane.net/BayHac2014/JohnHancock.png | |
wget http://johnmacfarlane.net/BayHac2014/fuel.hs | |
wget http://johnmacfarlane.net/BayHac2014/cng_fuel_chicago.json |
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
\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$$if(papersize)$$papersize$,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$} | |
$if(fontfamily)$ | |
\usepackage{$fontfamily$} | |
$else$ | |
\usepackage{lmodern} | |
$endif$ | |
$if(linestretch)$ | |
\usepackage{setspace} | |
\setstretch{$linestretch$} | |
$endif$ | |
\usepackage{amssymb,amsmath} | |
\usepackage{ifxetex,ifluatex} | |
\usepackage{fixltx2e} % provides \textsubscript | |
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex | |
\usepackage[T1]{fontenc} | |
\usepackage[utf8]{inputenc} | |
$if(euro)$ | |
\usepackage{eurosym} | |
$endif$ | |
\else % if luatex or xelatex | |
\ifxetex | |
\usepackage{mathspec} | |
\usepackage{xltxtra,xunicode} | |
\else | |
\usepackage{fontspec} | |
\fi | |
\defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} | |
\newcommand{\euro}{€} | |
$if(mainfont)$ | |
\setmainfont{$mainfont$} | |
$endif$ | |
$if(sansfont)$ | |
\setsansfont{$sansfont$} | |
$endif$ | |
$if(monofont)$ | |
\setmonofont[Mapping=tex-ansi]{$monofont$} | |
$endif$ | |
$if(mathfont)$ | |
\setmathfont(Digits,Latin,Greek){$mathfont$} | |
$endif$ | |
$if(CJKmainfont)$ | |
\usepackage{xeCJK} | |
\setCJKmainfont[$CJKoptions$]{$CJKmainfont$} | |
$endif$ | |
\fi | |
% use upquote if available, for straight quotes in verbatim environments | |
\IfFileExists{upquote.sty}{\usepackage{upquote}}{} | |
% use microtype if available | |
\IfFileExists{microtype.sty}{% | |
\usepackage{microtype} | |
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts | |
}{} | |
$if(geometry)$ | |
\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} | |
$endif$ | |
\ifxetex | |
\usepackage[setpagesize=false, % page size defined by xetex | |
unicode=false, % unicode breaks when used with xetex | |
xetex]{hyperref} | |
\else | |
\usepackage[unicode=true]{hyperref} | |
\fi | |
\usepackage[usenames,dvipsnames]{color} | |
\hypersetup{breaklinks=true, | |
bookmarks=true, | |
pdfauthor={$author-meta$}, | |
pdftitle={$title-meta$}, | |
colorlinks=true, | |
citecolor=$if(citecolor)$$citecolor$$else$blue$endif$, | |
urlcolor=$if(urlcolor)$$urlcolor$$else$blue$endif$, | |
linkcolor=$if(linkcolor)$$linkcolor$$else$magenta$endif$, | |
pdfborder={0 0 0}} | |
\urlstyle{same} % don't use monospace font for urls | |
$if(lang)$ | |
\ifxetex | |
\usepackage{polyglossia} | |
\setmainlanguage{$mainlang$} | |
\setotherlanguages{$for(otherlang)$$otherlang$$sep$,$endfor$} | |
\else | |
\usepackage[shorthands=off,$lang$]{babel} | |
\fi | |
$endif$ | |
$if(natbib)$ | |
\usepackage{natbib} | |
\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$} | |
$endif$ | |
$if(biblatex)$ | |
\usepackage{biblatex} | |
$for(bibliography)$ | |
\addbibresource{$bibliography$} | |
$endfor$ | |
$endif$ | |
$if(listings)$ | |
\usepackage{listings} | |
$endif$ | |
$if(lhs)$ | |
\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} | |
$endif$ | |
$if(highlighting-macros)$ | |
$highlighting-macros$ | |
$endif$ | |
$if(verbatim-in-note)$ | |
\usepackage{fancyvrb} | |
\VerbatimFootnotes | |
$endif$ | |
$if(tables)$ | |
\usepackage{longtable,booktabs} | |
$endif$ | |
$if(graphics)$ | |
\usepackage{graphicx,grffile} | |
\makeatletter | |
\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi} | |
\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} | |
\makeatother | |
% Scale images if necessary, so that they will not overflow the page | |
% margins by default, and it is still possible to overwrite the defaults | |
% using explicit options in \includegraphics[width, height, ...]{} | |
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} | |
$endif$ | |
$if(links-as-notes)$ | |
% Make links footnotes instead of hotlinks: | |
\renewcommand{\href}[2]{#2\footnote{\url{#1}}} | |
$endif$ | |
$if(strikeout)$ | |
\usepackage[normalem]{ulem} | |
% avoid problems with \sout in headers with hyperref: | |
\pdfstringdefDisableCommands{\renewcommand{\sout}{}} | |
$endif$ | |
\setlength{\parindent}{0pt} | |
\setlength{\parskip}{6pt plus 2pt minus 1pt} | |
\setlength{\emergencystretch}{3em} % prevent overfull lines | |
\providecommand{\tightlist}{% | |
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} | |
$if(numbersections)$ | |
\setcounter{secnumdepth}{5} | |
$else$ | |
\setcounter{secnumdepth}{0} | |
$endif$ | |
$if(verbatim-in-note)$ | |
\VerbatimFootnotes % allows verbatim text in footnotes | |
$endif$ | |
$if(title)$ | |
\title{$title$$if(subtitle)$\\\vspace{0.5em}{\large $subtitle$}$endif$} | |
$endif$ | |
$if(author)$ | |
\author{$for(author)$$author$$sep$ \and $endfor$} | |
$endif$ | |
\date{$date$} | |
$for(header-includes)$ | |
$header-includes$ | |
$endfor$ | |
% Redefines (sub)paragraphs to behave more like sections | |
\ifx\paragraph\undefined\else | |
\let\oldparagraph\paragraph | |
\renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}} | |
\fi | |
\ifx\subparagraph\undefined\else | |
\let\oldsubparagraph\subparagraph | |
\renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} | |
\fi | |
\begin{document} | |
$if(title)$ | |
\maketitle | |
$endif$ | |
$if(abstract)$ | |
\begin{abstract} | |
$abstract$ | |
\end{abstract} | |
$endif$ | |
$for(include-before)$ | |
$include-before$ | |
$endfor$ | |
$if(toc)$ | |
{ | |
\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$black$endif$} | |
\setcounter{tocdepth}{$toc-depth$} | |
\tableofcontents | |
} | |
$endif$ | |
$if(lot)$ | |
\listoftables | |
$endif$ | |
$if(lof)$ | |
\listoffigures | |
$endif$ | |
$body$ | |
$if(natbib)$ | |
$if(bibliography)$ | |
$if(biblio-title)$ | |
$if(book-class)$ | |
\renewcommand\bibname{$biblio-title$} | |
$else$ | |
\renewcommand\refname{$biblio-title$} | |
$endif$ | |
$endif$ | |
\bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$} | |
$endif$ | |
$endif$ | |
$if(biblatex)$ | |
\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$ | |
$endif$ | |
$for(include-after)$ | |
$include-after$ | |
$endfor$ | |
\end{document} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment