@@ -35,6 +35,7 @@ module Text.Pandoc.Pretty (
3535 , render
3636 , cr
3737 , blankline
38+ , blanklines
3839 , space
3940 , text
4041 , char
@@ -100,7 +101,7 @@ data D = Text Int String
100101 | BreakingSpace
101102 | CarriageReturn
102103 | NewLine
103− | BlankLine
104+ | BlankLines Int -- number of blank lines
104105 deriving (Show)
105106
106107newtype Doc = Doc { unDoc :: Seq D }
@@ -113,7 +114,7 @@ isBlank :: D -> Bool
113114isBlank BreakingSpace = True
114115isBlank CarriageReturn = True
115116isBlank NewLine = True
116−isBlank BlankLine = True
117+isBlank (BlankLines _) = True
117118isBlank (Text _ (c:_)) = isSpace c
118119isBlank _ = False
119120
@@ -190,7 +191,7 @@ vsep = foldr ($+$) empty
190191nestle :: Doc -> Doc
191192nestle (Doc d) = Doc $ go d
192193 where go x = case viewl x of
193− (BlankLine :< rest) -> go rest
194+ (BlankLines _ :< rest) -> go rest
194195 (NewLine :< rest) -> go rest
195196 _ -> x
196197
@@ -203,7 +204,7 @@ chomp d = Doc (fromList dl')
203204 go (BreakingSpace : xs) = go xs
204205 go (CarriageReturn : xs) = go xs
205206 go (NewLine : xs) = go xs
206− go (BlankLine : xs) = go xs
207+ go (BlankLines _ : xs) = go xs
207208 go (Prefixed s d' : xs) = Prefixed s (chomp d') : xs
208209 go xs = xs
209210
@@ -216,9 +217,10 @@ outp off s | off < 0 = do -- offset < 0 means newline characters
216217 let pref = reverse $ dropWhile isSpace $ reverse rawpref
217218 modify $ \st -> st{ output = fromString pref : output st
218219 , column = column st + realLength pref }
220+ let numnewlines = length $ takeWhile (=='\n') $ reverse s
219221 modify $ \st -> st { output = fromString s : output st
220222 , column = 0
221− , newlines = newlines st + 1 }
223+ , newlines = newlines st + numnewlines }
222224outp off s = do -- offset >= 0 (0 might be combining char)
223225 st' <- get
224226 let pref = prefix st'
@@ -277,15 +279,11 @@ renderList (BeforeNonBlank d : xs) =
277279 | otherwise -> renderDoc d >> renderList xs
278280 [] -> renderList xs
279281
280−renderList (BlankLine : xs) = do
282+renderList (BlankLines num : xs) = do
281283 st <- get
282284 case output st of
283− _ | newlines st > 1 || null xs -> return ()
284− _ | column st == 0 -> do
285− outp (-1) "\n"
286− _ -> do
287− outp (-1) "\n"
288− outp (-1) "\n"
285+ _ | newlines st > num || null xs -> return ()
286+ | otherwise -> replicateM_ (1 + num - newlines st) (outp (-1) "\n")
289287 renderList xs
290288
291289renderList (CarriageReturn : xs) = do
@@ -302,7 +300,7 @@ renderList (NewLine : xs) = do
302300
303301renderList (BreakingSpace : CarriageReturn : xs) = renderList (CarriageReturn:xs)
304302renderList (BreakingSpace : NewLine : xs) = renderList (NewLine:xs)
305−renderList (BreakingSpace : BlankLine : xs) = renderList (BlankLine:xs)
303+renderList (BreakingSpace : BlankLines n : xs) = renderList (BlankLines n:xs)
306304renderList (BreakingSpace : BreakingSpace : xs) = renderList (BreakingSpace:xs)
307305renderList (BreakingSpace : xs) = do
308306 let isText (Text _ _) = True
@@ -383,9 +381,13 @@ cr = Doc $ singleton CarriageReturn
383381
384382-- | Inserts a blank line unless one exists already.
385383-- (@blankline <> blankline@ has the same effect as @blankline@.
386−-- If you want multiple blank lines, use @text "\\n\\n"@.
387384blankline :: Doc
388−blankline = Doc $ singleton BlankLine
385+blankline = Doc $ singleton (BlankLines 1)
386+
387+-- | Inserts a blank lines unless they exists already.
388+-- (@blanklines m <> blanklines n@ has the same effect as @blankline (max m n)@.
389+blanklines :: Int -> Doc
390+blanklines n = Doc $ singleton (BlankLines n)
389391
390392-- | Uses the specified string as a prefix for every line of
391393-- the inside document (except the first, if not at the beginning