packages feed

BlogLiterately 0.8.6.3 → 0.8.7

raw patch · 8 files changed

+132/−90 lines, 8 filesdep ~basedep ~lensdep ~pandocPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, lens, pandoc, pandoc-citeproc, pandoc-types

API changes (from Hackage documentation)

- Text.BlogLiterately.Block: onTag :: String -> (Attr -> String -> a) -> (Block -> a) -> Block -> a
+ Text.BlogLiterately.Block: onTag :: Text -> (Attr -> Text -> a) -> (Block -> a) -> Block -> a
- Text.BlogLiterately.Block: unTag :: String -> (Maybe String, String)
+ Text.BlogLiterately.Block: unTag :: Text -> (Maybe Text, Text)
- Text.BlogLiterately.Highlight: colourIt :: Bool -> String -> String
+ Text.BlogLiterately.Highlight: colourIt :: Bool -> Text -> String
- Text.BlogLiterately.Highlight: litify :: String -> String
+ Text.BlogLiterately.Highlight: litify :: Text -> Text

Files

BlogLiterately.cabal view
@@ -1,5 +1,5 @@ Name:           BlogLiterately-Version:        0.8.6.3+Version:        0.8.7 Synopsis:       A tool for posting Haskelly articles to blogs Description:    Write blog posts in Markdown format, then use BlogLiterately                 to do syntax highlighting, format ghci sessions, and upload@@ -26,7 +26,7 @@ Maintainer:     Brent Yorgey <byorgey@gmail.com> Stability:      experimental Build-Type:     Simple-Tested-With:    GHC ==8.0.2, GHC ==8.2.2, GHC ==8.4.4, GHC ==8.6.3+Tested-With:    GHC ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.3 || ==8.10.1 Extra-Source-Files: CHANGES.md                     README.markdown                     doc/BlogLiteratelyDoc.lhs@@ -39,7 +39,7 @@   location: git://github.com/byorgey/BlogLiterately.git  Library-  Build-Depends:   base >= 4.0 && < 4.13,+  Build-Depends:   base >= 4.0 && < 4.15,                    process,                    filepath,                    directory,@@ -58,12 +58,12 @@                    blaze-html >= 0.5 && < 0.10,                    cmdargs >= 0.9.5 && < 0.11,                    haxr >= 3000.11 && < 3000.12,-                   pandoc >= 2.0 && < 2.8,-                   pandoc-types >= 1.16 && < 1.20,-                   pandoc-citeproc >= 0.1.2 && < 0.17,+                   pandoc >= 2.0 && < 2.11,+                   pandoc-types >= 1.20 && < 1.22,+                   pandoc-citeproc >= 0.1.2 && < 0.18,                    highlighting-kate >= 0.5 && < 0.7,                    data-default >= 0.5 && < 0.8,-                   lens >= 3.8 && < 4.18,+                   lens >= 3.8 && < 4.20,                    tagsoup >= 0.13.4 && < 0.15,                    HTTP >= 4000.3 && < 4000.4   Exposed-modules: Text.BlogLiterately
CHANGES.md view
@@ -1,3 +1,9 @@+0.8.7 (21 July 2020)+--------------------++  - Add support for GHC 8.8, 8.10+  - Switch to `pandoc-2.9` and `text`+ 0.8.6.3 (4 March 2019) ---------------------- 
src/Text/BlogLiterately/Block.hs view
@@ -16,21 +16,26 @@     , onTag     ) where -import           Data.Char                     (toLower)-import           Text.Pandoc                   (Attr, Block (CodeBlock))-import           Text.ParserCombinators.Parsec+import           Data.Text        (Text)+import qualified Data.Text        as T+import           Text.Pandoc      (Attr, Block (CodeBlock))+import           Text.Parsec+import           Text.Parsec.Text --- | Given a block, if begins with a tag in square brackets, strip off+-- switch to megaparsec, use e.g. https://hackage.haskell.org/package/megaparsec-8.0.0/docs/Text-Megaparsec.html#v:takeWhileP ?++-- | Given a block, if it 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 :: Text -> (Maybe Text, Text) unTag s = either (const (Nothing, s)) id $ parse tag "" s   where+    tag :: Parser (Maybe Text, Text)     tag = do-      tg <- between (char '[') (char ']') $ many $ noneOf "[]"+      tg <- T.pack <$> (between (char '[') (char ']') $ many $ noneOf "[]")       skipMany $ oneOf " \t"       _   <- (string "\r\n" <|> string "\n")-      txt <- many $ anyToken+      txt <- T.pack <$> many anyToken       eof       return (Just tg, txt) @@ -38,13 +43,10 @@ --   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 :: Text -> (Attr -> Text -> a) -> (Block -> a) -> Block -> a onTag t f def b@(CodeBlock attr@(_, as, _) s)-  | lowercase t `elem` map lowercase (maybe id (:) tag $ as)+  | T.toLower t `elem` map T.toLower (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
src/Text/BlogLiterately/Ghci.hs view
@@ -41,6 +41,8 @@ import           Data.Char                  (isSpace) import           Data.Functor               ((<$>)) import           Data.List                  (intercalate, isPrefixOf)+import           Data.Text                  (Text)+import qualified Data.Text                  as T import           System.FilePath            (takeFileName) import           System.IO import qualified System.IO.Strict           as Strict@@ -194,14 +196,14 @@ formatInlineGhci f = withGhciProcess f . bottomUpM formatInlineGhci'   where     formatInlineGhci' :: Block -> ReaderT ProcessInfo IO Block-    formatInlineGhci' = onTag "ghci" formatGhciBlock return+    formatInlineGhci' = onTag (T.pack "ghci") formatGhciBlock return      formatGhciBlock attr src = do       let inputs = parseGhciInputs src       results <- zipWith GhciLine inputs <$> mapM ghciEval inputs-      return $ CodeBlock attr (intercalate "\n" $ map formatGhciResult results)+      return $ CodeBlock attr (T.intercalate (T.pack "\n") $ map (T.pack . formatGhciResult) results) -parseGhciInputs :: String -> [GhciInput]+parseGhciInputs :: Text -> [GhciInput] parseGhciInputs = map mkGhciInput                 . split                   ( dropInitBlank@@ -210,6 +212,7 @@                   $ whenElt (not . (" " `isPrefixOf`))                   )                 . lines+                . T.unpack  mkGhciInput :: [String] -> GhciInput mkGhciInput []       = GhciInput "" Nothing
src/Text/BlogLiterately/Highlight.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings  #-} {-# LANGUAGE TemplateHaskell    #-}  -----------------------------------------------------------------------------@@ -26,6 +27,12 @@     , colourisePandoc     ) where +-- xmlParse (from HaXmL) uses String+-- hscolour uses String++import           Data.Text                           (Text)+import qualified Data.Text                           as T+ import           Control.Lens                        (makePrisms) import           Control.Monad                       (liftM) import           Data.Char                           (toLower)@@ -39,7 +46,7 @@ import           Text.Highlighting.Kate import           Text.Pandoc.Definition import           Text.Pandoc.Shared                  (safeRead)-import           Text.XML.HaXml                      hiding (find, attr, html)+import           Text.XML.HaXml                      hiding (attr, find, html) import           Text.XML.HaXml.Posn                 (noPos)  import           Text.BlogLiterately.Block           (unTag)@@ -67,9 +74,9 @@ The `Attr` component has metadata about what's in the code block:      [haskell]-    type Attr = ( String,             -- code block identifier-                , [String]            -- list of code classes-                , [(String, String)]  -- name/value pairs+    type Attr = ( Text,           -- code block identifier+                , [Text]          -- list of code classes+                , [(Text, Text)]  -- name/value pairs                 )  Thanks to some feedback from the Pandoc author, John MacFarlane, I@@ -147,9 +154,9 @@  -- | Use hscolour to syntax highlight some Haskell code.  The first -- argument indicates whether the code is literate Haskell.-colourIt :: Bool -> String -> String+colourIt :: Bool -> Text -> String colourIt literate srcTxt =-    wrapCode $ hscolour CSS defaultColourPrefs False True "" literate srcTxt'+    wrapCode $ hscolour CSS defaultColourPrefs False True "" literate (T.unpack srcTxt')     where srcTxt' | literate  = litify srcTxt                   | otherwise = srcTxt           -- wrap the result in a <pre><code> tag, similar to@@ -164,8 +171,8 @@                     `when` tag "pre"  -- | Prepend literate Haskell markers to some source code.-litify :: String -> String-litify = unlines . map ("> " ++) . lines+litify :: Text -> Text+litify = T.unlines . map (T.append "> ") . T.lines  {- Hscolour uses HTML `span` elements and CSS classes like 'hs-keyword'@@ -259,8 +266,8 @@   | ctag == Just "haskell" || haskell   = case hsHighlight of         HsColourInline style ->-            rawHtml $ bakeStyles style $ colourIt lit src-        HsColourCSS   -> rawHtml $ colourIt lit src+            rawHtmlT . bakeStyles style $ colourIt lit src+        HsColourCSS   -> rawHtmlT $ colourIt lit src         HsNoHighlight -> rawHtml $ simpleHTML hsrc         HsKate        -> case ctag of             Nothing -> myHighlightK attr hsrc@@ -283,11 +290,12 @@         | otherwise    = src     lit          = "sourceCode" `elem` classes     haskell      = "haskell" `elem` classes-    simpleHTML h = "<pre><code>" ++ h ++ "</code></pre>"+    simpleHTML h = T.append "<pre><code>" (T.append h "</code></pre>")     myHighlightK attrs h = case highlight formatHtmlBlock attrs h of-        Nothing   -> rawHtml $ simpleHTML s-        Just html -> rawHtml $ replaceBreaks $ renderHtml html-    rawHtml = RawBlock (Format "html")+        Nothing   -> rawHtml  $ simpleHTML s+        Just html -> rawHtmlT $ replaceBreaks $ renderHtml html+    rawHtmlT = rawHtml . T.pack+    rawHtml  = RawBlock (Format "html")  colouriseCodeBlock _ _ b = b @@ -311,21 +319,21 @@ lcLanguages = map (map toLower) languages  highlight :: (FormatOptions -> [SourceLine] -> a) -- ^ Formatter-          -> Attr -- ^ Attributes of the CodeBlock-          -> String -- ^ Raw contents of the CodeBlock+          -> Attr    -- ^ Attributes of the CodeBlock+          -> Text    -- ^ Raw contents of the CodeBlock           -> Maybe a -- ^ Maybe the formatted result highlight formatter (_, classes, keyvals) rawCode =   let firstNum = case safeRead (fromMaybe "1" $ lookup "startFrom" keyvals) of-                      Just n -> n+                      Just n  -> n                       Nothing -> 1       fmtOpts = defaultFormatOpts{                   startNumber = firstNum,                   numberLines = any (`elem`                         ["number","numberLines", "number-lines"]) classes }-      lcclasses = map (map toLower) classes+      lcclasses = map (T.unpack . T.toLower) classes   in case find (`elem` lcLanguages) lcclasses of             Nothing -> Nothing             Just language -> Just                               $ formatter fmtOpts{ codeClasses = [language],-                                                   containerClasses = classes }-                              $ highlightAs language rawCode+                                                   containerClasses = map T.unpack classes }+                              $ highlightAs language (T.unpack rawCode)
src/Text/BlogLiterately/Image.hs view
@@ -19,6 +19,8 @@     , mkMediaObject     ) where +import qualified Data.Text                   as T+ import           Control.Monad.IO.Class      (liftIO) import           Control.Monad.Trans.Class   (lift) import           Control.Monad.Trans.State   (StateT, get, modify, runStateT)@@ -55,21 +57,24 @@     _           -> return p   where     uploadOneImage :: String -> Inline -> StateT (M.Map FilePath URL) IO Inline-    uploadOneImage xmlrpc i@(Image attr altText (imgUrl, imgTitle))+    uploadOneImage xmlrpc i@(Image attr altText (imgUrlT, imgTitle))       | isLocal imgUrl = do           uploaded <- get           case M.lookup imgUrl uploaded of-            Just url -> return $ Image attr altText (url, imgTitle)+            Just url -> return $ Image attr altText (T.pack url, imgTitle)             Nothing  -> do               res <- lift $ uploadIt xmlrpc imgUrl bl               case res of                 Just (ValueStruct (lookup "url" -> Just (ValueString newUrl))) -> do                   modify (M.insert imgUrl newUrl)-                  return $ Image attr altText (newUrl, imgTitle)+                  return $ Image attr altText (T.pack newUrl, imgTitle)                 _ -> do                   liftIO . putStrLn $ "Warning: upload of " ++ imgUrl ++ " failed."                   return i       | otherwise      = return i+      where+        imgUrl = T.unpack imgUrlT+     uploadOneImage _ i = return i      isLocal imgUrl = none (`isPrefixOf` imgUrl) ["http", "/"]
src/Text/BlogLiterately/LaTeX.hs view
@@ -10,26 +10,32 @@ -- ----------------------------------------------------------------------------- +{-# LANGUAGE OverloadedStrings #-}+ module Text.BlogLiterately.LaTeX     (       rawTeXify     , wpTeXify     ) where -import           Data.List   (isPrefixOf)+import           Data.Text   (Text)+import qualified Data.Text   as T import           Text.Pandoc +bracket :: Text -> Text -> Text -> Text+bracket l r t = T.append l (T.append t r)+ -- | Pass LaTeX through unchanged. rawTeXify :: Pandoc -> Pandoc rawTeXify = bottomUp formatDisplayTex . bottomUp formatInlineTex   where formatInlineTex :: [Inline] -> [Inline]         formatInlineTex (Math InlineMath tex : is)-          = (RawInline (Format "html") ("$" ++ tex ++ "$")) : is+          = (RawInline (Format "html") (bracket "$" "$" tex)) : is         formatInlineTex is = is          formatDisplayTex :: [Block] -> [Block]         formatDisplayTex (Para [Math DisplayMath tex] : bs)-          = RawBlock (Format "html") ("\n\\[" ++ tex ++ "\\]\n")+          = RawBlock (Format "html") (bracket "\n\\[" "\\]\n" tex)           : bs         formatDisplayTex bs = bs @@ -40,17 +46,17 @@ wpTeXify = bottomUp formatDisplayTex . bottomUp formatInlineTex   where formatInlineTex :: [Inline] -> [Inline]         formatInlineTex (Math InlineMath tex : is)-          = (Str $ "$latex " ++ unPrefix "latex" tex ++ "$") : is+          = (Str $ bracket "$latex " "$" (unPrefix "latex" tex)) : is         formatInlineTex is = is          formatDisplayTex :: [Block] -> [Block]         formatDisplayTex (Para [Math DisplayMath tex] : bs)           = RawBlock (Format "html") "<p><div style=\"text-align: center\">"-          : Plain [Str $ "$latex " ++ "\\displaystyle " ++ unPrefix "latex" tex ++ "$"]+          : Plain [Str $ bracket "$latex \\displaystyle " "$" (unPrefix "latex" tex)]           : RawBlock (Format "html") "</div></p>"           : bs         formatDisplayTex bs = bs          unPrefix pre s-          | pre `isPrefixOf` s = drop (length pre) s-          | otherwise          = s+          | pre `T.isPrefixOf` s = T.drop (T.length pre) s+          | otherwise            = s
src/Text/BlogLiterately/Transform.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-} {-# LANGUAGE TupleSections     #-} {-# LANGUAGE TypeOperators     #-}@@ -276,7 +277,7 @@ -- --   is a simple 'SpecialLink' which causes links of the form --   @twitter::user@ to be replaced by @https://twitter.com/user@.-type SpecialLink = (String, String -> BlogLiterately -> IO String)+type SpecialLink = (Text, Text -> BlogLiterately -> IO Text)  -- | Create a transformation which looks for the given special links --   and replaces them appropriately. You can use this function with@@ -292,7 +293,7 @@     specialLink :: Inline -> IO Inline     specialLink i@(Link attrs alt (url, title))       | Just (typ, target) <- getSpecial url-      = mkLink <$> case lookup (map toLower typ) links of+      = mkLink <$> case lookup (T.toLower typ) links of                      Just mkURL -> mkURL target bl                      Nothing    -> return target       where@@ -301,9 +302,9 @@     specialLink i = return i      getSpecial url-      | "::" `isInfixOf` url =-          let (typ:rest) = splitOn "::" url-          in  Just (typ, intercalate "::" rest)+      | "::" `T.isInfixOf` url =+          let (typ:rest) = T.splitOn "::" url+          in  Just (typ, T.intercalate "::" rest)       | otherwise = Nothing  -- | Turn @lucky::<search>@ into a link to the first Google result for@@ -311,12 +312,16 @@ luckyLink :: SpecialLink luckyLink = ("lucky", getLucky)   where+    getLucky :: Text -> BlogLiterately -> IO Text     getLucky searchTerm _ = do-      results <- openURL $ "http://www.google.com/search?q=" ++ searchTerm+      results <- openURL $ "http://www.google.com/search?q=" ++ (T.unpack searchTerm)       let tags   = parseTags results-          anchor = take 1 . dropWhile (~/= "<a>") . dropWhile (~/= "<h3 class='r'>") $ tags+          anchor = take 1+            . dropWhile (~/= ("<a>" :: String))+            . dropWhile (~/= ("<h3 class='r'>" :: String))+            $ tags           url = case anchor of-            [t@(TagOpen{})] -> takeWhile (/='&') . dropWhile (/='h') . fromAttrib "href" $ t+            [t@(TagOpen{})] -> T.pack . takeWhile (/='&') . dropWhile (/='h') . fromAttrib "href" $ t             _ -> searchTerm       return url @@ -327,7 +332,7 @@ -- | Given @wiki::<title>@, generate a link to the Wikipedia page for --   @<title>@.  Note that the page is not checked for existence. wikiLink :: SpecialLink-wikiLink = ("wiki", \target _ -> return $ "https://en.wikipedia.org/wiki/" ++ target)+wikiLink = ("wiki", \target _ -> return $ T.append "https://en.wikipedia.org/wiki/" target)  -- | @postLink@ handles two types of special links. --@@ -341,12 +346,13 @@ postLink :: SpecialLink postLink = ("post", getPostLink)   where+    getPostLink :: Text -> BlogLiterately -> IO Text     getPostLink target bl =-      fromMaybe target <$>-        case (all isDigit target, bl ^. blog) of+      (fromMaybe target . fmap T.pack) <$>+        case (T.all isDigit target, bl ^. blog) of           (_    , Nothing ) -> return Nothing-          (True , Just url) -> getPostURL url target (user' bl) (password' bl)-          (False, Just url) -> findTitle 20 url target (user' bl) (password' bl)+          (True , Just url) -> getPostURL url (T.unpack target) (user' bl) (password' bl)+          (False, Just url) -> findTitle 20 url (T.unpack target) (user' bl) (password' bl)            -- If all digits, replace with permalink for that postid           -- Otherwise, search titles of 20 most recent posts.@@ -363,10 +369,11 @@ githubLink :: SpecialLink githubLink = ("github", getGithubLink)   where-    getGithubLink target bl =-      case splitOn "/" target of-        (user : repo : ghTarget) -> return $ github </> user </> repo </> mkTarget ghTarget-        _ -> return $ github </> target+    getGithubLink :: Text -> BlogLiterately -> IO Text+    getGithubLink target bl = return . T.pack $+      case splitOn "/" (T.unpack target) of+        (user : repo : ghTarget) -> github </> user </> repo </> mkTarget ghTarget+        _ -> github </> (T.unpack target)     github = "https://github.com/"     mkTarget []                 = ""     mkTarget (('@': hash) : _)  = "commit" </> hash@@ -377,7 +384,8 @@ hackageLink :: SpecialLink hackageLink = ("hackage", getHackageLink)   where-    getHackageLink pkg bl = return $ hackagePrefix ++ pkg+    getHackageLink :: Text -> BlogLiterately -> IO Text+    getHackageLink pkg bl = return $ T.append hackagePrefix pkg     hackagePrefix = "http://hackage.haskell.org/package/"  -- | Potentially extract a title from the metadata block, and set it@@ -389,9 +397,9 @@       (Pandoc (Meta m) _) <- gets snd       case M.lookup "title" m of         Just (MetaString s) ->-          setTitle s+          setTitle (T.unpack s)         Just (MetaInlines is) ->-          setTitle (intercalate " " [s | Str s <- is])+          setTitle (intercalate " " [T.unpack s | Str s <- is])         _ -> return ()      -- title set explicitly with --title takes precedence.@@ -412,7 +420,7 @@ --   options record.  If the blog is not tagged with @[BLOpts]@ these --   will just be empty. extractOptions :: Block -> ([ParseError], BlogLiterately)-extractOptions = onTag "blopts" (const readBLOptions) (const mempty)+extractOptions = onTag "blopts" (const (readBLOptions . T.unpack)) (const mempty)  -- | Delete any blocks tagged with @[BLOpts]@. killOptionBlocks :: Block -> Block@@ -533,14 +541,17 @@ -- | Transform a complete input document string to an HTML output --   string, given a list of transformation passes. xformDoc :: BlogLiterately -> [Transform] -> String -> IO (Either PandocError (BlogLiterately, String))-xformDoc bl xforms = runIO .+xformDoc bl xforms s = do+  Right tpl <- compileTemplate "" blHtmlTemplate+  runIO .     (     fixLineEndings       >>> T.pack       >>> parseFile parseOpts       >=> (liftIO . runTransforms xforms bl)-      >=> (\(bl', p) -> (bl',) <$> writeHtml5String (writeOpts bl') p)+      >=> (\(bl', p) -> (bl',) <$> writeHtml5String (writeOpts bl' tpl) p)       >=> _2 (return . T.unpack)     )+    $ s   where     parseFile :: ReaderOptions -> Text -> PandocIO Pandoc     parseFile opts =@@ -572,44 +583,45 @@             -- Ext_pandoc_title_block             -- Ext_citations       }-    writeOpts bl = def-      { writerReferenceLinks = True+    writeOpts bl tpl = def+      { writerReferenceLinks  = True       , writerTableOfContents = toc' bl-      , writerHTMLMathMethod =+      , writerHTMLMathMethod  =           case math' bl of             ""  -> PlainMath-            opt -> mathOption opt-      , writerTemplate       = Just blHtmlTemplate+            opt -> mathOption (T.pack opt)+      , writerTemplate        = Just tpl       }      mathOption opt-      | opt `isPrefixOf` "mathml"      = MathML-      | opt `isPrefixOf` "mimetex"     =+      | opt `T.isPrefixOf` "mathml"      = MathML+      | opt `T.isPrefixOf` "mimetex"     =           WebTeX (mathUrl "/cgi-bin/mimetex.cgi?" opt)-      | opt `isPrefixOf` "webtex"      = WebTeX (mathUrl webTeXURL opt)-      | opt `isPrefixOf` "mathjax"     = MathJax (mathUrl mathJaxURL opt)+      | opt `T.isPrefixOf` "webtex"      = WebTeX (mathUrl webTeXURL opt)+      | opt `T.isPrefixOf` "mathjax"     = MathJax (mathUrl mathJaxURL opt)       | otherwise                      = PlainMath      webTeXURL  = "http://chart.apis.google.com/chart?cht=tx&chl="-    mathJaxURL = "http://cdn.mathjax.org/mathjax/latest/MathJax.js"-                 ++ "?config=TeX-AMS-MML_HTMLorMML"+    mathJaxURL = T.append "http://cdn.mathjax.org/mathjax/latest/MathJax.js"+                   "?config=TeX-AMS-MML_HTMLorMML" -    urlPart = drop 1 . dropWhile (/='=')+    urlPart :: Text -> Text+    urlPart = T.drop 1 . T.dropWhile (/='=')      mathUrl dflt opt  = case urlPart opt of "" -> dflt; x -> x  -- | Turn @CRLF@ pairs into a single @LF@.  This is necessary since --   'readMarkdown' is picky about line endings. fixLineEndings :: String -> String-fixLineEndings [] = []+fixLineEndings []             = [] fixLineEndings ('\r':'\n':cs) = '\n':fixLineEndings cs-fixLineEndings (c:cs) = c:fixLineEndings cs+fixLineEndings (c:cs)         = c:fixLineEndings cs  -- We use a special template with the "standalone" pandoc writer.  We -- don't actually want truly "standalone" HTML documents because they -- have to sit inside another web page.  But we do want things like -- math typesetting and a table of contents.-blHtmlTemplate = unlines+blHtmlTemplate = T.unlines   [ "$if(highlighting-css)$"   , "  <style type=\"text/css\">"   , "$highlighting-css$"