69 lines
2.2 KiB
Haskell
69 lines
2.2 KiB
Haskell
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Main where
|
|
|
|
import Text.Pandoc
|
|
import Text.Pandoc.Error
|
|
import Text.Pandoc.Class (runIOorExplode)
|
|
import Text.Pandoc.PDF (makePDF)
|
|
import System.Environment (getArgs)
|
|
import System.FilePath (replaceExtension)
|
|
import System.Process (callProcess)
|
|
import System.IO (writeFile)
|
|
import System.Directory (doesFileExist)
|
|
import Data.Text (Text)
|
|
import qualified Data.Text as T
|
|
import qualified Data.Text.IO as TIO
|
|
import Data.Hashable (hash)
|
|
import Control.Monad (when, void)
|
|
|
|
-- Transform Mermaid code blocks into image embeds
|
|
processMermaid :: Block -> IO Block
|
|
processMermaid (CodeBlock (id', classes, _) contents)
|
|
| "mermaid" `elem` classes = do
|
|
let baseName = if null id' then "diagram-" ++ take 6 (show (abs (hash contents))) else id'
|
|
mmdFile = baseName ++ ".mmd"
|
|
svgFile = baseName ++ ".svg"
|
|
|
|
writeFile mmdFile contents
|
|
exists <- doesFileExist svgFile
|
|
when (not exists) $ void $ callProcess "mmdc" ["-i", mmdFile, "-o", svgFile]
|
|
|
|
return $ Para [Image nullAttr [] (T.pack svgFile, "Mermaid diagram")]
|
|
processMermaid x = return x
|
|
|
|
-- Walk the Pandoc AST and process blocks
|
|
transformDoc :: Pandoc -> IO Pandoc
|
|
transformDoc = walkM processMermaid
|
|
|
|
main :: IO ()
|
|
main = do
|
|
args <- getArgs
|
|
case args of
|
|
["-pdf", path] -> compileToPDF path
|
|
["-html", path] -> compileToHTML path
|
|
_ -> putStrLn "Usage: docster -pdf|-html <file.md>"
|
|
|
|
compileToPDF :: FilePath -> IO ()
|
|
compileToPDF path = do
|
|
content <- TIO.readFile path
|
|
pandoc <- runIOorExplode $ readMarkdown def content
|
|
transformed <- transformDoc pandoc
|
|
|
|
let outputPath = replaceExtension path "pdf"
|
|
result <- runIOorExplode $ makePDF "pdflatex" [] transformed
|
|
case result of
|
|
Left err -> error $ "PDF error: " ++ show err
|
|
Right bs -> writeFile outputPath bs >> putStrLn ("✅ PDF written to " ++ outputPath)
|
|
|
|
compileToHTML :: FilePath -> IO ()
|
|
compileToHTML path = do
|
|
content <- TIO.readFile path
|
|
pandoc <- runIOorExplode $ readMarkdown def content
|
|
transformed <- transformDoc pandoc
|
|
|
|
let outputPath = replaceExtension path "html"
|
|
html <- runIOorExplode $ writeHtml5String def transformed
|
|
TIO.writeFile outputPath html
|
|
putStrLn ("✅ HTML written to " ++ outputPath)
|