From 712d746320d2f2bd1ee345dfa903b8d20d359cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edwin=20T=C3=B6r=C3=B6k?= Date: Tue, 19 Dec 2023 20:13:41 +0000 Subject: [PATCH] fix(docx): sort inline elements in schema order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #9273 ``` [ { "Description": "The element has unexpected child element 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:b'.", "Path": { "NamespacesDefinitions": [ "xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"" ], "Namespaces": { }, "XPath": "/w:document[1]/w:body[1]/w:p[1]/w:r[7]/w:rPr[1]", "PartUri": "/word/document.xml" }, "Id": "Sch_UnexpectedElementContentExpectingComplex", "ErrorType": "Schema" } ] ``` Signed-off-by: Edwin Török --- src/Text/Pandoc/Writers/Docx.hs | 61 +++++++++++++++++++- test/docx/golden/custom_style_preserve.docx | Bin 10532 -> 10532 bytes test/docx/golden/inline_formatting.docx | Bin 9918 -> 9921 bytes 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index 44c0e900d..afafd6926 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -36,7 +36,8 @@ import Control.Monad.State.Strict ( StateT(runStateT), gets, modify ) import qualified Data.ByteString.Lazy as BL import Data.Containers.ListUtils (nubOrd) import Data.Char (isSpace, isLetter) -import Data.List (intercalate, isPrefixOf, isSuffixOf) +import Data.List (intercalate, isPrefixOf, isSuffixOf, sortBy) +import Data.Ord (comparing) import Data.String (fromString) import qualified Data.Map as M import Data.Maybe (fromMaybe, isNothing, mapMaybe, maybeToList, isJust) @@ -77,9 +78,63 @@ import Text.Pandoc.XML.Light as XML import Data.Generics (mkT, everywhere) import Text.Collate.Lang (renderLang, Lang(..)) +-- from wml.xsd EG_RPrBase +rPrTagOrder :: M.Map Text Int +rPrTagOrder = + M.fromList + (zip [ "rStyle" + , "rFonts" + , "b" + , "bCs" + , "i" + , "iCs" + , "caps" + , "smallCaps" + , "strike" + , "dstrike" + , "outline" + , "shadow" + , "emboss" + , "imprint" + , "noProof" + , "snapToGrid" + , "vanish" + , "webHidden" + , "color" + , "spacing" + , "w" + , "kern" + , "position" + , "sz" + , "szCs" + , "highlight" + , "u" + , "effect" + , "bdr" + , "shd" + , "fitText" + , "vertAlign" + , "rtl" + , "cs" + , "em" + , "lang" + , "eastAsianLayout" + , "specVanish" + , "oMath" + ] [0..]) + +sortSquashed :: [Element] -> [Element] +sortSquashed l = + sortBy (comparing tagIndex) l + where + tagIndex :: Element -> Int + tagIndex el = + fromMaybe 0 (M.lookup tag rPrTagOrder) + where tag = (qName . elName) el + squashProps :: EnvProps -> [Element] -squashProps (EnvProps Nothing es) = es -squashProps (EnvProps (Just e) es) = e : es +squashProps (EnvProps Nothing es) = sortSquashed es +squashProps (EnvProps (Just e) es) = sortSquashed (e : es) renumIdMap :: Int -> [Element] -> M.Map Text Text renumIdMap _ [] = M.empty diff --git a/test/docx/golden/custom_style_preserve.docx b/test/docx/golden/custom_style_preserve.docx index f0e87643145aaab87f2cc5d2112f4c18ad396e9d..caceab9cea9fe0a81492130a713c44495f5624f1 100644 GIT binary patch delta 610 zcmZ1yv?Pc(z?+#xgn@~JgW<@E$s2h$GBN|{%?BBIA&iSm+00-Od$w4x$mIF#Z@~in z990k{JY1%nU=bJL^AHg+QC7x!pfTYJU7aj4j0_C!ObiTy3=9k@`N;uA`31%L$@xX8 zdKI}jODCPpJ7gfx60iEnwopdJWvu|;T8phgOM|w)I=g9lg5duX_sl+gGv#biDtvwR z^~}FE*}LOpeWw3)=(u%LHPO}6Xu~DV+}o;^_t$)8jWpf*C1w}H`h%4mD-_e}SDtm# z`#b54fbDXVQ?e3*-A^`n-r1GFvdn1974Dtlx))aIJio%gr5bQS*x$=Z%8qi?nGUp60{^~w0x&rg5M zdS+!y2S#u%SvmE|ijB?7mR(PcI?2EkE3rLbxzgQda(#QbwbY(2v+_5oa!l3alrN5- z(tq>uw!uS8RJrhTXo6VWx z{g4>=EwK$8-diL+*+7g<3dKwydUBc4X-GsUpMt0qRJ8+31gV;V>26gUFnvnZ9ZZX; zd4TD7HCr$}U(E_k-+}UF)NMFm@i;j_-5e}AOWhhw-%y7bE~()F=ErD244a2A8JU6f=7Ws95XMEOY-X^CJzFeTWb%CWw_t&O zjw*-}9xhW(u!xKBd5DOZC@W(<(3o(!pO?6TlLvxv3QEmnf>^p=Ld}{tm&x%Kho6VWx z{g4>=EwK$8-diL+*+7g<3dKwydUBc4X-GsUpMt0qRJ8+31gV;V>26gUFnvnZ9ZZX; zd4TD7HCr$}U(E_k-+}UF)NMFm@i;j_-5e}AOWhhw-%y7bE~()F=ErD244htcVYQyQPl-IPqylreL4TI^5f)t`PY4CNylkkn8&iGEOYb1rQgkbg^qg% zoYC!NmHj8ntM%-#wwPzK!S)Ob3-K3IeCqeD53?6K+Oo{HSIRlL&;8)TmEr~yeiSJj z%=Q#e`MfYMoa;54+2)0!ueL0Y(l~h0qWBAUUdXMDUrq}I{?}dC$e6`@6i(3?% zdROYWUyIprovV)3x#N@Qyi?h4L}lco|6lpLq;P`KlG$VkdvQB5`tTm($6T)zjoRoHTF}fBqtT z#ujIZR!-p(jaKEPb^k1nE~!Z=o1^`^Lru_5@vr%z62Cw7dp6m2iAyZq+5Ah$H+0JX zaP9AIj2jbj5?0EbdE#rT(RF+li`BWMV%}PFnY|VsoLEqFZf?pS&9YRcfNd#xm!{lZ zaF&1OO2r%og^M?TnmO(e`pK@zRl8}`riasx1V-3zdi|a;{%Q%M^!7ToOD5Y_+RqNF zHQV_uy2m^FvZb#iU#W8Kv5ATsrhkr-E!Z#Jv1_*9r@Hcc|5#Cy&t^eZYjFCR?9a9o zoQ}S;RY4L|3CCv+ut=7mGel&A5Gx}GD2aW)IoE#jUSawAvwnvS1X|)%KiL+}@!(iv zV%t!~#M!ANV1D}EvarYUH@P$K%b8~eYkfU-_VvuaHrcx)-}%n}>(FuQCTpUrr_qK> znz_4KE92LHs@{|%{c>jsV_frRfdJ<-L9=^fezD$Es`AU65^bO)b~17Dj>3Z+KB+HO zh!?3_EeMUg7s#wJrQX4@|G=H|E=5jSmdbz2U${3+5~(ssFboPasQReHBAjp5b4q^s z#flFFm#f6mzuUdKX~E-ccxAEa)ATQ&pZ?61F}-fKXoHZ)ZH<$G$^5y_`lq){Vr1E6 zkbB;B*I8K^Ht`UjQ=z4^GCnn(3KFt=YNsv#_3`B@*ITRByqXhgSskGnu9|L|e)amt z8LR(sUs$4k_eH(H`3B98U-L8S8BxQTS+pM#&Qry;H=m?c}x1Y%4UP&f@1 zxTkOmqI9*A9a!Rxk{MFY)>bx?2Sq~Z+Cyn9j0_B$Sr`~(7?1(`1FbE-A#gHHf)tr`}Uy_$!f?dCS9<%UGpuR$&sXz@#V408|)PUst z+}zZ>60G)v5}XXses>K0>n01TDuBa-F~!d<1*ql

