git.iko.soy/typeable/pandoc
on master help sign in
Org reader: Add support for figures

Support for figures (images with name and caption) is added.

commitae4280fba528efe68c5955cb3ca0779e6910f43b authorAlbert Krewinkel <tarleb@moltkeplatz.de> dateSat 12 Apr 2014, 00:17 (13 years ago) parent8bc09ce
2 files changed+70−8
src/Text/Pandoc/Readers/Org.hs+49−8 tests/Tests/Readers/Org.hs+21
src/Text/Pandoc/Readers/Org.hs+49−8
@@ -37,6 +37,7 @@ import Text.Pandoc.Parsing hiding (newline, orderedListMarker, updateL
3737import Text.Pandoc.Shared (compactify')
3838
3939import Control.Applicative (pure, (<$>), (<$), (<*>), (<*), (*>), (<**>))
40+import Control.Arrow ((***))
4041import Control.Monad (guard, when)
4142import Data.Char (toLower)
4243import Data.Default
@@ -158,6 +159,7 @@ block = choice [ mempty <$ blanklines
158159 , orgBlock
159160 , example
160161 , drawer
162+ , figure
161163 , specialLine
162164 , header
163165 , hline
@@ -252,6 +254,43 @@ drawerEnd = try $
252254 skipSpaces *> stringAnyCase ":END:" <* skipSpaces <* newline
253255
254256
257+--
258+-- Figures
259+--
260+
261+-- Figures (Image on a line by itself, preceded by name and/or caption)
262+figure :: OrgParser Blocks
263+figure = try $ do
264+ (tit, cap) <- (maybe mempty withFigPrefix *** fromMaybe mempty)
265+ <$> nameAndOrCaption
266+ src <- skipSpaces *> selfTarget <* skipSpaces <* newline
267+ guard (isImageFilename src)
268+ return . B.para $ B.image src tit cap
269+ where withFigPrefix cs = if "fig:" `isPrefixOf` cs
270+ then cs
271+ else "fig:" ++ cs
272+
273+nameAndOrCaption :: OrgParser (Maybe String, Maybe Inlines)
274+nameAndOrCaption = try $ nameFirst <|> captionFirst
275+ where
276+ nameFirst = try $ do
277+ n <- name
278+ c <- optionMaybe caption
279+ return (Just n, c)
280+ captionFirst = try $ do
281+ c <- caption
282+ n <- optionMaybe name
283+ return (n, Just c)
284+
285+caption :: OrgParser Inlines
286+caption = try $ annotation "CAPTION" *> inlinesTillNewline
287+
288+name :: OrgParser String
289+name = try $ annotation "NAME" *> skipSpaces *> manyTill anyChar newline
290+
291+annotation :: String -> OrgParser String
292+annotation ann = try $ metaLineStart *> stringAnyCase ann <* char ':'
293+
255294-- Comments, Options and Metadata
256295specialLine :: OrgParser Blocks
257296specialLine = try $ metaLine <|> commentLine
@@ -277,7 +316,7 @@ declarationLine = try $ do
277316 return mempty
278317
279318metaValue :: OrgParser MetaValue
280−metaValue = MetaInlines . B.toList . trimInlines <$> restOfLine
319+metaValue = MetaInlines . B.toList <$> inlinesTillNewline
281320
282321metaKey :: OrgParser String
283322metaKey = map toLower <$> many1 (noneOf ": \n\r")
@@ -288,7 +327,7 @@ metaKey = map toLower <$> many1 (noneOf ": \n\r")
288327header :: OrgParser Blocks
289328header = try $
290329 B.header <$> headerStart
291− <*> (trimInlines <$> restOfLine)
330+ <*> inlinesTillNewline
292331
293332headerStart :: OrgParser Int
294333headerStart = try $
@@ -424,13 +463,10 @@ setAligns aligns t = t{ orgTableAlignments = aligns }
424463-- Paragraphs or Plain text
425464paraOrPlain :: OrgParser Blocks
426465paraOrPlain = try $
427− trimInlines . mconcat
428− <$> many1 inline
429− <**> option B.plain
430− (try $ newline *> pure B.para)
466+ parseInlines <**> option B.plain (try $ newline *> pure B.para)
431467
432−restOfLine :: OrgParser Inlines
433−restOfLine = mconcat <$> manyTill inline newline
468+inlinesTillNewline :: OrgParser Inlines
469+inlinesTillNewline = trimInlines . mconcat <$> manyTill inline newline
434470
435471
436472--
@@ -523,6 +559,8 @@ inline =
523559 ] <* (guard =<< newlinesCountWithinLimits)
524560 <?> "inline"
525561
562+parseInlines :: OrgParser Inlines
563+parseInlines = trimInlines . mconcat <$> many1 inline
526564
527565-- treat these as potentially non-text when parsing inline:
528566specialChars :: [Char]
@@ -580,6 +618,9 @@ selflinkOrImage = try $ do
580618 then B.image src "" ""
581619 else B.link src "" (B.str src)
582620
621+selfTarget :: OrgParser String
622+selfTarget = try $ char '[' *> linkTarget <* char ']'
623+
583624linkTarget :: OrgParser String
584625linkTarget = enclosed (char '[') (char ']') (noneOf "\n\r]")
585626
tests/Tests/Readers/Org.hs+21
@@ -377,6 +377,27 @@ tests =
377377 code' = "main = putStrLn greeting\n" ++
378378 " where greeting = \"moin\"\n"
379379 in codeBlockWith attr' code'
380+
381+ , "Figure" =:
382+ unlines [ "#+caption: A very courageous man."
383+ , "#+name: goodguy"
384+ , "[[edward.jpg]]"
385+ ] =?>
386+ para (image "edward.jpg" "fig:goodguy" "A very courageous man.")
387+
388+ , "Unnamed figure" =:
389+ unlines [ "#+caption: A great whistleblower."
390+ , "[[snowden.png]]"
391+ ] =?>
392+ para (image "snowden.png" "" "A great whistleblower.")
393+
394+ , "Figure with `fig:` prefix in name" =:
395+ unlines [ "#+caption: Used as a metapher in evolutionary biology."
396+ , "#+name: fig:redqueen"
397+ , "[[the-red-queen.jpg]]"
398+ ] =?>
399+ para (image "the-red-queen.jpg" "fig:redqueen"
400+ "Used as a metapher in evolutionary biology.")
380401 ]
381402
382403 , testGroup "Lists" $