diff --git a/app/Main.hs b/app/Main.hs index f440aea..dc8d9bb 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -9,7 +9,7 @@ import Text.Pandoc.PDF (makePDF) import Text.Pandoc.Walk (walkM) import Text.Pandoc.Extensions (Extension(..), enableExtension, getDefaultExtensions) import System.Environment (getArgs) -import System.FilePath (replaceExtension) +import System.FilePath (replaceExtension, takeDirectory, ()) import System.Process (callProcess) import System.Directory (doesFileExist) import Data.Text (Text) @@ -20,30 +20,24 @@ import Control.Monad (when, void) import qualified Data.ByteString.Lazy as BL -- Transform Mermaid code blocks into image embeds -processMermaid :: Block -> IO Block -processMermaid block@(CodeBlock (id', classes, _) contents) +processMermaidInDir :: FilePath -> Block -> IO Block +processMermaidInDir sourceDir block@(CodeBlock (id', classes, _) contents) | "mermaid" `elem` classes = do - putStrLn $ "🎯 Found Mermaid block with classes: " ++ show classes let baseName = if T.null id' then "diagram-" ++ take 6 (show (abs (hash (T.unpack contents)))) else T.unpack id' - mmdFile = baseName ++ ".mmd" - pngFile = baseName ++ ".png" + mmdFile = sourceDir baseName ++ ".mmd" + pngFile = sourceDir baseName ++ ".png" - putStrLn $ "📝 Writing to " ++ mmdFile ++ " and generating " ++ pngFile writeFile mmdFile (T.unpack contents) void $ callProcess "mmdc" ["-i", mmdFile, "-o", pngFile] putStrLn $ "✅ Generated " ++ pngFile return $ Para [Image nullAttr [] (T.pack pngFile, "Mermaid diagram")] -processMermaid x = do - -- Debug: show what blocks we're processing - case x of - CodeBlock (_, classes, _) _ -> putStrLn $ "📄 Found code block with classes: " ++ show classes - _ -> return () - return x +processMermaidInDir _ x = return x + -- Walk the Pandoc AST and process blocks using walkM -transformDoc :: Pandoc -> IO Pandoc -transformDoc = walkM processMermaid +transformDoc :: FilePath -> Pandoc -> IO Pandoc +transformDoc sourceDir = walkM (processMermaidInDir sourceDir) main :: IO () main = do @@ -77,15 +71,65 @@ compileToPDF :: FilePath -> IO () compileToPDF path = do content <- TIO.readFile path let readerOptions = def { readerExtensions = getDefaultExtensions "markdown" } + sourceDir = takeDirectory path pandoc <- runIOorExplode $ readMarkdown readerOptions content - transformed <- transformDoc pandoc + transformed <- transformDoc sourceDir pandoc let outputPath = replaceExtension path "pdf" writerOptions = def - -- First generate LaTeX with proper document structure + -- Generate LaTeX and add proper header with tightlist definition latexOutput <- runIOorExplode $ writeLaTeX writerOptions transformed - let latexWithHeader = "\\documentclass{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage{graphicx}\n\\usepackage{geometry}\n\\geometry{margin=1in}\n\\begin{document}\n" <> latexOutput <> "\n\\end{document}" - result <- runIOorExplode $ makePDF "pdflatex" [] (\_ _ -> return latexWithHeader) def transformed + let latexWithProperHeader = T.unlines [ + "\\documentclass{article}", + "\\usepackage[utf8]{inputenc}", + "\\usepackage{fontspec}", + "\\usepackage{graphicx}", + "\\usepackage{geometry}", + "\\geometry{margin=1in}", + "\\usepackage{hyperref}", + "\\usepackage{enumitem}", + "\\usepackage{amsmath}", + "\\usepackage{amssymb}", + "\\usepackage{fancyvrb}", + "\\usepackage{color}", + "\\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\\\\{\\}}", + "\\newenvironment{Shaded}{}{}", + "\\newcommand{\\AlertTok}[1]{\\textcolor[rgb]{1.00,0.00,0.00}{\\textbf{#1}}}", + "\\newcommand{\\AnnotationTok}[1]{\\textcolor[rgb]{0.38,0.63,0.69}{\\textbf{\\textit{#1}}}}", + "\\newcommand{\\AttributeTok}[1]{\\textcolor[rgb]{0.49,0.56,0.16}{#1}}", + "\\newcommand{\\BaseNTok}[1]{\\textcolor[rgb]{0.25,0.63,0.44}{#1}}", + "\\newcommand{\\BuiltInTok}[1]{#1}", + "\\newcommand{\\CharTok}[1]{\\textcolor[rgb]{0.25,0.44,0.63}{#1}}", + "\\newcommand{\\CommentTok}[1]{\\textcolor[rgb]{0.38,0.63,0.69}{\\textit{#1}}}", + "\\newcommand{\\CommentVarTok}[1]{\\textcolor[rgb]{0.38,0.63,0.69}{\\textbf{\\textit{#1}}}}", + "\\newcommand{\\ConstantTok}[1]{\\textcolor[rgb]{0.53,0.00,0.00}{#1}}", + "\\newcommand{\\ControlFlowTok}[1]{\\textcolor[rgb]{0.00,0.44,0.13}{\\textbf{#1}}}", + "\\newcommand{\\DataTypeTok}[1]{\\textcolor[rgb]{0.56,0.13,0.00}{#1}}", + "\\newcommand{\\DecValTok}[1]{\\textcolor[rgb]{0.25,0.63,0.44}{#1}}", + "\\newcommand{\\DocumentationTok}[1]{\\textcolor[rgb]{0.73,0.13,0.13}{\\textit{#1}}}", + "\\newcommand{\\ErrorTok}[1]{\\textcolor[rgb]{1.00,0.00,0.00}{\\textbf{#1}}}", + "\\newcommand{\\ExtensionTok}[1]{#1}", + "\\newcommand{\\FloatTok}[1]{\\textcolor[rgb]{0.25,0.63,0.44}{#1}}", + "\\newcommand{\\FunctionTok}[1]{\\textcolor[rgb]{0.02,0.16,0.49}{#1}}", + "\\newcommand{\\ImportTok}[1]{#1}", + "\\newcommand{\\InformationTok}[1]{\\textcolor[rgb]{0.38,0.63,0.69}{\\textbf{\\textit{#1}}}}", + "\\newcommand{\\KeywordTok}[1]{\\textcolor[rgb]{0.00,0.44,0.13}{\\textbf{#1}}}", + "\\newcommand{\\NormalTok}[1]{#1}", + "\\newcommand{\\OperatorTok}[1]{\\textcolor[rgb]{0.40,0.40,0.40}{#1}}", + "\\newcommand{\\OtherTok}[1]{\\textcolor[rgb]{0.00,0.44,0.13}{#1}}", + "\\newcommand{\\PreprocessorTok}[1]{\\textcolor[rgb]{0.74,0.48,0.00}{#1}}", + "\\newcommand{\\RegionMarkerTok}[1]{#1}", + "\\newcommand{\\SpecialCharTok}[1]{\\textcolor[rgb]{0.25,0.44,0.63}{#1}}", + "\\newcommand{\\SpecialStringTok}[1]{\\textcolor[rgb]{0.73,0.40,0.53}{#1}}", + "\\newcommand{\\StringTok}[1]{\\textcolor[rgb]{0.25,0.44,0.63}{#1}}", + "\\newcommand{\\VariableTok}[1]{\\textcolor[rgb]{0.10,0.09,0.49}{#1}}", + "\\newcommand{\\VerbatimStringTok}[1]{\\textcolor[rgb]{0.25,0.44,0.63}{#1}}", + "\\newcommand{\\WarningTok}[1]{\\textcolor[rgb]{0.38,0.63,0.69}{\\textbf{\\textit{#1}}}}", + "\\providecommand{\\tightlist}{%", + " \\setlength{\\itemsep}{0pt}\\setlength{\\parskip}{0pt}}", + "\\begin{document}" + ] <> latexOutput <> "\n\\end{document}" + result <- runIOorExplode $ makePDF "xelatex" [] (\_ _ -> return latexWithProperHeader) def transformed case result of Left err -> error $ "PDF error: " ++ show err Right bs -> BL.writeFile outputPath bs >> putStrLn ("✅ PDF written to " ++ outputPath) @@ -93,12 +137,10 @@ compileToPDF path = do compileToHTML :: FilePath -> IO () compileToHTML path = do content <- TIO.readFile path - putStrLn $ "📖 Reading: " ++ path - putStrLn $ "📝 Content: " ++ T.unpack content let readerOptions = def { readerExtensions = getDefaultExtensions "markdown" } + sourceDir = takeDirectory path pandoc <- runIOorExplode $ readMarkdown readerOptions content - putStrLn $ "🔍 Parsed AST: " ++ show pandoc - transformed <- transformDoc pandoc + transformed <- transformDoc sourceDir pandoc let outputPath = replaceExtension path "html" html <- runIOorExplode $ writeHtml5String def transformed