1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE OverloadedLists #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 {-# LANGUAGE ViewPatterns #-}
6 {-# OPTIONS_GHC -fno-warn-orphans #-}
7 module Language.TCT.Write.XML where
9 import Control.Arrow (first)
10 import Control.Monad (Monad(..), (=<<))
12 import Data.Default.Class (Default(..))
13 import Data.Eq (Eq(..))
14 import Data.Foldable (Foldable(..))
15 import Data.Function (($), (.), id)
16 import Data.Functor ((<$>), (<$))
17 import Data.Maybe (Maybe(..), maybe, fromMaybe)
18 import Data.Monoid (Monoid(..))
19 import Data.Semigroup (Semigroup(..))
20 import Data.Sequence (Seq, ViewL(..), ViewR(..), (<|))
22 import Data.TreeSeq.Strict (Tree(..))
23 import Data.Tuple (uncurry)
24 import Prelude (undefined)
25 import qualified Data.Char as Char
26 import qualified Data.List as List
27 import qualified Data.Sequence as Seq
28 import qualified Data.Text.Lazy as TL
29 import qualified Language.TCT.Write.Plain as Plain
30 import qualified System.FilePath as FP
32 import Text.Blaze.XML ()
33 import Language.TCT hiding (Parser)
34 import Language.TCT.Debug
37 xmlDocument :: Roots -> XMLs
39 -- (`S.evalState` def) $
40 case Seq.viewl trees of
41 Tree (unCell -> NodeHeader HeaderSection{}) vs :< ts ->
42 case spanlNodeToken vs of
43 (titles@(Seq.viewl -> (unTree -> cell_begin -> bp) :< _), vs') ->
47 Tree (unCell -> NodeHeader (HeaderColon "about" _)) _ -> True
49 Nothing -> Tree (Cell bp bp $ NodeHeader $ HeaderColon "about" "") mempty <| vs'
54 , inh_para = List.repeat xmlPara
62 type Xmls = S.State State XMLs
63 type Xml = S.State State XML
64 instance Semigroup Xmls where
66 instance Monoid Xmls where
67 mempty = return mempty
75 instance Default State where
85 , inh_para :: [Cell () -> XMLs -> XML]
88 instance Default Inh where
96 newtype Merge a = Merge a
98 instance Semigroup (Merge Roots) where
100 instance Monad (Merge Roots) where
108 xmlify :: Inh -> a -> XMLs
109 instance Xmlify Roots where
111 case Seq.viewl roots of
113 l@(Tree cel@(Cell bp _ep nod) ts) :< rs ->
115 NodeHeader (HeaderBar n _wh)
116 | (span, rest) <- spanlHeaderBar n roots ->
117 let (attrs,body) = partitionAttrs span in
118 (<| xmlify inh rest) $
120 xmlAttrs (attrs `defaultAttr` Cell bp bp ("type", fromMaybe "text/plain" $ mimetype n)) <>
121 xmlify inh{inh_para=[]} body
122 ----------------------
123 NodeHeader (HeaderGreat n _wh)
124 | (span, rest) <- spanlHeaderGreat n roots ->
125 let (attrs,body) = partitionAttrs span in
126 (<| xmlify inh rest) $
128 xmlAttrs (attrs `defaultAttr` Cell bp bp ("type", fromMaybe "text/plain" $ mimetype n)) <>
129 xmlify inh{inh_para=[]} (debug0 "body" body)
130 ----------------------
131 NodeHeader (HeaderColon n _wh)
132 | (span, rest) <- spanlHeaderColon n rs
134 xmlify inh $ Tree cel (ts<>span) <| rest
135 ----------------------
136 NodeHeader HeaderBrackets{}
137 | (span,rest) <- spanlBrackets roots
139 (<| xmlify inh rest) $
140 element "references" $
142 ----------------------
144 | Tree (cy@(unCell -> NodeText y)) ys :< rs' <- Seq.viewl rs ->
145 xmlify inh $ Tree (NodeText <$> (x <$ cel) <> (y <$ cy)) (ts <> ys) <| rs'
146 ----------------------
148 | Tree (Cell bb eb (NodePair PairBracket)) bracket :< rs' <- Seq.viewl rs ->
149 (<| xmlify inh rs') $
151 (toList -> [unTree -> Cell bl el (NodeToken (TokenLink lnk))]) ->
153 xmlAttrs [Cell bl el ("to",lnk)] <>
157 xmlAttrs [Cell bb eb ("to",Plain.plainDocument bracket)] <>
159 ----------------------
160 _ | (span, rest) <- spanlItems (==HeaderDash) roots
162 (<| xmlify inh rest) $
164 span >>= xmlify inh{inh_para=List.repeat xmlPara}
165 ----------------------
166 _ | (span,rest) <- spanlItems (\case HeaderDot{} -> True; _ -> False) roots
168 (<| xmlify inh rest) $
170 span >>= xmlify inh{inh_para=List.repeat xmlPara}
171 ----------------------
176 element :: XmlName -> XMLs -> XML
177 element n = tree (XmlElem n <$ cel)
179 t@(Tree (NodePair (PairElem))) :< ts ->
181 [] -> xmlify inh t <> go inh ts
182 _ | isTokenElem toks -> xmlify inh t <> go inh ts
184 (case Seq.viewl toks of
186 (unTree -> cell_begin -> bp) :< _ -> (tree0 bp (xmlify inh t) <|)) $
189 instance Xmlify Root where
190 xmlify inh (Tree cel@(Cell bp ep nod) ts) =
192 NodeGroup -> xmlify inh ts
193 ----------------------
200 xmlify inh{inh_para} ts
201 ----------------------
205 let (attrs,body) = partitionAttrs ts in
207 { inh_para = xmlTitle : List.repeat xmlPara
212 xmlAttrs (attrs `defaultAttr` Cell ep ep ("id",getAttrId body)) <>
214 HeaderColon kn _wh ->
215 let (attrs,body) = partitionAttrs ts in
216 let inh' = inh { inh_para =
218 "about" -> xmlTitle : xmlTitle : List.repeat xmlPara
219 "reference" -> xmlTitle : xmlTitle : List.repeat xmlPara
220 "serie" -> List.repeat xmlName
221 "author" -> List.repeat xmlName
222 "editor" -> List.repeat xmlName
223 "org" -> List.repeat xmlName
227 _ | kn == "about" -> xmlAbout inh' cel {-attrs-} body
228 _ | inh_figure inh && not (kn`List.elem`elems) ->
231 xmlAttrs (setAttr (Cell ep ep ("type",kn)) attrs) <>
233 [Tree0{}] -> xmlify inh'{inh_para = List.repeat xmlPara} body
234 _ -> xmlify inh'{inh_para = xmlTitle : List.repeat xmlPara} body
237 element (xmlLocalName kn) $
240 HeaderGreat n _wh -> Seq.singleton $ element (xmlLocalName n) $ xmlify inh ts
241 HeaderEqual n _wh -> Seq.singleton $ element (xmlLocalName n) $ xmlify inh ts
242 HeaderBar n _wh -> Seq.singleton $ element (xmlLocalName n) $ xmlify inh ts
243 HeaderDot _n -> Seq.singleton $ element "li" $ xmlify inh ts
244 HeaderDash -> Seq.singleton $ element "li" $ xmlify inh ts
245 HeaderDashDash -> Seq.singleton $ Tree0 $ cell $ XmlComment $
246 -- debug1_ ("TS", ts) $
247 -- debug1_ ("RS", (S.evalState (Plain.rackUpLeft ts) Nothing)) $
248 Plain.plainDocument ts
249 -- Plain.text def $ S.evalState (Plain.rackUpLeft ts) Nothing
256 (\_k' -> cell1 . unCell)) <$> ts
258 HeaderBrackets ident ->
259 let inh' = inh{inh_figure = False} in
260 let (attrs,body) = partitionAttrs ts in
262 element "reference" $
263 xmlAttrs (setAttr (Cell ep ep ("id",ident)) attrs) <>
264 xmlify inh'{inh_para = xmlTitle : xmlTitle : List.repeat xmlPara} body
268 xmlAttrs [cell ("href",TL.pack $ FP.replaceExtension p "dtc")] <>
270 ----------------------
273 PairBracket | to <- Plain.plainDocument ts
274 , TL.all (\c -> Char.isAlphaNum c || Char.isSymbol c) to ->
277 xmlAttrs [cell ("to",to)]
278 PairStar -> Seq.singleton $ element "b" $ xmlify inh ts
279 PairSlash -> Seq.singleton $ element "i" $ xmlify inh ts
280 PairBackquote -> Seq.singleton $ element "code" $ xmlify inh ts
287 (Seq.viewl -> Tree0 (Cell bl el (TokenPlain l)) :< ls) ->
289 m :> Tree0 (Cell br er (TokenPlain r)) ->
291 Tree0 (Cell bl el (TokenPlain (Text.dropWhile Char.isSpace l)))
292 <|(m|>Tree0 (Cell br er (TokenPlain (Text.dropWhileEnd Char.isSpace r))))
295 Tree0 (Cell bl el (TokenPlain (Text.dropAround Char.isSpace l))) <| ls
296 (Seq.viewr -> rs :> Tree0 (Cell br er (TokenPlain r))) ->
298 rs |> Tree0 (Cell br er (TokenPlain (Text.dropAround Char.isSpace r)))
304 xmlAttrs [cell ("to",Plain.plainDocument ts)]
305 PairElem name attrs ->
307 element (xmlLocalName name) $
308 xmlAttrs (Seq.fromList $ (\(_wh,ElemAttr{..}) ->
309 cell (xmlLocalName elemAttr_name,elemAttr_value)) <$> attrs) <>
312 let (open, close) = pairBorders pair ts in
313 Seq.singleton (Tree0 $ Cell bp bp $ XmlText open) `unionXml`
314 xmlify inh ts `unionXml`
315 Seq.singleton (Tree0 $ Cell ep ep $ XmlText close)
316 ----------------------
317 NodeText t -> Seq.singleton $ Tree0 $ cell $ XmlText t
318 ----------------------
321 TokenEscape c -> Seq.singleton $ Tree0 $ cell $ XmlText $ TL.singleton c
322 TokenText t -> Seq.singleton $ Tree0 $ cell $ XmlText t
323 TokenTag t -> Seq.singleton $ element "ref" $ xmlAttrs [cell ("to",t)]
324 TokenLink lnk -> Seq.singleton $ element "eref" $ xmlAttrs [cell ("to",lnk)]
325 ----------------------
333 element :: XmlName -> XMLs -> XML
334 element n = tree (cell $ XmlElem n)
336 -- | TODO: add more mimetypes
337 mimetype :: TL.Text -> Maybe TL.Text
338 mimetype "txt" = Just "text/plain"
339 mimetype "plain" = Just "text/plain"
340 mimetype "hs" = Just "text/x-haskell"
341 mimetype "sh" = Just "text/x-shellscript"
342 mimetype "shell" = Just "text/x-shellscript"
343 mimetype "shellscript" = Just "text/x-shellscript"
346 xmlPara :: Cell a -> XMLs -> XML
347 xmlPara c = tree (XmlElem "para" <$ c)
349 xmlTitle :: Cell a -> XMLs -> XML
350 xmlTitle c = tree (XmlElem "title" <$ c)
352 xmlName :: Cell a -> XMLs -> XML
353 -- xmlName bp (toList -> [unTree -> unCell -> XmlText t]) = Tree0 $ Cell bp bp $ XmlAttr "name" t
354 xmlName c = tree (XmlElem "name" <$ c)
359 -- Seq (Cell (XmlName, Text)) ->
361 xmlAbout inh nod body =
362 xmlify inh $ Tree nod $
363 case Seq.viewl (inh_titles inh) of
364 (unTree -> cell_begin -> bt) :< _ ->
365 ((<$> inh_titles inh) $ \title ->
366 Tree (Cell bt bt $ NodeHeader $ HeaderColon "title" "") $
367 Seq.singleton $ title)
371 xmlAttrs :: Seq (Cell (XmlName,TL.Text)) -> XMLs
372 xmlAttrs = (Tree0 . (uncurry XmlAttr <$>) <$>)
374 -- | Unify two 'XMLs', merging border 'XmlText's if any.
375 unionXml :: XMLs -> XMLs -> XMLs
377 case (Seq.viewr x, Seq.viewl y) of
378 (xs :> x0, y0 :< ys) ->
380 ( Tree0 (Cell bx ex (XmlText tx))
381 , Tree0 (Cell by ey (XmlText ty)) ) ->
383 Seq.singleton (Tree0 $ (XmlText <$>) $ Cell bx ex tx <> Cell by ey ty) `unionXml`
389 unionsXml :: Foldable f => f XMLs -> XMLs
390 unionsXml = foldl' unionXml mempty
392 partitionAttrs :: Roots -> (Seq (Cell (XmlName, TL.Text)), Roots)
393 partitionAttrs ts = (attrs,cs)
395 (as,cs) = (`Seq.partition` ts) $ \case
396 Tree (unCell -> NodeHeader (HeaderEqual (TL.null -> False) _wh)) _cs -> True
400 Tree (Cell bp ep (NodeHeader (HeaderEqual n _wh))) a ->
401 Cell bp ep (xmlLocalName n, v)
403 v = Plain.text (Plain.setStart a def{Plain.state_escape = False}) a
406 spanlHeaderBar :: Name -> Roots -> (Roots, Roots)
407 spanlHeaderBar name = first unHeaderBar . debug0 "spanBar" . spanBar
410 unHeaderBar :: Roots -> Roots
411 unHeaderBar = (=<<) $ \case
412 Tree (unCell -> NodeHeader HeaderBar{}) ts -> ts
416 Tree (unCell -> NodeHeader (HeaderBar n _)) _ | n == name -> True
417 Tree (unCell -> NodeHeader (HeaderGreat n _)) _ | n == name -> True
420 spanlHeaderGreat :: Name -> Roots -> (Roots, Roots)
421 spanlHeaderGreat name = first unHeaderGreat . debug0 "spanGreat" . spanGreat
424 unHeaderGreat :: Roots -> Roots
425 unHeaderGreat = (=<<) $ \case
426 Tree (unCell -> NodeHeader HeaderGreat{}) ts -> ts
430 Tree (unCell -> NodeHeader (HeaderGreat n _)) _ | n == name -> True
433 spanlItems :: (Header -> Bool) -> Roots -> (Roots, Roots)
434 spanlItems liHeader =
435 Seq.spanl $ \(unTree -> unCell -> nod) ->
437 NodeHeader (HeaderColon "li" _wh) -> True
438 NodeHeader hdr -> liHeader hdr
439 NodePair (PairElem "li" _as) -> True
442 spanlHeaderColon :: Name -> Roots -> (Roots, Roots)
443 spanlHeaderColon name =
445 Tree (unCell -> NodeHeader (HeaderBar n _)) _ -> n == name
446 Tree (unCell -> NodeHeader (HeaderGreat n _)) _ -> n == name
449 spanlBrackets :: Roots -> (Roots, Roots)
452 Tree (unCell -> NodeHeader HeaderBrackets{}) _ -> True
455 spanlNodeToken :: Roots -> (Roots, Roots)
458 Tree (unCell -> NodeToken{}) _ -> True
461 getAttrId :: Roots -> TL.Text
465 t :< _ -> Plain.plainDocument $ Seq.singleton t
468 Cell (XmlName, TL.Text) ->
469 Seq (Cell (XmlName, TL.Text)) ->
470 Seq (Cell (XmlName, TL.Text))
471 setAttr a@(unCell -> (k, _v)) as =
472 case Seq.findIndexL (\(unCell -> (n,_v)) -> n == k) as of
473 Just idx -> Seq.update idx a as
477 Seq (Cell (XmlName, TL.Text)) ->
478 Cell (XmlName, TL.Text) ->
479 Seq (Cell (XmlName, TL.Text))
480 defaultAttr as a@(unCell -> (k, _v)) =
481 case Seq.findIndexL (\(unCell -> (n,_v)) -> n == k) as of