git.iko.soy/typeable/pandoc
on master help sign in
MediaWiki reader: preformatted blocks and tests.
5104c21John MacFarlane
src/Text/Pandoc/Readers/MediaWiki.hs+28−11
@@ -1,6 +1,6 @@
1{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7
1{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7
2{-
2{-
3−Copyright (C) 2012 John MacFarlane <jgm@berkeley.edu>
3+ Copyright (C) 2012 John MacFarlane <jgm@berkeley.edu>
4
4
5This program is free software; you can redistribute it and/or modify
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
6it under the terms of the GNU General Public License as published by
@@ -33,8 +33,6 @@ TODO:
33_ support HTML lists
33_ support HTML lists
34_ support list style attributes and start values in ol lists, also
34_ support list style attributes and start values in ol lists, also
35 value attribute on li
35 value attribute on li
36−_ support preformatted text (lines starting with space)
37−_ support preformatted text blocks
38_ support internal links http://www.mediawiki.org/wiki/Help:Links
36_ support internal links http://www.mediawiki.org/wiki/Help:Links
39_ support external links (partially implemented)
37_ support external links (partially implemented)
40_ support images http://www.mediawiki.org/wiki/Help:Images
38_ support images http://www.mediawiki.org/wiki/Help:Images
@@ -50,13 +48,13 @@ import Text.Pandoc.Definition
50import qualified Text.Pandoc.Builder as B
48import qualified Text.Pandoc.Builder as B
51import Text.Pandoc.Builder (Inlines, Blocks, trimInlines, (<>))
49import Text.Pandoc.Builder (Inlines, Blocks, trimInlines, (<>))
52import Text.Pandoc.Options
50import Text.Pandoc.Options
53−import Text.Pandoc.Readers.HTML ( htmlTag, htmlInBalanced,
51+import Text.Pandoc.Readers.HTML ( htmlTag, isInlineTag,
54− isInlineTag, isBlockTag, isTextTag, isCommentTag )
52+ isBlockTag, isCommentTag )
55import Text.Pandoc.XML ( fromEntities )
53import Text.Pandoc.XML ( fromEntities )
56import Text.Pandoc.Parsing
54import Text.Pandoc.Parsing
55+import Text.Pandoc.Generic ( bottomUp )
57import Text.Pandoc.Shared ( stripTrailingNewlines )
56import Text.Pandoc.Shared ( stripTrailingNewlines )
58import Data.Monoid (mconcat, mempty)
57import Data.Monoid (mconcat, mempty)
59−import qualified Data.Foldable as F
60import Control.Applicative ((<$>), (<*), (*>), (<$))
58import Control.Applicative ((<$>), (<*), (*>), (<$))
61import Control.Monad
59import Control.Monad
62import Data.List (intersperse)
60import Data.List (intersperse)
@@ -124,12 +122,13 @@ block = header
124 <|> bulletList
122 <|> bulletList
125 <|> orderedList
123 <|> orderedList
126 <|> definitionList
124 <|> definitionList
125+ <|> mempty <$ try (spaces *> htmlComment)
126+ <|> preformatted
127 <|> blockquote
127 <|> blockquote
128 <|> codeblock
128 <|> codeblock
129 <|> syntaxhighlight
129 <|> syntaxhighlight
130 <|> haskell
130 <|> haskell
131 <|> mempty <$ skipMany1 blankline
131 <|> mempty <$ skipMany1 blankline
132− <|> mempty <$ try (spaces *> htmlComment)
133 <|> pTag
132 <|> pTag
134 <|> blockHtml
133 <|> blockHtml
135 <|> para
134 <|> para
@@ -147,6 +146,22 @@ blockHtml = (B.rawBlock "html" . snd <$> htmlTag isBlockTag)
147hrule :: MWParser Blocks
146hrule :: MWParser Blocks
148hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline)
147hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline)
149
148
149+preformatted :: MWParser Blocks
150+preformatted = do
151+ char ' '
152+ let endline' = B.linebreak <$ (try $ newline <* char ' ')
153+ let whitespace' = B.str <$> many1 ('\160' <$ spaceChar)
154+ let spToNbsp ' ' = '\160'
155+ spToNbsp x = x
156+ let nowiki' = mconcat . intersperse B.linebreak . map B.str .
157+ lines . fromEntities . map spToNbsp <$> try
158+ (htmlTag (~== TagOpen "nowiki" []) *>
159+ manyTill anyChar (htmlTag (~== TagClose "nowiki")))
160+ let inline' = whitespace' <|> endline' <|> nowiki' <|> inline
161+ let strToCode (Str s) = Code ("",[],[]) s
162+ strToCode x = x
163+ B.para . bottomUp strToCode . mconcat <$> many1 inline'
164+
150blockquote :: MWParser Blocks
165blockquote :: MWParser Blocks
151blockquote = B.blockQuote <$> blocksInTags "blockquote"
166blockquote = B.blockQuote <$> blocksInTags "blockquote"
152
167
@@ -159,8 +174,8 @@ trimCode xs = stripTrailingNewlines xs
159
174
160syntaxhighlight :: MWParser Blocks
175syntaxhighlight :: MWParser Blocks
161syntaxhighlight = try $ do
176syntaxhighlight = try $ do
162− (tag@(TagOpen _ attrs), _) <- lookAhead
177+ (TagOpen _ attrs, _) <- lookAhead
163− $ htmlTag (~== TagOpen "syntaxhighlight" [])
178+ $ htmlTag (~== TagOpen "syntaxhighlight" [])
164 let mblang = lookup "lang" attrs
179 let mblang = lookup "lang" attrs
165 let mbstart = lookup "start" attrs
180 let mbstart = lookup "start" attrs
166 let mbline = lookup "line" attrs
181 let mbline = lookup "line" attrs
@@ -220,6 +235,7 @@ listItem c = try $ do
220 if null extras
235 if null extras
221 then listItem' c
236 then listItem' c
222 else do
237 else do
238+ skipMany spaceChar
223 first <- manyTill anyChar newline
239 first <- manyTill anyChar newline
224 rest <- many (try $ string extras *> manyTill anyChar newline)
240 rest <- many (try $ string extras *> manyTill anyChar newline)
225 contents <- parseFromString (many1 $ listItem' c)
241 contents <- parseFromString (many1 $ listItem' c)
@@ -233,14 +249,15 @@ listItem c = try $ do
233listItem' :: Char -> MWParser Blocks
249listItem' :: Char -> MWParser Blocks
234listItem' c = try $ do
250listItem' c = try $ do
235 listStart c
251 listStart c
252+ skipMany spaceChar
236 first <- manyTill anyChar newline
253 first <- manyTill anyChar newline
237 rest <- many (try $ char c *> lookAhead listStartChar *>
254 rest <- many (try $ char c *> lookAhead listStartChar *>
238 manyTill anyChar newline)
255 manyTill anyChar newline)
239 contents <- parseFromString (mconcat <$> many1 block)
256 contents <- parseFromString (mconcat <$> many1 block)
240 $ unlines $ first : rest
257 $ unlines $ first : rest
241 case viewl (B.unMany contents) of
258 case viewl (B.unMany contents) of
242− (Para xs) :< rest -> return $ B.Many $ (Plain xs) <| rest
259+ (Para xs) :< ys -> return $ B.Many $ (Plain xs) <| ys
243− _ -> return contents
260+ _ -> return contents
244
261
245--
262--
246-- inline parsers
263-- inline parsers
tests/mediawiki-reader.native+6−2
@@ -6,7 +6,7 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
6,Header 5 [Str "header",Space,Str "level",Space,Str "5"]
6,Header 5 [Str "header",Space,Str "level",Space,Str "5"]
7,Header 6 [Str "header",Space,Str "level",Space,Str "6"]
7,Header 6 [Str "header",Space,Str "level",Space,Str "6"]
8,Para [Str "=======",Space,Str "not",Space,Str "a",Space,Str "header",Space,Str "========"]
8,Para [Str "=======",Space,Str "not",Space,Str "a",Space,Str "header",Space,Str "========"]
9−,Para [Str "==",Space,Str "not",Space,Str "a",Space,Str "header",Space,Str "=="]
9+,Para [Code ("",[],[]) "==\160not\160a\160header\160=="]
10,Header 2 [Str "emph",Space,Str "and",Space,Str "strong"]
10,Header 2 [Str "emph",Space,Str "and",Space,Str "strong"]
11,Para [Emph [Str "emph"],Space,Strong [Str "strong"]]
11,Para [Emph [Str "emph"],Space,Strong [Str "strong"]]
12,Para [Strong [Emph [Str "strong",Space,Str "and",Space,Str "emph"]]]
12,Para [Strong [Emph [Str "strong",Space,Str "and",Space,Str "emph"]]]
@@ -131,4 +131,8 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
131 [[Plain [Str "five",Space,Str "sub",Space,Str "1",Space,Str "sub",Space,Str "1"]]]]
131 [[Plain [Str "five",Space,Str "sub",Space,Str "1",Space,Str "sub",Space,Str "1"]]]]
132 ,[Plain [Str "five",Space,Str "sub",Space,Str "2"]]]]]
132 ,[Plain [Str "five",Space,Str "sub",Space,Str "2"]]]]]
133,Header 2 [Str "math"]
133,Header 2 [Str "math"]
134−,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."]]
134+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Math InlineMath "x=\\frac{y^\\pi}{z}",Str "."]
135+,Header 2 [Str "preformatted",Space,Str "blocks"]
136+,Para [Code ("",[],[]) "Start\160each\160line\160with\160a\160space.",LineBreak,Code ("",[],[]) "Text\160is\160",Strong [Code ("",[],[]) "preformatted"],Code ("",[],[]) "\160and",LineBreak,Emph [Code ("",[],[]) "markups"],Code ("",[],[]) "\160",Strong [Emph [Code ("",[],[]) "can"]],Code ("",[],[]) "\160be\160done."]
137+,Para [Code ("",[],[]) "\160hell\160\160\160\160\160\160yeah"]
138+,Para [Code ("",[],[]) "Start\160with\160a\160space\160in\160the\160first\160column,",LineBreak,Code ("",[],[]) "(before\160the\160<nowiki>).",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "Then\160your\160block\160format\160will\160be",LineBreak,Code ("",[],[]) "\160\160\160\160maintained.",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "This\160is\160good\160for\160copying\160in\160code\160blocks:",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "def\160function():",LineBreak,Code ("",[],[]) "\160\160\160\160\"\"\"documentation\160string\"\"\"",LineBreak,Code ("",[],[]) "",LineBreak,Code ("",[],[]) "\160\160\160\160if\160True:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160True",LineBreak,Code ("",[],[]) "\160\160\160\160else:",LineBreak,Code ("",[],[]) "\160\160\160\160\160\160\160\160print\160False"]]
tests/mediawiki-reader.wiki+25
@@ -193,3 +193,28 @@ ends the list.
193
193
194Here is some <math>x=\frac{y^\pi}{z}</math>.
194Here is some <math>x=\frac{y^\pi}{z}</math>.
195
195
196+== preformatted blocks ==
197+
198+ Start each line with a space.
199+ Text is '''preformatted''' and
200+ ''markups'' '''''can''''' be done.
201+
202+ hell yeah
203+
204+ <nowiki>Start with a space in the first column,
205+(before the <nowiki>).
206+
207+Then your block format will be
208+ maintained.
209+
210+This is good for copying in code blocks:
211+
212+def function():
213+ """documentation string"""
214+
215+ if True:
216+ print True
217+ else:
218+ print False</nowiki>
219+
220+