aboutsummaryrefslogtreecommitdiff
path: root/haddock-api/src/Haddock/Backends/Xhtml.hs
diff options
context:
space:
mode:
authorMateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>2014-08-23 10:09:34 +0100
committerMateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>2014-08-23 10:09:34 +0100
commit5d41d4396425fc5c2e9b90d3e1e0baa5dc1ac224 (patch)
treedf13708dded1d48172cb51feb05fb41e74565ac8 /haddock-api/src/Haddock/Backends/Xhtml.hs
parent92e50dba7b099f24cc357de71aaa7fe06bd061b1 (diff)
Move sources under haddock-api/src
Diffstat (limited to 'haddock-api/src/Haddock/Backends/Xhtml.hs')
-rw-r--r--haddock-api/src/Haddock/Backends/Xhtml.hs690
1 files changed, 690 insertions, 0 deletions
diff --git a/haddock-api/src/Haddock/Backends/Xhtml.hs b/haddock-api/src/Haddock/Backends/Xhtml.hs
new file mode 100644
index 00000000..9628a33d
--- /dev/null
+++ b/haddock-api/src/Haddock/Backends/Xhtml.hs
@@ -0,0 +1,690 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module : Haddock.Backends.Html
+-- Copyright : (c) Simon Marlow 2003-2006,
+-- David Waern 2006-2009,
+-- Mark Lentczner 2010,
+-- Mateusz Kowalczyk 2013
+-- License : BSD-like
+--
+-- Maintainer : haddock@projects.haskell.org
+-- Stability : experimental
+-- Portability : portable
+-----------------------------------------------------------------------------
+{-# LANGUAGE CPP #-}
+module Haddock.Backends.Xhtml (
+ ppHtml, copyHtmlBits,
+ ppHtmlIndex, ppHtmlContents,
+) where
+
+
+import Prelude hiding (div)
+
+import Haddock.Backends.Xhtml.Decl
+import Haddock.Backends.Xhtml.DocMarkup
+import Haddock.Backends.Xhtml.Layout
+import Haddock.Backends.Xhtml.Names
+import Haddock.Backends.Xhtml.Themes
+import Haddock.Backends.Xhtml.Types
+import Haddock.Backends.Xhtml.Utils
+import Haddock.ModuleTree
+import Haddock.Types
+import Haddock.Version
+import Haddock.Utils
+import Text.XHtml hiding ( name, title, p, quote )
+import Haddock.GhcUtils
+
+import Control.Monad ( when, unless )
+#if !MIN_VERSION_base(4,7,0)
+import Control.Monad.Instances ( ) -- for Functor Either a
+#endif
+import Data.Char ( toUpper )
+import Data.Functor ( (<$>) )
+import Data.List ( sortBy, groupBy, intercalate, isPrefixOf )
+import Data.Maybe
+import System.FilePath hiding ( (</>) )
+import System.Directory
+import Data.Map ( Map )
+import qualified Data.Map as Map hiding ( Map )
+import qualified Data.Set as Set hiding ( Set )
+import Data.Function
+import Data.Ord ( comparing )
+
+import DynFlags (Language(..))
+import GHC hiding ( NoLink, moduleInfo )
+import Name
+import Module
+
+--------------------------------------------------------------------------------
+-- * Generating HTML documentation
+--------------------------------------------------------------------------------
+
+
+ppHtml :: String
+ -> Maybe String -- ^ Package
+ -> [Interface]
+ -> FilePath -- ^ Destination directory
+ -> Maybe (Doc GHC.RdrName) -- ^ Prologue text, maybe
+ -> Themes -- ^ Themes
+ -> SourceURLs -- ^ The source URL (--source)
+ -> WikiURLs -- ^ The wiki URL (--wiki)
+ -> Maybe String -- ^ The contents URL (--use-contents)
+ -> Maybe String -- ^ The index URL (--use-index)
+ -> Bool -- ^ Whether to use unicode in output (--use-unicode)
+ -> QualOption -- ^ How to qualify names
+ -> Bool -- ^ Output pretty html (newlines and indenting)
+ -> IO ()
+
+ppHtml doctitle maybe_package ifaces odir prologue
+ themes maybe_source_url maybe_wiki_url
+ maybe_contents_url maybe_index_url unicode
+ qual debug = do
+ let
+ visible_ifaces = filter visible ifaces
+ visible i = OptHide `notElem` ifaceOptions i
+
+ when (isNothing maybe_contents_url) $
+ ppHtmlContents odir doctitle maybe_package
+ themes maybe_index_url maybe_source_url maybe_wiki_url
+ (map toInstalledIface visible_ifaces)
+ False -- we don't want to display the packages in a single-package contents
+ prologue debug (makeContentsQual qual)
+
+ when (isNothing maybe_index_url) $
+ ppHtmlIndex odir doctitle maybe_package
+ themes maybe_contents_url maybe_source_url maybe_wiki_url
+ (map toInstalledIface visible_ifaces) debug
+
+ mapM_ (ppHtmlModule odir doctitle themes
+ maybe_source_url maybe_wiki_url
+ maybe_contents_url maybe_index_url unicode qual debug) visible_ifaces
+
+
+copyHtmlBits :: FilePath -> FilePath -> Themes -> IO ()
+copyHtmlBits odir libdir themes = do
+ let
+ libhtmldir = joinPath [libdir, "html"]
+ copyCssFile f = copyFile f (combine odir (takeFileName f))
+ copyLibFile f = copyFile (joinPath [libhtmldir, f]) (joinPath [odir, f])
+ mapM_ copyCssFile (cssFiles themes)
+ mapM_ copyLibFile [ jsFile, framesFile ]
+
+
+headHtml :: String -> Maybe String -> Themes -> Html
+headHtml docTitle miniPage themes =
+ header << [
+ meta ! [httpequiv "Content-Type", content "text/html; charset=UTF-8"],
+ thetitle << docTitle,
+ styleSheet themes,
+ script ! [src jsFile, thetype "text/javascript"] << noHtml,
+ script ! [thetype "text/javascript"]
+ -- NB: Within XHTML, the content of script tags needs to be
+ -- a <![CDATA[ section. Will break if the miniPage name could
+ -- have "]]>" in it!
+ << primHtml (
+ "//<![CDATA[\nwindow.onload = function () {pageLoad();"
+ ++ setSynopsis ++ "};\n//]]>\n")
+ ]
+ where
+ setSynopsis = maybe "" (\p -> "setSynopsis(\"" ++ p ++ "\");") miniPage
+
+
+srcButton :: SourceURLs -> Maybe Interface -> Maybe Html
+srcButton (Just src_base_url, _, _, _) Nothing =
+ Just (anchor ! [href src_base_url] << "Source")
+srcButton (_, Just src_module_url, _, _) (Just iface) =
+ let url = spliceURL (Just $ ifaceOrigFilename iface)
+ (Just $ ifaceMod iface) Nothing Nothing src_module_url
+ in Just (anchor ! [href url] << "Source")
+srcButton _ _ =
+ Nothing
+
+
+wikiButton :: WikiURLs -> Maybe Module -> Maybe Html
+wikiButton (Just wiki_base_url, _, _) Nothing =
+ Just (anchor ! [href wiki_base_url] << "User Comments")
+
+wikiButton (_, Just wiki_module_url, _) (Just mdl) =
+ let url = spliceURL Nothing (Just mdl) Nothing Nothing wiki_module_url
+ in Just (anchor ! [href url] << "User Comments")
+
+wikiButton _ _ =
+ Nothing
+
+
+contentsButton :: Maybe String -> Maybe Html
+contentsButton maybe_contents_url
+ = Just (anchor ! [href url] << "Contents")
+ where url = fromMaybe contentsHtmlFile maybe_contents_url
+
+
+indexButton :: Maybe String -> Maybe Html
+indexButton maybe_index_url
+ = Just (anchor ! [href url] << "Index")
+ where url = fromMaybe indexHtmlFile maybe_index_url
+
+
+bodyHtml :: String -> Maybe Interface
+ -> SourceURLs -> WikiURLs
+ -> Maybe String -> Maybe String
+ -> Html -> Html
+bodyHtml doctitle iface
+ maybe_source_url maybe_wiki_url
+ maybe_contents_url maybe_index_url
+ pageContent =
+ body << [
+ divPackageHeader << [
+ unordList (catMaybes [
+ srcButton maybe_source_url iface,
+ wikiButton maybe_wiki_url (ifaceMod <$> iface),
+ contentsButton maybe_contents_url,
+ indexButton maybe_index_url])
+ ! [theclass "links", identifier "page-menu"],
+ nonEmptySectionName << doctitle
+ ],
+ divContent << pageContent,
+ divFooter << paragraph << (
+ "Produced by " +++
+ (anchor ! [href projectUrl] << toHtml projectName) +++
+ (" version " ++ projectVersion)
+ )
+ ]
+
+
+moduleInfo :: Interface -> Html
+moduleInfo iface =
+ let
+ info = ifaceInfo iface
+
+ doOneEntry :: (String, HaddockModInfo GHC.Name -> Maybe String) -> Maybe HtmlTable
+ doOneEntry (fieldName, field) =
+ field info >>= \a -> return (th << fieldName <-> td << a)
+
+ entries :: [HtmlTable]
+ entries = mapMaybe doOneEntry [
+ ("Copyright",hmi_copyright),
+ ("License",hmi_license),
+ ("Maintainer",hmi_maintainer),
+ ("Stability",hmi_stability),
+ ("Portability",hmi_portability),
+ ("Safe Haskell",hmi_safety),
+ ("Language", lg)
+ ] ++ extsForm
+ where
+ lg inf = case hmi_language inf of
+ Nothing -> Nothing
+ Just Haskell98 -> Just "Haskell98"
+ Just Haskell2010 -> Just "Haskell2010"
+
+ extsForm
+ | OptShowExtensions `elem` ifaceOptions iface =
+ let fs = map (dropOpt . show) (hmi_extensions info)
+ in case map stringToHtml fs of
+ [] -> []
+ [x] -> extField x -- don't use a list for a single extension
+ xs -> extField $ unordList xs ! [theclass "extension-list"]
+ | otherwise = []
+ where
+ extField x = return $ th << "Extensions" <-> td << x
+ dropOpt x = if "Opt_" `isPrefixOf` x then drop 4 x else x
+ in
+ case entries of
+ [] -> noHtml
+ _ -> table ! [theclass "info"] << aboves entries
+
+
+--------------------------------------------------------------------------------
+-- * Generate the module contents
+--------------------------------------------------------------------------------
+
+
+ppHtmlContents
+ :: FilePath
+ -> String
+ -> Maybe String
+ -> Themes
+ -> Maybe String
+ -> SourceURLs
+ -> WikiURLs
+ -> [InstalledInterface] -> Bool -> Maybe (Doc GHC.RdrName)
+ -> Bool
+ -> Qualification -- ^ How to qualify names
+ -> IO ()
+ppHtmlContents odir doctitle _maybe_package
+ themes maybe_index_url
+ maybe_source_url maybe_wiki_url ifaces showPkgs prologue debug qual = do
+ let tree = mkModuleTree showPkgs
+ [(instMod iface, toInstalledDescription iface) | iface <- ifaces]
+ html =
+ headHtml doctitle Nothing themes +++
+ bodyHtml doctitle Nothing
+ maybe_source_url maybe_wiki_url
+ Nothing maybe_index_url << [
+ ppPrologue qual doctitle prologue,
+ ppModuleTree qual tree
+ ]
+ createDirectoryIfMissing True odir
+ writeFile (joinPath [odir, contentsHtmlFile]) (renderToString debug html)
+
+ -- XXX: think of a better place for this?
+ ppHtmlContentsFrame odir doctitle themes ifaces debug
+
+
+ppPrologue :: Qualification -> String -> Maybe (Doc GHC.RdrName) -> Html
+ppPrologue _ _ Nothing = noHtml
+ppPrologue qual title (Just doc) =
+ divDescription << (h1 << title +++ docElement thediv (rdrDocToHtml qual doc))
+
+
+ppModuleTree :: Qualification -> [ModuleTree] -> Html
+ppModuleTree qual ts =
+ divModuleList << (sectionName << "Modules" +++ mkNodeList qual [] "n" ts)
+
+
+mkNodeList :: Qualification -> [String] -> String -> [ModuleTree] -> Html
+mkNodeList qual ss p ts = case ts of
+ [] -> noHtml
+ _ -> unordList (zipWith (mkNode qual ss) ps ts)
+ where
+ ps = [ p ++ '.' : show i | i <- [(1::Int)..]]
+
+
+mkNode :: Qualification -> [String] -> String -> ModuleTree -> Html
+mkNode qual ss p (Node s leaf pkg short ts) =
+ htmlModule <+> shortDescr +++ htmlPkg +++ subtree
+ where
+ modAttrs = case (ts, leaf) of
+ (_:_, False) -> collapseControl p True "module"
+ (_, _ ) -> [theclass "module"]
+
+ cBtn = case (ts, leaf) of
+ (_:_, True) -> thespan ! collapseControl p True "" << spaceHtml
+ (_, _ ) -> noHtml
+ -- We only need an explicit collapser button when the module name
+ -- is also a leaf, and so is a link to a module page. Indeed, the
+ -- spaceHtml is a minor hack and does upset the layout a fraction.
+
+ htmlModule = thespan ! modAttrs << (cBtn +++
+ if leaf
+ then ppModule (mkModule (stringToPackageId (fromMaybe "" pkg))
+ (mkModuleName mdl))
+ else toHtml s
+ )
+
+ mdl = intercalate "." (reverse (s:ss))
+
+ shortDescr = maybe noHtml (origDocToHtml qual) short
+ htmlPkg = maybe noHtml (thespan ! [theclass "package"] <<) pkg
+
+ subtree = mkNodeList qual (s:ss) p ts ! collapseSection p True ""
+
+
+-- | Turn a module tree into a flat list of full module names. E.g.,
+-- @
+-- A
+-- +-B
+-- +-C
+-- @
+-- becomes
+-- @["A", "A.B", "A.B.C"]@
+flatModuleTree :: [InstalledInterface] -> [Html]
+flatModuleTree ifaces =
+ map (uncurry ppModule' . head)
+ . groupBy ((==) `on` fst)
+ . sortBy (comparing fst)
+ $ mods
+ where
+ mods = [ (moduleString mdl, mdl) | mdl <- map instMod ifaces ]
+ ppModule' txt mdl =
+ anchor ! [href (moduleHtmlFile mdl), target mainFrameName]
+ << toHtml txt
+
+
+ppHtmlContentsFrame :: FilePath -> String -> Themes
+ -> [InstalledInterface] -> Bool -> IO ()
+ppHtmlContentsFrame odir doctitle themes ifaces debug = do
+ let mods = flatModuleTree ifaces
+ html =
+ headHtml doctitle Nothing themes +++
+ miniBody << divModuleList <<
+ (sectionName << "Modules" +++
+ ulist << [ li ! [theclass "module"] << m | m <- mods ])
+ createDirectoryIfMissing True odir
+ writeFile (joinPath [odir, frameIndexHtmlFile]) (renderToString debug html)
+
+
+--------------------------------------------------------------------------------
+-- * Generate the index
+--------------------------------------------------------------------------------
+
+
+ppHtmlIndex :: FilePath
+ -> String
+ -> Maybe String
+ -> Themes
+ -> Maybe String
+ -> SourceURLs
+ -> WikiURLs
+ -> [InstalledInterface]
+ -> Bool
+ -> IO ()
+ppHtmlIndex odir doctitle _maybe_package themes
+ maybe_contents_url maybe_source_url maybe_wiki_url ifaces debug = do
+ let html = indexPage split_indices Nothing
+ (if split_indices then [] else index)
+
+ createDirectoryIfMissing True odir
+
+ when split_indices $ do
+ mapM_ (do_sub_index index) initialChars
+ -- Let's add a single large index as well for those who don't know exactly what they're looking for:
+ let mergedhtml = indexPage False Nothing index
+ writeFile (joinPath [odir, subIndexHtmlFile merged_name]) (renderToString debug mergedhtml)
+
+ writeFile (joinPath [odir, indexHtmlFile]) (renderToString debug html)
+
+ where
+ indexPage showLetters ch items =
+ headHtml (doctitle ++ " (" ++ indexName ch ++ ")") Nothing themes +++
+ bodyHtml doctitle Nothing
+ maybe_source_url maybe_wiki_url
+ maybe_contents_url Nothing << [
+ if showLetters then indexInitialLetterLinks else noHtml,
+ if null items then noHtml else
+ divIndex << [sectionName << indexName ch, buildIndex items]
+ ]
+
+ indexName ch = "Index" ++ maybe "" (\c -> " - " ++ [c]) ch
+ merged_name = "All"
+
+ buildIndex items = table << aboves (map indexElt items)
+
+ -- an arbitrary heuristic:
+ -- too large, and a single-page will be slow to load
+ -- too small, and we'll have lots of letter-indexes with only one
+ -- or two members in them, which seems inefficient or
+ -- unnecessarily hard to use.
+ split_indices = length index > 150
+
+ indexInitialLetterLinks =
+ divAlphabet <<
+ unordList (map (\str -> anchor ! [href (subIndexHtmlFile str)] << str) $
+ [ [c] | c <- initialChars
+ , any ((==c) . toUpper . head . fst) index ] ++
+ [merged_name])
+
+ -- todo: what about names/operators that start with Unicode
+ -- characters?
+ -- Exports beginning with '_' can be listed near the end,
+ -- presumably they're not as important... but would be listed
+ -- with non-split index!
+ initialChars = [ 'A'..'Z' ] ++ ":!#$%&*+./<=>?@\\^|-~" ++ "_"
+
+ do_sub_index this_ix c
+ = unless (null index_part) $
+ writeFile (joinPath [odir, subIndexHtmlFile [c]]) (renderToString debug html)
+ where
+ html = indexPage True (Just c) index_part
+ index_part = [(n,stuff) | (n,stuff) <- this_ix, toUpper (head n) == c]
+
+
+ index :: [(String, Map GHC.Name [(Module,Bool)])]
+ index = sortBy cmp (Map.toAscList full_index)
+ where cmp (n1,_) (n2,_) = comparing (map toUpper) n1 n2
+
+ -- for each name (a plain string), we have a number of original HsNames that
+ -- it can refer to, and for each of those we have a list of modules
+ -- that export that entity. Each of the modules exports the entity
+ -- in a visible or invisible way (hence the Bool).
+ full_index :: Map String (Map GHC.Name [(Module,Bool)])
+ full_index = Map.fromListWith (flip (Map.unionWith (++)))
+ (concatMap getIfaceIndex ifaces)
+
+ getIfaceIndex iface =
+ [ (getOccString name
+ , Map.fromList [(name, [(mdl, name `Set.member` visible)])])
+ | name <- instExports iface ]
+ where
+ mdl = instMod iface
+ visible = Set.fromList (instVisibleExports iface)
+
+ indexElt :: (String, Map GHC.Name [(Module,Bool)]) -> HtmlTable
+ indexElt (str, entities) =
+ case Map.toAscList entities of
+ [(nm,entries)] ->
+ td ! [ theclass "src" ] << toHtml str <->
+ indexLinks nm entries
+ many_entities ->
+ td ! [ theclass "src" ] << toHtml str <-> td << spaceHtml </>
+ aboves (zipWith (curry doAnnotatedEntity) [1..] many_entities)
+
+ doAnnotatedEntity :: (Integer, (Name, [(Module, Bool)])) -> HtmlTable
+ doAnnotatedEntity (j,(nm,entries))
+ = td ! [ theclass "alt" ] <<
+ toHtml (show j) <+> parens (ppAnnot (nameOccName nm)) <->
+ indexLinks nm entries
+
+ ppAnnot n | not (isValOcc n) = toHtml "Type/Class"
+ | isDataOcc n = toHtml "Data Constructor"
+ | otherwise = toHtml "Function"
+
+ indexLinks nm entries =
+ td ! [ theclass "module" ] <<
+ hsep (punctuate comma
+ [ if visible then
+ linkId mdl (Just nm) << toHtml (moduleString mdl)
+ else
+ toHtml (moduleString mdl)
+ | (mdl, visible) <- entries ])
+
+
+--------------------------------------------------------------------------------
+-- * Generate the HTML page for a module
+--------------------------------------------------------------------------------
+
+
+ppHtmlModule
+ :: FilePath -> String -> Themes
+ -> SourceURLs -> WikiURLs
+ -> Maybe String -> Maybe String -> Bool -> QualOption
+ -> Bool -> Interface -> IO ()
+ppHtmlModule odir doctitle themes
+ maybe_source_url maybe_wiki_url
+ maybe_contents_url maybe_index_url unicode qual debug iface = do
+ let
+ mdl = ifaceMod iface
+ aliases = ifaceModuleAliases iface
+ mdl_str = moduleString mdl
+ real_qual = makeModuleQual qual aliases mdl
+ html =
+ headHtml mdl_str (Just $ "mini_" ++ moduleHtmlFile mdl) themes +++
+ bodyHtml doctitle (Just iface)
+ maybe_source_url maybe_wiki_url
+ maybe_contents_url maybe_index_url << [
+ divModuleHeader << (moduleInfo iface +++ (sectionName << mdl_str)),
+ ifaceToHtml maybe_source_url maybe_wiki_url iface unicode real_qual
+ ]
+
+ createDirectoryIfMissing True odir
+ writeFile (joinPath [odir, moduleHtmlFile mdl]) (renderToString debug html)
+ ppHtmlModuleMiniSynopsis odir doctitle themes iface unicode real_qual debug
+
+ppHtmlModuleMiniSynopsis :: FilePath -> String -> Themes
+ -> Interface -> Bool -> Qualification -> Bool -> IO ()
+ppHtmlModuleMiniSynopsis odir _doctitle themes iface unicode qual debug = do
+ let mdl = ifaceMod iface
+ html =
+ headHtml (moduleString mdl) Nothing themes +++
+ miniBody <<
+ (divModuleHeader << sectionName << moduleString mdl +++
+ miniSynopsis mdl iface unicode qual)
+ createDirectoryIfMissing True odir
+ writeFile (joinPath [odir, "mini_" ++ moduleHtmlFile mdl]) (renderToString debug html)
+
+
+ifaceToHtml :: SourceURLs -> WikiURLs -> Interface -> Bool -> Qualification -> Html
+ifaceToHtml maybe_source_url maybe_wiki_url iface unicode qual
+ = ppModuleContents qual exports +++
+ description +++
+ synopsis +++
+ divInterface (maybe_doc_hdr +++ bdy)
+ where
+ exports = numberSectionHeadings (ifaceRnExportItems iface)
+
+ -- todo: if something has only sub-docs, or fn-args-docs, should
+ -- it be measured here and thus prevent omitting the synopsis?
+ has_doc ExportDecl { expItemMbDoc = (Documentation mDoc mWarning, _) } = isJust mDoc || isJust mWarning
+ has_doc (ExportNoDecl _ _) = False
+ has_doc (ExportModule _) = False
+ has_doc _ = True
+
+ no_doc_at_all = not (any has_doc exports)
+
+ description | isNoHtml doc = doc
+ | otherwise = divDescription $ sectionName << "Description" +++ doc
+ where doc = docSection qual (ifaceRnDoc iface)
+
+ -- omit the synopsis if there are no documentation annotations at all
+ synopsis
+ | no_doc_at_all = noHtml
+ | otherwise
+ = divSynposis $
+ paragraph ! collapseControl "syn" False "caption" << "Synopsis" +++
+ shortDeclList (
+ mapMaybe (processExport True linksInfo unicode qual) exports
+ ) ! (collapseSection "syn" False "" ++ collapseToggle "syn")
+
+ -- if the documentation doesn't begin with a section header, then
+ -- add one ("Documentation").
+ maybe_doc_hdr
+ = case exports of
+ [] -> noHtml
+ ExportGroup {} : _ -> noHtml
+ _ -> h1 << "Documentation"
+
+ bdy =
+ foldr (+++) noHtml $
+ mapMaybe (processExport False linksInfo unicode qual) exports
+
+ linksInfo = (maybe_source_url, maybe_wiki_url)
+
+
+miniSynopsis :: Module -> Interface -> Bool -> Qualification -> Html
+miniSynopsis mdl iface unicode qual =
+ divInterface << concatMap (processForMiniSynopsis mdl unicode qual) exports
+ where
+ exports = numberSectionHeadings (ifaceRnExportItems iface)
+
+
+processForMiniSynopsis :: Module -> Bool -> Qualification -> ExportItem DocName
+ -> [Html]
+processForMiniSynopsis mdl unicode qual ExportDecl { expItemDecl = L _loc decl0 } =
+ ((divTopDecl <<).(declElem <<)) <$> case decl0 of
+ TyClD d -> let b = ppTyClBinderWithVarsMini mdl d in case d of
+ (FamDecl decl) -> [ppTyFamHeader True False decl unicode qual]
+ (DataDecl{}) -> [keyword "data" <+> b]
+ (SynDecl{}) -> [keyword "type" <+> b]
+ (ClassDecl {}) -> [keyword "class" <+> b]
+ _ -> []
+ SigD (TypeSig lnames (L _ _)) ->
+ map (ppNameMini Prefix mdl . nameOccName . getName . unLoc) lnames
+ _ -> []
+processForMiniSynopsis _ _ qual (ExportGroup lvl _id txt) =
+ [groupTag lvl << docToHtml qual txt]
+processForMiniSynopsis _ _ _ _ = []
+
+
+ppNameMini :: Notation -> Module -> OccName -> Html
+ppNameMini notation mdl nm =
+ anchor ! [ href (moduleNameUrl mdl nm)
+ , target mainFrameName ]
+ << ppBinder' notation nm
+
+
+ppTyClBinderWithVarsMini :: Module -> TyClDecl DocName -> Html
+ppTyClBinderWithVarsMini mdl decl =
+ let n = tcdName decl
+ ns = tyvarNames $ tcdTyVars decl -- it's safe to use tcdTyVars, see code above
+ in ppTypeApp n [] ns (\is_infix -> ppNameMini is_infix mdl . nameOccName . getName) ppTyName
+
+
+ppModuleContents :: Qualification -> [ExportItem DocName] -> Html
+ppModuleContents qual exports
+ | null sections = noHtml
+ | otherwise = contentsDiv
+ where
+ contentsDiv = divTableOfContents << (
+ sectionName << "Contents" +++
+ unordList sections)
+
+ (sections, _leftovers{-should be []-}) = process 0 exports
+
+ process :: Int -> [ExportItem DocName] -> ([Html],[ExportItem DocName])
+ process _ [] = ([], [])
+ process n items@(ExportGroup lev id0 doc : rest)
+ | lev <= n = ( [], items )
+ | otherwise = ( html:secs, rest2 )
+ where
+ html = linkedAnchor (groupId id0)
+ << docToHtmlNoAnchors qual doc +++ mk_subsections ssecs
+ (ssecs, rest1) = process lev rest
+ (secs, rest2) = process n rest1
+ process n (_ : rest) = process n rest
+
+ mk_subsections [] = noHtml
+ mk_subsections ss = unordList ss
+
+-- we need to assign a unique id to each section heading so we can hyperlink
+-- them from the contents:
+numberSectionHeadings :: [ExportItem DocName] -> [ExportItem DocName]
+numberSectionHeadings = go 1
+ where go :: Int -> [ExportItem DocName] -> [ExportItem DocName]
+ go _ [] = []
+ go n (ExportGroup lev _ doc : es)
+ = ExportGroup lev (show n) doc : go (n+1) es
+ go n (other:es)
+ = other : go n es
+
+
+processExport :: Bool -> LinksInfo -> Bool -> Qualification
+ -> ExportItem DocName -> Maybe Html
+processExport _ _ _ _ ExportDecl { expItemDecl = L _ (InstD _) } = Nothing -- Hide empty instances
+processExport summary _ _ qual (ExportGroup lev id0 doc)
+ = nothingIf summary $ groupHeading lev id0 << docToHtml qual doc
+processExport summary links unicode qual (ExportDecl decl doc subdocs insts fixities splice)
+ = processDecl summary $ ppDecl summary links decl doc insts fixities subdocs splice unicode qual
+processExport summary _ _ qual (ExportNoDecl y [])
+ = processDeclOneLiner summary $ ppDocName qual Prefix True y
+processExport summary _ _ qual (ExportNoDecl y subs)
+ = processDeclOneLiner summary $
+ ppDocName qual Prefix True y
+ +++ parenList (map (ppDocName qual Prefix True) subs)
+processExport summary _ _ qual (ExportDoc doc)
+ = nothingIf summary $ docSection_ qual doc
+processExport summary _ _ _ (ExportModule mdl)
+ = processDeclOneLiner summary $ toHtml "module" <+> ppModule mdl
+
+
+nothingIf :: Bool -> a -> Maybe a
+nothingIf True _ = Nothing
+nothingIf False a = Just a
+
+
+processDecl :: Bool -> Html -> Maybe Html
+processDecl True = Just
+processDecl False = Just . divTopDecl
+
+
+processDeclOneLiner :: Bool -> Html -> Maybe Html
+processDeclOneLiner True = Just
+processDeclOneLiner False = Just . divTopDecl . declElem
+
+groupHeading :: Int -> String -> Html -> Html
+groupHeading lev id0 = groupTag lev ! [identifier (groupId id0)]
+
+groupTag :: Int -> Html -> Html
+groupTag lev
+ | lev == 1 = h1
+ | lev == 2 = h2
+ | lev == 3 = h3
+ | otherwise = h4