    {- |
    Module      : Text.Pandoc.CSS
    Copyright   : © 2006-2024 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
      ( cssAttributes
      , pickStyleAttrProps
      , pickStylesToKVs
      )
    where

    import Data.Either (fromRight)
    import Data.Maybe (mapMaybe, listToMaybe)
    import Data.Text (Text, pack)
    import Text.Pandoc.Shared (trim)
    import Text.Pandoc.Parsing

    type Parser = Parsec Text ()

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

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

    -- | Parses a style string, returning the CSS attributes.
    -- Returns an empty list on failure.
    cssAttributes :: Text -> [(Text, Text)]
    cssAttributes :: Text -> [(Text, Text)]
    cssAttributes Text
    styleString =
      [(Text, Text)]
    -> Either ParseError [(Text, Text)] -> [(Text, Text)]
    forall b a. b -> Either a b -> b
    fromRight [] (Either ParseError [(Text, Text)] -> [(Text, Text)])
    -> Either ParseError [(Text, Text)] -> [(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 [Char]
    "" Text
    styleString

    -- | takes a list of keys/properties and a CSS string and
    -- returns the corresponding key-value-pairs.
    pickStylesToKVs :: [Text] -> Text -> [(Text, Text)]
    pickStylesToKVs :: [Text] -> Text -> [(Text, Text)]
    pickStylesToKVs [Text]
    props Text
    styleAttr =
      ((Text, Text) -> Bool) -> [(Text, Text)] -> [(Text, Text)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (\(Text, Text)
    s -> (Text, Text) -> Text
    forall a b. (a, b) -> a
    fst (Text, Text)
    s Text -> [Text] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Text]
    props) ([(Text, Text)] -> [(Text, Text)])
    -> [(Text, Text)] -> [(Text, Text)]
    forall a b. (a -> b) -> a -> b
    $ Text -> [(Text, Text)]
    cssAttributes Text
    styleAttr

    -- | 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 :: [Text] -> Text -> Maybe Text
    pickStyleAttrProps :: [Text] -> Text -> Maybe Text
    pickStyleAttrProps [Text]
    lookupProps Text
    styleAttr = do
        styles <- (ParseError -> Maybe [(Text, Text)])
    -> ([(Text, Text)] -> Maybe [(Text, Text)])
    -> Either ParseError [(Text, Text)]
    -> Maybe [(Text, Text)]
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (Maybe [(Text, Text)] -> ParseError -> Maybe [(Text, Text)]
    forall a b. a -> b -> a
    const Maybe [(Text, Text)]
    forall a. Maybe a
    Nothing) [(Text, Text)] -> Maybe [(Text, Text)]
    forall a. a -> Maybe a
    Just (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 [Char]
    "" Text
    styleAttr
        listToMaybe $ mapMaybe (`lookup` styles) lookupProps