X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Rakka%2FWiki%2FEngine.hs;h=72effb3ed2414817ae7a4d09e6062082a657d06d;hb=bf15724655b75bf1b8f0fdabb111c158a91680a8;hp=a4b70d79b6c3b8b4ecca2a19b72c7072f6360a16;hpb=45a315230ec341d3f7a9b80f8004148949a5e2e5;p=Rakka.git diff --git a/Rakka/Wiki/Engine.hs b/Rakka/Wiki/Engine.hs index a4b70d7..72effb3 100644 --- a/Rakka/Wiki/Engine.hs +++ b/Rakka/Wiki/Engine.hs @@ -1,19 +1,18 @@ module Rakka.Wiki.Engine ( InterpTable - , xmlizePage , makeMainXHTML , makeSubXHTML , makeDraft + , makePreviewXHTML ) where import qualified Codec.Binary.Base64 as B64 +import qualified Codec.Binary.UTF8.String as UTF8 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 qualified Data.ByteString.Lazy as Lazy import Data.Map (Map) import qualified Data.Map as M import Data.Maybe @@ -29,7 +28,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 @@ -37,95 +36,10 @@ 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 - pFileName <- maybeA (getXPathTreesInDoc "/page/fileName/text()" >>> getText) -< tree + -> do pType <- getXPathTreesInDoc "/page/@type/text()" >>> getText >>> arr read -< tree textData <- maybeA (getXPathTreesInDoc "/page/textData/text()" >>> getText) -< tree base64Data <- maybeA (getXPathTreesInDoc "/page/binaryData/text()" >>> getText) -< tree @@ -133,7 +47,7 @@ wikifyPage interpTable case pType of MIMEType "text" "x-rakka" _ - -> case parse (wikiPage cmdTypeOf) "" (fromJust textData) of + -> case parse (wikiPage $ cmdTypeOf interpTable) "" (fromJust textData) of Left err -> wikifyParseError -< err Right xs -> returnA -< xs @@ -142,20 +56,18 @@ wikifyPage interpTable -> returnA -< [ Paragraph [Image (Left $ fromJust dataURI) Nothing] ] _ -> if isJust dataURI then - -- foo.zip + -- + -- application/zip + -- returnA -< [ Paragraph [ Anchor [("href", show dataURI)] - [Text (fromMaybe (defaultFileName pType pName) pFileName)] + [Text (show pType)] ] ] else -- pre returnA -< [ Preformatted [Text $ fromJust textData] ] where - cmdTypeOf :: String -> Maybe CommandType - cmdTypeOf name - = fmap commandType (M.lookup name interpTable) - binToURI :: MIMEType -> String -> URI binToURI pType base64Data = nullURI { @@ -170,6 +82,49 @@ wikifyPage interpTable | otherwise = x : stripWhiteSpace xs +wikifyBin :: (ArrowXml a, ArrowChoice a) => InterpTable -> a (MIMEType, Lazy.ByteString) WikiPage +wikifyBin interpTable + = proc (pType, pBin) + -> do let text = UTF8.decode $ Lazy.unpack pBin + dataURI = binToURI pType pBin + + case pType of + MIMEType "text" "x-rakka" _ + -> case parse (wikiPage $ cmdTypeOf interpTable) "" text of + Left err -> wikifyParseError -< err + Right xs -> returnA -< xs + + MIMEType "image" _ _ + -- + -> returnA -< [ Paragraph [Image (Left dataURI) Nothing] ] + + + _ + -- + -- application/zip (19372 bytes) + -- + -> returnA -< [ Paragraph [ Anchor + [("href", show dataURI)] + [Text (show pType ++ + " (" ++ + show (Lazy.length pBin) ++ + " bytes)")] + ] + ] + where + binToURI :: MIMEType -> Lazy.ByteString -> URI + binToURI m b + = nullURI { + uriScheme = "data:" + , uriPath = show m ++ ";base64," ++ B64.encode (Lazy.unpack b) + } + + +cmdTypeOf :: InterpTable -> String -> Maybe CommandType +cmdTypeOf interpTable name + = fmap commandType (M.lookup name interpTable) + + makeMainXHTML :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Storage -> SystemConfig @@ -181,7 +136,7 @@ makeMainXHTML sto sysConf interpTable wiki <- wikifyPage interpTable -< tree pName <- getXPathTreesInDoc "/page/@name/text()" >>> getText -< tree interpreted <- interpretCommands sto sysConf interpTable - -< (pName, Just (tree, wiki), wiki) + -< (pName, Just tree, Just wiki, wiki) formatWikiBlocks -< (baseURI, interpreted) @@ -201,7 +156,21 @@ makeSubXHTML sto sysConf interpTable -> returnA -< Nothing subWiki <- wikifyPage interpTable -< subPage interpreted <- interpretCommands sto sysConf interpTable - -< (mainPageName, mainWiki, subWiki) + -< (mainPageName, fmap fst mainWiki, fmap snd mainWiki, subWiki) + formatWikiBlocks -< (baseURI, interpreted) + + +makePreviewXHTML :: (ArrowXml a, ArrowChoice a, ArrowIO a) => + Storage + -> SystemConfig + -> InterpTable + -> a (PageName, MIMEType, Lazy.ByteString) XmlTree +makePreviewXHTML sto sysConf interpTable + = proc (name, pageType, pageBin) + -> do BaseURI baseURI <- getSysConfA sysConf -< () + wiki <- wikifyBin interpTable -< (pageType, pageBin) + interpreted <- interpretCommands sto sysConf interpTable + -< (name, Nothing, Just wiki, wiki) formatWikiBlocks -< (baseURI, interpreted) @@ -209,13 +178,13 @@ interpretCommands :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Storage -> SystemConfig -> InterpTable - -> a (PageName, Maybe (XmlTree, WikiPage), WikiPage) WikiPage + -> a (PageName, Maybe XmlTree, Maybe WikiPage, WikiPage) WikiPage interpretCommands sto sysConf interpTable - = proc (name, mainPageAndWiki, targetWiki) + = proc (name, mainPage, mainWiki, targetWiki) -> let ctx = InterpreterContext { ctxPageName = name - , ctxMainPage = fmap fst mainPageAndWiki - , ctxMainWiki = fmap snd mainPageAndWiki + , ctxMainPage = mainPage + , ctxMainWiki = mainWiki , ctxTargetWiki = targetWiki , ctxStorage = sto , ctxSysConf = sysConf @@ -279,63 +248,92 @@ interpretCommands sto sysConf interpTable makeDraft :: (ArrowXml a, ArrowChoice a, ArrowIO a) => InterpTable -> a XmlTree Document makeDraft interpTable = proc tree -> - do doc <- arrIO0 newDocument -< () + do redir <- maybeA (getXPathTreesInDoc "/page/@redirect") -< tree + case redir of + Nothing -> makeEntityDraft -< tree + Just _ -> makeRedirectDraft -< tree + where + makeEntityDraft :: (ArrowXml a, ArrowChoice a, ArrowIO a) => a XmlTree Document + makeEntityDraft + = proc tree -> + do doc <- arrIO0 newDocument -< () - pName <- getXPathTreesInDoc "/page/@name/text()" >>> getText -< tree - pType <- getXPathTreesInDoc "/page/@type/text()" >>> getText -< tree - pLastMod <- getXPathTreesInDoc "/page/@lastModified/text()" >>> getText -< tree - pIsLocked <- getXPathTreesInDoc "/page/@isLocked/text()" >>> getText -< tree - pIsBoring <- getXPathTreesInDoc "/page/@isBoring/text()" >>> getText -< tree - pIsBinary <- getXPathTreesInDoc "/page/@isBinary/text()" >>> getText -< tree - pRevision <- getXPathTreesInDoc "/page/@revision/text()" >>> getText -< tree - pLang <- maybeA (getXPathTreesInDoc "/page/@lang/text()" >>> getText) -< tree - pFileName <- maybeA (getXPathTreesInDoc "/page/@fileName/text()" >>> getText) -< tree - pIsTheme <- maybeA (getXPathTreesInDoc "/page/@isTheme/text()" >>> getText) -< tree - pIsFeed <- maybeA (getXPathTreesInDoc "/page/@isFeed/text()" >>> getText) -< tree - pSummary <- maybeA (getXPathTreesInDoc "/page/summary/text()" >>> getText) -< tree - - arrIO2 setURI -< (doc, Just $ mkRakkaURI pName) - arrIO2 (flip setAttribute "@title" ) -< (doc, Just pName) - arrIO2 (flip setAttribute "@type" ) -< (doc, Just pType) - arrIO2 (flip setAttribute "@mdate" ) -< (doc, Just pLastMod) - arrIO2 (flip setAttribute "@lang" ) -< (doc, pLang) - arrIO2 (flip setAttribute "rakka:fileName") -< (doc, pFileName) - arrIO2 (flip setAttribute "rakka:isLocked") -< (doc, Just pIsLocked) - arrIO2 (flip setAttribute "rakka:isBoring") -< (doc, Just pIsBoring) - arrIO2 (flip setAttribute "rakka:isBinary") -< (doc, Just pIsBinary) - arrIO2 (flip setAttribute "rakka:revision") -< (doc, Just pRevision) - arrIO2 (flip setAttribute "rakka:summary" ) -< (doc, pSummary) - - arrIO2 addHiddenText -< (doc, pName) - - case pSummary of - Just s -> arrIO2 addHiddenText -< (doc, s) - Nothing -> returnA -< () - - -- otherLang はリンク先ページ名を hidden text で入れる。 - otherLangs <- listA (getXPathTreesInDoc "/page/otherLang/link/@page/text()" >>> getText) -< tree - listA ( (arr fst &&& arrL snd) - >>> - arrIO2 addHiddenText - >>> - none - ) -< (doc, otherLangs) - - case read pType of - MIMEType "text" "css" _ - -> arrIO2 (flip setAttribute "rakka:isTheme") -< (doc, pIsTheme) + pName <- getXPathTreesInDoc "/page/@name/text()" >>> getText -< tree + pType <- getXPathTreesInDoc "/page/@type/text()" >>> getText -< tree + pLastMod <- getXPathTreesInDoc "/page/@lastModified/text()" >>> getText -< tree + pIsLocked <- getXPathTreesInDoc "/page/@isLocked/text()" >>> getText -< tree + pIsBoring <- getXPathTreesInDoc "/page/@isBoring/text()" >>> getText -< tree + pIsBinary <- getXPathTreesInDoc "/page/@isBinary/text()" >>> getText -< tree + pRevision <- getXPathTreesInDoc "/page/@revision/text()" >>> getText -< tree + pLang <- maybeA (getXPathTreesInDoc "/page/@lang/text()" >>> getText) -< tree + pFileName <- maybeA (getXPathTreesInDoc "/page/@fileName/text()" >>> getText) -< tree + pIsTheme <- maybeA (getXPathTreesInDoc "/page/@isTheme/text()" >>> getText) -< tree + pIsFeed <- maybeA (getXPathTreesInDoc "/page/@isFeed/text()" >>> getText) -< tree + pSummary <- maybeA (getXPathTreesInDoc "/page/summary/text()" >>> getText) -< tree + + arrIO2 setURI -< (doc, Just $ mkRakkaURI pName) + arrIO2 (flip setAttribute "@title" ) -< (doc, Just pName) + arrIO2 (flip setAttribute "@type" ) -< (doc, Just pType) + arrIO2 (flip setAttribute "@mdate" ) -< (doc, Just pLastMod) + arrIO2 (flip setAttribute "@lang" ) -< (doc, pLang) + arrIO2 (flip setAttribute "rakka:fileName") -< (doc, pFileName) + arrIO2 (flip setAttribute "rakka:isLocked") -< (doc, Just pIsLocked) + arrIO2 (flip setAttribute "rakka:isBoring") -< (doc, Just pIsBoring) + arrIO2 (flip setAttribute "rakka:isBinary") -< (doc, Just pIsBinary) + arrIO2 (flip setAttribute "rakka:revision") -< (doc, Just pRevision) + arrIO2 (flip setAttribute "rakka:summary" ) -< (doc, pSummary) + + arrIO2 addHiddenText -< (doc, pName) + + case pSummary of + Just s -> arrIO2 addHiddenText -< (doc, s) + Nothing -> returnA -< () + + -- otherLang はリンク先ページ名を hidden text で入れる。 + otherLangs <- listA (getXPathTreesInDoc "/page/otherLang/link/@page/text()" >>> getText) -< tree + listA ( (arr fst &&& arrL snd) + >>> + arrIO2 addHiddenText + >>> + none + ) -< (doc, otherLangs) + + case read pType of + MIMEType "text" "css" _ + -> arrIO2 (flip setAttribute "rakka:isTheme") -< (doc, pIsTheme) - MIMEType "text" "x-rakka" _ - -- wikify して興味のある部分を addText する。 - -> do arrIO2 (flip setAttribute "rakka:isFeed") -< (doc, pIsFeed) - wikiPage <- wikifyPage interpTable -< tree - arrIO2 (mapM_ . addBlockText) -< (doc, wikiPage) + MIMEType "text" "x-rakka" _ + -- wikify して興味のある部分を addText する。 + -> do arrIO2 (flip setAttribute "rakka:isFeed") -< (doc, pIsFeed) + wiki <- wikifyPage interpTable -< tree + arrIO2 (mapM_ . addBlockText) -< (doc, wiki) - MIMEType _ _ _ - -> returnA -< () + MIMEType _ _ _ + -> returnA -< () + + returnA -< doc + + makeRedirectDraft :: (ArrowXml a, ArrowChoice a, ArrowIO a) => a XmlTree Document + makeRedirectDraft + = proc tree -> + do doc <- arrIO0 newDocument -< () + + pName <- getXPathTreesInDoc "/page/@name/text()" >>> getText -< tree + pRedir <- getXPathTreesInDoc "/page/@redirect/text()" >>> getText -< tree + pRevision <- getXPathTreesInDoc "/page/@revision/text()" >>> getText -< tree + pLastMod <- getXPathTreesInDoc "/page/@lastModified/text()" >>> getText -< tree + + arrIO2 setURI -< (doc, Just $ mkRakkaURI pName) + arrIO2 (flip setAttribute "@title" ) -< (doc, Just pName) + arrIO2 (flip setAttribute "@type" ) -< (doc, Just "application/x-rakka-redirection") + arrIO2 (flip setAttribute "@mdate" ) -< (doc, Just pLastMod) + arrIO2 (flip setAttribute "rakka:revision") -< (doc, Just pRevision) + + -- リダイレクト先ページ名はテキストとして入れる + arrIO2 addText -< (doc, pRedir) + + returnA -< doc - returnA -< doc - where addElemText :: Document -> Element -> IO () addElemText doc (Block b) = addBlockText doc b addElemText doc (Inline i) = addInlineText doc i @@ -372,7 +370,7 @@ makeDraft interpTable case alt of Just text -> addHiddenText doc text Nothing -> return () - addInlineText doc (Anchor attrs inlines) = mapM_ (addInlineText doc) inlines + addInlineText doc (Anchor _ inlines) = mapM_ (addInlineText doc) inlines addInlineText _ (Input _) = return () addInlineText _ EmptyInline = return () addInlineText doc (InlineCmd icmd) = addInlineCmdText doc icmd