No description
Find a file
phedor ead6d89792
All checks were successful
CI Pipeline / build_and_test (push) Successful in 57s
test: remove test, fix syntax for php8.2
2026-07-20 12:59:54 +03:00
.forgejo/workflows ci: add forgejo ci 2026-07-20 12:50:24 +03:00
.opencode/skills feat: page-break, поворот текста в заголовках, colspan, rowspan 2026-07-13 15:32:07 +03:00
examples feat: add absoluteTextField API with custom pageLayout and content-aware visual compare scoring 2026-07-13 18:34:44 +03:00
src test: remove test, fix syntax for php8.2 2026-07-20 12:59:54 +03:00
tests test: remove test, fix syntax for php8.2 2026-07-20 12:59:54 +03:00
tools feat: add absoluteTextField API with custom pageLayout and content-aware visual compare scoring 2026-07-13 18:34:44 +03:00
.gitignore feat: add absoluteTextField API with custom pageLayout and content-aware visual compare scoring 2026-07-13 18:34:44 +03:00
composer.json refactor: fix PHPStan level 8 type errors and remove unused Component.php 2026-07-14 12:35:15 +03:00
composer.lock chore: add PHPStan config and PHPDoc type annotations 2026-07-14 11:50:26 +03:00
justfile test: remove test, fix syntax for php8.2 2026-07-20 12:59:54 +03:00
phpstan.neon chore: add PHPStan config and PHPDoc type annotations 2026-07-14 11:50:26 +03:00
phpunit.xml initial commit: ODT generator with table styles, borders, and PHPUnit tests 2026-07-11 00:44:16 +03:00
README.md feat: Изменено api для генерации документа 2026-07-12 03:26:49 +03:00

PHP ODT Generator

Pure PHP library for generating OpenDocument Text (.odt) files. Functional component architecture with schema validation.

Requirements

  • PHP 8.2+
  • zip extension
  • xml extension

Installation

composer require odt/generator

Quick Start

use Odt\Odt\Document;

Document::save(
    ['title' => 'My Document', 'creator' => 'My App'],
    'output.odt',
    Document::paragraph('Hello, World!'),
    Document::centeredParagraph('Centered Title', ['fontSize' => '18pt', 'font-weight' => 'bold']),
);

Architecture

Components are plain arrays validated against schemas. The Document class provides static factory methods and a single root() / save() entry point.

src/Odt/
  Core/
    H.php              # h()/hc() hyperscript + XmlElement
    Schema.php         # Schema definition (tag, attrs, children, validateFn)
    Validator.php      # Static registry, validate()/validateTree()
  Schema/
    ParagraphSchema.php
    TableSchema.php
    StyleSchema.php
  Document.php         # Static factories + root()/save()/send()
  Render.php           # Static XML generation
  Zipper.php           # Static ZIP packaging
  Component.php        # Function wrappers → Document::

API Reference

Document

Method Description
root(array $meta, ...$components) Build ODT, return ZIP data as string
save(array $meta, string $path, ...$components) Build and write .odt file
send(array $meta, string $filename, ...$components) Stream .odt to browser

Component Factories

Method Description
paragraph(string $text, array $props) Add a paragraph
centeredParagraph(string $text, array $props) Add centered paragraph
rightParagraph(string $text, array $props) Add right-aligned paragraph
spans(array $parts, array $props) Paragraph with inline styled spans
lineBreak() Insert an empty line
table(string $name, array $headers, array $rows, array $style) Add a table

Paragraph Properties

Property Description Example
fontSize Font size '12pt', '14pt'
font-weight Font weight 'bold'
font-style Font style 'italic'
color Text color '#2e75b6'
align Alignment 'left', 'center', 'right'

Table Style

Method Description
tableStyle(array $props) Build a table style array
thinBorder() 0.05pt solid black border
thickBorder() 0.1cm solid black border
noBorder() No visible border
dashedBorder() Dashed line style
dottedBorder() Dotted line style
headerStyle(array $props) Configure header cell style

