packages feed

fathead-util-0.1.0.0: src/DDG/FatHead/Util/Parse.hs

module DDG.FatHead.Util.Parse
  ( hasClass
  , withClass
  , readHaddockDocument
  , eltUrl
  , defaultAbstract
  , definitionList
  ) where


import Text.XML.HXT.Core
import Data.Monoid ((<>))
import Data.Tree.NTree.TypeDefs (NTree)
import Network.URI (URI, parseURI)
import Data.Maybe (fromJust)


pagePath :: String -> FilePath
pagePath = (basePath<>)
  where basePath = "download/haddock/doc/html/"


readHaddockDocument :: String -> IOStateArrow s b XmlTree
readHaddockDocument = readDocument sysConfig . pagePath
  where sysConfig = [withInputEncoding iso8859_1, withParseHTML yes]


hasClass :: ArrowXml a => String -> a XmlTree XmlTree
hasClass c = hasAttrValue "class" (==c)


buildAbstract :: ArrowXml a => a b XmlTree -> a b String
buildAbstract p = (eelem "span" += p >>> normalizeText >>> writeDocumentToString [withOutputHTML, withRemoveWS yes])
                  >. (makeAbstract . concat)
  where makeAbstract = id


normalizeText :: ArrowXml a => a XmlTree XmlTree
normalizeText = processTopDown $ choiceA [ hasName "p" :-> normalizeP
                                         , hasName "pre" :-> normalizePre
                                         , this :-> this]
  where normalizeP = processChildren (changeText (unwords . lines) `when` isText)
        normalizePre = processChildren (changeText (escapeNewlines . stringTrim) `when` isText)
        escapeNewlines = concatMap (\x -> if x == '\n' then "\\n" else [x])


makeSourceLink :: (Arrow a) => String -> a String URI
makeSourceLink page = arr (base<>) >>> arr parseURIWithBase
  where base = "http://www.haskell.org/haddock/doc/html/" <> page <> "#"
        parseURIWithBase = maybe (fromJust $ parseURI base) id . parseURI


withClass :: ArrowXml cat => String -> String -> cat XmlTree XmlTree
withClass n c = hasName n >>> hasClass c


-- | Pairs of @(<dt>, <dd>)@ tags (terms and definitions).
definitionList :: (ArrowXml a, ArrowList a) => a XmlTree (XmlTree, XmlTree)
definitionList = listA (getChildren >>> (dt <+> dd))
                 >>> partitionA dt >>> arr pairs >>> unlistA
  where pairs = uncurry zip
        dt = hasName "dt"
        dd = hasName "dd"


defaultAbstract :: IOSLA (XIOState ()) (NTree XNode) String
defaultAbstract = buildAbstract isAbstract
  where isAbstract = getChildren >>> (hasName "p") <+> (hasName "pre")


-- | Create a source URL appropriate for use in articles from
-- the current element's name and page.
eltUrl :: String -> IOSLA (XIOState ()) XmlTree URI
eltUrl page = anchor >>> makeSourceLink page
  where anchor = hasAttr "name" >>> getAttrValue "name"