HiveBrain v1.2.0
Get Started
← Back to all entries
snippetMinor

Pandoc filter to allow embedding arbitary HTML in latex documents

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
latexallowfilterembeddingarbitarypandocdocumentshtml

Problem

I wrote a Pandoc filter that allows me to embed arbitrary HTML snippets in LaTeX documents, which are then printed out as-is when the document is converted to HTML. It is slightly more generic than it needs to be right now, in case I want to embed other types of things in the future.

It can be used like:

\begin{verbatim}
    %%% html
    
\end{verbatim}


In particular, I think the chain of >>= in convertCode could be improved some how, possibly using Applicatives. runReader basically does nothing except rearrange its arguments and call a thing.

```
import Data.Char ( isSpace )
import Data.List ( dropWhileEnd )
import Data.Maybe ( fromMaybe )

import Text.Pandoc.JSON ( Block(CodeBlock, RawBlock), Format(Format), toJSONFilter )

main = toJSONFilter convertCodeBlocks

type Reader = String -> Maybe [Block]

convertCodeBlocks :: Block -> [Block]
convertCodeBlocks b = case b of
(CodeBlock _ code) -> fromMaybe [b] $ convertCode code
_ -> [b]

-- Given a string of code, try to convert it into something nicer
convertCode :: String -> Maybe [Block]
convertCode code =
codeBlockType codeHead >>= codeBlockReader >>= runReader codeTail
where (codeHead, codeTail) = splitWhen (== '\n') $ strip code

-- Get the reader name from the magic header
codeBlockType :: String -> Maybe String
codeBlockType line = if percent == "%%% "
then Just $ strip typeName
else Nothing
where (percent, typeName) = splitAt 4 $ strip line

-- All the known readers and their name from the magic header
codeBlockReader :: String -> Maybe Reader
codeBlockReader "html" = Just rawHtml
codeBlockReader _ = Nothing

-- Make a raw HTML block from some string
rawHtml html = Just [RawBlock (Format "html") html]

-- A mostly useless function, only here because I can't make Applicatives work
runReader :: String -> Reader -> Maybe [Block]
runReader code reader = reader code

-- Strip whitespace from the start and end of a string
strip = dropWhileEnd isSpace .

Solution

I think it's clearer to just merge all those functions into one since you only really care about one case:

convertCode :: String -> Maybe [Block]
convertCode code =
case strip codeHead of
('%':'%':'%':' ':typeName) -> matchType $ strip typeName
_ -> Nothing
where
(codeHead, codeTail) = splitWhen (== '\n') $ strip code

matchType "html" = Just [RawBlock (Format "html") codeTail]
matchType _ = Nothing


Does this do the same thing? I cant test it without too much effort on my part.

Context

StackExchange Code Review Q#149713, answer score: 4

Revisions (0)

No revisions yet.