git.iko.soy/typeable/pandoc
on master help sign in
MediaWiki reader: Interpret width attribute on table columns.
0a2fb20John MacFarlane
src/Text/Pandoc/Readers/MediaWiki.hs+33−14
@@ -30,10 +30,8 @@ Conversion of mediawiki text to 'Pandoc' document.
30-}
30-}
31{-
31{-
32TODO:
32TODO:
33−_ tables - cell alignment and width
34_ wikipedia {{cite}} tags
33_ wikipedia {{cite}} tags
35_ <references /> {{Reflist}}
34_ <references /> {{Reflist}}
36−_ calculate cell widths when not given??? see html? latex? reader
37_ support tables http://www.mediawiki.org/wiki/Help:Tables
35_ support tables http://www.mediawiki.org/wiki/Help:Tables
38- footnotes?
36- footnotes?
39-}
37-}
@@ -54,6 +52,7 @@ import Control.Monad
54import Data.List (intersperse, intercalate, isPrefixOf )
52import Data.List (intersperse, intercalate, isPrefixOf )
55import Text.HTML.TagSoup
53import Text.HTML.TagSoup
56import Data.Sequence (viewl, ViewL(..), (<|))
54import Data.Sequence (viewl, ViewL(..), (<|))
55+import Data.Char (isDigit)
57
56
58-- | Read mediawiki from an input string and return a Pandoc document.
57-- | Read mediawiki from an input string and return a Pandoc document.
59readMediaWiki :: ReaderOptions -- ^ Reader options
58readMediaWiki :: ReaderOptions -- ^ Reader options
@@ -185,20 +184,27 @@ table :: MWParser Blocks
185table = do
184table = do
186 tableStart
185 tableStart
187 styles <- manyTill anyChar newline
186 styles <- manyTill anyChar newline
188− let tableWidth = maybe (1.0 :: Double) read
189− $ lookup "width" $ parseAttrs styles
187+ let tableWidth = case lookup "width" $ parseAttrs styles of
188+ Just w -> maybe 1.0 id $ parseWidth w
189+ Nothing -> 1.0
190 caption <- option mempty tableCaption
190 caption <- option mempty tableCaption
191 optional rowsep
191 optional rowsep
192 hasheader <- option False $ True <$ (lookAhead (char '!'))
192 hasheader <- option False $ True <$ (lookAhead (char '!'))
193− (aligns,hdr) <- unzip <$> tableRow
193+ (cellspecs',hdr) <- unzip <$> tableRow
194+ let widths = map ((tableWidth *) . snd) cellspecs'
195+ let restwidth = tableWidth - sum widths
196+ let zerocols = length $ filter (==0.0) widths
197+ let defaultwidth = if zerocols == 0 || zerocols == length widths
198+ then 0.0
199+ else restwidth / fromIntegral zerocols
200+ let widths' = map (\w -> if w == 0 then defaultwidth else w) widths
201+ let cellspecs = zip (map fst cellspecs') widths'
194 rows' <- many $ try $ rowsep *> (map snd <$> tableRow)
202 rows' <- many $ try $ rowsep *> (map snd <$> tableRow)
195 tableEnd
203 tableEnd
196− -- TODO handle cellspecs from styles and aligns...
197 let cols = length hdr
204 let cols = length hdr
198 let (headers,rows) = if hasheader
205 let (headers,rows) = if hasheader
199 then (hdr, rows')
206 then (hdr, rows')
200 else (replicate cols mempty, hdr:rows')
207 else (replicate cols mempty, hdr:rows')
201− let cellspecs = zip aligns (repeat 0.0)
202 return $ B.table caption cellspecs headers rows
208 return $ B.table caption cellspecs headers rows
203
209
204parseAttrs :: String -> [(String,String)]
210parseAttrs :: String -> [(String,String)]
@@ -224,11 +230,15 @@ tableEnd = try $ guardColumnOne *> sym "|}" <* blanklines
224rowsep :: MWParser ()
230rowsep :: MWParser ()
225rowsep = try $ guardColumnOne *> sym "|-" <* blanklines
231rowsep = try $ guardColumnOne *> sym "|-" <* blanklines
226
232
227−-- TODO add something like 'guard inTable' since this is used in endline
228cellsep :: MWParser ()
233cellsep :: MWParser ()
234+cellsep = try $
229−cellsep = (try $ guardColumnOne <*
235+ (guardColumnOne <*
230− (char '!' <|> (char '|' <* notFollowedBy (oneOf "-}+"))))
236+ ( (char '|' <* notFollowedBy (oneOf "-}+"))
237+ <|> (char '!')
238+ )
239+ )
231− <|> (() <$ try (string "||"))
240+ <|> (() <$ try (string "||"))
241+ <|> (() <$ try (string "!!"))
232
242
233tableCaption :: MWParser Inlines
243tableCaption :: MWParser Inlines
234tableCaption = try $ do
244tableCaption = try $ do
@@ -238,10 +248,10 @@ tableCaption = try $ do
238 res <- manyTill anyChar newline >>= parseFromString (many inline)
248 res <- manyTill anyChar newline >>= parseFromString (many inline)
239 return $ trimInlines $ mconcat res
249 return $ trimInlines $ mconcat res
240
250
241−tableRow :: MWParser [(Alignment, Blocks)]
251+tableRow :: MWParser [((Alignment, Double), Blocks)]
242tableRow = try $ many tableCell
252tableRow = try $ many tableCell
243
253
244−tableCell :: MWParser (Alignment, Blocks)
254+tableCell :: MWParser ((Alignment, Double), Blocks)
245tableCell = try $ do
255tableCell = try $ do
246 cellsep
256 cellsep
247 skipMany spaceChar
257 skipMany spaceChar
@@ -255,7 +265,16 @@ tableCell = try $ do
255 Just "right" -> AlignRight
265 Just "right" -> AlignRight
256 Just "center" -> AlignCenter
266 Just "center" -> AlignCenter
257 _ -> AlignDefault
267 _ -> AlignDefault
268+ let width = case lookup "width" attrs of
269+ Just xs -> maybe 0.0 id $ parseWidth xs
270+ Nothing -> 0.0
258− return (align, bs)
271+ return ((align, width), bs)
272+
273+parseWidth :: String -> Maybe Double
274+parseWidth s =
275+ case reverse s of
276+ ('%':ds) | all isDigit ds -> safeRead ('0':'.':reverse ds)
277+ _ -> Nothing
259
278
260template :: MWParser String
279template :: MWParser String
261template = try $ do
280template = try $ do
tests/mediawiki-reader.native+1−1
@@ -214,7 +214,7 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
214 ,[[Para [Str "Butter"]]
214 ,[[Para [Str "Butter"]]
215 ,[Para [Str "Ice",Space,Str "cream"]]
215 ,[Para [Str "Ice",Space,Str "cream"]]
216 ,[Para [Str "and",Space,Str "more"]]]]
216 ,[Para [Str "and",Space,Str "more"]]]]
217−,Table [] [AlignLeft,AlignRight,AlignCenter] [0.0,0.0,0.0]
217+,Table [] [AlignLeft,AlignRight,AlignCenter] [0.25,0.125,0.125]
218 [[Para [Str "Left"]]
218 [[Para [Str "Left"]]
219 ,[Para [Str "Right"]]
219 ,[Para [Str "Right"]]
220 ,[Para [Str "Center"]]]
220 ,[Para [Str "Center"]]]
tests/mediawiki-reader.wiki+2−2
@@ -330,8 +330,8 @@ and cheese
330| Butter || Ice cream || and more
330| Butter || Ice cream || and more
331|}
331|}
332
332
333−{|
333+{|width="50%"
334−! align="left"| Left
334+! align="left" width="50%"| Left
335! align="right"|Right
335! align="right"|Right
336! align="center"|Center
336! align="center"|Center
337|-
337|-