    {-|
    Module      : Text.Jira.Parser.Core
    Copyright   : © 2019–2023 Albert Krewinkel
    License     : MIT

    Maintainer  : Albert Krewinkel <tarleb@zeitkraut.de>
    Stability   : alpha
    Portability : portable

    Core components of the Jira wiki markup parser.
    -}
    module Text.Jira.Parser.Core
      (
      -- * Jira parser and state
        JiraParser
      , ParserState (..)
      , defaultState
      , parseJira
      , withStateFlag
      -- * String position tracking
      , updateLastStrPos
      , updateLastSpcPos
      , notAfterString
      , afterString
      , afterSpace
      -- * Parsing helpers
      , endOfPara
      , notFollowedBy'
      , many1Till
      , blankline
      , skipSpaces
      , blockNames
      , parameters
      ) where

    import Control.Monad (join, void)
    import Data.Text (Text, pack)
    import Text.Jira.Markup
    import Text.Parsec

    -- | Jira Parsec parser
    type JiraParser = Parsec Text ParserState

    -- | Parser state used to keep track of various parameteres.
    data ParserState = ParserState
      { ParserState -> Bool
    stateInLink      :: Bool            -- ^ whether the parser is within a link
      , ParserState -> Bool
    stateInList      :: Bool            -- ^ whether the parser is within a list
      , ParserState -> Bool
    stateInMarkup    :: Bool            -- ^ whether the parser is within markup
      , ParserState -> Bool
    stateInTable     :: Bool            -- ^ whether the parser is within a table
      , ParserState -> Maybe SourcePos
    stateLastSpcPos  :: Maybe SourcePos -- ^ most recent space char position
      , ParserState -> Maybe SourcePos
    stateLastStrPos  :: Maybe SourcePos -- ^ position at which the last string
                                            --   ended
      }

    -- | Default parser state (i.e., start state)
    defaultState :: ParserState
    defaultState :: ParserState
    defaultState = ParserState
      { stateInLink :: Bool
    stateInLink      = Bool
    False
      , stateInList :: Bool
    stateInList      = Bool
    False
      , stateInMarkup :: Bool
    stateInMarkup    = Bool
    False
      , stateInTable :: Bool
    stateInTable     = Bool
    False
      , stateLastSpcPos :: Maybe SourcePos
    stateLastSpcPos  = Maybe SourcePos
    forall a. Maybe a
    Nothing
      , stateLastStrPos :: Maybe SourcePos
    stateLastStrPos  = Maybe SourcePos
    forall a. Maybe a
    Nothing
      }

    -- | Set a flag in the parser to @True@ before running a parser, then
    -- set the flag's value to @False@.
    withStateFlag :: (Bool -> ParserState -> ParserState)
                  -> JiraParser a
                  -> JiraParser a
    withStateFlag :: forall a.
    (Bool -> ParserState -> ParserState)
    -> JiraParser a -> JiraParser a
    withStateFlag Bool -> ParserState -> ParserState
    flagSetter JiraParser a
    parser = JiraParser a -> JiraParser a
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
    try (JiraParser a -> JiraParser a) -> JiraParser a -> JiraParser a
    forall a b. (a -> b) -> a -> b
    $
      let setFlag :: Bool -> ParsecT s ParserState Identity ()
    setFlag = (ParserState -> ParserState) -> ParsecT s ParserState Identity ()
    forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
    modifyState ((ParserState -> ParserState) -> ParsecT s ParserState Identity ())
    -> (Bool -> ParserState -> ParserState)
    -> Bool
    -> ParsecT s ParserState Identity ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Bool -> ParserState -> ParserState
    flagSetter
      in Bool -> ParsecT Text ParserState Identity ()
    forall {s}. Bool -> ParsecT s ParserState Identity ()
    setFlag Bool
    True ParsecT Text ParserState Identity ()
    -> JiraParser a -> JiraParser a
    forall a b.
    ParsecT Text ParserState Identity a
    -> ParsecT Text ParserState Identity b
    -> ParsecT Text ParserState Identity b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> JiraParser a
    parser JiraParser a
    -> ParsecT Text ParserState Identity () -> JiraParser a
    forall a b.
    ParsecT Text ParserState Identity a
    -> ParsecT Text ParserState Identity b
    -> ParsecT Text ParserState Identity a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Bool -> ParsecT Text ParserState Identity ()
    forall {s}. Bool -> ParsecT s ParserState Identity ()
    setFlag Bool
    False

    -- | Updates the state, marking the current input position as the end of a
    -- string.
    updateLastStrPos :: JiraParser ()
    updateLastStrPos :: ParsecT Text ParserState Identity ()
    updateLastStrPos = do
      pos <- ParsecT Text ParserState Identity SourcePos
    forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
    getPosition
      modifyState $ \ParserState
    st -> ParserState
    st { stateLastStrPos = Just pos }

    -- | Updates the state, marking the current input position as the end of a
    -- string.
    updateLastSpcPos :: JiraParser ()
    updateLastSpcPos :: ParsecT Text ParserState Identity ()
    updateLastSpcPos = do
      pos <- ParsecT Text ParserState Identity SourcePos
    forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
    getPosition
      modifyState $ \ParserState
    st -> ParserState
    st { stateLastSpcPos = Just pos }

    -- | Returns @'True'@ if the current parser position is directly
    -- after a word/string. Returns @'False'@ if the parser is
    -- looking at the first character of the input.
    afterString :: JiraParser Bool
    afterString :: JiraParser Bool
    afterString = do
      curPos <- ParsecT Text ParserState Identity SourcePos
    forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
    getPosition
      prevPos <- stateLastStrPos <$> getState
      return (Just curPos == prevPos)

    -- | Returns true when the current parser position is either at
    -- the beginning of the document or if the preceding characters
    -- did not belong to a string.
    notAfterString :: JiraParser Bool
    notAfterString :: JiraParser Bool
    notAfterString = Bool -> Bool
    not (Bool -> Bool) -> JiraParser Bool -> JiraParser Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> JiraParser Bool
    afterString

    -- | Returns @'True'@ iff the character before the current parser
    -- position was a space.
    afterSpace :: JiraParser Bool
    afterSpace :: JiraParser Bool
    afterSpace = do
      curPos <- ParsecT Text ParserState Identity SourcePos
    forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
    getPosition
      lastSpacePos <- stateLastSpcPos <$> getState
      return (Just curPos == lastSpacePos)

    -- | Parses a string with the given Jira parser.
    parseJira :: JiraParser a -> Text -> Either ParseError a
    parseJira :: forall a. JiraParser a -> Text -> Either ParseError a
    parseJira JiraParser a
    parser = JiraParser a
    -> ParserState -> SourceName -> Text -> Either ParseError a
    forall s t u a.
    Stream s Identity t =>
    Parsec s u a -> u -> SourceName -> s -> Either ParseError a
    runParser JiraParser a
    parser ParserState
    defaultState SourceName
    ""

    -- | Skip zero or more space chars.
    skipSpaces :: JiraParser ()
    skipSpaces :: ParsecT Text ParserState Identity ()
    skipSpaces = ParsecT Text ParserState Identity Char
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m ()
    skipMany (Char -> ParsecT Text ParserState Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    ' ')

    -- | Parses an empty line, i.e., a line with no chars or whitespace only.
    blankline :: JiraParser ()
    blankline :: ParsecT Text ParserState Identity ()
    blankline = ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
    try (ParsecT Text ParserState Identity ()
     -> ParsecT Text ParserState Identity ())
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall a b. (a -> b) -> a -> b
    $ ParsecT Text ParserState Identity ()
    skipSpaces ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall a b.
    ParsecT Text ParserState Identity a
    -> ParsecT Text ParserState Identity b
    -> ParsecT Text ParserState Identity b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> ParsecT Text ParserState Identity Char
    -> ParsecT Text ParserState Identity ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void ParsecT Text ParserState Identity Char
    forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
    newline

    -- | Parses a set of panel parameters
    parameters :: JiraParser (Maybe Text, [Parameter])
    parameters :: JiraParser (Maybe Text, [Parameter])
    parameters = (Maybe Text, [Parameter])
    -> JiraParser (Maybe Text, [Parameter])
    -> JiraParser (Maybe Text, [Parameter])
    forall s (m :: * -> *) t a u.
    Stream s m t =>
    a -> ParsecT s u m a -> ParsecT s u m a
    option (Maybe Text
    forall a. Maybe a
    Nothing, []) (JiraParser (Maybe Text, [Parameter])
     -> JiraParser (Maybe Text, [Parameter]))
    -> JiraParser (Maybe Text, [Parameter])
    -> JiraParser (Maybe Text, [Parameter])
    forall a b. (a -> b) -> a -> b
    $ do
      _      <- Char -> ParsecT Text ParserState Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    ':'
      lang   <- optionMaybe (try language)
      params <- try (Parameter <$> key <*> (char '=' *> value)) `sepBy` pipe
      return (lang, params)
      where
        pipe :: ParsecT Text u Identity Char
    pipe     = Char -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    '|'
        key :: ParsecT Text u Identity Text
    key      = SourceName -> Text
    pack (SourceName -> Text)
    -> ParsecT Text u Identity SourceName
    -> ParsecT Text u Identity Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ParsecT Text u Identity Char -> ParsecT Text u Identity SourceName
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many1 (SourceName -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    SourceName -> ParsecT s u m Char
    noneOf SourceName
    "\"'\t\n\r |{}=")
        value :: ParsecT Text u Identity Text
    value    = SourceName -> Text
    pack (SourceName -> Text)
    -> ParsecT Text u Identity SourceName
    -> ParsecT Text u Identity Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ParsecT Text u Identity Char -> ParsecT Text u Identity SourceName
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many1 (SourceName -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    SourceName -> ParsecT s u m Char
    noneOf SourceName
    "\"'\n\r|{}=")
        language :: ParsecT Text u Identity Text
    language = ParsecT Text u Identity Text
    forall {u}. ParsecT Text u Identity Text
    key ParsecT Text u Identity Text
    -> ParsecT Text u Identity Char -> ParsecT Text u Identity Text
    forall a b.
    ParsecT Text u Identity a
    -> ParsecT Text u Identity b -> ParsecT Text u Identity a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* (ParsecT Text u Identity Char
    forall {u}. ParsecT Text u Identity Char
    pipe ParsecT Text u Identity Char
    -> ParsecT Text u Identity Char -> ParsecT Text u Identity Char
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text u Identity Char -> ParsecT Text u Identity Char
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead (Char -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    '}'))

    -- | Like @manyTill@, but reads at least one item.
    many1Till :: (Show end)
              => JiraParser a
              -> JiraParser end
              -> JiraParser [a]
    many1Till :: forall end a.
    Show end =>
    JiraParser a -> JiraParser end -> JiraParser [a]
    many1Till JiraParser a
    p JiraParser end
    end = do
      JiraParser end -> ParsecT Text ParserState Identity ()
    forall a.
    Show a =>
    JiraParser a -> ParsecT Text ParserState Identity ()
    notFollowedBy' JiraParser end
    end
      first <- JiraParser a
    p
      rest <- manyTill p end
      return (first:rest)

    -- | Succeeds if the parser is looking at the end of a paragraph.
    endOfPara :: JiraParser ()
    endOfPara :: ParsecT Text ParserState Identity ()
    endOfPara = ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u.
    (Stream s m t, Show t) =>
    ParsecT s u m ()
    eof
      ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead ParsecT Text ParserState Identity ()
    blankline
      ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead ParsecT Text ParserState Identity ()
    forall {u}. ParsecT Text u Identity ()
    headerStart
      ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead ParsecT Text ParserState Identity ()
    forall {u}. ParsecT Text u Identity ()
    quoteStart
      ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead ParsecT Text ParserState Identity ()
    horizontalRule
      ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead ParsecT Text ParserState Identity ()
    listItemStart
      ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead ParsecT Text ParserState Identity ()
    tableStart
      ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m a
    lookAhead ParsecT Text ParserState Identity ()
    forall {u}. ParsecT Text u Identity ()
    panelStart
      where
        headerStart :: ParsecT Text u Identity ()
    headerStart    = ParsecT Text u Identity Char -> ParsecT Text u Identity ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ParsecT Text u Identity Char -> ParsecT Text u Identity ())
    -> ParsecT Text u Identity Char -> ParsecT Text u Identity ()
    forall a b. (a -> b) -> a -> b
    $ Char -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    'h' ParsecT Text u Identity Char
    -> ParsecT Text u Identity Char -> ParsecT Text u Identity Char
    forall a b.
    ParsecT Text u Identity a
    -> ParsecT Text u Identity b -> ParsecT Text u Identity b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> SourceName -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    SourceName -> ParsecT s u m Char
    oneOf SourceName
    "123456" ParsecT Text u Identity Char
    -> ParsecT Text u Identity Char -> ParsecT Text u Identity Char
    forall a b.
    ParsecT Text u Identity a
    -> ParsecT Text u Identity b -> ParsecT Text u Identity a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Char -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    '.'
        quoteStart :: ParsecT Text u Identity ()
    quoteStart     = ParsecT Text u Identity SourceName -> ParsecT Text u Identity ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ParsecT Text u Identity SourceName -> ParsecT Text u Identity ())
    -> ParsecT Text u Identity SourceName -> ParsecT Text u Identity ()
    forall a b. (a -> b) -> a -> b
    $ SourceName -> ParsecT Text u Identity SourceName
    forall s (m :: * -> *) u.
    Stream s m Char =>
    SourceName -> ParsecT s u m SourceName
    string SourceName
    "bq."
        listItemStart :: ParsecT Text ParserState Identity ()
    listItemStart  = ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ParsecT Text ParserState Identity SourceName
     -> ParsecT Text ParserState Identity ())
    -> ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity ()
    forall a b. (a -> b) -> a -> b
    $ ParsecT Text ParserState Identity ()
    skipSpaces ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity SourceName
    forall a b.
    ParsecT Text ParserState Identity a
    -> ParsecT Text ParserState Identity b
    -> ParsecT Text ParserState Identity b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> ParsecT Text ParserState Identity Char
    -> ParsecT Text ParserState Identity SourceName
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many1 (SourceName -> ParsecT Text ParserState Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    SourceName -> ParsecT s u m Char
    oneOf SourceName
    "#*-") ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity Char
    -> ParsecT Text ParserState Identity SourceName
    forall a b.
    ParsecT Text ParserState Identity a
    -> ParsecT Text ParserState Identity b
    -> ParsecT Text ParserState Identity a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Char -> ParsecT Text ParserState Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    ' '
        tableStart :: ParsecT Text ParserState Identity ()
    tableStart     = ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ParsecT Text ParserState Identity SourceName
     -> ParsecT Text ParserState Identity ())
    -> ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity ()
    forall a b. (a -> b) -> a -> b
    $ ParsecT Text ParserState Identity ()
    skipSpaces ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity SourceName
    forall a b.
    ParsecT Text ParserState Identity a
    -> ParsecT Text ParserState Identity b
    -> ParsecT Text ParserState Identity b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> ParsecT Text ParserState Identity Char
    -> ParsecT Text ParserState Identity SourceName
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
    many1 (Char -> ParsecT Text ParserState Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    '|')
        panelStart :: ParsecT Text u Identity ()
    panelStart     = ParsecT Text u Identity SourceName -> ParsecT Text u Identity ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ParsecT Text u Identity SourceName -> ParsecT Text u Identity ())
    -> ParsecT Text u Identity SourceName -> ParsecT Text u Identity ()
    forall a b. (a -> b) -> a -> b
    $ Char -> ParsecT Text u Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char Char
    '{' ParsecT Text u Identity Char
    -> ParsecT Text u Identity SourceName
    -> ParsecT Text u Identity SourceName
    forall a b.
    ParsecT Text u Identity a
    -> ParsecT Text u Identity b -> ParsecT Text u Identity b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> [ParsecT Text u Identity SourceName]
    -> ParsecT Text u Identity SourceName
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    [ParsecT s u m a] -> ParsecT s u m a
    choice ((SourceName -> ParsecT Text u Identity SourceName)
    -> [SourceName] -> [ParsecT Text u Identity SourceName]
    forall a b. (a -> b) -> [a] -> [b]
    map (ParsecT Text u Identity SourceName
    -> ParsecT Text u Identity SourceName
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
    try (ParsecT Text u Identity SourceName
     -> ParsecT Text u Identity SourceName)
    -> (SourceName -> ParsecT Text u Identity SourceName)
    -> SourceName
    -> ParsecT Text u Identity SourceName
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SourceName -> ParsecT Text u Identity SourceName
    forall s (m :: * -> *) u.
    Stream s m Char =>
    SourceName -> ParsecT s u m SourceName
    string) [SourceName]
    blockNames)
        horizontalRule :: ParsecT Text ParserState Identity ()
    horizontalRule = ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ParsecT Text ParserState Identity ()
     -> ParsecT Text ParserState Identity ())
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall a b. (a -> b) -> a -> b
    $ ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity SourceName
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
    try (SourceName -> ParsecT Text ParserState Identity SourceName
    forall s (m :: * -> *) u.
    Stream s m Char =>
    SourceName -> ParsecT s u m SourceName
    string SourceName
    "----") ParsecT Text ParserState Identity SourceName
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall a b.
    ParsecT Text ParserState Identity a
    -> ParsecT Text ParserState Identity b
    -> ParsecT Text ParserState Identity b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> ParsecT Text ParserState Identity ()
    blankline

    blockNames :: [String]
    blockNames :: [SourceName]
    blockNames = [SourceName
    "code", SourceName
    "color", SourceName
    "noformat", SourceName
    "panel", SourceName
    "quote"]

    -- | Variant of parsec's @notFollowedBy@ function which properly fails even if
    -- the given parser does not consume any input (like @eof@ does).
    notFollowedBy' :: Show a => JiraParser a -> JiraParser ()
    notFollowedBy' :: forall a.
    Show a =>
    JiraParser a -> ParsecT Text ParserState Identity ()
    notFollowedBy' JiraParser a
    p =
      let failIfSucceeds :: ParsecT Text ParserState Identity (ParsecT Text u Identity a)
    failIfSucceeds = SourceName -> ParsecT Text u Identity a
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    SourceName -> ParsecT s u m a
    unexpected (SourceName -> ParsecT Text u Identity a)
    -> (a -> SourceName) -> a -> ParsecT Text u Identity a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> SourceName
    forall a. Show a => a -> SourceName
    show (a -> ParsecT Text u Identity a)
    -> JiraParser a
    -> ParsecT Text ParserState Identity (ParsecT Text u Identity a)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> JiraParser a -> JiraParser a
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
    try JiraParser a
    p
          unitParser :: ParsecT
      Text ParserState Identity (ParsecT Text ParserState Identity ())
    unitParser = ParsecT Text ParserState Identity ()
    -> ParsecT
         Text ParserState Identity (ParsecT Text ParserState Identity ())
    forall a. a -> ParsecT Text ParserState Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (() -> ParsecT Text ParserState Identity ()
    forall a. a -> ParsecT Text ParserState Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())
      in ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
    try (ParsecT Text ParserState Identity ()
     -> ParsecT Text ParserState Identity ())
    -> ParsecT Text ParserState Identity ()
    -> ParsecT Text ParserState Identity ()
    forall a b. (a -> b) -> a -> b
    $ ParsecT
      Text ParserState Identity (ParsecT Text ParserState Identity ())
    -> ParsecT Text ParserState Identity ()
    forall (m :: * -> *) a. Monad m => m (m a) -> m a
    join (ParsecT
      Text ParserState Identity (ParsecT Text ParserState Identity ())
    forall {u} {a}.
    ParsecT Text ParserState Identity (ParsecT Text u Identity a)
    failIfSucceeds ParsecT
      Text ParserState Identity (ParsecT Text ParserState Identity ())
    -> ParsecT
         Text ParserState Identity (ParsecT Text ParserState Identity ())
    -> ParsecT
         Text ParserState Identity (ParsecT Text ParserState Identity ())
    forall s u (m :: * -> *) a.
    ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
    <|> ParsecT
      Text ParserState Identity (ParsecT Text ParserState Identity ())
    unitParser)