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 forM_ (mangleHead title head) $ d_TreeCell []
57 forM_ body $ d_TreeCell []
59 forM_ ts $ d_TreeCell []
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_TreeCell :: [Key] -> Tree (Cell Key) (Cell Tokens) -> DTC
78 d_TreeCell path (TreeN (unCell -> key@KeySection{}) ts) =
79 case Seq.viewl children of
80 Tree0 (Cell _posTitle _ (unTokens -> toList -> [TokenPlain title])) :< body ->
81 d_attrs (mangleAttrs title attrs) $
82 case Text.splitOn "\n" title of
84 D.section ! DA.name (attrValue t0) $ do
85 let st = Text.intercalate "\n" t1
86 when (not (Text.null st)) $
87 D.name $ B.toMarkup st
90 D.section ! DA.name (attrValue title) $
92 Tree0 (Cell _posTitle _ title) :< body ->
93 d_attrs (mangleAttrs (TL.toStrict $ Write.t_Tokens title) attrs) $
95 D.name $ d_Tokens (key:path) title
99 D.section $ d_content children
101 (attrs,children) = partitionAttributesChildren ts
102 d_content cs = forM_ cs $ d_TreeCell (key:path)
103 mangleAttrs :: Text -> Attributes -> Attributes
104 mangleAttrs title = Map.insertWith (\_new old -> old) "id" title
105 d_TreeCell path (Tree0 cell) = d_CellTokens path cell
106 d_TreeCell path (TreeN cell@(unCell -> KeyColon{}) ts) =
107 let (attrs,children) = partitionAttributesChildren ts in
108 d_attrs attrs $ d_CellKey path cell children
109 d_TreeCell path (TreeN cell ts) = d_CellKey path cell ts
111 d_CellKey :: [Key] -> Cell Key -> Trees (Cell Key) (Cell Tokens) -> DTC
112 d_CellKey path (Cell _pos _posEnd key) cells = do
114 KeyColon n _wh -> d_Key n
115 KeyGreat n _wh -> d_Key n
116 KeyEqual n _wh -> d_Key n
117 KeyBar n _wh -> d_Key n
119 B.toMarkup ("- "::Text)
120 forM_ cells $ d_TreeCell (key:path)
122 KeyLower name attrs -> do
123 B.Content $ "<"<>B.toMarkup name
125 forM_ cells $ d_TreeCell path
129 d_Key name | null cells =
130 B.CustomLeaf (B.Text name) True mempty
132 B.CustomParent (B.Text name) $
133 forM_ cells $ d_TreeCell (key:path)
135 d_CellTokens :: [Key] -> Cell Tokens -> DTC
136 d_CellTokens path (Cell _pos _posEnd ts) =
137 -- case L.find (\case KeySection{} -> True; _ -> False) $ dbg "d_CellTokens: path:" path of
138 case dbg "d_CellTokens: path" path of
141 (unTokens -> toList -> [TokenPair PairElem{} _ts]) -> d_Tokens path ts
142 _ -> D.para $ d_Tokens path ts
143 _ -> d_Tokens path ts
145 d_Tokens :: [Key] -> Tokens -> DTC
146 d_Tokens _path tok = goTokens tok
148 -- indent = Text.replicate (columnPos pos - 1) " "
150 go (TokenPlain t) = B.toMarkup t
151 go (TokenTag t) = D.ref mempty ! DA.to (attrValue t)
152 go (TokenEscape c) = B.toMarkup c
153 go (TokenLink lnk) = D.eref (B.toMarkup lnk) ! DA.to (attrValue lnk)
154 go (TokenPair PairSlash ts) = D.i $ goTokens ts
155 go (TokenPair PairBackquote ts) = D.code $ goTokens ts
156 go (TokenPair PairFrenchquote ts) = D.q $ goTokens ts
157 go (TokenPair PairHash (unTokens -> toList -> [TokenPlain ts])) =
158 D.ref mempty ! DA.to (attrValue ts)
159 go (TokenPair (PairElem name attrs) ts) =
162 Tokens s | Seq.null s ->
163 B.CustomLeaf (B.Text name) True mempty
164 _ -> B.CustomParent (B.Text name) $ goTokens ts
165 go (TokenPair p ts) = do
166 let (o,c) = pairBorders p ts
170 goTokens :: Tokens -> DTC
171 goTokens (Tokens ts) = foldMap go ts
173 d_Attrs :: Attrs -> DTC -> DTC
174 d_Attrs = flip $ foldl' d_Attr
176 d_Attr :: DTC -> (Text,Attr) -> DTC
177 d_Attr acc (_,Attr{..}) =
183 -- attr_id :: Text -> [(Text,Text)] -> [(Text,Text)]
184 -- attr_id title = ("id",title)
186 -- * Type 'Attributes'
187 type Attributes = Map Name Text
189 d_attrs :: Attributes -> DTC -> DTC
190 d_attrs = flip $ Map.foldrWithKey $ \n v ->
191 B.AddCustomAttribute (B.Text n) (B.Text v)
193 partitionAttributesChildren ::
194 Trees (Cell Key) (Cell Tokens) ->
195 (Attributes, Trees (Cell Key) (Cell Tokens))
196 partitionAttributesChildren ts = (attrs,children)
203 TreeN (unCell -> KeyEqual n _wh) a -> Map.insert n v acc
206 Write.text Write.config_text{Write.config_text_escape = False} $
207 Write.treeRackUpLeft <$> a
210 children = Seq.filter (\t ->
213 TreeN (unCell -> KeyEqual{}) _cs -> False