content: {-# LANGUAGE OverloadedStrings #-}
  {- |
     Module      : Tests.Readers.Org.Block.Header
     Copyright   : © 2014-2024 Albert Krewinkel
     License     : GNU GPL, version 2 or above
  
     Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>
     Stability   : alpha
     Portability : portable
  
  Test parsing of org lists.
  -}
  module Tests.Readers.Org.Block.List (tests) where
  
  import Data.Text (Text)
  import Test.Tasty (TestTree)
  import Tests.Helpers ((=?>), purely, test)
  import Tests.Readers.Org.Shared ((=:), spcSep)
  import Text.Pandoc (ReaderOptions (readerExtensions),
                      Extension (Ext_fancy_lists), def, enableExtension,
                      getDefaultExtensions, readOrg)
  import Text.Pandoc.Builder
  import qualified Data.Text as T
  
  orgFancyLists :: Text -> Pandoc
  orgFancyLists = purely $
    let extensionsFancy = enableExtension Ext_fancy_lists (getDefaultExtensions "org")
    in readOrg def{ readerExtensions = extensionsFancy }
  
  tests :: [TestTree]
  tests =
    [ "Simple Bullet Lists" =:
        ("- Item1\n" <>
         "- Item2\n") =?>
        bulletList [ plain "Item1"
                   , plain "Item2"
                   ]
  
    , "Simple Bullet List with Ignored Counter Cookie" =:
        ("- [@4] Item1\n" <>
         "- Item2\n") =?>
        bulletList [ plain "Item1"
                   , plain "Item2"
                   ]
  
    , "Indented Bullet Lists" =:
        ("   - Item1\n" <>
         "   - Item2\n") =?>
        bulletList [ plain "Item1"
                   , plain "Item2"
                   ]
  
    , "Unindented *" =:
        ("- Item1\n" <>
         "* Item2\n") =?>
        bulletList [ plain "Item1"
                   ] <>
        headerWith ("item2", [], []) 1 "Item2"
  
    , "Multi-line Bullet Lists" =:
        ("- *Fat\n" <>
         "  Tony*\n" <>
         "- /Sideshow\n" <>
         " Bob/") =?>
        bulletList [ plain $ strong ("Fat" <> softbreak <> "Tony")
                   , plain $ emph ("Sideshow" <> softbreak <> "Bob")
                   ]
  
    , "Nested Bullet Lists" =:
        ("- Discovery\n" <>
         "  + One More Time\n" <>
         "  + Harder, Better, Faster, Stronger\n" <>
         "- Homework\n" <>
         "  + Around the World\n"<>
         "- Human After All\n" <>
         "  + Technologic\n" <>
         "  + Robot Rock\n") =?>
        bulletList [ mconcat
                     [ plain "Discovery"
                     , bulletList [ plain ("One" <> space <>
                                           "More" <> space <>
                                           "Time")
                                  , plain ("Harder," <> space <>
                                           "Better," <> space <>
                                           "Faster," <> space <>
                                           "Stronger")
                                  ]
                     ]
                   , mconcat
                     [ plain "Homework"
                     , bulletList [ plain ("Around" <> space <>
                                           "the" <> space <>
                                           "World")
                                  ]
                     ]
                   , mconcat
                     [ plain ("Human" <> space <> "After" <> space <> "All")
                     , bulletList [ plain "Technologic"
                                  , plain ("Robot" <> space <> "Rock")
                                  ]
                     ]
                   ]
  
    , "Bullet List with Decreasing Indent" =:
         "  - Discovery\n\
          \ - Human After All\n" =?>
         mconcat [ bulletList [ plain "Discovery" ]
                 , bulletList [ plain ("Human" <> space <> "After" <> space <> "All")]
                 ]
  
    , "Header follows Bullet List" =:
        "  - Discovery\n\
         \  - Human After All\n\
         \* Homework" =?>
        mconcat [ bulletList [ plain "Discovery"
                             , plain ("Human" <> space <> "After" <> space <> "All")
                             ]
                , headerWith ("homework", [], []) 1 "Homework"
                ]
  
    , "Bullet List Unindented with trailing Header" =:
        "- Discovery\n\
         \- Homework\n\
         \* NotValidListItem" =?>
        mconcat [ bulletList [ plain "Discovery"
                             , plain "Homework"
                             ]
                , headerWith ("notvalidlistitem", [], []) 1 "NotValidListItem"
                ]
  
    , "Empty bullet points" =:
        T.unlines [ "-"
                  , "- "
                  ] =?>
        bulletList [ plain "", plain "" ]
  
    , "Task list" =:
      T.unlines [ "- [ ] nope"
                , "- [X] yup"
                , "- [-] started"
                , "  1. [X] sure"
                , "  2. [ ] nuh-uh"
                ] =?>
      bulletList [ plain "☐ nope", plain "☒ yup"
                 , mconcat [ plain "☐ started"
                           , orderedList [plain "☒ sure", plain "☐ nuh-uh"]
                           ]
                 ]
  
    , "Task List with Counter Cookies" =:
      T.unlines [ "- [ ] nope"
                , "- [@9] [X] yup"
                , "- [@a][-] started"
                , "  1. [@3][X] sure"
                , "  2. [@b] [ ] nuh-uh"
                ] =?>
      bulletList [ plain "☐ nope", plain "☒ yup"
                 , mconcat [ plain "☐ started"
                           , orderedListWith
                             (3, DefaultStyle, DefaultDelim)
                             [plain "☒ sure", plain "☐ nuh-uh"]
                           ]
                 ]
  
    , test orgFancyLists "Task with alphabetical markers and counter cookie" $
      T.unlines [ "- [ ] nope"
                , "- [@9] [X] yup"
                , "- [@a][-] started"
                , "  a) [@D][X] sure"
                , "  b) [@8] [ ] nuh-uh"
                ] =?>
      bulletList [ plain "☐ nope", plain "☒ yup"
                 , mconcat [ plain "☐ started"
                           , orderedListWith
                             (4, LowerAlpha, OneParen)
                             [plain "☒ sure", plain "☐ nuh-uh"]
                           ]
                 ]
  
    , "Simple Ordered List" =:
        ("1. Item1\n" <>
         "2. Item2\n") =?>
        let listStyle = (1, DefaultStyle, DefaultDelim)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , test orgFancyLists "Simple Ordered List with fancy lists extension" $
        ("1. Item1\n" <>
         "2. Item2\n") =?>
        let listStyle = (1, Decimal, Period)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , test orgFancyLists "Simple Ordered List with lower alpha marker" $
        ("a) Item1\n" <>
         "b) Item2\n") =?>
        let listStyle = (1, LowerAlpha, OneParen)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , test orgFancyLists "Simple Ordered List with upper and lower alpha markers" $
        ("A. Item1\n" <>
         "b) Item2\n") =?>
        let listStyle = (1, UpperAlpha, Period)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , "Simple Ordered List with Counter Cookie" =:
        ("1. [@1234] Item1\n" <>
         "2. Item2\n") =?>
        let listStyle = (1234, DefaultStyle, DefaultDelim)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , "Simple Ordered List with Alphabetical Counter Cookie" =:
        ("1. [@c] Item1\n" <>
         "2. Item2\n") =?>
        let listStyle = (3, DefaultStyle, DefaultDelim)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , "Simple Ordered List with Ignored Counter Cookie" =:
        ("1. Item1\n" <>
         "2. [@4] Item2\n") =?>
        let listStyle = (1, DefaultStyle, DefaultDelim)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , "Simple Ordered List with Parens" =:
        ("1) Item1\n" <>
         "2) Item2\n") =?>
        let listStyle = (1, DefaultStyle, DefaultDelim)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , "Indented Ordered List" =:
        (" 1. Item1\n" <>
         " 2. Item2\n") =?>
        let listStyle = (1, DefaultStyle, DefaultDelim)
            listStructure = [ plain "Item1"
                            , plain "Item2"
                            ]
        in orderedListWith listStyle listStructure
  
    , "Empty ordered list item" =:
        T.unlines [ "1."
                  , "3. "
                  ] =?>
        orderedList [ plain "", plain "" ]
  
    , test orgFancyLists "Empty ordered list item with fancy lists extension" $
        T.unlines [ "a."
                  , "2. "
                  ] =?>
        orderedListWith (1, LowerAlpha, Period) [ plain "", plain "" ]
  
    , "Empty ordered list item with counter cookie" =:
        T.unlines [ "1. [@5]"
                  , "3. [@e] "
                  ] =?>
        let listStyle = (5, DefaultStyle, DefaultDelim)
        in orderedListWith listStyle [ plain "", plain "" ]
  
    , "Nested Ordered Lists" =:
        ("1. One\n" <>
         "   1. One-One\n" <>
         "   2. One-Two\n" <>
         "2. Two\n" <>
         "   1. Two-One\n"<>
         "   2. Two-Two\n") =?>
        let listStyle = (1, DefaultStyle, DefaultDelim)
            listStructure = [ mconcat
                              [ plain "One"
                              , orderedList [ plain "One-One"
                                            , plain "One-Two"
                                            ]
                              ]
                            , mconcat
                              [ plain "Two"
                              , orderedList [ plain "Two-One"
                                            , plain "Two-Two"
                                            ]
                              ]
                            ]
        in orderedListWith listStyle listStructure
  
    , "Ordered List in Bullet List" =:
        ("- Emacs\n" <>
         "  1. Org\n") =?>
        bulletList [ plain "Emacs" <>
                     orderedList [ plain "Org"]
                   ]
  
    , "Bullet List in Ordered List" =:
        ("1. GNU\n" <>
         "   - Freedom\n") =?>
        orderedList [ plain "GNU" <> bulletList [ plain "Freedom" ] ]
  
    , "Definition List" =:
        T.unlines [ "- PLL :: phase-locked loop"
                  , "- TTL ::"
                  , "  transistor-transistor logic"
                  , "- PSK :: phase-shift keying"
                  , ""
                  , "  a digital modulation scheme"
                  ] =?>
        definitionList [ ("PLL", [ plain $ "phase-locked" <> space <> "loop" ])
                       , ("TTL", [ plain $ "transistor-transistor" <> space <>
                                             "logic" ])
                       , ("PSK", [ mconcat
                                   [ para $ "phase-shift" <> space <> "keying"
                                   , para $ spcSep [ "a", "digital"
                                                   , "modulation", "scheme" ]
                                   ]
                                 ])
                       ]
    , "Definition list with multi-word term" =:
      " - Elijah Wood :: He plays Frodo" =?>
       definitionList [ ("Elijah" <> space <> "Wood", [plain $ "He" <> space <> "plays" <> space <> "Frodo"])]
    , "Compact definition list" =:
         T.unlines [ "- ATP :: adenosine 5' triphosphate"
                   , "- DNA :: deoxyribonucleic acid"
                   , "- PCR :: polymerase chain reaction"
                   , ""
                   ] =?>
        definitionList
        [ ("ATP", [ plain $ spcSep [ "adenosine", "5'", "triphosphate" ] ])
        , ("DNA", [ plain $ spcSep [ "deoxyribonucleic", "acid" ] ])
        , ("PCR", [ plain $ spcSep [ "polymerase", "chain", "reaction" ] ])
        ]
  
    , "Definition List With Trailing Header" =:
        "- definition :: list\n\
        \- cool :: defs\n\
        \* header" =?>
        mconcat [ definitionList [ ("definition", [plain "list"])
                                 , ("cool", [plain "defs"])
                                 ]
                , headerWith ("header", [], []) 1 "header"
                ]
  
    , "Definition lists double-colon markers must be surrounded by whitespace" =:
        "- std::cout" =?>
        bulletList [ plain "std::cout" ]
  
    , "Loose bullet list" =:
       T.unlines [ "- apple"
                 , ""
                 , "- orange"
                 , ""
                 , "- peach"
                 ] =?>
        bulletList [ para "apple"
                   , para "orange"
                   , para "peach"
                   ]
  
    , "Recognize preceding paragraphs in non-list contexts" =:
        T.unlines [ "CLOSED: [2015-10-19 Mon 15:03]"
                  , "- Note taken on [2015-10-19 Mon 13:24]"
                  ] =?>
        mconcat [ para "CLOSED: [2015-10-19 Mon 15:03]"
                , bulletList [ plain "Note taken on [2015-10-19 Mon 13:24]" ]
                ]
  
    , "Markup after header and list" =:
        T.unlines [ "* headline"
                  , "- list"
                  , ""
                  , "~variable name~"
                  ] =?>
        mconcat [ headerWith ("headline", [], []) 1 "headline"
                , bulletList [ plain "list" ]
                , para (code "variable name")
                ]
    ]
  