pandoc-linear-table-0.2.0.5: src/Text/Pandoc/Filters/LinearTable.hs
{-|
Module : LinearTable
Description : An easy way to create tables with wrapped text in Markdown.
Copyright : (c) 2020-2023 Amy de Buitléir
License : BSD--3
Maintainer : amy@nualeargais.ie
Stability : experimental
Portability : POSIX
See <https://github.com/mhwombat/pandoc-linear-table> for information
on how to use this filter.
-}
{-# LANGUAGE OverloadedStrings #-}
module Text.Pandoc.Filters.LinearTable
(
transform,
formatLinearTable
) where
import Data.Foldable (foldl')
import Data.Text qualified as T
import Text.Pandoc qualified as P
import Text.Pandoc.Walk (walk)
-- | A transformation that can be used with Hakyll.
transform :: P.Pandoc -> P.Pandoc
transform = walk formatLinearTable
-- | Exported for use by the executable.
formatLinearTable :: P.Block -> P.Block
formatLinearTable x@(P.CodeBlock (_,cs,_) s)
| null cs = x
| head cs == "linear-table" = toTable . splitRows $ T.lines s
| otherwise = x
formatLinearTable x = x
toTable :: [[T.Text]] -> P.Block
toTable xss = P.Table attr defaultTableCaption colSpecs
defaultTableHeader [toTableBody xss]
defaultTableFooter
where attr = ("",["linear-table"],[])
colSpecs = replicate nCols defaultColSpec
nCols = maximum $ map length xss
toTableBody :: [[T.Text]] -> P.TableBody
toTableBody = P.TableBody P.nullAttr (P.RowHeadColumns 0) []
. map toTableRow
toTableRow :: [T.Text] -> P.Row
toTableRow = P.Row P.nullAttr . map toCell
toCell :: T.Text -> P.Cell
toCell = blocksToCell . map removePara . parseBlocks
blocksToCell :: [P.Block] -> P.Cell
blocksToCell
= P.Cell P.nullAttr P.AlignDefault (P.RowSpan 1) (P.ColSpan 1)
removePara :: P.Block -> P.Block
removePara (P.Para xs) = P.Plain xs
removePara x = x
splitRows :: Foldable t => t T.Text -> [[T.Text]]
splitRows xs = reverse . map reverse $ foldl' splitter [] xs
splitter :: [[T.Text]] -> T.Text -> [[T.Text]]
splitter [] x | x == "" = []
| otherwise = [[x]]
splitter accum x | x == "" = []:accum
| otherwise = (x:(head accum)) : tail accum
readDefaults :: P.ReaderOptions
readDefaults = P.def { P.readerStandalone = True,
P.readerExtensions = P.pandocExtensions }
parseBlocks :: T.Text -> [P.Block]
parseBlocks s = f . P.runPure $ P.readMarkdown readDefaults s
where f (Right (P.Pandoc _ bs)) = bs
f (Left e) = error $ "readMarkdown failed: " ++ show e
defaultColSpec :: P.ColSpec
defaultColSpec = (P.AlignDefault, P.ColWidthDefault)
defaultTableCaption :: P.Caption
defaultTableCaption = P.Caption Nothing []
defaultTableHeader :: P.TableHead
defaultTableHeader = P.TableHead P.nullAttr []
defaultTableFooter :: P.TableFoot
defaultTableFooter = P.TableFoot P.nullAttr []