git.iko.soy/typeable/pandoc
on master help sign in
Write FB2 lists without nesting blocks inside <p> (#4004)

According to FB2 XML schema <empty-line /> cannot be placed inside <p>. Linux FBReader can't display such paragraphs, e.g. any "loose" lists produced by pandoc prior to this commit. Besides that, FB2 writer placed <p> inside <p> when writing nested lists, this commit fixes the bug. Also this commit removes leading non-breaking space from ordered lists for consistency with bullet lists. Definition lists are not affected at all.

commit3263d0d7c4052307ce38f342800197dec5a3fba0 authorAlexander <ilabdsf@gmail.com> dateSun 29 Oct 2017, 21:46 (9 years ago) parente8be4b0
3 files changed+119−99
src/Text/Pandoc/Writers/FB2.hs+32−16 test/fb2/basic.fb2+1−1 test/writer.fb2+86−82
src/Text/Pandoc/Writers/FB2.hs+32−16
@@ -338,13 +338,13 @@ blockToXml (LineBlock lns) =
338338blockToXml (OrderedList a bss) = do
339339 state <- get
340340 let pmrk = parentListMarker state
341− let markers = map ((pmrk ++ " ") ++) $ orderedListMarkers a
341+ let markers = map (pmrk ++) $ orderedListMarkers a
342342 let mkitem mrk bs = do
343− modify (\s -> s { parentListMarker = mrk })
344− itemtext <- cMapM blockToXml . paraToPlain $ bs
343+ modify (\s -> s { parentListMarker = mrk ++ " "})
344+ item <- cMapM blockToXml $ plainToPara $ indentBlocks (mrk ++ " ") bs
345345 modify (\s -> s { parentListMarker = pmrk }) -- old parent marker
346− return . el "p" $ [ txt mrk, txt " " ] ++ itemtext
347− zipWithM mkitem markers bss
346+ return item
347+ concat <$> (zipWithM mkitem markers bss)
348348blockToXml (BulletList bss) = do
349349 state <- get
350350 let level = parentBulletLevel state
@@ -354,10 +354,10 @@ blockToXml (BulletList bss) = do
354354 let mrk = prefix ++ bullets !! (level `mod` length bullets)
355355 let mkitem bs = do
356356 modify (\s -> s { parentBulletLevel = level+1 })
357− itemtext <- cMapM blockToXml . paraToPlain $ bs
357+ item <- cMapM blockToXml $ plainToPara $ indentBlocks (mrk ++ " ") bs
358358 modify (\s -> s { parentBulletLevel = level }) -- restore bullet level
359− return $ el "p" $ txt (mrk ++ " ") : itemtext
360− mapM mkitem bss
359+ return item
360+ cMapM mkitem bss
361361blockToXml (DefinitionList defs) =
362362 cMapM mkdef defs
363363 where
@@ -408,19 +408,24 @@ blockToXml Null = return []
408408paraToPlain :: [Block] -> [Block]
409409paraToPlain [] = []
410410paraToPlain (Para inlines : rest) =
411− let p = Plain (inlines ++ [LineBreak])
412− in p : paraToPlain rest
411+ Plain (inlines) : Plain ([LineBreak]) : paraToPlain rest
413412paraToPlain (p:rest) = p : paraToPlain rest
414413
414+-- Replace plain text with paragraphs and add line break after paragraphs.
415+-- It is used to convert plain text from tight list items to paragraphs.
416+plainToPara :: [Block] -> [Block]
417+plainToPara [] = []
418+plainToPara (Plain inlines : rest) =
419+ Para (inlines) : plainToPara rest
420+plainToPara (Para inlines : rest) =
421+ Para (inlines) : Plain [LineBreak] : plainToPara rest
422+plainToPara (p:rest) = p : plainToPara rest
423+
415424-- Simulate increased indentation level. Will not really work
416425-- for multi-line paragraphs.
417−indent :: Block -> Block
418−indent = indentBlock
426+indentPrefix :: String -> Block -> Block
427+indentPrefix spacer = indentBlock
419428 where
420− -- indentation space
421− spacer :: String
422− spacer = replicate 4 ' '
423− --
424429 indentBlock (Plain ins) = Plain (Str spacer:ins)
425430 indentBlock (Para ins) = Para (Str spacer:ins)
426431 indentBlock (CodeBlock a s) =
@@ -434,6 +439,17 @@ indent = indentBlock
434439 indentLines ins = let lns = split isLineBreak ins :: [[Inline]]
435440 in intercalate [LineBreak] $ map (Str spacer:) lns
436441
442+indent :: Block -> Block
443+indent = indentPrefix spacer
444+ where
445+ -- indentation space
446+ spacer :: String
447+ spacer = replicate 4 ' '
448+
449+indentBlocks :: String -> [Block] -> [Block]
450+indentBlocks _ [] = []
451+indentBlocks prefix (x:xs) = indentPrefix prefix x : map (indentPrefix $ replicate (length prefix) ' ') xs
452+
437453-- | Convert a Pandoc's Inline element to FictionBook XML representation.
438454toXml :: PandocMonad m => Inline -> FBM m [Content]
439455toXml (Str s) = return [txt s]
test/fb2/basic.fb2+1−1
@@ -1,3 +1,3 @@
11<?xml version="1.0" encoding="UTF-8"?>
2−<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><title><p>Top-level title</p></title><section><title><p>Section</p></title><section><title><p>Subsection</p></title><p>This <emphasis>emphasized</emphasis> <strong>strong</strong> <code>verbatim</code> markdown. See this link<a l:href="#l1" type="note"><sup>[1]</sup></a>.</p><p>Ordered list:</p><p> 1. one</p><p> 2. two</p><p> 3. three</p><cite><p>Blockquote is for citatons.</p></cite><empty-line /><p><code>Code</code></p><p><code>block</code></p><p><code>is</code></p><p><code>for</code></p><p><code>code.</code></p><empty-line /><p><strikethrough>Strikeout</strikethrough> is Pandoc’s extension. Superscript and subscripts too: H<sub>2</sub>O is a liquid<a l:href="#n2" type="note"><sup>[2]</sup></a>. 2<sup>10</sup> is 1024.</p><p>Math is another Pandoc extension: <code>E = m c^2</code>.</p></section></section></section></body><body name="notes"><section id="l1"><title><p>1</p></title><p><code>http://example.com/</code></p></section><section id="n2"><title><p>2</p></title><p>Sometimes.</p></section></body></FictionBook>
2+<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink"><description><title-info /><document-info><program-used>pandoc</program-used></document-info></description><body><title><p /></title><annotation><p></p></annotation><section><title><p>Top-level title</p></title><section><title><p>Section</p></title><section><title><p>Subsection</p></title><p>This <emphasis>emphasized</emphasis> <strong>strong</strong> <code>verbatim</code> markdown. See this link<a l:href="#l1" type="note"><sup>[1]</sup></a>.</p><p>Ordered list:</p><p>1. one</p><p>2. two</p><p>3. three</p><cite><p>Blockquote is for citatons.</p></cite><empty-line /><p><code>Code</code></p><p><code>block</code></p><p><code>is</code></p><p><code>for</code></p><p><code>code.</code></p><empty-line /><p><strikethrough>Strikeout</strikethrough> is Pandoc’s extension. Superscript and subscripts too: H<sub>2</sub>O is a liquid<a l:href="#n2" type="note"><sup>[2]</sup></a>. 2<sup>10</sup> is 1024.</p><p>Math is another Pandoc extension: <code>E = m c^2</code>.</p></section></section></section></body><body name="notes"><section id="l1"><title><p>1</p></title><p><code>http://example.com/</code></p></section><section id="n2"><title><p>2</p></title><p>Sometimes.</p></section></body></FictionBook>
33
test/writer.fb2+86−82
@@ -115,8 +115,8 @@
115115</p>
116116<empty-line />
117117<p>A list:</p>
118−<p> 1. item one</p>
119−<p> 2. item two</p>
118+<p>1. item one</p>
119+<p>2. item two</p>
120120<p>Nested block quotes:</p>
121121<cite>
122122<p>nested</p>
@@ -191,127 +191,131 @@
191191<p>• asterisk 2</p>
192192<p>• asterisk 3</p>
193193<p>Asterisks loose:</p>
194−<p>• asterisk 1<empty-line />
195−</p>
196−<p>• asterisk 2<empty-line />
197−</p>
198−<p>• asterisk 3<empty-line />
199−</p>
194+<p>• asterisk 1</p>
195+<empty-line />
196+<p>• asterisk 2</p>
197+<empty-line />
198+<p>• asterisk 3</p>
199+<empty-line />
200200<p>Pluses tight:</p>
201201<p>• Plus 1</p>
202202<p>• Plus 2</p>
203203<p>• Plus 3</p>
204204<p>Pluses loose:</p>
205−<p>• Plus 1<empty-line />
206−</p>
207−<p>• Plus 2<empty-line />
208−</p>
209−<p>• Plus 3<empty-line />
210−</p>
205+<p>• Plus 1</p>
206+<empty-line />
207+<p>• Plus 2</p>
208+<empty-line />
209+<p>• Plus 3</p>
210+<empty-line />
211211<p>Minuses tight:</p>
212212<p>• Minus 1</p>
213213<p>• Minus 2</p>
214214<p>• Minus 3</p>
215215<p>Minuses loose:</p>
216−<p>• Minus 1<empty-line />
217−</p>
218−<p>• Minus 2<empty-line />
219−</p>
220−<p>• Minus 3<empty-line />
221−</p>
216+<p>• Minus 1</p>
217+<empty-line />
218+<p>• Minus 2</p>
219+<empty-line />
220+<p>• Minus 3</p>
221+<empty-line />
222222</section>
223223<section>
224224<title>
225225<p>Ordered</p>
226226</title>
227227<p>Tight:</p>
228−<p> 1. First</p>
229−<p> 2. Second</p>
230−<p> 3. Third</p>
228+<p>1. First</p>
229+<p>2. Second</p>
230+<p>3. Third</p>
231231<p>and:</p>
232−<p> 1. One</p>
233−<p> 2. Two</p>
234−<p> 3. Three</p>
232+<p>1. One</p>
233+<p>2. Two</p>
234+<p>3. Three</p>
235235<p>Loose using tabs:</p>
236−<p> 1. First<empty-line />
237−</p>
238−<p> 2. Second<empty-line />
239−</p>
240−<p> 3. Third<empty-line />
241−</p>
236+<p>1. First</p>
237+<empty-line />
238+<p>2. Second</p>
239+<empty-line />
240+<p>3. Third</p>
241+<empty-line />
242242<p>and using spaces:</p>
243−<p> 1. One<empty-line />
244−</p>
245−<p> 2. Two<empty-line />
246−</p>
247−<p> 3. Three<empty-line />
248−</p>
243+<p>1. One</p>
244+<empty-line />
245+<p>2. Two</p>
246+<empty-line />
247+<p>3. Three</p>
248+<empty-line />
249249<p>Multiple paragraphs:</p>
250−<p> 1. Item 1, graf one.<empty-line />Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.<empty-line />
251−</p>
252−<p> 2. Item 2.<empty-line />
253−</p>
254−<p> 3. Item 3.<empty-line />
255−</p>
250+<p>1. Item 1, graf one.</p>
251+<empty-line />
252+<p>   Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.</p>
253+<empty-line />
254+<p>2. Item 2.</p>
255+<empty-line />
256+<p>3. Item 3.</p>
257+<empty-line />
256258</section>
257259<section>
258260<title>
259261<p>Nested</p>
260262</title>
261−<p>• Tab<p>◦ Tab<p>* Tab</p>
262−</p>
263−</p>
263+<p>• Tab</p>
264+<p>◦ Tab</p>
265+<p>* Tab</p>
264266<p>Here’s another:</p>
265−<p> 1. First</p>
266−<p> 2. Second:<p>   • Fee</p>
267+<p>1. First</p>
268+<p>2. Second:</p>
269+<p>   • Fee</p>
267270<p>   • Fie</p>
268271<p>   • Foe</p>
269−</p>
270−<p> 3. Third</p>
272+<p>3. Third</p>
271273<p>Same thing but with paragraphs:</p>
272−<p> 1. First<empty-line />
273−</p>
274−<p> 2. Second:<empty-line />
274+<p>1. First</p>
275+<empty-line />
276+<p>2. Second:</p>
277+<empty-line />
275278<p>   • Fee</p>
276279<p>   • Fie</p>
277280<p>   • Foe</p>
278−</p>
279−<p> 3. Third<empty-line />
280−</p>
281+<p>3. Third</p>
282+<empty-line />
281283</section>
282284<section>
283285<title>
284286<p>Tabs and spaces</p>
285287</title>
286−<p>• this is a list item indented with tabs<empty-line />
287−</p>
288−<p>• this is a list item indented with spaces<empty-line />
289−<p>◦ this is an example list item indented with tabs<empty-line />
290−</p>
291−<p>◦ this is an example list item indented with spaces<empty-line />
292−</p>
293−</p>
288+<p>• this is a list item indented with tabs</p>
289+<empty-line />
290+<p>• this is a list item indented with spaces</p>
291+<empty-line />
292+<p>◦ this is an example list item indented with tabs</p>
293+<empty-line />
294+<p>◦ this is an example list item indented with spaces</p>
295+<empty-line />
294296</section>
295297<section>
296298<title>
297299<p>Fancy list markers</p>
298300</title>
299−<p> (2) begins with 2</p>
300−<p> (3) and now 3<empty-line />with a continuation<empty-line />
301−<p> (3) iv. sublist with roman numerals, starting with 4</p>
302−<p> (3) v. more items<p> (3) v. (A) a subsublist</p>
303−<p> (3) v. (B) a subsublist</p>
304−</p>
305−</p>
301+<p>(2) begins with 2</p>
302+<p>(3) and now 3</p>
303+<empty-line />
304+<p>    with a continuation</p>
305+<empty-line />
306+<p>(3) iv. sublist with roman numerals, starting with 4</p>
307+<p>(3) v. more items</p>
308+<p>(3) v. (A) a subsublist</p>
309+<p>(3) v. (B) a subsublist</p>
306310<p>Nesting:</p>
307−<p> A. Upper Alpha<p> A. I. Upper Roman.<p> A. I. (6) Decimal start with 6<p> A. I. (6) c) Lower alpha with paren</p>
308−</p>
309−</p>
310−</p>
311+<p>A. Upper Alpha</p>
312+<p>A. I. Upper Roman.</p>
313+<p>A. I. (6) Decimal start with 6</p>
314+<p>A. I. (6) c) Lower alpha with paren</p>
311315<p>Autonumbering:</p>
312−<p> 1. Autonumber.</p>
313−<p> 2. More.<p> 2. 1. Nested.</p>
314−</p>
316+<p>1. Autonumber.</p>
317+<p>2. More.</p>
318+<p>2. 1. Nested.</p>
315319<p>Should not be a list item:</p>
316320<p>M.A. 2007</p>
317321<p>B. Williams</p>
@@ -427,8 +431,8 @@
427431<strong>orange</strong>
428432</p>
429433<p>    orange fruit<empty-line />
430−<p> 1. sublist</p>
431−<p> 2. sublist</p>
434+<p>1. sublist</p>
435+<p>2. sublist</p>
432436</p>
433437</section>
434438<section>
@@ -753,7 +757,7 @@
753757</a>
754758</p>
755759</cite>
756−<p> 1. And in list items.<a l:href="#n32" type="note">
760+<p>1. And in list items.<a l:href="#n32" type="note">
757761<sup>[32]</sup>
758762</a>
759763</p>