From 4aab281f4b3e562e370a36921cb478f636a074da Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Tue, 29 Jul 2025 19:06:14 +0200 Subject: [PATCH] Fix broken diagram links by implementing format-aware image paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: HTML output contained broken image links because all formats used the same full path (e.g., living-documentation/diagram-536389.png). This worked for PDFs but failed for HTML since both files are in the same directory and need relative paths. Solution: - Add output format detection with isHTMLOutput function - Update processMermaidBlock to take OutputPath parameter - Generate context-appropriate paths: * HTML: relative path (diagram-536389.png) * PDF: full path (living-documentation/diagram-536389.png) - Update transformDocument and compilation functions to pass output path Both HTML and PDF generation now work correctly with proper image embedding. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- app/Main.hs | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 486190a..0e08f8d 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 (getDefaultExtensions) import System.Environment (getArgs) -import System.FilePath (replaceExtension, takeDirectory, ()) +import System.FilePath (replaceExtension, takeDirectory, takeFileName, takeExtension, ()) import System.Process (callProcess) import System.Directory (removeFile) import Data.Text (Text) @@ -52,13 +52,17 @@ generateDiagramId explicitId contents | otherwise = DiagramId explicitId -- | Transform Mermaid code blocks into image embeds with resource cleanup -processMermaidBlock :: SourceDir -> Block -> IO Block -processMermaidBlock (SourceDir sourceDir) (CodeBlock (id', classes, _) contents) +processMermaidBlock :: SourceDir -> OutputPath -> Block -> IO Block +processMermaidBlock (SourceDir sourceDir) (OutputPath outputPath) (CodeBlock (id', classes, _) contents) | "mermaid" `elem` classes = do let DiagramId diagId = generateDiagramId id' contents diagIdStr = T.unpack diagId mmdFile = sourceDir diagIdStr <> ".mmd" pngFile = sourceDir diagIdStr <> ".png" + -- Determine the correct image path based on output format + imagePath = if isHTMLOutput outputPath + then takeFileName pngFile -- Just filename for HTML + else pngFile -- Full path for PDF/LaTeX -- Use bracket to ensure cleanup of temporary mermaid file bracket @@ -67,12 +71,16 @@ processMermaidBlock (SourceDir sourceDir) (CodeBlock (id', classes, _) contents) (\_ -> do void $ callProcess mermaidCommand ["-i", mmdFile, "-o", pngFile] putStrLn $ successEmoji <> " Generated " <> pngFile - return $ Para [Image nullAttr [] (T.pack pngFile, "Mermaid diagram")]) -processMermaidBlock _ block = return block + return $ Para [Image nullAttr [] (T.pack imagePath, "Mermaid diagram")]) +processMermaidBlock _ _ block = return block + +-- | Check if output is HTML format based on file extension +isHTMLOutput :: FilePath -> Bool +isHTMLOutput path = takeExtension path == ".html" -- | Walk the Pandoc AST and process blocks using walkM -transformDocument :: SourceDir -> Pandoc -> IO Pandoc -transformDocument sourceDir = walkM (processMermaidBlock sourceDir) +transformDocument :: SourceDir -> OutputPath -> Pandoc -> IO Pandoc +transformDocument sourceDir outputPath = walkM (processMermaidBlock sourceDir outputPath) -- | LaTeX template with comprehensive package support latexTemplate :: Text -> Text @@ -154,12 +162,12 @@ compileToPDF path = do -- | Safe PDF compilation with proper error handling compileToPDFSafe :: SourceDir -> OutputPath -> OutputPath -> IO (Either DocsterError ()) -compileToPDFSafe sourceDir (OutputPath inputPath) (OutputPath outputPath) = do +compileToPDFSafe sourceDir (OutputPath inputPath) outputPath@(OutputPath outputPathStr) = do content <- TIO.readFile inputPath let readerOptions = def { readerExtensions = getDefaultExtensions "markdown" } pandoc <- runIOorExplode $ readMarkdown readerOptions content - transformed <- transformDocument sourceDir pandoc + transformed <- transformDocument sourceDir outputPath pandoc -- Generate LaTeX with proper template latexOutput <- runIOorExplode $ writeLaTeX def transformed @@ -169,8 +177,8 @@ compileToPDFSafe sourceDir (OutputPath inputPath) (OutputPath outputPath) = do case result of Left err -> return $ Left $ PDFGenerationError $ T.pack $ show err Right bs -> do - BL.writeFile outputPath bs - putStrLn $ successEmoji <> " PDF written to " <> outputPath + BL.writeFile outputPathStr bs + putStrLn $ successEmoji <> " PDF written to " <> outputPathStr return $ Right () -- | Compile markdown to HTML @@ -186,20 +194,20 @@ compileToHTML path = do -- | Safe HTML compilation with proper error handling compileToHTMLSafe :: SourceDir -> OutputPath -> OutputPath -> IO (Either DocsterError ()) -compileToHTMLSafe sourceDir (OutputPath inputPath) (OutputPath outputPath) = do +compileToHTMLSafe sourceDir (OutputPath inputPath) outputPath@(OutputPath outputPathStr) = do content <- TIO.readFile inputPath let readerOptions = def { readerExtensions = getDefaultExtensions "markdown" } pandoc <- runIOorExplode $ readMarkdown readerOptions content - transformed <- transformDocument sourceDir pandoc + transformed <- transformDocument sourceDir outputPath pandoc html <- runIOorExplode $ writeHtml5String def transformed - TIO.writeFile outputPath html - putStrLn $ successEmoji <> " HTML written to " <> outputPath + TIO.writeFile outputPathStr html + putStrLn $ successEmoji <> " HTML written to " <> outputPathStr -- Open the generated HTML file in browser - putStrLn $ "🌐 Opening " <> outputPath <> " in browser for error checking..." - void $ callProcess "open" [outputPath] + putStrLn $ "🌐 Opening " <> outputPathStr <> " in browser for error checking..." + void $ callProcess "open" [outputPathStr] return $ Right ()