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
201 (toList -> [TokenPair PairElem{} _ts]) -> d_Tokens path ts
202 _ -> D.para $ d_Tokens path ts
203 _ -> d_Tokens path ts
205 d_Tokens :: [Key] -> Tokens -> DTC
206 d_Tokens _path tok = goTokens tok
208 -- indent = Text.replicate (columnPos pos - 1) " "
210 go (TokenPlain t) = B.toMarkup t
211 go (TokenTag t) = D.ref mempty ! DA.to (attrValue t)
212 go (TokenEscape c) = B.toMarkup c
213 go (TokenLink lnk) = D.eref (B.toMarkup lnk) ! DA.to (attrValue lnk)
214 go (TokenPair PairSlash ts) = D.i $ goTokens ts
215 go (TokenPair PairBackquote ts) = D.code $ goTokens ts
216 go (TokenPair PairFrenchquote ts) = D.q $ goTokens ts
217 go (TokenPair PairHash (toList -> [TokenPlain ts])) =
218 D.ref mempty ! DA.to (attrValue ts)
219 go (TokenPair (PairElem name attrs) ts) =
222 Tokens s | Seq.null s ->
223 B.CustomLeaf (B.Text name) True mempty
224 _ -> B.CustomParent (B.Text name) $ goTokens ts
225 go (TokenPair p ts) = do
226 let (o,c) = pairBorders p ts
230 goTokens :: Tokens -> DTC
231 goTokens (Tokens ts) = foldMap go ts
233 d_Attrs :: Attrs -> DTC -> DTC
234 d_Attrs = flip $ foldl' d_Attr
236 d_Attr :: DTC -> (Text,Attr) -> DTC
237 d_Attr acc (_,Attr{..}) =
243 -- attr_id :: Text -> [(Text,Text)] -> [(Text,Text)]
244 -- attr_id title = ("id",title)
246 -- * Type 'Attributes'
247 type Attributes = Map Name Text
249 d_attrs :: Attributes -> DTC -> DTC
250 d_attrs = flip $ Map.foldrWithKey $ \n v ->
251 B.AddCustomAttribute (B.Text n) (B.Text v)
253 partitionAttributesChildren ::
254 Trees (Cell Key) (Cell Tokens) ->
255 (Attributes, Trees (Cell Key) (Cell Tokens))
256 partitionAttributesChildren ts = (attrs,children)
263 TreeN (unCell -> KeyEqual n _wh) a -> Map.insert n v acc
266 Write.text Write.config_text{Write.config_text_escape = False} $
267 Write.treeRackUpLeft <$> a
270 children = Seq.filter (\t ->
273 TreeN (unCell -> KeyEqual{}) _cs -> False