module Data.CSS.Style.Cascade( query, cascade, TrivialPropertyParser(..), PropertyParser(..), Props ) where import Data.CSS.Style.Common import Data.CSS.Syntax.Tokens -- TODO do performance tests to decide beside between strict/lazy, -- or is another Map implementation better? import Data.HashMap.Strict import Data.Text (unpack) class PropertyParser a where temp :: a inherit :: a -> a inherit = id shorthand :: a -> Text -> [Token] -> [(Text, [Token])] shorthand self key value | Just _ <- longhand self self key value = [(key, value)] | otherwise = [] -- longhand parent self name value longhand :: a -> a -> Text -> [Token] -> Maybe a data TrivialPropertyParser = TrivialPropertyParser (HashMap String [Token]) instance PropertyParser TrivialPropertyParser where temp = TrivialPropertyParser empty longhand _ (TrivialPropertyParser self) key value = Just $ TrivialPropertyParser $ insert (unpack key) value self type Props = [(Text, [Token])] --- The query step exposes the available psuedoelements to the caller. query :: RuleStore s => s -> Element -> HashMap Text [StyleRule'] query self el = Prelude.foldr yield empty $ lookupRules self el where yield rule store = insertWith (++) (psuedoElement rule) [rule] store cascade :: PropertyParser p => [StyleRule'] -> Props -> p -> p cascade styles overrides base = dispatch base (inherit base) $ toList $ cascadeRules overrides styles cascadeRules :: Props -> [StyleRule'] -> HashMap Text [Token] cascadeRules overrides rules = cascadeProperties overrides $ concat $ Prelude.map properties rules cascadeProperties :: Props -> Props -> HashMap Text [Token] cascadeProperties overrides props = fromList (props ++ overrides) dispatch :: PropertyParser p => p -> p -> Props -> p dispatch base child ((key, value):props) | Just child' <- longhand base child key value = dispatch base child' props | otherwise = dispatch base child props dispatch _ child [] = child