From 5f6a5c4d6c15946798cacaff9c80db892dd341cf Mon Sep 17 00:00:00 2001 From: Max Podolskii Date: Thu, 27 Dec 2018 22:21:46 -0800 Subject: [PATCH] Added `PAGE_BREAK` feature: use '\f' in your text to get a manual page break rendered. --- docs/index.rst | 4 ++-- docxtpl/__init__.py | 22 +++++++++++++++------- tests/escape.py | 5 +++-- tests/templates/escape_tpl.docx | Bin 11054 -> 12419 bytes 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index b2a802b..89defe2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -189,12 +189,12 @@ especially ``<``, ``>`` and ``&``. In order to use them, you must escape them. T * ``context = { 'var':escape('my text')}`` and ``{{ }}`` in the template. * enable autoescaping when calling render method: ``tpl.render(context, autoescape=True)`` (default is autoescape=False) -The ``RichText()`` or ``R()`` offers newline and new paragraph feature : just use ``\n`` or ``\a`` in the +The ``RichText()`` or ``R()`` offers newline, new paragraph, and page break features : just use ``\n``, ``\a``, or ``\f`` in the text, they will be converted accordingly. 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 and \a, +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 :: diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py index a64ff85..2044eb8 100644 --- a/docxtpl/__init__.py +++ b/docxtpl/__init__.py @@ -32,6 +32,8 @@ import zipfile NEWLINE_XML = '' NEWPARAGRAPH_XML = '' TAB_XML = '' +PAGE_BREAK = '' + class DocxTemplate(object): """ Class for managing docx files as they were jinja2 templates """ @@ -582,6 +584,7 @@ class Subdoc(object): def __html__(self): return self._get_xml() + class RichText(object): """ class to generate Rich Text when using templates variables @@ -612,10 +615,11 @@ class RichText(object): text = six.text_type(text) if not isinstance(text, six.text_type): text = text.decode('utf-8',errors='ignore') - text = ( escape(text) - .replace('\n', NEWLINE_XML) - .replace('\a', NEWPARAGRAPH_XML) - .replace('\t',TAB_XML) ) + text = (escape(text) + .replace('\n', NEWLINE_XML) + .replace('\a', NEWPARAGRAPH_XML) + .replace('\t', TAB_XML) + .replace('\f', PAGE_BREAK)) prop = u'' @@ -670,8 +674,10 @@ class RichText(object): def __html__(self): return self.xml + R = RichText + class Listing(object): r"""class to manage \n and \a without to use RichText, by this way you keep the current template styling @@ -683,9 +689,11 @@ class Listing(object): # If not a string : cast to string (ex: int, dict etc...) if not isinstance(text, (six.text_type, six.binary_type)): text = six.text_type(text) - self.xml = ( escape(text) - .replace('\n', NEWLINE_XML) - .replace('\a', NEWPARAGRAPH_XML) ) + self.xml = (escape(text) + .replace('\n', NEWLINE_XML) + .replace('\a', NEWPARAGRAPH_XML) + .replace('\t', TAB_XML) + .replace('\f', PAGE_BREAK)) def __unicode__(self): return self.xml diff --git a/tests/escape.py b/tests/escape.py index 9f12654..2addc87 100644 --- a/tests/escape.py +++ b/tests/escape.py @@ -3,9 +3,10 @@ from docxtpl import * tpl = DocxTemplate('templates/escape_tpl.docx') context = {'myvar': R('"less than" must be escaped : <, this can be done with RichText() or R()'), - 'myescvar':'It can be escaped with a "|e" jinja filter in the template too : < ', - 'nlnp' : R('Here is a multiple\nlines\nstring\aand some\aother\aparagraphs\aNOTE: the current character styling is removed'), + 'myescvar': 'It can be escaped with a "|e" jinja filter in the template too : < ', + 'nlnp': R('Here is a multiple\nlines\nstring\aand some\aother\aparagraphs\aNOTE: the current character styling is removed'), 'mylisting': Listing('the listing\nwith\nsome\nlines\nand special chars : <>&'), + 'page_break': R('\f'), } tpl.render(context) diff --git a/tests/templates/escape_tpl.docx b/tests/templates/escape_tpl.docx index 6a97756a2b76611152192df36f755424929bd15a..eb0cfe370bf260db2ef46a63b4d4f6a9c477ca69 100644 GIT binary patch literal 12419 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 literal 11054 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 F{{sL^VSoSt