git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #1207 from mpickering/htmlinlines

Fix #1162, #1175 and rewrite textile and HTML backend to use the builder

commitced8be1d080019f56033c8200974598910985dc4 authorJohn MacFarlane <jgm@berkeley.edu> dateTue 1 Apr 2014, 09:21 (13 years ago) parent99f4f6390269cb
10 files changed+446−391
src/Text/Pandoc/Parsing.hs+21−22 src/Text/Pandoc/Readers/HTML.hs+126−109 src/Text/Pandoc/Readers/Markdown.hs+1−1 src/Text/Pandoc/Readers/RST.hs+1−1 src/Text/Pandoc/Readers/Textile.hs+165−134 tests/html-reader.html+5 tests/html-reader.native+78−74 tests/opml-reader.native+1−1 tests/textile-reader.native+45−46 tests/textile-reader.textile+3−3
src/Text/Pandoc/Parsing.hs+21−22
@@ -997,17 +997,17 @@ registerHeader (ident,classes,kvs) header' = do
997997failUnlessSmart :: HasReaderOptions st => Parser s st ()
998998failUnlessSmart = getOption readerSmart >>= guard
999999
1000−smartPunctuation :: Parser [Char] ParserState Inline
1001− -> Parser [Char] ParserState Inline
1000+smartPunctuation :: Parser [Char] ParserState Inlines
1001+ -> Parser [Char] ParserState Inlines
10021002smartPunctuation inlineParser = do
10031003 failUnlessSmart
10041004 choice [ quoted inlineParser, apostrophe, dash, ellipses ]
10051005
1006−apostrophe :: Parser [Char] ParserState Inline
1007−apostrophe = (char '\'' <|> char '\8217') >> return (Str "\x2019")
1006+apostrophe :: Parser [Char] ParserState Inlines
1007+apostrophe = (char '\'' <|> char '\8217') >> return (B.str "\x2019")
10081008
1009−quoted :: Parser [Char] ParserState Inline
1010− -> Parser [Char] ParserState Inline
1009+quoted :: Parser [Char] ParserState Inlines
1010+ -> Parser [Char] ParserState Inlines
10111011quoted inlineParser = doubleQuoted inlineParser <|> singleQuoted inlineParser
10121012
10131013withQuoteContext :: QuoteContext
@@ -1022,20 +1022,19 @@ withQuoteContext context parser = do
10221022 setState newState { stateQuoteContext = oldQuoteContext }
10231023 return result
10241024
1025−singleQuoted :: Parser [Char] ParserState Inline
1026− -> Parser [Char] ParserState Inline
1025+singleQuoted :: Parser [Char] ParserState Inlines
1026+ -> Parser [Char] ParserState Inlines
10271027singleQuoted inlineParser = try $ do
10281028 singleQuoteStart
10291029 withQuoteContext InSingleQuote $ many1Till inlineParser singleQuoteEnd >>=
1030− return . Quoted SingleQuote . normalizeSpaces
1030+ return . B.singleQuoted . mconcat
10311031
1032−doubleQuoted :: Parser [Char] ParserState Inline
1033− -> Parser [Char] ParserState Inline
1032+doubleQuoted :: Parser [Char] ParserState Inlines
1033+ -> Parser [Char] ParserState Inlines
10341034doubleQuoted inlineParser = try $ do
10351035 doubleQuoteStart
1036− withQuoteContext InDoubleQuote $ do
1037− contents <- manyTill inlineParser doubleQuoteEnd
1038− return . Quoted DoubleQuote . normalizeSpaces $ contents
1036+ withQuoteContext InDoubleQuote $ manyTill inlineParser doubleQuoteEnd >>=
1037+ return . B.doubleQuoted . mconcat
10391038
10401039failIfInQuoteContext :: QuoteContext -> Parser [tok] ParserState ()
10411040failIfInQuoteContext context = do
@@ -1079,17 +1078,17 @@ doubleQuoteEnd = do
10791078 charOrRef "\"\8221\148"
10801079 return ()
10811080
1082−ellipses :: Parser [Char] st Inline
1081+ellipses :: Parser [Char] st Inlines
10831082ellipses = do
10841083 try (charOrRef "\8230\133") <|> try (string "..." >> return '…')
1085− return (Str "\8230")
1084+ return (B.str "\8230")
10861085
1087−dash :: Parser [Char] ParserState Inline
1086+dash :: Parser [Char] ParserState Inlines
10881087dash = do
10891088 oldDashes <- getOption readerOldDashes
10901089 if oldDashes
10911090 then emDashOld <|> enDashOld
1092− else Str `fmap` (hyphenDash <|> emDash <|> enDash)
1091+ else B.str `fmap` (hyphenDash <|> emDash <|> enDash)
10931092
10941093-- Two hyphens = en-dash, three = em-dash
10951094hyphenDash :: Parser [Char] st String
@@ -1107,16 +1106,16 @@ enDash = do
11071106 try (charOrRef "\8212\151")
11081107 return "\8211"
11091108
1110−enDashOld :: Parser [Char] st Inline
1109+enDashOld :: Parser [Char] st Inlines
11111110enDashOld = do
11121111 try (charOrRef "\8211\150") <|>
11131112 try (char '-' >> lookAhead (satisfy isDigit) >> return '–')
1114− return (Str "\8211")
1113+ return (B.str "\8211")
11151114
1116−emDashOld :: Parser [Char] st Inline
1115+emDashOld :: Parser [Char] st Inlines
11171116emDashOld = do
11181117 try (charOrRef "\8212\151") <|> (try $ string "--" >> optional (char '-') >> return '-')
1119− return (Str "\8212")
1118+ return (B.str "\8212")
11201119
11211120-- This is used to prevent exponential blowups for things like:
11221121-- a**a*a**a*a**a*a**a*a**a*a**a*a**
src/Text/Pandoc/Readers/HTML.hs+126−109
@@ -40,6 +40,7 @@ import Text.HTML.TagSoup
4040import Text.HTML.TagSoup.Match
4141import Text.Pandoc.Definition
4242import qualified Text.Pandoc.Builder as B
43+import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)
4344import Text.Pandoc.Shared
4445import Text.Pandoc.Options
4546import Text.Pandoc.Parsing
@@ -48,6 +49,8 @@ import Data.List ( intercalate )
4849import Data.Char ( isDigit )
4950import Control.Monad ( liftM, guard, when, mzero )
5051import Control.Applicative ( (<$>), (<$), (<*) )
52+import Data.Monoid
53+import Data.Sequence (ViewL(..), ViewR(..), viewr, viewl)
5154
5255isSpace :: Char -> Bool
5356isSpace ' ' = True
@@ -66,30 +69,30 @@ readHtml opts inp =
6669 where tags = canonicalizeTags $
6770 parseTagsOptions parseOptions{ optTagPosition = True } inp
6871 parseDoc = do
69− blocks <- (fixPlains False . concat) <$> manyTill block eof
72+ blocks <- (fixPlains False) . mconcat <$> manyTill block eof
7073 meta <- stateMeta <$> getState
71− return $ Pandoc meta blocks
74+ return $ Pandoc meta (B.toList blocks)
7275
7376type TagParser = Parser [Tag String] ParserState
7477
75−pBody :: TagParser [Block]
78+pBody :: TagParser Blocks
7679pBody = pInTags "body" block
7780
78−pHead :: TagParser [Block]
79−pHead = pInTags "head" $ pTitle <|> pMetaTag <|> ([] <$ pAnyTag)
80− where pTitle = pInTags "title" inline >>= setTitle . normalizeSpaces
81− setTitle t = [] <$ (updateState $ B.setMeta "title" (B.fromList t))
81+pHead :: TagParser Blocks
82+pHead = pInTags "head" $ pTitle <|> pMetaTag <|> (mempty <$ pAnyTag)
83+ where pTitle = pInTags "title" inline >>= setTitle . trimInlines
84+ setTitle t = mempty <$ (updateState $ B.setMeta "title" t)
8285 pMetaTag = do
8386 mt <- pSatisfy (~== TagOpen "meta" [])
8487 let name = fromAttrib "name" mt
8588 if null name
86− then return []
89+ then return mempty
8790 else do
8891 let content = fromAttrib "content" mt
8992 updateState $ B.setMeta name (B.text content)
90− return []
93+ return mempty
9194
92−block :: TagParser [Block]
95+block :: TagParser Blocks
9396block = choice
9497 [ pPara
9598 , pHeader
@@ -105,10 +108,10 @@ block = choice
105108 , pRawHtmlBlock
106109 ]
107110
108−pList :: TagParser [Block]
111+pList :: TagParser Blocks
109112pList = pBulletList <|> pOrderedList <|> pDefinitionList
110113
111−pBulletList :: TagParser [Block]
114+pBulletList :: TagParser Blocks
112115pBulletList = try $ do
113116 pSatisfy (~== TagOpen "ul" [])
114117 let nonItem = pSatisfy (\t ->
@@ -118,9 +121,9 @@ pBulletList = try $ do
118121 -- treat it as a list item, though it's not valid xhtml...
119122 skipMany nonItem
120123 items <- manyTill (pInTags "li" block >>~ skipMany nonItem) (pCloses "ul")
121− return [BulletList $ map (fixPlains True) items]
124+ return $ B.bulletList $ map (fixPlains True) items
122125
123−pOrderedList :: TagParser [Block]
126+pOrderedList :: TagParser Blocks
124127pOrderedList = try $ do
125128 TagOpen _ attribs <- pSatisfy (~== TagOpen "ol" [])
126129 let (start, style) = (sta', sty')
@@ -146,27 +149,27 @@ pOrderedList = try $ do
146149 -- treat it as a list item, though it's not valid xhtml...
147150 skipMany nonItem
148151 items <- manyTill (pInTags "li" block >>~ skipMany nonItem) (pCloses "ol")
149− return [OrderedList (start, style, DefaultDelim) $ map (fixPlains True) items]
152+ return $ B.orderedListWith (start, style, DefaultDelim) $ map (fixPlains True) items
150153
151−pDefinitionList :: TagParser [Block]
154+pDefinitionList :: TagParser Blocks
152155pDefinitionList = try $ do
153156 pSatisfy (~== TagOpen "dl" [])
154157 items <- manyTill pDefListItem (pCloses "dl")
155− return [DefinitionList items]
158+ return $ B.definitionList items
156159
157−pDefListItem :: TagParser ([Inline],[[Block]])
160+pDefListItem :: TagParser (Inlines, [Blocks])
158161pDefListItem = try $ do
159162 let nonItem = pSatisfy (\t -> not (t ~== TagOpen "dt" []) &&
160163 not (t ~== TagOpen "dd" []) && not (t ~== TagClose "dl"))
161164 terms <- many1 (try $ skipMany nonItem >> pInTags "dt" inline)
162165 defs <- many1 (try $ skipMany nonItem >> pInTags "dd" block)
163166 skipMany nonItem
164− let term = intercalate [LineBreak] terms
167+ let term = foldl1 (\x y -> x <> B.linebreak <> y) terms
165168 return (term, map (fixPlains True) defs)
166169
167−fixPlains :: Bool -> [Block] -> [Block]
168−fixPlains inList bs = if any isParaish bs
169− then map plainToPara bs
170+fixPlains :: Bool -> Blocks -> Blocks
171+fixPlains inList bs = if any isParaish bs'
172+ then B.fromList $ map plainToPara bs'
170173 else bs
171174 where isParaish (Para _) = True
172175 isParaish (CodeBlock _ _) = True
@@ -178,6 +181,7 @@ fixPlains inList bs = if any isParaish bs
178181 isParaish _ = False
179182 plainToPara (Plain xs) = Para xs
180183 plainToPara x = x
184+ bs' = B.toList bs
181185
182186pRawTag :: TagParser String
183187pRawTag = do
@@ -187,20 +191,20 @@ pRawTag = do
187191 then return []
188192 else return $ renderTags' [tag]
189193
190−pDiv :: TagParser [Block]
194+pDiv :: TagParser Blocks
191195pDiv = try $ do
192196 getOption readerParseRaw >>= guard
193197 TagOpen _ attr <- lookAhead $ pSatisfy $ tagOpen (=="div") (const True)
194198 contents <- pInTags "div" block
195− return [Div (mkAttr attr) contents]
199+ return $ B.divWith (mkAttr attr) contents
196200
197−pRawHtmlBlock :: TagParser [Block]
201+pRawHtmlBlock :: TagParser Blocks
198202pRawHtmlBlock = do
199203 raw <- pHtmlBlock "script" <|> pHtmlBlock "style" <|> pRawTag
200204 parseRaw <- getOption readerParseRaw
201205 if parseRaw && not (null raw)
202− then return [RawBlock (Format "html") raw]
203− else return []
206+ then return $ B.rawBlock "html" raw
207+ else return mempty
204208
205209pHtmlBlock :: String -> TagParser String
206210pHtmlBlock t = try $ do
@@ -208,35 +212,34 @@ pHtmlBlock t = try $ do
208212 contents <- manyTill pAnyTag (pSatisfy (~== TagClose t))
209213 return $ renderTags' $ [open] ++ contents ++ [TagClose t]
210214
211−pHeader :: TagParser [Block]
215+pHeader :: TagParser Blocks
212216pHeader = try $ do
213217 TagOpen tagtype attr <- pSatisfy $
214218 tagOpen (`elem` ["h1","h2","h3","h4","h5","h6"])
215219 (const True)
216220 let bodyTitle = TagOpen tagtype attr ~== TagOpen "h1" [("class","title")]
217221 let level = read (drop 1 tagtype)
218− contents <- liftM concat $ manyTill inline (pCloses tagtype <|> eof)
222+ contents <- trimInlines . mconcat <$> manyTill inline (pCloses tagtype <|> eof)
219223 let ident = fromMaybe "" $ lookup "id" attr
220224 let classes = maybe [] words $ lookup "class" attr
221225 let keyvals = [(k,v) | (k,v) <- attr, k /= "class", k /= "id"]
222226 return $ if bodyTitle
223− then [] -- skip a representation of the title in the body
224− else [Header level (ident, classes, keyvals) $
225− normalizeSpaces contents]
227+ then mempty -- skip a representation of the title in the body
228+ else B.headerWith (ident, classes, keyvals) level contents
226229
227−pHrule :: TagParser [Block]
230+pHrule :: TagParser Blocks
228231pHrule = do
229232 pSelfClosing (=="hr") (const True)
230− return [HorizontalRule]
233+ return B.horizontalRule
231234
232−pTable :: TagParser [Block]
235+pTable :: TagParser Blocks
233236pTable = try $ do
234237 TagOpen _ _ <- pSatisfy (~== TagOpen "table" [])
235238 skipMany pBlank
236− caption <- option [] $ pInTags "caption" inline >>~ skipMany pBlank
239+ caption <- option mempty $ pInTags "caption" inline >>~ skipMany pBlank
237240 -- TODO actually read these and take width information from them
238241 widths' <- pColgroup <|> many pCol
239− head' <- option [] $ pOptInTag "thead" $ pInTags "tr" (pCell "th")
242+ head' <- option mempty $ pOptInTag "thead" $ pInTags "tr" (pCell "th")
240243 skipMany pBlank
241244 rows <- pOptInTag "tbody"
242245 $ many1 $ try $ skipMany pBlank >> pInTags "tr" (pCell "td")
@@ -245,19 +248,21 @@ pTable = try $ do
245248 let isSinglePlain [] = True
246249 isSinglePlain [Plain _] = True
247250 isSinglePlain _ = False
248− let isSimple = all isSinglePlain $ concat (head':rows)
249− let cols = length $ if null head'
250− then head rows
251− else head'
251+ let lHead = B.toList head'
252+ let lRows = map B.toList rows
253+ let isSimple = all isSinglePlain (lHead:lRows)
254+ let cols = length $ if null lHead
255+ then head lRows
256+ else lHead
252257 -- fail if there are colspans or rowspans
253− guard $ all (\r -> length r == cols) rows
258+ guard $ all (\r -> length r == cols) lRows
254259 let aligns = replicate cols AlignLeft
255260 let widths = if null widths'
256261 then if isSimple
257262 then replicate cols 0
258263 else replicate cols (1.0 / fromIntegral cols)
259264 else widths'
260− return [Table caption aligns widths head' rows]
265+ return $ B.table caption (zip aligns widths) [head'] [rows]
261266
262267pCol :: TagParser Double
263268pCol = try $ do
@@ -275,31 +280,31 @@ pColgroup = try $ do
275280 skipMany pBlank
276281 manyTill pCol (pCloses "colgroup" <|> eof) <* skipMany pBlank
277282
278−pCell :: String -> TagParser [TableCell]
283+pCell :: String -> TagParser Blocks
279284pCell celltype = try $ do
280285 skipMany pBlank
281286 res <- pInTags celltype block
282287 skipMany pBlank
283− return [res]
288+ return res
284289
285−pBlockQuote :: TagParser [Block]
290+pBlockQuote :: TagParser Blocks
286291pBlockQuote = do
287292 contents <- pInTags "blockquote" block
288− return [BlockQuote $ fixPlains False contents]
293+ return $ B.blockQuote $ fixPlains False contents
289294
290−pPlain :: TagParser [Block]
295+pPlain :: TagParser Blocks
291296pPlain = do
292− contents <- liftM (normalizeSpaces . concat) $ many1 inline
293− if null contents
294− then return []
295− else return [Plain contents]
297+ contents <- trimInlines . mconcat <$> many1 inline
298+ if B.isNull contents
299+ then return mempty
300+ else return $ B.plain contents
296301
297−pPara :: TagParser [Block]
302+pPara :: TagParser Blocks
298303pPara = do
299− contents <- pInTags "p" inline
300− return [Para $ normalizeSpaces contents]
304+ contents <- trimInlines <$> pInTags "p" inline
305+ return $ B.para contents
301306
302−pCodeBlock :: TagParser [Block]
307+pCodeBlock :: TagParser Blocks
303308pCodeBlock = try $ do
304309 TagOpen _ attr <- pSatisfy (~== TagOpen "pre" [])
305310 contents <- manyTill pAnyTag (pCloses "pre" <|> eof)
@@ -312,9 +317,9 @@ pCodeBlock = try $ do
312317 let result = case reverse result' of
313318 '\n':_ -> init result'
314319 _ -> result'
315− return [CodeBlock (mkAttr attr) result]
320+ return $ B.codeBlockWith (mkAttr attr) result
316321
317−inline :: TagParser [Inline]
322+inline :: TagParser Inlines
318323inline = choice
319324 [ pTagText
320325 , pQ
@@ -354,7 +359,7 @@ pSelfClosing f g = do
354359 optional $ pSatisfy (tagClose f)
355360 return open
356361
357−pQ :: TagParser [Inline]
362+pQ :: TagParser Inlines
358363pQ = do
359364 quoteContext <- stateQuoteContext `fmap` getState
360365 let quoteType = case quoteContext of
@@ -363,82 +368,93 @@ pQ = do
363368 let innerQuoteContext = if quoteType == SingleQuote
364369 then InSingleQuote
365370 else InDoubleQuote
366− withQuoteContext innerQuoteContext $ pInlinesInTags "q" (Quoted quoteType)
371+ let constructor = case quoteType of
372+ SingleQuote -> B.singleQuoted
373+ DoubleQuote -> B.doubleQuoted
374+ withQuoteContext innerQuoteContext $
375+ pInlinesInTags "q" constructor
367376
368−pEmph :: TagParser [Inline]
369−pEmph = pInlinesInTags "em" Emph <|> pInlinesInTags "i" Emph
377+pEmph :: TagParser Inlines
378+pEmph = pInlinesInTags "em" B.emph <|> pInlinesInTags "i" B.emph
370379
371−pStrong :: TagParser [Inline]
372−pStrong = pInlinesInTags "strong" Strong <|> pInlinesInTags "b" Strong
380+pStrong :: TagParser Inlines
381+pStrong = pInlinesInTags "strong" B.strong <|> pInlinesInTags "b" B.strong
373382
374−pSuperscript :: TagParser [Inline]
375−pSuperscript = pInlinesInTags "sup" Superscript
383+pSuperscript :: TagParser Inlines
384+pSuperscript = pInlinesInTags "sup" B.superscript
376385
377−pSubscript :: TagParser [Inline]
378−pSubscript = pInlinesInTags "sub" Subscript
386+pSubscript :: TagParser Inlines
387+pSubscript = pInlinesInTags "sub" B.subscript
379388
380−pStrikeout :: TagParser [Inline]
389+pStrikeout :: TagParser Inlines
381390pStrikeout = do
382− pInlinesInTags "s" Strikeout <|>
383− pInlinesInTags "strike" Strikeout <|>
384− pInlinesInTags "del" Strikeout <|>
391+ pInlinesInTags "s" B.strikeout <|>
392+ pInlinesInTags "strike" B.strikeout <|>
393+ pInlinesInTags "del" B.strikeout <|>
385394 try (do pSatisfy (~== TagOpen "span" [("class","strikeout")])
386− contents <- liftM concat $ manyTill inline (pCloses "span")
387− return [Strikeout contents])
395+ contents <- mconcat <$> manyTill inline (pCloses "span")
396+ return $ B.strikeout contents)
388397
389−pLineBreak :: TagParser [Inline]
398+pLineBreak :: TagParser Inlines
390399pLineBreak = do
391400 pSelfClosing (=="br") (const True)
392− return [LineBreak]
401+ return B.linebreak
393402
394−pLink :: TagParser [Inline]
403+pLink :: TagParser Inlines
395404pLink = try $ do
396405 tag <- pSatisfy (tagOpenLit "a" (isJust . lookup "href"))
397406 let url = fromAttrib "href" tag
398407 let title = fromAttrib "title" tag
399− lab <- liftM concat $ manyTill inline (pCloses "a")
400− return [Link (normalizeSpaces lab) (escapeURI url, title)]
408+ lab <- trimInlines . mconcat <$> manyTill inline (pCloses "a")
409+ return $ B.link (escapeURI url) title lab
401410
402−pImage :: TagParser [Inline]
411+pImage :: TagParser Inlines
403412pImage = do
404413 tag <- pSelfClosing (=="img") (isJust . lookup "src")
405414 let url = fromAttrib "src" tag
406415 let title = fromAttrib "title" tag
407416 let alt = fromAttrib "alt" tag
408− return [Image (B.toList $ B.text alt) (escapeURI url, title)]
417+ return $ B.image (escapeURI url) title (B.text alt)
409418
410−pCode :: TagParser [Inline]
419+pCode :: TagParser Inlines
411420pCode = try $ do
412421 (TagOpen open attr) <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True)
413422 result <- manyTill pAnyTag (pCloses open)
414− return [Code (mkAttr attr) $ intercalate " " $ lines $ innerText result]
423+ return $ B.codeWith (mkAttr attr) $ intercalate " " $ lines $ innerText result
415424
416−pSpan :: TagParser [Inline]
425+pSpan :: TagParser Inlines
417426pSpan = try $ do
418427 getOption readerParseRaw >>= guard
419428 TagOpen _ attr <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True)
420429 contents <- pInTags "span" inline
421− return [Span (mkAttr attr) contents]
430+ return $ B.spanWith (mkAttr attr) contents
422431
423−pRawHtmlInline :: TagParser [Inline]
432+pRawHtmlInline :: TagParser Inlines
424433pRawHtmlInline = do
425434 result <- pSatisfy (tagComment (const True)) <|> pSatisfy isInlineTag
426435 parseRaw <- getOption readerParseRaw
427436 if parseRaw
428− then return [RawInline (Format "html") $ renderTags' [result]]
429− else return []
437+ then return $ B.rawInline "html" $ renderTags' [result]
438+ else return mempty
430439
431−pInlinesInTags :: String -> ([Inline] -> Inline)
432− -> TagParser [Inline]
440+pInlinesInTags :: String -> (Inlines -> Inlines)
441+ -> TagParser Inlines
433442pInlinesInTags tagtype f = do
434− contents <- pInTags tagtype inline
435− return [f $ normalizeSpaces contents]
436−
437−pInTags :: String -> TagParser [a]
438− -> TagParser [a]
443+ contents <- B.unMany <$> pInTags tagtype inline
444+ let left = case viewl contents of
445+ EmptyL -> mempty
446+ (a :< _) -> padSpace a
447+ let right = case viewr contents of
448+ EmptyR -> mempty
449+ (_ :> a) -> padSpace a
450+ return (left <> f (trimInlines . B.Many $ contents) <> right)
451+ where padSpace a = if a == Space then B.space else mempty
452+
453+pInTags :: (Monoid a) => String -> TagParser a
454+ -> TagParser a
439455pInTags tagtype parser = try $ do
440456 pSatisfy (~== TagOpen tagtype [])
441− liftM concat $ manyTill parser (pCloses tagtype <|> eof)
457+ mconcat <$> manyTill parser (pCloses tagtype <|> eof)
442458
443459pOptInTag :: String -> TagParser a
444460 -> TagParser a
@@ -461,36 +477,36 @@ pCloses tagtype = try $ do
461477 (TagClose "dl") | tagtype == "li" -> return ()
462478 _ -> mzero
463479
464−pTagText :: TagParser [Inline]
480+pTagText :: TagParser Inlines
465481pTagText = try $ do
466482 (TagText str) <- pSatisfy isTagText
467483 st <- getState
468484 case runParser (many pTagContents) st "text" str of
469485 Left _ -> fail $ "Could not parse `" ++ str ++ "'"
470− Right result -> return result
486+ Right result -> return $ mconcat result
471487
472488pBlank :: TagParser ()
473489pBlank = try $ do
474490 (TagText str) <- pSatisfy isTagText
475491 guard $ all isSpace str
476492
477−pTagContents :: Parser [Char] ParserState Inline
493+pTagContents :: Parser [Char] ParserState Inlines
478494pTagContents =
479− Math DisplayMath `fmap` mathDisplay
480− <|> Math InlineMath `fmap` mathInline
495+ B.displayMath <$> mathDisplay
496+ <|> B.math <$> mathInline
481497 <|> pStr
482498 <|> pSpace
483499 <|> smartPunctuation pTagContents
484500 <|> pSymbol
485501 <|> pBad
486502
487−pStr :: Parser [Char] ParserState Inline
503+pStr :: Parser [Char] ParserState Inlines
488504pStr = do
489505 result <- many1 $ satisfy $ \c ->
490506 not (isSpace c) && not (isSpecial c) && not (isBad c)
491507 pos <- getPosition
492508 updateState $ \s -> s{ stateLastStrPos = Just pos }
493− return $ Str result
509+ return $ B.str result
494510
495511isSpecial :: Char -> Bool
496512isSpecial '"' = True
@@ -504,13 +520,13 @@ isSpecial '\8220' = True
504520isSpecial '\8221' = True
505521isSpecial _ = False
506522
507−pSymbol :: Parser [Char] ParserState Inline
508−pSymbol = satisfy isSpecial >>= return . Str . (:[])
523+pSymbol :: Parser [Char] ParserState Inlines
524+pSymbol = satisfy isSpecial >>= return . B.str . (:[])
509525
510526isBad :: Char -> Bool
511527isBad c = c >= '\128' && c <= '\159' -- not allowed in HTML
512528
513−pBad :: Parser [Char] ParserState Inline
529+pBad :: Parser [Char] ParserState Inlines
514530pBad = do
515531 c <- satisfy isBad
516532 let c' = case c of
@@ -542,10 +558,10 @@ pBad = do
542558 '\158' -> '\382'
543559 '\159' -> '\376'
544560 _ -> '?'
545− return $ Str [c']
561+ return $ B.str [c']
546562
547−pSpace :: Parser [Char] ParserState Inline
548−pSpace = many1 (satisfy isSpace) >> return Space
563+pSpace :: Parser [Char] ParserState Inlines
564+pSpace = many1 (satisfy isSpace) >> return B.space
549565
550566--
551567-- Constants
@@ -679,3 +695,4 @@ mkAttr attr = (attribsId, attribsClasses, attribsKV)
679695 attribsClasses = words $ fromMaybe "" $ lookup "class" attr
680696 attribsKV = filter (\(k,_) -> k /= "class" && k /= "id") attr
681697
698+
src/Text/Pandoc/Readers/Markdown.hs+1−1
@@ -1873,7 +1873,7 @@ smart :: MarkdownParser (F Inlines)
18731873smart = do
18741874 getOption readerSmart >>= guard
18751875 doubleQuoted <|> singleQuoted <|>
1876− choice (map (return . B.singleton <$>) [apostrophe, dash, ellipses])
1876+ choice (map (return <$>) [apostrophe, dash, ellipses])
18771877
18781878singleQuoted :: MarkdownParser (F Inlines)
18791879singleQuoted = try $ do
src/Text/Pandoc/Readers/RST.hs+1−1
@@ -1140,7 +1140,7 @@ smart :: RSTParser Inlines
11401140smart = do
11411141 getOption readerSmart >>= guard
11421142 doubleQuoted <|> singleQuoted <|>
1143− choice (map (B.singleton <$>) [apostrophe, dash, ellipses])
1143+ choice [apostrophe, dash, ellipses]
11441144
11451145singleQuoted :: RSTParser Inlines
11461146singleQuoted = try $ do
src/Text/Pandoc/Readers/Textile.hs+165−134
@@ -50,20 +50,20 @@ TODO : refactor common patterns across readers :
5050
5151
5252module Text.Pandoc.Readers.Textile ( readTextile) where
53−
5453import Text.Pandoc.Definition
54+import Text.Pandoc.Builder (Inlines, Blocks, trimInlines)
5555import qualified Text.Pandoc.Builder as B
56−import Text.Pandoc.Shared
5756import Text.Pandoc.Options
58−import Text.Pandoc.Parsing
57+import Text.Pandoc.Parsing
5958import Text.Pandoc.Readers.HTML ( htmlTag, isInlineTag, isBlockTag )
6059import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock )
6160import Text.HTML.TagSoup (parseTags, innerText, fromAttrib, Tag(..))
6261import Text.HTML.TagSoup.Match
6362import Data.List ( intercalate )
64−import Data.Char ( digitToInt, isUpper )
63+import Data.Char ( digitToInt, isUpper)
6564import Control.Monad ( guard, liftM )
6665import Control.Applicative ((<$>), (*>), (<*))
66+import Data.Monoid
6767
6868-- | Parse a Textile text and return a Pandoc document.
6969readTextile :: ReaderOptions -- ^ Reader options
@@ -95,7 +95,7 @@ parseTextile = do
9595 updateState $ \s -> s { stateNotes = reverse reversedNotes }
9696 -- now parse it for real...
9797 blocks <- parseBlocks
98− return $ Pandoc nullMeta blocks -- FIXME
98+ return $ Pandoc nullMeta (B.toList blocks) -- FIXME
9999
100100noteMarker :: Parser [Char] ParserState [Char]
101101noteMarker = skipMany spaceChar >> string "fn" >> manyTill digit (char '.')
@@ -115,11 +115,11 @@ noteBlock = try $ do
115115 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
116116
117117-- | Parse document blocks
118−parseBlocks :: Parser [Char] ParserState [Block]
119−parseBlocks = manyTill block eof
118+parseBlocks :: Parser [Char] ParserState Blocks
119+parseBlocks = mconcat <$> manyTill block eof
120120
121121-- | Block parsers list tried in definition order
122−blockParsers :: [Parser [Char] ParserState Block]
122+blockParsers :: [Parser [Char] ParserState Blocks]
123123blockParsers = [ codeBlock
124124 , header
125125 , blockQuote
@@ -130,29 +130,32 @@ blockParsers = [ codeBlock
130130 , rawLaTeXBlock'
131131 , maybeExplicitBlock "table" table
132132 , maybeExplicitBlock "p" para
133+ , endBlock
133134 ]
134135
136+endBlock :: Parser [Char] ParserState Blocks
137+endBlock = string "\n\n" >> return mempty
135138-- | Any block in the order of definition of blockParsers
136−block :: Parser [Char] ParserState Block
139+block :: Parser [Char] ParserState Blocks
137140block = choice blockParsers <?> "block"
138141
139−commentBlock :: Parser [Char] ParserState Block
142+commentBlock :: Parser [Char] ParserState Blocks
140143commentBlock = try $ do
141144 string "###."
142145 manyTill anyLine blanklines
143− return Null
146+ return mempty
144147
145−codeBlock :: Parser [Char] ParserState Block
148+codeBlock :: Parser [Char] ParserState Blocks
146149codeBlock = codeBlockBc <|> codeBlockPre
147150
148−codeBlockBc :: Parser [Char] ParserState Block
151+codeBlockBc :: Parser [Char] ParserState Blocks
149152codeBlockBc = try $ do
150153 string "bc. "
151154 contents <- manyTill anyLine blanklines
152− return $ CodeBlock ("",[],[]) $ unlines contents
155+ return $ B.codeBlock (unlines contents)
153156
154157-- | Code Blocks in Textile are between <pre> and </pre>
155−codeBlockPre :: Parser [Char] ParserState Block
158+codeBlockPre :: Parser [Char] ParserState Blocks
156159codeBlockPre = try $ do
157160 (t@(TagOpen _ attrs),_) <- htmlTag (tagOpen (=="pre") (const True))
158161 result' <- (innerText . parseTags) `fmap` -- remove internal tags
@@ -169,29 +172,29 @@ codeBlockPre = try $ do
169172 let classes = words $ fromAttrib "class" t
170173 let ident = fromAttrib "id" t
171174 let kvs = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]
172− return $ CodeBlock (ident,classes,kvs) result'''
175+ return $ B.codeBlockWith (ident,classes,kvs) result'''
173176
174177-- | Header of the form "hN. content" with N in 1..6
175−header :: Parser [Char] ParserState Block
178+header :: Parser [Char] ParserState Blocks
176179header = try $ do
177180 char 'h'
178181 level <- digitToInt <$> oneOf "123456"
179182 attr <- attributes
180183 char '.'
181− whitespace
182− name <- normalizeSpaces <$> manyTill inline blockBreak
183− attr' <- registerHeader attr (B.fromList name)
184− return $ Header level attr' name
184+ lookAhead whitespace
185+ name <- trimInlines . mconcat <$> manyTill inline blockBreak
186+ attr' <- registerHeader attr name
187+ return $ B.headerWith attr' level name
185188
186189-- | Blockquote of the form "bq. content"
187−blockQuote :: Parser [Char] ParserState Block
190+blockQuote :: Parser [Char] ParserState Blocks
188191blockQuote = try $ do
189192 string "bq" >> attributes >> char '.' >> whitespace
190− BlockQuote . singleton <$> para
193+ B.blockQuote <$> para
191194
192195-- Horizontal rule
193196
194−hrule :: Parser [Char] st Block
197+hrule :: Parser [Char] st Blocks
195198hrule = try $ do
196199 skipSpaces
197200 start <- oneOf "-*"
@@ -199,62 +202,62 @@ hrule = try $ do
199202 skipMany (spaceChar <|> char start)
200203 newline
201204 optional blanklines
202− return HorizontalRule
205+ return B.horizontalRule
203206
204207-- Lists handling
205208
206209-- | Can be a bullet list or an ordered list. This implementation is
207210-- strict in the nesting, sublist must start at exactly "parent depth
208211-- plus one"
209−anyList :: Parser [Char] ParserState Block
212+anyList :: Parser [Char] ParserState Blocks
210213anyList = try $ anyListAtDepth 1 <* blanklines
211214
212215-- | This allow one type of list to be nested into an other type,
213216-- provided correct nesting
214−anyListAtDepth :: Int -> Parser [Char] ParserState Block
217+anyListAtDepth :: Int -> Parser [Char] ParserState Blocks
215218anyListAtDepth depth = choice [ bulletListAtDepth depth,
216219 orderedListAtDepth depth,
217220 definitionList ]
218221
219222-- | Bullet List of given depth, depth being the number of leading '*'
220−bulletListAtDepth :: Int -> Parser [Char] ParserState Block
221−bulletListAtDepth depth = try $ BulletList <$> many1 (bulletListItemAtDepth depth)
223+bulletListAtDepth :: Int -> Parser [Char] ParserState Blocks
224+bulletListAtDepth depth = try $ B.bulletList <$> many1 (bulletListItemAtDepth depth)
222225
223226-- | Bullet List Item of given depth, depth being the number of
224227-- leading '*'
225−bulletListItemAtDepth :: Int -> Parser [Char] ParserState [Block]
228+bulletListItemAtDepth :: Int -> Parser [Char] ParserState Blocks
226229bulletListItemAtDepth = genericListItemAtDepth '*'
227230
228231-- | Ordered List of given depth, depth being the number of
229232-- leading '#'
230−orderedListAtDepth :: Int -> Parser [Char] ParserState Block
233+orderedListAtDepth :: Int -> Parser [Char] ParserState Blocks
231234orderedListAtDepth depth = try $ do
232235 items <- many1 (orderedListItemAtDepth depth)
233− return (OrderedList (1, DefaultStyle, DefaultDelim) items)
236+ return $ B.orderedList items
234237
235238-- | Ordered List Item of given depth, depth being the number of
236239-- leading '#'
237−orderedListItemAtDepth :: Int -> Parser [Char] ParserState [Block]
240+orderedListItemAtDepth :: Int -> Parser [Char] ParserState Blocks
238241orderedListItemAtDepth = genericListItemAtDepth '#'
239242
240243-- | Common implementation of list items
241−genericListItemAtDepth :: Char -> Int -> Parser [Char] ParserState [Block]
244+genericListItemAtDepth :: Char -> Int -> Parser [Char] ParserState Blocks
242245genericListItemAtDepth c depth = try $ do
243246 count depth (char c) >> attributes >> whitespace
244− p <- many listInline
247+ p <- mconcat <$> many listInline
245248 newline
246− sublist <- option [] (singleton <$> anyListAtDepth (depth + 1))
247− return (Plain p : sublist)
249+ sublist <- option mempty (anyListAtDepth (depth + 1))
250+ return $ (B.plain p) <> sublist
248251
249252-- | A definition list is a set of consecutive definition items
250−definitionList :: Parser [Char] ParserState Block
251−definitionList = try $ DefinitionList <$> many1 definitionListItem
253+definitionList :: Parser [Char] ParserState Blocks
254+definitionList = try $ B.definitionList <$> many1 definitionListItem
252255
253256-- | List start character.
254257listStart :: Parser [Char] st Char
255258listStart = oneOf "*#-"
256259
257−listInline :: Parser [Char] ParserState Inline
260+listInline :: Parser [Char] ParserState Inlines
258261listInline = try (notFollowedBy newline >> inline)
259262 <|> try (endline <* notFollowedBy listStart)
260263
@@ -262,16 +265,16 @@ listInline = try (notFollowedBy newline >> inline)
262265-- the term defined, then spaces and ":=". The definition follows, on
263266-- the same single line, or spaned on multiple line, after a line
264267-- break.
265−definitionListItem :: Parser [Char] ParserState ([Inline], [[Block]])
268+definitionListItem :: Parser [Char] ParserState (Inlines, [Blocks])
266269definitionListItem = try $ do
267270 string "- "
268− term <- many1Till inline (try (whitespace >> string ":="))
271+ term <- mconcat <$> many1Till inline (try (whitespace >> string ":="))
269272 def' <- multilineDef <|> inlineDef
270273 return (term, def')
271− where inlineDef :: Parser [Char] ParserState [[Block]]
272− inlineDef = liftM (\d -> [[Plain d]])
273− $ optional whitespace >> many listInline <* newline
274− multilineDef :: Parser [Char] ParserState [[Block]]
274+ where inlineDef :: Parser [Char] ParserState [Blocks]
275+ inlineDef = liftM (\d -> [B.plain d])
276+ $ optional whitespace >> (trimInlines . mconcat <$> many listInline) <* newline
277+ multilineDef :: Parser [Char] ParserState [Blocks]
275278 multilineDef = try $ do
276279 optional whitespace >> newline
277280 s <- many1Till anyChar (try (string "=:" >> newline))
@@ -288,59 +291,57 @@ blockBreak = try (newline >> blanklines >> return ()) <|>
288291-- raw content
289292
290293-- | A raw Html Block, optionally followed by blanklines
291−rawHtmlBlock :: Parser [Char] ParserState Block
294+rawHtmlBlock :: Parser [Char] ParserState Blocks
292295rawHtmlBlock = try $ do
293296 (_,b) <- htmlTag isBlockTag
294297 optional blanklines
295− return $ RawBlock (Format "html") b
298+ return $ B.rawBlock "html" b
296299
297300-- | Raw block of LaTeX content
298−rawLaTeXBlock' :: Parser [Char] ParserState Block
301+rawLaTeXBlock' :: Parser [Char] ParserState Blocks
299302rawLaTeXBlock' = do
300303 guardEnabled Ext_raw_tex
301− RawBlock (Format "latex") <$> (rawLaTeXBlock <* spaces)
304+ B.rawBlock "latex" <$> (rawLaTeXBlock <* spaces)
302305
303306
304307-- | In textile, paragraphs are separated by blank lines.
305−para :: Parser [Char] ParserState Block
306−para = try $ Para . normalizeSpaces <$> manyTill inline blockBreak
307−
308+para :: Parser [Char] ParserState Blocks
309+para = B.para . trimInlines . mconcat <$> manyTill inline blockBreak
308310
309311-- Tables
310312
311313-- | A table cell spans until a pipe |
312−tableCell :: Parser [Char] ParserState TableCell
314+tableCell :: Parser [Char] ParserState Blocks
313315tableCell = do
314316 c <- many1 (noneOf "|\n")
315− content <- parseFromString (many1 inline) c
316− return $ [ Plain $ normalizeSpaces content ]
317+ content <- trimInlines . mconcat <$> parseFromString (many1 inline) c
318+ return $ B.plain content
317319
318320-- | A table row is made of many table cells
319−tableRow :: Parser [Char] ParserState [TableCell]
321+tableRow :: Parser [Char] ParserState [Blocks]
320322tableRow = try $ ( char '|' *>
321323 (endBy1 tableCell (optional blankline *> char '|')) <* newline)
322324
323325-- | Many table rows
324−tableRows :: Parser [Char] ParserState [[TableCell]]
326+tableRows :: Parser [Char] ParserState [[Blocks]]
325327tableRows = many1 tableRow
326328
327329-- | Table headers are made of cells separated by a tag "|_."
328−tableHeaders :: Parser [Char] ParserState [TableCell]
330+tableHeaders :: Parser [Char] ParserState [Blocks]
329331tableHeaders = let separator = (try $ string "|_.") in
330332 try $ ( separator *> (sepBy1 tableCell separator) <* char '|' <* newline )
331333
332334-- | A table with an optional header. Current implementation can
333335-- handle tables with and without header, but will parse cells
334336-- alignment attributes as content.
335−table :: Parser [Char] ParserState Block
337+table :: Parser [Char] ParserState Blocks
336338table = try $ do
337− headers <- option [] tableHeaders
339+ headers <- option mempty tableHeaders
338340 rows <- tableRows
339341 blanklines
340342 let nbOfCols = max (length headers) (length $ head rows)
341− return $ Table []
342− (replicate nbOfCols AlignDefault)
343− (replicate nbOfCols 0.0)
343+ return $ B.table mempty
344+ (zip (replicate nbOfCols AlignDefault) (replicate nbOfCols 0.0))
344345 headers
345346 rows
346347
@@ -348,8 +349,8 @@ table = try $ do
348349-- | Blocks like 'p' and 'table' do not need explicit block tag.
349350-- However, they can be used to set HTML/CSS attributes when needed.
350351maybeExplicitBlock :: String -- ^ block tag name
351− -> Parser [Char] ParserState Block -- ^ implicit block
352− -> Parser [Char] ParserState Block
352+ -> Parser [Char] ParserState Blocks -- ^ implicit block
353+ -> Parser [Char] ParserState Blocks
353354maybeExplicitBlock name blk = try $ do
354355 optional $ try $ string name >> attributes >> char '.' >>
355356 optional whitespace >> optional endline
@@ -363,12 +364,14 @@ maybeExplicitBlock name blk = try $ do
363364
364365
365366-- | Any inline element
366−inline :: Parser [Char] ParserState Inline
367−inline = choice inlineParsers <?> "inline"
367+inline :: Parser [Char] ParserState Inlines
368+inline = do
369+ choice inlineParsers <?> "inline"
368370
369371-- | Inline parsers tried in order
370−inlineParsers :: [Parser [Char] ParserState Inline]
371−inlineParsers = [ str
372+inlineParsers :: [Parser [Char] ParserState Inlines]
373+inlineParsers = [ inlineMarkup
374+ , str
372375 , whitespace
373376 , endline
374377 , code
@@ -378,58 +381,57 @@ inlineParsers = [ str
378381 , rawLaTeXInline'
379382 , note
380383 , try $ (char '[' *> inlineMarkup <* char ']')
381− , inlineMarkup
382384 , link
383385 , image
384386 , mark
385− , (Str . (:[])) <$> characterReference
387+ , (B.str . (:[])) <$> characterReference
386388 , smartPunctuation inline
387389 , symbol
388390 ]
389391
390392-- | Inline markups
391−inlineMarkup :: Parser [Char] ParserState Inline
392−inlineMarkup = choice [ simpleInline (string "??") (Cite [])
393− , simpleInline (string "**") Strong
394− , simpleInline (string "__") Emph
395− , simpleInline (char '*') Strong
396− , simpleInline (char '_') Emph
397− , simpleInline (char '+') Emph -- approximates underline
398− , simpleInline (char '-' <* notFollowedBy (char '-')) Strikeout
399− , simpleInline (char '^') Superscript
400− , simpleInline (char '~') Subscript
393+inlineMarkup :: Parser [Char] ParserState Inlines
394+inlineMarkup = choice [ simpleInline (string "??") (B.cite [])
395+ , simpleInline (string "**") B.strong
396+ , simpleInline (string "__") B.emph
397+ , simpleInline (char '*') B.strong
398+ , simpleInline (char '_') B.emph
399+ , simpleInline (char '+') B.emph -- approximates underline
400+ , simpleInline (char '-' <* notFollowedBy (char '-')) B.strikeout
401+ , simpleInline (char '^') B.superscript
402+ , simpleInline (char '~') B.subscript
401403 ]
402404
403405-- | Trademark, registered, copyright
404−mark :: Parser [Char] st Inline
406+mark :: Parser [Char] st Inlines
405407mark = try $ char '(' >> (try tm <|> try reg <|> copy)
406408
407−reg :: Parser [Char] st Inline
409+reg :: Parser [Char] st Inlines
408410reg = do
409411 oneOf "Rr"
410412 char ')'
411− return $ Str "\174"
413+ return $ B.str "\174"
412414
413−tm :: Parser [Char] st Inline
415+tm :: Parser [Char] st Inlines
414416tm = do
415417 oneOf "Tt"
416418 oneOf "Mm"
417419 char ')'
418− return $ Str "\8482"
420+ return $ B.str "\8482"
419421
420−copy :: Parser [Char] st Inline
422+copy :: Parser [Char] st Inlines
421423copy = do
422424 oneOf "Cc"
423425 char ')'
424− return $ Str "\169"
426+ return $ B.str "\169"
425427
426−note :: Parser [Char] ParserState Inline
428+note :: Parser [Char] ParserState Inlines
427429note = try $ do
428430 ref <- (char '[' *> many1 digit <* char ']')
429431 notes <- stateNotes <$> getState
430432 case lookup ref notes of
431433 Nothing -> fail "note not found"
432− Just raw -> liftM Note $ parseFromString parseBlocks raw
434+ Just raw -> B.note <$> parseFromString parseBlocks raw
433435
434436-- | Special chars
435437markupChars :: [Char]
@@ -450,7 +452,7 @@ wordBoundaries = markupChars ++ stringBreakers
450452hyphenedWords :: Parser [Char] ParserState String
451453hyphenedWords = do
452454 x <- wordChunk
453− xs <- many (try $ char '-' >> wordChunk)
455+ xs <- many (try $ char '-' >> wordChunk)
454456 return $ intercalate "-" (x:xs)
455457
456458wordChunk :: Parser [Char] ParserState String
@@ -462,7 +464,7 @@ wordChunk = try $ do
462464 return $ hd:tl
463465
464466-- | Any string
465−str :: Parser [Char] ParserState Inline
467+str :: Parser [Char] ParserState Inlines
466468str = do
467469 baseStr <- hyphenedWords
468470 -- RedCloth compliance : if parsed word is uppercase and immediatly
@@ -472,89 +474,89 @@ str = do
472474 acro <- enclosed (char '(') (char ')') anyChar
473475 return $ concat [baseStr, " (", acro, ")"]
474476 updateLastStrPos
475− return $ Str fullStr
477+ return $ B.str fullStr
476478
477479-- | Textile allows HTML span infos, we discard them
478−htmlSpan :: Parser [Char] ParserState Inline
479−htmlSpan = try $ Str <$> ( char '%' *> attributes *> manyTill anyChar (char '%') )
480+htmlSpan :: Parser [Char] ParserState Inlines
481+htmlSpan = try $ B.str <$> ( char '%' *> attributes *> manyTill anyChar (char '%') )
480482
481483-- | Some number of space chars
482−whitespace :: Parser [Char] ParserState Inline
483−whitespace = many1 spaceChar >> return Space <?> "whitespace"
484+whitespace :: Parser [Char] ParserState Inlines
485+whitespace = many1 spaceChar >> return B.space <?> "whitespace"
484486
485487-- | In Textile, an isolated endline character is a line break
486−endline :: Parser [Char] ParserState Inline
488+endline :: Parser [Char] ParserState Inlines
487489endline = try $ do
488490 newline >> notFollowedBy blankline
489− return LineBreak
491+ return B.linebreak
490492
491−rawHtmlInline :: Parser [Char] ParserState Inline
492−rawHtmlInline = RawInline (Format "html") . snd <$> htmlTag isInlineTag
493+rawHtmlInline :: Parser [Char] ParserState Inlines
494+rawHtmlInline = B.rawInline "html" . snd <$> htmlTag isInlineTag
493495
494496-- | Raw LaTeX Inline
495−rawLaTeXInline' :: Parser [Char] ParserState Inline
497+rawLaTeXInline' :: Parser [Char] ParserState Inlines
496498rawLaTeXInline' = try $ do
497499 guardEnabled Ext_raw_tex
498− rawLaTeXInline
500+ B.singleton <$> rawLaTeXInline
499501
500502-- | Textile standard link syntax is "label":target. But we
501503-- can also have ["label":target].
502−link :: Parser [Char] ParserState Inline
504+link :: Parser [Char] ParserState Inlines
503505link = linkB <|> linkNoB
504506
505−linkNoB :: Parser [Char] ParserState Inline
507+linkNoB :: Parser [Char] ParserState Inlines
506508linkNoB = try $ do
507− name <- surrounded (char '"') inline
509+ name <- mconcat <$> surrounded (char '"') (withQuoteContext InDoubleQuote inline)
508510 char ':'
509511 let stopChars = "!.,;:"
510512 url <- manyTill nonspaceChar (lookAhead $ space <|> try (oneOf stopChars >> (space <|> newline)))
511− let name' = if name == [Str "$"] then [Str url] else name
512− return $ Link name' (url, "")
513+ let name' = if B.toList name == [Str "$"] then B.str url else name
514+ return $ B.link url "" name'
513515
514−linkB :: Parser [Char] ParserState Inline
516+linkB :: Parser [Char] ParserState Inlines
515517linkB = try $ do
516518 char '['
517− name <- surrounded (char '"') inline
519+ name <- mconcat <$> surrounded (char '"') inline
518520 char ':'
519521 url <- manyTill nonspaceChar (char ']')
520− let name' = if name == [Str "$"] then [Str url] else name
521− return $ Link name' (url, "")
522+ let name' = if B.toList name == [Str "$"] then B.str url else name
523+ return $ B.link url "" name'
522524
523525-- | image embedding
524−image :: Parser [Char] ParserState Inline
526+image :: Parser [Char] ParserState Inlines
525527image = try $ do
526528 char '!' >> notFollowedBy space
527529 src <- manyTill anyChar (lookAhead $ oneOf "!(")
528530 alt <- option "" (try $ (char '(' >> manyTill anyChar (char ')')))
529531 char '!'
530− return $ Image [Str alt] (src, alt)
532+ return $ B.image src alt (B.str alt)
531533
532−escapedInline :: Parser [Char] ParserState Inline
534+escapedInline :: Parser [Char] ParserState Inlines
533535escapedInline = escapedEqs <|> escapedTag
534536
535−escapedEqs :: Parser [Char] ParserState Inline
536−escapedEqs = Str <$> (try $ string "==" *> manyTill anyChar (try $ string "=="))
537+escapedEqs :: Parser [Char] ParserState Inlines
538+escapedEqs = B.str <$> (try $ string "==" *> manyTill anyChar (try $ string "=="))
537539
538540-- | literal text escaped btw <notextile> tags
539−escapedTag :: Parser [Char] ParserState Inline
540−escapedTag = Str <$>
541+escapedTag :: Parser [Char] ParserState Inlines
542+escapedTag = B.str <$>
541543 (try $ string "<notextile>" *> manyTill anyChar (try $ string "</notextile>"))
542544
543545-- | Any special symbol defined in wordBoundaries
544−symbol :: Parser [Char] ParserState Inline
545−symbol = Str . singleton <$> (oneOf wordBoundaries <|> oneOf markupChars)
546+symbol :: Parser [Char] ParserState Inlines
547+symbol = B.str . singleton <$> (oneOf wordBoundaries <|> oneOf markupChars)
546548
547549-- | Inline code
548−code :: Parser [Char] ParserState Inline
550+code :: Parser [Char] ParserState Inlines
549551code = code1 <|> code2
550552
551−code1 :: Parser [Char] ParserState Inline
552−code1 = Code nullAttr <$> surrounded (char '@') anyChar
553+code1 :: Parser [Char] ParserState Inlines
554+code1 = B.code <$> surrounded (char '@') anyChar
553555
554−code2 :: Parser [Char] ParserState Inline
556+code2 :: Parser [Char] ParserState Inlines
555557code2 = do
556558 htmlTag (tagOpen (=="tt") null)
557− Code nullAttr <$> manyTill anyChar (try $ htmlTag $ tagClose (=="tt"))
559+ B.code <$> manyTill anyChar (try $ htmlTag $ tagClose (=="tt"))
558560
559561-- | Html / CSS attributes
560562attributes :: Parser [Char] ParserState Attr
@@ -581,7 +583,7 @@ styleAttr = do
581583
582584langAttr :: Parser [Char] ParserState (Attr -> Attr)
583585langAttr = do
584− lang <- try $ enclosed (char '[') (char ']') anyChar
586+ lang <- try $ enclosed (char '[') (char ']') alphaNum
585587 return $ \(id',classes,keyvals) -> (id',classes,("lang",lang):keyvals)
586588
587589-- | Parses material surrounded by a parser.
@@ -590,14 +592,43 @@ surrounded :: Parser [Char] st t -- ^ surrounding parser
590592 -> Parser [Char] st [a]
591593surrounded border = enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try border)
592594
593−-- | Inlines are most of the time of the same form
595+
594596simpleInline :: Parser [Char] ParserState t -- ^ surrounding parser
595− -> ([Inline] -> Inline) -- ^ Inline constructor
596− -> Parser [Char] ParserState Inline -- ^ content parser (to be used repeatedly)
597−simpleInline border construct = surrounded border inlineWithAttribute >>=
598− return . construct . normalizeSpaces
599− where inlineWithAttribute = (try $ optional attributes) >> inline
597+ -> (Inlines -> Inlines) -- ^ Inline constructor
598+ -> Parser [Char] ParserState Inlines -- ^ content parser (to be used repeatedly)
599+simpleInline border construct = groupedSimpleInline border construct <|> ungroupedSimpleInline border construct
600+
601+ungroupedSimpleInline :: Parser [Char] ParserState t -- ^ surrounding parser
602+ -> (Inlines -> Inlines) -- ^ Inline constructor
603+ -> Parser [Char] ParserState Inlines -- ^ content parser (to be used repeatedly)
604+ungroupedSimpleInline border construct = try $ do
605+ st <- getState
606+ pos <- getPosition
607+ isWhitespace <- option False (whitespace >> return True)
608+ guard $ (stateQuoteContext st /= NoQuote)
609+ || (sourceColumn pos == 1)
610+ || isWhitespace
611+ body <- surrounded border inlineWithAttribute
612+ lookAhead (notFollowedBy alphaNum)
613+ let result = construct $ mconcat body
614+ return $ if isWhitespace then B.space <> result
615+ else result
616+ where
617+ inlineWithAttribute = (try $ optional attributes) >> notFollowedBy (string "\n\n")
618+ >> (withQuoteContext InSingleQuote inline)
619+
620+
621+groupedSimpleInline :: Parser [Char] ParserState t
622+ -> (Inlines -> Inlines)
623+ -> Parser [Char] ParserState Inlines
624+groupedSimpleInline border construct = try $ do
625+ char '['
626+ withQuoteContext InSingleQuote (simpleInline border construct) >>~ char ']'
627+
628+
629+
600630
601631-- | Create a singleton list
602632singleton :: a -> [a]
603633singleton x = [x]
634+
tests/html-reader.html+5
@@ -426,5 +426,10 @@ An e-mail address: nobody [at] nowhere.net<blockquote>
426426<pre><code> { &lt;code> }
427427</code></pre>
428428<p>If you want, you can use a caret at the beginning of every line, as with blockquotes, but all that you need is a caret at the beginning of the first line of the block and any preceding blank lines.</p>
429+<p>text<em> Leading space</em></p>
430+<p><em>Trailing space </em>text</p>
431+<p>text<em> Leading spaces</em></p>
432+<p><em>Trailing spaces </em>text</p>
433+
429434</body>
430435</html>
tests/html-reader.native+78−74
@@ -1,5 +1,5 @@
11Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]})
2−[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber",Str "'",Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
2+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber's",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
33,HorizontalRule
44,Header 1 ("",[],[]) [Str "Headers"]
55,Header 2 ("",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link [Str "embedded",Space,Str "link"] ("/url","")]
@@ -14,15 +14,15 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
1414,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
1515,HorizontalRule
1616,Header 1 ("",[],[]) [Str "Paragraphs"]
17−,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Str "regular",Space,Str "paragraph",Str "."]
18−,Para [Str "In",Space,Str "Markdown",Space,Str "1",Str ".",Str "0",Str ".",Str "0",Space,Str "and",Space,Str "earlier",Str ".",Space,Str "Version",Space,Str "8",Str ".",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item",Str ".",Space,Str "Because",Space,Str "a",Space,Str "hard",Str "-",Str "wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item",Str "."]
19−,Para [Str "Here",Str "'",Str "s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet",Str ".",Space,Str "*",Space,Str "criminey",Str "."]
20−,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Space,Str "here",Str "."]
17+,Para [Str "Here's",Space,Str "a",Space,Str "regular",Space,Str "paragraph."]
18+,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",Space,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item."]
19+,Para [Str "Here's",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."]
20+,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Space,Str "here."]
2121,HorizontalRule
2222,Header 1 ("",[],[]) [Str "Block",Space,Str "Quotes"]
23−,Para [Str "E",Str "-",Str "mail",Space,Str "style:"]
23+,Para [Str "E-mail",Space,Str "style:"]
2424,BlockQuote
25− [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote",Str ".",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short",Str "."]]
25+ [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]]
2626,BlockQuote
2727 [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"]
2828 ,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}"
@@ -35,8 +35,8 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
3535 [Para [Str "nested"]]
3636 ,BlockQuote
3737 [Para [Str "nested"]]]
38−,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1",Str "."]
39−,Para [Str "Box",Str "-",Str "style:"]
38+,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."]
39+,Para [Str "Box-style:"]
4040,BlockQuote
4141 [Para [Str "Example:"]
4242 ,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}"]
@@ -44,12 +44,12 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
4444 [OrderedList (1,DefaultStyle,DefaultDelim)
4545 [[Plain [Str "do",Space,Str "laundry"]]
4646 ,[Plain [Str "take",Space,Str "out",Space,Str "the",Space,Str "trash"]]]]
47−,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Str "nested",Space,Str "one:"]
47+,Para [Str "Here's",Space,Str "a",Space,Str "nested",Space,Str "one:"]
4848,BlockQuote
4949 [Para [Str "Joe",Space,Str "said:"]
5050 ,BlockQuote
51− [Para [Str "Don",Str "'",Str "t",Space,Str "quote",Space,Str "me",Str "."]]]
52−,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph",Str "."]
51+ [Para [Str "Don't",Space,Str "quote",Space,Str "me."]]]
52+,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."]
5353,HorizontalRule
5454,Header 1 ("",[],[]) [Str "Code",Space,Str "Blocks"]
5555,Para [Str "Code:"]
@@ -112,10 +112,10 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
112112 ,[Para [Str "Three"]]]
113113,Para [Str "Multiple",Space,Str "paragraphs:"]
114114,OrderedList (1,DefaultStyle,DefaultDelim)
115− [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one",Str "."]
116− ,Para [Str "Item",Space,Str "1",Str ".",Space,Str "graf",Space,Str "two",Str ".",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog",Str "'",Str "s",Space,Str "back",Str "."]]
117− ,[Para [Str "Item",Space,Str "2",Str "."]]
118− ,[Para [Str "Item",Space,Str "3",Str "."]]]
115+ [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."]
116+ ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog's",Space,Str "back."]]
117+ ,[Para [Str "Item",Space,Str "2."]]
118+ ,[Para [Str "Item",Space,Str "3."]]]
119119,Header 2 ("",[],[]) [Str "Nested"]
120120,BulletList
121121 [[Plain [Str "Tab"]
@@ -123,7 +123,7 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
123123 [[Plain [Str "Tab"]
124124 ,BulletList
125125 [[Plain [Str "Tab"]]]]]]]
126−,Para [Str "Here",Str "'",Str "s",Space,Str "another:"]
126+,Para [Str "Here's",Space,Str "another:"]
127127,OrderedList (1,DefaultStyle,DefaultDelim)
128128 [[Plain [Str "First"]]
129129 ,[Plain [Str "Second:"]
@@ -163,63 +163,63 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
163163,OrderedList (1,UpperAlpha,DefaultDelim)
164164 [[Plain [Str "Upper",Space,Str "Alpha"]
165165 ,OrderedList (1,UpperRoman,DefaultDelim)
166− [[Plain [Str "Upper",Space,Str "Roman",Str "."]
166+ [[Plain [Str "Upper",Space,Str "Roman."]
167167 ,OrderedList (6,Decimal,DefaultDelim)
168168 [[Plain [Str "Decimal",Space,Str "start",Space,Str "with",Space,Str "6"]
169169 ,OrderedList (3,LowerAlpha,DefaultDelim)
170170 [[Plain [Str "Lower",Space,Str "alpha",Space,Str "with",Space,Str "paren"]]]]]]]]]
171171,Para [Str "Autonumbering:"]
172172,OrderedList (1,DefaultStyle,DefaultDelim)
173− [[Plain [Str "Autonumber",Str "."]]
174− ,[Plain [Str "More",Str "."]
173+ [[Plain [Str "Autonumber."]]
174+ ,[Plain [Str "More."]
175175 ,OrderedList (1,DefaultStyle,DefaultDelim)
176− [[Plain [Str "Nested",Str "."]]]]]
176+ [[Plain [Str "Nested."]]]]]
177177,HorizontalRule
178178,Header 2 ("",[],[]) [Str "Definition"]
179179,DefinitionList
180180 [([Str "Violin"],
181− [[Plain [Str "Stringed",Space,Str "musical",Space,Str "instrument",Str "."]]
182− ,[Plain [Str "Torture",Space,Str "device",Str "."]]])
181+ [[Plain [Str "Stringed",Space,Str "musical",Space,Str "instrument."]]
182+ ,[Plain [Str "Torture",Space,Str "device."]]])
183183 ,([Str "Cello",LineBreak,Str "Violoncello"],
184− [[Plain [Str "Low",Str "-",Str "voiced",Space,Str "stringed",Space,Str "instrument",Str "."]]])]
184+ [[Plain [Str "Low-voiced",Space,Str "stringed",Space,Str "instrument."]]])]
185185,HorizontalRule
186186,Header 1 ("",[],[]) [Str "Inline",Space,Str "Markup"]
187187,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str "."]
188188,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str "."]
189189,Para [Str "An",Space,Emph [Link [Str "emphasized",Space,Str "link"] ("/url","")],Str "."]
190−,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]]]
191−,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Str "."]
192−,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]]]
193−,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Str "."]
190+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
191+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
192+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
193+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
194194,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",Space,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",Space,Code ("",[],[]) "<html>",Str "."]
195195,HorizontalRule
196196,Header 1 ("",[],[]) [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"]
197−,Para [Str "\"",Str "Hello,",Str "\"",Space,Str "said",Space,Str "the",Space,Str "spider",Str ".",Space,Str "\"",Str "'",Str "Shelob",Str "'",Space,Str "is",Space,Str "my",Space,Str "name",Str ".",Str "\""]
198−,Para [Str "'",Str "A",Str "'",Str ",",Space,Str "'",Str "B",Str "'",Str ",",Space,Str "and",Space,Str "'",Str "C",Str "'",Space,Str "are",Space,Str "letters",Str "."]
199−,Para [Str "'",Str "Oak,",Str "'",Space,Str "'",Str "elm,",Str "'",Space,Str "and",Space,Str "'",Str "beech",Str "'",Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees",Str ".",Space,Str "So",Space,Str "is",Space,Str "'",Str "pine",Str ".",Str "'"]
200−,Para [Str "'",Str "He",Space,Str "said,",Space,Str "\"",Str "I",Space,Str "want",Space,Str "to",Space,Str "go",Str ".",Str "\"",Str "'",Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70",Str "'",Str "s?"]
201−,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Str "'",Code ("",[],[]) "code",Str "'",Space,Str "and",Space,Str "a",Space,Str "\"",Link [Str "quoted",Space,Str "link"] ("http://example.com/?foo=1&bar=2",""),Str "\"",Str "."]
202−,Para [Str "Some",Space,Str "dashes:",Space,Str "one",Str "-",Str "-",Str "-",Str "two",Space,Str "-",Str "-",Str "-",Space,Str "three",Str "-",Str "-",Str "four",Space,Str "-",Str "-",Space,Str "five",Str "."]
203−,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5",Str "-",Str "7,",Space,Str "255",Str "-",Str "66,",Space,Str "1987",Str "-",Str "1999",Str "."]
204−,Para [Str "Ellipses",Str ".",Str ".",Str ".",Str "and",Str ".",Space,Str ".",Space,Str ".",Str "and",Space,Str ".",Space,Str ".",Space,Str ".",Space,Str "."]
197+,Para [Str "\"Hello,\"",Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Str "\"'Shelob'",Space,Str "is",Space,Str "my",Space,Str "name.\""]
198+,Para [Str "'A',",Space,Str "'B',",Space,Str "and",Space,Str "'C'",Space,Str "are",Space,Str "letters."]
199+,Para [Str "'Oak,'",Space,Str "'elm,'",Space,Str "and",Space,Str "'beech'",Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees.",Space,Str "So",Space,Str "is",Space,Str "'pine.'"]
200+,Para [Str "'He",Space,Str "said,",Space,Str "\"I",Space,Str "want",Space,Str "to",Space,Str "go.\"'",Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70's?"]
201+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Str "'",Code ("",[],[]) "code",Str "'",Space,Str "and",Space,Str "a",Space,Str "\"",Link [Str "quoted",Space,Str "link"] ("http://example.com/?foo=1&bar=2",""),Str "\"."]
202+,Para [Str "Some",Space,Str "dashes:",Space,Str "one---two",Space,Str "---",Space,Str "three--four",Space,Str "--",Space,Str "five."]
203+,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5-7,",Space,Str "255-66,",Space,Str "1987-1999."]
204+,Para [Str "Ellipses...and.",Space,Str ".",Space,Str ".and",Space,Str ".",Space,Str ".",Space,Str ".",Space,Str "."]
205205,HorizontalRule
206206,Header 1 ("",[],[]) [Str "LaTeX"]
207207,BulletList
208− [[Plain [Str "\\cite[22",Str "-",Str "23]{smith",Str ".",Str "1899}"]]
208+ [[Plain [Str "\\cite[22-23]{smith.1899}"]]
209209 ,[Plain [Str "\\doublespacing"]]
210− ,[Plain [Str "$",Str "2+2=4",Str "$"]]
211− ,[Plain [Str "$",Str "x",Space,Str "\\in",Space,Str "y",Str "$"]]
212− ,[Plain [Str "$",Str "\\alpha",Space,Str "\\wedge",Space,Str "\\omega",Str "$"]]
213− ,[Plain [Str "$",Str "223",Str "$"]]
214− ,[Plain [Str "$",Str "p",Str "$",Str "-",Str "Tree"]]
215− ,[Plain [Str "$",Str "\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)",Str "-",Str "f(x)}{h}",Str "$"]]
216− ,[Plain [Str "Here",Str "'",Str "s",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$",Str "\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",Space,Str "x^2",Str "$",Str "."]]]
217−,Para [Str "These",Space,Str "shouldn",Str "'",Str "t",Space,Str "be",Space,Str "math:"]
210+ ,[Plain [Str "$2+2=4$"]]
211+ ,[Plain [Str "$x",Space,Str "\\in",Space,Str "y$"]]
212+ ,[Plain [Str "$\\alpha",Space,Str "\\wedge",Space,Str "\\omega$"]]
213+ ,[Plain [Str "$223$"]]
214+ ,[Plain [Str "$p$-Tree"]]
215+ ,[Plain [Str "$\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)-f(x)}{h}$"]]
216+ ,[Plain [Str "Here's",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",Space,Str "x^2$."]]]
217+,Para [Str "These",Space,Str "shouldn't",Space,Str "be",Space,Str "math:"]
218218,BulletList
219219 [[Plain [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",Space,Code ("",[],[]) "$e = mc^2$",Str "."]]
220− ,[Plain [Str "$",Str "22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money",Str ".",Space,Str "So",Space,Str "is",Space,Str "$",Str "34,000",Str ".",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Str "\"",Str "lot",Str "\"",Space,Str "is",Space,Str "emphasized",Str ".",Str ")"]]
221− ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$",Str "73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23",Str "$",Str "."]]]
222−,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
220+ ,[Plain [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",Space,Str "worked",Space,Str "if",Space,Str "\"lot\"",Space,Str "is",Space,Str "emphasized.)"]]
221+ ,[Plain [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",Space,Str "emphasized"],Space,Str "23$."]]]
222+,Para [Str "Here's",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
223223,Para [Str "\\begin{tabular}{|l|l|}\\hline",Space,Str "Animal",Space,Str "&",Space,Str "Number",Space,Str "\\\\",Space,Str "\\hline",Space,Str "Dog",Space,Str "&",Space,Str "2",Space,Str "\\\\",Space,Str "Cat",Space,Str "&",Space,Str "1",Space,Str "\\\\",Space,Str "\\hline",Space,Str "\\end{tabular}"]
224224,HorizontalRule
225225,Header 1 ("",[],[]) [Str "Special",Space,Str "Characters"]
@@ -230,11 +230,11 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
230230 ,[Plain [Str "section:",Space,Str "\167"]]
231231 ,[Plain [Str "set",Space,Str "membership:",Space,Str "\8712"]]
232232 ,[Plain [Str "copyright:",Space,Str "\169"]]]
233−,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name",Str "."]
234−,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it",Str "."]
235−,Para [Str "This",Space,Str "&",Space,Str "that",Str "."]
236−,Para [Str "4",Space,Str "<",Space,Str "5",Str "."]
237−,Para [Str "6",Space,Str ">",Space,Str "5",Str "."]
233+,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."]
234+,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."]
235+,Para [Str "This",Space,Str "&",Space,Str "that."]
236+,Para [Str "4",Space,Str "<",Space,Str "5."]
237+,Para [Str "6",Space,Str ">",Space,Str "5."]
238238,Para [Str "Backslash:",Space,Str "\\"]
239239,Para [Str "Backtick:",Space,Str "`"]
240240,Para [Str "Asterisk:",Space,Str "*"]
@@ -245,7 +245,7 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
245245,Para [Str "Right",Space,Str "bracket:",Space,Str "]"]
246246,Para [Str "Left",Space,Str "paren:",Space,Str "("]
247247,Para [Str "Right",Space,Str "paren:",Space,Str ")"]
248−,Para [Str "Greater",Str "-",Str "than:",Space,Str ">"]
248+,Para [Str "Greater-than:",Space,Str ">"]
249249,Para [Str "Hash:",Space,Str "#"]
250250,Para [Str "Period:",Space,Str "."]
251251,Para [Str "Bang:",Space,Str "!"]
@@ -260,47 +260,51 @@ Pandoc (Meta {unMeta = fromList [("generator",MetaInlines [Str "pandoc"]),("titl
260260,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title preceded by a tab"),Str "."]
261261,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with \"quotes\" in it")]
262262,Para [Link [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","title with single quotes")]
263−,Para [Str "Email",Space,Str "link",Space,Str "(nobody",Space,Str "[at]",Space,Str "nowhere",Str ".",Str "net)"]
263+,Para [Str "Email",Space,Str "link",Space,Str "(nobody",Space,Str "[at]",Space,Str "nowhere.net)"]
264264,Para [Link [Str "Empty"] ("",""),Str "."]
265265,Header 2 ("",[],[]) [Str "Reference"]
266266,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
267267,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
268268,Para [Str "Foo",Space,Link [Str "bar"] ("/url/",""),Str "."]
269269,Para [Str "With",Space,Link [Str "embedded",Space,Str "[brackets]"] ("/url/",""),Str "."]
270−,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link",Str "."]
270+,Para [Link [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."]
271271,Para [Str "Indented",Space,Link [Str "once"] ("/url",""),Str "."]
272272,Para [Str "Indented",Space,Link [Str "twice"] ("/url",""),Str "."]
273273,Para [Str "Indented",Space,Link [Str "thrice"] ("/url",""),Str "."]
274−,Para [Str "This",Space,Str "should",Space,Str "[not]",Space,Str "be",Space,Str "a",Space,Str "link",Str "."]
274+,Para [Str "This",Space,Str "should",Space,Str "[not]",Space,Str "be",Space,Str "a",Space,Str "link."]
275275,CodeBlock ("",[],[]) "[not]: /url"
276276,Para [Str "Foo",Space,Link [Str "bar"] ("/url/","Title with \"quotes\" inside"),Str "."]
277277,Para [Str "Foo",Space,Link [Str "biz"] ("/url/","Title with \"quote\" inside"),Str "."]
278278,Header 2 ("",[],[]) [Str "With",Space,Str "ampersands"]
279−,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."]
280−,Para [Str "Here",Str "'",Str "s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] ("http://att.com/","AT&T"),Str "."]
281−,Para [Str "Here",Str "'",Str "s",Space,Str "an",Space,Link [Str "inline",Space,Str "link"] ("/script?foo=1&bar=2",""),Str "."]
282−,Para [Str "Here",Str "'",Str "s",Space,Str "an",Space,Link [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."]
279+,Para [Str "Here's",Space,Str "a",Space,Link [Str "link",Space,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."]
280+,Para [Str "Here's",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",Space,Link [Str "AT&T"] ("http://att.com/","AT&T"),Str "."]
281+,Para [Str "Here's",Space,Str "an",Space,Link [Str "inline",Space,Str "link"] ("/script?foo=1&bar=2",""),Str "."]
282+,Para [Str "Here's",Space,Str "an",Space,Link [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."]
283283,Header 2 ("",[],[]) [Str "Autolinks"]
284−,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link [Str "http://example",Str ".",Str "com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
284+,Para [Str "With",Space,Str "an",Space,Str "ampersand:",Space,Link [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
285285,BulletList
286286 [[Plain [Str "In",Space,Str "a",Space,Str "list?"]]
287− ,[Plain [Link [Str "http://example",Str ".",Str "com/"] ("http://example.com/","")]]
288− ,[Plain [Str "It",Space,Str "should",Str "."]]]
289−,Para [Str "An",Space,Str "e",Str "-",Str "mail",Space,Str "address:",Space,Str "nobody",Space,Str "[at]",Space,Str "nowhere",Str ".",Str "net"]
287+ ,[Plain [Link [Str "http://example.com/"] ("http://example.com/","")]]
288+ ,[Plain [Str "It",Space,Str "should."]]]
289+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Str "nobody",Space,Str "[at]",Space,Str "nowhere.net"]
290290,BlockQuote
291− [Para [Str "Blockquoted:",Space,Link [Str "http://example",Str ".",Str "com/"] ("http://example.com/","")]]
292−,Para [Str "Auto",Str "-",Str "links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",Space,Code ("",[],[]) "<http://example.com/>"]
291+ [Para [Str "Blockquoted:",Space,Link [Str "http://example.com/"] ("http://example.com/","")]]
292+,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",Space,Code ("",[],[]) "<http://example.com/>"]
293293,CodeBlock ("",[],[]) "or here: <http://example.com/>"
294294,HorizontalRule
295295,Header 1 ("",[],[]) [Str "Images"]
296−,Para [Str "From",Space,Str "\"",Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune",Str "\"",Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"]
296+,Para [Str "From",Space,Str "\"Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune\"",Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"]
297297,Para [Image [Str "lalune"] ("lalune.jpg","Voyage dans la Lune")]
298−,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon",Str "."]
298+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image [Str "movie"] ("movie.jpg",""),Space,Str "icon."]
299299,HorizontalRule
300300,Header 1 ("",[],[]) [Str "Footnotes"]
301−,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference",Link [Str "(1)"] ("#note_1",""),Str ",",Space,Str "and",Space,Str "another",Link [Str "(longnote)"] ("#note_longnote",""),Str ".",Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space^(my",Space,Str "note)",Str "."]
302−,Para [Link [Str "(1)"] ("#ref_1",""),Space,Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote",Str ".",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "in",Space,Str "the",Space,Str "document,",Space,Str "not",Space,Str "just",Space,Str "at",Space,Str "the",Space,Str "end",Str "."]
303−,Para [Link [Str "(longnote)"] ("#ref_longnote",""),Space,Str "Here",Str "'",Str "s",Space,Str "the",Space,Str "other",Space,Str "note",Str ".",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks",Str "."]
304−,Para [Str "Caret",Space,Str "characters",Space,Str "are",Space,Str "used",Space,Str "to",Space,Str "indicate",Space,Str "that",Space,Str "the",Space,Str "blocks",Space,Str "all",Space,Str "belong",Space,Str "to",Space,Str "a",Space,Str "single",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "block",Space,Str "quotes)",Str "."]
301+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference",Link [Str "(1)"] ("#note_1",""),Str ",",Space,Str "and",Space,Str "another",Link [Str "(longnote)"] ("#note_longnote",""),Str ".",Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space^(my",Space,Str "note)."]
302+,Para [Link [Str "(1)"] ("#ref_1",""),Space,Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "in",Space,Str "the",Space,Str "document,",Space,Str "not",Space,Str "just",Space,Str "at",Space,Str "the",Space,Str "end."]
303+,Para [Link [Str "(longnote)"] ("#ref_longnote",""),Space,Str "Here's",Space,Str "the",Space,Str "other",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."]
304+,Para [Str "Caret",Space,Str "characters",Space,Str "are",Space,Str "used",Space,Str "to",Space,Str "indicate",Space,Str "that",Space,Str "the",Space,Str "blocks",Space,Str "all",Space,Str "belong",Space,Str "to",Space,Str "a",Space,Str "single",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "block",Space,Str "quotes)."]
305305,CodeBlock ("",[],[]) " { <code> }"
306−,Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "use",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "every",Space,Str "line,",Space,Str "as",Space,Str "with",Space,Str "blockquotes,",Space,Str "but",Space,Str "all",Space,Str "that",Space,Str "you",Space,Str "need",Space,Str "is",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "the",Space,Str "block",Space,Str "and",Space,Str "any",Space,Str "preceding",Space,Str "blank",Space,Str "lines",Str "."]]
306+,Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "use",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "every",Space,Str "line,",Space,Str "as",Space,Str "with",Space,Str "blockquotes,",Space,Str "but",Space,Str "all",Space,Str "that",Space,Str "you",Space,Str "need",Space,Str "is",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "the",Space,Str "block",Space,Str "and",Space,Str "any",Space,Str "preceding",Space,Str "blank",Space,Str "lines."]
307+,Para [Str "text",Space,Emph [Str "Leading",Space,Str "space"]]
308+,Para [Emph [Str "Trailing",Space,Str "space"],Space,Str "text"]
309+,Para [Str "text",Space,Emph [Str "Leading",Space,Str "spaces"]]
310+,Para [Emph [Str "Trailing",Space,Str "spaces"],Space,Str "text"]]
tests/opml-reader.native+1−1
@@ -19,7 +19,7 @@ Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Dave",Spa
1919,Header 3 ("",[],[]) [Str "North",Space,Str "Dakota"]
2020,Header 3 ("",[],[]) [Str "Oklahoma"]
2121,Header 3 ("",[],[]) [Str "South",Space,Str "Dakota"]
22−,Header 2 ("",[],[]) [Str "Mid",Str "-",Str "Atlantic"]
22+,Header 2 ("",[],[]) [Str "Mid-Atlantic"]
2323,Header 3 ("",[],[]) [Str "Delaware"]
2424,Header 3 ("",[],[]) [Str "Maryland"]
2525,Header 3 ("",[],[]) [Str "New",Space,Str "Jersey"]
tests/textile-reader.native+45−46
@@ -1,5 +1,5 @@
11Pandoc (Meta {unMeta = fromList []})
2−[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Space,Str "Textile",Space,Str "Reader",Str ".",Space,Str "Part",Space,Str "of",Space,Str "it",Space,Str "comes",LineBreak,Str "from",Space,Str "John",Space,Str "Gruber",Str "\8217",Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
2+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Space,Str "Textile",Space,Str "Reader.",Space,Str "Part",Space,Str "of",Space,Str "it",Space,Str "comes",LineBreak,Str "from",Space,Str "John",Space,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
33,HorizontalRule
44,Header 1 ("headers",[],[]) [Str "Headers"]
55,Header 2 ("level-2-with-an-embeded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link [Str "embeded",Space,Str "link"] ("http://www.example.com","")]
@@ -8,42 +8,42 @@ Pandoc (Meta {unMeta = fromList []})
88,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"]
99,Header 6 ("level-6",[],[]) [Str "Level",Space,Str "6"]
1010,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"]
11−,Para [Str "Here",Str "\8217",Str "s",Space,Str "a",Space,Str "regular",Space,Str "paragraph",Str "."]
12−,Para [Str "Line",Space,Str "breaks",Space,Str "are",Space,Str "preserved",Space,Str "in",Space,Str "textile",Str ",",Space,Str "so",Space,Str "you",Space,Str "can",Space,Str "not",Space,Str "wrap",Space,Str "your",Space,Str "very",LineBreak,Str "long",Space,Str "paragraph",Space,Str "with",Space,Str "your",Space,Str "favourite",Space,Str "text",Space,Str "editor",Space,Str "and",Space,Str "have",Space,Str "it",Space,Str "rendered",LineBreak,Str "with",Space,Str "no",Space,Str "break",Str "."]
13−,Para [Str "Here",Str "\8217",Str "s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet",Str "."]
11+,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph."]
12+,Para [Str "Line",Space,Str "breaks",Space,Str "are",Space,Str "preserved",Space,Str "in",Space,Str "textile,",Space,Str "so",Space,Str "you",Space,Str "can",Space,Str "not",Space,Str "wrap",Space,Str "your",Space,Str "very",LineBreak,Str "long",Space,Str "paragraph",Space,Str "with",Space,Str "your",Space,Str "favourite",Space,Str "text",Space,Str "editor",Space,Str "and",Space,Str "have",Space,Str "it",Space,Str "rendered",LineBreak,Str "with",Space,Str "no",Space,Str "break."]
13+,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet."]
1414,BulletList
15− [[Plain [Str "criminey",Str "."]]]
15+ [[Plain [Str "criminey."]]]
1616,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "paragraph",Space,Str "break",Space,Str "between",Space,Str "here"]
17−,Para [Str "and",Space,Str "here",Str "."]
18−,Para [Str "pandoc",Space,Str "converts",Space,Str "textile",Str "."]
17+,Para [Str "and",Space,Str "here."]
18+,Para [Str "pandoc",Space,Str "converts",Space,Str "textile."]
1919,Header 1 ("block-quotes",[],[]) [Str "Block",Space,Str "Quotes"]
2020,BlockQuote
21− [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "famous",Space,Str "quote",Space,Str "from",Space,Str "somebody",Str ".",Space,Str "He",Space,Str "had",Space,Str "a",Space,Str "lot",Space,Str "of",Space,Str "things",Space,Str "to",LineBreak,Str "say",Str ",",Space,Str "so",Space,Str "the",Space,Str "text",Space,Str "is",Space,Str "really",Space,Str "really",Space,Str "long",Space,Str "and",Space,Str "spans",Space,Str "on",Space,Str "multiple",Space,Str "lines",Str "."]]
22−,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph",Str "."]
21+ [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "famous",Space,Str "quote",Space,Str "from",Space,Str "somebody.",Space,Str "He",Space,Str "had",Space,Str "a",Space,Str "lot",Space,Str "of",Space,Str "things",Space,Str "to",LineBreak,Str "say,",Space,Str "so",Space,Str "the",Space,Str "text",Space,Str "is",Space,Str "really",Space,Str "really",Space,Str "long",Space,Str "and",Space,Str "spans",Space,Str "on",Space,Str "multiple",Space,Str "lines."]]
22+,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."]
2323,Header 1 ("code-blocks",[],[]) [Str "Code",Space,Str "Blocks"]
24−,Para [Str "Code",Str ":"]
24+,Para [Str "Code:"]
2525,CodeBlock ("",[],[]) " ---- (should be four hyphens)\n\n sub status {\n print \"working\";\n }\n\n this code block is indented by one tab"
26−,Para [Str "And",Str ":"]
26+,Para [Str "And:"]
2727,CodeBlock ("",[],[]) " this code block is indented by two tabs\n\n These should not be escaped: \\$ \\\\ \\> \\[ \\{"
2828,CodeBlock ("",[],[]) "Code block with .bc\n continued\n @</\\\n"
29−,Para [Str "Inline",Space,Str "code",Str ":",Space,Code ("",[],[]) "<tt>",Str ",",Space,Code ("",[],[]) "@",Str "."]
29+,Para [Str "Inline",Space,Str "code:",Space,Code ("",[],[]) "<tt>",Str ",",Space,Code ("",[],[]) "@",Str "."]
3030,Header 1 ("notextile",[],[]) [Str "Notextile"]
3131,Para [Str "A",Space,Str "block",Space,Str "of",Space,Str "text",Space,Str "can",Space,Str "be",Space,Str "protected",Space,Str "with",Space,Str "notextile",Space,Str ":"]
3232,Para [Str "\nNo *bold* and\n* no bullet\n"]
33−,Para [Str "and",Space,Str "inlines",Space,Str "can",Space,Str "be",Space,Str "protected",Space,Str "with",Space,Str "double *equals (=)* markup",Str "."]
33+,Para [Str "and",Space,Str "inlines",Space,Str "can",Space,Str "be",Space,Str "protected",Space,Str "with",Space,Str "double *equals (=)* markup."]
3434,Header 1 ("lists",[],[]) [Str "Lists"]
3535,Header 2 ("unordered",[],[]) [Str "Unordered"]
36−,Para [Str "Asterisks",Space,Str "tight",Str ":"]
36+,Para [Str "Asterisks",Space,Str "tight:"]
3737,BulletList
3838 [[Plain [Str "asterisk",Space,Str "1"]]
3939 ,[Plain [Str "asterisk",Space,Str "2"]]
4040 ,[Plain [Str "asterisk",Space,Str "3"]]]
41−,Para [Str "With",Space,Str "line",Space,Str "breaks",Str ":"]
41+,Para [Str "With",Space,Str "line",Space,Str "breaks:"]
4242,BulletList
4343 [[Plain [Str "asterisk",Space,Str "1",LineBreak,Str "newline"]]
4444 ,[Plain [Str "asterisk",Space,Str "2"]]]
4545,Header 2 ("ordered",[],[]) [Str "Ordered"]
46−,Para [Str "Tight",Str ":"]
46+,Para [Str "Tight:"]
4747,OrderedList (1,DefaultStyle,DefaultDelim)
4848 [[Plain [Str "First"]]
4949 ,[Plain [Str "Second"]]
@@ -52,42 +52,42 @@ Pandoc (Meta {unMeta = fromList []})
5252,BulletList
5353 [[Plain [Str "ui",Space,Str "1"]
5454 ,BulletList
55− [[Plain [Str "ui",Space,Str "1",Str ".",Str "1"]
55+ [[Plain [Str "ui",Space,Str "1.1"]
5656 ,OrderedList (1,DefaultStyle,DefaultDelim)
57− [[Plain [Str "oi",Space,Str "1",Str ".",Str "1",Str ".",Str "1"]]
58− ,[Plain [Str "oi",Space,Str "1",Str ".",Str "1",Str ".",Str "2"]]]]
59− ,[Plain [Str "ui",Space,Str "1",Str ".",Str "2"]]]]
57+ [[Plain [Str "oi",Space,Str "1.1.1"]]
58+ ,[Plain [Str "oi",Space,Str "1.1.2"]]]]
59+ ,[Plain [Str "ui",Space,Str "1.2"]]]]
6060 ,[Plain [Str "ui",Space,Str "2"]
6161 ,OrderedList (1,DefaultStyle,DefaultDelim)
62− [[Plain [Str "oi",Space,Str "2",Str ".",Str "1"]
62+ [[Plain [Str "oi",Space,Str "2.1"]
6363 ,BulletList
64− [[Plain [Str "ui",Space,Str "2",Str ".",Str "1",Str ".",Str "1"]]
65− ,[Plain [Str "ui",Space,Str "2",Str ".",Str "1",Str ".",Str "2"]]]]]]]
64+ [[Plain [Str "ui",Space,Str "2.1.1"]]
65+ ,[Plain [Str "ui",Space,Str "2.1.2"]]]]]]]
6666,Header 2 ("definition-list",[],[]) [Str "Definition",Space,Str "List"]
6767,DefinitionList
6868 [([Str "coffee"],
6969 [[Plain [Str "Hot",Space,Str "and",Space,Str "black"]]])
7070 ,([Str "tea"],
71− [[Plain [Str "Also",Space,Str "hot",Str ",",Space,Str "but",Space,Str "a",Space,Str "little",Space,Str "less",Space,Str "black"]]])
71+ [[Plain [Str "Also",Space,Str "hot,",Space,Str "but",Space,Str "a",Space,Str "little",Space,Str "less",Space,Str "black"]]])
7272 ,([Str "milk"],
73− [[Para [Str "Nourishing",Space,Str "beverage",Space,Str "for",Space,Str "baby",Space,Str "cows",Str "."]
74− ,Para [Str "Cold",Space,Str "drink",Space,Str "that",Space,Str "goes",Space,Str "great",Space,Str "with",Space,Str "cookies",Str "."]]])
73+ [[Para [Str "Nourishing",Space,Str "beverage",Space,Str "for",Space,Str "baby",Space,Str "cows."]
74+ ,Para [Str "Cold",Space,Str "drink",Space,Str "that",Space,Str "goes",Space,Str "great",Space,Str "with",Space,Str "cookies."]]])
7575 ,([Str "beer"],
7676 [[Plain [Str "fresh",Space,Str "and",Space,Str "bitter"]]])]
7777,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"]
78−,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "Hyphenated-words-are-ok",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "strange_underscore_notation",Str ".",LineBreak,Str "A",Space,Link [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
79−,Para [Emph [Strong [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]],LineBreak,Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Space,Str "and",Space,Emph [Strong [Str "that",Space,Str "one"]],Str ".",LineBreak,Strikeout [Str "This",Space,Str "is",Space,Str "strikeout",Space,Str "and",Space,Strong [Str "strong"]]]
80−,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts",Str ":",Space,Subscript [Str "here"],Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O",Str "."]
81−,Para [Str "Dashes",Space,Str ":",Space,Str "How",Space,Str "cool",Space,Str "\8212",Space,Str "automatic",Space,Str "dashes",Str "."]
82−,Para [Str "Elipses",Space,Str ":",Space,Str "He",Space,Str "thought",Space,Str "and",Space,Str "thought",Space,Str "\8230",Space,Str "and",Space,Str "then",Space,Str "thought",Space,Str "some",Space,Str "more",Str "."]
83−,Para [Str "Quotes",Space,Str "and",Space,Str "apostrophes",Space,Str ":",Space,Quoted DoubleQuote [Str "I",Str "\8217",Str "d",Space,Str "like",Space,Str "to",Space,Str "thank",Space,Str "you"],Space,Str "for",Space,Str "example",Str "."]
78+,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "Hyphenated-words-are-ok,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "strange_underscore_notation.",LineBreak,Str "A",Space,Link [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
79+,Para [Emph [Strong [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]],LineBreak,Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Space,Str "and",Space,Emph [Strong [Str "that",Space,Str "one"]],Str ".",LineBreak,Strikeout [Str "This",Space,Str "is",Space,Str "strikeout",Space,Str "and",Space,Strong [Str "strong"]]]
80+,Para [Str "Superscripts:",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Space,Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts:",Space,Subscript [Str "here"],Space,Str "H",Space,Subscript [Str "2"],Str "O,",Space,Str "H",Space,Subscript [Str "23"],Str "O,",Space,Str "H",Space,Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O."]
81+,Para [Str "Dashes",Space,Str ":",Space,Str "How",Space,Str "cool",Space,Str "\8212",Space,Str "automatic",Space,Str "dashes."]
82+,Para [Str "Elipses",Space,Str ":",Space,Str "He",Space,Str "thought",Space,Str "and",Space,Str "thought",Space,Str "\8230",Space,Str "and",Space,Str "then",Space,Str "thought",Space,Str "some",Space,Str "more."]
83+,Para [Str "Quotes",Space,Str "and",Space,Str "apostrophes",Space,Str ":",Space,Quoted DoubleQuote [Str "I\8217d",Space,Str "like",Space,Str "to",Space,Str "thank",Space,Str "you"],Space,Str "for",Space,Str "example."]
8484,Header 1 ("links",[],[]) [Str "Links"]
8585,Header 2 ("explicit",[],[]) [Str "Explicit"]
8686,Para [Str "Just",Space,Str "a",Space,Link [Str "url"] ("http://www.url.com","")]
8787,Para [Link [Str "Email",Space,Str "link"] ("mailto:nobody@nowhere.net","")]
8888,Para [Str "Automatic",Space,Str "linking",Space,Str "to",Space,Link [Str "http://www.example.com"] ("http://www.example.com",""),Str "."]
89−,Para [Link [Str "Example"] ("http://www.example.com/",""),Str ":",Space,Str "Example",Space,Str "of",Space,Str "a",Space,Str "link",Space,Str "followed",Space,Str "by",Space,Str "a",Space,Str "colon",Str "."]
90−,Para [Str "A",Space,Str "link",Link [Str "with",Space,Str "brackets"] ("http://www.example.com",""),Str "and",Space,Str "no",Space,Str "spaces",Str "."]
89+,Para [Link [Str "Example"] ("http://www.example.com/",""),Str ":",Space,Str "Example",Space,Str "of",Space,Str "a",Space,Str "link",Space,Str "followed",Space,Str "by",Space,Str "a",Space,Str "colon."]
90+,Para [Str "A",Space,Str "link",Link [Str "with",Space,Str "brackets"] ("http://www.example.com",""),Str "and",Space,Str "no",Space,Str "spaces."]
9191,Header 1 ("tables",[],[]) [Str "Tables"]
9292,Para [Str "Textile",Space,Str "allows",Space,Str "tables",Space,Str "with",Space,Str "and",Space,Str "without",Space,Str "headers",Space,Str ":"]
9393,Header 2 ("without-headers",[],[]) [Str "Without",Space,Str "headers"]
@@ -121,11 +121,11 @@ Pandoc (Meta {unMeta = fromList []})
121121 ,[Plain [Str "45"]]
122122 ,[Plain [Str "f"]]]]
123123,Header 1 ("images",[],[]) [Str "Images"]
124−,Para [Str "Textile",Space,Str "inline",Space,Str "image",Space,Str "syntax",Str ",",Space,Str "like",Space,LineBreak,Str "here",Space,Image [Str "this is the alt text"] ("this_is_an_image.png","this is the alt text"),LineBreak,Str "and",Space,Str "here",Space,Image [Str ""] ("this_is_an_image.png",""),Str "."]
124+,Para [Str "Textile",Space,Str "inline",Space,Str "image",Space,Str "syntax,",Space,Str "like",LineBreak,Str "here",Space,Image [Str "this is the alt text"] ("this_is_an_image.png","this is the alt text"),LineBreak,Str "and",Space,Str "here",Space,Image [Str ""] ("this_is_an_image.png",""),Str "."]
125125,Header 1 ("attributes",[],[]) [Str "Attributes"]
126−,Header 2 ("ident",["bar","foo"],[("style","color:red"),("lang","en")]) [Str "HTML",Space,Str "and",Space,Str "CSS",Space,Str "attributes",Space,Str "are",Space,Str "parsed",Space,Str "in",Space,Str "headers",Str "."]
126+,Header 2 ("ident",["bar","foo"],[("style","color:red"),("lang","en")]) [Str "HTML",Space,Str "and",Space,Str "CSS",Space,Str "attributes",Space,Str "are",Space,Str "parsed",Space,Str "in",Space,Str "headers."]
127127,Para [Str "as",Space,Str "well",Space,Str "as",Space,Strong [Str "inline",Space,Str "attributes"],Space,Str "of",Space,Str " all kind"]
128−,Para [Str "and",Space,Str "paragraph",Space,Str "attributes",Str ",",Space,Str "and",Space,Str "table",Space,Str "attributes",Str "."]
128+,Para [Str "and",Space,Str "paragraph",Space,Str "attributes,",Space,Str "and",Space,Str "table",Space,Str "attributes."]
129129,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]
130130 []
131131 [[[Plain [Str "name"]]
@@ -137,7 +137,7 @@ Pandoc (Meta {unMeta = fromList []})
137137,Header 1 ("entities",[],[]) [Str "Entities"]
138138,Para [Str "*",LineBreak,Str "&"]
139139,Header 1 ("raw-html",[],[]) [Str "Raw",Space,Str "HTML"]
140−,Para [Str "However",Str ",",Space,RawInline (Format "html") "<strong>",Space,Str "raw",Space,Str "HTML",Space,Str "inlines",Space,RawInline (Format "html") "</strong>",Space,Str "are",Space,Str "accepted",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str ":"]
140+,Para [Str "However,",Space,RawInline (Format "html") "<strong>",Space,Str "raw",Space,Str "HTML",Space,Str "inlines",Space,RawInline (Format "html") "</strong>",Space,Str "are",Space,Str "accepted,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str ":"]
141141,RawBlock (Format "html") "<div class=\"foobar\">"
142142,Para [Str "any",Space,Strong [Str "Raw",Space,Str "HTML",Space,Str "Block"],Space,Str "with",Space,Str "bold"]
143143,RawBlock (Format "html") "</div>"
@@ -145,9 +145,9 @@ Pandoc (Meta {unMeta = fromList []})
145145,RawBlock (Format "html") "<div>"
146146,Para [Str "inlined"]
147147,RawBlock (Format "html") "</div>"
148−,Para [Str "as",Space,Str "well",Str "."]
148+,Para [Str "as",Space,Str "well."]
149149,BulletList
150− [[Plain [Str "this",Space,Str "<",Str "div",Str ">",Space,Str "won",Str "\8217",Str "t",Space,Str "produce",Space,Str "raw",Space,Str "html",Space,Str "blocks",Space,Str "<",Str "/div",Str ">"]]
150+ [[Plain [Str "this",Space,Str "<div>",Space,Str "won\8217t",Space,Str "produce",Space,Str "raw",Space,Str "html",Space,Str "blocks",Space,Str "</div>"]]
151151 ,[Plain [Str "but",Space,Str "this",Space,RawInline (Format "html") "<strong>",Space,Str "will",Space,Str "produce",Space,Str "inline",Space,Str "html",Space,RawInline (Format "html") "</strong>"]]]
152152,Para [Str "Can",Space,Str "you",Space,Str "prove",Space,Str "that",Space,Str "2",Space,Str "<",Space,Str "3",Space,Str "?"]
153153,Header 1 ("raw-latex",[],[]) [Str "Raw",Space,Str "LaTeX"]
@@ -156,12 +156,11 @@ Pandoc (Meta {unMeta = fromList []})
156156,Para [Str "and",Space,Str "for",Space,RawInline (Format "latex") "\\emph{inlines}",Str "."]
157157,Header 1 ("acronyms-and-marks",[],[]) [Str "Acronyms",Space,Str "and",Space,Str "marks"]
158158,Para [Str "PBS (Public Broadcasting System)"]
159−,Para [Str "Hi",Str "\8482"]
159+,Para [Str "Hi\8482"]
160160,Para [Str "Hi",Space,Str "\8482"]
161−,Para [Str "\174",Space,Str "Hi",Str "\174"]
162−,Para [Str "Hi",Str "\169",Str "2008",Space,Str "\169",Space,Str "2008"]
161+,Para [Str "\174",Space,Str "Hi\174"]
162+,Para [Str "Hi\169\&2008",Space,Str "\169",Space,Str "2008"]
163163,Header 1 ("footnotes",[],[]) [Str "Footnotes"]
164−,Para [Str "A",Space,Str "note",Str ".",Note [Para [Str "The",Space,Str "note",LineBreak,Str "is",Space,Str "here",Str "!"]],Space,Str "Another",Space,Str "note",Note [Para [Str "Other",Space,Str "note",Str "."]],Str "."]
164+,Para [Str "A",Space,Str "note.",Note [Para [Str "The",Space,Str "note",LineBreak,Str "is",Space,Str "here!"]],Space,Str "Another",Space,Str "note",Note [Para [Str "Other",Space,Str "note."]],Str "."]
165165,Header 1 ("comment-blocks",[],[]) [Str "Comment",Space,Str "blocks"]
166−,Null
167−,Para [Str "not",Space,Str "a",Space,Str "comment",Str "."]]
166+,Para [Str "not",Space,Str "a",Space,Str "comment."]]
tests/textile-reader.textile+3−3
@@ -139,8 +139,8 @@ _*This is strong and em.*_
139139So is *_this_* word and __**that one**__.
140140-This is strikeout and *strong*-
141141
142−Superscripts: a[^bc^]d a^*hello*^ a[^hello there^].
143−Subscripts: ~here~ H[~2~]O, H[~23~]O, H[~many of them~]O.
142+Superscripts: a[^bc^]d a ^*hello*^ a[^hello there^].
143+Subscripts: ~here~ H[ ~2~]O, H[ ~23~]O, H[ ~many of them~]O.
144144
145145Dashes : How cool -- automatic dashes.
146146
@@ -187,7 +187,7 @@ h2. With headers
187187
188188h1. Images
189189
190−Textile inline image syntax, like
190+Textile inline image syntax, like
191191here !this_is_an_image.png(this is the alt text)!
192192and here !this_is_an_image.png!.
193193