1 module Rakka.Wiki.Interpreter.Outline
8 import Rakka.Wiki.Interpreter
11 interpreters :: [Interpreter]
12 interpreters = [ outlineInterp ]
15 outlineInterp :: Interpreter
16 outlineInterp = BlockCommandInterpreter {
20 case ctxMainWiki ctx of
21 Just tree -> return $ Div [("class", "outline")] [Block $ mkOutline tree]
22 Nothing -> return EmptyBlock
26 mkOutline :: WikiPage -> BlockElement
27 mkOutline tree = fst (mkOutline' emptyOutline 1 headings)
29 headings :: [BlockElement]
30 headings = concat (map collectInBlock tree)
32 collectInBlock :: BlockElement -> [BlockElement]
33 collectInBlock hd@(Heading _ _)
35 collectInBlock (Div _ xs)
36 = concat $ map collectInBlock $ catMaybes (map castToBlock xs)
37 collectInBlock (BlockCmd (BlockCommand _ _ xs))
38 = concat $ map collectInBlock xs
42 castToBlock :: Element -> Maybe BlockElement
43 castToBlock (Block e) = Just e
44 castToBlock _ = Nothing
47 emptyOutline :: BlockElement
48 emptyOutline = List Bullet []
51 mkOutline' :: BlockElement -> Int -> [BlockElement] -> (BlockElement, [BlockElement])
52 mkOutline' soFar _ [] = (soFar, [])
53 mkOutline' soFar level (x:xs)
57 -- 同じレベルなので soFar に單獨の ListItem を追加して
59 -> let link = PageLink {
61 , linkFragment = Just text
62 , linkText = Just text
66 mkOutline' (soFar { listItems = listItems soFar ++ [item] }) n xs
73 -- 高いレベルなので再帰して ListElement を作り、
74 -- それを soFar の最後の ListItem に追加する。
75 -> let (nested, ys) = mkOutline' emptyOutline (level + 1) (x:xs)
76 itemsSoFar = listItems soFar
78 nonLastItems, lastItem :: [ListItem]
79 (nonLastItems, lastItem) = splitAt (length itemsSoFar - 1) itemsSoFar
82 lastItem' = case lastItem of
84 i:[] -> i ++ [Block nested]
87 soFar' = soFar { listItems = nonLastItems ++ [lastItem'] }
89 mkOutline' soFar' level ys