1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE RecordWildCards #-}
3 {-# LANGUAGE ViewPatterns #-}
4 {-# OPTIONS_GHC -fno-warn-orphans #-}
5 -- | Render a TCT file in DTC.
6 module Language.TCT.Write.DTC where
8 import Control.Monad (Monad(..), forM_, when)
10 import Data.Foldable (foldr, null, foldMap, foldl', any)
11 import Data.Function (($), (.), flip)
12 import Data.Functor ((<$>))
13 import Data.Map.Strict (Map)
14 import Data.Maybe (Maybe(..))
15 import Data.Monoid (Monoid(..))
16 import Data.Semigroup (Semigroup(..))
17 import Data.Sequence (ViewL(..), (<|), (|>))
18 import Data.String (String)
19 import Data.Text (Text)
20 import GHC.Exts (toList)
21 import Text.Blaze ((!))
22 import Text.Show (Show(..))
23 import qualified Data.Char as Char
24 import qualified Data.Map.Strict as Map
25 import qualified Data.Sequence as Seq
26 import qualified Data.Text as Text
27 import qualified Data.Text.Lazy as TL
28 import qualified Text.Blaze as B
29 import qualified Text.Blaze.Internal as B
31 import Language.TCT.Tree
32 import Language.TCT.Token
33 import Language.TCT.Elem hiding (trac,dbg)
34 import qualified Language.TCT.Write.Text as Write
35 import Text.Blaze.Utils
36 import Text.Blaze.DTC (DTC)
37 import qualified Text.Blaze.DTC as D
38 import qualified Text.Blaze.DTC.Attributes as DA
40 import Debug.Trace (trace)
41 trac :: String -> a -> a
44 dbg :: Show a => String -> a -> a
45 dbg m x = trac (m <> ": " <> show x) x
47 dtc :: Trees (Cell Key) (Cell Tokens) -> DTC
50 D.xmlModel "./schema/dtc.rnc"
51 D.xmlStylesheet $ "./xsl/document.html5."<>lang<>".xsl"
52 D.html5Stylesheet $ "./xsl/document.html5."<>lang<>".xsl"
53 D.atomStylesheet $ "./xsl/document.atom."<>lang<>".xsl"
56 TreeN (unCell -> KeySection{})
57 (Seq.viewl -> Tree0 (unCell -> Write.t_Tokens -> TL.toStrict -> title) :< head)
59 d_Trees [] (mangleHead title head)
66 Trees (Cell Key) (Cell Tokens) ->
67 Trees (Cell Key) (Cell Tokens)
68 mangleHead title head =
70 (`Seq.findIndexL` head) $ \case
71 TreeN (unCell -> KeyColon "about" _) _ -> True
75 TreeN (cell0 (KeyColon "about" ""))
78 Just i -> Seq.adjust f i head
80 f (TreeN c about) = TreeN c $ Seq.fromList names <> about
83 names = name <$> Text.splitOn "\n" title
85 TreeN (cell0 (KeyColon "name" "")) .
88 Tokens . Seq.singleton . TokenPlain
90 d_Trees :: [Key] -> Trees (Cell Key) (Cell Tokens) -> DTC
93 _ | (ul,ts') <- gatherLIs ts, not (null ul) -> do
94 D.ul $ forM_ ul $ d_Tree path
96 _ | t:<ts' <- Seq.viewl ts -> do
103 Trees (Cell Key) (Cell Tokens) ->
104 ( Trees (Cell Key) (Cell Tokens)
105 , Trees (Cell Key) (Cell Tokens) )
107 let (lis, ts') = spanLIs ts in
108 foldl' accumLIs (mempty,ts') lis
110 spanLIs = Seq.spanl $ \case
111 TreeN (unCell -> KeyDash) _ -> True
112 Tree0 (unCell -> Tokens toks) ->
114 TokenPair (PairElem "li" _) _ -> True
117 accumLIs acc@(oks,kos) t =
119 TreeN (unCell -> KeyDash) _ -> (oks|>t,kos)
120 Tree0 (Cell pos posEnd (Tokens toks)) ->
121 let mk = Tree0 . Cell pos posEnd . Tokens in
123 (`Seq.spanl` toks) $ \case
124 TokenPair (PairElem "li" _) _ -> True
125 TokenPlain txt -> Char.isSpace`Text.all`txt
127 ( if null ok then oks else oks|>mk (rmTokenPlain ok)
128 , if null ko then kos else mk ko<|kos )
132 TokenPlain{} -> False
135 d_Tree :: [Key] -> Tree (Cell Key) (Cell Tokens) -> DTC
136 d_Tree path (TreeN (unCell -> key@KeySection{}) ts) =
137 case Seq.viewl children of
138 Tree0 (Cell _posTitle _ (toList -> [TokenPlain title])) :< body ->
139 d_attrs (mangleAttrs title attrs) $
140 case Text.splitOn "\n" title of
142 D.section ! DA.name (attrValue t0) $ do
143 let st = Text.intercalate "\n" t1
144 when (not (Text.null st)) $
145 D.name $ B.toMarkup st
148 D.section ! DA.name (attrValue title) $
150 Tree0 (Cell _posTitle _ title) :< body ->
151 d_attrs (mangleAttrs (TL.toStrict $ Write.t_Tokens title) attrs) $
153 D.name $ d_Tokens (key:path) title
157 D.section $ d_content children
159 (attrs,children) = partitionAttributesChildren ts
160 d_content cs = d_Trees (key:path) cs
161 mangleAttrs :: Text -> Attributes -> Attributes
162 mangleAttrs title = Map.insertWith (\_new old -> old) "id" title
163 d_Tree path (Tree0 cell) = d_CellTokens path cell
164 d_Tree path (TreeN cell@(unCell -> KeyColon{}) ts) =
165 let (attrs,children) = partitionAttributesChildren ts in
166 d_attrs attrs $ d_CellKey path cell children
167 d_Tree path (TreeN cell ts) = d_CellKey path cell ts
169 d_CellKey :: [Key] -> Cell Key -> Trees (Cell Key) (Cell Tokens) -> DTC
170 d_CellKey path (Cell _pos _posEnd key) cells = do
172 KeyColon n _wh -> d_Key n
173 KeyGreat n _wh -> d_Key n
174 KeyEqual n _wh -> d_Key n
175 KeyBar n _wh -> d_Key n
176 KeyDash -> D.li $ d_Trees (key:path) cells
178 KeyLower name attrs -> do
179 B.Content $ "<"<>B.toMarkup name
181 forM_ cells $ d_Tree path
185 d_Key name | null cells =
186 B.CustomLeaf (B.Text name) True mempty
188 B.CustomParent (B.Text name) $
189 d_Trees (key:path) cells
191 d_CellTokens :: [Key] -> Cell Tokens -> DTC
192 d_CellTokens path (Cell _pos _posEnd ts) =
193 -- case L.find (\case KeySection{} -> True; _ -> False) $ dbg "d_CellTokens: path:" path of
194 case dbg "d_CellTokens: path" path of
197 (toList -> [TokenPair PairElem{} _ts]) -> d_Tokens path ts
198 _ -> D.para $ d_Tokens path ts
199 _ -> d_Tokens path ts
201 d_Tokens :: [Key] -> Tokens -> DTC
202 d_Tokens _path tok = goTokens tok
204 -- indent = Text.replicate (columnPos pos - 1) " "
206 go (TokenPlain t) = B.toMarkup t
207 go (TokenTag t) = D.ref mempty ! DA.to (attrValue t)
208 go (TokenEscape c) = B.toMarkup c
209 go (TokenLink lnk) = D.eref (B.toMarkup lnk) ! DA.to (attrValue lnk)
210 go (TokenPair PairSlash ts) = D.i $ goTokens ts
211 go (TokenPair PairBackquote ts) = D.code $ goTokens ts
212 go (TokenPair PairFrenchquote ts) = D.q $ goTokens ts
213 go (TokenPair PairHash (toList -> [TokenPlain ts])) =
214 D.ref mempty ! DA.to (attrValue ts)
215 go (TokenPair (PairElem name attrs) ts) =
218 Tokens s | Seq.null s ->
219 B.CustomLeaf (B.Text name) True mempty
220 _ -> B.CustomParent (B.Text name) $ goTokens ts
221 go (TokenPair p ts) = do
222 let (o,c) = pairBorders p ts
226 goTokens :: Tokens -> DTC
227 goTokens (Tokens ts) = foldMap go ts
229 d_Attrs :: Attrs -> DTC -> DTC
230 d_Attrs = flip $ foldl' d_Attr
232 d_Attr :: DTC -> (Text,Attr) -> DTC
233 d_Attr acc (_,Attr{..}) =
239 -- attr_id :: Text -> [(Text,Text)] -> [(Text,Text)]
240 -- attr_id title = ("id",title)
242 -- * Type 'Attributes'
243 type Attributes = Map Name Text
245 d_attrs :: Attributes -> DTC -> DTC
246 d_attrs = flip $ Map.foldrWithKey $ \n v ->
247 B.AddCustomAttribute (B.Text n) (B.Text v)
249 partitionAttributesChildren ::
250 Trees (Cell Key) (Cell Tokens) ->
251 (Attributes, Trees (Cell Key) (Cell Tokens))
252 partitionAttributesChildren ts = (attrs,children)
259 TreeN (unCell -> KeyEqual n _wh) a -> Map.insert n v acc
262 Write.text Write.config_text{Write.config_text_escape = False} $
263 Write.treeRackUpLeft <$> a
266 children = Seq.filter (\t ->
269 TreeN (unCell -> KeyEqual{}) _cs -> False