From ccdf20a121b1af64e9d65f4dfaadb35045645ac6 Mon Sep 17 00:00:00 2001 From: Eric Lapouyade Date: Wed, 15 Apr 2020 15:11:47 +0200 Subject: [PATCH] v0.9.0 --- CHANGES.rst | 70 ++--------------------- docs/conf.py | 4 +- docs/index.rst | 43 +++++++++++--- docxtpl/__init__.py | 5 +- tests/templates/merge_paragraph_tpl.docx | Bin 10880 -> 12150 bytes 5 files changed, 43 insertions(+), 79 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 41e77d2..f5c2744 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,7 @@ +0.9.0 (2020-04-15) +------------------- +- New syntax : {%- and -%} to merge lines/paragraphs + 0.8.1 (2020-04-14) ------------------- - fix #266 @@ -14,103 +18,37 @@ ------------------- - Add the possibility to add RichText to a Richtext - Prevent lxml from attempting to parse None - -0.6.3 (2019-06-20) -------------------- - PR #207 and #209 - -0.6.2 (2019-06-09) -------------------- - Handle spaces correctly when run are split by Jinja code (#205) - -0.6.1 (2019-06-05) -------------------- - PR #203 - -0.6.0 (2019-06-03) -------------------- - DocxTemplate now accepts file-like objects (Thanks to edufresne) 0.5.20 (2019-05-23) ------------------- - Fix #199 - -0.5.19 (2019-05-23) -------------------- - Add support for file-like objects for replace_media (#197) - -0.5.18 (2019-05-20) -------------------- - Fix #176 - -0.5.17 (2019-01-20) -------------------- - Delegated autoescaping to Jinja2 Environment (#175) - -0.5.16 (2019-01-11) -------------------- - Force to use python-docx 0.8.7 (#170) - Add getting undeclared variables in the template (#171) - -0.5.15 (2019-01-02) -------------------- - Added `PAGE_BREAK` feature (#168) - -0.5.14 (2018-12-23) -------------------- - Fixed issue #159: autoescaped values for both str and unicode. - -0.5.12 (2018-12-18) -------------------- - Fix tables with gridSpan that have less cells after the tc forloop (#164) - -0.5.11 (2018-11-21) -------------------- - Smart double quotes in jinja tags are now converted into simple double quotes - -0.5.10 (2018-11-20) -------------------- - Smart quotes in jinja tags are now converted into simple quotes - Add custom jinja filter example in tests/ - Reformat the code to be a little more PEP8 compliant - -0.5.9 (2018-11-18) ------------------- - Add {% hm %} tag for table columns horizontal merging (Thanks to nickgashkov) - Split tests/tests_files dir into templates and output dirs - -0.5.8 (2018-11-08) ------------------- - autoescape support for python 2.7 - fix issue #154 - -0.5.7 (2018-11-07) ------------------- - Render can now autoescape context dict - -0.5.6 (2018-10-18) ------------------- - Fix invalid xml parse because using {% vm %} - -0.5.5 (2018-10-05) ------------------- - Cast to string non-string value given to RichText or Listing objects - Import html.escape instead of cgi.escape (deprecated) - -0.5.4 (2018-09-19) ------------------- - Declare package as python2 and python3 compatible for wheel distrib - -0.5.3 (2018-09-19) ------------------- - Add sub/superscript in RichText - -0.5.2 (2018-09-13) ------------------- - Fix table vertical merge - -0.5.0 (2018-08-03) ------------------- - An hyperlink can now be used in RichText 0.4.13 (2018-06-21) diff --git a/docs/conf.py b/docs/conf.py index 5ed19b7..e49608b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,9 +53,9 @@ copyright = u'2015, Eric Lapouyade' # built documents. # # The short X.Y version. -version = '0.7' +version = '0.9' # The full version, including alpha/beta/rc tags. -release = '0.7.x' +release = '0.9.x' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/index.rst b/docs/index.rst index 187a9d5..7e8cf18 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -89,6 +89,29 @@ But use this instead in your docx template :: This syntax is possible because MS Word considers each line as a new paragraph and ``{%p`` tags are not in the same paragraph in the second case. +Split and merge text +.................... + +* You can merge a jinja2 tag with previous line by using ``{%-`` +* You can merge a jinja2 tag with next line by using ``-%}`` + +A text containing Jinja2 tags may be unreadable if too long:: + + My house is located {% if living_in_town %} in urban area {% else %} in countryside {% endif %} and I love it. + +One can use *ENTER* or *SHIFT+ENTER* to split a text like below, then use ``{%-`` and ``-%}`` to tell docxtpl to merge the whole thing:: + + My house is located + {%- if living_in_town -%} + in urban area + {%- else -%} + in countryside + {%- endif -%} + and I love it. + +**IMPORTANT :** Use an unbreakable space (*CTRL+SHIFT+SPACE*) when a space is wanted at line beginning or ending. + + Display variables ................. @@ -96,7 +119,7 @@ As part of jinja2, one can used double braces:: {{ }} -But if ```` is a RichText :ref:`RichText` object, you must specify that you are changing the actual 'run' :: +But if ```` is a RichText_ object, you must specify that you are changing the actual 'run':: {{r }} @@ -114,7 +137,7 @@ method to concatenate several strings and styles at python side and only one Cell color .......... -There is a special case when you want to change the background color of a table cell, you must put the following tag at the very beginning of the cell :: +There is a special case when you want to change the background color of a table cell, you must put the following tag at the very beginning of the cell:: {% cellbg %} @@ -124,7 +147,7 @@ Column spanning ............... If you want to dynamically span a table cell over many column (this is useful when you have a table with a dynamic column count), -you must put the following tag at the very beginning of the cell to span :: +you must put the following tag at the very beginning of the cell to span:: {% colspan %} @@ -133,11 +156,13 @@ you must put the following tag at the very beginning of the cell to span :: Escaping ........ -In order to display ``{%``, ``%}``, ``{{`` or ``}}``, one can use :: +In order to display ``{%``, ``%}``, ``{{`` or ``}}``, one can use:: {_%, %_}, {_{ or }_} + .. _RichText: + RichText -------- @@ -153,9 +178,9 @@ you do not specify a style in ``RichText()``, the style will go back to a micros This will affect only character styles, not the paragraph styles (MSWord manages this 2 kind of styles). Hyperlink with RichText -....................... ++++++++++++++++++++++++ -You can add an hyperlink to a text by using a Richtext with this syntax :: +You can add an hyperlink to a text by using a Richtext with this syntax:: tpl=DocxTemplate('your_template.docx') rt = RichText('You can add an hyperlink, here to ') @@ -167,7 +192,7 @@ Inline image ------------ You can dynamically add one or many images into your document (tested with JPEG and PNG files). -just add ``{{ }}`` tag in your template where ```` is an instance of doxtpl.InlineImage :: +just add ``{{ }}`` tag in your template where ```` is an instance of doxtpl.InlineImage:: myimage = InlineImage(tpl,'test_files/python_logo.png',width=Mm(20)) @@ -200,7 +225,7 @@ See tests/escape.py example for more informations. Another solution, if you want to include a listing into your document, that is to escape the text and manage \n, \a, and \f you can use the ``Listing`` class : -in your python code :: +in your python code:: context = { 'mylisting':Listing('the listing\nwith\nsome\nlines \a and some paragraph \a and special chars : <>&') } @@ -324,7 +349,7 @@ By this way you will be able to add some custom jinja filters:: doc.render(context,jinja_env) doc.save("generated_doc.docx") -Then in your template, you will be able to use :: +Then in your template, you will be able to use:: Euros price : {{ price_dollars|multiply_by(0.88) }} diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index 96a8997..211bd79 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -7,7 +7,7 @@ Created : 2015-03-12 import functools import io -__version__ = '0.8.1' +__version__ = '0.9.0' from lxml import etree from docx import Document @@ -410,7 +410,8 @@ class DocxTemplate(object): tpl.replace_media(io.BytesIO(image_stream), io.BytesIO(new_image_stream)) Note: for images, the aspect ratio will be the same as the replaced image - Note2 : it is important to have the source media file as it is required + + Note2: it is important to have the source media file as it is required to calculate its CRC to find them in the docx """ diff --git a/tests/templates/merge_paragraph_tpl.docx b/tests/templates/merge_paragraph_tpl.docx index 71faa5a5168cf2d69650e8dfa78f35cc8b2c133c..9d5e38893edf0269971cd513e5a92621d9c16514 100644 GIT binary patch delta 6293 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 delta 5025 zcmY+IbzBtP_s5s+?goJsgk2DXRis$^|4J8flO&DQS=vkY*_n5EcoS zkRLw3-|u<8-}&Rd-ZOLWna|9bd+#~t+&mawOF{qyHJq!d;ebHj89^Wl5D4V!>R~Nl z?P}%iY~$hu^>cRGGBk6|5~L2wZMe1M*mfq^Dm02@EU$W5ETLAOdH%$s=UF8q(^p(Z z_|;K8R*^^quD%|82?2j|)GB$g{7GGNf>joivJc1B%Y_6l0f+p|D0t7-Wo6a$+>Vx< zavA_pDo!mgay-xR&y~t4ap}H(EU$-26G{lvZa3lOoNtQgQsAJ*qU9(ToqrRhRW5}d zAm!*vEbN@<#aDS1MUeJ1aO<%yAK9lJ{jsvFsBcjVyK1$Kvr48-=2mRms_vn%p3fT4 zlaz~SQ6>59?$QOMGWAq%SA0oz3nY}Q#tgVe@C;?nC?Z4jSPd>A`?feoh*drtt&D%> zmF&!Vk2Gh#))Uh^`cn*;H$7be%+YsBu2@m1cPod&E%)<@bl%s}q|-L_Q&IKhU)U4D zEURdsH=TeCW~i0Kjk4*ZzNyeGy4%hSpL+QDwMaYCQ=y&g*mh#~BkYJmyb43Pl7KOY z{8h8+=()z>E0Zei-#*-0Gmp#oJ~H9T_QCLr3|(aUv_p;frLmtZyU{y$1sk%*^9x@G z9ngZ>6ig{(EVQc%i2A6k{qvYnRTuUIg{@uL>LrD!&J=ZJ17f`}!yJo&K-05JZ({EZ zv07s4Dn2t~xhZaxsGgVkLG9!~q4kn2`;abr~*b%PD;7XY)jhUJE7GJ6}s zwx4r8Vs%v2l{3YiKdd#;>%MBlGC4Do0})B5lW`Lot9}6q2wkqz)ugRj0X1aDi`2Pw zLE{UTp^kOiP@OeL3J%#cN{_PliO>;gw}PE6ni9TY9S6NU(%Vp6mV5(G4C$`<)u!Jp zkQBJvH<6n%F{#|~PK$<&WN|f_u_JbzBu;z1mg!Zs<`&73eLr#YH?cKJu$}1vC9hrf z6OVh)18KzhVydy_m!UH$z@XyoyNMSM&>A;eLO}YX`T1ew{_#?a*3?;hfM3FmEr&ff z<00HG?+kZUl7?&wRKwIWhxQ4a9B0b!yl!3FUb+5puH!jFxfUsBkf|P+AaQmibgUb% z7{i#n)h%6lP%&+tgZ7d5u(QuXzQk2#7Zikj`)#Xm2_B#-B1h>7xK-}A-A5lK&grEI z`mA-v)m!6t!fuWX9{_ig@%FY-Pu+D%kobl#G?;aM(c3mqW>dHAMHHrDSPoHt0SiW~ zwX#QDPZRt0*u%|$j~(|*Upt3JQ1j(y8f;Vmt0FWqc zXDenLy+HwO*-HInv8@R|$AY+FNAf(=8BcV>87$2ml4wcaF2P?_rP%!nyj1ZW$smy= zKfcCWejkCJl?+1`bVi@Iu;td^>tCwPp-A`?41mM*7qjMZ2cKz4-1Ugr!B`DJp<75 zX?)#vf=8US%TyreM@dbHcSVDA2z+rR&yS_NiRC=+bf1)^x7BHBwJHm%=_Z-a6vv> z2h^Reb`Cl;8s}O_3Vvt#FfD&v%=Q;fXOusbu=hgsc5ub#(S?LFxd1s0v%n42-0$uF zCD^Wa`G<$(B@(skVl=9^d4AGDDrVR09Mv@Q-z;&dPQ>{FfBA1jrXf?S-gb@*#hPg|(n=}Lb^xLHD(xXG9KK`b) zj9`XlnElKH{;Ti|HE@=F68gPuTSi3OFpvZ`3a_vf=^I0Sbz&tIde)Lo=CJcD+X+u3 z&bmnjSJ~K-^t%NvC-~P0a;EST#Pg4 zOydphV7juD?w?j$sloSs6}hp2d_VRh>50c92ZGP!#U|gdl)6n`W`x?e_SjgdxdKUx z7vt(tb$TQPlc^T0D^8kLXWB7gPG*h~TXyE414;S;_g$ryR`A%yWzu1G?5B2rSr$Lk zVQJ+?i-1-RBfa;6{x?R{$Ne^)_@-vj1`W@0A0K8U6BqX*@o?)aw>{mu8nthq=DMq; zzjuDMzAD`;hz!fw&LkN*9Ak*G@%qB^j(5jKf4e4ktw?mc;-wqXP5M@)@53R)5+^`4C(}6W&M4$3M zw`Is*ANpJyxc2x0cum)ZfuP``uHRuQ!X&J`RPhS9n^7Z}^(m}u7=X^G#wS7Y4o(!A z_K(?@{`lop6b=!OkKbla*W0*K5)C#v(M@&P$=NgZ#b^82enfozuyI~5@)a+#G{9lV|ngKVJaHuk~&rvR#IIZ$XU zzi*ByIZ4XbXH33z7L&=4$BeRM7INZPfCs867#MoreTmrwEgcdN2tK3XXQBvKqh`-t znLNP%lyjk|n#^PTyU50E3eFpdCgs@Q35ibx;nXX(5{Vu9V*pOX8`>s9LRfQj*8I_8 z_-ofKOyrftf-Oad{@iNvmP(ju)n~mwo}k6`iY{1Ton95tzjBk;w(N(iG(Im9Ju@E{ z;7!|XDIrmrW6NfKqdvp+xhRg}8h_hQDektNzhEb%o_Ua_)*e#X}MEwD--g6<_22`QHgIG09yR?zRT>6NCU4 z4bYI~th@A>d~j`TEC?@gO_%*8BJJg3euHU7zJ!Y9kH!~#^16c~Mjjzor_IJvmIn)~ z{XZ&@c!#dVW;gR%hgXSYOG8)ORE1t0$B7m!=)c}zv6TOE*;rf6X6rbUuu@=-RUY)% zkW$$Mu8()wj*c|n1idLjbxS*Gyp8Dk-~;%2_}PcXFBAS$IkG06m=pU-Nc3)aCEvUT z&MvjjzB01Fs*#Xj8x`{=9H-@LX%5QM@q*g%LX5yShP3G6`l0B^fpbLc4cWSRY1o7Z zWO|6vH^Y=0ZSy+fHhX`8@#wdFx^x+n8*@nu{DVg4UjvHhV|hX=&3MW{HkW0Sz+3=( zK)*6bC;xN%WVF%DUY5O^E5 zT_)@kJ;VRIO3nAe>BKFf`am8;glF5gsDjVl_lY4sh3M2;k`G!vgYObO`<*!y7o;yj z^sbR6szo;Col#o1Zfoakk0t{YA`Te-8Vb#7rZb3{j;Tu|x?OoX7@not3b%mMtGr7= ze_Zk_ltoV{4m2x9YF+@@R|F@%BIu60|E zV+2xa=V`SS%Ge%-g<9a%_*X;sM(A(N0!I({3g=rxo`2NyW!i_p3_Sv$*QY7CTEvX~ zE*5IR&B=N>CzL9=Swuf>d{Vda3&v3HWx`Lg;b@(<_k?py1RH2u_$Xgv7Ms z#o}WnCi%!b&q<*a4ZO85_m{a`ly_&Z!MUq1$-7-$Qp9ZrkBtWJHCw~WTTvgayH0{dPyHN5R03eZla7b^0Mpas>H=>)d%7xMp z0xy(MgsX3>#hSq?@=jEP1qFzw)N*iu zcMz}xP2wqe<#!sKoEP|3TNr?LKPsLBkVt=)^mC>6;L_r83d1`$85a9d8Kw(_{jI{B z5c#*=|1jR-cOf@G<%$_sMN(X%f7k29s2o9gEDWP>F7hKXK5(l!?oKPImTm_DwU3uW zsPUcjep0P?IH1B3BJ$_e)6@UYIH=dGk6`98Qayd@t^twI9laj%L#kVTXw09T{adL& zkIbKszOcAH{C44xe3y3&jy#-L#dkysIilr)s?{yR+)_0DCj~wSfGxSlsXV+UKUS#m4 zh+2tZ5z>&{b9X$*({`kFYdtQBY;_HvD@Lzm1Cc%c$Wp+v<@_#|zzbdYYo^;Z(f7!S z$)B{eN6ajrEhctdQQ>00Lcv)Y*i6Uwg3ZfF?^k8dYXNWk+enzU*50&k?RQRq!~< zhOt3k(BaynKiwLP_OeJukMWC3A+%4`Ek`rIw4WPrwl;m8+2pKD7SZK%u3BwM)I7$2 z5>Ph*;`jKHaWJi35OlWb)z0yj;5672w4tI~wUOvsoP>$?USY4jTxR~)LTtbB z5E=Z7g#Q+|5J3=4%m7lvIOIO_e`i{EY4$&dGRL z5cxk{|9}t^2y|B})ADe2^AvdQ=7!jSP&5A%|6u-aLG9lWNEQUS04MXmJ2?nM_V3+0 RvSLSQ3UJ_--T!m-e*g`|c6a~)