+ ctx :: InterpreterContext
+ ctx = InterpreterContext {
+ ctxPageName = name
+ , ctxMainPage = fmap fst mainPageAndTree
+ , ctxMainTree = fmap snd mainPageAndTree
+ , ctxTargetTree = targetTree
+ , ctxStorage = sto
+ , ctxSysConf = sysConf
+ }
+
+ interpBlockCmd :: BlockElement -> IO BlockElement
+ interpBlockCmd (BlockCmd cmd) = interpBlockCmd' cmd
+ interpBlockCmd others = return others
+
+ interpBlockCmd' :: BlockCommand -> IO BlockElement
+ interpBlockCmd' cmd
+ = case M.lookup (bCmdName cmd) interpTable of
+ Nothing
+ -> fail ("no such interpreter: " ++ bCmdName cmd)
+
+ Just interp
+ -> bciInterpret interp ctx cmd
+
+
+ interpInlineCmd :: InlineElement -> IO InlineElement
+ interpInlineCmd (InlineCmd cmd) = interpInlineCmd' cmd
+ interpInlineCmd others = return others
+
+ interpInlineCmd' :: InlineCommand -> IO InlineElement
+ interpInlineCmd' cmd
+ = case M.lookup (iCmdName cmd) interpTable of
+ Nothing
+ -> fail ("no such interpreter: " ++ iCmdName cmd)
+
+ Just interp
+ -> iciInterpret interp ctx cmd
+
+
+makeDraft :: InterpTable -> Page -> IO Document
+makeDraft interpTable page
+ = do doc <- newDocument
+
+ setURI doc $ Just $ mkRakkaURI $ pageName page
+ setAttribute doc "@title" $ Just $ pageName page
+ setAttribute doc "@lang" $ pageLanguage page
+ setAttribute doc "@type" $ Just $ show $ pageType page
+ setAttribute doc "@mdate" $ Just $ formatW3CDateTime $ pageLastMod page
+ setAttribute doc "rakka:fileName" $ pageFileName page
+ setAttribute doc "rakka:isLocked" $ Just $ yesOrNo $ pageIsLocked page
+ setAttribute doc "rakka:isBoring" $ Just $ yesOrNo $ pageIsBoring page
+ setAttribute doc "rakka:isBinary" $ Just $ yesOrNo $ pageIsBinary page
+ setAttribute doc "rakka:revision" $ Just $ show $ pageRevision page
+ setAttribute doc "rakka:summary" $ pageSummary page
+
+ addHiddenText doc (pageName page)
+
+ case pageType page of
+ MIMEType "text" "css" _
+ -> setAttribute doc "rakka:isTheme" $ Just $ yesOrNo $ pageIsTheme page
+ MIMEType "text" "x-rakka" _
+ -> setAttribute doc "rakka:isFeed" $ Just $ yesOrNo $ pageIsFeed page
+ _ -> return ()
+
+ case pageSummary page of
+ Nothing -> return ()
+ Just s -> addHiddenText doc s
+
+ -- otherLang はリンク先ページ名を hidden text で入れる。
+ sequence_ [ addHiddenText doc x
+ | (_, x) <- M.toList (pageOtherLang page) ]
+
+ -- wikify して興味のある部分を addText する。
+ let wikiPage = wikifyPage interpTable page
+ everywhereM' (mkM (addBlockText doc)) wikiPage
+ everywhereM' (mkM (addInlineText doc)) wikiPage
+
+ return doc
+ where
+ addBlockText :: Document -> BlockElement -> IO BlockElement
+ addBlockText doc b
+ = do case b of
+ Heading _ text
+ -> addText doc text
+ _ -> return ()
+ return b
+
+ addInlineText :: Document -> InlineElement -> IO InlineElement
+ addInlineText doc i
+ = do case i of
+ Text text
+ -> addText doc text
+ ObjectLink page Nothing
+ -> addText doc page
+ ObjectLink page (Just text)
+ -> do addHiddenText doc page
+ addText doc text
+ PageLink page fragment Nothing
+ -> addText doc (fromMaybe "" page ++
+ fromMaybe "" fragment)
+ PageLink page fragment (Just text)
+ -> do addHiddenText doc (fromMaybe "" page ++
+ fromMaybe "" fragment)
+ addText doc text
+ ExternalLink uri Nothing
+ -> addText doc (uriToString id uri "")
+ ExternalLink uri (Just text)
+ -> do addHiddenText doc (uriToString id uri "")
+ addText doc text
+ _ -> return ()
+ return i
+
+
+-- Perform monadic transformation in top-down order.
+everywhereM' :: Monad m => GenericM m -> GenericM m
+everywhereM' f x = f x >>= gmapM (everywhereM' f)
+
+
+wikifyParseError :: ParseError -> WikiPage
+wikifyParseError err
+ = [Div [("class", "error")]
+ [ Block (Preformatted [Text (show err)]) ]]