diff --git a/docxtpl/__init__.py b/docxtpl/__init__.py
index 1c0e1df..0ec37f1 100644
--- a/docxtpl/__init__.py
+++ b/docxtpl/__init__.py
@@ -9,6 +9,6 @@ __version__ = "0.19.1"
# flake8: noqa
from .inline_image import InlineImage
from .listing import Listing
-from .richtext import RichText, R
+from .richtext import RichText, R, RichTextParagraph, RP
from .subdoc import Subdoc
from .template import DocxTemplate
diff --git a/docxtpl/richtext.py b/docxtpl/richtext.py
index 75c3b1c..759eed0 100644
--- a/docxtpl/richtext.py
+++ b/docxtpl/richtext.py
@@ -119,5 +119,50 @@ class RichText(object):
def __html__(self):
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 += '' % parastyle
+
+ xml = ""
+ if prop:
+ xml += "%s" % prop
+ xml += text.xml
+ xml += ""
+ self.xml += xml
+
+ def __unicode__(self):
+ return self.xml
+
+ def __str__(self):
+ return self.xml
+
+ def __html__(self):
+ return self.xml
+
+
+
R = RichText
+RP = RichTextParagraph
diff --git a/docxtpl/template.py b/docxtpl/template.py
index b246ca7..e9c9cc4 100644
--- a/docxtpl/template.py
+++ b/docxtpl/template.py
@@ -160,7 +160,7 @@ class DocxTemplate(object):
flags=re.DOTALL,
)
src_xml = re.sub(
- r"({{r\s.*?}}|{%r\s.*?%})",
+ r"({{r.\s.*?}}|{%r.\s.*?%})",
r'\1',
src_xml,
flags=re.DOTALL,
@@ -173,7 +173,7 @@ class DocxTemplate(object):
r"-%}(?:(?!]|{%|{{).)*?]*?>", "%}", 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
# {%y xxx %} or {{y xxx}} template tag
# by {% xxx %} or {{ xx }} without any surrounding tags :
@@ -183,6 +183,18 @@ class DocxTemplate(object):
% {"y": y}
)
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 tags
+ # This allow for inline {rr }} and paragraph {rp }) styling
+ # This is mandatory to have jinja2 generating correct xml code
+ pat = (
+ r"](?:(?!]).)*({%%|{{)r%(y)s ([^}%%]*(?:%%}|}})).*?"
+ % {"y": y}
+ )
+ src_xml = re.sub(pat, r"\1 \2", src_xml, flags=re.DOTALL)
for y in ["tr", "tc", "p"]:
# same thing, but for {#y xxx #} (but not where y == 'r', since that
diff --git a/tests/richtextparagraph.py b/tests/richtextparagraph.py
new file mode 100644
index 0000000..e06bf47
--- /dev/null
+++ b/tests/richtextparagraph.py
@@ -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")
\ No newline at end of file
diff --git a/tests/templates/richtext_paragraph_tpl.docx b/tests/templates/richtext_paragraph_tpl.docx
new file mode 100644
index 0000000..738c502
Binary files /dev/null and b/tests/templates/richtext_paragraph_tpl.docx differ
diff --git a/tests/templates/richtext_tpl.docx b/tests/templates/richtext_tpl.docx
index bcf589e..be34203 100644
Binary files a/tests/templates/richtext_tpl.docx and b/tests/templates/richtext_tpl.docx differ