git.iko.soy/typeable/pandoc
on master help sign in
Org reader: fix parsing problem for colons in headline

Fixed a problem where words surrounded by colons could causing parse failures in some cases when they occurred in headers. Fixes: #5993

commit0a3cc7260cbdbe41596d8c0631acc05cc0fd8f50 authorAlbert Krewinkel <albert@zeitkraut.de> dateThu 19 Dec 2019, 07:09 (7 years ago) parent5bd2d28
3 files changed+37−11
src/Text/Pandoc/Readers/Org/DocumentTree.hs+26−11 src/Text/Pandoc/Readers/Org/Parsing.hs+1 test/Tests/Readers/Org/Block/Header.hs+10
src/Text/Pandoc/Readers/Org/DocumentTree.hs+26−11
@@ -1,6 +1,7 @@
11{-# LANGUAGE FlexibleContexts #-}
22{-# LANGUAGE NoImplicitPrelude #-}
33{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE TupleSections #-}
45{- |
56 Module : Text.Pandoc.Readers.Org.DocumentTree
67 Copyright : Copyright (C) 2014-2019 Albert Krewinkel
@@ -16,8 +17,8 @@ module Text.Pandoc.Readers.Org.DocumentTree
1617 ) where
1718
1819import Prelude
19−import Control.Arrow ((***))
20−import Control.Monad (guard, void)
20+import Control.Arrow ((***), first)
21+import Control.Monad (guard)
2122import Data.List (intersperse)
2223import Data.Maybe (mapMaybe)
2324import Data.Text (Text)
@@ -110,15 +111,13 @@ headline blocks inline lvl = try $ do
110111 level <- headerStart
111112 guard (lvl <= level)
112113 todoKw <- optionMaybe todoKeyword
113− title <- trimInlinesF . mconcat <$> manyTill inline endOfTitle
114− tags <- option [] headerTags
115− newline
114+ (title, tags) <- manyThen inline endOfTitle
116115 planning <- option emptyPlanning planningInfo
117116 properties <- option mempty propertiesDrawer
118117 contents <- blocks
119118 children <- many (headline blocks inline (level + 1))
120119 return $ do
121− title' <- title
120+ title' <- trimInlinesF (mconcat title)
122121 contents' <- contents
123122 children' <- sequence children
124123 return Headline
@@ -132,13 +131,29 @@ headline blocks inline lvl = try $ do
132131 , headlineChildren = children'
133132 }
134133 where
135− endOfTitle :: Monad m => OrgParser m ()
136− endOfTitle = void . lookAhead $ optional headerTags *> newline
134+ endOfTitle :: Monad m => OrgParser m [Tag]
135+ endOfTitle = try $ do
136+ skipSpaces
137+ tags <- option [] (headerTags <* skipSpaces)
138+ newline
139+ return tags
137140
138141 headerTags :: Monad m => OrgParser m [Tag]
139− headerTags = try $
140− let tag = orgTagWord <* char ':'
141− in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)
142+ headerTags = try $ do
143+ char ':'
144+ endBy1 (toTag <$> orgTagWord) (char ':')
145+
146+ manyThen :: Monad m
147+ => OrgParser m a
148+ -> OrgParser m b
149+ -> OrgParser m ([a], b)
150+ manyThen p end = (([],) <$> try end) <|> do
151+ x <- p
152+ first (x:) <$> manyThen p end
153+
154+ -- titleFollowedByTags :: Monad m => OrgParser m (Inlines, [Tag])
155+ -- titleFollowedByTags = do
156+
142157
143158unprunedHeadlineToBlocks :: Monad m => Headline -> OrgParserState -> OrgParser m [Block]
144159unprunedHeadlineToBlocks hdln st =
src/Text/Pandoc/Readers/Org/Parsing.hs+1
@@ -94,6 +94,7 @@ module Text.Pandoc.Readers.Org.Parsing
9494 , sepBy
9595 , sepBy1
9696 , sepEndBy1
97+ , endBy1
9798 , option
9899 , optional
99100 , optionMaybe
test/Tests/Readers/Org/Block/Header.hs+10
@@ -142,6 +142,16 @@ tests =
142142 "* This: is not: tagged" =?>
143143 headerWith ("this-is-not-tagged", [], []) 1 "This: is not: tagged"
144144
145+ , "Untagged header time followed by colon" =:
146+ "** Meeting at 5:23: free food" =?>
147+ let attr = ("meeting-at-523-free-food", [], [])
148+ in headerWith attr 2 "Meeting at 5:23: free food"
149+
150+ , "tag followed by text" =:
151+ "*** Looks like a :tag: but isn't" =?>
152+ let attr = ("looks-like-a-tag-but-isnt", [], [])
153+ in headerWith attr 3 "Looks like a :tag: but isn't"
154+
145155 , "Header starting with strokeout text" =:
146156 T.unlines [ "foo"
147157 , ""