~alcinnz/haskell-stylist

3630f677bc804ae9c6a86908e67b7e116a2123c0 — Adrian Cochrane 5 years ago 03ba02a
Draft html-conduit to Stylish Haskell bindings.
M stylish-html-conduit/src/Data/HTML2CSS.hs => stylish-html-conduit/src/Data/HTML2CSS.hs +89 -2
@@ 1,5 1,92 @@
{-# LANGUAGE OverloadedStrings #-}
module Data.HTML2CSS(
        
        externalStyles, internalStyles,
        cssPriorityAgent, cssPriorityUser, cssPriorityAuthor,
        traverseStyles, traverseStyles', elToStylish
    ) where

-- TODO
import qualified Data.List as L
import qualified Data.Map as M
import qualified Data.Text as Txt

import qualified Text.XML as XML
import Data.CSS.Syntax.StyleSheet
import Data.CSS.Style

import Network.URI

---- Constants
cssPriorityAgent = 1
cssPriorityUser = 2
cssPriorityAuthor = 3

---- Parsing
externalStyles :: PropertyParser s => QueryableStyleSheet s -> (M.Map XML.Name Txt.Text -> Bool) ->
        XML.Element -> (URI -> IO Txt.Text) -> IO (QueryableStyleSheet s)
externalStyles stylesheet testMedia html loadURL = do
    css <- externalStyles' testMedia html loadURL
    return $ foldl parse stylesheet {priority = cssPriorityAuthor} css
externalStyles' testMedia html loadURL = go $ linkedStyles' testMedia html
    where -- TODO parallelise loads
        go (link:links) = do
            response <- loadURL $ link
            rest <- go links
            return $ response : rest
        go [] = return []

linkedStyles' testMedia (XML.Element (XML.Name "link" _ _) attrs _)
    | Just link <- "href" `M.lookup` attrs,
        Just "stylesheet" <- "rel" `M.lookup` attrs,
        testMedia attrs,
        Just uri <- parseURIReference $ Txt.unpack link = [uri]
linkedStyles' testMedia (XML.Element _ _ children) =
    concat [linkedStyles' testMedia el | XML.NodeElement el <- children]

internalStyles testMedia stylesheet html =
    foldl parse (stylesheet {priority = cssPriorityAuthor}) $ internalStyles' testMedia html
internalStyles' testMedia (XML.Element (XML.Name "style"_ _) attrs children)
    | testMedia attrs = [strContent children]
internalStyles' testMedia (XML.Element _ _ children) =
    concat [internalStyles' testMedia el | XML.NodeElement el <- children]


strContent :: [XML.Node] -> Txt.Text
strContent (XML.NodeContent text : rest) = text `Txt.append` strContent rest
-- We do want to read in comments for CSS, just not for display.
strContent (XML.NodeComment text : rest) = text `Txt.append` strContent rest
strContent (XML.NodeElement (XML.Element _ _ children):rest) =
    strContent children `Txt.append` strContent rest
strContent (_:rest) = strContent rest
strContent [] = ""

---- Styling
traverseStyles :: PropertyParser s => (s -> [s] -> s) -> (Txt.Text -> s) -> 
        QueryableStyleSheet s -> XML.Element -> s
traverseStyles = traverseStyles' Nothing temp Nothing
traverseStyles' parent parentStyle previous builder textBuilder stylesheet el@(
        XML.Element _ _ children
    ) = builder style $ traverseChildren Nothing children
    where
        stylishEl = elToStylish el parent previous
        maybeEl = Just stylishEl
        style = cascade stylesheet stylishEl overrides parentStyle
        overrides = [] -- TODO

        traverseChildren prev (XML.NodeContent txt:nodes) =
            textBuilder txt : traverseChildren prev nodes
        traverseChildren prev (XML.NodeElement el:nodes) =
            traverseStyles' maybeEl style prev builder textBuilder stylesheet el :
                traverseChildren (Just $ elToStylish el maybeEl prev) nodes
        traverseChildren prev (_:nodes) = traverseChildren prev nodes
        traverseChildren _ [] = []

elToStylish (XML.Element (XML.Name name _ _) attrs _) parent previous =
    ElementNode {
        name = name,
        attributes = L.sort [
            Attribute (XML.nameLocalName name) (Txt.unpack value)
            | (name, value) <- M.toList attrs
        ],
        parent = parent,
        previous = previous
    }

M stylish-html-conduit/stylish-html-conduit.cabal => stylish-html-conduit/stylish-html-conduit.cabal +5 -2
@@ 51,7 51,7 @@ cabal-version:       >=1.10

library
  -- Modules exported by the library.
  -- exposed-modules:     
  exposed-modules:     Data.HTML2CSS
  
  -- Modules included in this library but not exported.
  -- other-modules:       


@@ 60,7 60,10 @@ library
  -- other-extensions:    
  
  -- Other library packages from which modules are imported.
  build-depends:       base >=4.9 && <4.10
  build-depends:       base >=4.9 && <4.10,
                       stylish-haskell >= 0.2.1,
                       xml-conduit, text, containers,
                       network-uri
  
  -- Directories containing source files.
  hs-source-dirs:      src