git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #1238 from tarleb/org-figures

Org reader: Add support for figures

commitd5d4227ea5144d7c9da2ffdd44fbbd8131d4d86d authorJohn MacFarlane <jgm@berkeley.edu> dateSun 13 Apr 2014, 14:03 (13 years ago) parentd4c1cd4ae4280f
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
@@ -155,6 +156,7 @@ block = choice [ mempty <$ blanklines
155156 , orgBlock
156157 , example
157158 , drawer
159+ , figure
158160 , specialLine
159161 , header
160162 , hline
@@ -249,6 +251,43 @@ drawerEnd = try $
249251 skipSpaces *> stringAnyCase ":END:" <* skipSpaces <* newline
250252
251253
254+--
255+-- Figures
256+--
257+
258+-- Figures (Image on a line by itself, preceded by name and/or caption)
259+figure :: OrgParser Blocks
260+figure = try $ do
261+ (tit, cap) <- (maybe mempty withFigPrefix *** fromMaybe mempty)
262+ <$> nameAndOrCaption
263+ src <- skipSpaces *> selfTarget <* skipSpaces <* newline
264+ guard (isImageFilename src)
265+ return . B.para $ B.image src tit cap
266+ where withFigPrefix cs = if "fig:" `isPrefixOf` cs
267+ then cs
268+ else "fig:" ++ cs
269+
270+nameAndOrCaption :: OrgParser (Maybe String, Maybe Inlines)
271+nameAndOrCaption = try $ nameFirst <|> captionFirst
272+ where
273+ nameFirst = try $ do
274+ n <- name
275+ c <- optionMaybe caption
276+ return (Just n, c)
277+ captionFirst = try $ do
278+ c <- caption
279+ n <- optionMaybe name
280+ return (n, Just c)
281+
282+caption :: OrgParser Inlines
283+caption = try $ annotation "CAPTION" *> inlinesTillNewline
284+
285+name :: OrgParser String
286+name = try $ annotation "NAME" *> skipSpaces *> manyTill anyChar newline
287+
288+annotation :: String -> OrgParser String
289+annotation ann = try $ metaLineStart *> stringAnyCase ann <* char ':'
290+
252291-- Comments, Options and Metadata
253292specialLine :: OrgParser Blocks
254293specialLine = try $ metaLine <|> commentLine
@@ -274,7 +313,7 @@ declarationLine = try $ do
274313 return mempty
275314
276315metaValue :: OrgParser MetaValue
277−metaValue = MetaInlines . B.toList . trimInlines <$> restOfLine
316+metaValue = MetaInlines . B.toList <$> inlinesTillNewline
278317
279318metaKey :: OrgParser String
280319metaKey = map toLower <$> many1 (noneOf ": \n\r")
@@ -285,7 +324,7 @@ metaKey = map toLower <$> many1 (noneOf ": \n\r")
285324header :: OrgParser Blocks
286325header = try $
287326 B.header <$> headerStart
288− <*> (trimInlines <$> restOfLine)
327+ <*> inlinesTillNewline
289328
290329headerStart :: OrgParser Int
291330headerStart = try $
@@ -421,13 +460,10 @@ setAligns aligns t = t{ orgTableAlignments = aligns }
421460-- Paragraphs or Plain text
422461paraOrPlain :: OrgParser Blocks
423462paraOrPlain = try $
424− trimInlines . mconcat
425− <$> many1 inline
426− <**> option B.plain
427− (try $ newline *> pure B.para)
463+ parseInlines <**> option B.plain (try $ newline *> pure B.para)
428464
429−restOfLine :: OrgParser Inlines
430−restOfLine = mconcat <$> manyTill inline newline
465+inlinesTillNewline :: OrgParser Inlines
466+inlinesTillNewline = trimInlines . mconcat <$> manyTill inline newline
431467
432468
433469--
@@ -520,6 +556,8 @@ inline =
520556 ] <* (guard =<< newlinesCountWithinLimits)
521557 <?> "inline"
522558
559+parseInlines :: OrgParser Inlines
560+parseInlines = trimInlines . mconcat <$> many1 inline
523561
524562-- treat these as potentially non-text when parsing inline:
525563specialChars :: [Char]
@@ -577,6 +615,9 @@ selflinkOrImage = try $ do
577615 then B.image src "" ""
578616 else B.link src "" (B.str src)
579617
618+selfTarget :: OrgParser String
619+selfTarget = try $ char '[' *> linkTarget <* char ']'
620+
580621linkTarget :: OrgParser String
581622linkTarget = enclosed (char '[') (char ']') (noneOf "\n\r]")
582623
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" $