xlsx-0.2.2: src/Codec/Xlsx/Types/Common.hs
{-# LANGUAGE OverloadedStrings #-}
module Codec.Xlsx.Types.Common
( CellRef
, XlsxText (..)
) where
import qualified Data.Map as Map
import Data.Text (Text)
import Text.XML
import Text.XML.Cursor
import Codec.Xlsx.Parser.Internal
import Codec.Xlsx.Types.RichText
import Codec.Xlsx.Writer.Internal
-- | Excel cell reference (e.g. @E3@)
-- see 18.18.62 @ST_Ref@ (p. 2482)
type CellRef = Text
-- | Common type containing either simple string or rich formatted text.
-- Used in @si@, @comment@ and @is@ elements
--
-- E.g. @si@ spec says: "If the string is just a simple string with formatting applied
-- at the cell level, then the String Item (si) should contain a single text
-- element used to express the string. However, if the string in the cell is
-- more complex - i.e., has formatting applied at the character level - then the
-- string item shall consist of multiple rich text runs which collectively are
-- used to express the string.". So we have either a single "Text" field, or
-- else a list of "RichTextRun"s, each of which is some "Text" with layout
-- properties.
--
-- TODO: Currently we do not support @phoneticPr@ (Phonetic Properties, 18.4.3,
-- p. 1723) or @rPh@ (Phonetic Run, 18.4.6, p. 1725).
--
-- Section 18.4.8, "si (String Item)" (p. 1725)
--
-- See @CT_Rst@, p. 3903
data XlsxText = XlsxText Text
| XlsxRichText [RichTextRun]
deriving (Show, Eq, Ord)
{-------------------------------------------------------------------------------
Rendering
-------------------------------------------------------------------------------}
-- | See @CT_Rst@, p. 3903
instance ToElement XlsxText where
toElement nm si = Element {
elementName = nm
, elementAttributes = Map.empty
, elementNodes = map NodeElement $
case si of
XlsxText text -> [elementContent "t" text]
XlsxRichText rich -> map (toElement "r") rich
}
{-------------------------------------------------------------------------------
Parsing
-------------------------------------------------------------------------------}
-- | See @CT_Rst@, p. 3903
instance FromCursor XlsxText where
fromCursor cur = do
let
ts = cur $/ element (n"t") >=> contentOrEmpty
contentOrEmpty c = case c $/ content of
[t] -> [t]
[] -> [""]
_ -> error "invalid item: more than one text nodes under <t>!"
rs = cur $/ element (n"r") >=> fromCursor
case (ts,rs) of
([t], []) ->
return $ XlsxText t
([], _:_) ->
return $ XlsxRichText rs
_ ->
fail "invalid item"