git.iko.soy/typeable/pandoc
on master help sign in
Docx reader: Parse fldChar tags

This will allow us to parse instrTxt inside fldChar tags.

commit404706d29a8f45b43ef2ef13e93d1786dde863a0 authorJesse Rosenthal <jrosenthal@jhu.edu> dateTue 16 Jan 2018, 10:45 (9 years ago) parent551d8e8
2 files changed+84−5
src/Text/Pandoc/Readers/Docx.hs+3 src/Text/Pandoc/Readers/Docx/Parse.hs+81−5
src/Text/Pandoc/Readers/Docx.hs+3
@@ -446,6 +446,9 @@ parPartToInlines' (PlainOMath exps) =
446446 return $ math $ writeTeX exps
447447parPartToInlines' (SmartTag runs) = do
448448 smushInlines <$> mapM runToInlines runs
449+parPartToInlines' (Field _ runs) = do
450+ smushInlines <$> mapM runToInlines runs
451+parPartToInlines' NullParPart = return mempty
449452
450453isAnchorSpan :: Inline -> Bool
451454isAnchorSpan (Span (_, classes, kvs) _) =
src/Text/Pandoc/Readers/Docx/Parse.hs+81−5
@@ -90,10 +90,19 @@ data ReaderEnv = ReaderEnv { envNotes :: Notes
9090 }
9191 deriving Show
9292
93−data ReaderState = ReaderState { stateWarnings :: [String] }
93+data ReaderState = ReaderState { stateWarnings :: [String]
94+ , stateFldCharState :: FldCharState
95+ }
9496 deriving Show
9597
96−data DocxError = DocxError | WrongElem
98+data FldCharState = FldCharOpen
99+ | FldCharFieldInfo FieldInfo
100+ | FldCharContent FieldInfo [Run]
101+ | FldCharClosed
102+ deriving (Show)
103+
104+data DocxError = DocxError
105+ | WrongElem
97106 deriving Show
98107
99108type D = ExceptT DocxError (ReaderT ReaderEnv (State ReaderState))
@@ -265,6 +274,9 @@ data ParPart = PlainRun Run
265274 | Chart -- placeholder for now
266275 | PlainOMath [Exp]
267276 | SmartTag [Run]
277+ | Field FieldInfo [Run]
278+ | NullParPart -- when we need to return nothing, but
279+ -- not because of an error.
268280 deriving Show
269281
270282data Run = Run RunStyle [RunElem]
@@ -274,6 +286,10 @@ data Run = Run RunStyle [RunElem]
274286 | InlineChart -- placeholder
275287 deriving Show
276288
289+data FieldInfo = HyperlinkField URL
290+ | UnknownField
291+ deriving (Show)
292+
277293data RunElem = TextRun String | LnBrk | Tab | SoftHyphen | NoBreakHyphen
278294 deriving Show
279295
@@ -328,7 +344,9 @@ archiveToDocxWithWarnings archive = do
328344 (styles, parstyles) = archiveToStyles archive
329345 rEnv =
330346 ReaderEnv notes comments numbering rels media Nothing styles parstyles InDocument
331− rState = ReaderState { stateWarnings = [] }
347+ rState = ReaderState { stateWarnings = []
348+ , stateFldCharState = FldCharClosed
349+ }
332350 (eitherDoc, st) = runD (archiveToDocument archive) rEnv rState
333351 case eitherDoc of
334352 Right doc -> Right (Docx doc, stateWarnings st)
@@ -736,9 +754,67 @@ elemToParPart ns element
736754 , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"
737755 , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) drawingElem
738756 = return Chart
757+{-
758+The next one is a bit complicated. fldChar fields work by first
759+having a <w:fldChar fldCharType="begin"> in a run, then a run with
760+<w:instrText>, then a <w:fldChar fldCharType="separate"> run, then the
761+content runs, and finally a <w:fldChar fldCharType="end"> run. For
762+example (omissions and my comments in brackets):
763+
764+ <w:r>
765+ [...]
766+ <w:fldChar w:fldCharType="begin"/>
767+ </w:r>
768+ <w:r>
769+ [...]
770+ <w:instrText xml:space="preserve"> HYPERLINK [hyperlink url] </w:instrText>
771+ </w:r>
772+ <w:r>
773+ [...]
774+ <w:fldChar w:fldCharType="separate"/>
775+ </w:r>
776+ <w:r w:rsidRPr=[...]>
777+ [...]
778+ <w:t>Foundations of Analysis, 2nd Edition</w:t>
779+ </w:r>
780+ <w:r>
781+ [...]
782+ <w:fldChar w:fldCharType="end"/>
783+ </w:r>
784+
785+So we do this in a number of steps. If we encounter the fldchar begin
786+tag, we start open a fldchar state variable (see state above). We add
787+the instrtext to it as FieldInfo. Then we close that and start adding
788+the runs when we get to separate. Then when we get to end, we produce
789+the Field type with approriate FieldInfo and Runs.
790+-}
791+elemToParPart ns element
792+ | isElem ns "w" "r" element
793+ , Just fldChar <- findChildByName ns "w" "fldChar" element
794+ , Just fldCharType <- findAttrByName ns "w" "fldCharType" fldChar = do
795+ fldCharState <- gets stateFldCharState
796+ case fldCharState of
797+ FldCharClosed | fldCharType == "begin" -> do
798+ modify $ \st -> st {stateFldCharState = FldCharOpen}
799+ return NullParPart
800+ FldCharFieldInfo info | fldCharType == "separate" -> do
801+ modify $ \st -> st {stateFldCharState = FldCharContent info []}
802+ return NullParPart
803+ FldCharContent info runs | fldCharType == "end" -> do
804+ modify $ \st -> st {stateFldCharState = FldCharClosed}
805+ return $ Field info runs
806+ _ -> throwError WrongElem
739807elemToParPart ns element
740− | isElem ns "w" "r" element =
741− elemToRun ns element >>= (\r -> return $ PlainRun r)
808+ | isElem ns "w" "r" element = do
809+ run <- elemToRun ns element
810+ -- we check to see if we have an open FldChar in state that we're
811+ -- recording.
812+ fldCharState <- gets stateFldCharState
813+ case fldCharState of
814+ FldCharContent info runs -> do
815+ modify $ \st -> st{stateFldCharState = FldCharContent info (run : runs)}
816+ return NullParPart
817+ _ -> return $ PlainRun run
742818elemToParPart ns element
743819 | Just change <- getTrackedChange ns element = do
744820 runs <- mapD (elemToRun ns) (elChildren element)