]> gitweb @ CieloNegro.org - Rakka.git/blobdiff - Rakka/Wiki/Engine.hs
The experiment has succeeded
[Rakka.git] / Rakka / Wiki / Engine.hs
index 56a7adb97459857af218590f925968dc39be2a46..b6969cc4b60c3bf9aca16fe32961ce229ee68bc8 100644 (file)
 module Rakka.Wiki.Engine
     ( formatPage
+    , formatSubPage
     )
     where
 
 import           Control.Arrow
-import           Control.Arrow.ArrowTree
+import           Control.Arrow.ArrowIO
 import           Data.Encoding
 import           Data.Encoding.UTF8
+import           Data.Generics
+import qualified Data.Map as M
 import           Network.HTTP.Lucu
+import           Rakka.Environment
 import           Rakka.Page
+import           Rakka.SystemConfig
+import           Rakka.Wiki
 import           Rakka.Wiki.Parser
 import           Rakka.Wiki.Formatter
+import           Rakka.Wiki.Interpreter
 import           Text.ParserCombinators.Parsec
 import           Text.XML.HXT.Arrow.XmlArrow
 import           Text.XML.HXT.DOM.TypeDefs
 
 
-formatPage :: (ArrowXml a, ArrowChoice a) =>
-              a Page XmlTree
-formatPage
+formatPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
+              Environment
+           -> a Page XmlTree
+formatPage env
     = proc page
-    -> do tree <- case pageType page of
-                    MIMEType "text" "x-rakka" _
-                        -> formatWikiPage -< page
-          attachXHtmlNs -< tree
+    -> do BaseURI baseURI <- getSysConfA (envSysConf env) -< ()
+          wiki            <- wikifyPage env -< page
+          xs              <- interpretCommandsA env -< (pageName page, (Just (page, wiki), wiki))
+          formatWikiBlocks -< (baseURI, xs)
 
 
-formatWikiPage :: (ArrowXml a, ArrowChoice a) =>
-                  a Page XmlTree
-formatWikiPage
+formatSubPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
+                 Environment
+              -> a (PageName, (Maybe Page, Page)) XmlTree
+formatSubPage env
+    = proc (mainPageName, (mainPage, subPage))
+    -> do BaseURI baseURI <- getSysConfA (envSysConf env) -< ()
+          mainWiki        <- case mainPage of
+                               Just page
+                                   -> do wiki <- wikifyPage env -< page
+                                         returnA -< Just (page, wiki)
+                               Nothing
+                                   -> returnA -< Nothing
+          subWiki        <- wikifyPage env -< subPage
+          xs             <- interpretCommandsA env -< (mainPageName, (mainWiki, subWiki))
+          formatWikiBlocks -< (baseURI, xs)
+
+
+wikifyPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
+                 Environment
+              -> a Page WikiPage
+wikifyPage env
     = proc page
-    -> do let source = decodeLazy UTF8 (pageContent page)
-          case parse wikiPage "" source of
-            Left  err   -> formatParseError   -< err
-            Right elems -> formatWikiElements -< elems
+    -> case pageType page of
+         MIMEType "text" "x-rakka" _
+             -> do let source = decodeLazy UTF8 (pageContent page)
+                       parser = wikiPage tableToFunc
+
+                   case parse parser "" source of
+                     Left  err
+                         -> wikifyParseError -< err
+
+                     Right xs
+                         -> returnA -< xs
+    where
+      tableToFunc :: String -> Maybe CommandType
+      tableToFunc name
+          = fmap commandType (M.lookup name (envInterpTable env))
 
 
-formatParseError :: ArrowXml a => a ParseError XmlTree
-formatParseError 
-    = proc err -> (eelem "pre" += txt (show err)) -<< ()
+interpretCommandsA :: ArrowIO a =>
+                      Environment
+                   -> a (PageName, (Maybe (Page, WikiPage), WikiPage)) WikiPage
+interpretCommandsA = arrIO3 . interpretCommands
 
 
-attachXHtmlNs :: ArrowXml a => a XmlTree XmlTree
-attachXHtmlNs = processBottomUp (changeQName attach')
+interpretCommands :: Environment -> PageName -> Maybe (Page, WikiPage) -> WikiPage -> IO WikiPage
+interpretCommands _   _    _        []         = return []
+interpretCommands env name mainPageAndTree targetTree
+    = everywhereM' (mkM interpBlockCmd) targetTree
+      >>=
+      everywhereM' (mkM interpInlineCmd)
     where
-      attach' :: QName -> QName
-      attach' qn = qn {
-                     namePrefix   = "xhtml"
-                   , namespaceUri = "http://www.w3.org/1999/xhtml"
-                   }
+      ctx :: InterpreterContext
+      ctx = InterpreterContext {
+              ctxPageName   = name
+            , ctxMainPage   = fmap fst mainPageAndTree
+            , ctxMainTree   = fmap snd mainPageAndTree
+            , ctxTargetTree = targetTree
+            , ctxStorage    = envStorage env
+            , ctxSysConf    = envSysConf env
+            }
+
+      interpBlockCmd :: BlockElement -> IO BlockElement
+      interpBlockCmd (BlockCmd cmd) = interpBlockCmd' cmd
+      interpBlockCmd others         = return others
+
+      interpBlockCmd' :: BlockCommand -> IO BlockElement
+      interpBlockCmd' cmd
+          = case M.lookup (bCmdName cmd) (envInterpTable env) of
+              Nothing
+                  -> fail ("no such interpreter: " ++ bCmdName cmd)
+
+              Just interp
+                  -> bciInterpret interp ctx cmd
+
+
+      interpInlineCmd :: InlineElement -> IO InlineElement
+      interpInlineCmd (InlineCmd cmd) = interpInlineCmd' cmd
+      interpInlineCmd others          = return others
+
+      interpInlineCmd' :: InlineCommand -> IO InlineElement
+      interpInlineCmd' cmd
+          = case M.lookup (iCmdName cmd) (envInterpTable env) of
+              Nothing
+                  -> fail ("no such interpreter: " ++ iCmdName cmd)
+
+              Just interp
+                  -> iciInterpret interp ctx cmd
+
+
+-- Perform monadic transformation in top-down order.
+everywhereM' :: Monad m => GenericM m -> GenericM m
+everywhereM' f x = f x >>= gmapM (everywhereM' f)
+
+
+wikifyParseError :: ArrowXml a => a ParseError WikiPage
+wikifyParseError 
+    = proc err -> returnA -< [Div [("class", "error")]
+                              [ Preformatted [Text (show err)] ]]