module Rakka.Page
( PageName
, Page(..)
+ , LanguageTag
+ , LanguageName
+
, encodePageName
, decodePageName
, mkPageURI
+ , mkPageFragmentURI
+ , mkObjectURI
+ , mkAuxiliaryURI
+ , mkRakkaURI
)
where
import qualified Data.ByteString.Char8 as C8
import Data.Encoding
import Data.Encoding.UTF8
+import Data.Map (Map)
import Network.HTTP.Lucu
import Network.URI
import Subversion.Types
+import System.FilePath
import System.Time
type PageName = String
+type LanguageTag = String -- See RFC 3066: http://www.ietf.org/rfc/rfc3066.txt
+type LanguageName = String -- i.e. "日本語"
+
data Page
= Redirection {
- redirName :: PageName
- , redirDest :: PageName
- , redirRevision :: Maybe RevNum
- , redirLastMod :: CalendarTime
+ redirName :: !PageName
+ , redirDest :: !PageName
+ , redirRevision :: !(Maybe RevNum)
+ , redirLastMod :: !CalendarTime
}
| Entity {
- pageName :: PageName
- , pageType :: MIMEType
- , pageIsTheme :: Bool -- text/css 以外では無意味
- , pageIsFeed :: Bool -- text/x-rakka 以外では無意味
- , pageIsLocked :: Bool
- , pageIsBoring :: Bool
- , pageRevision :: Maybe RevNum
- , pageLastMod :: CalendarTime
- , pageSummary :: Maybe String
- , pageOtherLang :: [(String, PageName)]
- , pageContent :: LazyByteString
+ pageName :: !PageName
+ , pageType :: !MIMEType
+ , pageLanguage :: !(Maybe LanguageTag)
+ , pageIsTheme :: !Bool -- text/css 以外では無意味
+ , pageIsFeed :: !Bool -- text/x-rakka 以外では無意味
+ , pageIsLocked :: !Bool
+ , pageIsBoring :: !Bool
+ , pageIsBinary :: !Bool
+ , pageRevision :: !RevNum
+ , pageLastMod :: !CalendarTime
+ , pageSummary :: !(Maybe String)
+ , pageOtherLang :: !(Map LanguageTag PageName)
+ , pageContent :: !LazyByteString
}
-- UTF-8 に encode してから 0x20 - 0x7E の範圍を除いて URI escape する。
encodePageName :: PageName -> FilePath
-encodePageName = escapeURIString shouldEscape . C8.unpack . encode UTF8
+encodePageName = escapeURIString isSafe . C8.unpack . encode UTF8
where
- shouldEscape :: Char -> Bool
- shouldEscape c
- | c >= ' ' && c <= '~' = False
- | otherwise = True
+ isSafe :: Char -> Bool
+ isSafe c
+ | c == '/' = True
+ | isReserved c = False
+ | c >= ' ' && c <= '~' = True
+ | otherwise = False
-- URI unescape して UTF-8 から decode する。
mkPageURI :: URI -> PageName -> URI
mkPageURI baseURI name
- | uriPath baseURI == "" = baseURI { uriPath = "/" ++ encoded }
- | uriPath baseURI == "/" = baseURI { uriPath = "/" ++ encoded }
- | last (uriPath baseURI) == '/' = baseURI { uriPath = uriPath baseURI ++ encoded }
- | otherwise = baseURI { uriPath = uriPath baseURI ++ "/" ++ encoded }
- where
- encoded = encodePageName name
+ = baseURI {
+ uriPath = foldl combine "/" [uriPath baseURI, encodePageName name ++ ".html"]
+ }
+
+
+mkPageFragmentURI :: URI -> PageName -> String -> URI
+mkPageFragmentURI baseURI name fragment
+ = baseURI {
+ uriPath = foldl combine "/" [uriPath baseURI, encodePageName name ++ ".html"]
+ , uriFragment = ('#':fragment)
+ }
+
+
+mkObjectURI :: URI -> PageName -> URI
+mkObjectURI baseURI name
+ = mkAuxiliaryURI baseURI ["object"] name
+
+
+mkAuxiliaryURI :: URI -> [String] -> PageName -> URI
+mkAuxiliaryURI baseURI basePath name
+ = baseURI {
+ uriPath = foldl combine "/" ([uriPath baseURI] ++ basePath ++ [encodePageName name])
+ }
+
+
+mkRakkaURI :: PageName -> URI
+mkRakkaURI name = URI {
+ uriScheme = "rakka:"
+ , uriAuthority = Nothing
+ , uriPath = encodePageName name
+ , uriQuery = ""
+ , uriFragment = ""
+ }