----------------------------------------------------------------------------- -- | -- Module : Text.BlogLiterately.Block -- Copyright : (c) 2008-2010 Robert Greayer, 2012 Brent Yorgey -- License : GPL (see LICENSE) -- Maintainer : Brent Yorgey <byorgey@gmail.com> -- -- Utilities for working with code blocks. -- ----------------------------------------------------------------------------- module Text.BlogLiterately.Block ( unTag , onTag ) where import Data.Char (toLower) import Text.Pandoc (Attr, Block (CodeBlock)) import Text.ParserCombinators.Parsec -- | Given a block, if begins with a tag in square brackets, strip off -- the tag and return a pair consisting of the tag and de-tagged -- block. Otherwise, return @Nothing@ and the unchanged block. unTag :: String -> (Maybe String, String) unTag s = either (const (Nothing, s)) id $ parse tag "" s where tag = do tg <- between (char '[') (char ']') $ many $ noneOf "[]" skipMany $ oneOf " \t" _ <- (string "\r\n" <|> string "\n") txt <- many $ anyToken eof return (Just tg, txt) -- | Run the given function on the attributes and source code of code -- blocks with a tag matching the given tag (case insensitive). On -- any other blocks (which don't have a matching tag, or are not code -- blocks), run the other function. onTag :: String -> (Attr -> String -> a) -> (Block -> a) -> Block -> a onTag t f def b@(CodeBlock attr@(_, as, _) s) | lowercase t `elem` map lowercase (maybe id (:) tag $ as) = f attr src | otherwise = def b where (tag, src) = unTag s onTag _ _ def b = def b lowercase :: String -> String lowercase = map toLower