~alcinnz/haskell-stylist

800ee36f4344f770200ee5c3c98883da52969565 — Adrian Cochrane 4 years ago 7b64476
Implement :is, :where, & :not functional pseudoclasses.

This is needed by some of the lowerings for other pseudoclasses.
TODO correctly compute specificity.
2 files changed, 20 insertions(+), 4 deletions(-)

M ISSUES/func-psudoclasses.md
M src/Data/CSS/Style/Selector/Interpret.hs
M ISSUES/func-psudoclasses.md => ISSUES/func-psudoclasses.md +3 -3
@@ 1,13 1,13 @@
# Functional psuedoclasses
These would mostly need to be added to the interpretor.

* [ ]  :not()
* [x]  :not() -- TODO apply specificity
* [x]  :dir()
* [ ]  :is()
* [x]  :is() -- TODO apply specificity
* [x]  :lang()
* [ ]  :nth-child()
* [ ]  :nth-last-child()
* [ ]  :nth-of-type()
* [ ]  :nth-last-child()
* [ ]  :where()
* [x]  :where()
* etc

M src/Data/CSS/Style/Selector/Interpret.hs => src/Data/CSS/Style/Selector/Interpret.hs +17 -1
@@ 11,12 11,16 @@ import Data.CSS.Style.Common
import Data.Text (unpack)
import Data.List
import Data.Maybe
import Data.Bits (xor)

-- For pseudoclasses
import Data.CSS.Syntax.Selector (parseSelectors)

-- | A compiled(?) CSS selector.
type SelectorFunc = Element -> Bool
type AttrsFunc = [Attribute] -> Bool
-- Mostly here for the sake of pseudoclasses.
data IL = Tagname Text | Fail
data IL = Tagname Text | Fail | Recursive Bool [Selector]

-- | Converts a parsed CSS selector into a callable function.
compile :: Selector -> SelectorFunc


@@ 31,6 35,8 @@ compileInner sel = compileInner' $ lowerInner sel
compileInner' :: ([IL], [(Text, String -> Bool)]) -> SelectorFunc
compileInner' ((Tagname tag:tests), attrs) = testTag tag $ compileInner' (tests, attrs)
compileInner' ((Fail:_), _) = \_ -> False
compileInner' ((Recursive negate' sels:tests), attrs) =
    recursiveSelect negate' (map compile sels) $ compileInner' (tests, attrs)
compileInner' ([], attrs) = testAttrs (compileAttrs $ sortAttrs attrs) matched
compileAttrs :: [(Text, String -> Bool)] -> AttrsFunc
compileAttrs ((tag, test):attrs) = testAttr tag test $ compileAttrs attrs


@@ 43,6 49,11 @@ lowerInner (Class c:s) = (tests, ("class", hasWord $ unpack c):attrs) where (tes
lowerInner (Property prop test:s) = (tests, (prop, compileAttrTest test):attrs)
    where (tests, attrs) = lowerInner s
-- psuedos, TODO handle argumented psuedoclasses.
lowerInner (Psuedoclass c args:s)
    | c `elem` ["is", "where"], (sels, []) <- parseSelectors args =
        (Recursive False sels:tests, attrs) where (tests, attrs) = lowerInner s
lowerInner (Psuedoclass "not" args:s) | (sels, []) <- parseSelectors args =
    (Recursive True sels:tests, attrs) where (tests, attrs) = lowerInner s
lowerInner (Psuedoclass c []:s) =
    (tests, ("", hasWord $ unpack c):attrs) where (tests, attrs) = lowerInner s
lowerInner (Psuedoclass _ _:_) = ([Fail], [])


@@ 93,6 104,11 @@ hasWord expected value = expected `elem` words value
hasLang :: [Char] -> [Char] -> Bool
hasLang expected value = expected == value || isPrefixOf (expected ++ "-") value

--- Pseudoclasses
recursiveSelect :: Bool -> [SelectorFunc] -> SelectorFunc -> SelectorFunc
recursiveSelect negate' sels success el | negate' `xor` any ($ el) sels = success el
    | otherwise = False

--------
---- RuleStore wrapper
--------