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 (Foldable(..))
11 import Data.Function (($), (.), flip)
12 import Data.Functor ((<$>))
13 import Data.Monoid (Monoid(..))
14 import Data.Semigroup (Semigroup(..))
15 import Data.Sequence (ViewL(..))
16 import Data.String (String)
17 import Data.Text (Text)
18 import Text.Blaze ((!))
19 import Text.Show (Show(..))
20 import Data.Map.Strict (Map)
21 import qualified Data.Sequence as Seq
22 import qualified Data.Text as Text
23 import qualified Text.Blaze as B
24 import qualified Text.Blaze.Internal as B
25 import qualified Data.Text.Lazy as TL
26 import qualified Data.Map.Strict as Map
28 import Language.TCT.Tree
29 import Language.TCT.Token
30 import Language.TCT.Elem hiding (trac,dbg)
31 import qualified Language.TCT.Write.Text as Write
32 import Text.Blaze.Utils
33 import Text.Blaze.DTC (DTC)
34 import qualified Text.Blaze.DTC as D
35 import qualified Text.Blaze.DTC.Attributes as DA
37 import Debug.Trace (trace)
38 trac :: String -> a -> a
41 dbg :: Show a => String -> a -> a
42 dbg m x = trac (m <> ": " <> show x) x
44 dtc :: Trees (Cell Key) (Cell Tokens) -> DTC
47 D.xmlModel "./schema/dtc.rnc"
48 D.xmlStylesheet $ "./xsl/document.html5."<>lang<>".xsl"
49 D.html5Stylesheet $ "./xsl/document.html5."<>lang<>".xsl"
50 D.atomStylesheet $ "./xsl/document.atom."<>lang<>".xsl"
53 TreeN (unCell -> KeySection{})
54 (Seq.viewl -> Tree0 (unCell -> Write.t_Tokens -> TL.toStrict -> title) :< head)
56 d_Trees [] (mangleHead title head)
63 Trees (Cell Key) (Cell Tokens) ->
64 Trees (Cell Key) (Cell Tokens)
65 mangleHead title head =
67 TreeN cell@(unCell -> KeyColon "about" _) about ->
68 TreeN cell $ Seq.fromList (name <$> Text.splitOn "\n" title) <> about
71 TreeN (cell0 (KeyColon "name" "")) .
72 Seq.fromList . return .
74 tokens . return . TokenPlain
77 d_Trees :: [Key] -> Trees (Cell Key) (Cell Tokens) -> DTC
80 _ | (ul,ts') <- Seq.spanl (\case TreeN (unCell -> KeyDash) _ -> True
81 Tree0 (unCell -> unTokens -> toList -> [TokenPair (PairElem "li" _) _]) -> True
84 D.ul $ forM_ ul $ d_Tree path
86 _ | t:<ts' <- Seq.viewl ts -> do
92 d_Tree :: [Key] -> Tree (Cell Key) (Cell Tokens) -> DTC
93 d_Tree path (TreeN (unCell -> key@KeySection{}) ts) =
94 case Seq.viewl children of
95 Tree0 (Cell _posTitle _ (unTokens -> toList -> [TokenPlain title])) :< body ->
96 d_attrs (mangleAttrs title attrs) $
97 case Text.splitOn "\n" title of
99 D.section ! DA.name (attrValue t0) $ do
100 let st = Text.intercalate "\n" t1
101 when (not (Text.null st)) $
102 D.name $ B.toMarkup st
105 D.section ! DA.name (attrValue title) $
107 Tree0 (Cell _posTitle _ title) :< body ->
108 d_attrs (mangleAttrs (TL.toStrict $ Write.t_Tokens title) attrs) $
110 D.name $ d_Tokens (key:path) title
114 D.section $ d_content children
116 (attrs,children) = partitionAttributesChildren ts
117 d_content cs = d_Trees (key:path) cs
118 mangleAttrs :: Text -> Attributes -> Attributes
119 mangleAttrs title = Map.insertWith (\_new old -> old) "id" title
120 d_Tree path (Tree0 cell) = d_CellTokens path cell
121 d_Tree path (TreeN cell@(unCell -> KeyColon{}) ts) =
122 let (attrs,children) = partitionAttributesChildren ts in
123 d_attrs attrs $ d_CellKey path cell children
124 d_Tree path (TreeN cell ts) = d_CellKey path cell ts
126 d_CellKey :: [Key] -> Cell Key -> Trees (Cell Key) (Cell Tokens) -> DTC
127 d_CellKey path (Cell _pos _posEnd key) cells = do
129 KeyColon n _wh -> d_Key n
130 KeyGreat n _wh -> d_Key n
131 KeyEqual n _wh -> d_Key n
132 KeyBar n _wh -> d_Key n
133 KeyDash -> D.li $ d_Trees (key:path) cells
135 KeyLower name attrs -> do
136 B.Content $ "<"<>B.toMarkup name
138 forM_ cells $ d_Tree path
142 d_Key name | null cells =
143 B.CustomLeaf (B.Text name) True mempty
145 B.CustomParent (B.Text name) $
146 d_Trees (key:path) cells
148 d_CellTokens :: [Key] -> Cell Tokens -> DTC
149 d_CellTokens path (Cell _pos _posEnd ts) =
150 -- case L.find (\case KeySection{} -> True; _ -> False) $ dbg "d_CellTokens: path:" path of
151 case dbg "d_CellTokens: path" path of
154 (unTokens -> toList -> [TokenPair PairElem{} _ts]) -> d_Tokens path ts
155 _ -> D.para $ d_Tokens path ts
156 _ -> d_Tokens path ts
158 d_Tokens :: [Key] -> Tokens -> DTC
159 d_Tokens _path tok = goTokens tok
161 -- indent = Text.replicate (columnPos pos - 1) " "
163 go (TokenPlain t) = B.toMarkup t
164 go (TokenTag t) = D.ref mempty ! DA.to (attrValue t)
165 go (TokenEscape c) = B.toMarkup c
166 go (TokenLink lnk) = D.eref (B.toMarkup lnk) ! DA.to (attrValue lnk)
167 go (TokenPair PairSlash ts) = D.i $ goTokens ts
168 go (TokenPair PairBackquote ts) = D.code $ goTokens ts
169 go (TokenPair PairFrenchquote ts) = D.q $ goTokens ts
170 go (TokenPair PairHash (unTokens -> toList -> [TokenPlain ts])) =
171 D.ref mempty ! DA.to (attrValue ts)
172 go (TokenPair (PairElem name attrs) ts) =
175 Tokens s | Seq.null s ->
176 B.CustomLeaf (B.Text name) True mempty
177 _ -> B.CustomParent (B.Text name) $ goTokens ts
178 go (TokenPair p ts) = do
179 let (o,c) = pairBorders p ts
183 goTokens :: Tokens -> DTC
184 goTokens (Tokens ts) = foldMap go ts
186 d_Attrs :: Attrs -> DTC -> DTC
187 d_Attrs = flip $ foldl' d_Attr
189 d_Attr :: DTC -> (Text,Attr) -> DTC
190 d_Attr acc (_,Attr{..}) =
196 -- attr_id :: Text -> [(Text,Text)] -> [(Text,Text)]
197 -- attr_id title = ("id",title)
199 -- * Type 'Attributes'
200 type Attributes = Map Name Text
202 d_attrs :: Attributes -> DTC -> DTC
203 d_attrs = flip $ Map.foldrWithKey $ \n v ->
204 B.AddCustomAttribute (B.Text n) (B.Text v)
206 partitionAttributesChildren ::
207 Trees (Cell Key) (Cell Tokens) ->
208 (Attributes, Trees (Cell Key) (Cell Tokens))
209 partitionAttributesChildren ts = (attrs,children)
216 TreeN (unCell -> KeyEqual n _wh) a -> Map.insert n v acc
219 Write.text Write.config_text{Write.config_text_escape = False} $
220 Write.treeRackUpLeft <$> a
223 children = Seq.filter (\t ->
226 TreeN (unCell -> KeyEqual{}) _cs -> False