leR4GauFCkLp?gVjh?s`hpO z<*op+Fp8S)$$hFyU^TW=xwc5MF);j+Wnd6RQR6cCysC-@DD3l=-kb+=OCu|~e~AfteQC3z*d=%b8~a2A8JU6f=7Ws9jGRD5xVe_|RKdyDndItk=Pfo6 z_$zw){Ok$u4rjGGt;$<%=RW%lyM!_0>V26x3;zB#-5xS^l5T*=TW+y}XJ^jLOg?@4 zcetu2>x-6)oO`45H5kwOs+G*UV1NAiRsX8}x33kZRjhQV7W#1OXsHwT`&=2we|ON>Rh@weXFHR+m6lgYdRbpf572UcO%R5 zNeUj%obRs_xW=2Kwovuej^$CB2QOL_f6~qixwG-hX@S7M+KYmU4qPptEqJFl!;Tz4|RrU;pCzS9O<;d8|BnZ`Rdq{kGdqAKdS$P#R-6^Fn&# zx%ZNr>Sbo~2KSZSe!-I~zm_{WU9!C;iiJIb@$TQYJyUo(+r#g-{4o1)*`SECJJ#xA z3jgWFuTQ_&AHPs&p69{4PA4zxRazNUW~FSCxm^*OChE1!d+Wc3UN-L7uNT)p*pj^A z5DU93_rs2etU5nKP5GI!%TFzIoXlpY_}BbUiQAt|snzu&`Ub0>@x9_UNsapxzt~2C z^+?mk#-$}2CYU`92rORXx!`d~*2X1QBo~NC$#AMazvQ{>&Gkr5hnr11J@s}UoFN|+ z?0AF0K`M3nZI*{#Pvn=J_!_zDQd_i;d*a^{EBCY4Y+a^(BklEa1>f4)|1M|VT|T*b ze`{>iOueg99$mPeE~B8yRJ}81HS@dg%z@>XJMXbcTp*7Gh=O0HrURKQVJA9}t$WKb?12LBO^CXj1-TcTv|9g<@+r zWi9n8y}HVpWircA89a%hrm~e=ra<)to0N-*i*{^{EACl(Kk)d` z#`g`=D)%jrn&4gEH)mes%GsSynx-VV?aIH;%b=-IvfyCC0@tt$tHlq#F4&$J@XuoF zp~=m=uX)b7dwfA!^8N3T@x0e&>|Zcn|9t-86)TMxcM3YpisEYHvd+k=iaj>Gyxz28_(G%)n(wH)-l>e+$@H^s&_L z*|Ps!S3Y`feleJnr|Wu3@Q1^0Y&)*#rlcB(xD)ZY6x|(@C#otbfNZdx%C$w3je+5pECYimiW*1p$qC}( zlV7Pqy!lgAnyVM6s64+YMZb7*f|@wk7p*cO=jH(Q9S35dlaK)O