module DocGen(htmlDoclet) where import List import Maybe import Monad (when) import Html import HDoclet displayBreakLength :: Int displayBreakLength = 30 htmlFile :: ModuleDoc -> String htmlFile md = moduleName md ++ ".html" class CanAppear a => AnchorLink a where makeAnchor :: a -> Html -> Html makeLinkU :: a -> [HtmlAttr] -> Html -> Html makeLink :: AnchorLink a => a -> Html -> Html makeLink d = makeLink' d [] makeLink' :: AnchorLink a => a -> [HtmlAttr] -> Html -> Html makeLink' d a | appearsInOutput d = makeLinkU d a | otherwise = id makeLinkUncond :: AnchorLink a => a -> Html -> Html makeLinkUncond d = makeLinkU d [] instance AnchorLink ModuleDoc where makeAnchor _ l = l makeLinkU md a = anchor ! (href (htmlFile md) : a) instance AnchorLink FunctionDoc where makeAnchor fd = anchor ! [name $ fanchor fd] makeLinkU fd a = anchor ! (href (htmlFile (themodule fd) ++ ('#' : fanchor fd)) : a) fanchor :: FunctionDoc -> String fanchor (fd @ (FunctionDoc {funclass=Instance id})) = fullname fd ++ ('_' : ianchor id) fanchor fd = fullname fd instance AnchorLink ClassDoc where makeAnchor cd = anchor ! [name $ fullname cd] makeLinkU cd a = anchor ! (href (htmlFile (themodule cd) ++ ('#' : fullname cd)) : a) instance AnchorLink DataDoc where makeAnchor dd = anchor ! [name $ fullname dd] makeLinkU dd a = anchor ! (href (htmlFile (themodule dd) ++ ('#' : fullname dd)) : a) instance AnchorLink TypeDoc where makeAnchor td = anchor ! [name $ fullname td] makeLinkU td a = anchor ! (href (htmlFile (themodule td) ++ ('#' : fullname td)) : a) instance AnchorLink InstanceDoc where makeAnchor id = anchor ! [name $ ianchor id] makeLinkU id a = anchor ! (href (htmlFile (themodule id) ++ ('#' : ianchor id)) : a) instance AnchorLink HDR where makeLinkU (FunctionRef f) = makeLinkU f makeLinkU (TypeRef t) = makeLinkU t makeLinkU (DataRef d) = makeLinkU d makeLinkU (ClassRef c) = makeLinkU c makeAnchor _ = error "makeAnchor should never be called for a HDR." ianchor :: InstanceDoc -> String ianchor id = type2text (typedef id) type2html :: Type -> Html type2html t = printType t htmlTyIdPrinter stringToHtml (+++) type2html_paren :: Type -> Html type2html_paren t@(Simple _) = type2html t type2html_paren t@(List _) = type2html t type2html_paren t@(Tuple _) = type2html t type2html_paren t = "(" +++ type2html t +++ ")" type2text :: Type -> String type2text t = printType t textTyIdPrinter id (++) htmlTyIdPrinter :: (HsQName, TypeId) -> Html htmlTyIdPrinter (n, TyUnknown ) = stringToHtml (hsQNameToString n) htmlTyIdPrinter (n, TyVar ) = stringToHtml (hsQNameToString n) htmlTyIdPrinter (n, TyType td) = makeLink td << (hsQNameToString n) htmlTyIdPrinter (n, TyData dd) = makeLink dd << (hsQNameToString n) htmlTyIdPrinter (n, TyClass cd) = makeLink cd << (hsQNameToString n) textTyIdPrinter :: (HsQName, TypeId) -> String textTyIdPrinter (n, _) = hsQNameToString n printType :: Type -> ((HsQName,TypeId) -> a) -> (String -> a) -> (a -> a -> a) -> a printType ty printer strconv conc = pt' (-1) ty where -- pt' :: Integer -> Type -> a (where `a' is the a from printType...) pt' _ (Simple s) = printer s pt' _ (Context c t) = pt' 0 c `conc` strconv " => " `conc` pt' 0 t pt' p (Con s ts) = strconv oP `conc` printer s `conc` strconv " " `conc` foldl comp (strconv "") (map (pt' 2) ts) `conc` strconv cP where comp x y = x `conc` (strconv " ") `conc` y (oP, cP) = if (p == 2) then ("(", ")") else ("", "") pt' _ (List t) = strconv "[" `conc` pt' 0 t `conc` strconv "]" pt' _ (Tuple ts) = strconv "(" `conc` genIntersp (strconv ", ") (strconv "") conc (map (pt' 0) ts) `conc` strconv ")" pt' p (Fun t1 t2) = strconv oP `conc` pt' 1 t1 `conc` strconv " -> " `conc` pt' 0 t2 `conc` strconv cP where (oP, cP) = if (p >= 1) then ("(", ")") else ("", "") pt' p (Forall vs t) = strconv (oP ++ "forall" ++ concat [' ':v | v <- vs] ++ ". ") `conc` pt' 0 t `conc` strconv cP where (oP, cP) = if p >= 0 then ("(", ")") else ("", "") typed2html' :: Integer -> Bool -> Typed -> Html typed2html' p True (Typed ty t) = oP +++ typed2html' 0 True ty +++ primHtml " :: " +++ type2html t +++ cP where (oP, cP) = if p >= 1 then ("(", ")") else ("" , "" ) typed2html' p False (Typed ty _) = typed2html' p False ty typed2html' _ b (SimpleT s) = stringToHtml s typed2html' p b (ConT s ts) = oP +++ s +++ " " +++ intersp' " " (map (typed2html' 2 b) ts) +++ cP where (oP, cP) = if p == 2 then ("(", ")") else ("" , "" ) typed2html' _ b (ContextT t1 t2) = typed2html' 0 b t1 +++ " => " +++ typed2html' 0 b t2 typed2html' _ b (ListT ty) = "[" +++ typed2html' 0 b ty +++ "]" typed2html' _ b (TupleT tys) = "(" +++ intersp' ", " (map (typed2html' 0 b) tys) +++ ")" typed2html' p b (FunT ty1 ty2) = oP +++ typed2html' 1 b ty1 +++ " -> " +++ typed2html' 0 b ty2 +++ cP where (oP, cP) = if (p >= 1) then ("(", ")") else ("" , "" ) -- ensure that parenthesis are put around the expression when if -- there is no "(...)" or "[...]" around it and it is not a -- single word typed2html_paren :: Typed -> Html typed2html_paren ty@(TupleT _) = typed2html ty typed2html_paren ty@(SimpleT _) = typed2html ty typed2html_paren ty@(ListT _) = typed2html ty typed2html_paren ty = "(" +++ typed2html ty +++ ")" typed_wo_t :: Typed -> Html typed_wo_t = typed2html' 0 False typed2html = typed2html' 0 True instance HTML HDocElement where toHtml = hde2html hde2html (HdeText str) = stringToHtml str hde2html (HdeTag1 BrTag) = br hde2html (HdeTag2 t2 tas h) = (case t2 of CodeTag -> thecode PreTag -> pre EmTag -> emphasize TTTag -> tt ItalicsTag -> italics StrongTag -> strong BoldTag -> bold ParagraphTag -> paragraph AnchorTag -> anchor ) ! (mkAttrs tas) << h hde2html (HdeUnicode u) = primHtml (unicodeHtml u) hde2html HdeWhiteSpace = stringToHtml " " hde2html x = error ("hdocText2html:\n " ++ show x ++ "\nunimplemented") mkAttrs :: [TagAttr] -> [HtmlAttr] mkAttrs = map mkAttr where mkAttr :: TagAttr -> HtmlAttr mkAttr (TaHref v) = href v mkAttr (TaClass v) = theclass v moduleDoc2html :: ModuleDoc -> Html moduleDoc2html md = makeAnchor md << h2 << ("module " ++ moduleName md) +++ condH modBodyNotEmpty modBody where modBody = hr +++ "module " +++ (bold << moduleName md) +++ p << (description md) +++ condH (notnull auth) << p << (bold << "Author: " +++ auth) +++ condH (notnull ver ) << p << (bold << "Version: "+++ ver) +++ condH (notnull see) << p << makeSeeAlso see auth = authorM md ver = versionM md see = seeTags md modBodyNotEmpty = any notnull [description md, auth, ver] || notnull see funDoc2html :: FunctionDoc -> Html funDoc2html fd = p << makeAnchor fd << fullsig +++ condH (isJust $ retdescr fd) (p << thecode << callsig) +++ dlist << (ddef << description fd +++ ddef << (dlist << ((if length (paramlist fd) > 0 then dterm << bold << "Arguments:" +++ pardesc else stringToHtml "") +++ (if isJust (retdescr fd) then dterm (bold << "Returns:") +++ ddef << retexpl else stringToHtml "") +++ classdesc +++ condH (notnull $ seeTags fd) (dterm << bold << "See Also:" +++ ddef << makeSeeList (seeTags fd))))) where Just (retdef, retexpl, rettype) = retdescr fd pardesc = map mkP (paramlist fd) fullsig = case signature fd of Nothing -> oneLineTable [(headFont << bold << prefixname fd, [])] Just sig -> oneLineTable [(headFont << bold << prefixname fd, []), (headFont << stringToHtml "::", []), (headFont << type2html sig, [])] callsig = (if isJust (retdescr fd) then (case (retdef, rettype) of (Nothing, _) -> stringToHtml "" (Just d, Functional)-> typed2html_paren d +++ " = " (Just d, Monadic) -> typed2html_paren d +++" <- ") else stringToHtml "") +++ stringToHtml (prefixname fd) +++ " " +++ intersp' " " (map (\(def,des) -> typed2html_paren def) (paramlist fd)) mkP (pdef, pdescr) = ddef << (thecode << typed_wo_t pdef +++ condH (notnull pdescr) (primHtml " - " +++ pdescr)) classdesc = case (funclass fd) of NoClass -> stringToHtml "" Class cd -> dterm << "Member of class: " +++ makeLink cd << bold << thename cd Instance id -> dterm << "Belongs to instance: " +++ makeLink id << bold << (type2text $ typedef id) dataDoc2html :: (DataDoc, [ConstructorDoc]) -> Html dataDoc2html (dd, shownConstructors) = p << makeAnchor dd << headFont << type2html (typedef dd) +++ miniTable dataCode +++ (dlist << (ddef << description dd +++ condH (notnull shownConstructors) (ddef (dlist << (dterm << bold << constructors +++ consdesc +++ condH (notnull $ seeTags dd) (dterm << bold << "See Also:" +++ ddef << makeSeeList (seeTags dd))) ) ) ) ) where dataCode | null shownConstructors = [[(dataDef +++ condH (notnull $ derivedInstances dd) deriv, nowrR)]] | length (type2text $ typedef dd) > displayBreakLength = [(dataDef1 +++ aSpace, nowrR), (dataDef2,[nowrap])] : [[(a,[align "right"]),(b,[])] | (a,b) <- zip (thecode << (fourSpaces +++ "=") : repeat (thecode << (fourSpaces +++ "|"))) constrColumn] ++ derivRow | otherwise = [[(x,nowrR),(cons,[])] | (x,cons) <- zip ((dataDef +++ thecode << " = ") : repeat (thecode << ("| "))) constrColumn] ++ derivRow constrColumn = map mkCshort shownConstructors derivRow = if null (derivedInstances dd) then [] else [[(stringToHtml "", []), (deriv, [])]] deriv = boldcode << " deriving" +++ thecode << (" (" +++ derived +++ ")") dataDef = dataDef1 +++ " " +++ dataDef2 dataDef1 = boldcode << data_or_nt dataDef2 = thecode << type2html (typedef dd) data_or_nt = primHtml $ if isNewType dd then " newtype " else " data " constructors = if isNewType dd then "Constructor:" else "Constructors:" mkCshort (ConstructorDoc (Constructor n fas ctx _ ts) _) = thecode << (showFAS fas +++ showOptContext ctx +++ if ":" `isPrefixOf` n && length ts >= 2 then type2html_paren (head ts) +++ " " +++ n +++ " " +++ intersp' " " (map type2html_paren (tail ts)) else n +++ " " +++ intersp' " " (map type2html_paren ts) ) mkCshort (ConstructorDoc (Labelled t tl) _) = thecode << (t +++ " { " +++ intersp' ", " (map typed2html tl) +++ " }") consdesc = map mkC shownConstructors mkC (ConstructorDoc (Constructor n fas _ tt _) d) = ddef << (thecode << co +++ condH (notnull d) (primHtml " - " +++ d)) where co = ({-showFAS fas +++-} if ":" `isPrefixOf` n && length tt >= 2 then typed_wo_t (head tt) +++ " " +++ n +++ " " +++ intersp' " " (map typed_wo_t (tail tt)) else n +++ " " +++ intersp' " " (map typed_wo_t tt) ) mkC (ConstructorDoc (Labelled c tl) d) = ddef << thecode << (c +++ " { " +++ intersp' ", " (map typed_wo_t tl) +++ " } " +++ condH (notnull d) (primHtml " - " +++ d)) derived = intersp' ", " (map stringToHtml (derivedInstances dd)) typeDoc2html :: (TypeDoc, Maybe Type) -> Html typeDoc2html (td, c) = p << makeAnchor td << headFont << type2html (typedef td) +++ oneLineTable [(boldcode << (aSpace +++ "type "), nowrR), (thecode << type2html (typedef td) +++ constr, [])] +++ condH (hasDesc || hasSee) (dlist << (condH hasDesc (ddef << description td) +++ condH hasSee (ddef << dlist << (dterm << bold << "See Also:" +++ ddef << makeSeeList (seeTags td))))) where hasDesc = notnull $ description td hasSee = notnull $ seeTags td constr = case c of Nothing -> stringToHtml "" Just co -> "=" +++ aSpace +++ thecode << type2html co classDoc2html :: (ClassDoc, [InstanceDoc]) -> Html classDoc2html (cd, knownInsts) = p << makeAnchor cd << headFont << type2html (typedef cd ) +++ p << description cd +++ classInstTable "class " cd memberFunctions (functionalDeps cd) origSig +++ condH (notnull knownInsts) ("Known instances: " +++ (ulist ! [compact] << map ilink knownInsts)) +++ condH (notnull $ seeTags cd) (p << makeSeeAlso (seeTags cd)) where ilink i = li << makeLink i << (type2text (typedef i)) classInstTable :: HasTypedef a => String -> a -> (a -> [FunctionDoc]) -> [FunDep] -> (FunctionDoc -> Maybe Type) -> Html classInstTable classInst obj theFuncs fundeps signat = p << table << (topRow : [mkF f | f <- theFuncs obj]) where topRow = tr << [td!(valign "top" : nowrR) << boldcode << classInst, td![valign "top", colspan 3] << (thecode << (type2html (typedef obj) +++ fundepsStr) +++ boldcode << " where")] mkF f = tr << ([td << "", td ! [valign "top"] << makeLink f << thecode << prefixname f] ++ case signat f of Nothing -> [] Just t -> [td ! [valign "top"] << thecode << "::", td ! [valign "top"] << thecode << type2html t] ) +++ condH (notnull $ description f) (tr << ([td << "", td << "", td << "", td << summary f])) fundepsStr | null fundeps = "" | otherwise = " | " ++ concat (intersperse ", " [vlist vs1 ++ " -> " ++ vlist vs2 | (vs1,vs2) <- fundeps]) vlist vs = concat (intersperse " " vs) instanceDoc2html :: InstanceDoc -> Html instanceDoc2html id = p << makeAnchor id << headFont << type2html (typedef id) +++ p << description id +++ classInstTable "instance " id instanceFunctions [] signature +++ condH (notnull $ seeTags id) (p << makeSeeAlso (seeTags id)) dataSummary :: [(DataDoc, [ConstructorDoc])] -> Html dataSummary dds = stdTable "Data Type Summary" [[mkDS d] | d <- dds] where mkDS (dd, shownConstructors) = dataSum +++ indentedDescriptionNoBr (summary dd) where dataSum = oneLineTable [(boldcodeSP << data_or_nt, nowrR), (thecode << (type2html (typedef dd) +++ conssum +++ deriv), [])] data_or_nt = if isNewType dd then "newtype " else "data " conssum = condH (notnull shownConstructors) (" = " +++ conses) conses = intersp' " | " (map mkCons shownConstructors) deriv = condH (notnull $ derivedInstances dd) (bold << " deriving" +++ " (" +++ derived +++ ")") mkCons (ConstructorDoc (Constructor n fas ctx _ ts) _) | ":" `isPrefixOf` n && length ts >= 2 = showFAS fas +++ showOptContext ctx +++ type2html_paren (head ts) +++ " " +++ n +++ " " +++ intersp' " " (map type2html_paren (tail ts)) | otherwise = showFAS fas +++ showOptContext ctx +++ n +++ " " +++ intersp' " " (map type2html_paren ts) mkCons (ConstructorDoc (Labelled c tl) _) = c +++ " { " +++ intersp' ", " (map typed2html tl) +++ " }" derived = intersp' ", " (map stringToHtml (derivedInstances dd)) typesynSummary :: [(TypeDoc, Maybe Type)] -> Html typesynSummary ts = stdTable "Type Synonyms Summary" [[mkTD t] | t <- ts] where mkTD (td,c) = oneLineTable [(boldcodeSP << "type ", nowrR), (thecode (type2html (typedef td) +++ constr), [])] +++ indentedDescriptionNoBr (summary td) where constr = case c of Nothing -> stringToHtml "" Just co -> " = " +++ type2html co classSummary :: [(ClassDoc, [InstanceDoc])] -> Html classSummary cs = stdTable "Class Summary" [[mkCS c] | c <- cs] where mkCS (c, _) = oneLineTable[(boldcodeSP << "class ", nowrR), (thecode << type2html (typedef c), [])] +++ indentedDescriptionNoBr (summary c) instanceSummary :: [InstanceDoc] -> Html instanceSummary is = stdTable "Instance Summary" [[mkIS i] | i <- is] where mkIS i = oneLineTable [(boldcodeSP << "instance ", nowrR), (thecode << makeLink i << (type2text $ typedef i), [])] +++ indentedDescriptionNoBr (summary i) funSummary :: [FunctionDoc] -> Html funSummary dl = stdTable "Function Summary" [[mkFD d] | d <- dl] where mkFD :: FunctionDoc -> Html mkFD f = oneLineTable ((thecode << (aSpace +++ makeLink f< [] Just s -> [(thecode << "::", [nowrap]), (thecode << type2html s, [])] alsoAvailTs :: [(TypeDoc, Maybe Type)] -> Html alsoAvailTs ts = alsoAvail "Type synonyms also available through this module" nameLinkUC (map fst ts) alsoAvailDs :: [(DataDoc, [ConstructorDoc])] -> Html alsoAvailDs ds = alsoAvail "Datatypes also available through this module" nameLinkUC (map fst ds) alsoAvailCs :: [(ClassDoc, [InstanceDoc])] -> Html alsoAvailCs cs = alsoAvail "Classes also available through this module" nameLinkUC (map fst cs) alsoAvailIs :: [InstanceDoc] -> Html alsoAvailIs is = alsoAvail "Instances also available through this module" iLink is where iLink i = makeLinkUncond i << type2text (typedef i) alsoAvailFs :: [FunctionDoc] -> Html alsoAvailFs fs = alsoAvail "Functions also available through this module" mkF fs where mkF f = makeLinkUncond f << prefixname f +++ info where info = case funclass f of NoClass -> stringToHtml "" Class cd -> font ! [size "-1"] << (" (" ++ thename cd ++ ")") Instance id -> font ! [size "-1"] << (" (" ++ type2text (typedef id)++ ")") alsoAvail :: String -> (a -> Html) -> [a] -> Html alsoAvail tableTitle f objs = stdTable tableTitle [[enumObjs]] where enumObjs = intersp' ", " (map mk objs) mk o = thecode << f o nameLinkUC :: (AnchorLink a, HasHDocName a) => a -> Html nameLinkUC o = makeLinkUncond o << prefixname o showFAS :: [String] -> Html showFAS [] = stringToHtml "" showFAS xs = stringToHtml ("forall" ++ concat [' ':x | x <- xs] ++ ". ") showOptContext :: Maybe Type -> Html showOptContext Nothing = stringToHtml "" showOptContext (Just t) = type2html t +++ " => " css :: FilePath -> Html css file = thelink ! [rel "stylesheet", thetype "text/css", href file] << "" makeDoc :: HDocSettings -> FilePath -> DocumentedModule -> Html makeDoc hdSet styleSheetFile dm = header << (css styleSheetFile +++ thetitle << ("Module " ++ moduleName md) )+++ body << (moduleDoc2html md +++ hr +++ condH (notnull tds) << p << typesynSummary tds +++ condH (notnull dds) << p << dataSummary dds +++ condH (notnull cds) << p << classSummary cds +++ condH (notnull ids) << p << instanceSummary ids +++ condH (notnull fds) << p << funSummary fds +++ condH (notnull alsoTs) << p << alsoAvailTs alsoTs +++ condH (notnull alsoDs) << p << alsoAvailDs alsoDs +++ condH (notnull alsoCs) << p << alsoAvailCs alsoCs +++ condH (notnull alsoIs) << p << alsoAvailIs alsoIs +++ condH (notnull alsoFs) << p << alsoAvailFs alsoFs +++ condH (notnull tds) << p << (partHeading "Type Synonyms" +++ intersp hr (map td2h tds)) +++ condH (notnull dds) << p << (partHeading "Data Types" +++ intersp hr (map dd2h dds)) +++ condH (notnull cds) << p << (partHeading "Classes" +++ intersp hr (map cd2h cds))+++ condH (notnull ids) << p << (partHeading "Instances" +++ intersp hr (map id2h ids)) +++ condH (notnull fds) << p << (partHeading "Function Detail" +++ intersp hr (map fd2h fds)) ) where fd2h fd = condH (hdsLineNumbers hdSet) (line fd) +++ funDoc2html fd cd2h c@(cd,_) = condH (hdsLineNumbers hdSet) (line cd) +++ classDoc2html c id2h id = condH (hdsLineNumbers hdSet) (line id) +++ instanceDoc2html id dd2h d@(dd,_) = condH (hdsLineNumbers hdSet) (line dd) +++ dataDoc2html d td2h t@(td,_) = condH (hdsLineNumbers hdSet) (line td) +++ typeDoc2html t line :: HasHDocName a => a -> Html line obj = thecode << ("line " ++ show (lineNumber obj)) +++ br md = documentedModule dm fds = documentedFunctions dm tds = documentedTypesynonyms dm dds = documentedDatatypes dm cds = documentedClasses dm ids = documentedInstances dm alsoFs = alsoFunctions dm alsoTs = alsoTypesynonyms dm alsoDs = alsoDatatypes dm alsoCs = alsoClasses dm alsoIs = alsoInstances dm notnull = not . null aSpace = primHtml " " twoSpaces = primHtml "  " fourSpaces = primHtml "    " tenSpaces = primHtml ("      " ++ "    ") nowrR :: [HtmlAttr] nowrR = [nowrap, align "right"] headFont :: Html -> Html headFont h = h3 << h -- ... boldcode :: Html -> Html boldcode h = thecode << bold << h --  ... boldcodeSP :: Html -> Html boldcodeSP h = thecode << (aSpace +++ bold << h) condH :: Bool -> Html -> Html condH True html = html condH False _ = stringToHtml "" intersp :: Html -> [Html] -> Html intersp _ [] = stringToHtml "" intersp inter hl = foldl1 (\x y -> x +++ inter +++ y) hl intersp' :: String -> [Html] -> Html intersp' inter = intersp (stringToHtml inter) genIntersp :: a -> a -> (a -> a -> a) -> [a] -> a genIntersp sep start conc = inter where inter [] = start inter (x:xs) = case xs of [] -> x _ -> x `conc` sep `conc` inter xs indentedDescription :: HDocText -> Html indentedDescription [] = stringToHtml "" indentedDescription text = br +++ oneLineTable [(fourSpaces,[nowrap]), (toHtml text,[])] indentedDescriptionNoBr :: HDocText -> Html indentedDescriptionNoBr [] = stringToHtml "" indentedDescriptionNoBr text = oneLineTable [(fourSpaces,[nowrap]), (toHtml text,[])] -- generate a table with the title `heading'. -- Each element of rows is the list of columns for the corresponding row. -- Each row must have the same number of entries! -- The heading gets a "class" attribute of "TableHeadingColor", -- all other rows get "TableRowColor". stdTable :: String -> [[Html]] -> Html stdTable heading rows = (table ! [border 1, width "100%"] << (tr ! [theclass "TableHeadingColor"] << td ! [colspan maxW] << font ! [size "+2"] << bold << heading +++ foldl (\x row -> x +++ (tr ! [theclass "TableRowColor"] << foldl (\x e -> x +++ (td << e)) (stringToHtml "") row)) (stringToHtml "") rows)) where maxW = maximum (0:(map length rows)) miniTable :: [[(Html,[HtmlAttr])]] -> Html miniTable rows = table << [tr ! [valign "top"] << [td ! attrs << c | (c,attrs) <- cs] | cs <- rows] oneLineTable :: [(Html,[HtmlAttr])] -> Html oneLineTable cols = miniTable [cols] -- Produce a table which has only a heading, but no other rows. partHeading :: String -> Html partHeading heading = stdTable heading [] makeFunIndex :: [FunctionDoc] -> Html makeFunIndex funs = makeIndexTable "Index of functions" (map mk funs) where mk :: FunctionDoc -> Html mk fd = makeLink' fd [target "mainFrame"] << prefixname fd +++ info where info = case funclass fd of NoClass -> stringToHtml "" Class cd -> font ! [size "-2"] << (" (" ++ thename cd ++ ")") Instance id -> font ! [size "-2"] << (" (" ++ type2text (typedef id)++ ")") makeDataIndex :: [TypeDoc] -> [DataDoc] -> Html makeDataIndex ts ds = condH (notnull ts) (makeIndexTable "Index of typesynonyms" (map typedefLink2mainFrame ts)) +++ condH (notnull ts && notnull ds) hr +++ condH (notnull ds) (makeIndexTable "Index of datatypes" (map typedefLink2mainFrame ds)) makeClassIndex :: [ClassDoc] -> Html makeClassIndex cs = makeIndexTable "Index of classes" (map typedefLink2mainFrame cs) makeInstanceIndex :: [InstanceDoc] -> Html makeInstanceIndex is = makeIndexTable "Index of instances" (map typedefLink2mainFrame is) typedefLink2mainFrame :: (AnchorLink a, HasTypedef a) => a -> Html typedefLink2mainFrame obj = makeLink' obj [target "mainFrame"] << type2text (typedef obj) makeIndexTable :: String -> [Html] -> Html makeIndexTable titleText xs = table ! [border 0, width "100%"] << [tr << td![nowrap] << (font![size "+1",theclass "FrameHeadingFont"] << titleText +++ [br +++ font![theclass "FrameItemFont"] << x | x <- xs])] makeSeeAlso :: [HDR] -> Html makeSeeAlso hdrs = bold << "See also:" +++ br +++ primHtml "  " +++ makeSeeList hdrs makeSeeList :: [HDR] -> Html makeSeeList hdrs = intersp' ", " [makeLink h << prefixname h | h <- hdrs] makeModIndex :: FilePath -> [ModuleDoc] -> Html makeModIndex cssFile mods = header << (css cssFile +++ thetitle << "Index of modules" ) +++ body << makeIndexTable "Index of modules" (map mk mods) -- (font ! [size "+1"] << bold << "Index of modules" +++ br +++ -- foldl (+++) (stringToHtml "") (map mk mods)) where mk :: ModuleDoc -> Html mk md = makeLink' md [target "mainFrame"] << moduleName md htmlDoclet :: HDocletInput -> IO () htmlDoclet docletInput = do putStrLn ("sending output to " ++ dirname) sequence_ (map writeModDoc modules) putStrLn "generating module index." writeFile (dirname ++ "modules.html") (renderHtml $ makeModIndex cssFile allModules) idxTables [("functions.html", "functions", makeFunIndex (allDocuFunctions docletInput)), ("datatypes.html", "types", makeDataIndex (map fst $ allDocuTypesynonyms docletInput) (map fst $ allDocuDatatypes docletInput)), ("classes.html", "classes", makeClassIndex (map fst $ allDocuClasses docletInput)), ("instances.html", "instances", makeInstanceIndex (allDocuInstances docletInput))] putStrLn "generating index.html." writeFile (dirname ++ "index.html") (renderHtml indexhtml) when (hdsStyleSheetFile hdSet == Nothing) (putStrLn ("generating default stylesheet file " ++ cssFileWithPath ++ ".") >> writeFile cssFileWithPath defaultCssFile ) putStrLn "finished." where modules = allDocuModules docletInput writeModDoc dm = do putStrLn ("generating " ++ modName ++ ".html") writeFile (dirname ++ modName ++ ".html") (renderHtml (makeDoc hdSet cssFile dm)) where modName = moduleName (documentedModule dm) indexhtml = header << (css cssFile +++ thetitle << hdsDocumentTitle hdSet ) +++ frameset ! [cols "20%,80%"] << (frameset ! [rows "30%,70%"] << (frame ! [src "modules.html"] << "" +++ frame ! [src "functions.html"] << "") +++ frame ! [src "functions.html", name "mainFrame"] << "") idxTables :: [(FilePath, String, Html)] -> IO () idxTables xs = sequence_ [mk i | i <- [0..lastIdx]] where (files, names, htmls) = unzip3 xs lastIdx = length xs - 1 mk :: Int -> IO () mk i = do putStrLn ("generating index of " ++ (names!!i) ++ ".") writeFile (dirname ++ (files!!i)) (renderHtml (header << (css cssFile +++ thetitle << (names!!i) )+++ body << t)) where t = intersp' " " [ref j | j <- [0..lastIdx]] +++ hr +++ (htmls!!i) ref j | i == j = stringToHtml (names!!j) | otherwise = anchor ! [href (files!!j)] << (names!!j) hdSet = hdocSettings docletInput dirname = hdsDestinationDir hdSet allModules = [documentedModule dm | dm <- allDocuModules docletInput] (cssFile, cssFileWithPath) = case hdsStyleSheetFile hdSet of Nothing -> ("hdoc.css", dirname ++ "hdoc.css") Just file -> (file, file) bgColor = "#DDDDDD" defaultCssFile :: String defaultCssFile = "body { background: " ++ bgColor ++ " }\n\ \h2 { color: #000000 }\n\ \\n\ \.TableHeadingColor { background: #CCCCFF }\n\ \.TableRowColor { background: " ++ bgColor ++ " }\n\ \\n\ \.FrameHeadingFont { font-size: normal; font-family: normal } \n\ \.FrameItemFont { font-size: normal; font-family: normal } \n\ \"