1 module Rakka.Storage.DefaultPage
6 import qualified Codec.Binary.Base64.String as B64
8 import Control.Arrow.ArrowIO
9 import Control.Arrow.ArrowList
10 import qualified Data.ByteString.Lazy.Char8 as L8
11 import Paths_Rakka -- Cabal が用意する。
14 import System.Directory
16 import Text.XML.HXT.Arrow.ReadDocument
17 import Text.XML.HXT.Arrow.XmlArrow
18 import Text.XML.HXT.Arrow.XmlIOStateArrow
19 import Text.XML.HXT.Arrow.XmlNodeSet
20 import Text.XML.HXT.DOM.TypeDefs
21 import Text.XML.HXT.DOM.XmlKeywords
24 loadDefaultPage :: PageName -> IO (Maybe Page)
25 loadDefaultPage pageName
26 -- ./data/Foo を探した後、Cabal で defaultPages/Foo を探す。
27 = do let pagePath = encodePageName pageName
28 isInDataDir <- doesFileExist ("./data/" ++ pagePath)
30 return . Just =<< loadPageFile pageName ("./data/" ++ pagePath)
32 do fpath <- getDataFileName ("defaultPages/" ++ pagePath)
33 isInstalled <- doesFileExist fpath
35 return . Just =<< loadPageFile pageName fpath
40 loadPageFile :: PageName -> FilePath -> IO Page
41 loadPageFile name path
42 = do [page] <- runX ( setErrorMsgHandler False fail
51 loadPageFileA :: IOStateArrow s (PageName, FilePath) Page
53 = proc (name, fpath) ->
54 do tree <- readFromDocument [ (a_validate , v_0)
55 , (a_check_namespaces , v_1)
56 , (a_remove_whitespace, v_1)
58 lastMod <- arrIO (\ x -> getModificationTime x >>= toCalendarTime) -< fpath
59 parsePage -< (name, lastMod, tree)
62 parsePage :: (ArrowXml a, ArrowChoice a) => a (PageName, CalendarTime, XmlTree) Page
64 = proc (name, lastMod, tree)
65 -> do redirect <- maybeA (getXPathTreesInDoc "/page/@redirect/text()" >>> getText) -< tree
67 Nothing -> parseEntity -< (name, lastMod, tree)
68 Just dest -> returnA -< (Redirection {
71 , redirRevision = Nothing
72 , redirLastMod = lastMod
76 parseEntity :: (ArrowXml a, ArrowChoice a) => a (PageName, CalendarTime, XmlTree) Page
78 = proc (name, lastMod, tree)
79 -> do mimeType <- (getXPathTreesInDoc "/page/@type/text()" >>> getText
82 isTheme <- (maybeA (getXPathTreesInDoc "/page/@type/text()" >>> getText)
84 >>> parseYesOrNo) -< tree
85 isFeed <- (maybeA (getXPathTreesInDoc "/page/@isFeed/text()" >>> getText)
87 >>> parseYesOrNo) -< tree
88 isLocked <- (maybeA (getXPathTreesInDoc "/page/@isLocked/text()" >>> getText)
90 >>> parseYesOrNo) -< tree
91 isBoring <- (maybeA (getXPathTreesInDoc "/page/@isBoring/text()" >>> getText)
93 >>> parseYesOrNo) -< tree
95 summary <- (maybeA (getXPathTreesInDoc "/page/summary/text()"
97 >>> deleteIfEmpty)) -< tree
99 otherLang <- listA (getXPathTreesInDoc "/page/otherLang/link"
101 (getAttrValue0 "lang"
103 getAttrValue0 "page")) -< tree
105 textData <- maybeA (getXPathTreesInDoc "/page/textData" >>> getText) -< tree
106 binaryData <- maybeA (getXPathTreesInDoc "/page/binaryData" >>> getText) -< tree
108 let content = case (textData, binaryData) of
109 (Just text, _ ) -> L8.pack text
110 (_ , Just binary) -> L8.pack $ B64.decode binary
114 , pageType = mimeType
115 , pageIsTheme = isTheme
116 , pageIsFeed = isFeed
117 , pageIsLocked = isLocked
118 , pageIsBoring = isBoring
119 , pageRevision = Nothing
120 , pageLastMod = lastMod
121 , pageSummary = summary
122 , pageOtherLang = otherLang
123 , pageContent = content