    {-# LANGUAGE CPP                   #-}
    {-# LANGUAGE FlexibleContexts      #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE ScopedTypeVariables   #-}
    {-# LANGUAGE ViewPatterns          #-}
    {-# LANGUAGE FlexibleInstances     #-}
    {-# LANGUAGE LambdaCase            #-}
    {-# LANGUAGE OverloadedStrings     #-}
    {- |
       Module      : Text.Pandoc.Shared
       Copyright   : Copyright (C) 2006-2020 John MacFarlane
       License     : GNU GPL, version 2 or above

       Maintainer  : John MacFarlane <jgm@berkeley.edu>
       Stability   : alpha
       Portability : portable

    Utility functions and definitions used by the various Pandoc modules.
    -}
    module Text.Pandoc.Shared (
                         -- * List processing
                         splitBy,
                         splitTextBy,
                         splitByIndices,
                         splitStringByIndices,
                         splitTextByIndices,
                         substitute,
                         ordNub,
                         findM,
                         -- * Text processing
                         ToString (..),
                         ToText (..),
                         tshow,
                         backslashEscapes,
                         escapeStringUsing,
                         elemText,
                         notElemText,
                         stripTrailingNewlines,
                         trim,
                         triml,
                         trimr,
                         trimMath,
                         stripFirstAndLast,
                         camelCaseToHyphenated,
                         camelCaseStrToHyphenated,
                         toRomanNumeral,
                         escapeURI,
                         tabFilter,
                         crFilter,
                         -- * Date/time
                         normalizeDate,
                         -- * Pandoc block and inline list processing
                         orderedListMarkers,
                         extractSpaces,
                         removeFormatting,
                         deNote,
                         deLink,
                         stringify,
                         capitalize,
                         compactify,
                         compactifyDL,
                         linesToPara,
                         makeSections,
                         uniqueIdent,
                         inlineListToIdentifier,
                         isHeaderBlock,
                         headerShift,
                         stripEmptyParagraphs,
                         onlySimpleTableCells,
                         isTightList,
                         taskListItemFromAscii,
                         taskListItemToAscii,
                         addMetaField,
                         makeMeta,
                         eastAsianLineBreakFilter,
                         underlineSpan,
                         htmlSpanLikeElements,
                         splitSentences,
                         filterIpynbOutput,
                         -- * TagSoup HTML handling
                         renderTags',
                         -- * File handling
                         inDirectory,
                         collapseFilePath,
                         uriPathToPath,
                         filteredFilesFromArchive,
                         -- * URI handling
                         schemes,
                         isURI,
                         -- * Error handling
                         mapLeft,
                         -- * for squashing blocks
                         blocksToInlines,
                         blocksToInlines',
                         blocksToInlinesWithSep,
                         defaultBlocksSeparator,
                         -- * Safe read
                         safeRead,
                         safeStrRead,
                         -- * User data directory
                         defaultUserDataDirs,
                         -- * Version
                         pandocVersion
                        ) where

    import Codec.Archive.Zip
    import qualified Control.Exception as E
    import Control.Monad (MonadPlus (..), msum, unless)
    import qualified Control.Monad.State.Strict as S
    import qualified Data.ByteString.Lazy as BL
    import qualified Data.Bifunctor as Bifunctor
    import Data.Char (isAlpha, isLower, isSpace, isUpper, toLower, isAlphaNum,
                      generalCategory, GeneralCategory(NonSpacingMark,
                      SpacingCombiningMark, EnclosingMark, ConnectorPunctuation))
    import Data.List (find, intercalate, intersperse, stripPrefix, sortOn)
    import qualified Data.Map as M
    import Data.Maybe (mapMaybe, fromMaybe)
    import Data.Monoid (Any (..))
    import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr)
    import qualified Data.Set as Set
    import qualified Data.Text as T
    import Data.Version (showVersion)
    import Network.URI (URI (uriScheme), escapeURIString, parseURI)
    import Paths_pandoc (version)
    import System.Directory
    import System.FilePath (isPathSeparator, splitDirectories)
    import qualified System.FilePath.Posix as Posix
    import Text.HTML.TagSoup (RenderOptions (..), Tag (..), renderOptions,
                              renderTagsOptions)
    import Text.Pandoc.Builder (Blocks, Inlines, ToMetaValue (..))
    import qualified Text.Pandoc.Builder as B
    import Data.Time
    import Text.Pandoc.Asciify (toAsciiChar)
    import Text.Pandoc.Definition
    import Text.Pandoc.Extensions (Extensions, Extension(..), extensionEnabled)
    import Text.Pandoc.Generic (bottomUp)
    import Text.DocLayout (charWidth)
    import Text.Pandoc.Walk

    -- | Version number of pandoc library.
    pandocVersion :: T.Text
    pandocVersion :: Text
    pandocVersion = String -> Text
    T.pack (String -> Text) -> String -> Text
    forall a b. (a -> b) -> a -> b
    $ Version -> String
    showVersion Version
    version

    --
    -- List processing
    --

    -- | Split list by groups of one or more sep.
    splitBy :: (a -> Bool) -> [a] -> [[a]]
    splitBy :: (a -> Bool) -> [a] -> [[a]]
    splitBy _ [] = []
    splitBy isSep :: a -> Bool
    isSep lst :: [a]
    lst =
      let (first :: [a]
    first, rest :: [a]
    rest) = (a -> Bool) -> [a] -> ([a], [a])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    break a -> Bool
    isSep [a]
    lst
          rest' :: [a]
    rest'         = (a -> Bool) -> [a] -> [a]
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile a -> Bool
    isSep [a]
    rest
      in  [a]
    first[a] -> [[a]] -> [[a]]
    forall a. a -> [a] -> [a]
    :(a -> Bool) -> [a] -> [[a]]
    forall a. (a -> Bool) -> [a] -> [[a]]
    splitBy a -> Bool
    isSep [a]
    rest'

    splitTextBy :: (Char -> Bool) -> T.Text -> [T.Text]
    splitTextBy :: (Char -> Bool) -> Text -> [Text]
    splitTextBy isSep :: Char -> Bool
    isSep t :: Text
    t
      | Text -> Bool
    T.null Text
    t = []
      | Bool
    otherwise = let (first :: Text
    first, rest :: Text
    rest) = (Char -> Bool) -> Text -> (Text, Text)
    T.break Char -> Bool
    isSep Text
    t
                        rest' :: Text
    rest'         = (Char -> Bool) -> Text -> Text
    T.dropWhile Char -> Bool
    isSep Text
    rest
                    in  Text
    first Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    : (Char -> Bool) -> Text -> [Text]
    splitTextBy Char -> Bool
    isSep Text
    rest'

    splitByIndices :: [Int] -> [a] -> [[a]]
    splitByIndices :: [Int] -> [a] -> [[a]]
    splitByIndices [] lst :: [a]
    lst = [[a]
    lst]
    splitByIndices (x :: Int
    x:xs :: [Int]
    xs) lst :: [a]
    lst = [a]
    first[a] -> [[a]] -> [[a]]
    forall a. a -> [a] -> [a]
    :[Int] -> [a] -> [[a]]
    forall a. [Int] -> [a] -> [[a]]
    splitByIndices ((Int -> Int) -> [Int] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map (\y :: Int
    y -> Int
    y Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    x)  [Int]
    xs) [a]
    rest
      where (first :: [a]
    first, rest :: [a]
    rest) = Int -> [a] -> ([a], [a])
    forall a. Int -> [a] -> ([a], [a])
    splitAt Int
    x [a]
    lst

    -- | Split string into chunks divided at specified indices.
    splitStringByIndices :: [Int] -> [Char] -> [[Char]]
    splitStringByIndices :: [Int] -> String -> [String]
    splitStringByIndices [] lst :: String
    lst = [String
    lst]
    splitStringByIndices (x :: Int
    x:xs :: [Int]
    xs) lst :: String
    lst =
      let (first :: String
    first, rest :: String
    rest) = Int -> String -> (String, String)
    splitAt' Int
    x String
    lst in
      String
    first String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : [Int] -> String -> [String]
    splitStringByIndices ((Int -> Int) -> [Int] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map (\y :: Int
    y -> Int
    y Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    x) [Int]
    xs) String
    rest

    splitTextByIndices :: [Int] -> T.Text -> [T.Text]
    splitTextByIndices :: [Int] -> Text -> [Text]
    splitTextByIndices ns :: [Int]
    ns = (String -> Text) -> [String] -> [Text]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap String -> Text
    T.pack ([String] -> [Text]) -> (Text -> [String]) -> Text -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Int] -> String -> [String]
    splitStringByIndices [Int]
    ns (String -> [String]) -> (Text -> String) -> Text -> [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack

    splitAt' :: Int -> [Char] -> ([Char],[Char])
    splitAt' :: Int -> String -> (String, String)
    splitAt' _ []          = ([],[])
    splitAt' n :: Int
    n xs :: String
    xs | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 0 = ([],String
    xs)
    splitAt' n :: Int
    n (x :: Char
    x:xs :: String
    xs)      = (Char
    xChar -> String -> String
    forall a. a -> [a] -> [a]
    :String
    ys,String
    zs)
      where (ys :: String
    ys,zs :: String
    zs) = Int -> String -> (String, String)
    splitAt' (Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Char -> Int
    charWidth Char
    x) String
    xs

    -- | Replace each occurrence of one sublist in a list with another.
    substitute :: (Eq a) => [a] -> [a] -> [a] -> [a]
    substitute :: [a] -> [a] -> [a] -> [a]
    substitute _ _ [] = []
    substitute [] _ xs :: [a]
    xs = [a]
    xs
    substitute target :: [a]
    target replacement :: [a]
    replacement lst :: [a]
    lst@(x :: a
    x:xs :: [a]
    xs) =
        case [a] -> [a] -> Maybe [a]
    forall a. Eq a => [a] -> [a] -> Maybe [a]
    stripPrefix [a]
    target [a]
    lst of
          Just lst' :: [a]
    lst' -> [a]
    replacement [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a] -> [a] -> [a] -> [a]
    forall a. Eq a => [a] -> [a] -> [a] -> [a]
    substitute [a]
    target [a]
    replacement [a]
    lst'
          Nothing   -> a
    x a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : [a] -> [a] -> [a] -> [a]
    forall a. Eq a => [a] -> [a] -> [a] -> [a]
    substitute [a]
    target [a]
    replacement [a]
    xs

    ordNub :: (Ord a) => [a] -> [a]
    ordNub :: [a] -> [a]
    ordNub l :: [a]
    l = Set a -> [a] -> [a]
    forall a. Ord a => Set a -> [a] -> [a]
    go Set a
    forall a. Set a
    Set.empty [a]
    l
      where
        go :: Set a -> [a] -> [a]
    go _ [] = []
        go s :: Set a
    s (x :: a
    x:xs :: [a]
    xs) = if a
    x a -> Set a -> Bool
    forall a. Ord a => a -> Set a -> Bool
    `Set.member` Set a
    s then Set a -> [a] -> [a]
    go Set a
    s [a]
    xs
                                          else a
    x a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : Set a -> [a] -> [a]
    go (a -> Set a -> Set a
    forall a. Ord a => a -> Set a -> Set a
    Set.insert a
    x Set a
    s) [a]
    xs

    findM :: forall m t a. (Monad m, Foldable t) => (a -> m Bool) -> t a -> m (Maybe a)
    findM :: (a -> m Bool) -> t a -> m (Maybe a)
    findM p :: a -> m Bool
    p = (a -> m (Maybe a) -> m (Maybe a))
    -> m (Maybe a) -> t a -> m (Maybe a)
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr a -> m (Maybe a) -> m (Maybe a)
    go (Maybe a -> m (Maybe a)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Maybe a
    forall a. Maybe a
    Nothing)
      where
        go :: a -> m (Maybe a) -> m (Maybe a)
        go :: a -> m (Maybe a) -> m (Maybe a)
    go x :: a
    x acc :: m (Maybe a)
    acc = do
          Bool
    b <- a -> m Bool
    p a
    x
          if Bool
    b then Maybe a -> m (Maybe a)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (a -> Maybe a
    forall a. a -> Maybe a
    Just a
    x) else m (Maybe a)
    acc

    --
    -- Text processing
    --

    class ToString a where
      toString :: a -> String

    instance ToString String where
      toString :: String -> String
    toString = String -> String
    forall a. a -> a
    id

    instance ToString T.Text where
      toString :: Text -> String
    toString = Text -> String
    T.unpack

    class ToText a where
      toText :: a -> T.Text

    instance ToText String where
      toText :: String -> Text
    toText = String -> Text
    T.pack

    instance ToText T.Text where
      toText :: Text -> Text
    toText = Text -> Text
    forall a. a -> a
    id

    tshow :: Show a => a -> T.Text
    tshow :: a -> Text
    tshow = String -> Text
    T.pack (String -> Text) -> (a -> String) -> a -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> String
    forall a. Show a => a -> String
    show

    -- | Returns an association list of backslash escapes for the
    -- designated characters.
    backslashEscapes :: [Char]    -- ^ list of special characters to escape
                     -> [(Char, T.Text)]
    backslashEscapes :: String -> [(Char, Text)]
    backslashEscapes = (Char -> (Char, Text)) -> String -> [(Char, Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map (\ch :: Char
    ch -> (Char
    ch, String -> Text
    T.pack ['\\',Char
    ch]))

    -- | Escape a string of characters, using an association list of
    -- characters and strings.
    escapeStringUsing :: [(Char, T.Text)] -> T.Text -> T.Text
    escapeStringUsing :: [(Char, Text)] -> Text -> Text
    escapeStringUsing tbl :: [(Char, Text)]
    tbl = (Char -> Text) -> Text -> Text
    T.concatMap ((Char -> Text) -> Text -> Text) -> (Char -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ \c :: Char
    c -> Text -> Maybe Text -> Text
    forall a. a -> Maybe a -> a
    fromMaybe (Char -> Text
    T.singleton Char
    c) (Maybe Text -> Text) -> Maybe Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Char -> [(Char, Text)] -> Maybe Text
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup Char
    c [(Char, Text)]
    tbl

    -- | @True@ exactly when the @Char@ appears in the @Text@.
    elemText :: Char -> T.Text -> Bool
    elemText :: Char -> Text -> Bool
    elemText c :: Char
    c = (Char -> Bool) -> Text -> Bool
    T.any (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    c)

    -- | @True@ exactly when the @Char@ does not appear in the @Text@.
    notElemText :: Char -> T.Text -> Bool
    notElemText :: Char -> Text -> Bool
    notElemText c :: Char
    c = (Char -> Bool) -> Text -> Bool
    T.all (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Char
    c)

    -- | Strip trailing newlines from string.
    stripTrailingNewlines :: T.Text -> T.Text
    stripTrailingNewlines :: Text -> Text
    stripTrailingNewlines = (Char -> Bool) -> Text -> Text
    T.dropWhileEnd (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '\n')

    -- | Remove leading and trailing space (including newlines) from string.
    trim :: T.Text -> T.Text
    trim :: Text -> Text
    trim = (Char -> Bool) -> Text -> Text
    T.dropAround (Char -> Text -> Bool
    `elemText` " \r\n\t")

    -- | Remove leading space (including newlines) from string.
    triml :: T.Text -> T.Text
    triml :: Text -> Text
    triml = (Char -> Bool) -> Text -> Text
    T.dropWhile (Char -> Text -> Bool
    `elemText` " \r\n\t")

    -- | Remove trailing space (including newlines) from string.
    trimr :: T.Text -> T.Text
    trimr :: Text -> Text
    trimr = (Char -> Bool) -> Text -> Text
    T.dropWhileEnd (Char -> Text -> Bool
    `elemText` " \r\n\t")

    -- | Trim leading space and trailing space unless after \.
    trimMath :: T.Text -> T.Text
    trimMath :: Text -> Text
    trimMath = Text -> Text
    triml (Text -> Text) -> (Text -> Text) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.reverse (Text -> Text) -> (Text -> Text) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    stripBeginSpace (Text -> Text) -> (Text -> Text) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.reverse -- no Text.spanEnd
      where
        stripBeginSpace :: Text -> Text
    stripBeginSpace t :: Text
    t
          | Text -> Bool
    T.null Text
    pref = Text
    t
          | Just ('\\', _) <- Text -> Maybe (Char, Text)
    T.uncons Text
    suff = Char -> Text -> Text
    T.cons (Text -> Char
    T.last Text
    pref) Text
    suff
          | Bool
    otherwise = Text
    suff
          where
            (pref :: Text
    pref, suff :: Text
    suff) = (Char -> Bool) -> Text -> (Text, Text)
    T.span (Char -> Text -> Bool
    `elemText` " \t\n\r") Text
    t

    -- | Strip leading and trailing characters from string
    stripFirstAndLast :: T.Text -> T.Text
    stripFirstAndLast :: Text -> Text
    stripFirstAndLast t :: Text
    t = case Text -> Maybe (Char, Text)
    T.uncons Text
    t of
      Just (_, t' :: Text
    t') -> case Text -> Maybe (Text, Char)
    T.unsnoc Text
    t' of
        Just (t'' :: Text
    t'', _) -> Text
    t''
        _             -> Text
    t'
      _               -> ""

    -- | Change CamelCase word to hyphenated lowercase (e.g., camel-case).
    camelCaseToHyphenated :: T.Text -> T.Text
    camelCaseToHyphenated :: Text -> Text
    camelCaseToHyphenated = String -> Text
    T.pack (String -> Text) -> (Text -> String) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String
    camelCaseStrToHyphenated (String -> String) -> (Text -> String) -> Text -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack

    -- This may not work as expected on general Unicode, if it contains
    -- letters with a longer lower case form than upper case. I don't know
    -- what the camel case practices of affected scripts are, though.
    camelCaseStrToHyphenated :: String -> String
    camelCaseStrToHyphenated :: String -> String
    camelCaseStrToHyphenated [] = ""
    camelCaseStrToHyphenated (a :: Char
    a:b :: Char
    b:rest :: String
    rest)
      | Char -> Bool
    isLower Char
    a
      , Char -> Bool
    isUpper Char
    b = Char
    aChar -> String -> String
    forall a. a -> [a] -> [a]
    :'-'Char -> String -> String
    forall a. a -> [a] -> [a]
    :Char -> Char
    toLower Char
    bChar -> String -> String
    forall a. a -> [a] -> [a]
    :String -> String
    camelCaseStrToHyphenated String
    rest
    -- handle ABCDef = abc-def
    camelCaseStrToHyphenated (a :: Char
    a:b :: Char
    b:c :: Char
    c:rest :: String
    rest)
      | Char -> Bool
    isUpper Char
    a
      , Char -> Bool
    isUpper Char
    b
      , Char -> Bool
    isLower Char
    c = Char -> Char
    toLower Char
    aChar -> String -> String
    forall a. a -> [a] -> [a]
    :'-'Char -> String -> String
    forall a. a -> [a] -> [a]
    :Char -> Char
    toLower Char
    bChar -> String -> String
    forall a. a -> [a] -> [a]
    :String -> String
    camelCaseStrToHyphenated (Char
    cChar -> String -> String
    forall a. a -> [a] -> [a]
    :String
    rest)
    camelCaseStrToHyphenated (a :: Char
    a:rest :: String
    rest) = Char -> Char
    toLower Char
    aChar -> String -> String
    forall a. a -> [a] -> [a]
    :String -> String
    camelCaseStrToHyphenated String
    rest

    -- | Convert number < 4000 to uppercase roman numeral.
    toRomanNumeral :: Int -> T.Text
    toRomanNumeral :: Int -> Text
    toRomanNumeral x :: Int
    x
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 4000 Bool -> Bool -> Bool
    || Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0 = "?"
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 1000 = "M" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1000)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 900  = "CM" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 900)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 500  = "D" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 500)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 400  = "CD" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 400)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 100  = "C" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 100)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 90   = "XC" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 90)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 50   = "L"  Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 50)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 40   = "XL" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 40)
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 10   = "X" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 10)
      | Int
    x Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 9    = "IX"
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 5    = "V" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 5)
      | Int
    x Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 4    = "IV"
      | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 1    = "I" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text
    toRomanNumeral (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1)
      | Bool
    otherwise = ""

    -- | Escape whitespace and some punctuation characters in URI.
    escapeURI :: T.Text -> T.Text
    escapeURI :: Text -> Text
    escapeURI = String -> Text
    T.pack (String -> Text) -> (Text -> String) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> String -> String
    escapeURIString (Bool -> Bool
    not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Bool
    needsEscaping) (String -> String) -> (Text -> String) -> Text -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack
      where needsEscaping :: Char -> Bool
    needsEscaping c :: Char
    c = Char -> Bool
    isSpace Char
    c Bool -> Bool -> Bool
    || Char
    c Char -> Text -> Bool
    `elemText` "<>|\"{}[]^`"

    -- | Convert tabs to spaces. Tabs will be preserved if tab stop is set to 0.
    tabFilter :: Int       -- ^ Tab stop
              -> T.Text    -- ^ Input
              -> T.Text
    tabFilter :: Int -> Text -> Text
    tabFilter 0 = Text -> Text
    forall a. a -> a
    id
    tabFilter tabStop :: Int
    tabStop = [Text] -> Text
    T.unlines ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Text -> Text
    go ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> [Text]
    T.lines
      where go :: Text -> Text
    go s :: Text
    s =
             let (s1 :: Text
    s1, s2 :: Text
    s2) = (Char -> Bool) -> Text -> (Text, Text)
    T.break (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '\t') Text
    s
             in  if Text -> Bool
    T.null Text
    s2
                    then Text
    s1
                    else Text
    s1 Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Int -> Text -> Text
    T.replicate
                           (Int
    tabStop Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - (Text -> Int
    T.length Text
    s1 Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` Int
    tabStop)) (String -> Text
    T.pack " ")
                           Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text -> Text
    go (Int -> Text -> Text
    T.drop 1 Text
    s2)

    -- | Strip out DOS line endings.
    crFilter :: T.Text -> T.Text
    crFilter :: Text -> Text
    crFilter = (Char -> Bool) -> Text -> Text
    T.filter (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= '\r')

    --
    -- Date/time
    --

    -- | Parse a date and convert (if possible) to "YYYY-MM-DD" format. We
    -- limit years to the range 1601-9999 (ISO 8601 accepts greater than
    -- or equal to 1583, but MS Word only accepts dates starting 1601).
    normalizeDate :: T.Text -> Maybe T.Text
    normalizeDate :: Text -> Maybe Text
    normalizeDate = (String -> Text) -> Maybe String -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap String -> Text
    T.pack (Maybe String -> Maybe Text)
    -> (Text -> Maybe String) -> Text -> Maybe Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Maybe String
    normalizeDate' (String -> Maybe String)
    -> (Text -> String) -> Text -> Maybe String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack

    normalizeDate' :: String -> Maybe String
    normalizeDate' :: String -> Maybe String
    normalizeDate' s :: String
    s = (Day -> String) -> Maybe Day -> Maybe String
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (TimeLocale -> String -> Day -> String
    forall t. FormatTime t => TimeLocale -> String -> t -> String
    formatTime TimeLocale
    defaultTimeLocale "%F")
      ([Maybe Day] -> Maybe Day
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, MonadPlus m) =>
    t (m a) -> m a
    msum ([Maybe Day] -> Maybe Day) -> [Maybe Day] -> Maybe Day
    forall a b. (a -> b) -> a -> b
    $ (String -> Maybe Day) -> [String] -> [Maybe Day]
    forall a b. (a -> b) -> [a] -> [b]
    map (\fs :: String
    fs -> String -> String -> Maybe Day
    parsetimeWith String
    fs String
    s Maybe Day -> (Day -> Maybe Day) -> Maybe Day
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Day -> Maybe Day
    rejectBadYear) [String]
    formats :: Maybe Day)
      where rejectBadYear :: Day -> Maybe Day
    rejectBadYear day :: Day
    day = case Day -> (Integer, Int, Int)
    toGregorian Day
    day of
              (y :: Integer
    y, _, _) | Integer
    y Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 1601 Bool -> Bool -> Bool
    && Integer
    y Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 9999 -> Day -> Maybe Day
    forall a. a -> Maybe a
    Just Day
    day
              _         -> Maybe Day
    forall a. Maybe a
    Nothing
            parsetimeWith :: String -> String -> Maybe Day
    parsetimeWith = Bool -> TimeLocale -> String -> String -> Maybe Day
    forall (m :: * -> *) t.
    (MonadFail m, ParseTime t) =>
    Bool -> TimeLocale -> String -> String -> m t
    parseTimeM Bool
    True TimeLocale
    defaultTimeLocale
            formats :: [String]
    formats = ["%x","%m/%d/%Y", "%D","%F", "%d %b %Y",
                        "%e %B %Y", "%b. %e, %Y", "%B %e, %Y",
                        "%Y%m%d", "%Y%m", "%Y"]

    --
    -- Pandoc block and inline list processing
    --

    -- | Generate infinite lazy list of markers for an ordered list,
    -- depending on list attributes.
    orderedListMarkers :: (Int, ListNumberStyle, ListNumberDelim) -> [T.Text]
    orderedListMarkers :: (Int, ListNumberStyle, ListNumberDelim) -> [Text]
    orderedListMarkers (start :: Int
    start, numstyle :: ListNumberStyle
    numstyle, numdelim :: ListNumberDelim
    numdelim) =
      let nums :: [Text]
    nums = case ListNumberStyle
    numstyle of
                         DefaultStyle -> (Int -> Text) -> [Int] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> Text
    forall a. Show a => a -> Text
    tshow [Int
    start..]
                         Example      -> (Int -> Text) -> [Int] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> Text
    forall a. Show a => a -> Text
    tshow [Int
    start..]
                         Decimal      -> (Int -> Text) -> [Int] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> Text
    forall a. Show a => a -> Text
    tshow [Int
    start..]
                         UpperAlpha   -> Int -> [Text] -> [Text]
    forall a. Int -> [a] -> [a]
    drop (Int
    start Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1) ([Text] -> [Text]) -> [Text] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ [Text] -> [Text]
    forall a. [a] -> [a]
    cycle ([Text] -> [Text]) -> [Text] -> [Text]
    forall a b. (a -> b) -> a -> b
    $
                                         (Char -> Text) -> String -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Text
    T.singleton ['A'..'Z']
                         LowerAlpha   -> Int -> [Text] -> [Text]
    forall a. Int -> [a] -> [a]
    drop (Int
    start Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1) ([Text] -> [Text]) -> [Text] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ [Text] -> [Text]
    forall a. [a] -> [a]
    cycle ([Text] -> [Text]) -> [Text] -> [Text]
    forall a b. (a -> b) -> a -> b
    $
                                         (Char -> Text) -> String -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Text
    T.singleton ['a'..'z']
                         UpperRoman   -> (Int -> Text) -> [Int] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> Text
    toRomanNumeral [Int
    start..]
                         LowerRoman   -> (Int -> Text) -> [Int] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text -> Text
    T.toLower (Text -> Text) -> (Int -> Text) -> Int -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Text
    toRomanNumeral) [Int
    start..]
          inDelim :: a -> a
    inDelim str :: a
    str = case ListNumberDelim
    numdelim of
                                DefaultDelim -> a
    str a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> "."
                                Period       -> a
    str a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> "."
                                OneParen     -> a
    str a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> ")"
                                TwoParens    -> "(" a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> a
    str a -> a -> a
    forall a. Semigroup a => a -> a -> a
    <> ")"
      in  (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Text -> Text
    forall a. (Semigroup a, IsString a) => a -> a
    inDelim [Text]
    nums

    -- | Extract the leading and trailing spaces from inside an inline element
    -- and place them outside the element.  SoftBreaks count as Spaces for
    -- these purposes.
    extractSpaces :: (Inlines -> Inlines) -> Inlines -> Inlines
    extractSpaces :: (Inlines -> Inlines) -> Inlines -> Inlines
    extractSpaces f :: Inlines -> Inlines
    f is :: Inlines
    is =
      let contents :: Seq Inline
    contents = Inlines -> Seq Inline
    forall a. Many a -> Seq a
    B.unMany Inlines
    is
          left :: Inlines
    left  = case Seq Inline -> ViewL Inline
    forall a. Seq a -> ViewL a
    viewl Seq Inline
    contents of
                        (Space :< _)     -> Inlines
    B.space
                        (SoftBreak :< _) -> Inlines
    B.softbreak
                        _                -> Inlines
    forall a. Monoid a => a
    mempty
          right :: Inlines
    right = case Seq Inline -> ViewR Inline
    forall a. Seq a -> ViewR a
    viewr Seq Inline
    contents of
                        (_ :> Space)     -> Inlines
    B.space
                        (_ :> SoftBreak) -> Inlines
    B.softbreak
                        _                -> Inlines
    forall a. Monoid a => a
    mempty in
      (Inlines
    left Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <> Inlines -> Inlines
    f (Inlines -> Inlines
    B.trimInlines (Inlines -> Inlines)
    -> (Seq Inline -> Inlines) -> Seq Inline -> Inlines
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Seq Inline -> Inlines
    forall a. Seq a -> Many a
    B.Many (Seq Inline -> Inlines) -> Seq Inline -> Inlines
    forall a b. (a -> b) -> a -> b
    $ Seq Inline
    contents) Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <> Inlines
    right)

    -- | Extract inlines, removing formatting.
    removeFormatting :: Walkable Inline a => a -> [Inline]
    removeFormatting :: a -> [Inline]
    removeFormatting = (Inline -> [Inline]) -> a -> [Inline]
    forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
    query Inline -> [Inline]
    go (a -> [Inline]) -> (a -> a) -> a -> [Inline]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Inline -> Inline) -> a -> a
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk (Inline -> Inline
    deNote (Inline -> Inline) -> (Inline -> Inline) -> Inline -> Inline
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Inline -> Inline
    deQuote)
      where go :: Inline -> [Inline]
            go :: Inline -> [Inline]
    go (Str xs :: Text
    xs)   = [Text -> Inline
    Str Text
    xs]
            go Space      = [Inline
    Space]
            go SoftBreak  = [Inline
    SoftBreak]
            go (Code _ x :: Text
    x) = [Text -> Inline
    Str Text
    x]
            go (Math _ x :: Text
    x) = [Text -> Inline
    Str Text
    x]
            go LineBreak  = [Inline
    Space]
            go _          = []

    deNote :: Inline -> Inline
    deNote :: Inline -> Inline
    deNote (Note _) = Text -> Inline
    Str ""
    deNote x :: Inline
    x        = Inline
    x

    deLink :: Inline -> Inline
    deLink :: Inline -> Inline
    deLink (Link _ ils :: [Inline]
    ils _) = Attr -> [Inline] -> Inline
    Span Attr
    nullAttr [Inline]
    ils
    deLink x :: Inline
    x              = Inline
    x

    deQuote :: Inline -> Inline
    deQuote :: Inline -> Inline
    deQuote (Quoted SingleQuote xs :: [Inline]
    xs) =
      Attr -> [Inline] -> Inline
    Span ("",[],[]) (Text -> Inline
    Str "\8216" Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline]
    xs [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Text -> Inline
    Str "\8217"])
    deQuote (Quoted DoubleQuote xs :: [Inline]
    xs) =
      Attr -> [Inline] -> Inline
    Span ("",[],[]) (Text -> Inline
    Str "\8220" Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline]
    xs [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Text -> Inline
    Str "\8221"])
    deQuote x :: Inline
    x = Inline
    x

    -- | Convert pandoc structure to a string with formatting removed.
    -- Footnotes are skipped (since we don't want their contents in link
    -- labels).
    stringify :: Walkable Inline a => a -> T.Text
    stringify :: a -> Text
    stringify = (Inline -> Text) -> a -> Text
    forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
    query Inline -> Text
    go (a -> Text) -> (a -> a) -> a -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Inline -> Inline) -> a -> a
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk (Inline -> Inline
    deNote (Inline -> Inline) -> (Inline -> Inline) -> Inline -> Inline
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Inline -> Inline
    deQuote)
      where go :: Inline -> T.Text
            go :: Inline -> Text
    go Space                                       = " "
            go SoftBreak                                   = " "
            go (Str x :: Text
    x)                                     = Text
    x
            go (Code _ x :: Text
    x)                                  = Text
    x
            go (Math _ x :: Text
    x)                                  = Text
    x
            go (RawInline (Format "html") (Text -> String
    T.unpack -> ('<':'b':'r':_)))
                                                           = " " -- see #2105
            go LineBreak                                   = " "
            go _                                           = ""

    -- | Bring all regular text in a pandoc structure to uppercase.
    --
    -- This function correctly handles cases where a lowercase character doesn't
    -- match to a single uppercase character – e.g. “Straße” would be converted
    -- to “STRASSE”, not “STRAßE”.
    capitalize :: Walkable Inline a => a -> a
    capitalize :: a -> a
    capitalize = (Inline -> Inline) -> a -> a
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk Inline -> Inline
    go
      where go :: Inline -> Inline
            go :: Inline -> Inline
    go (Str s :: Text
    s) = Text -> Inline
    Str (Text -> Inline) -> Text -> Inline
    forall a b. (a -> b) -> a -> b
    $ Text -> Text
    T.toUpper Text
    s
            go x :: Inline
    x       = Inline
    x

    -- | Change final list item from @Para@ to @Plain@ if the list contains
    -- no other @Para@ blocks.  Otherwise (if the list items contain @Para@
    -- blocks besides possibly at the end), turn any @Plain@s into @Para@s (#5285).
    compactify :: [Blocks]  -- ^ List of list items (each a list of blocks)
               -> [Blocks]
    compactify :: [Blocks] -> [Blocks]
    compactify [] = []
    compactify items :: [Blocks]
    items =
      let (others :: [Blocks]
    others, final :: Blocks
    final) = ([Blocks] -> [Blocks]
    forall a. [a] -> [a]
    init [Blocks]
    items, [Blocks] -> Blocks
    forall a. [a] -> a
    last [Blocks]
    items)
      in  case [Block] -> [Block]
    forall a. [a] -> [a]
    reverse (Blocks -> [Block]
    forall a. Many a -> [a]
    B.toList Blocks
    final) of
               (Para a :: [Inline]
    a:xs :: [Block]
    xs)
                 | [Block] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [[Inline] -> Block
    Para [Inline]
    x | Para x :: [Inline]
    x <- [Block]
    xs [Block] -> [Block] -> [Block]
    forall a. [a] -> [a] -> [a]
    ++ (Blocks -> [Block]) -> [Blocks] -> [Block]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Blocks -> [Block]
    forall a. Many a -> [a]
    B.toList [Blocks]
    others]
                 -> [Blocks]
    others [Blocks] -> [Blocks] -> [Blocks]
    forall a. [a] -> [a] -> [a]
    ++ [[Block] -> Blocks
    forall a. [a] -> Many a
    B.fromList ([Block] -> [Block]
    forall a. [a] -> [a]
    reverse ([Inline] -> Block
    Plain [Inline]
    a Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    xs))]
               _ | [Block] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [[Inline] -> Block
    Para [Inline]
    x | Para x :: [Inline]
    x <- (Blocks -> [Block]) -> [Blocks] -> [Block]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Blocks -> [Block]
    forall a. Many a -> [a]
    B.toList [Blocks]
    items]
                 -> [Blocks]
    items
               _ -> (Blocks -> Blocks) -> [Blocks] -> [Blocks]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Block -> Block) -> Blocks -> Blocks
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Block -> Block
    plainToPara) [Blocks]
    items

    plainToPara :: Block -> Block
    plainToPara :: Block -> Block
    plainToPara (Plain ils :: [Inline]
    ils) = [Inline] -> Block
    Para [Inline]
    ils
    plainToPara x :: Block
    x = Block
    x

    -- | Like @compactify@, but acts on items of definition lists.
    compactifyDL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]
    compactifyDL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]
    compactifyDL items :: [(Inlines, [Blocks])]
    items =
      let defs :: [Blocks]
    defs = ((Inlines, [Blocks]) -> [Blocks])
    -> [(Inlines, [Blocks])] -> [Blocks]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (Inlines, [Blocks]) -> [Blocks]
    forall a b. (a, b) -> b
    snd [(Inlines, [Blocks])]
    items
      in  case [Block] -> [Block]
    forall a. [a] -> [a]
    reverse ((Blocks -> [Block]) -> [Blocks] -> [Block]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap Blocks -> [Block]
    forall a. Many a -> [a]
    B.toList [Blocks]
    defs) of
               (Para x :: [Inline]
    x:xs :: [Block]
    xs)
                 | Bool -> Bool
    not ((Block -> Bool) -> [Block] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any Block -> Bool
    isPara [Block]
    xs) ->
                       let (t :: Inlines
    t,ds :: [Blocks]
    ds) = [(Inlines, [Blocks])] -> (Inlines, [Blocks])
    forall a. [a] -> a
    last [(Inlines, [Blocks])]
    items
                           lastDef :: [Block]
    lastDef = Blocks -> [Block]
    forall a. Many a -> [a]
    B.toList (Blocks -> [Block]) -> Blocks -> [Block]
    forall a b. (a -> b) -> a -> b
    $ [Blocks] -> Blocks
    forall a. [a] -> a
    last [Blocks]
    ds
                           ds' :: [Blocks]
    ds' = [Blocks] -> [Blocks]
    forall a. [a] -> [a]
    init [Blocks]
    ds [Blocks] -> [Blocks] -> [Blocks]
    forall a. [a] -> [a] -> [a]
    ++
                                 if [Block] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Block]
    lastDef
                                    then [[Block] -> Blocks
    forall a. [a] -> Many a
    B.fromList [Block]
    lastDef]
                                    else [[Block] -> Blocks
    forall a. [a] -> Many a
    B.fromList ([Block] -> Blocks) -> [Block] -> Blocks
    forall a b. (a -> b) -> a -> b
    $ [Block] -> [Block]
    forall a. [a] -> [a]
    init [Block]
    lastDef [Block] -> [Block] -> [Block]
    forall a. [a] -> [a] -> [a]
    ++ [[Inline] -> Block
    Plain [Inline]
    x]]
                        in [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]
    forall a. [a] -> [a]
    init [(Inlines, [Blocks])]
    items [(Inlines, [Blocks])]
    -> [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]
    forall a. [a] -> [a] -> [a]
    ++ [(Inlines
    t, [Blocks]
    ds')]
                 | Bool
    otherwise           -> [(Inlines, [Blocks])]
    items
               _                       -> [(Inlines, [Blocks])]
    items

    -- | Combine a list of lines by adding hard linebreaks.
    combineLines :: [[Inline]] -> [Inline]
    combineLines :: [[Inline]] -> [Inline]
    combineLines = [Inline] -> [[Inline]] -> [Inline]
    forall a. [a] -> [[a]] -> [a]
    intercalate [Inline
    LineBreak]

    -- | Convert a list of lines into a paragraph with hard line breaks. This is
    --   useful e.g. for rudimentary support of LineBlock elements in writers.
    linesToPara :: [[Inline]] -> Block
    linesToPara :: [[Inline]] -> Block
    linesToPara = [Inline] -> Block
    Para ([Inline] -> Block)
    -> ([[Inline]] -> [Inline]) -> [[Inline]] -> Block
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [[Inline]] -> [Inline]
    combineLines

    isPara :: Block -> Bool
    isPara :: Block -> Bool
    isPara (Para _) = Bool
    True
    isPara _        = Bool
    False

    -- | Convert Pandoc inline list to plain text identifier.  HTML
    -- identifiers must start with a letter, and may contain only
    -- letters, digits, and the characters _-.
    inlineListToIdentifier :: Extensions -> [Inline] -> T.Text
    inlineListToIdentifier :: Extensions -> [Inline] -> Text
    inlineListToIdentifier exts :: Extensions
    exts =
      Text -> Text
    dropNonLetter (Text -> Text) -> ([Inline] -> Text) -> [Inline] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    filterAscii (Text -> Text) -> ([Inline] -> Text) -> [Inline] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    toIdent (Text -> Text) -> ([Inline] -> Text) -> [Inline] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Inline] -> Text
    forall a. Walkable Inline a => a -> Text
    stringify ([Inline] -> Text) -> ([Inline] -> [Inline]) -> [Inline] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Inline] -> [Inline]) -> [Inline] -> [Inline]
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk [Inline] -> [Inline]
    unEmojify
      where
        unEmojify :: [Inline] -> [Inline]
        unEmojify :: [Inline] -> [Inline]
    unEmojify
          | Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_gfm_auto_identifiers Extensions
    exts Bool -> Bool -> Bool
    ||
            Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_ascii_identifiers Extensions
    exts = (Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk Inline -> Inline
    unEmoji
          | Bool
    otherwise = [Inline] -> [Inline]
    forall a. a -> a
    id
        unEmoji :: Inline -> Inline
    unEmoji (Span ("",["emoji"],[("data-emoji",ename :: Text
    ename)]) _) = Text -> Inline
    Str Text
    ename
        unEmoji x :: Inline
    x = Inline
    x
        dropNonLetter :: Text -> Text
    dropNonLetter
          | Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_gfm_auto_identifiers Extensions
    exts = Text -> Text
    forall a. a -> a
    id
          | Bool
    otherwise = (Char -> Bool) -> Text -> Text
    T.dropWhile (Bool -> Bool
    not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Bool
    isAlpha)
        filterAscii :: Text -> Text
    filterAscii
          | Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_ascii_identifiers Extensions
    exts
            = String -> Text
    T.pack (String -> Text) -> (Text -> String) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Maybe Char) -> String -> String
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe Char -> Maybe Char
    toAsciiChar (String -> String) -> (Text -> String) -> Text -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack
          | Bool
    otherwise = Text -> Text
    forall a. a -> a
    id
        toIdent :: Text -> Text
    toIdent
          | Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_gfm_auto_identifiers Extensions
    exts =
            Text -> Text
    filterPunct (Text -> Text) -> (Text -> Text) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    spaceToDash (Text -> Text) -> (Text -> Text) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.toLower
          | Bool
    otherwise = Text -> [Text] -> Text
    T.intercalate "-" ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> [Text]
    T.words (Text -> [Text]) -> (Text -> Text) -> Text -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    filterPunct (Text -> Text) -> (Text -> Text) -> Text -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.toLower
        filterPunct :: Text -> Text
    filterPunct = (Char -> Bool) -> Text -> Text
    T.filter (\c :: Char
    c -> Char -> Bool
    isSpace Char
    c Bool -> Bool -> Bool
    || Char -> Bool
    isAlphaNum Char
    c Bool -> Bool -> Bool
    || Char -> Bool
    isAllowedPunct Char
    c)
        isAllowedPunct :: Char -> Bool
    isAllowedPunct c :: Char
    c
          | Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_gfm_auto_identifiers Extensions
    exts
            = Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '-' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '_' Bool -> Bool -> Bool
    ||
              Char -> GeneralCategory
    generalCategory Char
    c GeneralCategory -> [GeneralCategory] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [GeneralCategory
    NonSpacingMark, GeneralCategory
    SpacingCombiningMark,
                                        GeneralCategory
    EnclosingMark, GeneralCategory
    ConnectorPunctuation]
          | Bool
    otherwise = Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '_' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '-' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '.'
        spaceToDash :: Text -> Text
    spaceToDash = (Char -> Char) -> Text -> Text
    T.map (\c :: Char
    c -> if Char -> Bool
    isSpace Char
    c then '-' else Char
    c)

    -- | Put a list of Pandoc blocks into a hierarchical structure:
    -- a list of sections (each a Div with class "section" and first
    -- element a Header).  If the 'numbering' parameter is True, Header
    -- numbers are added via the number attribute on the header.
    -- If the baseLevel parameter is Just n, Header levels are
    -- adjusted to be gapless starting at level n.
    makeSections :: Bool -> Maybe Int -> [Block] -> [Block]
    makeSections :: Bool -> Maybe Int -> [Block] -> [Block]
    makeSections numbering :: Bool
    numbering mbBaseLevel :: Maybe Int
    mbBaseLevel bs :: [Block]
    bs =
      State (Maybe Int, [Int]) [Block] -> (Maybe Int, [Int]) -> [Block]
    forall s a. State s a -> s -> a
    S.evalState ([Block] -> State (Maybe Int, [Int]) [Block]
    go [Block]
    bs) (Maybe Int
    mbBaseLevel, [])
     where
      go :: [Block] -> S.State (Maybe Int, [Int]) [Block]
      go :: [Block] -> State (Maybe Int, [Int]) [Block]
    go (Header level :: Int
    level (ident :: Text
    ident,classes :: [Text]
    classes,kvs :: [(Text, Text)]
    kvs) title' :: [Inline]
    title':xs :: [Block]
    xs) = do
        (mbLevel :: Maybe Int
    mbLevel, lastnum :: [Int]
    lastnum) <- StateT (Maybe Int, [Int]) Identity (Maybe Int, [Int])
    forall s (m :: * -> *). MonadState s m => m s
    S.get
        let level' :: Int
    level' = Int -> Maybe Int -> Int
    forall a. a -> Maybe a -> a
    fromMaybe Int
    level Maybe Int
    mbLevel
        let lastnum' :: [Int]
    lastnum' = Int -> [Int] -> [Int]
    forall a. Int -> [a] -> [a]
    take Int
    level' [Int]
    lastnum
        let newnum :: [Int]
    newnum =
              if Int
    level' Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > 0
                 then case [Int] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [Int]
    lastnum' of
                          x :: Int
    x | "unnumbered" Text -> [Text] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Text]
    classes -> []
                            | Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    level' -> [Int] -> [Int]
    forall a. [a] -> [a]
    init [Int]
    lastnum' [Int] -> [Int] -> [Int]
    forall a. [a] -> [a] -> [a]
    ++ [[Int] -> Int
    forall a. [a] -> a
    last [Int]
    lastnum' Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 1]
                            | Bool
    otherwise -> [Int]
    lastnum [Int] -> [Int] -> [Int]
    forall a. [a] -> [a] -> [a]
    ++
                                 Int -> Int -> [Int]
    forall a. Int -> a -> [a]
    replicate (Int
    level' Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - [Int] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [Int]
    lastnum Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1) 0 [Int] -> [Int] -> [Int]
    forall a. [a] -> [a] -> [a]
    ++ [1]
                 else []
        Bool
    -> StateT (Maybe Int, [Int]) Identity ()
    -> StateT (Maybe Int, [Int]) Identity ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless ([Int] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Int]
    newnum) (StateT (Maybe Int, [Int]) Identity ()
     -> StateT (Maybe Int, [Int]) Identity ())
    -> StateT (Maybe Int, [Int]) Identity ()
    -> StateT (Maybe Int, [Int]) Identity ()
    forall a b. (a -> b) -> a -> b
    $ ((Maybe Int, [Int]) -> (Maybe Int, [Int]))
    -> StateT (Maybe Int, [Int]) Identity ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    S.modify (((Maybe Int, [Int]) -> (Maybe Int, [Int]))
     -> StateT (Maybe Int, [Int]) Identity ())
    -> ((Maybe Int, [Int]) -> (Maybe Int, [Int]))
    -> StateT (Maybe Int, [Int]) Identity ()
    forall a b. (a -> b) -> a -> b
    $ \(mbl :: Maybe Int
    mbl, _) -> (Maybe Int
    mbl, [Int]
    newnum)
        let (sectionContents :: [Block]
    sectionContents, rest :: [Block]
    rest) = (Block -> Bool) -> [Block] -> ([Block], [Block])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    break (Int -> Block -> Bool
    headerLtEq Int
    level) [Block]
    xs
        ((Maybe Int, [Int]) -> (Maybe Int, [Int]))
    -> StateT (Maybe Int, [Int]) Identity ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    S.modify (((Maybe Int, [Int]) -> (Maybe Int, [Int]))
     -> StateT (Maybe Int, [Int]) Identity ())
    -> ((Maybe Int, [Int]) -> (Maybe Int, [Int]))
    -> StateT (Maybe Int, [Int]) Identity ()
    forall a b. (a -> b) -> a -> b
    $ \(_, ln :: [Int]
    ln) -> ((Int -> Int) -> Maybe Int -> Maybe Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 1) Maybe Int
    mbLevel, [Int]
    ln)
        [Block]
    sectionContents' <- [Block] -> State (Maybe Int, [Int]) [Block]
    go [Block]
    sectionContents
        ((Maybe Int, [Int]) -> (Maybe Int, [Int]))
    -> StateT (Maybe Int, [Int]) Identity ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    S.modify (((Maybe Int, [Int]) -> (Maybe Int, [Int]))
     -> StateT (Maybe Int, [Int]) Identity ())
    -> ((Maybe Int, [Int]) -> (Maybe Int, [Int]))
    -> StateT (Maybe Int, [Int]) Identity ()
    forall a b. (a -> b) -> a -> b
    $ \(_, ln :: [Int]
    ln) -> (Maybe Int
    mbLevel, [Int]
    ln)
        [Block]
    rest' <- [Block] -> State (Maybe Int, [Int]) [Block]
    go [Block]
    rest
        let kvs' :: [(Text, Text)]
    kvs' = -- don't touch number if already present
                   case Text -> [(Text, Text)] -> Maybe Text
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup "number" [(Text, Text)]
    kvs of
                      Nothing | Bool
    numbering ->
                            ("number", Text -> [Text] -> Text
    T.intercalate "." ((Int -> Text) -> [Int] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> Text
    forall a. Show a => a -> Text
    tshow [Int]
    newnum)) (Text, Text) -> [(Text, Text)] -> [(Text, Text)]
    forall a. a -> [a] -> [a]
    : [(Text, Text)]
    kvs
                      _ -> [(Text, Text)]
    kvs
        let divattr :: Attr
    divattr = (Text
    ident, "section"Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    classes, [(Text, Text)]
    kvs')
        let attr :: Attr
    attr = ("",[Text]
    classes,[(Text, Text)]
    kvs')
        [Block] -> State (Maybe Int, [Int]) [Block]
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Block] -> State (Maybe Int, [Int]) [Block])
    -> [Block] -> State (Maybe Int, [Int]) [Block]
    forall a b. (a -> b) -> a -> b
    $
          Attr -> [Block] -> Block
    Div Attr
    divattr (Int -> Attr -> [Inline] -> Block
    Header Int
    level' Attr
    attr [Inline]
    title' Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    sectionContents') Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    rest'
      go (Div divattr :: Attr
    divattr@(dident :: Text
    dident,dclasses :: [Text]
    dclasses,_) (Header level :: Int
    level hattr :: Attr
    hattr title' :: [Inline]
    title':ys :: [Block]
    ys) : xs :: [Block]
    xs)
          | (Block -> Bool) -> [Block] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all (\case
                   Header level' :: Int
    level' _ _ -> Int
    level' Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    level
                   _                 -> Bool
    True) [Block]
    ys
          , "column" Text -> [Text] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` [Text]
    dclasses
          , "columns" Text -> [Text] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` [Text]
    dclasses = do
        [Block]
    inner <- [Block] -> State (Maybe Int, [Int]) [Block]
    go (Int -> Attr -> [Inline] -> Block
    Header Int
    level Attr
    hattr [Inline]
    title'Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    :[Block]
    ys)
        [Block]
    rest <- [Block] -> State (Maybe Int, [Int]) [Block]
    go [Block]
    xs
        [Block] -> State (Maybe Int, [Int]) [Block]
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Block] -> State (Maybe Int, [Int]) [Block])
    -> [Block] -> State (Maybe Int, [Int]) [Block]
    forall a b. (a -> b) -> a -> b
    $
          case [Block]
    inner of
                [Div divattr' :: Attr
    divattr'@(dident' :: Text
    dident',_,_) zs :: [Block]
    zs]
                  | Text -> Bool
    T.null Text
    dident Bool -> Bool -> Bool
    || Text -> Bool
    T.null Text
    dident' Bool -> Bool -> Bool
    || Text
    dident Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    dident'
                  -> Attr -> [Block] -> Block
    Div (Attr -> Attr -> Attr
    combineAttr Attr
    divattr' Attr
    divattr) [Block]
    zs Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    rest
                _ -> Attr -> [Block] -> Block
    Div Attr
    divattr [Block]
    inner Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    rest
      go (Div attr :: Attr
    attr xs :: [Block]
    xs : rest :: [Block]
    rest) = do
        [Block]
    xs' <- [Block] -> State (Maybe Int, [Int]) [Block]
    go [Block]
    xs
        [Block]
    rest' <- [Block] -> State (Maybe Int, [Int]) [Block]
    go [Block]
    rest
        [Block] -> State (Maybe Int, [Int]) [Block]
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Block] -> State (Maybe Int, [Int]) [Block])
    -> [Block] -> State (Maybe Int, [Int]) [Block]
    forall a b. (a -> b) -> a -> b
    $ Attr -> [Block] -> Block
    Div Attr
    attr [Block]
    xs' Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    rest'
      go (x :: Block
    x:xs :: [Block]
    xs) = (Block
    x Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    :) ([Block] -> [Block])
    -> State (Maybe Int, [Int]) [Block]
    -> State (Maybe Int, [Int]) [Block]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [Block] -> State (Maybe Int, [Int]) [Block]
    go [Block]
    xs
      go [] = [Block] -> State (Maybe Int, [Int]) [Block]
    forall (m :: * -> *) a. Monad m => a -> m a
    return []

      combineAttr :: Attr -> Attr -> Attr
      combineAttr :: Attr -> Attr -> Attr
    combineAttr (id1 :: Text
    id1, classes1 :: [Text]
    classes1, kvs1 :: [(Text, Text)]
    kvs1) (id2 :: Text
    id2, classes2 :: [Text]
    classes2, kvs2 :: [(Text, Text)]
    kvs2) =
        (if Text -> Bool
    T.null Text
    id1 then Text
    id2 else Text
    id1,
         [Text] -> [Text]
    forall a. Ord a => [a] -> [a]
    ordNub ([Text]
    classes1 [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [Text]
    classes2),
         ((Text, Text) -> [(Text, Text)] -> [(Text, Text)])
    -> [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (\(k :: Text
    k,v :: Text
    v) kvs :: [(Text, Text)]
    kvs -> case Text -> [(Text, Text)] -> Maybe Text
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup Text
    k [(Text, Text)]
    kvs of
                                 Nothing -> (Text
    k,Text
    v)(Text, Text) -> [(Text, Text)] -> [(Text, Text)]
    forall a. a -> [a] -> [a]
    :[(Text, Text)]
    kvs
                                 Just _  -> [(Text, Text)]
    kvs) [(Text, Text)]
    forall a. Monoid a => a
    mempty ([(Text, Text)]
    kvs1 [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
    forall a. [a] -> [a] -> [a]
    ++ [(Text, Text)]
    kvs2))

    headerLtEq :: Int -> Block -> Bool
    headerLtEq :: Int -> Block -> Bool
    headerLtEq level :: Int
    level (Header l :: Int
    l _ _)  = Int
    l Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    level
    headerLtEq level :: Int
    level (Div _ (b :: Block
    b:_))   = Int -> Block -> Bool
    headerLtEq Int
    level Block
    b
    headerLtEq _ _                   = Bool
    False

    -- | Generate a unique identifier from a list of inlines.
    -- Second argument is a list of already used identifiers.
    uniqueIdent :: Extensions -> [Inline] -> Set.Set T.Text -> T.Text
    uniqueIdent :: Extensions -> [Inline] -> Set Text -> Text
    uniqueIdent exts :: Extensions
    exts title' :: [Inline]
    title' usedIdents :: Set Text
    usedIdents =
      if Text
    baseIdent Text -> Set Text -> Bool
    forall a. Ord a => a -> Set a -> Bool
    `Set.member` Set Text
    usedIdents
         then case (Int -> Bool) -> [Int] -> Maybe Int
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find (\x :: Int
    x -> Int -> Text
    forall a. Show a => a -> Text
    numIdent Int
    x Text -> Set Text -> Bool
    forall a. Ord a => a -> Set a -> Bool
    `Set.notMember` Set Text
    usedIdents)
                   ([1..60000] :: [Int]) of
                Just x :: Int
    x  -> Int -> Text
    forall a. Show a => a -> Text
    numIdent Int
    x
                Nothing -> Text
    baseIdent
                -- if we have more than 60,000, allow repeats
         else Text
    baseIdent
      where
        baseIdent :: Text
    baseIdent = case Extensions -> [Inline] -> Text
    inlineListToIdentifier Extensions
    exts [Inline]
    title' of
                         "" -> "section"
                         x :: Text
    x  -> Text
    x
        numIdent :: a -> Text
    numIdent n :: a
    n = Text
    baseIdent Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> "-" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> a -> Text
    forall a. Show a => a -> Text
    tshow a
    n

    -- | True if block is a Header block.
    isHeaderBlock :: Block -> Bool
    isHeaderBlock :: Block -> Bool
    isHeaderBlock Header{} = Bool
    True
    isHeaderBlock _        = Bool
    False

    -- | Shift header levels up or down.
    headerShift :: Int -> Pandoc -> Pandoc
    headerShift :: Int -> Pandoc -> Pandoc
    headerShift n :: Int
    n (Pandoc meta :: Meta
    meta (Header m :: Int
    m _ ils :: [Inline]
    ils : bs :: [Block]
    bs))
      | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0
      , Int
    m Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    n Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 0 = Int -> Pandoc -> Pandoc
    headerShift Int
    n (Pandoc -> Pandoc) -> Pandoc -> Pandoc
    forall a b. (a -> b) -> a -> b
    $
                     Inlines -> Pandoc -> Pandoc
    B.setTitle ([Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [Inline]
    ils) (Pandoc -> Pandoc) -> Pandoc -> Pandoc
    forall a b. (a -> b) -> a -> b
    $ Meta -> [Block] -> Pandoc
    Pandoc Meta
    meta [Block]
    bs
    headerShift n :: Int
    n (Pandoc meta :: Meta
    meta bs :: [Block]
    bs) = Meta -> [Block] -> Pandoc
    Pandoc Meta
    meta ((Block -> Block) -> [Block] -> [Block]
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk Block -> Block
    shift [Block]
    bs)

     where
       shift :: Block -> Block
       shift :: Block -> Block
    shift (Header level :: Int
    level attr :: Attr
    attr inner :: [Inline]
    inner)
         | Int
    level Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > 0  = Int -> Attr -> [Inline] -> Block
    Header (Int
    level Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    n) Attr
    attr [Inline]
    inner
         | Bool
    otherwise      = [Inline] -> Block
    Para [Inline]
    inner
       shift x :: Block
    x            = Block
    x

    -- | Remove empty paragraphs.
    stripEmptyParagraphs :: Pandoc -> Pandoc
    stripEmptyParagraphs :: Pandoc -> Pandoc
    stripEmptyParagraphs = ([Block] -> [Block]) -> Pandoc -> Pandoc
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk [Block] -> [Block]
    go
      where go :: [Block] -> [Block]
            go :: [Block] -> [Block]
    go = (Block -> Bool) -> [Block] -> [Block]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool) -> (Block -> Bool) -> Block -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Block -> Bool
    isEmptyParagraph)
            isEmptyParagraph :: Block -> Bool
    isEmptyParagraph (Para []) = Bool
    True
            isEmptyParagraph _         = Bool
    False

    -- | Detect if table rows contain only cells consisting of a single
    -- paragraph that has no @LineBreak@.
    onlySimpleTableCells :: [[TableCell]] -> Bool
    onlySimpleTableCells :: [[[Block]]] -> Bool
    onlySimpleTableCells = ([Block] -> Bool) -> [[Block]] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all [Block] -> Bool
    isSimpleCell ([[Block]] -> Bool)
    -> ([[[Block]]] -> [[Block]]) -> [[[Block]]] -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [[[Block]]] -> [[Block]]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat
      where
        isSimpleCell :: [Block] -> Bool
    isSimpleCell [Plain ils :: [Inline]
    ils] = Bool -> Bool
    not ([Inline] -> Bool
    hasLineBreak [Inline]
    ils)
        isSimpleCell [Para ils :: [Inline]
    ils ] = Bool -> Bool
    not ([Inline] -> Bool
    hasLineBreak [Inline]
    ils)
        isSimpleCell []          = Bool
    True
        isSimpleCell _           = Bool
    False
        hasLineBreak :: [Inline] -> Bool
    hasLineBreak = Any -> Bool
    getAny (Any -> Bool) -> ([Inline] -> Any) -> [Inline] -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Inline -> Any) -> [Inline] -> Any
    forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
    query Inline -> Any
    isLineBreak
        isLineBreak :: Inline -> Any
    isLineBreak LineBreak = Bool -> Any
    Any Bool
    True
        isLineBreak _         = Bool -> Any
    Any Bool
    False

    -- | Detect if a list is tight.
    isTightList :: [[Block]] -> Bool
    isTightList :: [[Block]] -> Bool
    isTightList = ([Block] -> Bool) -> [[Block]] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all (\item :: [Block]
    item -> [Block] -> Bool
    firstIsPlain [Block]
    item Bool -> Bool -> Bool
    || [Block] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Block]
    item)
      where firstIsPlain :: [Block] -> Bool
    firstIsPlain (Plain _ : _) = Bool
    True
            firstIsPlain _             = Bool
    False

    -- | Convert a list item containing tasklist syntax (e.g. @[x]@)
    -- to using @U+2610 BALLOT BOX@ or @U+2612 BALLOT BOX WITH X@.
    taskListItemFromAscii :: Extensions -> [Block] -> [Block]
    taskListItemFromAscii :: Extensions -> [Block] -> [Block]
    taskListItemFromAscii = ([Inline] -> [Inline]) -> Extensions -> [Block] -> [Block]
    handleTaskListItem [Inline] -> [Inline]
    fromMd
      where
        fromMd :: [Inline] -> [Inline]
    fromMd (Str "[" : Space : Str "]" : Space : is :: [Inline]
    is) = Text -> Inline
    Str "☐" Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : Inline
    Space Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline]
    is
        fromMd (Str "[x]"                 : Space : is :: [Inline]
    is) = Text -> Inline
    Str "☒" Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : Inline
    Space Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline]
    is
        fromMd (Str "[X]"                 : Space : is :: [Inline]
    is) = Text -> Inline
    Str "☒" Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : Inline
    Space Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline]
    is
        fromMd is :: [Inline]
    is = [Inline]
    is

    -- | Convert a list item containing text starting with @U+2610 BALLOT BOX@
    -- or @U+2612 BALLOT BOX WITH X@ to tasklist syntax (e.g. @[x]@).
    taskListItemToAscii :: Extensions -> [Block] -> [Block]
    taskListItemToAscii :: Extensions -> [Block] -> [Block]
    taskListItemToAscii = ([Inline] -> [Inline]) -> Extensions -> [Block] -> [Block]
    handleTaskListItem [Inline] -> [Inline]
    toMd
      where
        toMd :: [Inline] -> [Inline]
    toMd (Str "☐" : Space : is :: [Inline]
    is) = Text -> Inline
    rawMd "[ ]" Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : Inline
    Space Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline]
    is
        toMd (Str "☒" : Space : is :: [Inline]
    is) = Text -> Inline
    rawMd "[x]" Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : Inline
    Space Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline]
    is
        toMd is :: [Inline]
    is = [Inline]
    is
        rawMd :: Text -> Inline
    rawMd = Format -> Text -> Inline
    RawInline (Text -> Format
    Format "markdown")

    handleTaskListItem :: ([Inline] -> [Inline]) -> Extensions -> [Block] -> [Block]
    handleTaskListItem :: ([Inline] -> [Inline]) -> Extensions -> [Block] -> [Block]
    handleTaskListItem handleInlines :: [Inline] -> [Inline]
    handleInlines exts :: Extensions
    exts bls :: [Block]
    bls =
      if Extension
    Ext_task_lists Extension -> Extensions -> Bool
    `extensionEnabled` Extensions
    exts
      then [Block] -> [Block]
    handleItem [Block]
    bls
      else [Block]
    bls
      where
        handleItem :: [Block] -> [Block]
    handleItem (Plain is :: [Inline]
    is : bs :: [Block]
    bs) = [Inline] -> Block
    Plain ([Inline] -> [Inline]
    handleInlines [Inline]
    is) Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    bs
        handleItem (Para is :: [Inline]
    is  : bs :: [Block]
    bs) = [Inline] -> Block
    Para  ([Inline] -> [Inline]
    handleInlines [Inline]
    is) Block -> [Block] -> [Block]
    forall a. a -> [a] -> [a]
    : [Block]
    bs
        handleItem bs :: [Block]
    bs = [Block]
    bs

    -- | Set a field of a 'Meta' object.  If the field already has a value,
    -- convert it into a list with the new value appended to the old value(s).
    addMetaField :: ToMetaValue a
                 => T.Text
                 -> a
                 -> Meta
                 -> Meta
    addMetaField :: Text -> a -> Meta -> Meta
    addMetaField key :: Text
    key val :: a
    val (Meta meta :: Map Text MetaValue
    meta) =
      Map Text MetaValue -> Meta
    Meta (Map Text MetaValue -> Meta) -> Map Text MetaValue -> Meta
    forall a b. (a -> b) -> a -> b
    $ (MetaValue -> MetaValue -> MetaValue)
    -> Text -> MetaValue -> Map Text MetaValue -> Map Text MetaValue
    forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
    M.insertWith MetaValue -> MetaValue -> MetaValue
    combine Text
    key (a -> MetaValue
    forall a. ToMetaValue a => a -> MetaValue
    toMetaValue a
    val) Map Text MetaValue
    meta
      where combine :: MetaValue -> MetaValue -> MetaValue
    combine newval :: MetaValue
    newval (MetaList xs :: [MetaValue]
    xs) = [MetaValue] -> MetaValue
    MetaList ([MetaValue]
    xs [MetaValue] -> [MetaValue] -> [MetaValue]
    forall a. [a] -> [a] -> [a]
    ++ MetaValue -> [MetaValue]
    tolist MetaValue
    newval)
            combine newval :: MetaValue
    newval x :: MetaValue
    x             = [MetaValue] -> MetaValue
    MetaList [MetaValue
    x, MetaValue
    newval]
            tolist :: MetaValue -> [MetaValue]
    tolist (MetaList ys :: [MetaValue]
    ys) = [MetaValue]
    ys
            tolist y :: MetaValue
    y             = [MetaValue
    y]

    -- | Create 'Meta' from old-style title, authors, date.  This is
    -- provided to ease the transition from the old API.
    makeMeta :: [Inline] -> [[Inline]] -> [Inline] -> Meta
    makeMeta :: [Inline] -> [[Inline]] -> [Inline] -> Meta
    makeMeta title :: [Inline]
    title authors :: [[Inline]]
    authors date :: [Inline]
    date =
          Text -> Inlines -> Meta -> Meta
    forall a. ToMetaValue a => Text -> a -> Meta -> Meta
    addMetaField "title" ([Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [Inline]
    title)
        (Meta -> Meta) -> Meta -> Meta
    forall a b. (a -> b) -> a -> b
    $ Text -> [Inlines] -> Meta -> Meta
    forall a. ToMetaValue a => Text -> a -> Meta -> Meta
    addMetaField "author" (([Inline] -> Inlines) -> [[Inline]] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [[Inline]]
    authors)
        (Meta -> Meta) -> Meta -> Meta
    forall a b. (a -> b) -> a -> b
    $ Text -> Inlines -> Meta -> Meta
    forall a. ToMetaValue a => Text -> a -> Meta -> Meta
    addMetaField "date" ([Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [Inline]
    date) Meta
    nullMeta

    -- | Remove soft breaks between East Asian characters.
    eastAsianLineBreakFilter :: Pandoc -> Pandoc
    eastAsianLineBreakFilter :: Pandoc -> Pandoc
    eastAsianLineBreakFilter = ([Inline] -> [Inline]) -> Pandoc -> Pandoc
    forall a b. (Data a, Data b) => (a -> a) -> b -> b
    bottomUp [Inline] -> [Inline]
    go
      where go :: [Inline] -> [Inline]
    go (x :: Inline
    x:SoftBreak:y :: Inline
    y:zs :: [Inline]
    zs)
              | Just (_, b :: Char
    b) <- Text -> Maybe (Text, Char)
    T.unsnoc (Text -> Maybe (Text, Char)) -> Text -> Maybe (Text, Char)
    forall a b. (a -> b) -> a -> b
    $ Inline -> Text
    forall a. Walkable Inline a => a -> Text
    stringify Inline
    x
              , Just (c :: Char
    c, _) <- Text -> Maybe (Char, Text)
    T.uncons (Text -> Maybe (Char, Text)) -> Text -> Maybe (Char, Text)
    forall a b. (a -> b) -> a -> b
    $ Inline -> Text
    forall a. Walkable Inline a => a -> Text
    stringify Inline
    y
              , Char -> Int
    charWidth Char
    b Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 2
              , Char -> Int
    charWidth Char
    c Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == 2
              = Inline
    xInline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :Inline
    yInline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :[Inline]
    zs
              | Bool
    otherwise
              = Inline
    xInline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :Inline
    SoftBreakInline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :Inline
    yInline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :[Inline]
    zs
            go xs :: [Inline]
    xs
              = [Inline]
    xs

    -- | Builder for underline.
    -- This probably belongs in Builder.hs in pandoc-types.
    -- Will be replaced once Underline is an element.
    underlineSpan :: Inlines -> Inlines
    underlineSpan :: Inlines -> Inlines
    underlineSpan = Attr -> Inlines -> Inlines
    B.spanWith ("", ["underline"], [])

    -- | Set of HTML elements that are represented as Span with a class equal as
    -- the element tag itself.
    htmlSpanLikeElements :: Set.Set T.Text
    htmlSpanLikeElements :: Set Text
    htmlSpanLikeElements = [Text] -> Set Text
    forall a. Ord a => [a] -> Set a
    Set.fromList ["kbd", "mark", "dfn"]

    -- | Returns the first sentence in a list of inlines, and the rest.
    breakSentence :: [Inline] -> ([Inline], [Inline])
    breakSentence :: [Inline] -> ([Inline], [Inline])
    breakSentence [] = ([],[])
    breakSentence xs :: [Inline]
    xs =
      let isSentenceEndInline :: Inline -> Bool
    isSentenceEndInline (Str ys :: Text
    ys)
            | Just (_, c :: Char
    c) <- Text -> Maybe (Text, Char)
    T.unsnoc Text
    ys = Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '.' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '?'
          isSentenceEndInline LineBreak  = Bool
    True
          isSentenceEndInline _          = Bool
    False
          (as :: [Inline]
    as, bs :: [Inline]
    bs) = (Inline -> Bool) -> [Inline] -> ([Inline], [Inline])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    break Inline -> Bool
    isSentenceEndInline [Inline]
    xs
      in  case [Inline]
    bs of
            []             -> ([Inline]
    as, [])
            [c :: Inline
    c]            -> ([Inline]
    as [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Inline
    c], [])
            (c :: Inline
    c:Space:cs :: [Inline]
    cs)   -> ([Inline]
    as [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Inline
    c], [Inline]
    cs)
            (c :: Inline
    c:SoftBreak:cs :: [Inline]
    cs) -> ([Inline]
    as [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Inline
    c], [Inline]
    cs)
            (Str ".":Str s :: Text
    s@(Text -> Maybe (Char, Text)
    T.uncons -> Just (')',_)):cs :: [Inline]
    cs)
              -> ([Inline]
    as [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Text -> Inline
    Str ".", Text -> Inline
    Str Text
    s], [Inline]
    cs)
            (x :: Inline
    x@(Str (Text -> Text -> Maybe Text
    T.stripPrefix ".)" -> Just _)):cs :: [Inline]
    cs) -> ([Inline]
    as [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Inline
    x], [Inline]
    cs)
            (LineBreak:x :: Inline
    x@(Str (Text -> Maybe (Char, Text)
    T.uncons -> Just ('.',_))):cs :: [Inline]
    cs) -> ([Inline]
    as [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++[Inline
    LineBreak], Inline
    xInline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :[Inline]
    cs)
            (c :: Inline
    c:cs :: [Inline]
    cs)         -> ([Inline]
    as [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Inline
    c] [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Inline]
    ds, [Inline]
    es)
              where (ds :: [Inline]
    ds, es :: [Inline]
    es) = [Inline] -> ([Inline], [Inline])
    breakSentence [Inline]
    cs

    -- | Split a list of inlines into sentences.
    splitSentences :: [Inline] -> [[Inline]]
    splitSentences :: [Inline] -> [[Inline]]
    splitSentences xs :: [Inline]
    xs =
      let (sent :: [Inline]
    sent, rest :: [Inline]
    rest) = [Inline] -> ([Inline], [Inline])
    breakSentence [Inline]
    xs
      in  if [Inline] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Inline]
    rest then [[Inline]
    sent] else [Inline]
    sent [Inline] -> [[Inline]] -> [[Inline]]
    forall a. a -> [a] -> [a]
    : [Inline] -> [[Inline]]
    splitSentences [Inline]
    rest

    -- | Process ipynb output cells.  If mode is Nothing,
    -- remove all output.  If mode is Just format, select
    -- best output for the format.  If format is not ipynb,
    -- strip out ANSI escape sequences from CodeBlocks (see #5633).
    filterIpynbOutput :: Maybe Format -> Pandoc -> Pandoc
    filterIpynbOutput :: Maybe Format -> Pandoc -> Pandoc
    filterIpynbOutput mode :: Maybe Format
    mode = (Block -> Block) -> Pandoc -> Pandoc
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk Block -> Block
    go
      where go :: Block -> Block
    go (Div (ident :: Text
    ident, "output":os :: [Text]
    os, kvs :: [(Text, Text)]
    kvs) bs :: [Block]
    bs) =
              case Maybe Format
    mode of
                Nothing  -> Attr -> [Block] -> Block
    Div (Text
    ident, "output"Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    os, [(Text, Text)]
    kvs) []
                -- "best" for ipynb includes all formats:
                Just fmt :: Format
    fmt
                  | Format
    fmt Format -> Format -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Format
    Format "ipynb"
                              -> Attr -> [Block] -> Block
    Div (Text
    ident, "output"Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    os, [(Text, Text)]
    kvs) [Block]
    bs
                  | Bool
    otherwise -> Attr -> [Block] -> Block
    Div (Text
    ident, "output"Text -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    os, [(Text, Text)]
    kvs) ([Block] -> Block) -> [Block] -> Block
    forall a b. (a -> b) -> a -> b
    $
                                  (Block -> Block) -> [Block] -> [Block]
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk Block -> Block
    removeANSI ([Block] -> [Block]) -> [Block] -> [Block]
    forall a b. (a -> b) -> a -> b
    $
                                  Int -> [Block] -> [Block]
    forall a. Int -> [a] -> [a]
    take 1 ([Block] -> [Block]) -> [Block] -> [Block]
    forall a b. (a -> b) -> a -> b
    $ (Block -> Int) -> [Block] -> [Block]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn Block -> Int
    rank [Block]
    bs
                     where
                      rank :: Block -> Int
    rank (RawBlock (Format "html") _)
                        | Format
    fmt Format -> Format -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Format
    Format "html" = 1 :: Int
                        | Format
    fmt Format -> Format -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Format
    Format "markdown" = 2
                        | Bool
    otherwise = 3
                      rank (RawBlock (Format "latex") _)
                        | Format
    fmt Format -> Format -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Format
    Format "latex" = 1
                        | Format
    fmt Format -> Format -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Format
    Format "markdown" = 2
                        | Bool
    otherwise = 3
                      rank (RawBlock f :: Format
    f _)
                        | Format
    fmt Format -> Format -> Bool
    forall a. Eq a => a -> a -> Bool
    == Format
    f = 1
                        | Bool
    otherwise = 3
                      rank (Para [Image{}]) = 1
                      rank _ = 2
                      removeANSI :: Block -> Block
    removeANSI (CodeBlock attr :: Attr
    attr code :: Text
    code) =
                        Attr -> Text -> Block
    CodeBlock Attr
    attr (Text -> Text
    removeANSIEscapes Text
    code)
                      removeANSI x :: Block
    x = Block
    x
                      removeANSIEscapes :: Text -> Text
    removeANSIEscapes t :: Text
    t
                        | Just cs :: Text
    cs <- Text -> Text -> Maybe Text
    T.stripPrefix "\x1b[" Text
    t =
                            Text -> Text
    removeANSIEscapes (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Int -> Text -> Text
    T.drop 1 (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ (Char -> Bool) -> Text -> Text
    T.dropWhile (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /='m') Text
    cs
                        | Just (c :: Char
    c, cs :: Text
    cs) <- Text -> Maybe (Char, Text)
    T.uncons Text
    t = Char -> Text -> Text
    T.cons Char
    c (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text -> Text
    removeANSIEscapes Text
    cs
                        | Bool
    otherwise = ""
            go x :: Block
    x = Block
    x

    --
    -- TagSoup HTML handling
    --

    -- | Render HTML tags.
    renderTags' :: [Tag T.Text] -> T.Text
    renderTags' :: [Tag Text] -> Text
    renderTags' = RenderOptions Text -> [Tag Text] -> Text
    forall str. StringLike str => RenderOptions str -> [Tag str] -> str
    renderTagsOptions
                   RenderOptions Text
    forall str. StringLike str => RenderOptions str
    renderOptions{ optMinimize :: Text -> Bool
    optMinimize = [Text] -> Text -> Bool
    forall (t :: * -> *). Foldable t => t Text -> Text -> Bool
    matchTags ["hr", "br", "img",
                                                           "meta", "link"]
                                , optRawTag :: Text -> Bool
    optRawTag   = [Text] -> Text -> Bool
    forall (t :: * -> *). Foldable t => t Text -> Text -> Bool
    matchTags ["script", "style"] }
                  where matchTags :: t Text -> Text -> Bool
    matchTags tags :: t Text
    tags = (Text -> t Text -> Bool) -> t Text -> Text -> Bool
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Text -> t Text -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    elem t Text
    tags (Text -> Bool) -> (Text -> Text) -> Text -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.toLower

    --
    -- File handling
    --

    -- | Perform an IO action in a directory, returning to starting directory.
    inDirectory :: FilePath -> IO a -> IO a
    inDirectory :: String -> IO a -> IO a
    inDirectory path :: String
    path action :: IO a
    action = IO String -> (String -> IO ()) -> (String -> IO a) -> IO a
    forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
    E.bracket
                                 IO String
    getCurrentDirectory
                                 String -> IO ()
    setCurrentDirectory
                                 (IO a -> String -> IO a
    forall a b. a -> b -> a
    const (IO a -> String -> IO a) -> IO a -> String -> IO a
    forall a b. (a -> b) -> a -> b
    $ String -> IO ()
    setCurrentDirectory String
    path IO () -> IO a -> IO a
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> IO a
    action)

    --
    -- Error reporting
    --

    mapLeft :: (a -> b) -> Either a c -> Either b c
    mapLeft :: (a -> b) -> Either a c -> Either b c
    mapLeft = (a -> b) -> Either a c -> Either b c
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    Bifunctor.first

    -- | Remove intermediate "." and ".." directories from a path.
    --
    -- > collapseFilePath "./foo" == "foo"
    -- > collapseFilePath "/bar/../baz" == "/baz"
    -- > collapseFilePath "/../baz" == "/../baz"
    -- > collapseFilePath "parent/foo/baz/../bar" ==  "parent/foo/bar"
    -- > collapseFilePath "parent/foo/baz/../../bar" ==  "parent/bar"
    -- > collapseFilePath "parent/foo/.." ==  "parent"
    -- > collapseFilePath "/parent/foo/../../bar" ==  "/bar"
    collapseFilePath :: FilePath -> FilePath
    collapseFilePath :: String -> String
    collapseFilePath = [String] -> String
    Posix.joinPath ([String] -> String) -> (String -> [String]) -> String -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [String] -> [String]
    forall a. [a] -> [a]
    reverse ([String] -> [String])
    -> (String -> [String]) -> String -> [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([String] -> String -> [String])
    -> [String] -> [String] -> [String]
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl [String] -> String -> [String]
    go [] ([String] -> [String])
    -> (String -> [String]) -> String -> [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> [String]
    splitDirectories
      where
        go :: [String] -> String -> [String]
    go rs :: [String]
    rs "." = [String]
    rs
        go r :: [String]
    r@(p :: String
    p:rs :: [String]
    rs) ".." = case String
    p of
                                ".."                              -> ".."String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    :[String]
    r
                                (String -> Maybe Bool
    checkPathSeperator -> Just True) -> ".."String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    :[String]
    r
                                _                                 -> [String]
    rs
        go _ (String -> Maybe Bool
    checkPathSeperator -> Just True) = [[Char
    Posix.pathSeparator]]
        go rs :: [String]
    rs x :: String
    x = String
    xString -> [String] -> [String]
    forall a. a -> [a] -> [a]
    :[String]
    rs
        isSingleton :: [a] -> Maybe a
    isSingleton []  = Maybe a
    forall a. Maybe a
    Nothing
        isSingleton [x :: a
    x] = a -> Maybe a
    forall a. a -> Maybe a
    Just a
    x
        isSingleton _   = Maybe a
    forall a. Maybe a
    Nothing
        checkPathSeperator :: String -> Maybe Bool
    checkPathSeperator = (Char -> Bool) -> Maybe Char -> Maybe Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Char -> Bool
    isPathSeparator (Maybe Char -> Maybe Bool)
    -> (String -> Maybe Char) -> String -> Maybe Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Maybe Char
    forall a. [a] -> Maybe a
    isSingleton

    -- Convert the path part of a file: URI to a regular path.
    -- On windows, @/c:/foo@ should be @c:/foo@.
    -- On linux, @/foo@ should be @/foo@.
    uriPathToPath :: T.Text -> FilePath
    uriPathToPath :: Text -> String
    uriPathToPath (Text -> String
    T.unpack -> String
    path) =
    #ifdef _WINDOWS
      case path of
        '/':ps -> ps
        ps     -> ps
    #else
      String
    path
    #endif

    --
    -- File selection from the archive
    --
    filteredFilesFromArchive :: Archive -> (FilePath -> Bool) -> [(FilePath, BL.ByteString)]
    filteredFilesFromArchive :: Archive -> (String -> Bool) -> [(String, ByteString)]
    filteredFilesFromArchive zf :: Archive
    zf f :: String -> Bool
    f =
      (String -> Maybe (String, ByteString))
    -> [String] -> [(String, ByteString)]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe (Archive -> String -> Maybe (String, ByteString)
    fileAndBinary Archive
    zf) ((String -> Bool) -> [String] -> [String]
    forall a. (a -> Bool) -> [a] -> [a]
    filter String -> Bool
    f (Archive -> [String]
    filesInArchive Archive
    zf))
      where
        fileAndBinary :: Archive -> FilePath -> Maybe (FilePath, BL.ByteString)
        fileAndBinary :: Archive -> String -> Maybe (String, ByteString)
    fileAndBinary a :: Archive
    a fp :: String
    fp = String -> Archive -> Maybe Entry
    findEntryByPath String
    fp Archive
    a Maybe Entry
    -> (Entry -> Maybe (String, ByteString))
    -> Maybe (String, ByteString)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \e :: Entry
    e -> (String, ByteString) -> Maybe (String, ByteString)
    forall a. a -> Maybe a
    Just (String
    fp, Entry -> ByteString
    fromEntry Entry
    e)

    --
    -- IANA URIs
    --

    -- | Schemes from http://www.iana.org/assignments/uri-schemes.html plus
    -- the unofficial schemes doi, javascript, isbn, pmid.
    schemes :: Set.Set T.Text
    schemes :: Set Text
    schemes = [Text] -> Set Text
    forall a. Ord a => [a] -> Set a
    Set.fromList
      -- Official IANA schemes
      [ "aaa", "aaas", "about", "acap", "acct", "acr", "adiumxtra", "afp", "afs"
      , "aim", "appdata", "apt", "attachment", "aw", "barion", "beshare", "bitcoin"
      , "blob", "bolo", "browserext", "callto", "cap", "chrome", "chrome-extension"
      , "cid", "coap", "coaps", "com-eventbrite-attendee", "content", "crid", "cvs"
      , "data", "dav", "dict", "dis", "dlna-playcontainer", "dlna-playsingle"
      , "dns", "dntp", "dtn", "dvb", "ed2k", "example", "facetime", "fax", "feed"
      , "feedready", "file", "filesystem", "finger", "fish", "ftp", "geo", "gg"
      , "git", "gizmoproject", "go", "gopher", "graph", "gtalk", "h323", "ham"
      , "hcp", "http", "https", "hxxp", "hxxps", "hydrazone", "iax", "icap", "icon"
      , "im", "imap", "info", "iotdisco", "ipn", "ipp", "ipps", "irc", "irc6"
      , "ircs", "iris", "iris.beep", "iris.lwz", "iris.xpc", "iris.xpcs"
      , "isostore", "itms", "jabber", "jar", "jms", "keyparc", "lastfm", "ldap"
      , "ldaps", "lvlt", "magnet", "mailserver", "mailto", "maps", "market"
      , "message", "mid", "mms", "modem", "mongodb", "moz", "ms-access"
      , "ms-browser-extension", "ms-drive-to", "ms-enrollment", "ms-excel"
      , "ms-gamebarservices", "ms-getoffice", "ms-help", "ms-infopath"
      , "ms-media-stream-id", "ms-officeapp", "ms-project", "ms-powerpoint"
      , "ms-publisher", "ms-search-repair", "ms-secondary-screen-controller"
      , "ms-secondary-screen-setup", "ms-settings", "ms-settings-airplanemode"
      , "ms-settings-bluetooth", "ms-settings-camera", "ms-settings-cellular"
      , "ms-settings-cloudstorage", "ms-settings-connectabledevices"
      , "ms-settings-displays-topology", "ms-settings-emailandaccounts"
      , "ms-settings-language", "ms-settings-location", "ms-settings-lock"
      , "ms-settings-nfctransactions", "ms-settings-notifications"
      , "ms-settings-power", "ms-settings-privacy", "ms-settings-proximity"
      , "ms-settings-screenrotation", "ms-settings-wifi", "ms-settings-workplace"
      , "ms-spd", "ms-sttoverlay", "ms-transit-to", "ms-virtualtouchpad"
      , "ms-visio", "ms-walk-to", "ms-whiteboard", "ms-whiteboard-cmd", "ms-word"
      , "msnim", "msrp", "msrps", "mtqp", "mumble", "mupdate", "mvn", "news", "nfs"
      , "ni", "nih", "nntp", "notes", "ocf", "oid", "onenote", "onenote-cmd"
      , "opaquelocktoken", "pack", "palm", "paparazzi", "pkcs11", "platform", "pop"
      , "pres", "prospero", "proxy", "pwid", "psyc", "qb", "query", "redis"
      , "rediss", "reload", "res", "resource", "rmi", "rsync", "rtmfp", "rtmp"
      , "rtsp", "rtsps", "rtspu", "secondlife", "service", "session", "sftp", "sgn"
      , "shttp", "sieve", "sip", "sips", "skype", "smb", "sms", "smtp", "snews"
      , "snmp", "soap.beep", "soap.beeps", "soldat", "spotify", "ssh", "steam"
      , "stun", "stuns", "submit", "svn", "tag", "teamspeak", "tel", "teliaeid"
      , "telnet", "tftp", "things", "thismessage", "tip", "tn3270", "tool", "turn"
      , "turns", "tv", "udp", "unreal", "urn", "ut2004", "v-event", "vemmi"
      , "ventrilo", "videotex", "vnc", "view-source", "wais", "webcal", "wpid"
      , "ws", "wss", "wtai", "wyciwyg", "xcon", "xcon-userid", "xfire"
      , "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r"
      , "z39.50s"
      -- Unofficial schemes
      , "doi", "isbn", "javascript", "pmid"
      ]

    -- | Check if the string is a valid URL with a IANA or frequently used but
    -- unofficial scheme (see @schemes@).
    isURI :: T.Text -> Bool
    isURI :: Text -> Bool
    isURI = Bool -> (URI -> Bool) -> Maybe URI -> Bool
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Bool
    False URI -> Bool
    hasKnownScheme (Maybe URI -> Bool) -> (Text -> Maybe URI) -> Text -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Maybe URI
    parseURI (String -> Maybe URI) -> (Text -> String) -> Text -> Maybe URI
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack
      where
        hasKnownScheme :: URI -> Bool
    hasKnownScheme = (Text -> Set Text -> Bool
    forall a. Ord a => a -> Set a -> Bool
    `Set.member` Set Text
    schemes) (Text -> Bool) -> (URI -> Text) -> URI -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    T.toLower (Text -> Text) -> (URI -> Text) -> URI -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                         (Char -> Bool) -> Text -> Text
    T.filter (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= ':') (Text -> Text) -> (URI -> Text) -> URI -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Text
    T.pack (String -> Text) -> (URI -> String) -> URI -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . URI -> String
    uriScheme

    ---
    --- Squash blocks into inlines
    ---

    blockToInlines :: Block -> Inlines
    blockToInlines :: Block -> Inlines
    blockToInlines (Plain ils :: [Inline]
    ils) = [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [Inline]
    ils
    blockToInlines (Para ils :: [Inline]
    ils) = [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [Inline]
    ils
    blockToInlines (LineBlock lns :: [[Inline]]
    lns) = [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList ([Inline] -> Inlines) -> [Inline] -> Inlines
    forall a b. (a -> b) -> a -> b
    $ [[Inline]] -> [Inline]
    combineLines [[Inline]]
    lns
    blockToInlines (CodeBlock attr :: Attr
    attr str :: Text
    str) = Attr -> Text -> Inlines
    B.codeWith Attr
    attr Text
    str
    blockToInlines (RawBlock (Format fmt :: Text
    fmt) str :: Text
    str) = Text -> Text -> Inlines
    B.rawInline Text
    fmt Text
    str
    blockToInlines (BlockQuote blks :: [Block]
    blks) = [Block] -> Inlines
    blocksToInlines' [Block]
    blks
    blockToInlines (OrderedList _ blkslst :: [[Block]]
    blkslst) =
      [Inlines] -> Inlines
    forall a. Monoid a => [a] -> a
    mconcat ([Inlines] -> Inlines) -> [Inlines] -> Inlines
    forall a b. (a -> b) -> a -> b
    $ ([Block] -> Inlines) -> [[Block]] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map [Block] -> Inlines
    blocksToInlines' [[Block]]
    blkslst
    blockToInlines (BulletList blkslst :: [[Block]]
    blkslst) =
      [Inlines] -> Inlines
    forall a. Monoid a => [a] -> a
    mconcat ([Inlines] -> Inlines) -> [Inlines] -> Inlines
    forall a b. (a -> b) -> a -> b
    $ ([Block] -> Inlines) -> [[Block]] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map [Block] -> Inlines
    blocksToInlines' [[Block]]
    blkslst
    blockToInlines (DefinitionList pairslst :: [([Inline], [[Block]])]
    pairslst) =
      [Inlines] -> Inlines
    forall a. Monoid a => [a] -> a
    mconcat ([Inlines] -> Inlines) -> [Inlines] -> Inlines
    forall a b. (a -> b) -> a -> b
    $ (([Inline], [[Block]]) -> Inlines)
    -> [([Inline], [[Block]])] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map ([Inline], [[Block]]) -> Inlines
    f [([Inline], [[Block]])]
    pairslst
      where
        f :: ([Inline], [[Block]]) -> Inlines
    f (ils :: [Inline]
    ils, blkslst :: [[Block]]
    blkslst) = [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [Inline]
    ils Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <> Text -> Inlines
    B.str ":" Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <> Inlines
    B.space Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <>
          [Inlines] -> Inlines
    forall a. Monoid a => [a] -> a
    mconcat (([Block] -> Inlines) -> [[Block]] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map [Block] -> Inlines
    blocksToInlines' [[Block]]
    blkslst)
    blockToInlines (Header _ _  ils :: [Inline]
    ils) = [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList [Inline]
    ils
    blockToInlines HorizontalRule = Inlines
    forall a. Monoid a => a
    mempty
    blockToInlines (Table _ _ _ headers :: [[Block]]
    headers rows :: [[[Block]]]
    rows) =
      [Inlines] -> Inlines
    forall a. Monoid a => [a] -> a
    mconcat ([Inlines] -> Inlines) -> [Inlines] -> Inlines
    forall a b. (a -> b) -> a -> b
    $ Inlines -> [Inlines] -> [Inlines]
    forall a. a -> [a] -> [a]
    intersperse Inlines
    B.linebreak ([Inlines] -> [Inlines]) -> [Inlines] -> [Inlines]
    forall a b. (a -> b) -> a -> b
    $
        ([[Block]] -> Inlines) -> [[[Block]]] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map ([Inlines] -> Inlines
    forall a. Monoid a => [a] -> a
    mconcat ([Inlines] -> Inlines)
    -> ([[Block]] -> [Inlines]) -> [[Block]] -> Inlines
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Block] -> Inlines) -> [[Block]] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map [Block] -> Inlines
    blocksToInlines') ([[Block]]
    headers[[Block]] -> [[[Block]]] -> [[[Block]]]
    forall a. a -> [a] -> [a]
    :[[[Block]]]
    rows)
    blockToInlines (Div _ blks :: [Block]
    blks) = [Block] -> Inlines
    blocksToInlines' [Block]
    blks
    blockToInlines Null = Inlines
    forall a. Monoid a => a
    mempty

    blocksToInlinesWithSep :: Inlines -> [Block] -> Inlines
    blocksToInlinesWithSep :: Inlines -> [Block] -> Inlines
    blocksToInlinesWithSep sep :: Inlines
    sep =
      [Inlines] -> Inlines
    forall a. Monoid a => [a] -> a
    mconcat ([Inlines] -> Inlines)
    -> ([Block] -> [Inlines]) -> [Block] -> Inlines
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Inlines -> [Inlines] -> [Inlines]
    forall a. a -> [a] -> [a]
    intersperse Inlines
    sep ([Inlines] -> [Inlines])
    -> ([Block] -> [Inlines]) -> [Block] -> [Inlines]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Block -> Inlines) -> [Block] -> [Inlines]
    forall a b. (a -> b) -> [a] -> [b]
    map Block -> Inlines
    blockToInlines

    blocksToInlines' :: [Block] -> Inlines
    blocksToInlines' :: [Block] -> Inlines
    blocksToInlines' = Inlines -> [Block] -> Inlines
    blocksToInlinesWithSep Inlines
    defaultBlocksSeparator

    blocksToInlines :: [Block] -> [Inline]
    blocksToInlines :: [Block] -> [Inline]
    blocksToInlines = Inlines -> [Inline]
    forall a. Many a -> [a]
    B.toList (Inlines -> [Inline])
    -> ([Block] -> Inlines) -> [Block] -> [Inline]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Block] -> Inlines
    blocksToInlines'

    -- | Inline elements used to separate blocks when squashing blocks into
    -- inlines.
    defaultBlocksSeparator :: Inlines
    defaultBlocksSeparator :: Inlines
    defaultBlocksSeparator =
      -- This is used in the pandoc.utils.blocks_to_inlines function. Docs
      -- there should be updated if this is changed.
      Inlines
    B.space Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <> Text -> Inlines
    B.str "¶" Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <> Inlines
    B.space

    --
    -- Safe read
    --

    safeRead :: (MonadPlus m, Read a) => T.Text -> m a
    safeRead :: Text -> m a
    safeRead = String -> m a
    forall (m :: * -> *) a. (MonadPlus m, Read a) => String -> m a
    safeStrRead (String -> m a) -> (Text -> String) -> Text -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack

    safeStrRead :: (MonadPlus m, Read a) => String -> m a
    safeStrRead :: String -> m a
    safeStrRead s :: String
    s = case ReadS a
    forall a. Read a => ReadS a
    reads String
    s of
                      (d :: a
    d,x :: String
    x):_
                        | (Char -> Bool) -> String -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all Char -> Bool
    isSpace String
    x -> a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    d
                      _                 -> m a
    forall (m :: * -> *) a. MonadPlus m => m a
    mzero
    --
    -- User data directory
    --

    -- | Return appropriate user data directory for platform.  We use
    -- XDG_DATA_HOME (or its default value), but fall back to the
    -- legacy user data directory ($HOME/.pandoc on *nix) if this is
    -- missing.
    defaultUserDataDirs :: IO [FilePath]
    defaultUserDataDirs :: IO [String]
    defaultUserDataDirs = IO [String] -> (SomeException -> IO [String]) -> IO [String]
    forall e a. Exception e => IO a -> (e -> IO a) -> IO a
    E.catch (do
      String
    xdgDir <- XdgDirectory -> String -> IO String
    getXdgDirectory XdgDirectory
    XdgData "pandoc"
      String
    legacyDir <- String -> IO String
    getAppUserDataDirectory "pandoc"
      [String] -> IO [String]
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([String] -> IO [String]) -> [String] -> IO [String]
    forall a b. (a -> b) -> a -> b
    $ [String] -> [String]
    forall a. Ord a => [a] -> [a]
    ordNub [String
    xdgDir, String
    legacyDir])
     (\(SomeException
    _ :: E.SomeException) -> [String] -> IO [String]
    forall (m :: * -> *) a. Monad m => a -> m a
    return [])