Guide
Rich text runs
A paragraph is a list of TextRuns. Each run carries its own formatting, so you can mix weights, styles, colors and highlights inside a single line. Colors are hex strings without the # prefix.
doc.addParagraph(Paragraph(
runs: [
TextRun('Normal, '),
TextRun('bold, ', bold: true),
TextRun('italic, ', italic: true),
TextRun('red text, ', color: 'FF0000'),
TextRun('highlighted', backgroundColor: 'FFFF00'),
],
));| Property | Type | Description |
|---|---|---|
bold | bool | Bold text |
italic | bool | Italic text |
underline | bool | Underlined text |
strikethrough | bool | Strikethrough text |
color | String | Hex color (e.g. FF0000), without the # prefix |
backgroundColor | String | Highlight color |
hyperlink | String? | External URL link |
bookmarkRef | String? | Internal bookmark reference |
isLineBreak | bool | Line break (use TextRun.lineBreak()) |
Semantic styles
Named factories give each paragraph a real Word style — headings, subtitle, quote, code block, caption and footnote — so the output maps to the document outline instead of hand-tuned font sizes.
doc.addParagraph(Paragraph.heading('Title', level: 1));
doc.addParagraph(Paragraph.subtitle('Document subtitle'));
doc.addParagraph(Paragraph.quote('A famous quote...'));
doc.addParagraph(Paragraph.codeBlock('const x = 42;'));
doc.addParagraph(Paragraph.caption('Figure 1: Chart'));
doc.addParagraph(Paragraph.footnote('1. Reference note'));| Style | Method |
|---|---|
| Normal text | Paragraph.text('...') |
| Heading 1-4 | Paragraph.heading('...', level: 1) |
| Subtitle | Paragraph.subtitle('...') |
| Caption | Paragraph.caption('...') |
| Quote | Paragraph.quote('...') |
| Code block | Paragraph.codeBlock('...') |
| Footnote | Paragraph.footnote('...') |
Headings run from level 1 to level 4:
doc.addParagraph(Paragraph.heading('Heading Level 1', level: 1));
doc.addParagraph(Paragraph.heading('Heading Level 2', level: 2));
doc.addParagraph(Paragraph.heading('Heading Level 3', level: 3));
doc.addParagraph(Paragraph.heading('Heading Level 4', level: 4));Spacing
Since 1.3.4, Paragraph.empty() inserts a blank spacer paragraph — useful as vertical spacing between content blocks.
Alignment
Every paragraph factory accepts an alignment argument. Alignment has four values — left, center, right and justify (justify maps to the OOXML both value).
doc.addParagraph(Paragraph.text('Centered', alignment: Alignment.center));
doc.addParagraph(Paragraph.text('Right aligned', alignment: Alignment.right));
doc.addParagraph(Paragraph.text('Justified body', alignment: Alignment.justify));Tables
A Table is rows of cells. Set borders and background colors at the table level, and override alignment or backgrounds per cell.
doc.addTable(Table(
borders: TableBorders.all(),
rows: [
TableRow(cells: [
TableCell.text('Name', backgroundColor: 'CCCCCC'),
TableCell.text('Score', backgroundColor: 'CCCCCC'),
]),
TableRow(cells: [
TableCell.text('Alice'),
TableCell.text('95', alignment: Alignment.right),
]),
],
));Individual cells can override the table borders entirely — custom colors, a single side, or none at all. Border width is measured in eighths of a point (4 = 0.5pt, 8 = 1pt).
doc.addTable(Table(
borders: const TableBorders.all(),
rows: [
TableRow(cells: [
// Cell with custom red borders
TableCell.text('Alert', borders: const CellBorders.all(color: 'FF0000', size: 8)),
TableCell.text('Normal cell'),
]),
TableRow(cells: [
// Cell with only bottom border
TableCell.text('Underlined', borders: const CellBorders.bottom()),
// Cell with no borders (overrides table borders)
TableCell.text('Clean', borders: const CellBorders.none()),
]),
],
));
// Selective sides with different styles
TableCell(
paragraphs: [Paragraph.text('Custom')],
borders: const CellBorders(
top: Border(color: 'FF0000', size: 8, style: BorderStyle.double),
bottom: Border(color: '0000FF'),
),
);Lists & nesting
There are five list markers, each its own factory. Add items in sequence to build a list.
| Method | Marker |
|---|---|
Paragraph.bulletItem('...') | • bullet |
Paragraph.dashItem('...') | - dash |
Paragraph.numberedItem('...') | 1, 2, 3… |
Paragraph.alphaItem('...') | a, b, c… |
Paragraph.romanItem('...') | I, II, III… |
// Bullet list
doc.addParagraph(Paragraph.bulletItem('First item'));
doc.addParagraph(Paragraph.bulletItem('Second item'));
// Numbered list
doc.addParagraph(Paragraph.numberedItem('Step one'));
doc.addParagraph(Paragraph.numberedItem('Step two'));
// Nested list
doc.addParagraph(Paragraph.bulletItem('Parent'));
doc.addParagraph(Paragraph.bulletItem('Child', indentLevel: 1));Nesting is driven by indentLevel, and list types can be mixed at different depths:
doc.addParagraph(Paragraph.numberedItem('First item'));
doc.addParagraph(Paragraph.alphaItem('Sub-item a', indentLevel: 1));
doc.addParagraph(Paragraph.alphaItem('Sub-item b', indentLevel: 1));
doc.addParagraph(Paragraph.romanItem('Detail i', indentLevel: 2));
doc.addParagraph(Paragraph.numberedItem('Second item'));Nesting depth
indentLevel starts at 0 (top level); the maximum supported level is 8, which the README markets as "up to 9 levels" (levels 0 through 8).
Hyperlinks & bookmarks
Attach a hyperlink to any run for an external URL — it gets automatic blue color and underline styling. Hyperlinks and bookmarks are DOCX-only.
// External link
doc.addParagraph(Paragraph(
runs: [
TextRun('Visit '),
TextRun('our website', hyperlink: 'https://example.com'),
TextRun(' for more info.'),
],
));For internal navigation, name a bookmark on a paragraph with bookmarkName, then point a run at it with bookmarkRef:
// Create a bookmark
doc.addParagraph(Paragraph.heading(
'Chapter 1: Introduction',
level: 1,
bookmarkName: 'chapter1',
));
// Link to the bookmark
doc.addParagraph(Paragraph(
runs: [
TextRun('Go to '),
TextRun('Chapter 1', bookmarkRef: 'chapter1'),
],
));Table of contents
Turn on includeTableOfContents and docs_gee builds a linked TOC from your headings automatically. tocMaxLevel controls how deep it goes (default 3, i.e. Heading 1-3). The automatic table of contents is DOCX-only.
// Enable automatic Table of Contents
final doc = Document(
title: 'My Document',
includeTableOfContents: true,
tocTitle: 'Contents',
tocMaxLevel: 3, // Include Heading 1-3
);
doc.addParagraph(Paragraph.heading('Introduction', level: 1));
doc.addParagraph(Paragraph.heading('Getting Started', level: 2));
// TOC will be auto-generated with links to these headingsBreaks & emoji
Force a new page before a paragraph with pageBreakBefore:
doc.addParagraph(Paragraph.heading(
'New Chapter',
level: 1,
pageBreakBefore: true,
));Soft line breaks — like Shift+Enter in Word — keep multiple lines inside one paragraph. Use \n in text, or explicit TextRun.lineBreak() runs for per-line formatting. Line breaks are DOCX-only.
// Using \n in text (automatic conversion)
doc.addParagraph(Paragraph.text('Line 1\nLine 2\nLine 3'));
// Using explicit line break runs (for different formatting per line)
doc.addParagraph(Paragraph(
runs: [
TextRun('Bold line', bold: true),
TextRun.lineBreak(),
TextRun('Normal line'),
TextRun.lineBreak(),
TextRun('Italic line', italic: true),
],
));Emoji render in DOCX, where Word handles them natively:
doc.addParagraph(Paragraph.text('Hello World! 👋🌍'));Heads up
Emoji are DOCX-only — PDF uses standard fonts without emoji support.
