{-
<page site="CieloNegro"
+ baseURI="http://example.org"
name="Foo/Bar"
type="text/x-rakka"
lang="ja" -- 存在しない場合もある
<body>
blah blah...
</body>
+
+ <source><!-- isBinary="no" の場合にのみ存在 -->
+ blah blah...
+ </source>
</page>
-}
handleGetEntity :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a Page (Resource ())
{-
<pageNotFound site="CieloNegro"
- styleSheet="http://example.org/object/StyleSheet/Default"
+ baseURI="http://example.org"
name="Foo/Bar">
+ <styleSheets>
+ <styleSheet src="http://example.org/object/StyleSheet/Default" />
+ </styleSheets>
+
+ <scripts>
+ <script src="http://example.org/js" />
+ </scripts>
+
<pageTitle>
blah blah...
</pageTitle>
import Control.Arrow.ArrowIO
import Control.Concurrent.STM
+import Control.Monad
import Control.Monad.Trans
import qualified Data.ByteString.Char8 as C8
import Data.Dynamic
instance SysConfValue BaseURI where
confPath _ = "baseURI"
serialize (BaseURI uri) = uriToString id uri ""
- deserialize uri = fmap BaseURI (parseURI uri)
+ deserialize uri = fmap BaseURI
+ $ do parsed <- parseURI uri
+ when (uriPath parsed == "" ) (fail undefined)
+ when (last (uriPath parsed) /= '/') (fail undefined)
+ when (uriQuery parsed /= "" ) (fail undefined)
+ when (uriFragment parsed /= "" ) (fail undefined)
+ return parsed
defaultValue sc
= let conf = scLucuConf sc
host = C8.unpack $ LC.cnfServerHost conf
, imgAlt :: !(Maybe String)
}
| Anchor ![Attribute] ![InlineElement]
+ | Input ![Attribute]
| EmptyInline
| InlineCmd !InlineCommand
deriving (Eq, Show, Typeable, Data)
tree <- ( eelem "/"
+= ( eelem "page"
+= sattr "site" siteName
+ += sattr "baseURI" (uriToString id baseURI "")
+= sattr "name" (pageName page)
+= sattr "type" (show $ pageType page)
+= ( case pageLanguage page of
+= ( eelem "body"
+= (constA page >>> formatMainPage sto sysConf interpTable)
)
+ += (constA page >>> formatSource)
>>>
uniqueNamespacesFromDeclAndQNames
)
returnA -< tree
+formatSource :: (ArrowXml a, ArrowChoice a) => a Page XmlTree
+formatSource = proc page
+ -> if pageIsBinary page then
+ none -< ()
+ else
+ let source = decodeLazy UTF8 (pageContent page)
+ in
+ ( eelem "source" += mkText ) -< source
+
+
formatUnexistentPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
Storage
-> SystemConfig
tree <- ( eelem "/"
+= ( eelem "pageNotFound"
- += sattr "site" siteName
- += sattr "styleSheet" (uriToString id (mkObjectURI baseURI cssName) "")
- += sattr "name" name
+ += sattr "site" siteName
+ += sattr "baseURI" (uriToString id baseURI "")
+ += sattr "name" name
+
+ += ( eelem "styleSheets"
+ += ( eelem "styleSheet"
+ += sattr "src" (uriToString id (mkObjectURI baseURI cssName) "")
+ )
+ )
+
+ += ( eelem "scripts"
+ += ( eelem "script"
+ += sattr "src" (uriToString id (baseURI { uriPath = "/js" }) "")
+ )
+ )
+= ( eelem "pageTitle"
+= ( (constA name &&& constA Nothing &&& constA pageTitle)
Anchor attrs contents
-> formatElem "a" -< (baseURI, attrs, contents)
+ Input attrs
+ -> formatElem "input" -< (baseURI, attrs, [])
+
EmptyInline
-> none -< ()
where
import Data.Map (Map)
import qualified Data.Map as M
import Data.Maybe
+import Network.URI
import Rakka.Page
import Rakka.SystemConfig
import Rakka.Wiki
, divInterp
, pageNameInterp
, otherLangsInterp
+ , editPageInterp
]
mkLangLink :: (LanguageName, PageName) -> ListItem
mkLangLink (langName, pageName)
- = [Inline (PageLink (Just pageName) Nothing (Just langName))]
\ No newline at end of file
+ = [Inline (PageLink (Just pageName) Nothing (Just langName))]
+
+
+-- <input type="button"
+-- value="Edit"
+-- onclick="Rakka.editPage(\"http://example.org/\", \"Foo\")"
+-- class="editButton" />
+editPageInterp :: Interpreter
+editPageInterp
+ = InlineCommandInterpreter {
+ iciName = "editPage"
+ , iciInterpret
+ = \ ctx (InlineCommand _ args _) ->
+ do BaseURI baseURI <- getSysConf (ctxSysConf ctx)
+
+ let pageName = fromMaybe (ctxPageName ctx) (lookup "page" args)
+ label = fromMaybe "Edit this page" (lookup "label" args)
+ uri = uriToString id baseURI ""
+ attrs = [ ("type" , "button")
+ , ("value" , label)
+ , ("onclick", "Rakka.editPage(\"" ++ uri ++ "\", \"" ++ pageName ++ "\")")
+ , ("class" , "editButton")
+ ]
+
+ return (Input attrs)
+ }
, horizontalLine
, listElement cmdTypeOf
, definitionList cmdTypeOf
- , pdata
+ , verbatim
, leadingSpaced cmdTypeOf
, paragraph cmdTypeOf
, blockCmd cmdTypeOf
"description of term"
-pdata :: Parser BlockElement
-pdata = do try (string "<![PDATA[")
- many (oneOf " \t\n")
- x <- pdata'
- return (Preformatted [Text x])
+verbatim :: Parser BlockElement
+verbatim = do try (string "<!verbatim[")
+ many (oneOf " \t\n")
+ x <- verbatim'
+ return (Preformatted [Text x])
where
- pdata' :: Parser String
- pdata' = do try (many (oneOf " \t\n") >> string "]]>")
- return []
- <|>
- do x <- anyChar
- xs <- pdata'
- return (x:xs)
+ verbatim' :: Parser String
+ verbatim' = do try (many (oneOf " \t\n") >> string "]>")
+ return []
+ <|>
+ do x <- anyChar
+ xs <- verbatim'
+ return (x:xs)
leadingSpaced :: CommandTypeOf -> Parser BlockElement
inlineElement :: CommandTypeOf -> Parser InlineElement
inlineElement cmdTypeOf
= try $ do skipMany comment
- foldr (<|>) pzero [ cdata
+ foldr (<|>) pzero [ nowiki
, apostrophes cmdTypeOf
, text
, objLink
]
-cdata :: Parser InlineElement
-cdata = try (string "<![CDATA[") >> cdata' >>= return . Text
+nowiki :: Parser InlineElement
+nowiki = try (string "<!nowiki[") >> nowiki' >>= return . Text
where
- cdata' :: Parser String
- cdata' = do try (string "]]>")
- return []
- <|>
- do x <- anyChar
- xs <- cdata'
- return (x:xs)
+ nowiki' :: Parser String
+ nowiki' = do try (string "]>")
+ return []
+ <|>
+ do x <- anyChar
+ xs <- nowiki'
+ return (x:xs)
text :: Parser InlineElement
over ones'''' that are included as part of the text.)
]]>
-== CDATA section ==
-<![CDATA[
+== nowiki section ==
+<!nowiki[
[[Wiki]] markup is ignored here
but the text is reformatted.
-]]>
+]>
-== PDATA section ==
-<![PDATA[
+== verbatim section ==
+<!verbatim[
[[Wiki]] markup is ignored here
and reformatting is also disabled.
-]]>
+]>
<![CDATA[
== Leading spaces ==
isBoring="yes">
<textData><![CDATA[
= Control =
+* <editPage />
= In other languages =
<inOtherLanguages />
color: #008800;
text-decoration: none;
}
+a:hover {
+ text-decoration: underline;
+}
+
+input[type="button"] {
+ background-color: #eeeeee;
+
+ border-color: #fafafa #dddddd #dddddd #fafafa;
+ border-width: 2px;
+ border-style: solid;
+}
+input[type="button"]:active {
+ background-color: white;
+ border-color: #dddddd #fafafa #fafafa #dddddd;
+}
.header, .footer, .sideBar {
background-color: #eeeeee;
SOURCES = \
jquery-1.2.1.js \
+ jquery-dom.js \
+ base.js \
+ editPage.js \
$(NULL)
rm tmp.js tmp.packed.js
+jquery-dom.js:
+ @echo "Warning: jquery-dom.js is missing. Trying to download it..."
+ wget http://mg.to/files/jquery-dom.js
+
+
jquery-%.js:
@echo "Error: $@ has to be placed on this directory."
@echo " See http://jquery.com/"
--- /dev/null
+/* Namespace Rakka */
+var Rakka = {};
--- /dev/null
+Rakka.editPage = function (baseURI, pageName) {
+ var $body = $("div.body");
+
+ $body.text("Loading... please wait.");
+
+ // XML 版のページを取得する。
+ $.ajax({
+ url : baseURI + pageName + ".xml",
+ success: function (pageXml) {
+ var $page = $(pageXml).find("page");
+ var oldRevision = $page.attr("revision");
+ var defaultAction = $page.attr("isBinary") == "yes" ? "uploadFile"
+ : $page.attr("type") == "text/x-rakka" ? "editAsWiki"
+ : $page.attr("type") == "text/css" ? "editAsCSS"
+ : "unknown"
+ ;
+ var source = $page.find("source").text();
+ Rakka.displayPageEditor($body, pageName, oldRevision, defaultAction, source);
+ },
+ error : function (req) {
+ if (req.status == 404) {
+ Rakka.displayPageEditor($body, pageName, null, "editAsWiki");
+ }
+ else {
+ $body.text("Error: " + req.status + " " + req.statusText);
+ }
+ }
+ });
+};
+
+Rakka.displayPageEditor = function ($place, pageName, oldRevision, defaultAction, source) {
+ $place.empty();
+
+ var fldPageName
+ = $.INPUT({type : "text", value: pageName});
+
+ var btnEditAsWiki
+ = $.INPUT({type : "radio",
+ name : "action",
+ checked: (defaultAction == "editAsWiki" ? "checked" : "")});
+
+ var btnEditAsCSS
+ = $.INPUT({type : "radio",
+ name : "action",
+ checked: (defaultAction == "editAsCSS" ? "checked" : "")});
+
+ var btnUploadFile
+ = $.INPUT({type : "radio",
+ name : "action",
+ checked: (defaultAction == "uploadFile" ? "checked" : "")});
+
+ var btnDelete
+ = $.INPUT({type : "radio",
+ name : "action",
+ checked: ""});
+
+ var pageEditor
+ = $.TABLE({className: "pageEditor"},
+ $.TBODY({},
+ $.TR({},
+ $.TH({}, "Name of the page"),
+ $.TD({}, fldPageName)
+ ),
+ $.TR({},
+ $.TH({}, "Action"),
+ $.TD({},
+ $.UL({},
+ $.LI({},
+ $.LABEL({},
+ btnEditAsWiki,
+ "Edit as a Wiki page"
+ )
+ ),
+ $.LI({},
+ $.LABEL({},
+ btnEditAsCSS,
+ "Edit as a style sheet"
+ )
+ ),
+ $.LI({},
+ $.LABEL({},
+ btnUploadFile,
+ "Upload a file"
+ )
+ ),
+ (oldRevision != "" && oldRevision != 0
+ ? $.LI({},
+ $.LABEL({},
+ btnDelete,
+ "Delete this page"
+ )
+ )
+ : [])
+ )
+ )
+ )
+ )
+ );
+
+ $place.append(pageEditor);
+};