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 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
38 class HTML5able a where
41 class Textable a where
43 instance HTML5able TCT where
51 H.meta ! HA.httpEquiv "Content-Type"
52 ! HA.content "text/html; charset=UTF-8"
53 whenJust (titleTCT tct) $ \ts ->
54 H.title $ H.toMarkup $ L.head $
55 Text.lines (TL.toStrict $ t_Tokens ts) <> [""]
56 -- link ! rel "Chapter" ! title "SomeTitle">
57 H.link ! HA.rel "stylesheet"
59 ! HA.href "style/tct-html5-source.css"
61 H.a ! HA.id ("line-1") $ return ()
62 h_TreesCell (treePosLastCell tct)
64 h_TreesCell :: Trees (Pos,Cell Key) (Pos,Tokens) -> Html
65 h_TreesCell = foldMap h_TreeCell
67 titleTCT :: Trees (Cell Key) Tokens -> Maybe Tokens
70 TreeN (unCell -> KeySection{}) _ts -> True
73 TreeN (unCell -> KeySection _lvl) (Seq.viewl -> Tree0 title:<_) -> Just title
76 h_Text :: Text -> Html
79 h_Spaces :: Int -> Html
80 h_Spaces 0 = return ()
81 h_Spaces sp = H.span $ h_Text $ Text.replicate sp " "
83 h_TreeCell :: Tree (Pos,Cell Key) (Pos,Tokens) -> Html
84 h_TreeCell (TreeN (posEnd, Cell pos _ (KeySection lvl)) ts) = do
85 h_IndentCell (posEnd,pos)
87 H.span ! HA.class_ "section-title" $ do
88 H.span $ h_Text $ Text.replicate lvl "#" <> " "
90 Tree0 (_,title) :< _ -> h lvl $ h_IndentToken title
93 case Seq.viewl ts of {Tree0{} :< ts' -> ts'; _ -> ts}
101 h n | n > 0 = H.span ! HA.class_ ("h h"<>attrValue n)
103 h_TreeCell (Tree0 (posEnd,toks)) =
104 case Seq.viewl toks of
105 EmptyL -> h_IndentToken toks
106 t0:<_ -> h_IndentCell (posEnd,posCell t0) <> h_IndentToken toks
107 h_TreeCell (TreeN (posEnd,cell@(Cell pos _ _)) cs) =
108 h_IndentCell (posEnd,pos) <>
111 h_IndentCell :: (Pos,Pos) -> Html
112 h_IndentCell (Pos lineLast colLast,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,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_IndentToken :: Tokens -> Html
157 h_IndentToken (Seq.viewl -> EmptyL) = ""
158 h_IndentToken toks@(Seq.viewl -> Cell pos _ _ :< _) =
159 goTokens toks `S.evalState` linePos pos
161 indent = Text.replicate (columnPos pos - 1) " "
162 go :: Cell Token -> S.State Int Html
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 TokenEscape c -> return $ H.toMarkup ['\\',c]
186 H.a ! HA.href (attrValue lnk) $
188 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
202 ( "<"<>h_name<>h_Attrs attrs<>"/>"
205 ( "<"<>h_name<>h_Attrs attrs<>">"
206 , "</"<>h_name<>">" )
207 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 -> S.State Int Html
218 return $ foldr (<>) mempty ts'
220 h_Attrs :: Attrs -> Html
221 h_Attrs = foldMap h_Attr
223 h_Attr :: (Text,Attr) -> Html
224 h_Attr (attr_white,Attr{..}) = do
225 H.toMarkup attr_white
226 H.span ! HA.class_ "attr-name" $
229 H.span ! HA.class_ "attr-value" $
230 H.toMarkup attr_value
231 H.toMarkup attr_close