) -<< ()
returnA -< do let lastMod = toClockTime $ pageLastMod page
-
- case pageRevision page of
- Nothing -> foundTimeStamp lastMod
- Just rev -> foundEntity (strongETag $ show rev) lastMod
+
+ -- text/x-rakka の場合は、内容が動的に生
+ -- 成されてゐる可能性があるので、ETag も
+ -- Last-Modified も返す事が出來ない。
+ case pageType page of
+ MIMEType "text" "x-rakka" _
+ -> return ()
+ _ -> case pageRevision page of
+ Nothing -> foundTimeStamp lastMod
+ Just rev -> foundEntity (strongETag $ show rev) lastMod
outputXmlPage tree entityToXHTML
, CommandType(..)
, Attribute
+ , BlockCommand(..)
, InlineCommand(..)
)
where
| DefinitionList ![Definition]
| Preformatted ![InlineElement]
| Paragraph ![InlineElement]
+ | Div ![Attribute] ![BlockElement]
+ | BlockCmd !BlockCommand
deriving (Eq, Show)
, linkText :: !(Maybe String)
}
| LineBreak ![Attribute]
+ | Span ![Attribute] ![InlineElement]
| InlineCmd !InlineCommand
deriving (Eq, Show)
type Attribute = (String, String)
+data BlockCommand
+ = BlockCommand {
+ bCmdName :: !String
+ , bCmdAttributes :: ![Attribute]
+ , bCmdContents :: ![BlockElement]
+ }
+ deriving (Eq, Show)
+
+
data InlineCommand
= InlineCommand {
iCmdName :: !String
interpretCommands env table page blocks = mapM interpBlock blocks
where
interpBlock :: BlockElement -> IO BlockElement
- interpBlock (List list) = interpList list >>= return . List
+ interpBlock (List list) = interpList list >>= return . List
interpBlock (DefinitionList defs) = mapM interpDefinition defs >>= return . DefinitionList
- interpBlock (Preformatted xs ) = mapM interpInline xs >>= return . Preformatted
- interpBlock (Paragraph xs ) = mapM interpInline xs >>= return . Paragraph
+ interpBlock (Preformatted xs) = mapM interpInline xs >>= return . Preformatted
+ interpBlock (Paragraph xs) = mapM interpInline xs >>= return . Paragraph
+ interpBlock (Div attrs xs) = mapM interpBlock xs >>= return . Div attrs
+ interpBlock (BlockCmd cmd) = interpBlockCmd cmd
interpBlock others = return others
interpList :: ListElement -> IO ListElement
desc <- mapM interpInline (defDesc def)
return $ def { defTerm = term, defDesc = desc }
+ interpBlockCmd :: BlockCommand -> IO BlockElement
+ interpBlockCmd cmd
+ = case M.lookup (bCmdName cmd) table of
+ Nothing
+ -> fail ("no such interpreter: " ++ bCmdName cmd)
+
+ Just interp
+ -> bciInterpret interp cmd page (envStorage env) (envSysConf env)
+ >>=
+ interpBlock
+
interpInline :: InlineElement -> IO InlineElement
- interpInline (Italic xs ) = mapM interpInline xs >>= return . Italic
- interpInline (Bold xs ) = mapM interpInline xs >>= return . Bold
+ interpInline (Italic xs) = mapM interpInline xs >>= return . Italic
+ interpInline (Bold xs ) = mapM interpInline xs >>= return . Bold
+ interpInline (Span attrs xs) = mapM interpInline xs >>= return . Span attrs
interpInline (InlineCmd cmd) = interpInlineCmd cmd
interpInline others = return others
Paragraph inlines
-> formatParagraph -< (baseURI, inlines)
+ Div attrs contents
+ -> ( eelem "div"
+ += ( arrL (fst . snd)
+ >>>
+ attrFromPair
+ )
+ += ( (arr fst &&& arrL (snd . snd))
+ >>>
+ formatBlock
+ )
+ ) -< (baseURI, (attrs, contents))
+
formatHeading :: ArrowXml a => a (Int, String) XmlTree
formatHeading
= proc (level, text)
- -> selem ("h" ++ show level) [txt text] -<< ()
+ -> mkelem ("h" ++ show level)
+ [ sattr "id" text ]
+ [ txt text ] -<< ()
formatListElement :: (ArrowXml a, ArrowChoice a) => a (URI, ListElement) XmlTree
+= (arrL id >>> attrFromPair)
) -< attrs
+ Span attrs contents
+ -> ( eelem "span"
+ += ( arrL (fst . snd)
+ >>>
+ attrFromPair
+ )
+ += ( (arr fst &&& arrL (snd . snd))
+ >>>
+ formatInline
+ )
+ ) -< (baseURI, (attrs, contents))
+
attrFromPair :: (ArrowXml a) => a (String, String) XmlTree
attrFromPair = proc (name, value)
, commandType -- private
, pureInlineInterp
+ , pureBlockInterp
)
where
-> SystemConfig
-> IO InlineElement
}
+ | BlockCommandInterpreter {
+ bciName :: String
+ , bciInterpret :: BlockCommand
+ -> Maybe Page
+ -> Storage
+ -> SystemConfig
+ -> IO BlockElement
+ }
commandName :: Interpreter -> String
commandName (InlineCommandInterpreter name _) = name
+commandName (BlockCommandInterpreter name _) = name
commandType :: Interpreter -> CommandType
commandType (InlineCommandInterpreter _ _) = InlineCommandType
+commandType (BlockCommandInterpreter _ _) = BlockCommandType
pureInlineInterp :: String
-> Interpreter
pureInlineInterp name f
= InlineCommandInterpreter name $ \ cmd page _ _ -> return $ f cmd page
+
+
+pureBlockInterp :: String
+ -> (BlockCommand -> Maybe Page -> BlockElement)
+ -> Interpreter
+pureBlockInterp name f
+ = BlockCommandInterpreter name $ \ cmd page _ _ -> return $ f cmd page
baseInterpreters :: [Interpreter]
-baseInterpreters = [ lineBreakInterp ]
+baseInterpreters = [ lineBreakInterp
+ , spanInterp
+ , divInterp
+ ]
lineBreakInterp :: Interpreter
lineBreakInterp = pureInlineInterp "br" interpret
where
interpret (InlineCommand _ attrs _) _ = LineBreak attrs
+
+
+spanInterp :: Interpreter
+spanInterp = pureInlineInterp "span" interpret
+ where
+ interpret (InlineCommand _ attrs contents) _ = Span attrs contents
+
+
+divInterp :: Interpreter
+divInterp = pureBlockInterp "div" interpret
+ where
+ interpret (BlockCommand _ attrs contents) _ = Div attrs contents
\ No newline at end of file
wikiPage :: CommandTypeOf -> Parser WikiPage
wikiPage cmdTypeOf
- = do xs <- many $ try (blockElement cmdTypeOf)
+ = do xs <- many (blockElement cmdTypeOf)
skipMany ( comment
<|>
(newline >> return ())
blockElement :: CommandTypeOf -> Parser BlockElement
blockElement cmdTypeOf
- = skipMany ( comment
- <|>
- (newline >> return ())
- )
- >>
- ( foldr (<|>) pzero [ heading
- , horizontalLine
- , listElement cmdTypeOf
- , definitionList cmdTypeOf
- , pdata
- , leadingSpaced cmdTypeOf
- , paragraph cmdTypeOf
- ]
- )
+ = try $ do skipMany ( comment
+ <|>
+ (newline >> return ())
+ )
+ foldr (<|>) pzero [ heading
+ , horizontalLine
+ , listElement cmdTypeOf
+ , definitionList cmdTypeOf
+ , pdata
+ , leadingSpaced cmdTypeOf
+ , paragraph cmdTypeOf
+ , blockCmd cmdTypeOf
+ ]
heading :: Parser BlockElement
<|>
try ( do newline
((oneOf ('\n':blockSymbols) >> pzero) <|> return ())
- ((blockCommand >> pzero) <|> return ())
ys <- (paragraph' <|> return [])
return (Text "\n" : ys)
- -- \n があり、その次に \n、ブロックタ
- -- グまたは blockSymbols があれば、
- -- fail して 最初の newline を讀んだ
- -- æ\89\80ã\81¾ã\81§å\8d·ã\81\8dæ\88»ã\81\99ã\80\82
+ -- \n があり、その次に \n または
+ -- blockSymbols があれば、fail して
+ -- 最初の newline を讀んだ所まで卷き
+ -- 戻す。
)
<|>
- try paragraph'
+ paragraph'
-- それ以外の場合は次の inlineElement から
-- を讀んで見る。但し一つも無くても良い。
<|>
return (x:xs)
+blockCmd :: CommandTypeOf -> Parser BlockElement
+blockCmd cmdTypeOf
+ = (try $ do (tagName, tagAttrs) <- openTag
+ case cmdTypeOf tagName of
+ Just BlockCommandType
+ -> do xs <- contents
+ closeTag tagName
+ return $ BlockCmd $ BlockCommand {
+ bCmdName = tagName
+ , bCmdAttributes = tagAttrs
+ , bCmdContents = xs
+ }
+ _ -> pzero
+ )
+ <|>
+ (try $ do (tagName, tagAttrs) <- emptyTag
+ case cmdTypeOf tagName of
+ Just BlockCommandType
+ -> return $ BlockCmd $ BlockCommand {
+ bCmdName = tagName
+ , bCmdAttributes = tagAttrs
+ , bCmdContents = []
+ }
+ _ -> pzero
+ )
+ <?>
+ "block command"
+ where
+ contents :: Parser [BlockElement]
+ contents = do x <- try $ blockElement cmdTypeOf
+ xs <- contents
+ return (x:xs)
+ <|>
+ (comment >> contents)
+ <|>
+ return []
+
+
inlineElement :: CommandTypeOf -> Parser InlineElement
inlineElement cmdTypeOf
= try $ do skipMany comment
return $ InlineCmd $ InlineCommand {
iCmdName = tagName
, iCmdAttributes = tagAttrs
- , iCmdContents = xs
+ , iCmdContents = xs
}
_ -> pzero
)
}
_ -> pzero
)
+ <?>
+ "inline command"
where
contents :: Parser [InlineElement]
contents = do x <- inlineElement cmdTypeOf
blockSymbols :: [Char]
-blockSymbols = " =-*#;"
+blockSymbols = " =-*#;<"
inlineSymbols :: [Char]
type="text/x-rakka"
isBoring="yes">
<textData>= Main Page =
-This is the main page.<br />
+This is the main page.
Hello, world!
Another paragraph...
preformatted
text.
[[Foo|Wiki markup is interpreted here.]]
+
+== Listing ==
+* foo
+** bar
+*** baz
+
+# foo
+## bar
+### baz
+
+* foo
+*# bar
+*#* baz
+*# bar
+
+== Link ==
+* [[Page]]
+* [[page]]
+* [[space in a page name]]
+* [[Page|Link to "Page"]]
+* [[Page#Heading]]
+* [[#Main Page]]
+* [[Page#Heading|Link to "Page#Heading"]]
+* [[#example]]
+
+<div id="example" />
</textData>
</page>
, Text "\n"
, Text "bar"
]) ] ]))
+
+ , (parseWiki "<div>foo</div>"
+ ~?=
+ (Right [ BlockCmd (BlockCommand "div" []
+ [ Paragraph [Text "foo"] ]) ]))
+
+ , (parseWiki "<div><!-- comment --></div>"
+ ~?=
+ (Right [ BlockCmd (BlockCommand "div" [] []) ]))
+
+ , (parseWiki "foo<div id=\"bar\"/>"
+ ~?=
+ (Right [ Paragraph [Text "foo"]
+ , BlockCmd (BlockCommand "div" [("id", "bar")] [])
+ ]))
]