{-# LANGUAGE CPP #-}
module Main where
import Data.Spreadsheet as S
import Control.Monad.Exception.Asynchronous.Lazy as AsExc
import Control.Monad (liftM)
import Data.Monoid (mempty)
import Data.Char (toUpper)
import Data.List (isSuffixOf)
import Text.Pandoc.JSON
import Text.Pandoc.Definition
import Text.Pandoc.Builder (Inlines, Blocks, toList, fromList, table, para, str)
#if defined(INLINE_MARKDOWN)
import Text.Pandoc.Readers.Markdown
import Text.Pandoc.Options
#endif
main :: IO ()
main = toJSONFilter placeTable
placeTable :: Block -> IO [Block]
placeTable (CodeBlock (_, cls, kvs) txt) | "table" `elem` cls = do
csv <- case lookup "file" kvs of
Just name -> readFile name
Nothing -> return ""
let header = case lookup "header" kvs of
Just "yes" -> True
_ -> False
let toAlign c = case toUpper c of
'L' -> AlignLeft
'R' -> AlignRight
'C' -> AlignCenter
_ -> AlignDefault
let aligns = case lookup "aligns" kvs of
Just as -> map toAlign as
Nothing -> repeat AlignDefault
let capt = case lookup "caption" kvs of
Just c -> strToInlines c
Nothing -> mempty
let qc = case lookup "quotechar" kvs of
Just q -> head q
Nothing -> '"'
let sep = case lookup "delimiter" kvs of
Just d -> if head d == '\\'
then case head (tail d) of
't' -> '\t'
's' -> ' '
_ -> '\\'
else head d
Nothing -> ','
let s' = if null txt
then csv
else txt ++ "\n" ++ csv
let s = if isSuffixOf "\n" s'
then s'
else s' ++ "\n"
return $ toList $ csvToTable header aligns capt qc sep s
placeTable a = return [a]
-- | Convert a CSV String to a Pandoc Table
simpleCsvToTable :: String -> Blocks
simpleCsvToTable s = csvToTable False (repeat AlignDefault) mempty '"' ',' s
-- | Convert a bunch of options and a CSV String to a Pandoc Table
csvToTable :: Bool -- ^ interpret first row as headers
-> [Alignment] -- ^ table column alignments
-> Inlines -- ^ table caption
-> Char -- ^ csv quotation character like "
-> Char -- ^ csv field separator like ,
-> String -- ^ csv string to parse
-> Blocks
csvToTable header aligns caption qc sep s =
table caption cellspecs (map strToBlocks headers) $ (map . map) strToBlocks rows
where
exc = S.fromString qc sep s
rows' = case exception exc of
Nothing -> result exc
Just e -> [["Error parsing CSV: " ++ e]]
(headers, rows) = if header && length rows' > 0
then (head rows', tail rows')
else ([], rows')
cols = if null rows' then 0 else length $ head rows'
cellspecs = zip aligns $ replicate cols 0
strToInlines :: String -> Inlines
strToInlines s =
#if defined(INLINE_MARKDOWN)
case readMarkdown def s of
Right (Pandoc _ bs) -> fromList $ extractIns $ head bs
Left e -> str $ show e
where
extractIns (Para ins) = ins
extractIns _ = []
#else
str s
#endif
strToBlocks :: String -> Blocks
strToBlocks s =
#if defined(INLINE_MARKDOWN)
case readMarkdown def s of
Right (Pandoc _ bs) -> fromList bs
Left e -> para $ str $ show e
#else
para $ str s
#endif