Rich Text Paragraph Formatting Update

This commit is contained in:
ST-Imrie 2025-02-28 17:53:26 +00:00
parent b97fa32f10
commit aa7b7a77e3
6 changed files with 92 additions and 3 deletions

View File

@ -9,6 +9,6 @@ __version__ = "0.19.1"
# flake8: noqa # flake8: noqa
from .inline_image import InlineImage from .inline_image import InlineImage
from .listing import Listing from .listing import Listing
from .richtext import RichText, R from .richtext import RichText, R, RichTextParagraph, RP
from .subdoc import Subdoc from .subdoc import Subdoc
from .template import DocxTemplate from .template import DocxTemplate

View File

@ -119,5 +119,50 @@ class RichText(object):
def __html__(self): def __html__(self):
return self.xml return self.xml
class RichTextParagraph(object):
"""class to generate Rich Text Paragraphs when using templates variables
This is much faster than using Subdoc class,
but this only for texts OUTSIDE an existing paragraph.
"""
def __init__(self, text=None, **text_prop):
self.xml = ""
if text:
self.add(text, **text_prop)
def add(
self,
text,
parastyle=None,
):
# If a RichText is added
if not isinstance(text, RichText):
text = RichText(text)
prop = ""
if parastyle:
prop += '<w:pStyle w:val="%s"/>' % parastyle
xml = "<w:p>"
if prop:
xml += "<w:pPr>%s</w:pPr>" % prop
xml += text.xml
xml += "</w:p>"
self.xml += xml
def __unicode__(self):
return self.xml
def __str__(self):
return self.xml
def __html__(self):
return self.xml
R = RichText R = RichText
RP = RichTextParagraph

View File

@ -160,7 +160,7 @@ class DocxTemplate(object):
flags=re.DOTALL, flags=re.DOTALL,
) )
src_xml = re.sub( src_xml = re.sub(
r"({{r\s.*?}}|{%r\s.*?%})", r"({{r.\s.*?}}|{%r.\s.*?%})",
r'</w:t></w:r><w:r><w:t xml:space="preserve">\1</w:t></w:r><w:r><w:t xml:space="preserve">', r'</w:t></w:r><w:r><w:t xml:space="preserve">\1</w:t></w:r><w:r><w:t xml:space="preserve">',
src_xml, src_xml,
flags=re.DOTALL, flags=re.DOTALL,
@ -173,7 +173,7 @@ class DocxTemplate(object):
r"-%}(?:(?!<w:t[ >]|{%|{{).)*?<w:t[^>]*?>", "%}", src_xml, flags=re.DOTALL r"-%}(?:(?!<w:t[ >]|{%|{{).)*?<w:t[^>]*?>", "%}", src_xml, flags=re.DOTALL
) )
for y in ["tr", "tc", "p", "r"]: for y in ["tr", "tc", "p"]:
# replace into xml code the row/paragraph/run containing # replace into xml code the row/paragraph/run containing
# {%y xxx %} or {{y xxx}} template tag # {%y xxx %} or {{y xxx}} template tag
# by {% xxx %} or {{ xx }} without any surrounding <w:y> tags : # by {% xxx %} or {{ xx }} without any surrounding <w:y> tags :
@ -183,6 +183,18 @@ class DocxTemplate(object):
% {"y": y} % {"y": y}
) )
src_xml = re.sub(pat, r"\1 \2", src_xml, flags=re.DOTALL) src_xml = re.sub(pat, r"\1 \2", src_xml, flags=re.DOTALL)
for y in ["p", "r"]:
# replace into xml paragraph or run containing
# {%rp xxx %} or {{rp xxx}} template tag
# by {% xxx %} or {{ xx }} without any surrounding <w:p> tags
# This allow for inline {rr <var> }} and paragraph {rp <var> }) styling
# This is mandatory to have jinja2 generating correct xml code
pat = (
r"<w:%(y)s[ >](?:(?!<w:%(y)s[ >]).)*({%%|{{)r%(y)s ([^}%%]*(?:%%}|}})).*?</w:%(y)s>"
% {"y": y}
)
src_xml = re.sub(pat, r"\1 \2", src_xml, flags=re.DOTALL)
for y in ["tr", "tc", "p"]: for y in ["tr", "tc", "p"]:
# same thing, but for {#y xxx #} (but not where y == 'r', since that # same thing, but for {#y xxx #} (but not where y == 'r', since that

View File

@ -0,0 +1,32 @@
"""
Created : 2025-02-28
@author: Hannah Imrie
"""
from docxtpl import DocxTemplate, RichText, RichTextParagraph
tpl = DocxTemplate("templates/richtext_paragraph_tpl.docx")
rtp = RichTextParagraph()
rt = RichText()
rtp.add("The rich text paragraph function allows paragraph styles to be added to text",parastyle="myrichparastyle")
rtp.add("This allows for the use of")
rtp.add("bullet\apoints.", parastyle="SquareBullet")
rt.add("This works with ")
rt.add("Rich ", bold=True)
rt.add("Text ", italic=True)
rt.add("Strings", underline="single")
rt.add(" too.")
rtp.add(rt, parastyle="SquareBullet")
context = {
"example": rtp,
}
tpl.render(context)
tpl.save("output/richtext_paragraph.docx")

Binary file not shown.

Binary file not shown.