1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE RecordWildCards #-}
3 {-# LANGUAGE ViewPatterns #-}
4 -- | Render TCT as HTML5.
5 module Language.TCT.Write.HTML5 where
7 import Control.Monad (Monad(..), forM_, mapM, when)
9 import Data.Eq (Eq(..))
10 import Data.Foldable (Foldable(..))
11 import Data.Function (($))
13 import Data.Maybe (Maybe(..))
14 import Data.Monoid (Monoid(..))
15 import Data.Ord (Ord(..))
16 import Data.Semigroup (Semigroup(..))
17 import Data.Sequence (ViewL(..))
18 import Data.String (IsString(..))
19 import Data.Text (Text)
20 import Data.TreeSeq.Strict (Tree(..),Trees)
21 import Prelude (Num(..), undefined)
22 import Text.Blaze ((!))
23 import Text.Blaze.Html (Html)
24 import Text.Show (Show(..))
25 import qualified Control.Monad.Trans.State as S
26 import qualified Data.List as L
27 import qualified Data.Sequence as Seq
28 import qualified Data.Text as Text
29 import qualified Data.Text.Lazy as TL
30 import qualified Text.Blaze.Html5 as H
31 import qualified Text.Blaze.Html5.Attributes as HA
33 import Text.Blaze.Utils
35 import Language.TCT.Write.Text
37 html5Document :: TCTs -> Html
38 html5Document tct = do
42 H.meta ! HA.httpEquiv "Content-Type"
43 ! HA.content "text/html; charset=UTF-8"
44 whenJust (tokensTitle tct) $ \ts ->
45 H.title $ H.toMarkup $ L.head $
46 TL.lines (textTokens ts) <> [""]
47 -- link ! rel "Chapter" ! title "SomeTitle">
48 H.link ! HA.rel "stylesheet"
50 ! HA.href "style/tct-html5.css"
52 H.a ! HA.id ("line-1") $ return ()
53 html5TreesCell (treePosLastCell tct)
55 html5TreesCell :: Trees (Pos,Cell Key) (Pos,Tokens) -> Html
56 html5TreesCell = foldMap html5TreeCell
58 tokensTitle :: Trees (Cell Key) Tokens -> Maybe Tokens
61 TreeN (unCell -> KeySection{}) _ts -> True
64 TreeN (unCell -> KeySection _lvl) (Seq.viewl -> Tree0 title:<_) -> Just title
67 html5Text :: Text -> Html
68 html5Text = H.toMarkup
70 html5Spaces :: Int -> Html
71 html5Spaces 0 = return ()
72 html5Spaces sp = H.span $ html5Text $ Text.replicate sp " "
74 html5TreeCell :: Tree (Pos,Cell Key) (Pos,Tokens) -> Html
75 html5TreeCell (TreeN (posEnd, Cell pos _ (KeySection lvl)) ts) = do
76 html5IndentCell (posEnd,pos)
78 H.span ! HA.class_ "section-title" $ do
79 H.span $ html5Text $ Text.replicate lvl "#" <> " "
81 Tree0 (_,title) :< _ -> h lvl $ html5IndentToken title
84 case Seq.viewl ts of {Tree0{} :< ts' -> ts'; _ -> ts}
92 h n | n > 0 = H.span ! HA.class_ ("h h"<>attrValue n)
94 html5TreeCell (Tree0 (posEnd,toks)) =
95 case Seq.viewl toks of
96 EmptyL -> html5IndentToken toks
97 t0:<_ -> html5IndentCell (posEnd,posCell t0) <> html5IndentToken toks
98 html5TreeCell (TreeN (posEnd,cell@(Cell pos _ _)) cs) =
99 html5IndentCell (posEnd,pos) <>
102 html5IndentCell :: (Pos,Pos) -> Html
103 html5IndentCell (Pos lineLast colLast,Pos line col)
104 | lineLast < line = do
105 forM_ [lineLast+1..line] $ \lnum -> do
107 H.a ! HA.id ("line-"<>attrValue lnum) $ return ()
108 H.toMarkup $ Text.replicate (col - 1) " "
110 && colLast <= col = H.toMarkup $ Text.replicate (col - colLast) " "
111 | otherwise = undefined
113 html5CellKey :: Cell Key -> Trees (Pos,Cell Key) (Pos,Tokens) -> Html
114 html5CellKey (Cell _pos _posEnd key) ts = do
116 KeyColon n wh -> html5Key "" "" n wh ":" "" "colon"
117 KeyGreat n wh -> html5Key "" "" n wh ">" "" "great"
118 KeyEqual n wh -> html5Key "" "" n wh "=" "" "equal"
119 KeyBar n wh -> html5Key "" "" n wh "|" "" "bar"
120 KeyDot n -> html5Key "" "" n "" "." "" "dot"
121 KeyDash -> html5Key "" "" "" "" "-" " " "dash"
122 KeyDashDash -> html5Key "" "" "" "" "--" " " "dashdash"
123 KeyBrackets n -> html5Key "[" "" n "" "]" "" "dashdash"
124 KeyLower name attrs -> do
125 H.span ! HA.class_ (mconcat ["key key-lower"," key-name-",attrValue name]) $ do
126 H.span ! HA.class_ "key-mark" $ H.toMarkup '<'
127 H.span ! HA.class_ "key-name" $ H.toMarkup name
131 html5Key :: Text -> White -> Text -> White -> Text -> White -> H.AttributeValue -> Html
132 html5Key markBegin whmb name whn markEnd whme cl = do
133 -- html5Spaces $ colPos posEnd - (colPos pos + Text.length name + 1)
134 H.span ! HA.class_ (mconcat ["key key-",cl," key-name-",attrValue name]) $ do
135 when (markBegin/="") $
136 H.span ! HA.class_ "key-mark" $ H.toMarkup markBegin
139 H.span ! HA.class_ "key-name" $ H.toMarkup name
142 H.span ! HA.class_ "key-mark" $ H.toMarkup markEnd
144 H.span ! HA.class_ "key-value" $
147 html5IndentToken :: Tokens -> Html
148 html5IndentToken (Seq.viewl -> EmptyL) = ""
149 html5IndentToken toks@(Seq.viewl -> Cell pos _ _ :< _) =
150 goTokens toks `S.evalState` linePos pos
152 indent = Text.replicate (columnPos pos - 1) " "
153 go :: Cell Token -> S.State Int Html
158 let lines = Text.splitOn "\n" txt
159 let lnums = H.toMarkup :
162 H.a ! HA.id ("line-"<>attrValue lnum) $ return ()
167 S.put (lin - 1 + L.length lines)
168 return $ mconcat $ L.zipWith ($) lnums lines
171 H.span ! HA.class_ "tag" $ do
172 H.span ! HA.class_ "tag-open" $ H.toMarkup '#'
174 TokenEscape c -> return $ H.toMarkup ['\\',c]
177 H.a ! HA.href (attrValue lnk) $
179 TokenPair (PairElem name attrs) ts -> do
182 let cl = mconcat ["pair-PairElem", " pair-elem-", attrValue name]
183 H.span ! HA.class_ cl $ do
184 whenMarkup o $ H.span ! HA.class_ "pair-open" $ o
185 whenMarkup h $ H.span ! HA.class_ "pair-content" $ h
186 whenMarkup c $ H.span ! HA.class_ "pair-close" $ c
188 html5name = H.span ! HA.class_ "elem-name" $ H.toMarkup name
193 ( "<"<>html5name<>html5Attrs attrs<>"/>"
196 ( "<"<>html5name<>html5Attrs attrs<>">"
197 , "</"<>html5name<>">" )
198 TokenPair grp ts -> do
201 let (o,c) = pairBorders grp ts
202 H.span ! HA.class_ (mconcat ["pair-", fromString $ show grp]) $ do
203 H.span ! HA.class_ "pair-open" $ H.toMarkup o
204 H.span ! HA.class_ "pair-content" $ h
205 H.span ! HA.class_ "pair-close" $ H.toMarkup c
206 goTokens :: Tokens -> S.State Int Html
209 return $ foldr (<>) mempty ts'
211 html5Attrs :: Attrs -> Html
212 html5Attrs = foldMap html5Attr
214 html5Attr :: (Text,Attr) -> Html
215 html5Attr (attr_white,Attr{..}) = do
216 H.toMarkup attr_white
217 H.span ! HA.class_ "attr-name" $
220 H.span ! HA.class_ "attr-value" $
221 H.toMarkup attr_value
222 H.toMarkup attr_close