M src/Data/CSS/Style/Cascade.hs => src/Data/CSS/Style/Cascade.hs +1 -25
@@ 8,6 8,7 @@ module Data.CSS.Style.Cascade(
import Data.CSS.Style.Common
import Data.CSS.Syntax.Tokens
+import Stylist (PropertyParser(..), Props)
-- TODO do performance tests to decide beside between strict/lazy,
-- or is another Map implementation better?
@@ 15,28 16,6 @@ import Data.HashMap.Strict
import qualified Data.HashMap.Lazy as HML
import Data.Text (unpack, pack, isPrefixOf)
--- | Defines how to parse CSS properties into an output "style" format.
-class PropertyParser a where
- -- | Default styles.
- temp :: a
- -- | Creates a style inherited from a parent style.
- inherit :: a -> a
- inherit = id
-
- -- | Expand a shorthand property into longhand properties.
- 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
-
- -- | Retrieve stored variables, optional.
- getVars :: a -> Props
- getVars _ = []
- -- | Save variable values, optional.
- setVars :: Props -> a -> a
- setVars _ = id
-
-- | Gather properties into a hashmap.
data TrivialPropertyParser = TrivialPropertyParser (HashMap String [Token]) deriving (Show, Eq)
instance PropertyParser TrivialPropertyParser where
@@ 44,9 23,6 @@ instance PropertyParser TrivialPropertyParser where
longhand _ (TrivialPropertyParser self) key value =
Just $ TrivialPropertyParser $ insert (unpack key) value self
--- | "key: value;" entries to be parsed into an output type.
-type Props = [(Text, [Token])]
-
--------
---- Query/Psuedo-elements
--------
M src/Data/CSS/Style/Common.hs => src/Data/CSS/Style/Common.hs +1 -16
@@ 11,22 11,7 @@ import Data.CSS.Syntax.StyleSheet
import Data.CSS.Syntax.Selector
import Data.CSS.Syntax.Tokens
import Data.Text.Internal (Text(..))
-
--- | An inversely-linked tree of elements, to apply CSS selectors to.
-data Element = ElementNode {
- -- | The element's parent in the tree.
- parent :: Maybe Element,
- -- | The element's previous sibling in the tree.
- previous :: Maybe Element,
- -- | The element's name.
- name :: Text,
- -- | The element's namespace.
- namespace :: Text,
- -- | The element's attributes, in sorted order.
- attributes :: [Attribute]
-}
--- | A key-value attribute.
-data Attribute = Attribute Text Text String deriving (Eq, Ord)
+import Stylist (Element(..), Attribute(..))
class RuleStore a where
new :: a
M src/Data/CSS/StyleTree.hs => src/Data/CSS/StyleTree.hs +3 -44
@@ 1,50 1,9 @@
-- | Abstracts away tree traversals.
-- Mostly used by callers including (soon) XML Conduit Stylist,
-- but also used internally for generating counter text.
+--
+-- Backwards compatability module, this API has been moved out into "stylist-traits".
module Data.CSS.StyleTree(StyleTree(..), treeOrder, treeOrder',
Path, treeMap, treeFlatten, preorder, preorder', postorder) where
-data StyleTree p = StyleTree {
- style :: p,
- children :: [StyleTree p]
-}
-
-type Path = [Integer]
-treeOrder :: (c -> c -> Path -> p -> (c, p')) ->
- c -> StyleTree p -> StyleTree p'
-treeOrder cb ctxt tree = StyleTree
- (snd $ cb ctxt ctxt [] $ style tree)
- (snd $ treeOrder' cb ctxt ctxt [0] $ children tree)
-treeOrder' :: (c -> c -> Path -> p -> (c, p')) ->
- c -> c -> Path -> [StyleTree p] -> (c, [StyleTree p'])
-treeOrder' cb prevContext context (num:path) (node:nodes) = (tailContext, StyleTree node' children' : nodes')
- where
- (selfContext, node') = cb prevContext context (num:path) $ style node
- (childContext, children') = treeOrder' cb selfContext selfContext (0:num:path) $ children node
- (tailContext, nodes') = treeOrder' cb selfContext childContext (num + 1:path) nodes
-treeOrder' _ _ context _ [] = (context, [])
-treeOrder' _ _ _ [] _ = error "Invalid path during tree traversal!"
-
-treeMap :: (p -> p') -> StyleTree p -> StyleTree p'
-treeMap cb = treeOrder (\_ _ _ p -> ((), cb p)) ()
-
-treeFlatten :: StyleTree p -> [p]
-treeFlatten = treeFlatten' . children
-treeFlatten' :: [StyleTree p] -> [p]
-treeFlatten' (StyleTree p []:ps) = p : treeFlatten' ps
-treeFlatten' (StyleTree _ childs:sibs) = treeFlatten' childs ++ treeFlatten' sibs
-treeFlatten' [] = []
-
-preorder :: (Maybe b -> Maybe b -> a -> b) -> StyleTree a -> StyleTree b
-preorder cb self = head $ preorder' cb Nothing Nothing [self]
-preorder' :: (Maybe b -> Maybe b -> a -> b) ->
- Maybe b -> Maybe b -> [StyleTree a] -> [StyleTree b]
-preorder' cb parent previous (self:sibs) = let self' = cb parent previous $ style self
- in StyleTree self' (preorder' cb (Just self') Nothing $ children self) :
- preorder' cb parent (Just self') sibs
-preorder' _ _ _ [] = []
-
-postorder :: (a -> [b] -> [b]) -> StyleTree a -> [StyleTree b]
-postorder cb (StyleTree self childs) =
- [StyleTree self' children' | self' <- cb self $ Prelude.map style children']
- where children' = concat $ Prelude.map (postorder cb) childs
+import Stylist.Tree
M src/Data/CSS/Syntax/Selector.hs => src/Data/CSS/Syntax/Selector.hs +3 -112
@@ 1,119 1,10 @@
-- | Parses CSS selectors
-- See `parseSelectors`
+--
+-- Backwards-compatibility module, this API has been moved out into "stylist-traits".
module Data.CSS.Syntax.Selector(
Selector(..), SimpleSelector(..), PropertyTest(..), PropertyFunc(..),
parseSelectors
) where
-import Data.CSS.Syntax.Tokens
-import Data.CSS.Syntax.StylishUtil
-
-import Data.Text.Internal (Text(..))
-
--- | A CSS "selector" indicating which elements should be effected by CSS.
-data Selector = Element [SimpleSelector] -- ^ Selects a single element.
- | Child Selector [SimpleSelector] -- ^ Represents "a > b" operator.
- | Descendant Selector [SimpleSelector] -- ^ Represents "a b" operator.
- | Adjacent Selector [SimpleSelector] -- ^ Represents "a + b" operator.
- | Sibling Selector [SimpleSelector] -- ^ Represents "a ~ b" operator.
- deriving (Show, Eq)
--- | An individual test comprising a CSS stylesheet.
-data SimpleSelector = Tag Text -- ^ Matches a tagname, e.g. "a"
- | Namespace Text
- | Id Text -- ^ Matches the "id" attribute, e.g. "#header"
- | Class Text -- ^ Matches the "class" attribute, e.g. ".ad"
- | Property (Maybe Text) Text PropertyTest -- ^ Matches a specified property
- | Psuedoclass Text [Token] -- ^ Matches psuedoclasses provided by the caller (via a nameless property).
- deriving (Show, Eq)
--- | How should a property be matched.
-data PropertyTest = Exists -- ^ Matches whether an attribute actually exists, e.g. "[title]"
- | Equals Text -- ^ Matches whether the attribute is exactly equal to the value, e.g. "="
- | Suffix Text -- ^ Matches whether attribute ends with the given value, e.g. "$="
- | Prefix Text -- ^ Matches whether attribute starts with the given value, e.g. "^="
- | Substring Text -- ^ Matches whether the attribute contains the given value, e.g. "*="
- | Include Text -- ^ Is one of the whitespace-seperated values the one specified? e.g. "~="
- | Dash Text -- ^ Matches whitespace seperated values, or their "-"-seperated prefixes. e.g. "|="
- | Callback PropertyFunc -- ^ Calls the given function to test this property.
- deriving (Show, Eq)
--- | Caller-specified functions to extend property selection.
--- Has incorrect Show/Eq implementations so this rare exception doesn't break things.
-data PropertyFunc = PropertyFunc (String -> Bool)
-instance Show PropertyFunc where
- show _ = "xx"
-instance Eq PropertyFunc where
- _ == _ = False
-
--- | Parses a CSS selector.
-parseSelectors :: Parser [Selector]
-parseSelectors tokens = concatP (:) parseCompound parseSelectorsTail $ skipSpace tokens
-parseSelectorsTail :: Parser [Selector]
-parseSelectorsTail (Comma:tokens) = parseSelectors tokens
-parseSelectorsTail tokens = ([], tokens)
-parseCompound :: Parser Selector
-parseCompound tokens = parseCombinators (Element selector) tokens'
- where (selector, tokens') = parseSelector tokens
-
-parseSelector' :: SimpleSelector -> Parser [SimpleSelector]
-parseSelector' op tokens = (op:selector, tokens')
- where (selector, tokens') = parseSelector tokens
-
-parseSelector :: Parser [SimpleSelector]
-parseSelector (Ident ns:Delim '|':tokens) = parseSelector' (Namespace ns) tokens
-parseSelector (Delim '*':tokens) = parseSelector tokens
-parseSelector (Ident tag:tokens) = parseSelector' (Tag tag) tokens
-parseSelector (Hash _ i:tokens) = parseSelector' (Id i) tokens
-parseSelector (Delim '.':Ident class_:tokens) = parseSelector' (Class class_) tokens
-parseSelector (LeftSquareBracket:Ident ns:Delim '|':Ident prop:tokens) =
- concatP appendPropertySel parsePropertySel parseSelector tokens
- where appendPropertySel test selector = Property (Just ns) prop test : selector
-parseSelector (LeftSquareBracket:Ident prop:tokens) =
- concatP appendPropertySel parsePropertySel parseSelector tokens
- where appendPropertySel test selector = Property Nothing prop test : selector
-parseSelector (Colon:Ident p:ts) = parseSelector' (Psuedoclass p []) ts
-parseSelector (Colon:Function fn:tokens) =
- concatP appendPseudo scanBlock parseSelector tokens
- where appendPseudo args selector = Psuedoclass fn args : selector
-parseSelector tokens = ([], tokens)
-
-parseCombinators' :: Selector -> Parser Selector
-parseCombinators' selector tokens = parseCombinators selector' tokens'
- where (selector', tokens') = parseCombinator selector tokens
-parseCombinators :: Selector -> Parser Selector
-parseCombinators selector (Whitespace:tokens) = parseCombinators' selector tokens
-parseCombinators selector tokens@(Delim _:_) = parseCombinators' selector tokens
-parseCombinators selector tokens = (selector, tokens)
-
-parseCombinator' :: (Selector -> [SimpleSelector] -> Selector)
- -> Selector -> Parser Selector
-parseCombinator' cb selector tokens = (cb selector selector', tokens')
- where (selector', tokens') = parseSelector $ skipSpace tokens
-parseCombinator :: Selector -> [Token] -> (Selector, [Token])
-parseCombinator selector (Whitespace:tokens) = parseCombinator selector tokens
-parseCombinator selector (Delim '>':tokens) = parseCombinator' Child selector tokens
-parseCombinator selector (Delim '~':tokens) = parseCombinator' Sibling selector tokens
-parseCombinator selector (Delim '+':tokens) = parseCombinator' Adjacent selector tokens
--- Take special care to avoid adding a trailing Descendant when not needed.
-parseCombinator selector tokens@(LeftCurlyBracket:_) = (selector, tokens)
-parseCombinator selector tokens@(RightCurlyBracket:_) = (selector, tokens)
-parseCombinator selector tokens@(RightSquareBracket:_) = (selector, tokens)
-parseCombinator selector tokens@(Comma:_) = (selector, tokens)
-
-parseCombinator selector tokens@(RightParen:_) = (selector, tokens)
-parseCombinator selector [] = (selector, [])
-
-parseCombinator selector tokens = parseCombinator' Descendant selector tokens
-
-parsePropertySel :: Parser PropertyTest
-parsePropertySel (RightSquareBracket:tokens) = (Exists, tokens)
-parsePropertySel (Delim '=':tokens) = parsePropertyVal (Equals) tokens
-parsePropertySel (SuffixMatch:tokens) = parsePropertyVal (Suffix) tokens
-parsePropertySel (PrefixMatch:tokens) = parsePropertyVal (Prefix) tokens
-parsePropertySel (SubstringMatch:tokens) = parsePropertyVal (Substring) tokens
-parsePropertySel (IncludeMatch:tokens) = parsePropertyVal (Include) tokens
-parsePropertySel (DashMatch:tokens) = parsePropertyVal (Dash) tokens
-parsePropertySel tokens = (Exists, skipBlock tokens)
-
-parsePropertyVal :: (Text -> PropertyTest) -> Parser PropertyTest
-parsePropertyVal wrapper (Ident val:RightSquareBracket:tokens) = (wrapper val, tokens)
-parsePropertyVal wrapper (String val:RightSquareBracket:tokens) = (wrapper val, tokens)
-parsePropertyVal _ tokens = (Exists, skipBlock tokens)
+import Stylist.Parse.Selector
M src/Data/CSS/Syntax/StyleSheet.hs => src/Data/CSS/Syntax/StyleSheet.hs +3 -138
@@ 1,6 1,8 @@
{-# LANGUAGE OverloadedStrings #-}
-- | Parses a CSS stylesheet
-- See `StyleSheet` & `parseForURL`.
+--
+-- Backwards-compatability module, this API has been moved out into "stylist-traits".
module Data.CSS.Syntax.StyleSheet (
parse, parse', parseForURL, TrivialStyleSheet(..),
StyleSheet(..), skipAtRule, scanAtRule, scanBlock, skipSpace,
@@ 11,141 13,4 @@ module Data.CSS.Syntax.StyleSheet (
scanValue
) where
-import Data.CSS.Syntax.Tokens
-import Data.CSS.Syntax.Selector
-import Data.CSS.Syntax.StylishUtil
-
-import Data.Text.Internal (Text(..))
-import Data.Text (pack, unpack)
-import Network.URI (parseRelativeReference, relativeTo, uriToString, URI(..))
-
---------
----- Output type class
---------
--- | Describes how to store, and to some extent parse, CSS stylesheets.
--- These methods are used to construct the results from `parse`, etc.
-class StyleSheet s where
- -- | Sets the stylesheet priority (useragent vs user vs author), optional.
- setPriority :: Int -> s -> s
- setPriority _ = id
- -- | Stores a parsed selector+properties rule.
- addRule :: s -> StyleRule -> s
- -- | Stores and parses an identified at-rule.
- addAtRule :: s -> Text -> [Token] -> (s, [Token])
- addAtRule self _ tokens = (self, skipAtRule tokens)
-
--- | Stores the parsed selector*s*+proeprties rule.
-addRules :: StyleSheet ss => ss -> ([Selector], ([(Text, [Token])], Text)) -> ss
-addRules self (selector:selectors, val@(props, psuedoel)) = addRules self' (selectors, val)
- where self' = addRule self $ StyleRule selector props psuedoel
-addRules self ([], _) = self
-
--- | The properties to set for elements matching the given selector.
-data StyleRule = StyleRule Selector [(Text, [Token])] Text deriving (Show, Eq)
-
--- | Gathers StyleRules into a list, mainly for testing.
-data TrivialStyleSheet = TrivialStyleSheet [StyleRule] deriving (Show, Eq)
-instance StyleSheet TrivialStyleSheet where
- addRule (TrivialStyleSheet self) rule = TrivialStyleSheet $ rule:self
-
---------
----- Basic parsing
---------
--- | Parse a CSS stylesheet
-parse :: StyleSheet s => s -> Text -> s
-parse stylesheet source = parse' stylesheet $ tokenize source
-
--- | Parse a CSS stylesheet, resolving all URLs to absolute form.
-parseForURL :: StyleSheet s => s -> URI -> Text -> s
-parseForURL stylesheet base source = parse' stylesheet $ rewriteURLs $ tokenize source
- where
- rewriteURLs (Url text:toks)
- | Just url <- parseRelativeReference $ unpack text =
- Url (pack $ uriToString id (relativeTo url base) "") : rewriteURLs toks
- | otherwise = Function "url" : RightParen : rewriteURLs toks
- rewriteURLs (tok:toks) = tok : rewriteURLs toks
- rewriteURLs [] = []
-
--- | Parse a tokenized (via `css-syntax`) CSS stylesheet
-parse' :: StyleSheet t => t -> [Token] -> t
--- Things to skip.
-parse' stylesheet (Whitespace:tokens) = parse' stylesheet tokens
-parse' stylesheet (CDO:tokens) = parse' stylesheet tokens
-parse' stylesheet (CDC:tokens) = parse' stylesheet tokens
-parse' stylesheet (Comma:tokens) = parse' stylesheet tokens -- TODO issue warnings.
-
-parse' stylesheet [] = stylesheet
-
-parse' stylesheet (AtKeyword kind:tokens) = parse' stylesheet' tokens'
- where (stylesheet', tokens') = addAtRule stylesheet kind $ skipSpace tokens
-parse' stylesheet tokens = parse' (addRules stylesheet rule) tokens'
- where (rule, tokens') = concatP (,) parseSelectors parseProperties tokens
-
---------
----- Property parsing
---------
--- | Parse "{key: value; ...}" property values, with a psuedoelement.
-parseProperties :: Parser ([(Text, [Token])], Text)
-parseProperties (LeftCurlyBracket:tokens) = noPsuedoel $ parseProperties' tokens
-parseProperties (Whitespace:tokens) = parseProperties tokens
-parseProperties (Colon:Colon:Ident n:tokens) = ((val, n), tokens')
- where ((val, _), tokens') = parseProperties tokens
--- This error recovery is a bit overly conservative, but it's simple.
-parseProperties (_:tokens) = noPsuedoel ([], skipAtRule tokens)
-parseProperties [] = noPsuedoel ([], [])
-
-noPsuedoel :: (x, y) -> ((x, Text), y)
-noPsuedoel (val, tokens) = ((val, ""), tokens)
-
--- | Parse "key: value;"... property values, as per the HTML "style" property.
-parseProperties' :: Parser [(Text, [Token])]
-parseProperties' (Whitespace:tokens) = parseProperties' tokens
-parseProperties' (Ident name:tokens)
- | Colon:tokens' <- skipSpace tokens =
- concatP appendProp scanValue parseProperties' tokens'
- where appendProp value props = (name, value):props
-parseProperties' (RightCurlyBracket:tokens) = ([], tokens)
-parseProperties' [] = ([], [])
-parseProperties' tokens = parseProperties' (skipValue tokens)
-
---------
----- Skipping/Scanning utilities
---------
--- | Returns tokens before & after an at-rule value, terminated after a curly-bracketed block or a semicolon.
-scanAtRule :: Parser [Token]
-scanAtRule (Semicolon:tokens) = ([Semicolon], tokens)
-scanAtRule tokens@(LeftCurlyBracket:_) = scanInner tokens $ \rest -> ([], rest)
-
-scanAtRule tokens@(LeftParen:_) = scanInner tokens scanValue
-scanAtRule tokens@(Function _:_) = scanInner tokens scanValue
-scanAtRule tokens@(LeftSquareBracket:_) = scanInner tokens scanValue
--- To ensure parens are balanced, should already be handled.
-scanAtRule (RightCurlyBracket:tokens) = ([], RightCurlyBracket:tokens)
-scanAtRule (RightParen:tokens) = ([], RightParen:tokens)
-scanAtRule (RightSquareBracket:tokens) = ([], RightSquareBracket:tokens)
-
-scanAtRule tokens = capture scanAtRule tokens
-
--- | Returns tokens after an at-rule, as per `scanAtRule`.
-skipAtRule :: [Token] -> [Token]
-skipAtRule tokens = snd $ scanAtRule tokens
-
--- | Returns tokens before & after a semicolon.
-scanValue :: Parser [Token]
-scanValue (Semicolon:tokens) = ([], tokens)
-scanValue (Whitespace:tokens) = scanValue tokens
-
-scanValue tokens@(LeftCurlyBracket:_) = scanInner tokens scanValue
-scanValue tokens@(LeftParen:_) = scanInner tokens scanValue
-scanValue tokens@(Function _:_) = scanInner tokens scanValue
-scanValue tokens@(LeftSquareBracket:_) = scanInner tokens scanValue
--- To ensure parens are balanced, should already be handled.
-scanValue (RightCurlyBracket:tokens) = ([], RightCurlyBracket:tokens)
-scanValue (RightParen:tokens) = ([], RightParen:tokens)
-scanValue (RightSquareBracket:tokens) = ([], RightSquareBracket:tokens)
-
-scanValue tokens = capture scanValue tokens
-
--- | Returns tokens after a semicolon.
-skipValue :: [Token] -> [Token]
-skipValue tokens = snd $ scanValue tokens
+import Stylist.Parse
D src/Data/CSS/Syntax/StylishUtil.hs => src/Data/CSS/Syntax/StylishUtil.hs +0 -54
@@ 1,54 0,0 @@
--- | Utility parser combinators for parsing CSS stylesheets.
-module Data.CSS.Syntax.StylishUtil(
- concatP, capture, skipSpace,
- scanBlock, skipBlock, scanInner,
- Parser
- ) where
-
-import Data.CSS.Syntax.Tokens
-
--- | A simple parser combinator type.
-type Parser x = [Token] -> (x, [Token])
-
--- | Chains two parser combinators together.
-concatP :: (a -> b -> c) -> Parser a -> Parser b -> Parser c
-concatP join left right tokens = (join x y, remainder)
- where
- (x, tokens') = left tokens
- (y, remainder) = right tokens'
-
--- | "captures" the token being parsed into the returned output.
-capture :: Parser [Token] -> Parser [Token]
-capture cb (token:tokens) = (token:captured, tokens')
- where (captured, tokens') = cb tokens
-capture _ [] = ([], [])
-
--- | Removes preceding `Whitespace` tokens.
-skipSpace :: [Token] -> [Token]
-skipSpace (Whitespace:tokens) = skipSpace tokens
-skipSpace tokens = tokens
-
--- | Returns tokens until the next unbalanced closing brace.
-scanBlock :: Parser [Token]
--- TODO assert closing tags are correct
--- But what should the error recovery be?
-scanBlock (RightCurlyBracket:tokens) = ([RightCurlyBracket], tokens)
-scanBlock (RightParen:tokens) = ([RightParen], tokens)
-scanBlock (RightSquareBracket:tokens) = ([RightSquareBracket], tokens)
-
-scanBlock tokens@(LeftCurlyBracket:_) = scanInner tokens scanBlock
-scanBlock tokens@(LeftParen:_) = scanInner tokens scanBlock
-scanBlock tokens@(Function _:_) = scanInner tokens scanBlock
-scanBlock tokens@(LeftSquareBracket:_) = scanInner tokens scanBlock
-
-scanBlock tokens = capture scanBlock tokens
-
--- | Returns tokens after the next unbalanced closing brace.
-skipBlock :: [Token] -> [Token]
-skipBlock tokens = snd $ scanBlock tokens
-
--- | Parses a block followed by the given combinator, returning the tokens the matched.
-scanInner :: [Token] -> Parser [Token] -> ([Token], [Token])
-scanInner (token:tokens) cb = concatP gather scanBlock cb tokens
- where gather x y = token : x ++ y
-scanInner [] _ = error "Expected a token to capture."
M stylist.cabal => stylist.cabal +3 -4
@@ 59,8 59,7 @@ library
Data.CSS.Preprocessor.Assets, Data.CSS.Preprocessor.Text, Data.CSS.Preprocessor.PsuedoClasses
-- Modules included in this library but not exported.
- other-modules: Data.CSS.Syntax.StylishUtil,
- Data.CSS.Style.Importance, Data.CSS.Style.Common, Data.CSS.Style.Cascade,
+ other-modules: Data.CSS.Style.Importance, Data.CSS.Style.Common, Data.CSS.Style.Cascade,
Data.CSS.Style.Selector.Index, Data.CSS.Style.Selector.Interpret,
Data.CSS.Style.Selector.Specificity, Data.CSS.Style.Selector.LowerWhere
@@ 71,7 70,7 @@ library
build-depends: base >=4.9 && <5, css-syntax >=0.1 && <0.2, text,
unordered-containers >= 0.2 && <0.3, hashable,
network-uri >= 2.6 && <2.7, async >= 2.1 && <2.3,
- regex-tdfa >= 1.3
+ regex-tdfa >= 1.3, stylist-traits >= 0.1 && < 0.2
-- Directories containing source files.
hs-source-dirs: src
@@ 91,5 90,5 @@ test-suite test-stylist
unordered-containers >= 0.2 && <0.3, hashable,
network-uri >= 2.6 && <2.7, async >= 2.1 && <2.3,
regex-tdfa >= 1.3, hspec, QuickCheck,
- scientific >= 0.3 && <1.0, regex-tdfa >= 1.3
+ scientific >= 0.3 && <1.0, regex-tdfa >= 1.3, stylist-traits >= 0.1 && < 0.2
ghc-options: -Wall