1 module Rakka.Storage.DefaultPage
6 import qualified Codec.Binary.Base64 as B64
8 import Control.Arrow.ArrowIO
9 import Control.Arrow.ArrowList
10 import qualified Data.ByteString.Lazy as L
12 import Data.Encoding.UTF8
13 import qualified Data.Map as M
14 import Paths_Rakka -- Cabal が用意する。
17 import System.Directory
19 import Text.XML.HXT.Arrow.ReadDocument
20 import Text.XML.HXT.Arrow.XmlArrow
21 import Text.XML.HXT.Arrow.XmlIOStateArrow
22 import Text.XML.HXT.Arrow.XmlNodeSet
23 import Text.XML.HXT.DOM.TypeDefs
24 import Text.XML.HXT.DOM.XmlKeywords
27 loadDefaultPage :: PageName -> IO (Maybe Page)
28 loadDefaultPage pageName
29 -- ./defaultPages/Foo を探した後、Cabal で defaultPages/Foo を探す。
30 = do let pagePath = "defaultPages/" ++ encodePageName pageName
31 isInDataDir <- doesFileExist pagePath
33 return . Just =<< loadPageFile pageName pagePath
35 do fpath <- getDataFileName pagePath
36 isInstalled <- doesFileExist fpath
38 return . Just =<< loadPageFile pageName fpath
43 loadPageFile :: PageName -> FilePath -> IO Page
44 loadPageFile name path
45 = do [page] <- runX ( setErrorMsgHandler False fail
54 loadPageFileA :: IOStateArrow s (PageName, FilePath) Page
56 = proc (name, fpath) ->
57 do tree <- readFromDocument [ (a_validate , v_0)
58 , (a_check_namespaces , v_1)
59 , (a_remove_whitespace, v_1)
61 lastMod <- arrIO (\ x -> getModificationTime x >>= toCalendarTime) -< fpath
62 parsePage -< (name, lastMod, tree)
65 parsePage :: (ArrowXml a, ArrowChoice a) => a (PageName, CalendarTime, XmlTree) Page
67 = proc (name, lastMod, tree)
68 -> do redirect <- maybeA (getXPathTreesInDoc "/page/@redirect/text()" >>> getText) -< tree
70 Nothing -> parseEntity -< (name, lastMod, tree)
71 Just dest -> returnA -< (Redirection {
74 , redirRevision = Nothing
75 , redirLastMod = lastMod
79 parseEntity :: (ArrowXml a, ArrowChoice a) => a (PageName, CalendarTime, XmlTree) Page
81 = proc (name, lastMod, tree)
82 -> do mimeType <- (getXPathTreesInDoc "/page/@type/text()" >>> getText
85 lang <- maybeA (getXPathTreesInDoc "/page/@lang/text()" >>> getText) -< tree
87 isTheme <- (withDefault (getXPathTreesInDoc "/page/@isTheme/text()" >>> getText) "no"
88 >>> parseYesOrNo) -< tree
89 isFeed <- (withDefault (getXPathTreesInDoc "/page/@isFeed/text()" >>> getText) "no"
90 >>> parseYesOrNo) -< tree
91 isLocked <- (withDefault (getXPathTreesInDoc "/page/@isLocked/text()" >>> getText) "no"
92 >>> parseYesOrNo) -< tree
93 isBoring <- (withDefault (getXPathTreesInDoc "/page/@isBoring/text()" >>> getText) "no"
94 >>> parseYesOrNo) -< tree
96 summary <- (maybeA (getXPathTreesInDoc "/page/summary/text()"
98 >>> deleteIfEmpty)) -< tree
100 otherLang <- listA (getXPathTreesInDoc "/page/otherLang/link"
102 (getAttrValue0 "lang"
104 getAttrValue0 "page")) -< tree
106 textData <- maybeA (getXPathTreesInDoc "/page/textData/text()" >>> getText) -< tree
107 binaryData <- maybeA (getXPathTreesInDoc "/page/binaryData/text()" >>> getText) -< tree
109 let (isBinary, content)
110 = case (textData, binaryData) of
111 (Just text, _ ) -> (False, encodeLazy UTF8 text )
112 (_ , Just binary) -> (True , L.pack $ B64.decode binary)
116 , pageType = mimeType
117 , pageLanguage = lang
118 , pageIsTheme = isTheme
119 , pageIsFeed = isFeed
120 , pageIsLocked = isLocked
121 , pageIsBoring = isBoring
122 , pageIsBinary = isBinary
123 , pageRevision = Nothing
124 , pageLastMod = lastMod
125 , pageSummary = summary
126 , pageOtherLang = M.fromList otherLang
127 , pageContent = content