1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE ViewPatterns #-}
10 , ParseTokenForestError(..), PStack(..)
11 -- * Rendering forests
18import Text.HTML.Parser
21-- | If you want to store additional data into your tree, you can define your own token type and
22-- instantiate this class to define a mapping between your type and 'Token'. See
25 toToken :: a -> Maybe Token
26 fromToken :: Token -> a
28instance IsToken Token where
33parseTokenForest :: (IsToken token) => [token] -> Either (ParseTokenForestError token) (Forest token)
34parseTokenForest = f (PStack [] [])
36 f (PStack ss []) [] = Right (reverse ss)
37 f pstack [] = Left $ ParseTokenForestErrorBracketMismatch pstack Nothing
38 f pstack (t : ts) = case toToken t of
39 Just (TagOpen "br" _) -> f (pushFlatSibling t pstack) ts
40 Just (TagOpen "hr" _) -> f (pushFlatSibling t pstack) ts
41 Just (TagOpen "img" _) -> f (pushFlatSibling t pstack) ts
42 Just (TagOpen _ _) -> f (pushParent t pstack) ts
43 Just (TagClose n) -> (`f` ts) =<< popParent n pstack
44 Just (ContentChar _) -> f (pushFlatSibling t pstack) ts
45 Just (ContentText _) -> f (pushFlatSibling t pstack) ts
46 Just (Comment _) -> f (pushFlatSibling t pstack) ts
47 Just (Doctype _) -> f (pushFlatSibling t pstack) ts
48 Nothing -> f (pushFlatSibling t pstack) ts
50data ParseTokenForestError t =
51 ParseTokenForestErrorBracketMismatch (PStack t) (Maybe Token)
55 { _pstackToplevelSiblings :: Forest t
56 , _pstackParents :: [(t, Forest t)]
60pushParent :: t -> PStack t -> PStack t
61pushParent t (PStack ss ps) = PStack [] ((t, ss) : ps)
63popParent :: (IsToken t) => TagName -> PStack t -> Either (ParseTokenForestError t) (PStack t)
64popParent n (PStack ss ((p@(toToken -> Just (TagOpen n' _)), ss') : ps))
65 | n == n' = Right $ PStack (Node p (reverse ss) : ss') ps
67 = Left $ ParseTokenForestErrorBracketMismatch pstack (Just $ TagClose n)
69pushFlatSibling :: t -> PStack t -> PStack t
70pushFlatSibling t (PStack ss ps) = PStack (Node t [] : ss) ps
73renderTokenForest :: (IsToken t, Show t) => Forest t -> [t]
74renderTokenForest = mconcat . fmap renderTokenTree
76renderTokenTree :: (IsToken t) => Tree t -> [t]
77renderTokenTree = \case
78 (Node o@(toToken -> Just (TagOpen n _)) ts)
79 -> [o] <> renderTokenForest ts <> [fromToken $ TagClose n]
83 -> error "renderTokenTree: leaf node with children."
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list