Convert .docx file to PDF using Pandoc Haskell libraries Macro (v10.2)

Recently, someone told me that it was possible to convert PDF using Pandoc Haskell libraries. Using the following macro, and plug-in, we can accomplish it with KM.

Note: pandoc, pandoc-types, and exceptions packages should be installed.

Convert .docx file to PDF using Pandoc Haskell libraries.kmmacros (9.0 KB)

Expand disclosure triangle to see "haskell" source
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad
import Control.Monad.Catch
import Control.Monad.IO.Class
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import Data.List
import qualified Data.Text as T
import Data.Text.Encoding
import qualified Data.Text.IO as TIO
import Text.Pandoc
import Text.Pandoc.PDF
import Text.Pandoc.Shared
import Data.Aeson
import Data.Map.Strict (Map, fromList, (!))

interact'' :: (Map String T.Text -> IO ()) -> IO ()
interact'' f =
  getContents
    >>= BL.readFile
    >>= pure . (eitherDecode :: BL.ByteString -> Either String (Map String T.Text))
    >>= either putStrLn f

export :: (PandocMonad m, MonadIO m, MonadMask m) => String -> Template T.Text -> Pandoc -> m (Either BL.ByteString BL.ByteString)
export pdfengine tmpl = makePDF pdfengine [] writeLaTeX def {writerTemplate = Just tmpl}


docxToPDF :: FilePath -> FilePath -> BL.ByteString -> IO ()
docxToPDF pdfengine fpOut =
  ( either BL.putStr (BL.writeFile fpOut)
      <=< handleError
      <=< runIO
  )
    . ( readDocx def
          >=> \doc ->
            compileDefaultTemplate "latex"
              >>= flip (export pdfengine) doc
      )

main :: IO ()
main =
  interact'' $
    ( \kv ->
        let pdfengine = T.unpack $ kv ! "pdfengine"
            fpIn = T.unpack $ kv ! "fpIn"
            fpOut = T.unpack $ kv ! "fpOut"
         in BL.readFile fpIn
               >>= docxToPDF pdfengine fpOut
    )

Execute a Haskell Script with Arguments Plug-In: