~alcinnz/haskell-stylist

dc7809767970bbbcd9cb8606b952c6d0acff47c0 — Adrian Cochrane 4 years ago 52e91d5
Provide utilities for rewriting CSS-referenced URLs.
2 files changed, 48 insertions(+), 1 deletions(-)

A src/Data/CSS/Preprocessor/Assets.hs
M stylist.cabal
A src/Data/CSS/Preprocessor/Assets.hs => src/Data/CSS/Preprocessor/Assets.hs +44 -0
@@ 0,0 1,44 @@
module Data.CSS.Preprocessor.Assets(StyleAssets(..), URIRewriter) where

-- TODO Unit test!
import           Data.Text as Txt
import           Network.URI
import qualified Data.CSS.Syntax.StyleSheet as CSS
import qualified Data.CSS.Syntax.Tokens as CSSTok

-- | Extracts referenced URLs from specified properties.
data StyleAssets = StyleAssets {
    -- | The properties from which to extract URLs.
    filterProps :: [Txt.Text],
    -- | The extracted URLs.
    assets :: [URI]
}

instance CSS.StyleSheet StyleAssets where
    addRule (StyleAssets filterProps self) (CSS.StyleRule _ props _) =
        StyleAssets filterProps $ nub (
            self ++ [uri | (prop, val) <- props,
                    prop `elem` filterProps,
                    CSSTok.Url text <- val,
                    Just uri <- [parseAbsoluteURI $ Txt.unpack text]]
            )


-- | Substitutes in given URLs into a property value.
rewritePropertyVal rewrites (CSSTok.Url text:vals)
    | Just uri <- parseURIReference $ Txt.unpack text, Just rewrite <- uri `M.lookup` rewrites =
        CSSTok.Url (Txt.pack $ uriToString id rewrite "") : rewritePropertyVal rewrites vals
    | otherwise = CSSTok.Url "" : rewritePropertyVal rewrites vals
rewritePropertyVal rewrites (val:vals) = val:rewritePropertyVal rewrites vals
rewritePropertyVal _ [] = []

-- | Substitutes in given URLs into the inner stylesheet being parsed.
data URIRewriter s = URIRewriter (M.Map URI URI) s
instance CSS.StyleSheet s => CSS.StyleSheet (URIRewriter s) where
    setPriority p (URIRewriter r s) = URIRewriter r $ CSS.setPriority p s
    addRule (URIRewriter r s) (CSS.StyleRule sel props psuedo) =
        URIRewriter r $ CSS.addRule s $ CSS.StyleRule sel [
            (prop, rewritePropertyVal r val) | (prop, val) <- props
        ] psuedo
    addAtRule (URIRewriter r s) name toks =
        let (self', toks') = CSS.addAtRule s name toks in (URIRewriter r s, toks)

M stylist.cabal => stylist.cabal +4 -1
@@ 53,7 53,10 @@ source-repository head

library
  -- Modules exported by the library.
  exposed-modules:     Data.CSS.Syntax.StyleSheet, Data.CSS.Syntax.Selector, Data.CSS.Style, Data.CSS.Preprocessor.Conditions, Data.CSS.Preprocessor.Conditions.Expr
  exposed-modules:     Data.CSS.Syntax.StyleSheet, Data.CSS.Syntax.Selector,
                       Data.CSS.Style,
                       Data.CSS.Preprocessor.Conditions, Data.CSS.Preprocessor.Conditions.Expr,
                       Data.CSS.Preprocessor.Assets
  
  -- Modules included in this library but not exported.
  other-modules:       Data.CSS.Syntax.StylishUtil,