Header/row properties

Property Description Example
fontSize Font size '10pt', '8pt'
font-weight Font weight 'bold', 'normal'
color Text color '#ffffff', '#333333'
backgroundColor Cell background '#d9e2f3', '#f0f0f0'
align Text alignment 'left', 'center', 'right'

Examples

Basic document

Document::save(
    ['title' => 'Report'],
    'report.odt',
    Document::paragraph('Introduction text here.'),
    Document::paragraph('More content.', ['fontSize' => '14pt']),
);

Styled paragraphs

Document::save(
    ['title' => 'Styled'],
    'styled.odt',
    Document::paragraph('Normal text.'),
    Document::centeredParagraph('Title', ['fontSize' => '18pt', 'font-weight' => 'bold']),
    Document::centeredParagraph('Subtitle', ['fontSize' => '14pt', 'color' => '#2e75b6']),
    Document::rightParagraph('Date: July 2026', ['font-style' => 'italic']),
);

Inline styled spans

Document::save(
    ['title' => 'Spans'],
    'spans.odt',
    Document::spans([
        'This is ',
        ['text' => 'bold', 'font-weight' => 'bold'],
        ' and this is ',
        ['text' => 'colored', 'color' => '#ff0000'],
        '.',
    ]),
);

Default bordered table

Document::save(
    ['title' => 'Inventory'],
    'inventory.odt',
    Document::paragraph('Product Inventory:'),
    Document::table(
        'Products',
        ['Name', 'Price', 'Stock'],
        [
            ['Widget A', '$10.00', '100'],
            ['Widget B', '$25.00', '50'],
        ],
    ),
);

Custom styled table

Document::save(
    ['title' => 'Styled Table'],
    'styled-table.odt',
    Document::table(
        'Sales',
        ['Product', 'Price', 'Qty'],
        [
            ['Widget A', '$10.00', '100'],
            ['Widget B', '$25.00', '50'],
        ],
        Document::tableStyle(
            Document::thickBorder(
                Document::headerStyle(['backgroundColor' => '#cc0000', 'color' => '#ffffff'])
            )
        ),
    ),
);

Multiple tables with different styles

Document::save(
    ['title' => 'Multi Table'],
    'multi-table.odt',
    Document::table('Default', ['A', 'B', 'C'], [['1', '2', '3']]),
    Document::lineBreak(),
    Document::table(
        'Minimal',
        ['Name', 'Value'],
        [['Alpha', '100'], ['Beta', '200']],
        Document::tableStyle(
            Document::noBorder(
                Document::headerStyle(['backgroundColor' => '#f0f0f0'])
            )
        ),
    ),
);

Full document

Document::save(
    ['title' => 'Monthly Report', 'creator' => 'Reporting System'],
    'report.odt',
    Document::centeredParagraph('Monthly Sales Report', ['fontSize' => '20pt', 'font-weight' => 'bold']),
    Document::centeredParagraph('July 2026', ['fontSize' => '14pt', 'color' => '#2e75b6']),
    Document::lineBreak(),
    Document::paragraph('This report summarizes sales data for the month.'),
    Document::lineBreak(),
    Document::table(
        'Sales',
        ['Product', 'Units Sold', 'Revenue'],
        [
            ['Product A', '150', '$4,500'],
            ['Product B', '89', '$3,560'],
            ['Product C', '210', '$6,300'],
        ],
        Document::tableStyle(
            Document::thinBorder(
                Document::headerStyle(['backgroundColor' => '#e8e8e8'])
            )
        ),
    ),
    Document::lineBreak(),
    Document::paragraph('Total revenue: $14,360', ['font-weight' => 'bold']),
);

Schema validation

use Odt\Odt\Core\Validator;

$errors = Validator::validate(Document::paragraph('Hello'));
if ($errors) {
    foreach ($errors as $error) {
        echo "Validation error: {$error}\n";
    }
}