1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE RecordWildCards #-}
3 {-# LANGUAGE ViewPatterns #-}
4 -- | Render a TCT source file in HTML5.
5 module Language.TCT.Write.HTML5.Source 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 Prelude (Num(..), undefined)
21 import Text.Blaze ((!))
22 import Text.Blaze.Html (Html)
23 import Text.Show (Show(..))
24 import qualified Control.Monad.Trans.State as S
25 import qualified Data.List as L
26 import qualified Data.Sequence as Seq
27 import qualified Data.Text as Text
28 import qualified Data.Text.Lazy as TL
29 import qualified Text.Blaze.Html5 as H
30 import qualified Text.Blaze.Html5.Attributes as HA
32 import Text.Blaze.Utils
33 import Language.TCT.Tree
34 import Language.TCT.Token
35 import Language.TCT.Elem
36 import Language.TCT.Write.Text
39 class HTML5able a where
42 class Textable a where
44 instance HTML5able TCT where
47 html5 :: Trees (Cell Key) (Cell Tokens) -> Html
52 H.meta ! HA.httpEquiv "Content-Type"
53 ! HA.content "text/html; charset=UTF-8"
54 whenJust (titleTCT tct) $ \(unCell -> ts) ->
55 H.title $ H.toMarkup $ L.head $
56 Text.lines (TL.toStrict $ t_Tokens ts) <> [""]
57 -- link ! rel "Chapter" ! title "SomeTitle">
58 H.link ! HA.rel "stylesheet"
60 ! HA.href "style/tct-html5-source.css"
62 H.a ! HA.id ("line-1") $ return ()
63 h_TreesCell (treePosLastCell tct)
65 h_TreesCell :: Trees (Pos,Cell Key) (Pos,Cell Tokens) -> Html
66 h_TreesCell = foldMap h_TreeCell
68 titleTCT :: Trees (Cell Key) (Cell a) -> Maybe (Cell a)
71 TreeN (unCell -> KeySection{}) _ts -> True
74 TreeN (unCell -> KeySection _lvl) (Seq.viewl -> Tree0 title:<_) -> Just title
77 h_Text :: Text -> Html
80 h_Spaces :: Int -> Html
81 h_Spaces 0 = return ()
82 h_Spaces sp = H.span $ h_Text $ Text.replicate sp " "
84 h_TreeCell :: Tree (Pos,Cell Key) (Pos,Cell Tokens) -> Html
85 h_TreeCell (TreeN c@(_, unCell -> KeySection lvl) ts) = do
88 H.span ! HA.class_ "section-title" $ do
89 H.span $ h_Text $ Text.replicate lvl "#" <> " "
91 Tree0 (_,Cell posTitle _ title) :< _ -> h lvl $ h_IndentToken posTitle title
94 case Seq.viewl ts of {Tree0{} :< ts' -> ts'; _ -> ts}
102 h n | n > 0 = H.span ! HA.class_ ("h h"<>attrValue n)
104 h_TreeCell (Tree0 c@(_,cell)) = do
107 h_TreeCell (TreeN c@(_,cell) cs) = do
111 h_IndentCell :: (Pos,Cell a) -> Html
112 h_IndentCell (Pos lineLast colLast,posCell -> Pos line col)
113 | lineLast < line = do
114 forM_ [lineLast+1..line] $ \lnum -> do
116 H.a ! HA.id ("line-"<>attrValue lnum) $ return ()
117 H.toMarkup $ Text.replicate (col - 1) " "
119 && colLast <= col = H.toMarkup $ Text.replicate (col - colLast) " "
120 | otherwise = undefined
122 h_CellKey :: Cell Key -> Trees (Pos,Cell Key) (Pos,Cell Tokens) -> Html
123 h_CellKey (Cell _pos _posEnd key) ts = do
125 KeyColon n wh -> h_Key "" "" n wh ":" "" "colon"
126 KeyGreat n wh -> h_Key "" "" n wh ">" "" "great"
127 KeyEqual n wh -> h_Key "" "" n wh "=" "" "equal"
128 KeyBar n wh -> h_Key "" "" n wh "|" "" "bar"
129 KeyDot n -> h_Key "" "" n "" "." "" "dot"
130 KeyDash -> h_Key "" "" "" "" "-" " " "dash"
131 KeyDashDash -> h_Key "" "" "" "" "--" " " "dashdash"
132 KeyBrackets n -> h_Key "[" "" n "" "]" "" "dashdash"
133 KeyLower name attrs -> do
134 H.span ! HA.class_ (mconcat ["key key-lower"," key-name-",attrValue name]) $ do
135 H.span ! HA.class_ "key-mark" $ H.toMarkup '<'
136 H.span ! HA.class_ "key-name" $ H.toMarkup name
140 h_Key :: Text -> White -> Text -> White -> Text -> White -> H.AttributeValue -> Html
141 h_Key markBegin whmb name whn markEnd whme cl = do
142 -- h_Spaces $ colPos posEnd - (colPos pos + Text.length name + 1)
143 H.span ! HA.class_ (mconcat ["key key-",cl," key-name-",attrValue name]) $ do
144 when (markBegin/="") $
145 H.span ! HA.class_ "key-mark" $ H.toMarkup markBegin
148 H.span ! HA.class_ "key-name" $ H.toMarkup name
151 H.span ! HA.class_ "key-mark" $ H.toMarkup markEnd
153 H.span ! HA.class_ "key-value" $
156 h_CellToken :: Cell Tokens -> Html
157 h_CellToken (Cell pos _posEnd tok) =
158 h_IndentToken pos tok
160 h_IndentToken :: Pos -> Tokens -> Html
161 h_IndentToken pos toks = goTokens toks `S.evalState` linePos pos
163 indent = Text.replicate (columnPos pos - 1) " "
164 go :: Token -> S.State Int Html
165 go (TokenPlain txt) = do
167 let lines = Text.splitOn "\n" txt
168 let lnums = H.toMarkup :
171 H.a ! HA.id ("line-"<>attrValue lnum) $ return ()
176 S.put (lin - 1 + L.length lines)
177 return $ mconcat $ L.zipWith ($) lnums lines
180 H.span ! HA.class_ "tag" $ do
181 H.span ! HA.class_ "tag-open" $ H.toMarkup '#'
183 go (TokenEscape c) = return $ H.toMarkup ['\\',c]
184 go (TokenLink lnk) = do
186 H.a ! HA.href (attrValue lnk) $
188 go (TokenPair (PairElem name attrs) ts) = do
191 let cl = mconcat ["pair-PairElem", " pair-elem-", attrValue name]
192 H.span ! HA.class_ cl $ do
193 whenMarkup o $ H.span ! HA.class_ "pair-open" $ o
194 whenMarkup h $ H.span ! HA.class_ "pair-content" $ h
195 whenMarkup c $ H.span ! HA.class_ "pair-close" $ c
197 h_name = H.span ! HA.class_ "elem-name" $ H.toMarkup name
201 Tokens s | Seq.null s ->
202 ( "<"<>h_name<>h_Attrs attrs<>"/>"
205 ( "<"<>h_name<>h_Attrs attrs<>">"
206 , "</"<>h_name<>">" )
207 go (TokenPair grp ts) = do
210 let (o,c) = pairBorders grp ts
211 H.span ! HA.class_ (mconcat ["pair-", fromString $ show grp]) $ do
212 H.span ! HA.class_ "pair-open" $ H.toMarkup o
213 H.span ! HA.class_ "pair-content" $ h
214 H.span ! HA.class_ "pair-close" $ H.toMarkup c
215 goTokens (Tokens ts) = do
217 return $ foldr (<>) mempty ts'
219 h_Attrs :: Attrs -> Html
220 h_Attrs = foldMap h_Attr
222 h_Attr :: (Text,Attr) -> Html
223 h_Attr (attr_white,Attr{..}) = do
224 H.toMarkup attr_white
225 H.span ! HA.class_ "attr-name" $
228 H.span ! HA.class_ "attr-value" $
229 H.toMarkup attr_value
230 H.toMarkup attr_close