From 81088281dea1283159f7e0cf3d9c2a5082e06d8a Mon Sep 17 00:00:00 2001
From: John MacFarlane <jgm@berkeley.edu>
Date: Sun, 13 Jul 2014 16:04:29 -0700
Subject: [PATCH] DokuWiki writer:  Use raw HTML for complex lists...

as in the mediawiki writer.  The dokuwiki markup isn't able
to handle multiple block-level items within a list item, except
in a few special cases (e.g. code blocks, and these must be started
on the same line as the preceding paragraph).  So we fall back to
raw HTML for these.

Perhaps there is a better solution.  We can "fake" multiple
paragraphs within list items using hard line breaks (`\\`), but
we must keep everything on one line.

(#1398)
---
 src/Text/Pandoc/Writers/DokuWiki.hs | 53 +++++++++++++++++++++-------
 tests/writer.dokuwiki               | 54 +++++++++++++++++++----------
 2 files changed, 75 insertions(+), 32 deletions(-)

diff --git a/src/Text/Pandoc/Writers/DokuWiki.hs b/src/Text/Pandoc/Writers/DokuWiki.hs
index c7b723a21..aef247164 100644
--- a/src/Text/Pandoc/Writers/DokuWiki.hs
+++ b/src/Text/Pandoc/Writers/DokuWiki.hs
@@ -113,11 +113,11 @@ blockToDokuWiki opts (Para [Image txt (src,'f':'i':'g':':':tit)]) = do
   return $ "{{:" ++ src ++ opt ++ "}}\n"
 
 blockToDokuWiki opts (Para inlines) = do
-  useTags <- get >>= return . stUseTags
-  indent <- get >>= return . stIndent
+  indent <- gets stIndent
+  useTags <- gets stUseTags
   contents <- inlineListToDokuWiki opts inlines
   return $ if useTags
-              then  "<p>" ++ contents ++ "</p>"
+              then "<HTML><p></HTML>" ++ contents ++ "<HTML></p></HTML>"
               else contents ++ if null indent then "\n" else ""
 
 blockToDokuWiki _ (RawBlock f str)
@@ -180,7 +180,7 @@ blockToDokuWiki opts x@(BulletList items) = do
         modify $ \s -> s { stUseTags = True }
         contents <- mapM (listItemToDokuWiki opts) items
         modify $ \s -> s { stUseTags = oldUseTags }
-        return $ "<ul>\n" ++ vcat contents ++ "</ul>\n"
+        return $ "<HTML><ul></HTML>\n" ++ vcat contents ++ "<HTML></ul></HTML>\n"
      else do
         modify $ \s -> s { stIndent = stIndent s ++ "  " }
         contents <- mapM (listItemToDokuWiki opts) items
@@ -196,7 +196,7 @@ blockToDokuWiki opts x@(OrderedList attribs items) = do
         modify $ \s -> s { stUseTags = True }
         contents <- mapM (orderedListItemToDokuWiki opts) items
         modify $ \s -> s { stUseTags = oldUseTags }
-        return $ "<ol" ++ listAttribsToString attribs ++ ">\n" ++ vcat contents ++ "</ol>\n"
+        return $ "<HTML><ol" ++ listAttribsToString attribs ++ "></HTML>\n" ++ vcat contents ++ "<HTML></ol></HTML>\n"
      else do
         modify $ \s -> s { stIndent = stIndent s ++ "  " }
         contents <- mapM (orderedListItemToDokuWiki opts) items
@@ -215,7 +215,7 @@ blockToDokuWiki opts x@(DefinitionList items) = do
         modify $ \s -> s { stUseTags = True }
         contents <- mapM (definitionListItemToDokuWiki opts) items
         modify $ \s -> s { stUseTags = oldUseTags }
-        return $ "<dl>\n" ++ vcat contents ++ "</dl>\n"
+        return $ "<HTML><dl></HTML>\n" ++ vcat contents ++ "<HTML></dl></HTML>\n"
      else do
         modify $ \s -> s { stIndent = stIndent s ++ "  " }
         contents <- mapM (definitionListItemToDokuWiki opts) items
@@ -241,7 +241,7 @@ listItemToDokuWiki opts items = do
   contents <- blockListToDokuWiki opts items
   useTags <- get >>= return . stUseTags
   if useTags
-     then return $ "<li>" ++ contents ++ "</li>"
+     then return $ "<HTML><li></HTML>" ++ contents ++ "<HTML></li></HTML>"
      else do
        indent <- get >>= return . stIndent
        return $ indent ++ "* " ++ contents
@@ -253,7 +253,7 @@ orderedListItemToDokuWiki opts items = do
   contents <- blockListToDokuWiki opts items
   useTags <- get >>= return . stUseTags
   if useTags
-     then return $ "<li>" ++ contents ++ "</li>"
+     then return $ "<HTML><li></HTML>" ++ contents ++ "<HTML></li></HTML>"
      else do
        indent <- get >>= return . stIndent
        return $ indent ++ "- " ++ contents
@@ -267,8 +267,8 @@ definitionListItemToDokuWiki opts (label, items) = do
   contents <- mapM (blockListToDokuWiki opts) items
   useTags <- get >>= return . stUseTags
   if useTags
-     then return $ "<dt>" ++ labelText ++ "</dt>\n" ++
-           (intercalate "\n" $ map (\d -> "<dd>" ++ d ++ "</dd>") contents)
+     then return $ "<HTML><dt></HTML>" ++ labelText ++ "<HTML></dt></HTML>\n" ++
+           (intercalate "\n" $ map (\d -> "<HTML><dd></HTML>" ++ d ++ "<HTML></dd></HTML>") contents)
      else do
        indent <- get >>= return . stIndent
        return $ indent ++ "* **" ++ labelText ++ "** " ++ concat contents
@@ -277,11 +277,38 @@ definitionListItemToDokuWiki opts (label, items) = do
 isSimpleList :: Block -> Bool
 isSimpleList x =
   case x of
-       BulletList _                     -> True
-       OrderedList _ _                  -> True
-       DefinitionList _                 -> True
+       BulletList items                 -> all isSimpleListItem items
+       OrderedList (num, sty, _) items  -> all isSimpleListItem items &&
+                                            num == 1 && sty `elem` [DefaultStyle, Decimal]
+       DefinitionList items             -> all isSimpleListItem $ concatMap snd items
        _                                -> False
 
+-- | True if list item can be handled with the simple wiki syntax.  False if
+--   HTML tags will be needed.
+isSimpleListItem :: [Block] -> Bool
+isSimpleListItem []  = True
+isSimpleListItem [x] =
+  case x of
+       Plain _           -> True
+       Para  _           -> True
+       BulletList _      -> isSimpleList x
+       OrderedList _ _   -> isSimpleList x
+       DefinitionList _  -> isSimpleList x
+       _                 -> False
+isSimpleListItem [x, y] | isPlainOrPara x =
+  case y of
+       BulletList _      -> isSimpleList y
+       OrderedList _ _   -> isSimpleList y
+       DefinitionList _  -> isSimpleList y
+       _                 -> False
+isSimpleListItem _ = False
+
+isPlainOrPara :: Block -> Bool
+isPlainOrPara (Plain _) = True
+isPlainOrPara (Para  _) = True
+isPlainOrPara _         = False
+
+
 -- | Concatenates strings with line breaks between them.
 vcat :: [String] -> String
 vcat = intercalate "\n"
diff --git a/tests/writer.dokuwiki b/tests/writer.dokuwiki
index 983db2274..e1844d62a 100644
--- a/tests/writer.dokuwiki
+++ b/tests/writer.dokuwiki
@@ -157,10 +157,11 @@ and using spaces:
 
 Multiple paragraphs:
 
-  - Item 1, graf one.
-Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.
-  - Item 2.
-  - Item 3.
+<HTML><ol style="list-style-type: decimal;"></HTML>
+<HTML><li></HTML><HTML><p></HTML>Item 1, graf one.<HTML></p></HTML>
+<HTML><p></HTML>Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.<HTML></p></HTML><HTML></li></HTML>
+<HTML><li></HTML><HTML><p></HTML>Item 2.<HTML></p></HTML><HTML></li></HTML>
+<HTML><li></HTML><HTML><p></HTML>Item 3.<HTML></p></HTML><HTML></li></HTML><HTML></ol></HTML>
 
 ===== Nested =====
 
@@ -195,20 +196,32 @@ Same thing but with paragraphs:
 
 ===== Fancy list markers =====
 
-  - begins with 2
-  - and now 3
-with a continuation
-    - sublist with roman numerals, starting with 4
-    - more items
-      - a subsublist
-      - a subsublist
+<HTML><ol start="2" style="list-style-type: decimal;"></HTML>
+<HTML><li></HTML>begins with 2<HTML></li></HTML>
+<HTML><li></HTML><HTML><p></HTML>and now 3<HTML></p></HTML>
+<HTML><p></HTML>with a continuation<HTML></p></HTML>
+<HTML><ol start="4" style="list-style-type: lower-roman;"></HTML>
+<HTML><li></HTML>sublist with roman numerals, starting with 4<HTML></li></HTML>
+<HTML><li></HTML>more items
+<HTML><ol style="list-style-type: upper-alpha;"></HTML>
+<HTML><li></HTML>a subsublist<HTML></li></HTML>
+<HTML><li></HTML>a subsublist<HTML></li></HTML><HTML></ol></HTML>
+<HTML></li></HTML><HTML></ol></HTML>
+<HTML></li></HTML><HTML></ol></HTML>
 
 Nesting:
 
-  - Upper Alpha
-    - Upper Roman.
-      - Decimal start with 6
-        - Lower alpha with paren
+<HTML><ol style="list-style-type: upper-alpha;"></HTML>
+<HTML><li></HTML>Upper Alpha
+<HTML><ol style="list-style-type: upper-roman;"></HTML>
+<HTML><li></HTML>Upper Roman.
+<HTML><ol start="6" style="list-style-type: decimal;"></HTML>
+<HTML><li></HTML>Decimal start with 6
+<HTML><ol start="3" style="list-style-type: lower-alpha;"></HTML>
+<HTML><li></HTML>Lower alpha with paren<HTML></li></HTML><HTML></ol></HTML>
+<HTML></li></HTML><HTML></ol></HTML>
+<HTML></li></HTML><HTML></ol></HTML>
+<HTML></li></HTML><HTML></ol></HTML>
 
 Autonumbering:
 
@@ -247,11 +260,14 @@ Loose:
 
 Multiple blocks with italics:
 
-  * **//apple//** red fruit
-contains seeds, crisp, pleasant to taste
-  * **//orange//** orange fruit
+<HTML><dl></HTML>
+<HTML><dt></HTML>//apple//<HTML></dt></HTML>
+<HTML><dd></HTML><HTML><p></HTML>red fruit<HTML></p></HTML>
+<HTML><p></HTML>contains seeds, crisp, pleasant to taste<HTML></p></HTML><HTML></dd></HTML>
+<HTML><dt></HTML>//orange//<HTML></dt></HTML>
+<HTML><dd></HTML><HTML><p></HTML>orange fruit<HTML></p></HTML>
 <code>{ orange code block }</code>
-> orange block quote
+> <HTML><p></HTML>orange block quote<HTML></p></HTML><HTML></dd></HTML><HTML></dl></HTML>
 
 Multiple definitions, tight: