@@ -46,10 +46,11 @@ import qualified Text.Pandoc.Builder as B
4646import Text.Pandoc.Builder ( Inlines, Blocks )
4747import Text.Pandoc.Definition
4848import Text.Pandoc.Options
49−import Text.Pandoc.Shared ( compactify', compactify'DL )
49+import Text.Pandoc.Shared ( compactify', compactify'DL, safeRead )
5050
5151import Control.Monad ( foldM, guard, mzero, void )
5252import Data.Char ( isSpace, toLower, toUpper)
53+import Data.Default ( Default )
5354import Data.List ( foldl', isPrefixOf )
5455import Data.Maybe ( fromMaybe, isNothing )
5556import Data.Monoid ((<>))
@@ -687,18 +688,24 @@ commentLine = commentLineStart *> anyLine *> pure mempty
687688--
688689-- Tables
689690--
691+data ColumnProperty = ColumnProperty
692+ { columnAlignment :: Maybe Alignment
693+ , columnRelWidth :: Maybe Int
694+ } deriving (Show, Eq)
695+
696+instance Default ColumnProperty where
697+ def = ColumnProperty Nothing Nothing
690698
691699data OrgTableRow = OrgContentRow (F [Blocks])
692− | OrgAlignRow [Alignment]
700+ | OrgAlignRow [ColumnProperty]
693701 | OrgHlineRow
694702
695703-- OrgTable is strongly related to the pandoc table ADT. Using the same
696704-- (i.e. pandoc-global) ADT would mean that the reader would break if the
697705-- global structure was to be changed, which would be bad. The final table
698−-- should be generated using a builder function. Column widths aren't
699−-- implemented yet, so they are not tracked here.
706+-- should be generated using a builder function.
700707data OrgTable = OrgTable
701− { orgTableAlignments :: [Alignment]
708+ { orgTableColumnProperties :: [ColumnProperty]
702709 , orgTableHeader :: [Blocks]
703710 , orgTableRows :: [[Blocks]]
704711 }
@@ -715,8 +722,20 @@ table = try $ do
715722orgToPandocTable :: OrgTable
716723 -> Inlines
717724 -> Blocks
718−orgToPandocTable (OrgTable aligns heads lns) caption =
719− B.table caption (zip aligns $ repeat 0) heads lns
725+orgToPandocTable (OrgTable colProps heads lns) caption =
726+ let totalWidth = if any (not . isNothing) (map columnRelWidth colProps)
727+ then Just . sum $ map (fromMaybe 1 . columnRelWidth) colProps
728+ else Nothing
729+ in B.table caption (map (convertColProp totalWidth) colProps) heads lns
730+ where
731+ convertColProp :: Maybe Int -> ColumnProperty -> (Alignment, Double)
732+ convertColProp totalWidth colProp =
733+ let
734+ align' = fromMaybe AlignDefault $ columnAlignment colProp
735+ width' = fromMaybe 0 $ (\w t -> (fromIntegral w / fromIntegral t))
736+ <$> (columnRelWidth colProp)
737+ <*> totalWidth
738+ in (align', width')
720739
721740tableRows :: OrgParser [OrgTableRow]
722741tableRows = try $ many (tableAlignRow <|> tableHline <|> tableContentRow)
@@ -732,22 +751,22 @@ tableContentCell = try $
732751tableAlignRow :: OrgParser OrgTableRow
733752tableAlignRow = try $ do
734753 tableStart
735− cells <- many1Till tableAlignCell newline
754+ colProps <- many1Till columnPropertyCell newline
736755 -- Empty rows are regular (i.e. content) rows, not alignment rows.
737− guard $ any (/= AlignDefault) cells
738− return $ OrgAlignRow cells
739−
740−tableAlignCell :: OrgParser Alignment
741−tableAlignCell =
742− choice [ try $ emptyCell *> return AlignDefault
743− , try $ skipSpaces
744− *> char '<'
745− *> tableAlignFromChar
746− <* many digit
747− <* char '>'
748− <* emptyCell
749− ] <?> "alignment info"
750− where emptyCell = try $ skipSpaces *> endOfCell
756+ guard $ any (/= def) colProps
757+ return $ OrgAlignRow colProps
758+
759+columnPropertyCell :: OrgParser ColumnProperty
760+columnPropertyCell = emptyCell <|> propCell <?> "alignment info"
761+ where
762+ emptyCell = ColumnProperty Nothing Nothing <$ (try $ skipSpaces *> endOfCell)
763+ propCell = try $ ColumnProperty
764+ <$> (skipSpaces
765+ *> char '<'
766+ *> optionMaybe tableAlignFromChar)
767+ <*> (optionMaybe (many1 digit >>= safeRead)
768+ <* char '>'
769+ <* emptyCell)
751770
752771tableAlignFromChar :: OrgParser Alignment
753772tableAlignFromChar = try $
@@ -769,7 +788,8 @@ rowsToTable = foldM rowToContent emptyTable
769788 where emptyTable = OrgTable mempty mempty mempty
770789
771790normalizeTable :: OrgTable -> OrgTable
772−normalizeTable (OrgTable aligns heads rows) = OrgTable aligns' heads rows
791+normalizeTable (OrgTable colProps heads rows) =
792+ OrgTable colProps' heads rows
773793 where
774794 refRow = if heads /= mempty
775795 then heads
@@ -778,7 +798,7 @@ normalizeTable (OrgTable aligns heads rows) = OrgTable aligns' heads rows
778798 _ -> mempty
779799 cols = length refRow
780800 fillColumns base padding = take cols $ base ++ repeat padding
781− aligns' = fillColumns aligns AlignDefault
801+ colProps' = fillColumns colProps def
782802
783803-- One or more horizontal rules after the first content line mark the previous
784804-- line as a header. All other horizontal lines are discarded.
@@ -788,7 +808,7 @@ rowToContent :: OrgTable
788808rowToContent orgTable row =
789809 case row of
790810 OrgHlineRow -> return singleRowPromotedToHeader
791− OrgAlignRow as -> return . setAligns $ as
811+ OrgAlignRow props -> return . setProperties $ props
792812 OrgContentRow cs -> appendToBody cs
793813 where
794814 singleRowPromotedToHeader :: OrgTable
@@ -797,8 +817,8 @@ rowToContent orgTable row =
797817 orgTable{ orgTableHeader = b , orgTableRows = [] }
798818 _ -> orgTable
799819
800− setAligns :: [Alignment] -> OrgTable
801− setAligns aligns = orgTable{ orgTableAlignments = aligns }
820+ setProperties :: [ColumnProperty] -> OrgTable
821+ setProperties ps = orgTable{ orgTableColumnProperties = ps }
802822
803823 appendToBody :: F [Blocks] -> F OrgTable
804824 appendToBody frow = do