git.iko.soy/typeable/pandoc
on master help sign in
MediaWiki reader: Implemented basic internal links.
fc2f7a4John MacFarlane
src/Text/Pandoc/Readers/MediaWiki.hs+62−41
@@ -110,16 +110,27 @@ htmlComment :: MWParser ()
110htmlComment = () <$ htmlTag isCommentTag
110htmlComment = () <$ htmlTag isCommentTag
111
111
112inlinesInTags :: String -> MWParser Inlines
112inlinesInTags :: String -> MWParser Inlines
113+inlinesInTags tag = try $ do
114+ (_,raw) <- htmlTag (~== TagOpen tag [])
115+ if '/' `elem` raw -- self-closing tag
116+ then return mempty
113−inlinesInTags tag = trimInlines . mconcat <$> try
117+ else trimInlines . mconcat <$>
114− (manyTill inline (htmlTag (~== TagClose tag)))
118+ manyTill inline (htmlTag (~== TagClose tag))
115
119
116blocksInTags :: String -> MWParser Blocks
120blocksInTags :: String -> MWParser Blocks
117−blocksInTags tag = mconcat <$> try
121+blocksInTags tag = try $ do
122+ (_,raw) <- htmlTag (~== TagOpen tag [])
123+ if '/' `elem` raw -- self-closing tag
124+ then return mempty
118− (manyTill block (htmlTag (~== TagClose tag)))
125+ else mconcat <$> manyTill block (htmlTag (~== TagClose tag))
119
126
120charsInTags :: String -> MWParser [Char]
127charsInTags :: String -> MWParser [Char]
128+charsInTags tag = try $ do
129+ (_,raw) <- htmlTag (~== TagOpen tag [])
130+ if '/' `elem` raw -- self-closing tag
131+ then return ""
121−charsInTags tag = innerText . parseTags <$> try
132+ else innerText . parseTags <$>
122− (manyTill anyChar (htmlTag (~== TagClose tag)))
133+ manyTill anyChar (htmlTag (~== TagClose tag))
123
134
124--
135--
125-- main parser
136-- main parser
@@ -146,8 +157,6 @@ block = mempty <$ skipMany1 blankline
146 <|> mempty <$ try (spaces *> htmlComment)
157 <|> mempty <$ try (spaces *> htmlComment)
147 <|> preformatted
158 <|> preformatted
148 <|> blockTag
159 <|> blockTag
149− <|> pTag
150− <|> blockHtml
151 <|> template
160 <|> template
152 <|> para
161 <|> para
153
162
@@ -164,16 +173,17 @@ template = B.rawBlock "mediawiki" <$> doublebrackets
164
173
165blockTag :: MWParser Blocks
174blockTag :: MWParser Blocks
166blockTag = do
175blockTag = do
167− (TagOpen t attrs, raw) <- htmlTag (\x -> isBlockTag' x && isTagOpen x)
176+ (tag, _) <- lookAhead $ htmlTag isBlockTag'
168− case t of
177+ case tag of
169− "blockquote" -> B.blockQuote <$> blocksInTags "blockquote"
178+ TagOpen "blockquote" _ -> B.blockQuote <$> blocksInTags "blockquote"
170− "pre" -> B.codeBlock . trimCode <$> charsInTags "pre"
179+ TagOpen "pre" _ -> B.codeBlock . trimCode <$> charsInTags "pre"
171− "syntaxhighlight" -> syntaxhighlight attrs
180+ TagOpen "syntaxhighlight" attrs -> syntaxhighlight attrs
172− "haskell" -> B.codeBlockWith ("",["haskell"],[]) . trimCode <$>
181+ TagOpen "haskell" _ -> B.codeBlockWith ("",["haskell"],[]) . trimCode <$>
173− charsInTags "haskell"
182+ charsInTags "haskell"
174− "gallery" -> blocksInTags "gallery"
183+ TagOpen "gallery" _ -> blocksInTags "gallery"
175− "p" -> return mempty
184+ TagOpen "p" _ -> mempty <$ htmlTag (~== tag)
185+ TagClose "p" -> mempty <$ htmlTag (~== tag)
176− _ -> return $ B.rawBlock "html" raw
186+ _ -> B.rawBlock "html" . snd <$> htmlTag (~== tag)
177
187
178trimCode :: String -> String
188trimCode :: String -> String
179trimCode ('\n':xs) = stripTrailingNewlines xs
189trimCode ('\n':xs) = stripTrailingNewlines xs
@@ -189,13 +199,6 @@ syntaxhighlight attrs = try $ do
189 contents <- charsInTags "syntaxhighlight"
199 contents <- charsInTags "syntaxhighlight"
190 return $ B.codeBlockWith ("",classes,kvs) $ trimCode contents
200 return $ B.codeBlockWith ("",classes,kvs) $ trimCode contents
191
201
192−-- We can just skip pTags, as contents will be treated as paragraphs
193−pTag :: MWParser Blocks
194−pTag = mempty <$ (htmlTag (\t -> t ~== TagOpen "p" [] || t ~== TagClose "p"))
195−
196−blockHtml :: MWParser Blocks
197−blockHtml = (B.rawBlock "html" . snd <$> htmlTag isBlockTag)
198−
199hrule :: MWParser Blocks
202hrule :: MWParser Blocks
200hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline)
203hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline)
201
204
@@ -271,7 +274,7 @@ anyListStart = char '*'
271 <|> char ';'
274 <|> char ';'
272
275
273li :: MWParser Blocks
276li :: MWParser Blocks
274−li = htmlTag (~== TagOpen "li" []) *>
277+li = lookAhead (htmlTag (~== TagOpen "li" [])) *>
275 (firstParaToPlain <$> blocksInTags "li") <* spaces
278 (firstParaToPlain <$> blocksInTags "li") <* spaces
276
279
277listItem :: Char -> MWParser Blocks
280listItem :: Char -> MWParser Blocks
@@ -317,6 +320,7 @@ inline = whitespace
317 <|> str
320 <|> str
318 <|> strong
321 <|> strong
319 <|> emph
322 <|> emph
323+ <|> internalLink
320 <|> externalLink
324 <|> externalLink
321 <|> inlineTag
325 <|> inlineTag
322 <|> B.singleton <$> charRef
326 <|> B.singleton <$> charRef
@@ -336,21 +340,25 @@ variable = B.rawInline "mediawiki" <$> triplebrackets
336
340
337inlineTag :: MWParser Inlines
341inlineTag :: MWParser Inlines
338inlineTag = do
342inlineTag = do
339− (TagOpen t _, raw) <- htmlTag (\x -> isInlineTag x && isTagOpen x)
343+ (tag, _) <- lookAhead $ htmlTag isInlineTag
340− case t of
344+ case tag of
345+ TagOpen "nowiki" _ -> try $ do
346+ (_,raw) <- htmlTag (~== tag)
347+ if '/' `elem` raw
348+ then return mempty
341− "nowiki" -> B.text . fromEntities <$> try
349+ else B.text . fromEntities <$>
342− (manyTill anyChar (htmlTag (~== TagClose "nowiki")))
350+ manyTill anyChar (htmlTag (~== TagClose "nowiki"))
343− "br" -> B.linebreak <$
351+ TagOpen "br" _ -> B.linebreak <$ (htmlTag (~== TagOpen "br" []) -- will get /> too
344− (optional (htmlTag (~== TagClose "br")) *> optional blankline)
352+ *> optional blankline)
345− "strike" -> B.strikeout <$> inlinesInTags "strike"
353+ TagOpen "strike" _ -> B.strikeout <$> inlinesInTags "strike"
346− "del" -> B.strikeout <$> inlinesInTags "del"
354+ TagOpen "del" _ -> B.strikeout <$> inlinesInTags "del"
347− "sub" -> B.subscript <$> inlinesInTags "sub"
355+ TagOpen "sub" _ -> B.subscript <$> inlinesInTags "sub"
348− "sup" -> B.superscript <$> inlinesInTags "sup"
356+ TagOpen "sup" _ -> B.superscript <$> inlinesInTags "sup"
349− "math" -> B.math <$> charsInTags "math"
357+ TagOpen "math" _ -> B.math <$> charsInTags "math"
350− "code" -> B.code <$> charsInTags "code"
358+ TagOpen "code" _ -> B.code <$> charsInTags "code"
351− "tt" -> B.code <$> charsInTags "tt"
359+ TagOpen "tt" _ -> B.code <$> charsInTags "tt"
352− "hask" -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask"
360+ TagOpen "hask" _ -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask"
353− _ -> return $ B.rawInline "html" raw
361+ _ -> B.rawInline "html" . snd <$> htmlTag (~== tag)
354
362
355special :: MWParser Inlines
363special :: MWParser Inlines
356special = B.str <$> count 1 (notFollowedBy' (htmlTag isBlockTag') *>
364special = B.str <$> count 1 (notFollowedBy' (htmlTag isBlockTag') *>
@@ -368,6 +376,19 @@ endline = () <$ try (newline <*
368 notFollowedBy' hrule <*
376 notFollowedBy' hrule <*
369 notFollowedBy anyListStart)
377 notFollowedBy anyListStart)
370
378
379+internalLink :: MWParser Inlines
380+internalLink = try $ do
381+ string "[["
382+ pagename <- unwords . words <$> many (noneOf "|]")
383+ label <- option (B.text pagename) $ char '|' *>
384+ ( (mconcat <$> many1 (notFollowedBy (char ']') *> inline))
385+ -- the "pipe trick"
386+ -- [[Help:Contents|] -> "Contents"
387+ <|> (return $ B.text $ drop 1 $ dropWhile (/=':') pagename) )
388+ string "]]"
389+ linktrail <- B.text <$> many (char '\'' <|> letter)
390+ return $ B.link pagename "wikilink" (label <> linktrail)
391+
371externalLink :: MWParser Inlines
392externalLink :: MWParser Inlines
372externalLink = try $ do
393externalLink = try $ do
373 char '['
394 char '['
tests/mediawiki-reader.native+6
@@ -74,6 +74,12 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
74,Para [Link [Str "http://johnmacfarlane.net/pandoc/"] ("http://johnmacfarlane.net/pandoc/","")]
74,Para [Link [Str "http://johnmacfarlane.net/pandoc/"] ("http://johnmacfarlane.net/pandoc/","")]
75,Para [Link [Str "1"] ("http://google.com",""),Space,Link [Str "2"] ("http://yahoo.com","")]
75,Para [Link [Str "1"] ("http://google.com",""),Space,Link [Str "2"] ("http://yahoo.com","")]
76,Para [Link [Str "email",Space,Str "me"] ("mailto:info@example.org","")]
76,Para [Link [Str "email",Space,Str "me"] ("mailto:info@example.org","")]
77+,Header 2 [Str "internal",Space,Str "links"]
78+,Para [Link [Str "Help"] ("Help","wikilink")]
79+,Para [Link [Str "the",Space,Str "help",Space,Str "page"] ("Help","wikilink")]
80+,Para [Link [Str "Helpers"] ("Help","wikilink")]
81+,Para [Link [Str "Help"] ("Help","wikilink"),Str "ers"]
82+,Para [Link [Str "Contents"] ("Help:Contents","wikilink")]
77,Header 2 [Str "lists"]
83,Header 2 [Str "lists"]
78,BulletList
84,BulletList
79 [[Plain [Str "Start",Space,Str "each",Space,Str "line"]]
85 [[Plain [Str "Start",Space,Str "each",Space,Str "line"]]
tests/mediawiki-reader.wiki+12
@@ -147,6 +147,18 @@ http://johnmacfarlane.net/pandoc/
147
147
148[mailto:info@example.org email me]
148[mailto:info@example.org email me]
149
149
150+== internal links ==
151+
152+[[Help]]
153+
154+[[Help|the help page]]
155+
156+[[Help]]ers
157+
158+[[Help]]<nowiki/>ers
159+
160+[[Help:Contents|]]
161+
150== lists ==
162== lists ==
151
163
152* Start each line
164* Start each line