X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Rakka%2FWiki%2FEngine.hs;h=7c4487a3ed178e20518c821861258ba2bae59c19;hb=9681bedbfde02fa1bcda4fbbacba941378c7a57a;hp=1f24e37332b96f1f6f093d75546ed73ce385edc2;hpb=656fdb2772ab4de5cd083cbe9e7c1610cccef73b;p=Rakka.git diff --git a/Rakka/Wiki/Engine.hs b/Rakka/Wiki/Engine.hs index 1f24e37..7c4487a 100644 --- a/Rakka/Wiki/Engine.hs +++ b/Rakka/Wiki/Engine.hs @@ -7,14 +7,9 @@ module Rakka.Wiki.Engine ) where -import qualified Codec.Binary.Base64 as B64 import Control.Arrow import Control.Arrow.ArrowIO import Control.Arrow.ArrowList -import qualified Data.ByteString.Lazy as L -import Data.Encoding -import Data.Encoding.UTF8 -import Data.Generics import Data.Map (Map) import qualified Data.Map as M import Data.Maybe @@ -30,7 +25,7 @@ import Rakka.Wiki.Formatter import Rakka.Wiki.Interpreter import Text.HyperEstraier hiding (getText) import Text.ParserCombinators.Parsec -import Text.XML.HXT.Arrow.XmlArrow +import Text.XML.HXT.Arrow.XmlArrow hiding (err) import Text.XML.HXT.Arrow.XmlNodeSet import Text.XML.HXT.DOM.TypeDefs @@ -38,97 +33,16 @@ import Text.XML.HXT.DOM.TypeDefs type InterpTable = Map String Interpreter -{- - -- デフォルトでない場合のみ存在 - lastModified="2000-01-01T00:00:00"> - - - blah blah... - -- 存在しない場合もある - - -- 存在しない場合もある - - - - - - blah blah... - - - SKJaHKS8JK/DH8KS43JDK2aKKaSFLLS... - - --} -xmlizePage :: (ArrowXml a, ArrowChoice a) => a Page XmlTree -xmlizePage - = proc page - -> (eelem "/" - += ( eelem "page" - += sattr "name" (pageName page) - += sattr "type" (show $ pageType page) - += ( case pageLanguage page of - Just x -> sattr "lang" x - Nothing -> none - ) - += ( case pageFileName page of - Just x -> sattr "fileName" x - Nothing -> none - ) - += ( case pageType page of - MIMEType "text" "css" _ - -> sattr "isTheme" (yesOrNo $ pageIsTheme page) - MIMEType "text" "x-rakka" _ - -> sattr "isFeed" (yesOrNo $ pageIsFeed page) - _ - -> none - ) - += sattr "isLocked" (yesOrNo $ pageIsLocked page) - += sattr "isBoring" (yesOrNo $ pageIsBoring page) - += sattr "isBinary" (yesOrNo $ pageIsBinary page) - += sattr "revision" (show $ pageRevision page) - += sattr "lastModified" (formatW3CDateTime $ pageLastMod page) - += ( case pageSummary page of - Just s -> eelem "summary" += txt s - Nothing -> none - ) - += ( if M.null (pageOtherLang page) then - none - else - selem "otherLang" - [ eelem "link" - += sattr "lang" lang - += sattr "page" page - | (lang, page) <- M.toList (pageOtherLang page) ] - ) - += ( if pageIsBinary page then - ( eelem "binaryData" - += txt (B64.encode $ L.unpack $ pageContent page) - ) - else - ( eelem "textData" - += txt (decodeLazy UTF8 $ pageContent page) - ) - ) - ) - ) -<< () - - wikifyPage :: (ArrowXml a, ArrowChoice a) => InterpTable -> a XmlTree WikiPage wikifyPage interpTable = proc tree -> do pName <- getXPathTreesInDoc "/page/@name/text()" >>> getText -< tree pType <- getXPathTreesInDoc "/page/@type/text()" >>> getText >>> arr read -< tree - pIsBinary <- getXPathTreesInDoc "/page/@isBinary/text()" >>> getText -< tree pFileName <- maybeA (getXPathTreesInDoc "/page/fileName/text()" >>> getText) -< tree textData <- maybeA (getXPathTreesInDoc "/page/textData/text()" >>> getText) -< tree + base64Data <- maybeA (getXPathTreesInDoc "/page/binaryData/text()" >>> getText) -< tree + + let dataURI = fmap (binToURI pType) base64Data case pType of MIMEType "text" "x-rakka" _ @@ -137,13 +51,14 @@ wikifyPage interpTable Right xs -> returnA -< xs MIMEType "image" _ _ - -> returnA -< [ Paragraph [Image pName Nothing] ] - - _ -> if pIsBinary == "yes" then - returnA -< [ Paragraph [ ObjectLink { - objLinkPage = pName - , objLinkText = Just $ fromMaybe (defaultFileName pType pName) pFileName - } + -- + -> returnA -< [ Paragraph [Image (Left $ fromJust dataURI) Nothing] ] + + _ -> if isJust dataURI then + -- foo.zip + returnA -< [ Paragraph [ Anchor + [("href", show dataURI)] + [Text (fromMaybe (defaultFileName pType pName) pFileName)] ] ] else @@ -219,37 +134,59 @@ interpretCommands sto sysConf interpTable , ctxSysConf = sysConf } in - ( arrIO (everywhereM' (mkM $ interpBlockCmd ctx)) - >>> - arrIO (everywhereM' (mkM $ interpInlineCmd ctx)) - ) -<< targetWiki + arrIO2 (mapM . interpBlock) -< (ctx, targetWiki) where - interpBlockCmd :: InterpreterContext -> BlockElement -> IO BlockElement - interpBlockCmd ctx (BlockCmd cmd) = interpBlockCmd' ctx cmd - interpBlockCmd _ others = return others - - interpBlockCmd' :: InterpreterContext -> BlockCommand -> IO BlockElement - interpBlockCmd' ctx cmd + interpElem :: InterpreterContext -> Element -> IO Element + interpElem ctx (Block b) = interpBlock ctx b >>= return . Block + interpElem ctx (Inline i) = interpInline ctx i >>= return . Inline + + interpBlock :: InterpreterContext -> BlockElement -> IO BlockElement + interpBlock ctx (List lType lItems) = mapM (interpListItem ctx) lItems >>= return . List lType + interpBlock ctx (DefinitionList defs) = mapM (interpDefinition ctx) defs >>= return . DefinitionList + interpBlock ctx (Preformatted inlines) = mapM (interpInline ctx) inlines >>= return . Preformatted + interpBlock ctx (Paragraph inlines) = mapM (interpInline ctx) inlines >>= return . Paragraph + interpBlock ctx (Div attrs elems) = mapM (interpElem ctx) elems >>= return . Div attrs + interpBlock ctx (BlockCmd bcmd) = interpBlockCommand ctx bcmd + interpBlock _ x = return x + + interpInline :: InterpreterContext -> InlineElement -> IO InlineElement + interpInline ctx (Italic inlines) = mapM (interpInline ctx) inlines >>= return . Italic + interpInline ctx (Bold inlines) = mapM (interpInline ctx) inlines >>= return . Bold + interpInline ctx (Span attrs inlines) = mapM (interpInline ctx) inlines >>= return . Span attrs + interpInline ctx (Anchor attrs inlines) = mapM (interpInline ctx) inlines >>= return . Anchor attrs + interpInline ctx (InlineCmd icmd) = interpInlineCommand ctx icmd + interpInline _ x = return x + + interpListItem :: InterpreterContext -> ListItem -> IO ListItem + interpListItem = mapM . interpElem + + interpDefinition :: InterpreterContext -> Definition -> IO Definition + interpDefinition ctx (Definition term desc) + = do term' <- mapM (interpInline ctx) term + desc' <- mapM (interpInline ctx) desc + return (Definition term' desc') + + interpBlockCommand :: InterpreterContext -> BlockCommand -> IO BlockElement + interpBlockCommand ctx cmd = case M.lookup (bCmdName cmd) interpTable of Nothing -> fail ("no such interpreter: " ++ bCmdName cmd) Just interp -> bciInterpret interp ctx cmd + >>= + interpBlock ctx - - interpInlineCmd :: InterpreterContext -> InlineElement -> IO InlineElement - interpInlineCmd ctx (InlineCmd cmd) = interpInlineCmd' ctx cmd - interpInlineCmd _ others = return others - - interpInlineCmd' :: InterpreterContext -> InlineCommand -> IO InlineElement - interpInlineCmd' ctx cmd + interpInlineCommand :: InterpreterContext -> InlineCommand -> IO InlineElement + interpInlineCommand ctx cmd = case M.lookup (iCmdName cmd) interpTable of Nothing -> fail ("no such interpreter: " ++ iCmdName cmd) Just interp -> iciInterpret interp ctx cmd + >>= + interpInline ctx makeDraft :: (ArrowXml a, ArrowChoice a, ArrowIO a) => InterpTable -> a XmlTree Document @@ -304,52 +241,68 @@ makeDraft interpTable MIMEType "text" "x-rakka" _ -- wikify して興味のある部分を addText する。 -> do arrIO2 (flip setAttribute "rakka:isFeed") -< (doc, pIsFeed) - wikiPage <- wikifyPage interpTable -< tree - arrIO0 (everywhereM' (mkM (addBlockText doc)) wikiPage) -<< () - arrIO0 (everywhereM' (mkM (addInlineText doc)) wikiPage) -<< () - returnA -< () + wiki <- wikifyPage interpTable -< tree + arrIO2 (mapM_ . addBlockText) -< (doc, wiki) MIMEType _ _ _ -> returnA -< () returnA -< doc where - addBlockText :: Document -> BlockElement -> IO BlockElement - addBlockText doc b - = do case b of - Heading _ text - -> addText doc text - _ -> return () - return b - - addInlineText :: Document -> InlineElement -> IO InlineElement - addInlineText doc i - = do case i of - Text text - -> addText doc text - ObjectLink page Nothing - -> addText doc page - ObjectLink page (Just text) - -> do addHiddenText doc page - addText doc text - PageLink page fragment Nothing - -> addText doc (fromMaybe "" page ++ - fromMaybe "" fragment) - PageLink page fragment (Just text) - -> do addHiddenText doc (fromMaybe "" page ++ - fromMaybe "" fragment) - addText doc text - ExternalLink uri Nothing - -> addText doc (uriToString id uri "") - ExternalLink uri (Just text) - -> do addHiddenText doc (uriToString id uri "") - addText doc text - _ -> return () - return i - --- Perform monadic transformation in top-down order. -everywhereM' :: Monad m => GenericM m -> GenericM m -everywhereM' f x = f x >>= gmapM (everywhereM' f) + addElemText :: Document -> Element -> IO () + addElemText doc (Block b) = addBlockText doc b + addElemText doc (Inline i) = addInlineText doc i + + addBlockText :: Document -> BlockElement -> IO () + addBlockText doc (Heading _ text) = addText doc text + addBlockText _ HorizontalLine = return () + addBlockText doc (List _ items) = mapM_ (addListItemText doc) items + addBlockText doc (DefinitionList defs) = mapM_ (addDefinitionText doc) defs + addBlockText doc (Preformatted inlines) = mapM_ (addInlineText doc) inlines + addBlockText doc (Paragraph inlines) = mapM_ (addInlineText doc) inlines + addBlockText doc (Div _ elems) = mapM_ (addElemText doc) elems + addBlockText _ EmptyBlock = return () + addBlockText doc (BlockCmd bcmd) = addBlockCmdText doc bcmd + + addInlineText :: Document -> InlineElement -> IO () + addInlineText doc (Text text) = addText doc text + addInlineText doc (Italic inlines) = mapM_ (addInlineText doc) inlines + addInlineText doc (Bold inlines) = mapM_ (addInlineText doc) inlines + addInlineText doc (ObjectLink page Nothing) = addText doc page + addInlineText doc (ObjectLink page (Just text)) = addHiddenText doc page + >> addText doc text + addInlineText doc (PageLink page fragm Nothing) = addText doc (fromMaybe "" page ++ fromMaybe "" fragm) + addInlineText doc (PageLink page fragm (Just text)) = addHiddenText doc (fromMaybe "" page ++ fromMaybe "" fragm) + >> addText doc text + addInlineText doc (ExternalLink uri Nothing) = addText doc (uriToString id uri "") + addInlineText doc (ExternalLink uri (Just text)) = addHiddenText doc (uriToString id uri "") + >> addText doc text + addInlineText _ (LineBreak _) = return () + addInlineText doc (Span _ inlines) = mapM_ (addInlineText doc) inlines + addInlineText doc (Image src alt) = do case src of + Left uri -> addHiddenText doc (uriToString id uri "") + Right page -> addHiddenText doc page + case alt of + Just text -> addHiddenText doc text + Nothing -> return () + addInlineText doc (Anchor _ inlines) = mapM_ (addInlineText doc) inlines + addInlineText _ (Input _) = return () + addInlineText _ EmptyInline = return () + addInlineText doc (InlineCmd icmd) = addInlineCmdText doc icmd + + addListItemText :: Document -> ListItem -> IO () + addListItemText = mapM_ . addElemText + + addDefinitionText :: Document -> Definition -> IO () + addDefinitionText doc (Definition term desc) + = do mapM_ (addInlineText doc) term + mapM_ (addInlineText doc) desc + + addBlockCmdText :: Document -> BlockCommand -> IO () + addBlockCmdText doc (BlockCommand _ _ blocks) = mapM_ (addBlockText doc) blocks + + addInlineCmdText :: Document -> InlineCommand -> IO () + addInlineCmdText doc (InlineCommand _ _ inlines) = mapM_ (addInlineText doc) inlines wikifyParseError :: Arrow a => a ParseError WikiPage