content: {-# LANGUAGE FlexibleContexts    #-}
  
  {-# LANGUAGE ScopedTypeVariables #-}
  {- |
     Module      : Text.Pandoc.Readers.CSV
     Copyright   : Copyright (C) 2006-2024 John MacFarlane
     License     : GNU GPL, version 2 or above
  
     Maintainer  : John MacFarlane <jgm@berkeley.edu>
     Stability   : alpha
     Portability : portable
  
  Conversion from CSV or TSV to a 'Pandoc' table.
  -}
  module Text.Pandoc.Readers.CSV (
    readCSV,
    readTSV
  ) where
  import qualified Data.Text as T
  import Text.Pandoc.CSV (parseCSV, defaultCSVOptions, CSVOptions(..))
  import Text.Pandoc.Definition
  import qualified Text.Pandoc.Builder as B
  import Text.Pandoc.Class (PandocMonad)
  import Text.Pandoc.Sources (ToSources(..), sourcesToText)
  import Text.Pandoc.Options (ReaderOptions)
  import Control.Monad.Except (throwError)
  import Data.Text (Text)
  import Data.List (intersperse)
  import Text.Pandoc.Parsing (fromParsecError)
  
  readCSV :: (PandocMonad m, ToSources a)
          => ReaderOptions -- ^ Reader options
          -> a
          -> m Pandoc
  readCSV _opts s = do
    readCSVWith defaultCSVOptions $ sourcesToText $ toSources s
  
  readTSV :: (PandocMonad m, ToSources a)
          => ReaderOptions -- ^ Reader options
          -> a
          -> m Pandoc
  readTSV _opts s = do
    readCSVWith tsvOpts $ sourcesToText $ toSources s
   where
    tsvOpts = CSVOptions{
      csvDelim = '\t',
      csvQuote = Nothing,
      csvKeepSpace = False,
      csvEscape = Nothing }
  
  readCSVWith :: PandocMonad m
              => CSVOptions
              -> Text
              -> m Pandoc
  readCSVWith csvopts txt = do
    case parseCSV csvopts txt of
      Right (r:rs) -> return $ B.doc $ B.table capt
                                               (zip aligns widths)
                                               (TableHead nullAttr hdrs)
                                               [TableBody nullAttr 0 [] rows]
                                               (TableFoot nullAttr [])
         where capt = B.emptyCaption
               numcols = length r
               toplain = B.simpleCell . B.plain . mconcat .
                         intersperse B.linebreak . map B.text . T.lines
               toRow = Row nullAttr . map toplain
               toHeaderRow l = [toRow l | not (null l)]
               hdrs = toHeaderRow r
               rows = map toRow rs
               aligns = replicate numcols AlignDefault
               widths = replicate numcols ColWidthDefault
      Right []     -> return $ B.doc mempty
      Left e       -> throwError $ fromParsecError (toSources [("",txt)]) e
  