1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE ViewPatterns #-}
3 -- | Render a TCT source file in HTML5.
4 module Language.TCT.HTML5.Source where
6 -- import Data.Char (Char)
7 -- import Data.Eq (Eq(..))
9 -- import Data.Text.Lazy.Builder (Buildable(..))
10 -- import qualified Data.ByteString.Lazy as BSL
11 -- import qualified Data.Char as Char
12 -- import qualified Data.Text.Lazy as TL
13 -- import qualified Data.Text.Lazy.Builder as TL
14 import Control.Applicative (Applicative(..))
15 import Control.Monad (Monad(..), forM_, mapM)
17 import Data.Eq (Eq(..))
18 import Data.Foldable (sum)
19 import Data.Function (($), (.), const, id)
20 import Data.Functor ((<$>))
22 import Data.Maybe (Maybe(..))
23 import Data.Monoid (Monoid(..))
24 import Data.Ord (Ord(..))
25 import Data.Semigroup (Semigroup(..))
26 import Data.Sequence (ViewL(..))
27 import Data.String (IsString(..))
28 import Data.Text (Text)
29 import Prelude (Num(..), undefined)
30 import Text.Blaze ((!))
31 import Text.Blaze.Html (Html)
32 import Text.Show (Show(..))
33 import qualified Control.Monad.Trans.State as S
34 import qualified Data.List as L
35 import qualified Data.Sequence as Seq
36 import qualified Data.Text as T
37 import qualified Text.Blaze.Html5 as H
38 import qualified Text.Blaze.Html5.Attributes as HA
40 import Language.TCT.Tree
41 import Language.TCT.Markup
42 import Language.TCT.Read.Tree
43 import Language.TCT.Read.Markup
46 class HTML5able a where
49 class Textable a where
51 instance HTML5able TCT where
54 whenJust :: Applicative m => Maybe a -> (a -> m ()) -> m ()
55 whenJust Nothing _f = pure ()
56 whenJust (Just a) f = f a
58 html5 :: Trees (Cell Key) (Cell Markup) -> Html
63 H.meta ! HA.httpEquiv "Content-Type"
64 ! HA.content "text/html; charset=UTF-8"
65 whenJust (titleTCT tct) $ \(unCell -> t) ->
66 H.title $ H.toMarkup $ t_Markup t
67 -- link ! rel "Chapter" ! title "SomeTitle">
68 H.link ! HA.rel "stylesheet"
70 ! HA.href "tct-text.css"
72 H.a ! HA.id ("line-1") $ return ()
73 forM_ (treePosLastCell tct) $ h_TreeCell
75 titleTCT :: Trees (Cell Key) (Cell a) -> Maybe (Cell a)
78 TreeN (unCell -> KeySection{}) _ts -> True
81 TreeN (unCell -> KeySection _lvl) (Seq.viewl -> Tree0 title:<_) -> Just title
84 h_Text :: Text -> Html
87 h_Spaces :: Int -> Html
88 h_Spaces 0 = return ()
89 h_Spaces sp = H.span $ h_Text $ T.replicate sp " "
91 h_TreeCell :: Tree (Pos,Cell Key) (Pos,Cell Markup) -> Html
92 h_TreeCell (TreeN c@(_, unCell -> KeySection lvl) ts) = do
95 H.span ! HA.class_ "section-title" $ do
96 H.span $ h_Text $ T.replicate lvl "#" <> " "
98 Tree0 (_,Cell posTitle _ title) :< _ -> h lvl $ h_Markup posTitle title
100 forM_ (case Seq.viewl ts of {Tree0{} :< ts' -> ts'; _ -> ts}) $ h_TreeCell
108 h n | n > 0 = H.span ! HA.class_ ("h h"`mappend`fromString (show n))
110 h_TreeCell (Tree0 c@(_,cell)) = do
113 h_TreeCell (TreeN c@(_,cell) cs) = do
116 forM_ cs $ h_TreeCell
118 h_IndentCell :: (Pos,Cell a) -> Html
119 h_IndentCell ((lineLast,colLast),posCell -> (line,col))
120 | lineLast < line = do
121 forM_ [lineLast+1..line] $ \lnum -> do
123 H.a ! HA.id ("line-"`mappend`fromString (show lnum)) $ return ()
124 H.toMarkup $ T.replicate (col - 1) " "
126 && colLast <= col = H.toMarkup $ T.replicate (col - colLast) " "
127 | otherwise = undefined
129 h_CellKey :: Cell Key -> Html
130 h_CellKey (Cell pos posEnd key) = do
132 KeyColon n -> h_Key n ':' "colon"
133 KeyGreat n -> h_Key n '>' "great"
134 KeyEqual n -> h_Key n '=' "equal"
135 KeyBar n -> h_Key n '|' "bar"
136 KeyDash -> H.toMarkup ("- "::Text)
138 h_Key nam mark cl = do
139 -- h_Spaces $ colPos posEnd - (colPos pos + T.length nam + 1)
140 H.span ! HA.class_ (mconcat ["key key-",cl," key-name-",fromString $ T.unpack nam]) $ do
142 H.span ! HA.class_ "key-mark" $ H.toMarkup mark
144 h_CellKey (TreeN (Cell pos posEnd k) _) = do
146 H.pre $ H.toMarkup $ show k
149 h_CellText :: Cell Text -> Html
150 h_CellText (Cell pos posEnd a) = h_IndentText pos a
152 h_CellMarkup :: Cell Markup -> Html
153 h_CellMarkup (Cell pos posEnd (MarkupPlain t)) =
156 h_IndentText :: Pos -> Text -> Html
158 let lines = T.splitOn "\n" v in
159 let lnums = H.toMarkup :
162 H.a ! HA.id ("line-"`mappend`fromString (show lnum)) $ return ()
165 | lnum <- [linePos pos+1..]
167 mconcat $ L.zipWith ($) lnums lines
168 where pad = T.replicate (columnPos pos - 1) " "
170 h_Markup :: Pos -> Markup -> Html
171 h_Markup pos (MarkupPlain v) = h_IndentText pos v
173 h_Markup pos (Tag v) =
174 H.span ! HA.class_ "tag" $
175 toMarkup $ T.concat ["#",v,if T.all isTagNameShortChar v then "" else "#"]
176 h_Markup pos (Values vs) = do
177 forM_ vs (h_Markup pos)
178 h_Markup pos v = H.pre $ toMarkup $ show v
181 t_Markup :: Markup -> Text
182 t_Markup (MarkupPlain t) = t
183 t_Value :: Text -> Text
186 t_Value (Tag v) = T.concat ["#",v,if T.all isTagNameShortChar v then "" else "#"]
187 t_Value v = T.pack $ show v
190 treePosLastCell :: Trees (Cell k) (Cell a) -> Trees (Pos,Cell k) (Pos,Cell a)
191 treePosLastCell t = S.evalState (go`mapM`t) (1,1)
195 S.put $ posEndCell cell
196 return $ Tree0 (lastPos,cell)
197 go (TreeN cell ts) = do
199 S.put $ posEndCell cell
201 return $ TreeN (lastPos,cell) ts'
204 colValue :: Value -> Column
206 Plain t -> T.length t
207 Tag t -> T.length t + (if T.all isTagNameCharShort t then 0 else 1)
208 Values vs -> sum $ colValue <$> vs
209 Group _g v -> 2 + colValue v