X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Rakka%2FPage.hs;h=ec6ce8008209b498afb4064d9560f26e2df4d85c;hb=859d4378c2e2a1ccc8028821a37eeaa43aaa23fb;hp=c22e5206583c819facd8baab5ec437a4038d60a7;hpb=885faf1cabc3f79c90e1885268e2a9138b1ddefb;p=Rakka.git diff --git a/Rakka/Page.hs b/Rakka/Page.hs index c22e520..ec6ce80 100644 --- a/Rakka/Page.hs +++ b/Rakka/Page.hs @@ -1,26 +1,42 @@ module Rakka.Page ( PageName , Page(..) + , LanguageTag + , LanguageName + , encodePageName , decodePageName + + , pageFileName' + , mkPageURI + , mkPageFragmentURI , mkObjectURI + , mkFragmentURI + , mkAuxiliaryURI + , mkRakkaURI ) where import Data.ByteString.Base (LazyByteString) import qualified Data.ByteString.Char8 as C8 +import Data.Char import Data.Encoding import Data.Encoding.UTF8 +import Data.Map (Map) +import Data.Maybe import Network.HTTP.Lucu import Network.URI import Subversion.Types -import System.FilePath +import System.FilePath.Posix 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 { @@ -32,27 +48,35 @@ data Page | Entity { pageName :: !PageName , pageType :: !MIMEType + , pageLanguage :: !(Maybe LanguageTag) + , pageFileName :: !(Maybe String) , pageIsTheme :: !Bool -- text/css 以外では無意味 , pageIsFeed :: !Bool -- text/x-rakka 以外では無意味 , pageIsLocked :: !Bool , pageIsBoring :: !Bool , pageIsBinary :: !Bool - , pageRevision :: !(Maybe RevNum) + , pageRevision :: !RevNum , pageLastMod :: !CalendarTime , pageSummary :: !(Maybe String) - , pageOtherLang :: ![(String, PageName)] + , pageOtherLang :: !(Map LanguageTag PageName) , pageContent :: !LazyByteString } -- UTF-8 に encode してから 0x20 - 0x7E の範圍を除いて URI escape する。 encodePageName :: PageName -> FilePath -encodePageName = escapeURIString isSafe . C8.unpack . encode UTF8 +encodePageName = escapeURIString isSafeChar . C8.unpack . encode UTF8 . fixPageName where - isSafe :: Char -> Bool - isSafe c - | c >= ' ' && c <= '~' = True - | otherwise = False + fixPageName :: PageName -> PageName + fixPageName = (\ (x:xs) -> toUpper x : xs) . map (\ c -> if c == ' ' then '_' else c) + + +isSafeChar :: Char -> Bool +isSafeChar c + | c == '/' = True + | isReserved c = False + | c > ' ' && c <= '~' = True + | otherwise = False -- URI unescape して UTF-8 から decode する。 @@ -60,15 +84,63 @@ decodePageName :: FilePath -> PageName decodePageName = decode UTF8 . C8.pack . unEscapeString +encodeFragment :: String -> String +encodeFragment = escapeURIString isSafeChar . C8.unpack . encode UTF8 + + +pageFileName' :: Page -> String +pageFileName' page = fromMaybe (defaultFileName page) (pageFileName page) + + +defaultFileName :: Page -> String +defaultFileName page + = let baseName = takeFileName (pageName page) + in + case pageType page of + MIMEType "text" "x-rakka" _ -> baseName <.> "rakka" + MIMEType "text" "css" _ -> baseName <.> "css" + _ -> baseName + + mkPageURI :: URI -> PageName -> URI mkPageURI baseURI name = baseURI { - uriPath = foldl combine "/" [uriPath baseURI, encodePageName name] + uriPath = foldl () "/" [uriPath baseURI, encodePageName name ++ ".html"] + } + + +mkPageFragmentURI :: URI -> PageName -> String -> URI +mkPageFragmentURI baseURI name fragment + = baseURI { + uriPath = foldl () "/" [uriPath baseURI, encodePageName name ++ ".html"] + , uriFragment = ('#' : encodeFragment fragment) + } + + +mkFragmentURI :: String -> URI +mkFragmentURI fragment + = nullURI { + uriFragment = ('#' : encodeFragment 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, "object", encodePageName name] + uriPath = foldl () "/" ([uriPath baseURI] ++ basePath ++ [encodePageName name]) } + + +mkRakkaURI :: PageName -> URI +mkRakkaURI name = URI { + uriScheme = "rakka:" + , uriAuthority = Nothing + , uriPath = encodePageName name + , uriQuery = "" + , uriFragment = "" + }