RichText & Paragraphs¶
Template variables are ideal when LibreOffice already contains the document structure. RichText and Paragraph are the foundation for sections whose structure must be assembled in PHP.
A RichText object is a container. It can hold paragraphs, images, tables, lists, and other ODT elements. A Paragraph represents a native ODT paragraph and can contain differently styled text runs, line breaks, tabs, hyperlinks, and embedded elements.
Build a generated section¶
Suppose the template contains:
Build the replacement in PHP:
use OdtTemplateEngine\Elements\Paragraph;
use OdtTemplateEngine\Elements\RichText;
$paragraph = new Paragraph();
$paragraph
->addText('Important: ', ['bold' => true])
->addText('this text remains editable.', ['italic' => true]);
$intro = new RichText();
$intro->addParagraph($paragraph);
$template->setElement('intro', $intro);
The result is native ODT content, not HTML pasted into the document.
RichText as a document-section container¶
A RichText block can combine several kinds of content:
$section = new RichText();
$section->addParagraph('Profile');
$section->addParagraph(
'Experienced developer with a focus on document automation.'
);
$section->addBulletList([
'PHP development',
'OpenDocument generation',
'Document workflows',
]);
$template->setElement('profile', $section);
For larger sections, build explicit Paragraph, ListElement, ImageElement, or RichTable objects and add them to the same container.
Paragraph text styles¶
Paragraph::addText() accepts an inline text-style array:
$paragraph = new Paragraph();
$paragraph
->addText('Normal text. ')
->addText('Bold text. ', ['bold' => true])
->addText('Colored text.', [
'color' => '#12324a',
'font-size' => '11pt',
'font-family' => 'Arial',
]);
Common text options include:
[
'bold' => true,
'italic' => true,
'underline' => true,
'color' => '#333333',
'background-color' => '#fff4cc',
'font-size' => '11pt',
'font-family' => 'Arial',
]
These describe the text itself. Paragraph geometry is a separate concern.
Paragraph styles¶
A paragraph style controls properties such as spacing, alignment, indentation, borders, padding, and line height.
$paragraph = new Paragraph(null, [
'margin-top' => '0.3cm',
'margin-bottom' => '0.1cm',
'text-align' => 'left',
'line-height' => '110%',
'border-left' => '2pt solid #12324a',
'padding-left' => '0.2cm',
]);
$paragraph->addText('A styled paragraph.');
The important distinction is:
Paragraph style
├── spacing
├── alignment
├── indentation
├── borders
├── padding
└── line height
Text style
├── font family
├── font size
├── bold / italic
├── underline
└── color
Keeping these responsibilities separate makes complex documents easier to reason about and produces cleaner ODF structures.
Named paragraph styles¶
For a reusable semantic style, define a meaningful named paragraph style on the current document, then reference that name from paragraphs:
$template->styles()->defineParagraph('DocumentSectionHeading', [
'margin-top' => '0.4cm',
'margin-bottom' => '0.1cm',
'border-bottom' => '1.5pt solid #12324a',
'padding-bottom' => '0.03cm',
]);
$heading = new Paragraph('DocumentSectionHeading');
$heading->addText('Experience', [
'bold' => true,
'font-size' => '12pt',
]);
The definition is document-local and semantically owned by the current
document. new Paragraph('DocumentSectionHeading') is only a named style
reference; it does not define or register the style. This pattern is useful in
larger documents because generated ODT styles retain understandable names such
as DocumentSectionHeading instead of being only implementation-generated
identifiers.
For one-off paragraph styling, pass friendly style options directly to the
Paragraph constructor. The document-style facade is for reusable generated
named paragraph definitions.
Line breaks and tabs¶
A paragraph can contain native ODT line breaks and tabs:
$paragraph = new Paragraph();
$paragraph
->addText('First line')
->addLineBreak()
->addText('Second line')
->addTab()
->addText('After tab');
For aligned tabular text, define tab stops:
$paragraph = new Paragraph();
$paragraph
->addTabStopDefinition(4.0, 'left')
->addTabStopDefinition(10.0, 'right')
->addText('Item')
->addTab()
->addText('129.90');
Tabs are useful for smaller aligned text structures. Use native ODT tables when the content is genuinely tabular or needs stable cell structure.
Hyperlinks¶
Paragraph can add native hyperlinks:
$paragraph->addHyperlink(
'Project website',
'https://example.com',
['color' => '#1a5fb4', 'underline' => true]
);
Adding arbitrary ODT elements¶
RichText::addElement() accepts an OdtElement:
Images can also be placed inside paragraphs when inline placement is needed:
This compositional model is what makes RichText useful for larger generated regions.
Recommended architecture¶
For a complex section, prefer a small rendering method that receives application data and returns a RichText block:
function buildProfile(array $profile): RichText
{
$content = new RichText();
$heading = new Paragraph();
$heading->addText('Profile', ['bold' => true]);
$content->addParagraph($heading);
$content->addParagraph($profile['summary']);
return $content;
}
$template->setElement('profile', buildProfile($profile));
This keeps application data separate from ODT rendering and prevents the LibreOffice template from accumulating large amounts of presentation logic.
Related samples¶
- L04 — Rich Content builds several native
Paragraphobjects in aRichTextblock and inserts them into a template-owned placeholder. - B01 — advanced tabs, margins, borders, and paragraph styles
- S01b — Professional CV · Structured Template — professional mixed-ownership document with bounded RichText regions
Continue with Lists, Tables, and Images for structured child elements.