    {- |
    Module      : Text.Pandoc.CSS
    Copyright   : © 2006-2020 John MacFarlane <jgm@berkeley.edu>,
                    2015-2016 Mauro Bieg,
                    2015      Ophir Lifshitz <hangfromthefloor@gmail.com>
    License     : GNU GPL, version 2 or above

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

    Tools for working with CSS.
    -}
    module Text.Pandoc.CSS ( foldOrElse
                           , pickStyleAttrProps
                           , pickStylesToKVs
                           )
    where

    import qualified Data.Text as T
    import Text.Pandoc.Shared (trim)
    import Text.Parsec
    import Text.Parsec.Text

    ruleParser :: Parser (T.Text, T.Text)
    ruleParser :: Parser (Text, Text)
    ruleParser = do
        [Char]
    p <- ParsecT Text () Identity Char -> ParsecT Text () Identity [Char]
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 ([Char] -> ParsecT Text () Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    [Char] -> ParsecT s u m Char
    noneOf ":")  ParsecT Text () Identity [Char]
    -> ParsecT Text () Identity Char -> ParsecT Text () Identity [Char]
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Char -> ParsecT Text () Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ':'
        [Char]
    v <- ParsecT Text () Identity Char -> ParsecT Text () Identity [Char]
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 ([Char] -> ParsecT Text () Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    [Char] -> ParsecT s u m Char
    noneOf ":;") ParsecT Text () Identity [Char]
    -> ParsecT Text () Identity () -> ParsecT Text () Identity [Char]
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* ParsecT Text () Identity Char -> ParsecT Text () Identity ()
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m ()
    optional (Char -> ParsecT Text () Identity Char
    forall s (m :: * -> *) u.
    Stream s m Char =>
    Char -> ParsecT s u m Char
    char ';') ParsecT Text () Identity [Char]
    -> ParsecT Text () Identity () -> ParsecT Text () Identity [Char]
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* ParsecT Text () Identity ()
    forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
    spaces
        (Text, Text) -> Parser (Text, Text)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text -> Text
    trim (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ [Char] -> Text
    T.pack [Char]
    p, Text -> Text
    trim (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ [Char] -> Text
    T.pack [Char]
    v)

    styleAttrParser :: Parser [(T.Text, T.Text)]
    styleAttrParser :: Parser [(Text, Text)]
    styleAttrParser = Parser (Text, Text) -> Parser [(Text, Text)]
    forall s (m :: * -> *) t u a.
    Stream s m t =>
    ParsecT s u m a -> ParsecT s u m [a]
    many1 Parser (Text, Text)
    ruleParser

    orElse :: Eq a => a -> a -> a -> a
    orElse :: a -> a -> a -> a
    orElse v :: a
    v x :: a
    x y :: a
    y = if a
    v a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    x then a
    y else a
    x

    foldOrElse :: Eq a => a -> [a] -> a
    foldOrElse :: a -> [a] -> a
    foldOrElse v :: a
    v xs :: [a]
    xs = (a -> a -> a) -> a -> [a] -> a
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (a -> a -> a -> a
    forall a. Eq a => a -> a -> a -> a
    orElse a
    v) a
    v [a]
    xs

    eitherToMaybe :: Either a b -> Maybe b
    eitherToMaybe :: Either a b -> Maybe b
    eitherToMaybe (Right x :: b
    x) = b -> Maybe b
    forall a. a -> Maybe a
    Just b
    x
    eitherToMaybe _         = Maybe b
    forall a. Maybe a
    Nothing

    -- | takes a list of keys/properties and a CSS string and
    -- returns the corresponding key-value-pairs.
    pickStylesToKVs :: [T.Text] -> T.Text -> [(T.Text, T.Text)]
    pickStylesToKVs :: [Text] -> Text -> [(Text, Text)]
    pickStylesToKVs props :: [Text]
    props styleAttr :: Text
    styleAttr =
      case Parser [(Text, Text)]
    -> [Char] -> Text -> Either ParseError [(Text, Text)]
    forall s t a.
    Stream s Identity t =>
    Parsec s () a -> [Char] -> s -> Either ParseError a
    parse Parser [(Text, Text)]
    styleAttrParser "" Text
    styleAttr of
        Left _       -> []
        Right styles :: [(Text, Text)]
    styles -> ((Text, Text) -> Bool) -> [(Text, Text)] -> [(Text, Text)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (\s :: (Text, Text)
    s -> (Text, Text) -> Text
    forall a b. (a, b) -> a
    fst (Text, Text)
    s Text -> [Text] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Text]
    props) [(Text, Text)]
    styles

    -- | takes a list of key/property synonyms and a CSS string and maybe
    -- returns the value of the first match (in order of the supplied list)
    pickStyleAttrProps :: [T.Text] -> T.Text -> Maybe T.Text
    pickStyleAttrProps :: [Text] -> Text -> Maybe Text
    pickStyleAttrProps lookupProps :: [Text]
    lookupProps styleAttr :: Text
    styleAttr = do
        [(Text, Text)]
    styles <- Either ParseError [(Text, Text)] -> Maybe [(Text, Text)]
    forall a b. Either a b -> Maybe b
    eitherToMaybe (Either ParseError [(Text, Text)] -> Maybe [(Text, Text)])
    -> Either ParseError [(Text, Text)] -> Maybe [(Text, Text)]
    forall a b. (a -> b) -> a -> b
    $ Parser [(Text, Text)]
    -> [Char] -> Text -> Either ParseError [(Text, Text)]
    forall s t a.
    Stream s Identity t =>
    Parsec s () a -> [Char] -> s -> Either ParseError a
    parse Parser [(Text, Text)]
    styleAttrParser "" Text
    styleAttr
        Maybe Text -> [Maybe Text] -> Maybe Text
    forall a. Eq a => a -> [a] -> a
    foldOrElse Maybe Text
    forall a. Maybe a
    Nothing ([Maybe Text] -> Maybe Text) -> [Maybe Text] -> Maybe Text
    forall a b. (a -> b) -> a -> b
    $ (Text -> Maybe Text) -> [Text] -> [Maybe Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text -> [(Text, Text)] -> Maybe Text
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    `lookup` [(Text, Text)]
    styles) [Text]
    lookupProps