Skip to content

Add Pandoc Meta data to Context #643

@flupe

Description

@flupe

One interesting feature of ReST is that you can define document variables and meta data directly inside the document, without having to rely on some additional YAML header.

For example, the title of the document and its eventual subtitle can be inferred from the first headers of the file (see Markup Specification (Document Structure)),
and if the first non-comment element is a definition list, its fields update the bibliographic information of the document (see Markup Specification (Bibliographic Fields)).

Although the ReST Parser of Pandoc is far from perfect (it does not support custom directives or roles, and the Pandoc AST is quite restrictive), it does implement the aforementioned features, in standalone mode, and populates the Meta information of the Pandoc document.

Document Title
==============

Subtitle
--------

:author: flupe

However, it seems as though the Pandoc compilers provided by Hakyll completely ignore the meta information of the parsed Pandoc documents.

I don't really know if other markup languages supported by Pandoc also populate the meta information, but I do think it would be useful to provide an easier way to inject this meta information into Hakyll contexts.


For a custom site I've just set up, it is somehow working a little. Here is the relevant part (source):

 match "posts/*" $ do
    route $ setExtension "html"

    let ropts = defaultHakyllReaderOptions { readerStandalone = True }
        wopts = defaultHakyllWriterOptions

    compile $ do
        document <- getResourceBody >>= readPandocWith ropts

        let
            Pandoc meta _ = itemBody document

            inlinesToString :: [Inline] -> String
            inlinesToString inlines =
                concatMap inlineToString inlines
                where
                    inlineToString (Str a) = a
                    inlineToString (Space) = " "

            extractMeta :: String -> MetaValue -> Context a
            extractMeta name metavalue =
                case metavalue of
                    MetaInlines inlines -> mkField $ inlinesToString inlines
                    _ -> mempty
                where
                    mkField = field name . const . return

            ctx :: Context String
            ctx = foldMapWithKey extractMeta (unMeta meta)
                <> postCtx

        writePandocWith wopts document
            &   loadAndApplyTemplate "templates/post.html" ctx
            >>= loadAndApplyTemplate "templates/default.html" ctx
            >>= relativizeUrls

Essentially, we:

  1. Parse the post and get an Item Pandoc
  2. Create a new context ctx populated with the metadata from the document.
  3. Render the post with templates using the new context we created.

However, this mechanism in ReST implies that you actually need to parse the document to get the context, and I have no idea how to make this work well with other rules such as creating and index.html or archives.html page (without having to parse again for each rule).


In conclusion, here's what I am suggesting:

  • adding a proper way to transform Pandoc Meta into an Hakyll Context.
  • a way to associate this information and posts inside snapshots?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions