Fix broken diagram links by implementing format-aware image paths
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 <noreply@anthropic.com>
This commit is contained in:
parent
1a92427b90
commit
4aab281f4b
42
app/Main.hs
42
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 ()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user