1{-# LANGUAGE LambdaCase #-}2{-# LANGUAGE OverloadedStrings #-}34-- | This module provides functions for applying a 'Formatter' to5-- create 'Component's for given S-expressions. Furthermore, an6-- HTML document, for recognized 'Component's, can be generated7-- using this module.8module SchemeDoc.Format.Formatter (findComponents, format, defFormatter)9where1011import Control.Applicative12import Control.Monad1314import qualified SchemeDoc.Format.Library as L15import SchemeDoc.Format.Procedure16import SchemeDoc.Format.Syntax17import SchemeDoc.Format.Types18import SchemeDoc.Format.Variable19import SchemeDoc.Types2021import qualified Data.Text as T22import Text.Blaze.Html23import qualified Text.Blaze.Html5 as H2425-- ToC represents a table of contents with a depth of one.26data ToC = Heading Section | Items [Declaration]2728tableOfContents' :: [Component] -> [ToC] -> [ToC]29tableOfContents' ((D pc) : xs) ((Items lst) : toc) = tableOfContents' xs (toc ++ [Items $ lst ++ [pc]])30tableOfContents' ((D pc) : xs) toc = tableOfContents' xs (toc ++ [Items [pc]])31tableOfContents' ((S sec) : xs) toc = tableOfContents' xs (toc ++ [Heading sec])32tableOfContents' [] toc = toc3334tableOfContents :: [Component] -> Html35tableOfContents comps = H.ul $ do36 forM_37 (tableOfContents' comps [])38 ( \case39 Heading s -> H.li (compLink $ S s)40 Items lst -> H.ul (formatItems lst)41 )42 where43 formatItems :: [Declaration] -> Html44 formatItems decls = forM_ decls (H.li . compLink . D)4546------------------------------------------------------------------------4748-- | The default 'Formatter', can be extented via the 'Maybe' applicative.49defFormatter :: Sexp -> T.Text -> Maybe Declaration50defFormatter sexp desc =51 flip fmt desc <$> mkVariable sexp52 <|> flip fmt desc <$> mkProcedure sexp53 <|> flip fmt desc <$> mkSyntax sexp5455-- | Find all 'Component's recognized by the given 'Formatter'.56-- Non-recognized S-expressions are also returned.57findComponents :: Formatter -> [Documented] -> ([Component], [Sexp])58findComponents formatFn = foldl foldFunc ([], [])59 where60 foldFunc (acc, unFmt) (secRaw, com@(DocComment desc)) =61 case sectionComment secRaw of62 Just sec -> let s = Section sec desc in (acc ++ [S s], unFmt)63 Nothing -> (acc, unFmt ++ [com])64 foldFunc (acc, unFmt) (desc, expr) =65 case formatFn expr desc of66 Just c -> (acc ++ [D c], unFmt)67 Nothing -> (acc, unFmt ++ [expr])6869-- | Format all 'Component's which are exported by the given 'L.Library'.70format :: L.Library -> [Component] -> Html71format lib comps = do72 H.h2 "Index"73 H.details $ do74 H.summary "Table of contents"75 tableOfContents finalComps76 forM_77 finalComps78 ( \case79 D c -> declFmt c (L.externalId lib $ declId c)80 S s -> sectionFmt s81 )82 where83 -- Exclude any non-exported program components.84 exportedComps =85 filter86 ( \case87 D c -> L.exports lib $ declId c88 S _ -> True89 )90 comps9192 -- Extra components to prepend to the component list.93 -- Neccessary to ensure that HTML heading structure is always valid.94 extraComps =95 if any (\case D _ -> False; S _ -> True) exportedComps96 then []97 else [S defaultSection]9899 -- Prepend extraComps to the exported components.100 finalComps = extraComps ++ exportedComps