    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE ViewPatterns #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# OPTIONS_GHC -fno-warn-orphans #-}
    -- | This module defines a 'CiteprocOutput' instance for pandoc 'Inlines'.
    module Citeproc.Pandoc
      ()
    where
    import Text.Pandoc.Definition
    import Text.Pandoc.Builder as B
    import Text.Pandoc.Walk
    import qualified Data.Text as T
    import qualified Data.Sequence as Seq
    import Data.Text (Text)
    import Citeproc.Types
    import Citeproc.CaseTransform
    import Control.Monad.Trans.State.Strict as S
    import Control.Monad (unless, when)
    import Data.Functor.Reverse
    import Data.Char (isSpace, isPunctuation, isAlphaNum)

    instance CiteprocOutput Inlines where
      toText :: Inlines -> Text
    toText                = Inlines -> Text
    forall a. Walkable Inline a => a -> Text
    stringify
      fromText :: Text -> Inlines
    fromText Text
    t            = (if Text
    " " Text -> Text -> Bool
    `T.isPrefixOf` Text
    t
                                  then Inlines
    B.space
                                  else Inlines
    forall a. Monoid a => a
    mempty) Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <>
                              Text -> Inlines
    B.text Text
    t Inlines -> Inlines -> Inlines
    forall a. Semigroup a => a -> a -> a
    <> -- B.text eats leading/trailing spaces
                              (if Text
    " " Text -> Text -> Bool
    `T.isSuffixOf` Text
    t
                                  then Inlines
    B.space
                                  else Inlines
    forall a. Monoid a => a
    mempty)
      dropTextWhile :: (Char -> Bool) -> Inlines -> Inlines
    dropTextWhile         = (Char -> Bool) -> Inlines -> Inlines
    dropTextWhile'
      dropTextWhileEnd :: (Char -> Bool) -> Inlines -> Inlines
    dropTextWhileEnd      = (Char -> Bool) -> Inlines -> Inlines
    dropTextWhileEnd'
      addFontVariant :: FontVariant -> Inlines -> Inlines
    addFontVariant FontVariant
    x      =
        case FontVariant
    x of
          FontVariant
    NormalVariant    -> Inlines -> Inlines
    forall a. a -> a
    id
          FontVariant
    SmallCapsVariant -> Inlines -> Inlines
    B.smallcaps
      addFontStyle :: FontStyle -> Inlines -> Inlines
    addFontStyle FontStyle
    x        =
        case FontStyle
    x of
          FontStyle
    NormalFont       -> Inlines -> Inlines
    forall a. a -> a
    id
          FontStyle
    ItalicFont       -> Inlines -> Inlines
    B.emph
          FontStyle
    ObliqueFont      -> Inlines -> Inlines
    B.emph
      addFontWeight :: FontWeight -> Inlines -> Inlines
    addFontWeight FontWeight
    x       =
        case FontWeight
    x of
          FontWeight
    NormalWeight     -> Inlines -> Inlines
    forall a. a -> a
    id
          FontWeight
    LightWeight      -> Inlines -> Inlines
    forall a. a -> a
    id
          FontWeight
    BoldWeight       -> Inlines -> Inlines
    B.strong
      addTextDecoration :: TextDecoration -> Inlines -> Inlines
    addTextDecoration TextDecoration
    x   =
        case TextDecoration
    x of
          TextDecoration
    NoDecoration        -> Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "nodecoration"],[])
          TextDecoration
    UnderlineDecoration -> Inlines -> Inlines
    B.underline
      addVerticalAlign :: VerticalAlign -> Inlines -> Inlines
    addVerticalAlign VerticalAlign
    x    =
        case VerticalAlign
    x of
          VerticalAlign
    BaselineAlign    -> Inlines -> Inlines
    forall a. a -> a
    id
          VerticalAlign
    SubAlign         -> Inlines -> Inlines
    B.subscript
          VerticalAlign
    SupAlign         -> Inlines -> Inlines
    B.superscript
      addTextCase :: Maybe Lang -> TextCase -> Inlines -> Inlines
    addTextCase Maybe Lang
    mblang TextCase
    x =
        case TextCase
    x of
          TextCase
    Lowercase        -> Maybe Lang -> CaseTransformer -> Inlines -> Inlines
    caseTransform Maybe Lang
    mblang CaseTransformer
    withLowercaseAll
          TextCase
    Uppercase        -> Maybe Lang -> CaseTransformer -> Inlines -> Inlines
    caseTransform Maybe Lang
    mblang CaseTransformer
    withUppercaseAll
          TextCase
    CapitalizeFirst  -> Maybe Lang -> CaseTransformer -> Inlines -> Inlines
    caseTransform Maybe Lang
    mblang CaseTransformer
    withCapitalizeFirst
          TextCase
    CapitalizeAll    -> Maybe Lang -> CaseTransformer -> Inlines -> Inlines
    caseTransform Maybe Lang
    mblang CaseTransformer
    withCapitalizeWords
          TextCase
    SentenceCase     -> Maybe Lang -> CaseTransformer -> Inlines -> Inlines
    caseTransform Maybe Lang
    mblang CaseTransformer
    withSentenceCase
          TextCase
    TitleCase        -> Maybe Lang -> CaseTransformer -> Inlines -> Inlines
    caseTransform Maybe Lang
    mblang CaseTransformer
    withTitleCase
          TextCase
    PreserveCase     -> Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "nocase"],[])
      addDisplay :: DisplayStyle -> Inlines -> Inlines
    addDisplay DisplayStyle
    x          =
        case DisplayStyle
    x of
          DisplayStyle
    DisplayBlock       -> Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "csl-block"],[])
          DisplayStyle
    DisplayLeftMargin  -> Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "csl-left-margin"],[])
          DisplayStyle
    DisplayRightInline -> Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "csl-right-inline"],[])
          DisplayStyle
    DisplayIndent      -> Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "csl-indent"],[])
      addQuotes :: Inlines -> Inlines
    addQuotes             = Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "csl-quoted"],[])
      inNote :: Inlines -> Inlines
    inNote                = Attr -> Inlines -> Inlines
    B.spanWith (Text
    "",[Text
    "csl-note"],[])
      movePunctuationInsideQuotes :: Inlines -> Inlines
    movePunctuationInsideQuotes
                            = Inlines -> Inlines
    punctuationInsideQuotes
      mapText :: (Text -> Text) -> Inlines -> Inlines
    mapText Text -> Text
    f             = (Inline -> Inline) -> Inlines -> Inlines
    forall a b. Walkable a b => (a -> a) -> b -> b
    walk Inline -> Inline
    go
        where go :: Inline -> Inline
    go (Str Text
    t) = Text -> Inline
    Str (Text -> Text
    f Text
    t)
              go Inline
    x       = Inline
    x
      addHyperlink :: Text -> Inlines -> Inlines
    addHyperlink Text
    t        = Text -> Text -> Inlines -> Inlines
    B.link Text
    t Text
    ""
      localizeQuotes :: Locale -> Inlines -> Inlines
    localizeQuotes        = Locale -> Inlines -> Inlines
    convertQuotes

    -- localized quotes
    convertQuotes :: Locale -> Inlines -> Inlines
    convertQuotes :: Locale -> Inlines -> Inlines
    convertQuotes Locale
    locale = [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList ([Inline] -> Inlines)
    -> (Inlines -> [Inline]) -> Inlines -> Inlines
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    DoubleQuote) ([Inline] -> [Inline])
    -> (Inlines -> [Inline]) -> Inlines -> [Inline]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Inlines -> [Inline]
    forall a. Many a -> [a]
    B.toList
     where
      ((Text
    oqOuter, Text
    cqOuter), (Text
    oqInner, Text
    cqInner)) = Locale -> ((Text, Text), (Text, Text))
    lookupQuotes Locale
    locale

      oq :: QuoteType -> Text
    oq QuoteType
    DoubleQuote  = Text
    oqOuter
      oq QuoteType
    SingleQuote  = Text
    oqInner
      cq :: QuoteType -> Text
    cq QuoteType
    DoubleQuote  = Text
    cqOuter
      cq QuoteType
    SingleQuote  = Text
    cqInner

      flipflop :: QuoteType -> QuoteType
    flipflop QuoteType
    SingleQuote = QuoteType
    DoubleQuote
      flipflop QuoteType
    DoubleQuote = QuoteType
    SingleQuote

      go :: QuoteType -> Inline -> Inline
      go :: QuoteType -> Inline -> Inline
    go QuoteType
    q (Span (Text
    "",[Text
    "csl-quoted"],[]) [Inline]
    ils) =
        Attr -> [Inline] -> Inline
    Span (Text
    "",[Text
    "csl-quoted"],[])
          (Text -> Inline
    Str (QuoteType -> Text
    oq QuoteType
    q) Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : (Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go (QuoteType -> QuoteType
    flipflop QuoteType
    q)) [Inline]
    ils [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Text -> Inline
    Str (QuoteType -> Text
    cq QuoteType
    q)])
      go QuoteType
    q (Span Attr
    attr [Inline]
    zs) = Attr -> [Inline] -> Inline
    Span Attr
    attr ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Quoted QuoteType
    qt' [Inline]
    zs) = QuoteType -> [Inline] -> Inline
    Quoted QuoteType
    qt' ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (SmallCaps [Inline]
    zs) = [Inline] -> Inline
    SmallCaps ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Superscript [Inline]
    zs) = [Inline] -> Inline
    Superscript ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Subscript [Inline]
    zs) = [Inline] -> Inline
    Subscript ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Emph [Inline]
    zs) = [Inline] -> Inline
    Emph ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Underline [Inline]
    zs) = [Inline] -> Inline
    Underline ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Strong [Inline]
    zs) = [Inline] -> Inline
    Strong ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Strikeout [Inline]
    zs) = [Inline] -> Inline
    Strikeout ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Cite [Citation]
    cs [Inline]
    zs) = [Citation] -> [Inline] -> Inline
    Cite [Citation]
    cs ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs)
      go QuoteType
    q (Link Attr
    attr [Inline]
    zs (Text, Text)
    t) = Attr -> [Inline] -> (Text, Text) -> Inline
    Link Attr
    attr ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs) (Text, Text)
    t
      go QuoteType
    q (Image Attr
    attr [Inline]
    zs (Text, Text)
    t) = Attr -> [Inline] -> (Text, Text) -> Inline
    Image Attr
    attr ((Inline -> Inline) -> [Inline] -> [Inline]
    forall a b. (a -> b) -> [a] -> [b]
    map (QuoteType -> Inline -> Inline
    go QuoteType
    q) [Inline]
    zs) (Text, Text)
    t
      go QuoteType
    _ Inline
    x = Inline
    x

    punctuationInsideQuotes :: Inlines -> Inlines
    punctuationInsideQuotes :: Inlines -> Inlines
    punctuationInsideQuotes = [Inline] -> Inlines
    forall a. [a] -> Many a
    B.fromList ([Inline] -> Inlines)
    -> (Inlines -> [Inline]) -> Inlines -> Inlines
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Inline] -> [Inline]
    go ([Inline] -> [Inline])
    -> (Inlines -> [Inline]) -> Inlines -> [Inline]
    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]
    go ([Inline] -> [Inline])
    -> (Inlines -> [Inline]) -> Inlines -> [Inline]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Inlines -> [Inline]
    forall a. Many a -> [a]
    B.toList
     where
      startsWithMovable :: Text -> Bool
    startsWithMovable Text
    t =
        case Text -> Maybe (Char, Text)
    T.uncons Text
    t of
          Just (Char
    c,Text
    _) -> Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '.' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    ','
          Maybe (Char, Text)
    Nothing    -> Bool
    False
      go :: [Inline] -> [Inline]
    go [] = []
      go (Span (Text
    "",[Text
    "csl-quoted"],[]) [Inline]
    xs : Str Text
    t : [Inline]
    rest)
        | Text -> Bool
    startsWithMovable Text
    t
          = Attr -> [Inline] -> Inline
    Span (Text
    "",[Text
    "csl-quoted"],[])
               ([Inline]
    xs [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Text -> Inline
    Str (Int -> Text -> Text
    T.take Int
    1 Text
    t) | Bool -> Bool
    not (Bool -> [Inline] -> Bool
    endWithPunct Bool
    True [Inline]
    xs)]) Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :
            if Text -> Int
    T.length Text
    t Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    1
               then [Inline] -> [Inline]
    go [Inline]
    rest
               else Text -> Inline
    Str (Int -> Text -> Text
    T.drop Int
    1 Text
    t) Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline] -> [Inline]
    go [Inline]
    rest
      go (Quoted QuoteType
    qt [Inline]
    xs : Str Text
    t : [Inline]
    rest)
        | Text -> Bool
    startsWithMovable Text
    t
          = QuoteType -> [Inline] -> Inline
    Quoted QuoteType
    qt
               ([Inline]
    xs [Inline] -> [Inline] -> [Inline]
    forall a. [a] -> [a] -> [a]
    ++ [Text -> Inline
    Str (Int -> Text -> Text
    T.take Int
    1 Text
    t) | Bool -> Bool
    not (Bool -> [Inline] -> Bool
    endWithPunct Bool
    True [Inline]
    xs)]) Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    :
            if Text -> Int
    T.length Text
    t Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    1
               then [Inline] -> [Inline]
    go [Inline]
    rest
               else Text -> Inline
    Str (Int -> Text -> Text
    T.drop Int
    1 Text
    t) Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline] -> [Inline]
    go [Inline]
    rest
      go (Inline
    x:[Inline]
    xs) = Inline
    x Inline -> [Inline] -> [Inline]
    forall a. a -> [a] -> [a]
    : [Inline] -> [Inline]
    go [Inline]
    xs

    endWithPunct :: Bool -> [Inline] -> Bool
    endWithPunct :: Bool -> [Inline] -> Bool
    endWithPunct Bool
    _ [] = Bool
    False
    endWithPunct Bool
    onlyFinal xs :: [Inline]
    xs@(Inline
    _:[Inline]
    _) =
      case String -> String
    forall a. [a] -> [a]
    reverse (Text -> String
    T.unpack (Text -> String) -> Text -> String
    forall a b. (a -> b) -> a -> b
    $ [Inline] -> Text
    forall a. Walkable Inline a => a -> Text
    stringify [Inline]
    xs) of
           []                       -> Bool
    True
           -- covers .), .", etc.:
           (Char
    d:Char
    c:String
    _) | Char -> Bool
    isPunctuation Char
    d
                     Bool -> Bool -> Bool
    && Bool -> Bool
    not Bool
    onlyFinal
                     Bool -> Bool -> Bool
    && Char -> Bool
    isEndPunct Char
    c -> Bool
    True
           (Char
    c:String
    _) | Char -> Bool
    isEndPunct Char
    c      -> Bool
    True
                 | Bool
    otherwise         -> Bool
    False
      where isEndPunct :: Char -> Bool
    isEndPunct Char
    c = Char
    c Char -> String -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` (String
    ".,;:!?" :: String)

    dropTextWhile' :: (Char -> Bool) -> Inlines -> Inlines
    dropTextWhile' :: (Char -> Bool) -> Inlines -> Inlines
    dropTextWhile' Char -> Bool
    f Inlines
    ils = State Bool Inlines -> Bool -> Inlines
    forall s a. State s a -> s -> a
    evalState ((Inline -> StateT Bool Identity Inline)
    -> Inlines -> State Bool Inlines
    forall a b (m :: * -> *).
    (Walkable a b, Monad m, Applicative m, Functor m) =>
    (a -> m a) -> b -> m b
    forall (m :: * -> *).
    (Monad m, Applicative m, Functor m) =>
    (Inline -> m Inline) -> Inlines -> m Inlines
    walkM Inline -> StateT Bool Identity Inline
    forall {m :: * -> *}. Monad m => Inline -> StateT Bool m Inline
    go Inlines
    ils) Bool
    True
     where
      go :: Inline -> StateT Bool m Inline
    go Inline
    x = do
        atStart <- StateT Bool m Bool
    forall (m :: * -> *) s. Monad m => StateT s m s
    get
        if atStart
           then
             case x of
               Str Text
    t -> do
                 let t' :: Text
    t' = (Char -> Bool) -> Text -> Text
    T.dropWhile Char -> Bool
    f Text
    t
                 Bool -> StateT Bool m () -> StateT Bool m ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (Text -> Bool
    T.null Text
    t') (StateT Bool m () -> StateT Bool m ())
    -> StateT Bool m () -> StateT Bool m ()
    forall a b. (a -> b) -> a -> b
    $
                   Bool -> StateT Bool m ()
    forall (m :: * -> *) s. Monad m => s -> StateT s m ()
    put Bool
    False
                 Inline -> StateT Bool m Inline
    forall a. a -> StateT Bool m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Inline -> StateT Bool m Inline) -> Inline -> StateT Bool m Inline
    forall a b. (a -> b) -> a -> b
    $ Text -> Inline
    Str Text
    t'
               Inline
    _ | Inline
    x Inline -> Inline -> Bool
    forall a. Eq a => a -> a -> Bool
    == Inline
    Space Bool -> Bool -> Bool
    || Inline
    x Inline -> Inline -> Bool
    forall a. Eq a => a -> a -> Bool
    == Inline
    SoftBreak ->
                 if Char -> Bool
    f Char
    ' '
                    then Inline -> StateT Bool m Inline
    forall a. a -> StateT Bool m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Inline -> StateT Bool m Inline) -> Inline -> StateT Bool m Inline
    forall a b. (a -> b) -> a -> b
    $ Text -> Inline
    Str Text
    ""
                    else do
                      Bool -> StateT Bool m ()
    forall (m :: * -> *) s. Monad m => s -> StateT s m ()
    put Bool
    False
                      Inline -> StateT Bool m Inline
    forall a. a -> StateT Bool m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Inline
    Space
                 | Bool
    otherwise  -> Inline -> StateT Bool m Inline
    forall a. a -> StateT Bool m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Inline
    x
           else return x

    dropTextWhileEnd' :: (Char -> Bool) -> Inlines -> Inlines
    dropTextWhileEnd' :: (Char -> Bool) -> Inlines -> Inlines
    dropTextWhileEnd' Char -> Bool
    f Inlines
    ils =
      Reverse Many Inline -> Inlines
    forall {k} (f :: k -> *) (a :: k). Reverse f a -> f a
    getReverse (Reverse Many Inline -> Inlines) -> Reverse Many Inline -> Inlines
    forall a b. (a -> b) -> a -> b
    $ State Bool (Reverse Many Inline) -> Bool -> Reverse Many Inline
    forall s a. State s a -> s -> a
    evalState ((Inline -> StateT Bool Identity Inline)
    -> Reverse Many Inline -> State Bool (Reverse Many Inline)
    forall a b (m :: * -> *).
    (Walkable a b, Monad m, Applicative m, Functor m) =>
    (a -> m a) -> b -> m b
    forall (m :: * -> *).
    (Monad m, Applicative m, Functor m) =>
    (Inline -> m Inline)
    -> Reverse Many Inline -> m (Reverse Many Inline)
    walkM Inline -> StateT Bool Identity Inline
    forall {m :: * -> *}. Monad m => Inline -> StateT Bool m Inline
    go (Reverse Many Inline -> State Bool (Reverse Many Inline))
    -> Reverse Many Inline -> State Bool (Reverse Many Inline)
    forall a b. (a -> b) -> a -> b
    $ Inlines -> Reverse Many Inline
    forall {k} (f :: k -> *) (a :: k). f a -> Reverse f a
    Reverse Inlines
    ils) Bool
    True
     where
      go :: Inline -> StateT Bool m Inline
    go Inline
    x = do
        atEnd <- StateT Bool m Bool
    forall (m :: * -> *) s. Monad m => StateT s m s
    get
        if atEnd
           then
             case x of
               Str Text
    t -> do
                 let t' :: Text
    t' = (Char -> Bool) -> Text -> Text
    T.dropWhileEnd Char -> Bool
    f Text
    t
                 Bool -> StateT Bool m () -> StateT Bool m ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (Text -> Bool
    T.null Text
    t') (StateT Bool m () -> StateT Bool m ())
    -> StateT Bool m () -> StateT Bool m ()
    forall a b. (a -> b) -> a -> b
    $
                   Bool -> StateT Bool m ()
    forall (m :: * -> *) s. Monad m => s -> StateT s m ()
    put Bool
    False
                 Inline -> StateT Bool m Inline
    forall a. a -> StateT Bool m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Inline -> StateT Bool m Inline) -> Inline -> StateT Bool m Inline
    forall a b. (a -> b) -> a -> b
    $ Text -> Inline
    Str Text
    t'
               Inline
    _ | Inline
    x Inline -> Inline -> Bool
    forall a. Eq a => a -> a -> Bool
    == Inline
    Space Bool -> Bool -> Bool
    || Inline
    x Inline -> Inline -> Bool
    forall a. Eq a => a -> a -> Bool
    == Inline
    SoftBreak
                 , Char -> Bool
    f Char
    ' ' -> Inline -> StateT Bool m Inline
    forall a. a -> StateT Bool m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Inline -> StateT Bool m Inline) -> Inline -> StateT Bool m Inline
    forall a b. (a -> b) -> a -> b
    $ Text -> Inline
    Str Text
    ""
                 | Bool
    otherwise -> Inline -> StateT Bool m Inline
    forall a. a -> StateT Bool m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Inline
    x
           else return x

    -- taken from Text.Pandoc.Shared:

    -- | 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 :: forall a. Walkable Inline a => a -> Text
    stringify = (Inline -> Text) -> a -> Text
    forall c. Monoid c => (Inline -> c) -> a -> c
    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
    unNote (Inline -> Inline) -> (Inline -> Inline) -> Inline -> Inline
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Inline -> Inline
    unQuote)
     where
      go :: Inline -> T.Text
      go :: Inline -> Text
    go Inline
    Space                                       = Text
    " "
      go Inline
    SoftBreak                                   = Text
    " "
      go (Str Text
    x)                                     = Text
    x
      go (Code Attr
    _ Text
    x)                                  = Text
    x
      go (Math MathType
    _ Text
    x)                                  = Text
    x
      go (RawInline (Format Text
    "html") (Text -> String
    T.unpack -> (Char
    '<':Char
    'b':Char
    'r':String
    _)))
                                                     = Text
    " " -- see #2105
      go Inline
    LineBreak                                   = Text
    " "
      go Inline
    _                                           = Text
    ""

      unNote :: Inline -> Inline
      unNote :: Inline -> Inline
    unNote (Note [Block]
    _) = Text -> Inline
    Str Text
    ""
      unNote Inline
    x        = Inline
    x

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

    caseTransform :: Maybe Lang
                  -> CaseTransformer
                  -> Inlines
                  -> Inlines
    caseTransform :: Maybe Lang -> CaseTransformer -> Inlines -> Inlines
    caseTransform Maybe Lang
    mblang CaseTransformer
    f Inlines
    x =
      State CaseTransformState Inlines -> CaseTransformState -> Inlines
    forall s a. State s a -> s -> a
    evalState ((CaseTransformState -> Text -> Text)
    -> Inlines -> State CaseTransformState Inlines
    caseTransform' (CaseTransformer -> Maybe Lang -> CaseTransformState -> Text -> Text
    unCaseTransformer CaseTransformer
    f Maybe Lang
    mblang) Inlines
    x) CaseTransformState
    Start

    -- custom traversal which does not descend into
    -- SmallCaps, Superscript, Subscript, Span "nocase" (implicit nocase)
    caseTransform' :: (CaseTransformState -> Text -> Text)
                   -> Inlines
                   -> State CaseTransformState Inlines
    caseTransform' :: (CaseTransformState -> Text -> Text)
    -> Inlines -> State CaseTransformState Inlines
    caseTransform' CaseTransformState -> Text -> Text
    f Inlines
    ils =
      case Seq Inline -> ViewR Inline
    forall a. Seq a -> ViewR a
    Seq.viewr (Inlines -> Seq Inline
    forall a. Many a -> Seq a
    unMany Inlines
    ils) of
        Seq Inline
    xs Seq.:> Str Text
    t | Bool -> Bool
    not (Seq Inline -> Bool
    forall a. Seq a -> Bool
    Seq.null Seq Inline
    xs)
                        , Bool -> Bool
    not (Text -> Bool
    hasWordBreak Text
    t) -> do
            xs' <- (Inline -> StateT CaseTransformState Identity Inline)
    -> Seq Inline -> StateT CaseTransformState Identity (Seq Inline)
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Seq a -> m (Seq b)
    mapM Inline -> StateT CaseTransformState Identity Inline
    go Seq Inline
    xs
            st <- get
            when (st == AfterWordEnd || st == StartSentence || st == Start) $
              put BeforeLastWord
            x' <- go (Str t)
            return $ Many $ xs' Seq.|> x'
        ViewR Inline
    _ -> (Inline -> StateT CaseTransformState Identity Inline)
    -> Inlines -> State CaseTransformState Inlines
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Many a -> m (Many b)
    mapM Inline -> StateT CaseTransformState Identity Inline
    go Inlines
    ils
     where
      go :: Inline -> StateT CaseTransformState Identity Inline
    go (Str Text
    t) = Text -> Inline
    Str (Text -> Inline) -> ([Text] -> Text) -> [Text] -> Inline
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Text] -> Text
    forall a. Monoid a => [a] -> a
    mconcat ([Text] -> Inline)
    -> StateT CaseTransformState Identity [Text]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Text -> StateT CaseTransformState Identity Text)
    -> [Text] -> StateT CaseTransformState Identity [Text]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Text -> StateT CaseTransformState Identity Text
    g (Text -> [Text]
    splitUp Text
    t)
      go Inline
    Space = Inline
    Space Inline
    -> StateT CaseTransformState Identity Text
    -> StateT CaseTransformState Identity Inline
    forall a b.
    a
    -> StateT CaseTransformState Identity b
    -> StateT CaseTransformState Identity a
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ Text -> StateT CaseTransformState Identity Text
    g Text
    " "
      go (SmallCaps [Inline]
    zs) = Inline -> StateT CaseTransformState Identity Inline
    forall {b}.
    Walkable Inline b =>
    b -> StateT CaseTransformState Identity b
    return' (Inline -> StateT CaseTransformState Identity Inline)
    -> Inline -> StateT CaseTransformState Identity Inline
    forall a b. (a -> b) -> a -> b
    $ [Inline] -> Inline
    SmallCaps [Inline]
    zs
      go (Superscript [Inline]
    zs) = Inline -> StateT CaseTransformState Identity Inline
    forall {b}.
    Walkable Inline b =>
    b -> StateT CaseTransformState Identity b
    return' (Inline -> StateT CaseTransformState Identity Inline)
    -> Inline -> StateT CaseTransformState Identity Inline
    forall a b. (a -> b) -> a -> b
    $ [Inline] -> Inline
    Superscript [Inline]
    zs
      go (Subscript [Inline]
    zs) = Inline -> StateT CaseTransformState Identity Inline
    forall {b}.
    Walkable Inline b =>
    b -> StateT CaseTransformState Identity b
    return' (Inline -> StateT CaseTransformState Identity Inline)
    -> Inline -> StateT CaseTransformState Identity Inline
    forall a b. (a -> b) -> a -> b
    $ [Inline] -> Inline
    Subscript [Inline]
    zs
      go (Span attr :: Attr
    attr@(Text
    _,[Text]
    classes,[(Text, Text)]
    _) [Inline]
    zs)
          | Text
    "nocase" Text -> [Text] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Text]
    classes = do
                st <- StateT CaseTransformState Identity CaseTransformState
    forall (m :: * -> *) s. Monad m => StateT s m s
    get
                case st of
                  CaseTransformState
    AfterWordChar | [Text]
    classes [Text] -> [Text] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Text
    "nocase"]
                    -> Inline -> StateT CaseTransformState Identity Inline
    forall {b}.
    Walkable Inline b =>
    b -> StateT CaseTransformState Identity b
    return' (Inline -> StateT CaseTransformState Identity Inline)
    -> Inline -> StateT CaseTransformState Identity Inline
    forall a b. (a -> b) -> a -> b
    $ Attr -> [Inline] -> Inline
    Span Attr
    nullAttr [Inline]
    zs
                  CaseTransformState
    _ -> Inline -> StateT CaseTransformState Identity Inline
    forall {b}.
    Walkable Inline b =>
    b -> StateT CaseTransformState Identity b
    return' (Inline -> StateT CaseTransformState Identity Inline)
    -> Inline -> StateT CaseTransformState Identity Inline
    forall a b. (a -> b) -> a -> b
    $ Attr -> [Inline] -> Inline
    Span Attr
    attr [Inline]
    zs
          | Bool
    otherwise = Attr -> [Inline] -> Inline
    Span Attr
    attr ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Emph [Inline]
    zs) = [Inline] -> Inline
    Emph ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Underline [Inline]
    zs) = [Inline] -> Inline
    Underline ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Strong [Inline]
    zs) = [Inline] -> Inline
    Strong ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Strikeout [Inline]
    zs) = [Inline] -> Inline
    Strikeout ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Quoted QuoteType
    qt [Inline]
    zs) = QuoteType -> [Inline] -> Inline
    Quoted QuoteType
    qt ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Cite [Citation]
    cs [Inline]
    zs) = [Citation] -> [Inline] -> Inline
    Cite [Citation]
    cs ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Link Attr
    attr [Inline]
    zs (Text, Text)
    t) = (\[Inline]
    x -> Attr -> [Inline] -> (Text, Text) -> Inline
    Link Attr
    attr [Inline]
    x (Text, Text)
    t) ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go (Image Attr
    attr [Inline]
    zs (Text, Text)
    t) = (\[Inline]
    x -> Attr -> [Inline] -> (Text, Text) -> Inline
    Image Attr
    attr [Inline]
    x (Text, Text)
    t) ([Inline] -> Inline)
    -> StateT CaseTransformState Identity [Inline]
    -> StateT CaseTransformState Identity Inline
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Inline -> StateT CaseTransformState Identity Inline)
    -> [Inline] -> StateT CaseTransformState Identity [Inline]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM Inline -> StateT CaseTransformState Identity Inline
    go [Inline]
    zs
      go Inline
    x = Inline -> StateT CaseTransformState Identity Inline
    forall a. a -> StateT CaseTransformState Identity a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Inline
    x

      -- we need to apply g to update the state:
      return' :: b -> StateT CaseTransformState Identity b
    return' b
    x = b
    x b
    -> StateT CaseTransformState Identity Text
    -> StateT CaseTransformState Identity b
    forall a b.
    a
    -> StateT CaseTransformState Identity b
    -> StateT CaseTransformState Identity a
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ Text -> StateT CaseTransformState Identity Text
    g ((Inline -> Text) -> b -> Text
    forall c. Monoid c => (Inline -> c) -> b -> c
    forall a b c. (Walkable a b, Monoid c) => (a -> c) -> b -> c
    query Inline -> Text
    fromStr b
    x)

      fromStr :: Inline -> Text
    fromStr (Str Text
    t) = Text
    t
      fromStr Inline
    _ = Text
    forall a. Monoid a => a
    mempty

      g :: Text -> State CaseTransformState Text
      g :: Text -> StateT CaseTransformState Identity Text
    g Text
    t = do
        st <- StateT CaseTransformState Identity CaseTransformState
    forall (m :: * -> *) s. Monad m => StateT s m s
    get
        put $ case T.unsnoc t of
                Maybe (Text, Char)
    Nothing -> CaseTransformState
    st
                Just (Text
    _,Char
    c)
                  | Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '.' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '?' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '!' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    ':' ->
                    CaseTransformState
    AfterSentenceEndingPunctuation
                  | Char -> Bool
    isAlphaNum Char
    c -> CaseTransformState
    AfterWordChar
                  | Char -> Bool
    isSpace Char
    c
                  , CaseTransformState
    st CaseTransformState -> CaseTransformState -> Bool
    forall a. Eq a => a -> a -> Bool
    == CaseTransformState
    AfterSentenceEndingPunctuation -> CaseTransformState
    StartSentence
                  | Char -> Bool
    isWordBreak Char
    c -> CaseTransformState
    AfterWordEnd
                  | Bool
    otherwise -> CaseTransformState
    st
        return $
          if T.all isAlphaNum t
             then f st t
             else t
      isWordBreak :: Char -> Bool
    isWordBreak Char
    '-' = Bool
    True
      isWordBreak Char
    '/' = Bool
    True
      isWordBreak Char
    '\x2013' = Bool
    True
      isWordBreak Char
    '\x2014' = Bool
    True
      isWordBreak Char
    c = Char -> Bool
    isSpace Char
    c
      hasWordBreak :: Text -> Bool
    hasWordBreak = (Char -> Bool) -> Text -> Bool
    T.any Char -> Bool
    isWordBreak
      splitUp :: Text -> [Text]
    splitUp = (Char -> Char -> Bool) -> Text -> [Text]
    T.groupBy Char -> Char -> Bool
    sameType
      sameType :: Char -> Char -> Bool
    sameType Char
    c Char
    d =
        (Char -> Bool
    isAlphaNum Char
    c Bool -> Bool -> Bool
    && Char -> Bool
    isAlphaNum Char
    d) Bool -> Bool -> Bool
    || (Char -> Bool
    isSpace Char
    c Bool -> Bool -> Bool
    && Char -> Bool
    isSpace Char
    d) Bool -> Bool -> Bool
    ||
          (Char -> Bool
    isPunctuation Char
    c Bool -> Bool -> Bool
    && Char -> Bool
    isPunctuation Char
    d)