content: {-# LANGUAGE OverloadedStrings #-}
  {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
  module Tests.Writers.Markdown (tests) where
  
  import Data.Text (unpack)
  import Test.Tasty
  import Test.Tasty.HUnit (HasCallStack)
  import Tests.Helpers
  import Text.Pandoc
  import Text.Pandoc.Arbitrary ()
  import Text.Pandoc.Builder
  
  defopts :: WriterOptions
  defopts = def
    { writerExtensions = pandocExtensions
    , writerSetextHeaders = True }
  
  markdown :: (ToPandoc a) => a -> String
  markdown = unpack . purely (writeMarkdown defopts) . toPandoc
  
  markdownWithOpts :: (ToPandoc a) => WriterOptions -> a -> String
  markdownWithOpts opts x = unpack . purely (writeMarkdown opts) $ toPandoc x
  
  {-
    "my test" =: X =?> Y
  
  is shorthand for
  
    test markdown "my test" $ X =?> Y
  
  which is in turn shorthand for
  
    test markdown "my test" (X,Y)
  -}
  
  infix 4 =:
  (=:) :: (ToString a, ToPandoc a, HasCallStack)
       => String -> (a, String) -> TestTree
  (=:) = test markdown
  
  tests :: [TestTree]
  tests = [ "indented code after list"
               =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test")
               =?> "1.  one\n\n    two\n\n<!-- -->\n\n    test"
          , "list with tight sublist"
               =: bulletList [ plain "foo" <> bulletList [ plain "bar" ],
                               plain "baz" ]
               =?> "- foo\n  - bar\n- baz\n"
          , "emph/strong with spaces (#10696)"
               =: emph (str "f" <> strong (space <> str "d" <> space)) <> str "l" =?>
               "*f **d*** l"
          ] ++ [noteTests] ++ [shortcutLinkRefsTests]
  
  {-
  
  Testing with the following text:
  
  First Header
  ============
  
  This is a footnote.[^1] And this is a [link](https://www.google.com).
  
  > A note inside a block quote.[^2]
  >
  > A second paragraph.
  
  Second Header
  =============
  
  Some more text.
  
  
  [^1]: Down here.
  
  [^2]: The second note.
  
  -}
  
  noteTestDoc :: Blocks
  noteTestDoc =
    header 1 "First Header" <>
    para ("This is a footnote." <>
          note (para "Down here.") <>
          " And this is a " <>
          link "https://www.google.com" "" "link" <>
          ".") <>
    blockQuote (para ("A note inside a block quote." <>
                      note (para "The second note.")) <>
                para "A second paragraph.") <>
    header 1 "Second Header" <>
    para "Some more text."
  
  
  
  noteTests :: TestTree
  noteTests = testGroup "note and reference location"
    [ test (markdownWithOpts defopts)
      "footnotes at the end of a document" $
      noteTestDoc =?>
      unlines [ "First Header"
                 , "============"
                 , ""
                 , "This is a footnote.[^1] And this is a [link](https://www.google.com)."
                 , ""
                 , "> A note inside a block quote.[^2]"
                 , ">"
                 , "> A second paragraph."
                 , ""
                 , "Second Header"
                 , "============="
                 , ""
                 , "Some more text."
                 , ""
                 , "[^1]: Down here."
                 , ""
                 , "[^2]: The second note."
                 ]
    , test (markdownWithOpts defopts{writerReferenceLocation=EndOfBlock})
      "footnotes at the end of blocks" $
      noteTestDoc =?>
      unlines [ "First Header"
                 , "============"
                 , ""
                 , "This is a footnote.[^1] And this is a [link](https://www.google.com)."
                 , ""
                 , "[^1]: Down here."
                 , ""
                 , "> A note inside a block quote.[^2]"
                 , ">"
                 , "> A second paragraph."
                 , ""
                 , "[^2]: The second note."
                 , ""
                 , "Second Header"
                 , "============="
                 , ""
                 , "Some more text."
                 ]
    , test (markdownWithOpts defopts{writerReferenceLocation=EndOfBlock, writerReferenceLinks=True})
      "footnotes and reference links at the end of blocks" $
      noteTestDoc =?>
      unlines [ "First Header"
                 , "============"
                 , ""
                 , "This is a footnote.[^1] And this is a [link]."
                 , ""
                 , "[^1]: Down here."
                 , ""
                 , "  [link]: https://www.google.com"
                 , ""
                 , "> A note inside a block quote.[^2]"
                 , ">"
                 , "> A second paragraph."
                 , ""
                 , "[^2]: The second note."
                 , ""
                 , "Second Header"
                 , "============="
                 , ""
                 , "Some more text."
                 ]
    , test (markdownWithOpts defopts{writerReferenceLocation=EndOfSection})
      "footnotes at the end of section" $
      noteTestDoc =?>
      unlines [ "First Header"
                 , "============"
                 , ""
                 , "This is a footnote.[^1] And this is a [link](https://www.google.com)."
                 , ""
                 , "> A note inside a block quote.[^2]"
                 , ">"
                 , "> A second paragraph."
                 , ""
                 , "[^1]: Down here."
                 , ""
                 , "[^2]: The second note."
                 , ""
                 , "Second Header"
                 , "============="
                 , ""
                 , "Some more text."
                 ]
  
    ]
  
  shortcutLinkRefsTests :: TestTree
  shortcutLinkRefsTests =
    let infix 4 =:
        (=:) :: (ToString a, ToPandoc a, HasCallStack)
  
          => String -> (a, String) -> TestTree
        (=:) = test (purely (writeMarkdown defopts{writerReferenceLinks = True}) . toPandoc)
    in testGroup "Shortcut reference links"
       [ "Simple link (shortcutable)"
             =: para (link "/url" "title" "foo")
             =?> "[foo]\n\n  [foo]: /url \"title\""
       , "Followed by another link (unshortcutable)"
             =: para (link "/url1" "title1" "first"
                    <> link "/url2" "title2" "second")
             =?> unlines [ "[first][][second]"
                         , ""
                         , "  [first]: /url1 \"title1\""
                         , "  [second]: /url2 \"title2\""
                         ]
       , "Followed by space and another link (unshortcutable)"
             =: para (link "/url1" "title1" "first" <> " "
                    <> link "/url2" "title2" "second")
             =?> unlines [ "[first][] [second]"
                         , ""
                         , "  [first]: /url1 \"title1\""
                         , "  [second]: /url2 \"title2\""
                         ]
       , "Reference link is used multiple times (unshortcutable)"
             =: para (link "/url1" "" "foo" <> link "/url2" "" "foo"
                                               <> link "/url3" "" "foo")
             =?> unlines [ "[foo][][foo][1][foo][2]"
                         , ""
                         , "  [foo]: /url1"
                         , "  [1]: /url2"
                         , "  [2]: /url3"
                         ]
       , "Reference link is used multiple times (unshortcutable)"
             =: para (link "/url1" "" "foo" <> " " <> link "/url2" "" "foo"
                                               <> " " <> link "/url3" "" "foo")
             =?> unlines [ "[foo][] [foo][1] [foo][2]"
                         , ""
                         , "  [foo]: /url1"
                         , "  [1]: /url2"
                         , "  [2]: /url3"
                         ]
       , "Reference link is followed by text in brackets"
            =:  para (link "/url" "" "link" <> "[text in brackets]")
            =?> unlines [ "[link][]\\[text in brackets\\]"
                        , ""
                        , "  [link]: /url"
                        ]
       , "Reference link is followed by space and text in brackets"
            =:  para (link "/url" "" "link" <> " [text in brackets]")
            =?> unlines [ "[link][] \\[text in brackets\\]"
                        , ""
                        , "  [link]: /url"
                        ]
       , "Reference link is followed by RawInline"
            =: para (link "/url" "" "link" <> rawInline "markdown" "[rawText]")
            =?> unlines [ "[link][][rawText]"
                        , ""
                        , "  [link]: /url"
                        ]
       , "Reference link is followed by space and RawInline"
            =: para (link "/url" "" "link" <> space <> rawInline "markdown" "[rawText]")
            =?> unlines [ "[link][] [rawText]"
                        , ""
                        , "  [link]: /url"
                        ]
       , "Reference link is followed by RawInline with space"
            =: para (link "/url" "" "link" <> rawInline "markdown" " [rawText]")
            =?> unlines [ "[link][] [rawText]"
                        , ""
                        , "  [link]: /url"
                        ]
       , "Reference link is followed by citation"
            =: para (link "/url" "" "link" <> cite [Citation "author" [] [] NormalCitation 0 0] (str "[@author]"))
            =?> unlines [ "[link][][@author]"
                        , ""
                        , "  [link]: /url"
                        ]
       , "Reference link is followed by space and citation"
            =: para (link "/url" "" "link" <> space <> cite [Citation "author" [] [] NormalCitation 0 0] (str "[@author]"))
            =?> unlines [ "[link][] [@author]"
                        , ""
                        , "  [link]: /url"
                        ]
       ]
  