From c0fcc8a7891892357854cf498ce262b256fac1ca Mon Sep 17 00:00:00 2001 From: Jesse Rosenthal Date: Sun, 29 Jun 2014 18:44:22 -0400 Subject: [PATCH 1/3] Docx reader: Add ParIndentation type to parser. This lets us keep more information about the indentation, and act accordingly in the reader. --- src/Text/Pandoc/Readers/Docx/Parse.hs | 31 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/Text/Pandoc/Readers/Docx/Parse.hs b/src/Text/Pandoc/Readers/Docx/Parse.hs index 07f34450d..537c5c272 100644 --- a/src/Text/Pandoc/Readers/Docx/Parse.hs +++ b/src/Text/Pandoc/Readers/Docx/Parse.hs @@ -42,6 +42,7 @@ module Text.Pandoc.Readers.Docx.Parse ( Docx(..) , Relationship , Media , RunStyle(..) + , ParIndentation(..) , ParagraphStyle(..) , Row(..) , Cell(..) @@ -341,16 +342,37 @@ testBitMask bitMaskS n = [] -> False ((n', _) : _) -> ((n' .|. n) /= 0) +data ParIndentation = ParIndentation { leftParIndent :: Maybe Integer + , rightParIndent :: Maybe Integer + , hangingParIndent :: Maybe Integer} + deriving Show + data ParagraphStyle = ParagraphStyle { pStyle :: [String] - , indent :: Maybe Integer + , indentation :: Maybe ParIndentation } deriving Show defaultParagraphStyle :: ParagraphStyle defaultParagraphStyle = ParagraphStyle { pStyle = [] - , indent = Nothing + , indentation = Nothing } +elemToParIndentation :: NameSpaces -> Element -> Maybe ParIndentation +elemToParIndentation ns element + | qName (elName element) == "ind" && + qURI (elName element) == (lookup "w" ns) = + Just $ ParIndentation { + leftParIndent = + findAttr (QName "left" (lookup "w" ns) (Just "w")) element >>= + stringToInteger + , rightParIndent = + findAttr (QName "right" (lookup "w" ns) (Just "w")) element >>= + stringToInteger + , hangingParIndent = + findAttr (QName "hanging" (lookup "w" ns) (Just "w")) element >>= + stringToInteger} +elemToParIndentation _ _ = Nothing + elemToParagraphStyle :: NameSpaces -> Element -> ParagraphStyle elemToParagraphStyle ns element = case findChild (QName "pPr" (lookup "w" ns) (Just "w")) element of @@ -360,10 +382,9 @@ elemToParagraphStyle ns element = mapMaybe (findAttr (QName "val" (lookup "w" ns) (Just "w"))) (findChildren (QName "pStyle" (lookup "w" ns) (Just "w")) pPr) - , indent = + , indentation = findChild (QName "ind" (lookup "w" ns) (Just "w")) pPr >>= - findAttr (QName "left" (lookup "w" ns) (Just "w")) >>= - stringToInteger + elemToParIndentation ns } Nothing -> defaultParagraphStyle From 0f59196e0ef2f0977d404699ae16a48009fa7632 Mon Sep 17 00:00:00 2001 From: Jesse Rosenthal Date: Sun, 29 Jun 2014 22:50:29 -0400 Subject: [PATCH 2/3] Docx reader: Make use of new ParIndentation info. Here, when hanging indents are greater than or equal to left indents, we don't set it to block quote. Such indents are frequently used in academic bibliographies. (Thanks to Caleb McDaniel.) --- src/Text/Pandoc/Readers/Docx.hs | 35 +++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs index 71baa5dde..8357b4cca 100644 --- a/src/Text/Pandoc/Readers/Docx.hs +++ b/src/Text/Pandoc/Readers/Docx.hs @@ -94,6 +94,7 @@ import System.FilePath (combine) import qualified Data.Map as M import Control.Monad.Reader import Control.Monad.State +import Control.Applicative (liftA2) readDocx :: ReaderOptions -> B.ByteString @@ -148,7 +149,6 @@ runStyleToContainers rPr = in classContainers ++ formatters - divAttrToContainers :: [String] -> [(String, String)] -> [Container Block] divAttrToContainers (c:cs) _ | Just n <- isHeaderClass c = [Container $ \_ -> @@ -166,22 +166,37 @@ divAttrToContainers (c:cs) kvs | c `elem` listParagraphDivs = divAttrToContainers (c:cs) kvs | c `elem` blockQuoteDivs = (Container BlockQuote) : (divAttrToContainers (cs \\ blockQuoteDivs) kvs) divAttrToContainers (_:cs) kvs = divAttrToContainers cs kvs -divAttrToContainers [] kvs | Just numString <- lookup "indent" kvs = - let kvs' = filter (\(k,_) -> k /= "indent") kvs +divAttrToContainers [] kvs | Just _ <- lookup "indent" kvs + , Just flInd <- lookup "first-line-indent" kvs = + let + kvs' = filter (\(k,_) -> notElem k ["indent", "first-line-indent"]) kvs in - case numString of - "0" -> divAttrToContainers [] kvs' - ('-' : _) -> divAttrToContainers [] kvs' - _ -> (Container BlockQuote) : divAttrToContainers [] kvs' + case flInd of + "0" -> divAttrToContainers [] kvs' + ('-':_) -> divAttrToContainers [] kvs' + _ -> (Container BlockQuote) : divAttrToContainers [] kvs' +divAttrToContainers [] kvs | Just ind <- lookup "indent" kvs = + let + kvs' = filter (\(k,_) -> notElem k ["indent"]) kvs + in + case ind of + "0" -> divAttrToContainers [] kvs' + ('-':_) -> divAttrToContainers [] kvs' + _ -> (Container BlockQuote) : divAttrToContainers [] kvs' + divAttrToContainers _ _ = [] parStyleToContainers :: ParagraphStyle -> [Container Block] parStyleToContainers pPr = let classes = pStyle pPr - kvs = case indent pPr of - Just n -> [("indent", show n)] - Nothing -> [] + indent = indentation pPr >>= leftParIndent + hanging = indentation pPr >>= hangingParIndent + firstLineIndent = liftA2 (-) indent hanging + kvs = mapMaybe id + [ indent >>= (\n -> Just ("indent", show n)), + firstLineIndent >>= (\n -> Just ("first-line-indent", show n)) + ] in divAttrToContainers classes kvs From 1405e7b7091dedb50578c9e0cafd62f2c77ca689 Mon Sep 17 00:00:00 2001 From: Jesse Rosenthal Date: Sun, 29 Jun 2014 23:37:00 -0400 Subject: [PATCH 3/3] Docx reader: Add tests for hanging indent handline. We want to treat it as a plain paragraph if the hanging amount is greater to or equal to the left indent---i.e., if the first line has zero indentation. But we still want it to be a block quote if it starts to the right of the margin. Someone might format verse with wrapping lines with a hanging indent, for example. --- tests/Tests/Readers/Docx.hs | 4 ++++ tests/docx.hanging_indent.docx | Bin 0 -> 29924 bytes tests/docx.hanging_indent.native | 3 +++ 3 files changed, 7 insertions(+) create mode 100644 tests/docx.hanging_indent.docx create mode 100644 tests/docx.hanging_indent.native diff --git a/tests/Tests/Readers/Docx.hs b/tests/Tests/Readers/Docx.hs index 8c51217cf..a379bbf23 100644 --- a/tests/Tests/Readers/Docx.hs +++ b/tests/Tests/Readers/Docx.hs @@ -112,6 +112,10 @@ tests = [ testGroup "inlines" "blockquotes (parsing indent as blockquote)" "docx.block_quotes.docx" "docx.block_quotes_parse_indent.native" + , testCompare + "hanging indents" + "docx.hanging_indent.docx" + "docx.hanging_indent.native" , testCompare "tables" "docx.tables.docx" diff --git a/tests/docx.hanging_indent.docx b/tests/docx.hanging_indent.docx new file mode 100644 index 0000000000000000000000000000000000000000..6f62dc7315e7befbc4ab8ccacd4c4cb61d8891f1 GIT binary patch literal 29924 zcmeIb2UrwKvj95eBrG{fP(&0YNt7%Ih)56=5QG(wu%t!e3JZ&5MMObCL2?EGB}!Z} zDiS10W*3z#yGmGLS>B-ke~#ze|G)3Pckg@O_uh5*cBZDgy1J{os-~)E=r%E+pkxQA z0a^e6jsPERhjskO0N^qe0I&hH6PW-xi2wWe zU)%##kKP!yOEX8UpKsLuD1KqeTa#8~>Gmhu$0s0j6N$rfhBXaMYKc`v#l;NSYa$5_ z{Tj2x^qcCIE|1@}(7+7O?p%#OcKsE{;4sy9-ln|xV{{LBS|7=qJP@HgeF6^u`hM{2 zdFhFWu#5J-#*e7g$$GV%__?Qwo{ycv4vr1WklI}{x0_}tK8>D}mWhj_KKYHS@WbWK zkAAn&7RR`a5*9}4j$b+Z#OH!HC(9#+hN^cO%u@zrZytOn^vR`X`>arvN_%y5(O1kX z%L@BnH?zKy5dH#L%p&9V@mcL*Elq=}w+e#+ZZT@OS*B(Fz@pUU$vB6()JCp_nGXHflI7gtt_)`3nI(?m zDOL?S)|)p%Yi3E~A+@KwP3^f3HTjY04eUE8DVL`%vUj)Lj%PJ$;4gFXD#Yu#2bWw0VVw5IW8EvcE;+czaB!DreDhQGWq->15tcdm?KaWLL0&DeY3&W3u0O&5 zV&8+Ox^2w)F`tu<@ybHJegFFYwQ6qolXZt)cTs{b!s~TaF=E-bY%dFnwcN~KGkmQW`xc-v<(dEl_iE()UWt_d)WHMdOu!JJZ+?wsrr?D((3HgXtGeTOzy}1 zrr@Cs>h-2u`~&zqwBPSHh~6;D$hlGC5c~Z4>36IWuZM&z48r7QZsrAWqGXtI&cv*U z98vOsk-tdxMsfNa>P$G)kz@E+`P95Ye`h&o-2M>tPC8NObxwA21~}sX(ej#6To{0Y zR@V*`Efx^thw%I=HXT=5@25&LH(4xeSUyW+PH<1nesCpEuJ*#EfNhGy($_gAUn>l3 ztn40AO7*PeaD_ZRI{rZxKJ%{ervLWrIUTEfMvK#Q*`23_F6N8PSDX(k=$=RNF*_8! zbIChq5XKdKxzmWpuc*l%g}a|7BD=LApQA2B0jyfdDt0u*SEeH)Sf4xwkJw%kzAPueZ)ueJmK5kye`fit(S*b` zC$CaVrsQq$i>6%3mpS)N)UA7=8CY&ge^FZ{z5Ez8r}xI?LTFf4%ESAU2_F(zXwGXs zWNAP3a``)RIIzLfieUBBFMu%~E9FIQr(dgxjD_vKrd`7BcUM6f_wAa-pXa!Z7;~4S zJR|d*=f8H`m8`0|KyIPSm1};S?n`#{dbDEG+KiLh%V52k)82NM`8FVvDZK3!Ja4A! zU=b}nfs^`IKYSgD;!c`Kq;4wV7Jc-I%&5#V2R8cwi%~IAZv0d-;xr(%6=1!ZrI8Co z=1bncf}qdty`FvR68Xsq$)Nbk3UiFj*Rk;2J&*U6J=YR-&q9WSJQ&R)C3p9u_8|XK z8q==DHZ#)zKr}x9aQssmeO(+q9HoAoWeyD4>Q!SnpAI`(7|*X81ZNX9N;&6O{NW{C z6)fk2#PZEXl`SLLhRPHkQ9NU{-mzon&K@r8h@&7Et7c993M1Ds$qk{JdAC{?fW0~Y z2;h*59#z>5g3s(WX?$}ow^cFXRz9X>nywHw@u?GdDEE=YFgk9|zuX5Vp=pYdYr9vF z%X06|p)!x=-M%Z0S@sFclwXUcTH=Jv#U?E+9~?R4aOhI2FqPDV1T$%&)N zo15a3c_9?nU3temYpvI;iuwUB?y!Q>i z+!ZWFeXO6GQdDTHm=UTwM|MUN!WD&Lp-R{opNNJKW){;Oyc9WwA9qjUR|B6Zwb=AsO=OT_7~8zYkrI^SyO?q9Uh%8odyrtC zTCe4fTD7;CaMO&p<`)mkZgU%P2qZi@kvog0&{9QC=M7{0lB2>5)J+y8bqp^yJ=$=Y zeUpD@fXPru(jntEGdwzVTBY#K)BY6?@5Q58V$$EZXNBKo;nh@4mGDKYn20NM=-XFT zWh+!T?KsAg=#Q!$yO-mCE_dV26zd#ZWN|FZkI>%S({(47{jLDPcc$f;#luNrCdd4- zZ*~oGaU~zNKau60&<(oweXe1ulzH#a&6cHiUb9&pblc<8a|-;*#|>G}p?T=|4O~Wy zXpCHTiv6EyD)vp+z4AZAi2H64uljT|UjZv2)M`PeQZTW8YHBHe5_>co9@0PEmE#+) znPM!Z3b+0;nZ!q2u>SHqFunG@QJ{F0O;gj$RQpODBd0G9Xdb;RWiPJEz7#ioeT`Z3!Y!=;bp?ab(5lKfX_$-(>hrNW6X_#Ylc$SZ?P1k5mUr*- zw(h(gyb!AOOg@b4us+5);p{-}Oog37L{ORuU23)SX!gm$JKZa!=f$lO?f1fNzExr~ z^>E;sSKQ-Rn z$oBQ&(QH0Fy~2K7dqHi&ZL>Awb0Slxo`j7;ycqMx70Rb(QUX$zKP9$~-+WiWy)bPG z&0*(o#^ldj;CpA*sfz1$Yq z8?!ubUB3@HT&cMB@J->}y3>_T+i#B8sZCQ@_(7OV4i$OU>(5Xh`r=Ef>%T>{866mJ zTB=wO{m7u8^foGR-aeM+nR0dVz;|mLG-dJX-t$HlsnOTP!aJQek}pdYw_PQUj(sb# z9g4WcIrrAeO=a{^w}E)%P3BHmyxohb{u^F4;Tsw+NS9bn@7kS}DpYHRG;y>BkoO3N zJ#Wr!;Jxv{^TC#d;Fg;I!0|+L$D-Z<^^|J+m(6o=u4mRyR#ZEF>)3sEBRTa%fN}w+ zRKn^ryJ$BRg+$kw)g{)*tg|j@fqZ2PdhbGX6L?ggD!<-}cvGex z-}T-2_*$4-rBQ~RTteRNjZhcgYtJ+;9CxQ1H|FW&9M7zNVpL`7H6GyNMdj1TSzY3I zveCE3>!h7iRFVySD&Of0a>9ehik`t$6pbDgqi#0WsLW37i9hPKYs@&k{>It%?dnGgFn38;FGuJ75BqZf^95afU4V>?3^)(|0sB}gO?_=` zsEMhuuKqwJ>bwAhor90pSrZem zI?#&*aSyJ4J+?-F1{^~Y|2qG#*nhiYxZ&gA0RUv+v>y4_8;(8>06;+map2BiLjZvC zpg#5hUoT$}4n2Uqf2Kb=fbD<6g+J0Sn`(nNjUdeA;N^XQ{|31kdVd@TPVyl~&nsr&^*Gq35Jw-Kf52p6H|)+Cfa#K8dzWuGp3?#0Qy^UE z1k=?A;S=C*%E?>z%1@X~4CbqU`6oxQj=^oU4(3%6fKihaf|Da7j={ta}JqzZ#1I}Qo2l)HRlg}Uc62G?2$@2m4A2~t? zbvQ;FZT-Tf<1aNy0QMlg1FjFa_XlBj@Xql^egCZO-}N4d+l_4G{-gNN5g;v`$Go)4)pcl0PXRQ z`=3|xO!9wXki}+F{1XO?g2(L00dg`53UW#cDk@5_Bglfme1MXLiuH)h zS!%XRb~HzCvY)>FFpE}L>t!p4>3iHUS$pp=I(kknZXRBdINWe_a(02a`uO_!2Ow?*hDSt3MaSH^n~?bEaZ>V=rzzPvxq0~o zg+;{`l~vU>wXf>x+uA!iySiV$c{?~XJTf}=VSECEo&Wgh^TOiNGXCqgjm@oX!uOp6 zzQ_QIKf3HEXMf`h>;y7$N=gb!nghPb$O8@-XQ8AzB16r3_7aWVO}3+_Z_~1CJ5Y_6?$hLbPQQn2F(!1A8(~lGHgfca%**RlS0U|@;pWl1N~RcR>jGz&ch{9@HmLRiW_2X(K9I9VsNDym^jc?$(+S7i^3I!`ho$;U>Aa?rY4_QJ#SuUSGhLQ{Z!;2eq|Gfz6dPGlD+y@jss?E{6i zo%8@{)dk2T52Xhk@c*%ky1`yE`eUbthw-i)dO~p@xV(L@kb)?=NU_JV56pGPe-}pM zOv-mpqAIsZ*|Y2?D0W}|k5&E$C*P&EcJ_fp_PuJ2)xmwhWp>YO=5!_m*N_R>(Ax*X z1vEb12d%djdNq&KKf4o)G|7Z~>H44T39vB~AJLO5q>E--!}~y`!Cnq((-`qKRHN-n zsK$Fi(jmk?kf5>;P|@!L70J6AsAUPfR;We;@Bid@{OA%$!ae{m|1M)ZX-4Xm+KSr; zM%3oTK*3p)Y>r7^N_4k)nya`}%G4iLz`Lf1C;f#WB4T~XtCr1$8Zf<{M8K}>+A;9~qfK&^^;!w){G zBT?f9dl~3WPC}NZ;B?#{gvq|&+;t>%ZVU2~q&^_F+x7v*Riv&TWE{Pff}6eL7u(Op zf8;ZvAvll74;_EaAl~cwp|tsF0LGYSa<8~+MuN}K(At#uqXp-T=tyr1P5*>(Ydqm3 zI#N~bW&r_ZH7qHQrXxx><3!uh%*zw&t%iD*uWG_O&=jgVd5EBEjbVb2(#KI*@I0b5 z?(ur8hh6NJgQ8uHF|)N_at*Yl&a@7q- zWE-;3#WOYKFDcVR59vgAZSMm-RiO98&pW6F$JDlsR1#tftyawIZIcp1UEGR5ty3lN ztS)>`NH0dnFQJlAS_p&>51b1MMFg%p{WqC=V`w$wkWwX%K8 zR0UE@SxA)R$R}PknR>m9S;=2tUIs!*xMjQE@oo|rglRHu4;Us#R zc}GGr5E!g4fz)@)ceQf9>tVP`V_9Df?9f~zXzaSU2~rWsFcQvCd~;n1LTW3O5VJFq z79AhLhd^~enfC!F2`Hw!vz(s5ri(8nW#qv~OnCmJWULeyf_J+^oxiSnaMOC4tDV*M zSaQhmmqTTqElPspJs2(`dk&^|Y;_a2-6^1y-aUtIpG1+lkdDCi0gMTvp|b*JMFSd} z@yCAaOm1VNy_nf50xOhl30+klMpP+Utl1fhmwQ-9FtBY1x2Uaozv*#`La-AGXv}49 zDMxpeGZ3Z6P#7A5BOcNTtr3mg=s_{M&QQL>GZkPpVrGQ!0y%RhH$C9jMpykHG%$e^ z1AaCNf=sTq9ERGqIE^@oYDQ>>@zPL&_8UN(mK^J9=1) z@J)2sH&@arf*sb7slO$W0BxCwzC#o#==MrKT!nLt>%UV~op6#b=OS@kPcbgO{AQk!^RJKwx!Si%7X2+k1O+`lCp=7Dj4-v!!X%Gqg!iM$3@Wx==$CVjAyu?^k)gH`OFowibhrcXin8PSv&EwG` zOJX1@fMjD4ie0l1Ulbc*!D19ik&DzBDMQ+n5Qe(aDe)13{o$S=r$PpJ%VRSxJ(Lr{ zH@#CoLU1k#>Dz)*ZR{y5w=J~ne7-&30OiuN%Tarr|D5deRz@XyZ7DNkz#q+yR4FHv zeO}SSqdO(&8g;PyK#T@sqcJ!pY(xP<wQ9$#A^zH*RLtQDKW3ljwfY#Y6NK~^(oOZ{Z zIS)wN3~izwL8T1gzr1rsm8Tfmik&5okLA6egH;h%j2i146F7ty8t_zAwBt-qFki7-8A@-T=}gz*AVfV z>7REoAw^lIW`yF+2R%qa1Y_fBTt>`M<@_{wej&|(1`AOTwBp=g5j(7Lbh;d#hA5Ut zNOMGCAhZT0M8??mS^;3FQE!)9W6STu2=b&xTxRV^qbkZHZ+JfO8gF;1XlP_!Z|=)Q zEg{H>ly(w*WIn;5TU{Do8-sMixHKNYNKL48lLQBdkefJTtP{GB5Y;`m(8B02SAHA5 z(I80i1~uQSNa7NR+tt1rYs|DHz&^a$L}QIxtA0HoQ7%_1*xn-GfoscPG18Ij6+P8uUH_&vAj6QSdcx8(i319Rb z#R>G?W-i!HNS+^tpZ>#gx(H}U7&WX1{ov$;l`hWuw7AHmj1oeSMa^KrixE_1c~vZ0 za*E;;Di%eJo-4A|AZX*`F>$2YB1E|+AqyiF6T)9N|BxeT*h$Joly`A{GjiicqI)(i_t?=>J`|1$J* zx_}O-oQ>I*S!(Bwb0qQB9QZA!GAR**VjzvBaCJ6OSlr#>tE&dRG8b_CAL4{Nc9Oyi zZ5pjUHAk1*Aawol)ERF412iY+(b2Ow($?ygK%`VtA6Hj5YC`0L}e`GBm&*3!64-~jO&h&lZr~Y%nKzR zt?%vcfKcTQ!qSCsQ?~T=LrCr5GPNqj3eZJbnhg&*@JGWJZDmJ1NuqA$^MZ8NL>|Ip zH%zID`B*cTi{ee>S!14M#aWtCzfy;`X08z|9&%^BS#ZWBg{uS3+%vZaX(MstlcP2b z-P-4|$8Td_ZKTmsbRbX8K?&ka1$l(@?T!%DCR}rQ4nd#+P9?aEVZFk9~Et{q4OoOnT=QEYIB@f`VjY$NEne`;N4z?vbXbQ z!@l3;UqHsK{s^4@X96#x!(N`BAmM~SB7U;l_9)>3n$@qD0khr#;Ub_hg3)WLbh)lj zMx^$fAi+LHbO_1v{7nv`ww` zhm`kzA)U-kj4+Q^1}4j~n@y}FzC0TGD!T+_S{L>Ar5=`I?d zlz-eErKw@O4>)IVA&u}Fw@+mfS~F*1Gpa*bT)gQOsuBSh2@2?oQF%4{^>);Fy=@Wd zW=U%~EQB-uTn&D@=}Sh=SvdBMJY=<3q2D-(L0lRV_}_^0|NlL$0Abt9Q$M*3r9e5u z;{|y)f{%80@Rqkh!qKdx6P7N@X}!Hk8Ku(*n%4UMyVyY~sZ*G``l{OD)C-*6HrA6< zhMtu?33N{>-O2Da(L{E8K??N}IDP@sf2Zn9c61w?OFst6u)HI&x{jw_*-DFT;SGpU zmBFj;18srZ(SH4cwjsT>GmJR%q@|GNBlv|lRfd8I+cfbmW%D9hnlhMR?LwP}8)ml4 z_^y959pMcmEQETt+ihOL6P!fhtPjb!>F5XsC>ab$crg`o zk-c*6Q(q+4J&$I7q$?_Vh>(b}h`5vyow_r)jPSOnedcg@XMJx$IA&DRuctx9?E#%%`Q*3uSxB=I(TAXhmujsasj?-< zUsg75hqEopBFu;M@Kwx2slBI-4kZLDBzQ7l&6>Mezx%Zh@k$>nt#HX@XgM#d30>;u={VlBbCv zTbQN{;V}q++u<3k2;+GODXr#LcU5%psN19yOWQuyR}rT@E^JT?HahMiktcA+OK|N* zc+s$C$)y@Jo4O!Tg79FXs{j+spjk}_$|OPwahQyV8MYciay}xXGes2ijGwpTDY|UA z!N++1qzi8e!FSnv*(&z|Oj)-sI6w4OUn1CAeF8<<2~rQvxhqcB9?dR%f7Sq35Vcu5 zB5xciaJUZd-+(EnyS5l2H(a$IV=FbHD#KA814fln(aAGnc&41JWfnJh!Q|pZNK+vU ze1$1UIJwXw$a%4b#D!b$G(@dgq1$I^VJUsFm?jDWFx}hBM$V+6OGhGm{-aR5!P2<)&TcN6DVdWwEg;c&Q|z9Gyh^rM#nxd zA#O&X!Cb*TZq9>?MkB!oNE}z7M^o?KhbBDdLxrMz7nbQB)xc}&$E)gx8759CS6Wxv zDp7MqgB}o?>I+c{Q?lpNieg7&L`NFsamJR-?~y8)UN$q`2Er~TBP_7HZM>@R7~a(t z{Xv7dx;)OmnFAM6RDAVAY-s>yyHi}k&=)_~5F0xHxkShVJCcf^f(w~#u?Ud^1LSFi zS*&223iMw6Su`#r4bu~AL++uzVvfd*Y-ZeR)WMV#H6KF+7*?j5;Emgxj!IZ`rV9=Q zxb8$f6^M5$a^(~{EE)?=s}^cdsUGnQ2Gx;K{R|;e?lsX0zK&GPM5@+T)YRcT(YqFi zpvx~|@=|vuE>>JK_Sxk@dNdAw3gdBi8d_~s6zTj_Iu>)ZvKB}s3EalKxvpBZJKHl>oc)o7j$*Gdejv zZaIhq8*Z|L5k|M6*q27FYNJRDAw%^u89}&qYr@+KOQO_ZB!&RXu_UON#CIzD$KIM3 zHw@}jNErmDMBDsR-IrHe~T>}o^pFJ+kWIQ5`cO{M;}v zG*Gb{bRQm<-&SW@)L;n_Ad2A4(ItrPR%i`Vd4VOOV!drb)s_kmU5&(K@IeU;y7(^{ zj@Y{V5%)5p*<3KRorDUl4i26eoUwr#C6MS&4Su9(CIob3O*Z=0U>Mzr_f1SkTo;iwJh;FpYbW`WRdq(CEa@t73LsGuR z%mkkfWyhrI%#{g+0=P(iUap(6ZXRP_MlmcfGPh!47PdY5ZNg^K;20N+KKuO$iu5{y z4Q_C2$HR0RvmPcTFaCtc!q}A+fU%+fyoG4yaWex=f1{6$vHiEVXb4fq$ETcdOyvcx ztk&md@gnp(I^8-Nz!IUmD#YV>czClgK|q6kX$JDXS=v@@tW&>{%r1|hVNQrh9t#PG zStVK*!xUJi-J}t1Z#@ij@E5l|ckbuqt^~f*M|lJw$L^AS0{uPXs1P!wEbfsY3-Z#g z8c4XuP2kL4S~K(V`g4SK>q{HS@Oh~?aAu90V7k0+I-;sr%+M>2smZ~5h|yxwb+^KjZGH z3t2~$@J6qJ5pM6EreNkQld9D2X`%zcnki>4BXS>r z$ZJG39~l%PzWm^U&CNy`<5JrK{fqLJ6iMv3 z*+@ZX4W83i17ZUkoPb#s+gzQT&_UT>mx0|BxqD9doEVvR_ZD<7rRtS>Z+=LB2Ia=2 zkDJ=VaASh?T+j)_(vk3`0Olv9RZ0(@*WXB3>bsDnAUkE{{5subisCHj3`56BmVPR? z)M=1M5*Xd|2R0b(dDQt3XRsr_#)oV^EDP`r%5zWZo(w8*;o7lH4$8SYMJF^QxzVfe z`OT4(w)YqS9(_P2lmyNoBhP^IG!cSK8~sdEgl;`Tn5r60q@4eNdm{`p4bjGpMI-fc z7AviK@?EUrqpJiNU6gHaACGmro+43}?3!Y4_1Nh;qkc0DlH(O_Z!BVgppEN-GRz{} zT1kf*aUavkag{Csw#Vc0h%<(^7YtD1V>0w05a-2~f#a6SE z#51@E#iWU}r0Q(K{r*c~pVj!C?(U3rsDo1|O&jCJ{AN!+_x*Z?dU2)XuC3Xco9OpJzzrN4yK=Z zNl$BxsF4c`uyU`l^1M^#60tbZ_1KwGK{@@AQAQBuRz$ldH~2ELMew$|czt6N_>Kh? zDInZ5>=$ee9hTf&k4|SD`BJ_)9dvQP*T&~+<16%_L=xp4BL<1DU0 zd0cC(biO>6k1WfIRMjqHG`D_PJiC`k?jbvu+*-Jasrt43QuEVPm{(lR*iMIfA2! zm4oslv@Zn=d9E%zT5LXr`x5)S)8kaRvyWPY$*lFXRn?30WOFY=I#88rHIFf+yxo|O zTMFuQLvw?TY=_n5@T=fV%jxcJD5JW_5-&9RNHbn-x-2!vML>yg28Xu6ZG|PRWw~VF zBA0m0Q}ZVmwbl*l0K9R82JRw!d>&I9b^|AMR}|mfnRZ-F(Gs`ySnyt>2X+PF3uPcA z8{im|V~HAe)Nxn_QBp6yrW`lc22Np`r>VWGKb)@cf_EX>7s^<8zfT%cN2Hq*q(jQ# zb`jRCyqfRjM8}9wZ1hX6iKMIsD1ISU9?g$vFm)@n`nrS98zo-Fs==*Z-J9Y*`f6C@ z{-}76<6YVomH)y^<^O-j*#8&5bNGK&g8%D{`ES3v|F2i|pJV=(j{n!}+kZX~e|+Qu zn#bSL@s}@`et-7!i;Vu3jz3-p{1lSk((zk5{{1V6-_r40I(|#X-%RGei@<*S9l!mK zU;WU(daS>tJB9P6`R%s9gU^s*MfELJoDAg+3F5_+r)k5cN_$-?` zx0PEhlt)!0*du!yvD<1j8!0qW=AMna#yWGhz@S9r{?~lE#j0OZ-3<1>s z`2Jtl1aCOoZN-1ELJqhd=pQT7`Z)Uf!aSXQ4%PvEc4g9YQi(Yjnz?^{vF`p_E}m2C zS)2Z{|I0URg@bFdI&sI^8tu+s^+Sh5XIoO8f55qWWBJ+B_ByXF3&CdbGb-fDb{og7 z(YxFPB_9=)Q7y0%$IvHs>=?|H3;DfbE{zb^=e zyLEM}hvQ_cGkkKq&Bnso35jt6uijX#do)|#Gji?h=u^A2E)frIS*!lso(^=dBpe z(3Oje$L2q-FLngZ#Io|Fr^j3~n+)O3aSHY%JHzoPu-VEfRx?yAOU$S*e1d0f8Zed1 zmsI_xsood%sJ&;7mAi9zf$?-6x8Lcb;l_?684?SRhUydHb7}Ohqx$==-?s4?+}G26 zO1z~$V{>FhpTKr^x$-PN{EKtNi+gNO?n#aI$L&*XgrV)lo;_ZbgUuLn1?M`WE@1VQ zCq&1gmfw;tB?)-l+em8D6;AwY5^bGx%2dN4j$frs0COU9mf?#^M3%kW(WLJK5v|UX zx6Bxfz59ga1;vU}4~y&5(V^j<%pdGZO4K58EjZ~b>Xhim+3#zIOW|#`k!i16*Y4o@ z24rKthF@B^UXn)OGcjA*zIc6A&{=M5r1YWU#nZjoA7a%ru=!M`bq_R^kTP8bM^7cM z2P6yDt~^0qhuWWayKHjnNw=CUw9^c6SC%8A2YOlLOL)Rt1Jx-H;6kBvsRjUA}ck=R*~)<$0X8sX~dNZZLdL>|%aF`CWl7 z+$Dtt;Q)274USisaQq9}*MX{(;fP};cxgK>x`rn&0_cJi?ULylp1tsE8zplyt_pWa zJM5B^=g{INoVS#<^Q^^i>(E`D!cc}~*iF+Pa6WhL%pE8VAJYU@2e2Y&h&~2$4 z{7-mLVgBPP&y6^2z*TT{DF$#QDpnBV$12ZG;EouV?d;th50q&tvB$IRU_tE1JCKLl zB7GE>bts2TU#@0n3rcfGTYeS(%56$&W;+x^f5gu)`@~oN-M&SHlk&cd^0-0#+wl}f z;XYPa!UL4 z-B#A}5JF8+$o%d3i|URU$TJiVhb0~mY3+g2#}9W3Q{2i48VuOMrb$1doFl4xK~HIl zr#w&*O6peUmVN|L6e`ef9hdr-1JQnU4Auqau!Doa{?CC3aI`o3#jf3pKWosg$sD<^ zwXgjosNsG1c^6Z9Q@BnHDb!CE#_8|e*7soq1^)9v<1J)kclY*Ibo{dvan3sz)uz5! zxjY~@ekiHd*!-*pG7uA(g0ycFP`@-M?e4i%T|!XEE|$oXq1U$vw7fjlcZQC^NlL}` z;q%nG8|9omop{ym(D=hMvI+GKHBA9ji59XCM9Rp~RXc)KpH7!XQrvxV-bkZyRk-!~ zeRYwt{sqx({^RPE_epp4cs!or*x9V+Nl2dNf5|t7`nnA|kMm(Y8#Fnz?2%}9dm3(j)fO}R`y%=Va>{q`%Kpvjajjf&~0Mm3|s z{J6Q6-j(q^Ih8GUl0?ZOFiKZS|L8cSPUe%(S|0Qp^;R9VC%n_ejKoVbH5rxUq{_>k z-hI4iji{Ii-6X%pe*W#JckC`JO>boU-5C<#$Z7%CcZ@g=44 znN9ZEmJf%{`JVGu5bB*V=MR-V#Btta1|z4BuNw=0{H6c4QQhLBHpSzszEweQK0oJ* z{sI?`>Z&hGR9utRd4n!>C&pcDx>-7UgZ=6^z51T1qY?Ny#+4mStvw@`3co> zwM6o;2W;c;(e>lTV;*xVF0LMR4DC5$>>Pd}Jn0@1p|kSBui@2>SCwM6-uG06GdfDo zd>Y;*6Nv2nre2WvHECMoIcMRs2OGza4=D+YCwxkj6aAR8shR>$T$K9werEs9kPM!3 zaZGT(`77v7{6_;R>K8)MPYnR)&H%u{(&Rr3q>t|{cgG*DMpf!1pHwC0?pgTfW{UQp z{yS+CV;855QfkKDRW(%^eNK0L5T4Kd{lV0+?ImL?%_G;Zj};oiVsucVhBMzYqhFFiA!(ZAQQel zf(e(gzBIFgtqC}+*?z`LCbL+)MKl;P1X&-iz{TB^N_rpEY`1$^d{+kD*AxFqlz_kF zWJR^Ta8XBVio4q|#`@tK;*d`MIhQY9`5Td}t8={_>V7z*T;JXa6_!{pdyWxQ*JtA- z$@ZnIexC*dajRBuD;k!0`)#MnmeWsZ2f#d5CAE{#mNu3SY_yd-R~Z5p!lcq&-^INN zebZh1y5Q-V=I^I+1XXQeJ`Ox7DWS2o7Gre}>IUL_a3dvOv3KE}qAcB0NyeMklVYCi zC*oGk@r0$F+IW*gd7bCK$a;LXlZi&=iIH&3_%sRXoMf5Q*m8eO*WTh3CZ#Ga;~91? z-eNEO?1isYPu9Z4=$vcjC~#;C+U%Kl&XkFmWwKD4gz`%K@xHE9#F?26WaFJq1RJ%F zgRJSWZmAevf8?~--Ev#DN((g+H@&K27q4?AF4THet~Ws77zl`6_c|wz2^Y5d&VTs* z1?Tmc7_wI>SLDLSH6>R0vdlcYx5*cMk1fB=XTDbXZ2FUXGGz^w!t|H$Pp;@uB@42G z?so4ypQqD|eXpx5sr6*PxBDkci@a;-ZW%V#GumUcE>I{ z0ZN1FZTs2D18b9q9f(rO{SUWTNL<0o=XXs6_r8mSe^To~Q5Jrx7Al`Mc={GuXRK{!E1{HGH%lJ~4PO$RF27PHiq+{-)C=R}=_!jn zJD&BXQ7Cbo?!8rLLGvBN{<3A$boIcOR9X)2u!&%{EUiAHoa8ifk?4W1qlzq6{5Cl% zdVcw)VMn)n>mP(G9zCjo)201>TT$yZq>)8y9;0>&3z?ynIL&w1Yz53|6<(9_uTOr+ zR@}~awyry{CXS)jND|((lIj8?rG)AqS`#oJ41T} z@zL_gg>!$Q%nMn!V?p6`T^^3lJ+T5?7ITkA^zy;=T~s(OO8#pPCeGxDXd&YPZ575$ zWv~lg)495w89q{Vz%ym!nV*ztk67wFk^?*WXK%+vZ@-AqI6!vyx>$P9uU+B)=-=>Z zbGMr4?0}qfe|9qejI-4xWD-hi=UL5P9Kxy0;-(JEVA~tCb?MDnSlLzHQt)9_PNFDZ z1y5DpCqHX&$4~6o>Rd>KjdHaQO{GqM>+MvuRJd{Ht>jUq6GaORfxQp2cb0^d+HUmI z@n~$$_dOdJzry#XRNlw?wZJPeV`2;0OK~4kfoi7%&7_0c=d(&{mu;g^N{@?i4QK9g zTJ%4AhJ2FV6m;vV0GvG0Lo~Ys!2(O)R=V^B8PJe;eKu$)@BSKoZgj|i9f_Q&eN%fkDY_tC2o-t+eB?MRTDdxbN1#c=qAAb&flOzF9Tsn=$|Dn}Mr!AA|^kc{>@ zA$XU+_VjICW?2Rgp-)yS*{XJd)VRXHcixQlVsj$L5*;bP ztE-7V3`?Z1)AZuWskCBQ5L+)bIud=qI4G~Q;6ZdTZK&l8Ig?ZDj>Odoj%twzl@(E8 zv(~PJ<;1(~wGBM2=Hk&7jZLeMdT6oHC&bFXpRB>u-@s4r8%ml7zLay%8B`^Vc{2#q z90qu6>MeGU%q6uOm)-k#9U1S0T7c(tY^v^Q)v4RcBb(dCeTcxf?FWDEPeev80R~6^ zdMC%9L-FVNU+n8>V(?c2f8AW}&!PZO2I|8vTh0Bw;9ob^`nBK+=qmnj5&z9LTYsnY z_g$9$q;-PsU+lT`_u_xw7U$36H4OhK{`XCCev3!c>c3|GPr{OkMa0hDE)T|e+@(b zEDr$j;DY9V^uj-b(!Uq~dzA1e0V$V%^8ZK7@b|)hHM4&f1psmQFLnRJ=$aT%fiebe QH30rmgJSyn=E2?n0f&Po;s5{u literal 0 HcmV?d00001 diff --git a/tests/docx.hanging_indent.native b/tests/docx.hanging_indent.native new file mode 100644 index 000000000..138a6967f --- /dev/null +++ b/tests/docx.hanging_indent.native @@ -0,0 +1,3 @@ +[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "hanging",Space,Str "indent,",Space,Str "with",Space,Str "the",Space,Str "left",Space,Str "side",Space,Str "set",Space,Str "to",Space,Str "the",Space,Str "left",Space,Str "margin,",Space,Str "and",Space,Str "it",Space,Str "wraps",Space,Str "around",Space,Str "the",Space,Str "line."] +,BlockQuote + [Para [Str "Five",Space,Str "years",Space,Str "have",Space,Str "passed,",Space,Str "five",Space,Str "summers",Space,Str "with",Space,Str "the",Space,Str "length"]]]