diff options
Diffstat (limited to 'src/Text/Pandoc/Readers/Odt/StyleReader.hs')
-rw-r--r-- | src/Text/Pandoc/Readers/Odt/StyleReader.hs | 744 |
1 files changed, 0 insertions, 744 deletions
diff --git a/src/Text/Pandoc/Readers/Odt/StyleReader.hs b/src/Text/Pandoc/Readers/Odt/StyleReader.hs deleted file mode 100644 index 26ba6df82..000000000 --- a/src/Text/Pandoc/Readers/Odt/StyleReader.hs +++ /dev/null @@ -1,744 +0,0 @@ -{-# LANGUAGE TupleSections #-} -{-# LANGUAGE PatternGuards #-} -{-# LANGUAGE ViewPatterns #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE Arrows #-} - -{- -Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --} - -{- | - Module : Text.Pandoc.Readers.Odt.StyleReader - Copyright : Copyright (C) 2015 Martin Linnemann - License : GNU GPL, version 2 or above - - Maintainer : Martin Linnemann <theCodingMarlin@googlemail.com> - Stability : alpha - Portability : portable - -Reader for the style information in an odt document. --} - -module Text.Pandoc.Readers.Odt.StyleReader -( Style (..) -, StyleName -, StyleFamily (..) -, Styles (..) -, StyleProperties (..) -, TextProperties (..) -, ParaProperties (..) -, VerticalTextPosition (..) -, ListItemNumberFormat (..) -, ListLevel -, ListStyle (..) -, ListLevelStyle (..) -, ListLevelType (..) -, LengthOrPercent (..) -, lookupStyle -, getTextProperty -, getTextProperty' -, getParaProperty -, getListStyle -, getListLevelStyle -, getStyleFamily -, lookupDefaultStyle -, lookupDefaultStyle' -, lookupListStyleByName -, getPropertyChain -, textPropertyChain -, stylePropertyChain -, stylePropertyChain' -, getStylePropertyChain -, extendedStylePropertyChain -, extendedStylePropertyChain' -, liftStyles -, readStylesAt -) where - -import Control.Arrow -import Control.Applicative hiding ( liftA, liftA2, liftA3 ) - -import qualified Data.Foldable as F -import qualified Data.Map as M -import qualified Data.Set as S -import Data.Char ( isDigit ) -import Data.Default -import Data.List ( unfoldr ) -import Data.Maybe - -import qualified Text.XML.Light as XML - -import Text.Pandoc.Readers.Odt.Arrows.State -import Text.Pandoc.Readers.Odt.Arrows.Utils - -import Text.Pandoc.Readers.Odt.Generic.Utils -import qualified Text.Pandoc.Readers.Odt.Generic.SetMap as SM -import Text.Pandoc.Readers.Odt.Generic.Fallible -import Text.Pandoc.Readers.Odt.Generic.XMLConverter - -import Text.Pandoc.Readers.Odt.Namespaces -import Text.Pandoc.Readers.Odt.Base - - -readStylesAt :: XML.Element -> Fallible Styles -readStylesAt e = runConverter' readAllStyles mempty e - --------------------------------------------------------------------------------- --- Reader for font declarations and font pitches --------------------------------------------------------------------------------- - --- Pandoc has no support for different font pitches. Yet knowing them can be --- very helpful in cases where Pandoc has more semantics than OpenDocument. --- In these cases, the pitch can help deciding as what to define a block of --- text. So let's start with a type for font pitches: - -data FontPitch = PitchVariable | PitchFixed - deriving ( Eq, Show ) - -instance Lookupable FontPitch where - lookupTable = [ ("variable" , PitchVariable) - , ("fixed" , PitchFixed ) - ] - -instance Default FontPitch where - def = PitchVariable - --- The font pitch can be specifed in a style directly. Normally, however, --- it is defined in the font. That is also the specs' recommendation. --- --- Thus, we want - -type FontFaceName = String - -type FontPitches = M.Map FontFaceName FontPitch - --- To get there, the fonts have to be read and the pitches extracted. --- But the resulting map are only needed at one later place, so it should not be --- transported on the value level, especially as we already use a state arrow. --- So instead, the resulting map is lifted into the state of the reader. --- (An alternative might be ImplicitParams, but again, we already have a state.) --- --- So the main style readers will have the types -type StyleReader a b = XMLReader FontPitches a b --- and -type StyleReaderSafe a b = XMLReaderSafe FontPitches a b --- respectively. --- --- But before we can work with these, we need to define the reader that reads --- the fonts: - --- | A reader for font pitches -fontPitchReader :: XMLReader _s _x FontPitches -fontPitchReader = executeIn NsOffice "font-face-decls" ( - ( withEveryL NsStyle "font-face" $ liftAsSuccess ( - findAttr' NsStyle "name" - &&& - lookupDefaultingAttr NsStyle "font-pitch" - ) - ) - >>?^ ( M.fromList . (foldl accumLegalPitches []) ) - ) - where accumLegalPitches ls (Nothing,_) = ls - accumLegalPitches ls (Just n,p) = (n,p):ls - - --- | A wrapper around the font pitch reader that lifts the result into the --- state. -readFontPitches :: StyleReader x x -readFontPitches = producingExtraState () () fontPitchReader - - --- | Looking up a pitch in the state of the arrow. --- --- The function does the following: --- * Look for the font pitch in an attribute. --- * If that fails, look for the font name, look up the font in the state --- and use the pitch from there. --- * Return the result in a Maybe --- -findPitch :: XMLReaderSafe FontPitches _x (Maybe FontPitch) -findPitch = ( lookupAttr NsStyle "font-pitch" - `ifFailedDo` findAttr NsStyle "font-name" - >>? ( keepingTheValue getExtraState - >>% M.lookup - >>^ maybeToChoice - ) - ) - >>> choiceToMaybe - --------------------------------------------------------------------------------- --- Definitions of main data --------------------------------------------------------------------------------- - -type StyleName = String - --- | There are two types of styles: named styles with a style family and an --- optional style parent, and default styles for each style family, --- defining default style properties -data Styles = Styles - { stylesByName :: M.Map StyleName Style - , listStylesByName :: M.Map StyleName ListStyle - , defaultStyleMap :: M.Map StyleFamily StyleProperties - } - deriving ( Show ) - --- Styles from a monoid under union -instance Monoid Styles where - mempty = Styles M.empty M.empty M.empty - mappend (Styles sBn1 dSm1 lsBn1) - (Styles sBn2 dSm2 lsBn2) - = Styles (M.union sBn1 sBn2) - (M.union dSm1 dSm2) - (M.union lsBn1 lsBn2) - --- Not all families from the specifications are implemented, only those we need. --- But there are none that are not mentioned here. -data StyleFamily = FaText | FaParagraph --- | FaTable | FaTableCell | FaTableColumn | FaTableRow --- | FaGraphic | FaDrawing | FaChart --- | FaPresentation --- | FaRuby - deriving ( Eq, Ord, Show ) - -instance Lookupable StyleFamily where - lookupTable = [ ( "text" , FaText ) - , ( "paragraph" , FaParagraph ) --- , ( "table" , FaTable ) --- , ( "table-cell" , FaTableCell ) --- , ( "table-column" , FaTableColumn ) --- , ( "table-row" , FaTableRow ) --- , ( "graphic" , FaGraphic ) --- , ( "drawing-page" , FaDrawing ) --- , ( "chart" , FaChart ) --- , ( "presentation" , FaPresentation ) --- , ( "ruby" , FaRuby ) - ] - --- | A named style -data Style = Style { styleFamily :: Maybe StyleFamily - , styleParentName :: Maybe StyleName - , listStyle :: Maybe StyleName - , styleProperties :: StyleProperties - } - deriving ( Eq, Show ) - -data StyleProperties = SProps { textProperties :: Maybe TextProperties - , paraProperties :: Maybe ParaProperties --- , tableColProperties :: Maybe TColProperties --- , tableRowProperties :: Maybe TRowProperties --- , tableCellProperties :: Maybe TCellProperties --- , tableProperties :: Maybe TableProperties --- , graphicProperties :: Maybe GraphProperties - } - deriving ( Eq, Show ) - -instance Default StyleProperties where - def = SProps { textProperties = Just def - , paraProperties = Just def - } - -data TextProperties = PropT { isEmphasised :: Bool - , isStrong :: Bool - , pitch :: Maybe FontPitch - , verticalPosition :: VerticalTextPosition - , underline :: Maybe UnderlineMode - , strikethrough :: Maybe UnderlineMode - } - deriving ( Eq, Show ) - -instance Default TextProperties where - def = PropT { isEmphasised = False - , isStrong = False - , pitch = Just def - , verticalPosition = def - , underline = Nothing - , strikethrough = Nothing - } - -data ParaProperties = PropP { paraNumbering :: ParaNumbering - , indentation :: LengthOrPercent - , margin_left :: LengthOrPercent - } - deriving ( Eq, Show ) - -instance Default ParaProperties where - def = PropP { paraNumbering = NumberingNone - , indentation = def - , margin_left = def - } - ----- --- All the little data types that make up the properties ----- - -data VerticalTextPosition = VPosNormal | VPosSuper | VPosSub - deriving ( Eq, Show ) - -instance Default VerticalTextPosition where - def = VPosNormal - -instance Read VerticalTextPosition where - readsPrec _ s = [ (VPosSub , s') | ("sub" , s') <- lexS ] - ++ [ (VPosSuper , s') | ("super" , s') <- lexS ] - ++ [ (signumToVPos n , s') | ( n , s') <- readPercent s ] - where - lexS = lex s - signumToVPos n | n < 0 = VPosSub - | n > 0 = VPosSuper - | otherwise = VPosNormal - -data UnderlineMode = UnderlineModeNormal | UnderlineModeSkipWhitespace - deriving ( Eq, Show ) - -instance Lookupable UnderlineMode where - lookupTable = [ ( "continuous" , UnderlineModeNormal ) - , ( "skip-white-space" , UnderlineModeSkipWhitespace ) - ] - - -data ParaNumbering = NumberingNone | NumberingKeep | NumberingRestart Int - deriving ( Eq, Show ) - -data LengthOrPercent = LengthValueMM Int | PercentValue Int - deriving ( Eq, Show ) - -instance Default LengthOrPercent where - def = LengthValueMM 0 - -instance Read LengthOrPercent where - readsPrec _ s = - [ (PercentValue percent , s' ) | (percent , s' ) <- readPercent s] - ++ [ (LengthValueMM lengthMM , s'') | (length' , s' ) <- reads s - , (unit , s'') <- reads s' - , let lengthMM = estimateInMillimeter - length' unit - ] - -data XslUnit = XslUnitMM | XslUnitCM - | XslUnitInch - | XslUnitPoints | XslUnitPica - | XslUnitPixel - | XslUnitEM - -instance Show XslUnit where - show XslUnitMM = "mm" - show XslUnitCM = "cm" - show XslUnitInch = "in" - show XslUnitPoints = "pt" - show XslUnitPica = "pc" - show XslUnitPixel = "px" - show XslUnitEM = "em" - -instance Read XslUnit where - readsPrec _ "mm" = [(XslUnitMM , "")] - readsPrec _ "cm" = [(XslUnitCM , "")] - readsPrec _ "in" = [(XslUnitInch , "")] - readsPrec _ "pt" = [(XslUnitPoints , "")] - readsPrec _ "pc" = [(XslUnitPica , "")] - readsPrec _ "px" = [(XslUnitPixel , "")] - readsPrec _ "em" = [(XslUnitEM , "")] - readsPrec _ _ = [] - --- | Rough conversion of measures into millimeters. --- Pixels and em's are actually implemetation dependant/relative measures, --- so I could not really easily calculate anything exact here even if I wanted. --- But I do not care about exactness right now, as I only use measures --- to determine if a paragraph is "indented" or not. -estimateInMillimeter :: Int -> XslUnit -> Int -estimateInMillimeter n XslUnitMM = n -estimateInMillimeter n XslUnitCM = n * 10 -estimateInMillimeter n XslUnitInch = n * 25 -- \* 25.4 -estimateInMillimeter n XslUnitPoints = n `div` 3 -- \* 1/72 * 25.4 -estimateInMillimeter n XslUnitPica = n * 4 -- \* 12 * 1/72 * 25.4 -estimateInMillimeter n XslUnitPixel = n `div`3 -- \* 1/72 * 25.4 -estimateInMillimeter n XslUnitEM = n * 7 -- \* 16 * 1/72 * 25.4 - - ----- --- List styles ----- - -type ListLevel = Int - -newtype ListStyle = ListStyle { levelStyles :: M.Map ListLevel ListLevelStyle - } - deriving ( Eq, Show ) - --- -getListLevelStyle :: ListLevel -> ListStyle -> Maybe ListLevelStyle -getListLevelStyle level ListStyle{..} = - let (lower , exactHit , _) = M.splitLookup level levelStyles - in exactHit <|> fmap fst (M.maxView lower) - -- findBy (`M.lookup` levelStyles) [level, (level-1) .. 1] - -- \^ simpler, but in general less efficient - -data ListLevelStyle = ListLevelStyle { listLevelType :: ListLevelType - , listItemPrefix :: Maybe String - , listItemSuffix :: Maybe String - , listItemFormat :: ListItemNumberFormat - , listItemStart :: Int - } - deriving ( Eq, Ord ) - -instance Show ListLevelStyle where - show ListLevelStyle{..} = "<LLS|" - ++ (show listLevelType) - ++ "|" - ++ (maybeToString listItemPrefix) - ++ (show listItemFormat) - ++ (maybeToString listItemSuffix) - ++ ">" - where maybeToString = fromMaybe "" - -data ListLevelType = LltBullet | LltImage | LltNumbered - deriving ( Eq, Ord, Show ) - -data ListItemNumberFormat = LinfNone - | LinfNumber - | LinfRomanLC | LinfRomanUC - | LinfAlphaLC | LinfAlphaUC - | LinfString String - deriving ( Eq, Ord ) - -instance Show ListItemNumberFormat where - show LinfNone = "" - show LinfNumber = "1" - show LinfRomanLC = "i" - show LinfRomanUC = "I" - show LinfAlphaLC = "a" - show LinfAlphaUC = "A" - show (LinfString s) = s - -instance Default ListItemNumberFormat where - def = LinfNone - -instance Read ListItemNumberFormat where - readsPrec _ "" = [(LinfNone , "")] - readsPrec _ "1" = [(LinfNumber , "")] - readsPrec _ "i" = [(LinfRomanLC , "")] - readsPrec _ "I" = [(LinfRomanUC , "")] - readsPrec _ "a" = [(LinfAlphaLC , "")] - readsPrec _ "A" = [(LinfAlphaUC , "")] - readsPrec _ s = [(LinfString s , "")] - --------------------------------------------------------------------------------- --- Readers --- --- ...it seems like a whole lot of this should be automatically deriveable --- or at least moveable into a class. Most of this is data concealed in --- code. --------------------------------------------------------------------------------- - --- -readAllStyles :: StyleReader _x Styles -readAllStyles = ( readFontPitches - >>?! ( readAutomaticStyles - &&& readStyles )) - >>?%? chooseMax - -- all top elements are always on the same hierarchy level - --- -readStyles :: StyleReader _x Styles -readStyles = executeIn NsOffice "styles" $ liftAsSuccess - $ liftA3 Styles - ( tryAll NsStyle "style" readStyle >>^ M.fromList ) - ( tryAll NsText "list-style" readListStyle >>^ M.fromList ) - ( tryAll NsStyle "default-style" readDefaultStyle >>^ M.fromList ) - --- -readAutomaticStyles :: StyleReader _x Styles -readAutomaticStyles = executeIn NsOffice "automatic-styles" $ liftAsSuccess - $ liftA3 Styles - ( tryAll NsStyle "style" readStyle >>^ M.fromList ) - ( tryAll NsText "list-style" readListStyle >>^ M.fromList ) - ( returnV M.empty ) - --- -readDefaultStyle :: StyleReader _x (StyleFamily, StyleProperties) -readDefaultStyle = lookupAttr NsStyle "family" - >>?! keepingTheValue readStyleProperties - --- -readStyle :: StyleReader _x (StyleName,Style) -readStyle = findAttr NsStyle "name" - >>?! keepingTheValue - ( liftA4 Style - ( lookupAttr' NsStyle "family" ) - ( findAttr' NsStyle "parent-style-name" ) - ( findAttr' NsStyle "list-style-name" ) - readStyleProperties - ) - --- -readStyleProperties :: StyleReaderSafe _x StyleProperties -readStyleProperties = liftA2 SProps - ( readTextProperties >>> choiceToMaybe ) - ( readParaProperties >>> choiceToMaybe ) - --- -readTextProperties :: StyleReader _x TextProperties -readTextProperties = - executeIn NsStyle "text-properties" $ liftAsSuccess - ( liftA6 PropT - ( searchAttr NsXSL_FO "font-style" False isFontEmphasised ) - ( searchAttr NsXSL_FO "font-weight" False isFontBold ) - ( findPitch ) - ( getAttr NsStyle "text-position" ) - ( readUnderlineMode ) - ( readStrikeThroughMode ) - ) - where isFontEmphasised = [("normal",False),("italic",True),("oblique",True)] - isFontBold = ("normal",False):("bold",True) - :(map ((,True).show) ([100,200..900]::[Int])) - -readUnderlineMode :: StyleReaderSafe _x (Maybe UnderlineMode) -readUnderlineMode = readLineMode "text-underline-mode" - "text-underline-style" - -readStrikeThroughMode :: StyleReaderSafe _x (Maybe UnderlineMode) -readStrikeThroughMode = readLineMode "text-line-through-mode" - "text-line-through-style" - -readLineMode :: String -> String -> StyleReaderSafe _x (Maybe UnderlineMode) -readLineMode modeAttr styleAttr = proc x -> do - isUL <- searchAttr NsStyle styleAttr False isLinePresent -< x - mode <- lookupAttr' NsStyle modeAttr -< x - if isUL - then case mode of - Just m -> returnA -< Just m - Nothing -> returnA -< Just UnderlineModeNormal - else returnA -< Nothing - where - isLinePresent = [("none",False)] ++ map (,True) - [ "dash" , "dot-dash" , "dot-dot-dash" , "dotted" - , "long-dash" , "solid" , "wave" - ] - --- -readParaProperties :: StyleReader _x ParaProperties -readParaProperties = - executeIn NsStyle "paragraph-properties" $ liftAsSuccess - ( liftA3 PropP - ( liftA2 readNumbering - ( isSet' NsText "number-lines" ) - ( readAttr' NsText "line-number" ) - ) - ( liftA2 readIndentation - ( isSetWithDefault NsStyle "auto-text-indent" False ) - ( getAttr NsXSL_FO "text-indent" ) - ) - ( getAttr NsXSL_FO "margin-left" ) - ) - where readNumbering (Just True) (Just n) = NumberingRestart n - readNumbering (Just True) _ = NumberingKeep - readNumbering _ _ = NumberingNone - - readIndentation False indent = indent - readIndentation True _ = def - ----- --- List styles ----- - --- -readListStyle :: StyleReader _x (StyleName, ListStyle) -readListStyle = - findAttr NsStyle "name" - >>?! keepingTheValue - ( liftA ListStyle - $ ( liftA3 SM.union3 - ( readListLevelStyles NsText "list-level-style-number" LltNumbered ) - ( readListLevelStyles NsText "list-level-style-bullet" LltBullet ) - ( readListLevelStyles NsText "list-level-style-image" LltImage ) - ) >>^ M.mapMaybe chooseMostSpecificListLevelStyle - ) --- -readListLevelStyles :: Namespace -> ElementName - -> ListLevelType - -> StyleReaderSafe _x (SM.SetMap Int ListLevelStyle) -readListLevelStyles namespace elementName levelType = - ( tryAll namespace elementName (readListLevelStyle levelType) - >>^ SM.fromList - ) - --- -readListLevelStyle :: ListLevelType -> StyleReader _x (Int, ListLevelStyle) -readListLevelStyle levelType = readAttr NsText "level" - >>?! keepingTheValue - ( liftA5 toListLevelStyle - ( returnV levelType ) - ( findAttr' NsStyle "num-prefix" ) - ( findAttr' NsStyle "num-suffix" ) - ( getAttr NsStyle "num-format" ) - ( findAttr' NsText "start-value" ) - ) - where - toListLevelStyle _ p s LinfNone b = ListLevelStyle LltBullet p s LinfNone (startValue b) - toListLevelStyle _ p s f@(LinfString _) b = ListLevelStyle LltBullet p s f (startValue b) - toListLevelStyle t p s f b = ListLevelStyle t p s f (startValue b) - startValue (Just "") = 1 - startValue (Just v) = if all isDigit v - then read v - else 1 - startValue Nothing = 1 - --- -chooseMostSpecificListLevelStyle :: S.Set ListLevelStyle -> Maybe ListLevelStyle -chooseMostSpecificListLevelStyle ls | ls == mempty = Nothing - | otherwise = Just ( F.foldr1 select ls ) - where - select ( ListLevelStyle t1 p1 s1 f1 b1 ) - ( ListLevelStyle t2 p2 s2 f2 _ ) - = ListLevelStyle (select' t1 t2) (p1 <|> p2) (s1 <|> s2) (selectLinf f1 f2) b1 - select' LltNumbered _ = LltNumbered - select' _ LltNumbered = LltNumbered - select' _ _ = LltBullet - selectLinf LinfNone f2 = f2 - selectLinf f1 LinfNone = f1 - selectLinf (LinfString _) f2 = f2 - selectLinf f1 (LinfString _) = f1 - selectLinf f1 _ = f1 - - --------------------------------------------------------------------------------- --- Tools to access style data --------------------------------------------------------------------------------- - --- -lookupStyle :: StyleName -> Styles -> Maybe Style -lookupStyle name Styles{..} = M.lookup name stylesByName - --- -lookupDefaultStyle :: StyleFamily -> Styles -> StyleProperties -lookupDefaultStyle family Styles{..} = fromMaybe def - (M.lookup family defaultStyleMap) - --- -lookupDefaultStyle' :: Styles -> StyleFamily -> StyleProperties -lookupDefaultStyle' Styles{..} family = fromMaybe def - (M.lookup family defaultStyleMap) - --- -getListStyle :: Style -> Styles -> Maybe ListStyle -getListStyle Style{..} styles = listStyle >>= (`lookupListStyleByName` styles) - --- -lookupListStyleByName :: StyleName -> Styles -> Maybe ListStyle -lookupListStyleByName name Styles{..} = M.lookup name listStylesByName - - --- | Returns a chain of parent of the current style. The direct parent will --- be the first element of the list, followed by its parent and so on. --- The current style is not in the list. -parents :: Style -> Styles -> [Style] -parents style styles = unfoldr findNextParent style -- Ha! - where findNextParent Style{..} - = fmap duplicate $ (`lookupStyle` styles) =<< styleParentName - --- | Looks up the style family of the current style. Normally, every style --- should have one. But if not, all parents are searched. -getStyleFamily :: Style -> Styles -> Maybe StyleFamily -getStyleFamily style@Style{..} styles - = styleFamily - <|> (F.asum $ map (`getStyleFamily` styles) $ parents style styles) - --- | Each 'Style' has certain 'StyleProperties'. But sometimes not all property --- values are specified. Instead, a value might be inherited from a --- parent style. This function makes this chain of inheritance --- concrete and easily accessible by encapsulating the necessary lookups. --- The resulting list contains the direct properties of the style as the first --- element, the ones of the direct parent element as the next one, and so on. --- --- Note: There should also be default properties for each style family. These --- are @not@ contained in this list because properties inherited from --- parent elements take precedence over default styles. --- --- This function is primarily meant to be used through convenience wrappers. --- -stylePropertyChain :: Style -> Styles -> [StyleProperties] -stylePropertyChain style styles - = map styleProperties (style : parents style styles) - --- -extendedStylePropertyChain :: [Style] -> Styles -> [StyleProperties] -extendedStylePropertyChain [] _ = [] -extendedStylePropertyChain [style] styles = (stylePropertyChain style styles) - ++ (maybeToList (fmap (lookupDefaultStyle' styles) (getStyleFamily style styles))) -extendedStylePropertyChain (style:trace) styles = (stylePropertyChain style styles) - ++ (extendedStylePropertyChain trace styles) --- Optimizable with Data.Sequence - --- -extendedStylePropertyChain' :: [Style] -> Styles -> Maybe [StyleProperties] -extendedStylePropertyChain' [] _ = Nothing -extendedStylePropertyChain' [style] styles = Just ( - (stylePropertyChain style styles) - ++ (maybeToList (fmap (lookupDefaultStyle' styles) (getStyleFamily style styles))) - ) -extendedStylePropertyChain' (style:trace) styles = fmap ((stylePropertyChain style styles) ++) - (extendedStylePropertyChain' trace styles) - --- -stylePropertyChain' :: Styles -> Style -> [StyleProperties] -stylePropertyChain' = flip stylePropertyChain - --- -getStylePropertyChain :: StyleName -> Styles -> [StyleProperties] -getStylePropertyChain name styles = maybe [] - (`stylePropertyChain` styles) - (lookupStyle name styles) - --- -getPropertyChain :: (StyleProperties -> Maybe a) -> Style -> Styles -> [a] -getPropertyChain extract style styles = catMaybes - $ map extract - $ stylePropertyChain style styles - --- -textPropertyChain :: Style -> Styles -> [TextProperties] -textPropertyChain = getPropertyChain textProperties - --- -paraPropertyChain :: Style -> Styles -> [ParaProperties] -paraPropertyChain = getPropertyChain paraProperties - --- -getTextProperty :: (TextProperties -> a) -> Style -> Styles -> Maybe a -getTextProperty extract style styles = fmap extract - $ listToMaybe - $ textPropertyChain style styles - --- -getTextProperty' :: (TextProperties -> Maybe a) -> Style -> Styles -> Maybe a -getTextProperty' extract style styles = F.asum - $ map extract - $ textPropertyChain style styles - --- -getParaProperty :: (ParaProperties -> a) -> Style -> Styles -> Maybe a -getParaProperty extract style styles = fmap extract - $ listToMaybe - $ paraPropertyChain style styles - --- | Lifts the reader into another readers' state. -liftStyles :: (OdtConverterState s -> OdtConverterState Styles) - -> (OdtConverterState Styles -> OdtConverterState s ) - -> XMLReader s x x -liftStyles extract inject = switchState extract inject - $ convertingExtraState M.empty readAllStyles - |