jaspervdj / hakyll

A static website compiler library in Haskell
jaspervdj.be/hakyll
Other
2.7k stars 411 forks source link

Impossible to tell renderPandoc the filetype of item you pass to it. #242

Open nagisa opened 10 years ago

nagisa commented 10 years ago

Consider such minimal example:

create ["index.html"] $
   compile $ makeItem ""
       >>= loadAndApplyTemplate "templates/index.md" defaultContext
       >>= return . renderPandoc
match "templates/*" $ compile templateCompiler

itemFileType will tell renderPandoc pandoc is getting a HTML file (identifier of Item passed around is index.html, after all), but after any intermediate step between makeItem and renderPandoc the contents in Item might have changed its type and not resemble the initial type at all.


Similarly this should fail to render markdown body too (even smaller test case):

create ["index.html"] $ compile $ renderPandoc <$> makeItem "# This is h1 heading"

This shows renderPandoc is trying to be too smart in certain corner cases. And I should note, people encounter this issue some of the time when trying to use pandoc in a non-standard way.

nagisa commented 10 years ago
create ["i.mkd"] $
    compile $ makeItem "This is $body$"
        >>= loadAndApplyTemplate "templates/index.mkd" defaultContext

create ["i.html"] $ do
    route $ idRoute
    compile $ renderPandoc <$> load "i.mkd"
        >>= makeItem . (itemBody :: Item String -> String)

Appears to be one of the sensible workarounds.

dunnl commented 8 years ago

I ran into this issue when creating a table of contents Context, which failed when compiling Markdown to HTML before applying a template. (After a lot of debugging, it turns out the compilation was preserving the ToC generated by Pandoc when the correct reader was applied).

In this case, a workaround is to read the ToC from a Snapshot of the original file, something like this:

tableOfContentsField :: String         -- ^ Key to use
                     -> Snapshot       -- ^ Snapshot to load
                     -> Context String -- ^ Returns ToC (HTML)
tableOfContentsField key snapshot = field key $ \item -> do
    item <- loadSnapshot (itemIdentifier item) snapshot
    (itemBody <$>) . getTableOfContents $ item
  where
    getTableOfContents :: Item String -> Compiler (Item String)
    getTableOfContents = renderPandocWith def tocOptions 
      where tocOptions = defaultHakyllWriterOptions {
              writerTableOfContents=True
            , writerStandalone=True
            , writerTemplate="$toc$"
      }