content: {-# LANGUAGE OverloadedStrings   #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE TupleSections #-}
  {- |
     Module      : Tests.Readers.DokuWiki
     Copyright   : © 2018-2020 Alexander Krotov
     License     : GNU GPL, version 2 or above
  
     Maintainer  : Alexander Krotov
     Stability   : alpha
     Portability : portable
  
  Tests for DokuWiki reader.
  -}
  module Tests.Readers.DokuWiki (tests) where
  
  import Data.Text (Text)
  import qualified Data.Text as T
  import Test.Tasty
  import Test.Tasty.HUnit (HasCallStack)
  import Tests.Helpers
  import Text.Pandoc
  import Text.Pandoc.Arbitrary ()
  import Text.Pandoc.Builder
  
  dokuwiki :: Text -> Pandoc
  dokuwiki = purely $ readDokuWiki def{ readerStandalone = True }
  
  infix 4 =:
  (=:) :: (ToString c, HasCallStack)
       => String -> (Text, c) -> TestTree
  (=:) = test dokuwiki
  
  tests :: [TestTree]
  tests = [ testGroup "inlines"
            [ "Bold" =:
              "**bold**" =?>
              para (strong "bold")
            , "Italic" =:
              "//italic//" =?>
              para (emph "italic")
            , "Underlined" =:
              "__underlined__" =?>
              para (underline "underlined")
            , "Monospaced" =:
              "''monospaced''" =?>
              para (code "monospaced")
            , "Monospaced with nowiki" =:
              "''%%monospaced%%''" =?>
              para (code "monospaced")
            , "Combined" =:
              "**__//''combine''//__**" =?>
              para (strong $ underline $ emph $ code "combine")
            , "Nowiki" =:
              T.unlines [ "<nowiki>"
                        , "This is some text which contains addresses like this: http://www.splitbrain.org and **formatting**, but nothing is done with it."
                        , "</nowiki>"
                        ] =?>
              para "This is some text which contains addresses like this: http://www.splitbrain.org and **formatting**, but nothing is done with it."
            , "Percent" =:
              "The same is true for %%//__this__ text// with a smiley ;-)%%." =?>
              para "The same is true for //__this__ text// with a smiley ;-)."
            , "Subscript" =:
              "<sub>subscript</sub>" =?>
              para (subscript "subscript")
            , "Superscript" =:
              "<sup>superscript</sup>" =?>
              para (superscript "superscript")
            , "Deleted" =:
              "<del>deleted</del>" =?>
              para (strikeout "deleted")
            , "Inline code" =:
              "foo <code java>public static void main</code> bar" =?>
              para (text "foo") <> codeBlockWith ("", ["java"], []) "public static void main"
                <> para (text "bar")
            , "Inline file" =:
              "foo <file></code></file> bar" =?>
              para (text "foo") <> codeBlock "</code>" <> para (text "bar")
            , "Inline HTML" =:
              "<html>\nThis is some <span style=\"color:red;font-size:150%;\">inline HTML</span>\n</html>" =?>
              para (rawInline "html" "\nThis is some <span style=\"color:red;font-size:150%;\">inline HTML</span>\n")
            , "Inline PHP" =:
              "<php>echo '<p>Hello World</p>';</php>" =?>
              para (rawInline "html" "<?php echo '<p>Hello World</p>'; ?>")
            , "Linebreak" =:
              T.unlines [ "This is some text with some linebreaks\\\\ Note that the"
                        , "two backslashes are only recognized at the end of a line\\\\"
                        , "or followed by\\\\ a whitespace \\\\this happens without it."
                        ] =?>
              para ("This is some text with some linebreaks" <> linebreak <> "Note that the\n" <>
                    "two backslashes are only recognized at the end of a line" <> linebreak <>
                    "or followed by" <> linebreak <> "a whitespace \\\\this happens without it.")
            , testGroup "External links"
              [ "Autolink" =:
                "http://www.google.com" =?>
                para (link "http://www.google.com" "" (str "http://www.google.com"))
              , "Link without description" =:
                "[[https://example.com]]" =?>
                para (link "https://example.com" "" (str "https://example.com"))
              , "Link with description" =:
                "[[http://www.google.com|This Link points to google]]" =?>
                para (link "http://www.google.com" "" (text "This Link points to google"))
              , "Trim whitespace around link and description" =:
                "[[   http://www.google.com    |   This Link points to google   ]]" =?>
                para (link "http://www.google.com" "" (text "This Link points to google"))
              , "Email address" =:
                "<andi@splitbrain.org>" =?>
                para (link "mailto:andi@splitbrain.org" "" (str "andi@splitbrain.org"))
              ]
            , testGroup "Internal links"
              [ "Current namespace" =:
                "[[example]]" =?>
                para (link "example" "" (str "example"))
              , "Current namespace starting with dot" =:
                "[[.example]]" =?>
                para (link "example" "" (str ".example"))
              , "Current namespace starting with dot and colon" =:
                "[[.:example]]" =?>
                para (link "example" "" (str "example"))
              , "Root namespace" =:
                "[[:example]]" =?>
                para (link "/example" "" (str "example"))
              , "Parent namespace" =:
                "[[..example]]" =?>
                para (link "../example" "" (str "..example"))
              , "Parent namespace with colon" =:
                "[[..:example]]" =?>
                para (link "../example" "" (str "example"))
              , "Beneath the root namespace" =:
                "[[wiki:example]]" =?>
                para (link "/wiki/example" "" (str "example"))
              , "Explicitly beneath the root namespace" =:
                "[[:wiki:example]]" =?>
                para (link "/wiki/example" "" (str "example"))
              ]
            , testGroup "Interwiki links"
              [ "Interwiki without description" =:
                "[[doku>DokuWiki]]" =?>
                para (link "https://www.dokuwiki.org/DokuWiki" "" (str "DokuWiki"))
              , "Interwiki link with description" =:
                "[[doku>toolbar|quickbuttons]]" =?>
                para (link "https://www.dokuwiki.org/toolbar" "" (str "quickbuttons"))
              ]
            , "Footnote" =:
              "((This is a footnote))" =?>
              para (note (para "This is a footnote"))
            , testGroup "Images"
              [ "Image" =:
                "{{image.jpg}}" =?>
                para (image "image.jpg" "" (str "image.jpg"))
              , "Image with caption" =:
                "{{image.png|This is the caption}}" =?>
                para (image "image.png" "" "This is the caption")
              , "Image with } in caption" =:
                "{{image.png|There is an } in the caption}}" =?>
                para (image "image.png" "" "There is an } in the caption")
              , "Wiki namespace starting with dot" =:
                "{{.wiki:image.jpg}}" =?>
                para (image "wiki/image.jpg" "" (str "image.jpg"))
              , "Left aligned image" =:
                "{{wiki:dokuwiki-128.png }}" =?>
                para (imageWith ("", ["align-left"], []) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))
              , "Right aligned image" =:
                "{{ wiki:dokuwiki-128.png}}" =?>
                para (imageWith ("", ["align-right"], []) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))
              , "Centered image" =:
                "{{ wiki:dokuwiki-128.png }}" =?>
                para (imageWith ("", ["align-center"], []) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))
              , "Image with width" =:
                "{{wiki:dokuwiki-128.png?50}}" =?>
                para (imageWith ("", [], [("width", "50"), ("query", "?50")]) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))
              , "Image with width and height" =:
                "{{wiki:dokuwiki-128.png?nocache&50x100}}" =?>
                para (imageWith ("", [], [("width", "50"), ("height", "100"), ("query", "?nocache&50x100")]) "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))
              , "Linkonly" =:
                "{{wiki:dokuwiki-128.png?linkonly}}" =?>
                para (link "/wiki/dokuwiki-128.png" "" (str "dokuwiki-128.png"))
              ]
            , "Ignore ~~NOTOC~~" =:
              "Here is a ~~NOTOC~~ macro" =?>
              para "Here is a macro"
            , "Ignore ~~NOCACHE~~" =:
              "Here is a ~~NOCACHE~~ macro" =?>
              para "Here is a macro"
            ]
          , testGroup "Sectioning"
            [ "Headline level 1" =:
              "====== Headline Level 1 ======" =?>
              header 1 "Headline Level 1"
            , "Headline level 2" =:
              "===== Headline Level 2 =====" =?>
              header 2 "Headline Level 2"
            , "Headline level 3" =:
              "==== Headline Level 3 ====" =?>
              header 3 "Headline Level 3"
            , "Headline level 4" =:
              "=== Headline Level 4 ===" =?>
              header 4 "Headline Level 4"
            , "Headline level 5" =:
              "== Headline Level 5 ==" =?>
              header 5 "Headline Level 5"
            , "Only two closing = are required" =:
              "====== Headline Level 1 ==" =?>
              header 1 "Headline Level 1"
            , "One closing = is not enough" =:
              "====== Headline Level 1 =" =?>
              para "====== Headline Level 1 ="
            , "One closing = is not enough" =:
              "== Headline with = sign ==" =?>
              header 5 "Headline with = sign"
            ]
          , "Horizontal line" =:
            "----" =?>
            horizontalRule
          , testGroup "Lists"
            [ "Unordered list" =:
              T.unlines [ "  * This is a list"
                        , "  * The second item"
                        , "    * You may have different levels"
                        , "  * Another item"
                        ] =?>
              bulletList [ plain "This is a list"
                         , plain "The second item" <>
                           bulletList [ plain "You may have different levels" ]
                         , plain "Another item"
                         ]
            , "Ordered list" =:
              T.unlines [ "  - The same list but ordered"
                        , "  - Another item"
                        , "    - Just use indentation for deeper levels"
                        , "  - That's it"
                        ] =?>
              orderedList [ plain "The same list but ordered"
                          , plain "Another item" <>
                            orderedList [ plain "Just use indentation for deeper levels" ]
                          , plain "That's it"
                          ]
            , "Multiline list items" =: -- https://www.dokuwiki.org/faq:lists
              T.unlines [ "  - first item"
                        , "  - second item with linebreak\\\\ second line"
                        , "  - third item with code: <code>"
                        , "some code"
                        , "comes here"
                        , "</code>"
                        , "  - fourth item"
                        ] =?>
              orderedList [ plain "first item"
                          , plain ("second item with linebreak" <> linebreak <> " second line")
                          , plain "third item with code: " <> codeBlock "some code\ncomes here\n"
                          , plain "fourth item"
                          ]
            ]
          , "Block HTML" =:
            T.unlines [ "<HTML>"
                      , "<p style=\"border:2px dashed red;\">And this is some block HTML</p>"
                      , "</HTML>"
                      ] =?>
            rawBlock "html" "<p style=\"border:2px dashed red;\">And this is some block HTML</p>\n"
          , "Block PHP" =:
            T.unlines [ "<PHP>"
                      , "echo '<p>Hello World</p>';"
                      , "</PHP>"
                      ] =?>
            rawBlock "html" "<?php echo '<p>Hello World</p>';\n ?>"
          , "Quote" =:
            T.unlines [ "> foo"
                      , ">no space is required after >"
                      , "> bar"
                      , ">> baz"
                      , "> bat"
                      ] =?>
            blockQuote (plain (text "foo" <> linebreak <>
                          text "no space is required after >" <> linebreak <>
                          text "bar") <>
                        blockQuote (plain "baz") <>
                        plain "bat")
          , "Code block" =:
            T.unlines [ "<code>"
                      , "foo bar baz"
                      , "</code>"
                      ] =?>
            codeBlock "foo bar baz\n"
          , "Java code block" =:
            T.unlines [ "<code java>"
                      , "public static void main"
                      , "</code>"
                      ] =?>
            codeBlockWith ("", ["java"], []) "public static void main\n"
          , "File with filename and no language" =:
            T.unlines [ "<file - foo.bar>"
                      , "file contents"
                      , "</file>"
                      ] =?>
            codeBlock "file contents\n"
          , "Table" =:
            T.unlines [ "| foo | bar |"
                      , "| bat | baz |"
                      ] =?>
            simpleTable [] [[plain "foo", plain "bar"]
                           ,[plain "bat", plain "baz"]]
          , "Table with header" =:
            T.unlines [ "^ foo ^ bar ^"
                      , "| bat | baz |"
                      ] =?>
            simpleTable [plain "foo", plain "bar"] [[plain "bat", plain "baz"]]
          , "Table with alignment" =:
            T.unlines [ "^ 0  ^  1  ^  2 ^ 3 ^"
                      , "| a  | b   | c  |d  |"
                      ] =?>
            table emptyCaption
                  (map (, ColWidthDefault) [AlignLeft, AlignCenter, AlignRight, AlignDefault])
                  (TableHead nullAttr
                            [Row nullAttr . map (simpleCell . plain) $ ["0", "1", "2", "3"]])
                  [TableBody nullAttr 0 []
                            [Row nullAttr . map (simpleCell . plain) $ ["a", "b", "c", "d"]]]
                  (TableFoot nullAttr [])
          , "Table with colspan" =:
            T.unlines [ "^ 0,0 ^ 0,1 ^ 0,2 ^"
                      , "| 1,0 | 1,1 ||"
                      , "| 2,0 | 2,1 | 2,2 |"
                      ] =?>
            simpleTable [plain "0,0", plain "0,1", plain "0,2"]
                        [[plain "1,0", plain "1,1", mempty]
                        ,[plain "2,0", plain "2,1", plain "2,2"]
                        ]
          , "Indented code block" =:
            T.unlines [ "foo"
                      , "  bar"
                      , "    bat"
                      , "baz"
                      ] =?>
            para "foo" <>
            codeBlock "bar\n  bat\n" <>
            para "baz"
          ]
  