docx_creator

pub package Dart SDK License: MIT

A developer-first DOCX generation library for Dart. Create, parse, read, and edit Microsoft Word documents with a fluent API, HTML/Markdown parsers, and full OpenXML compliance.

โœจ Features

Feature Description
๐Ÿ”งFluent Builder API Chain methods to create documents quickly
๐ŸŒHTML Parser Convert HTML to DOCX with 141 CSS named colors
๐Ÿ“Markdown Parser Parse Markdown including tables and nested lists
๐Ÿ“–DOCX Reader Load and edit existing .docx files
๐Ÿ“•PDF Reader Parse PDF files to DOCX structure
๐Ÿ“„PDF Export Export documents directly to PDF (pure Dart)
๐ŸŽจDrawing Shapes 70+ preset shapes (rectangles, arrows, stars, etc.)
๐Ÿ–ผ๏ธImages Embed local, remote, or base64 images (Inline & Floating)
๐Ÿ“ŠTables Styled tables, merged cells, borders, & conditional styles
๐Ÿ“‹Lists Bullet, numbered, and nested lists (9 levels)
๐Ÿ”คFonts Embed custom fonts with OOXML obfuscation
๐Ÿ“„Sections Headers, footers, page orientation, backgrounds
๐Ÿ“ŒFootnotes Full support for footnotes and endnotes
๐ŸงขDrop Caps Stylized drop caps for paragraph beginnings
๐ŸŽจTheme Support Theme colors, tints, shades, and font themes
๐ŸงฌAdvanced Styling Proper inheritance from docDefaults and style hierarchy

๐Ÿ“ฆ Installation

Add to your pubspec.yaml:

dependencies:
  docx_creator: ^1.0.9

Then run:

dart pub get

๐Ÿš€ Quick Start

Hello World

import 'package:docx_creator/docx_creator.dart';

void main() async {
  // Create a simple document
  final doc = docx()
    .h1('Hello, World!')
    .p('This is my first DOCX document.')
    .build();

  // Save to file
  await DocxExporter().exportToFile(doc, 'hello.docx');
}

From HTML

final htmlContent = '''
<h1>Report Title</h1>
<p>This is a <b>bold</b> and <i>italic</i> paragraph.</p>
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
''';

final elements = await DocxParser.fromHtml(htmlContent);
final doc = DocxBuiltDocument(elements: elements);
await DocxExporter().exportToFile(doc, 'from_html.docx');

From Markdown

final markdown = '''
# Project Report

## Summary
This is **important** information.

- Task 1: Complete
- Task 2: In Progress
''';

final elements = await MarkdownParser.parse(markdown);
final doc = DocxBuiltDocument(elements: elements);
await DocxExporter().exportToFile(doc, 'from_markdown.docx');

๐Ÿ“– Documentation

Table of Contents

  1. Builder API
  2. Text Formatting
  3. Lists
  4. Tables
  5. Images
  6. Shapes & Drawings
  7. HTML Parser
  8. Markdown Parser
  9. DOCX Reader & Editor
  10. DOCX Reader & Editor
  11. PDF Reader
  12. PDF Export
  13. Sections & Page Layout
  14. Font Embedding
  15. API Reference

PDF Export

Export documents directly to PDF with the PdfExporter. This is a pure Dart implementation with no native dependencies.

Basic Usage

import 'package:docx_creator/docx_creator.dart';

// Create a document
final doc = docx()
  .h1('PDF Export Demo')
  .p('This document will be exported to PDF.')
  .bullet(['Feature 1', 'Feature 2', 'Feature 3'])
  .build();

// Export to PDF file
await PdfExporter().exportToFile(doc, 'output.pdf');

// Or get as bytes
final pdfBytes = PdfExporter().exportToBytes(doc);

From HTML or Markdown

// From HTML
final html = '<h1>Title</h1><p>Content with <b>bold</b>.</p>';
final htmlDoc = DocxBuiltDocument(elements: await DocxParser.fromHtml(html));
await PdfExporter().exportToFile(htmlDoc, 'from_html.pdf');

// From Markdown
final md = '# Title\n\nParagraph with **bold**.';
final mdDoc = DocxBuiltDocument(elements: await MarkdownParser.parse(md));
await PdfExporter().exportToFile(mdDoc, 'from_markdown.pdf');

Supported Features

Feature Support
Headings (H1-H6) โœ…
Bold/Italic โœ…
Underline/Strikethrough โœ…
Custom Font Sizes โœ…
Superscript/Subscript โœ…
Text Colors โœ…
Background Colors โœ…
Text Alignment โœ…
Bullet Lists โœ…
Numbered Lists โœ…
Tables โœ…
Images (PNG) โœ…
Page Sizes (A4, Letter) โœ…
Multi-page โœ…

Builder API

The DocxDocumentBuilder provides a fluent interface for document creation:

final doc = DocxDocumentBuilder()
  // Headings
  .h1('Title')
  .h2('Chapter')
  .h3('Section')
  
  // Paragraphs
  .p('Simple paragraph text')
  .p('Right-aligned', align: DocxAlign.right)
  
  // Lists
  .bullet(['Item 1', 'Item 2', 'Item 3'])
  .numbered(['Step 1', 'Step 2', 'Step 3'])
  
  // Tables
  .table([
    ['Header 1', 'Header 2'],
    ['Cell 1', 'Cell 2'],
  ])
  
  // Special elements
  .pageBreak()
  .hr()  // Horizontal rule
  .quote('Blockquote text')
  .code('print("Hello");')
  
  .build();

Short vs Full Method Names

Short Full Description
h1(text) heading1(text) Heading level 1
h2(text) heading2(text) Heading level 2
h3(text) heading3(text) Heading level 3
p(text) text(content) Paragraph
bullet(items) addList(DocxList) Bullet list
numbered(items) addList(DocxList) Numbered list
hr() divider() Horizontal rule

Text Formatting

Create rich text with DocxText and DocxParagraph:

final doc = DocxDocumentBuilder()
  .add(DocxParagraph(children: [
    // Basic formatting
    DocxText('Bold ', fontWeight: DocxFontWeight.bold),
    DocxText('Italic ', fontStyle: DocxFontStyle.italic),
    DocxText('Underline ', decoration: DocxTextDecoration.underline),
    DocxText('Strikethrough', decoration: DocxTextDecoration.strikethrough),
  
    // Colors
    DocxText('Red text ', color: DocxColor.red),
    DocxText('Custom color ', color: DocxColor('#FF6600')),
    DocxText('With background ', shadingFill: 'FFFF00'),
  
    // Font size
    DocxText('Large text', fontSize: 24),
  
    // Superscript/Subscript
    DocxText('E=mc'),
    DocxText('2', isSuperscript: true),
    DocxText(' H'),
    DocxText('2', isSubscript: true),
    DocxText('O'),
  
    // Highlighting
    DocxText('Highlighted', highlight: DocxHighlight.yellow),
  
    // Hyperlinks
    DocxText('Click here', 
      href: 'https://example.com',
      color: DocxColor.blue,
      decoration: DocxTextDecoration.underline),
  ]))
  
  // Paragraph with specific line spacing
  .add(DocxParagraph(
    children: [DocxText('Exact Spacing')],
    lineSpacing: 240,       // 12 pt
    lineRule: 'exact',      // 'auto', 'exact', 'atLeast'
  ))
  .build();

Available Colors

// Predefined colors
DocxColor.black, DocxColor.white, DocxColor.red, DocxColor.blue,
DocxColor.green, DocxColor.yellow, DocxColor.orange, DocxColor.purple,
DocxColor.gray, DocxColor.lightGray, DocxColor.darkGray, DocxColor.cyan,
DocxColor.magenta, DocxColor.pink, DocxColor.brown, DocxColor.navy,
DocxColor.teal, DocxColor.lime, DocxColor.gold, DocxColor.silver

// Custom hex colors
DocxColor('#FF5722')
DocxColor('4285F4')  // # is optional

Lists

Simple Lists

// Bullet list
.bullet(['First item', 'Second item', 'Third item'])

// Numbered list
.numbered(['Step 1', 'Step 2', 'Step 3'])

Nested Lists

final nestedList = DocxList(
  style: DocxListStyle.disc,
  items: [
    DocxListItem.text('Level 0 - First', level: 0),
    DocxListItem.text('Level 1 - Nested', level: 1),
    DocxListItem.text('Level 2 - Deep', level: 2),
    DocxListItem.text('Level 1 - Back', level: 1),
    DocxListItem.text('Level 0 - Root', level: 0),
  ],
);

docx().add(nestedList).build();

List Styles

DocxListStyle.disc       // โ€ข Solid disc (default)
DocxListStyle.circle     // โ—ฆ Circle
DocxListStyle.square     // โ–ช Square
DocxListStyle.dash       // - Dash
DocxListStyle.arrow      // โ†’ Arrow
DocxListStyle.check      // โœ“ Checkmark
DocxListStyle.decimal    // 1, 2, 3
DocxListStyle.lowerAlpha // a, b, c
DocxListStyle.upperAlpha // A, B, C
DocxListStyle.lowerRoman // i, ii, iii
DocxListStyle.upperRoman // I, II, III

Tables

Simple Table

.table([
  ['Name', 'Age', 'City'],
  ['Alice', '25', 'New York'],
  ['Bob', '30', 'Los Angeles'],
])

Styled Table

final styledTable = DocxTable(
  rows: [
    DocxTableRow(cells: [
      DocxTableCell(
        children: [DocxParagraph(children: [
          DocxText('Header', fontWeight: DocxFontWeight.bold, color: DocxColor.white)
        ])],
        shadingFill: '4472C4',  // Blue background
        verticalAlign: DocxVerticalAlign.center,
      ),
      // More cells...
    ]),
    // More rows...
  ],
);

Images

import 'dart:io';

// From file
final imageBytes = await File('logo.png').readAsBytes();
final doc = docx()
  .add(DocxImage(
    bytes: imageBytes,
    extension: 'png',
    width: 200,
    height: 100,
    align: DocxAlign.center,
  ))
  .build();

// Inline image in paragraph
.add(DocxParagraph(children: [
  DocxText('See image: '),
  DocxInlineImage(bytes: imageBytes, extension: 'png', width: 50, height: 50),
  DocxText(' above.'),
]))

Shapes & Drawings

Create DrawingML shapes with 70+ presets:

// Basic shapes
DocxShapeBlock.rectangle(
  width: 200,
  height: 60,
  fillColor: DocxColor.blue,
  outlineColor: DocxColor.black,
  outlineWidth: 2,
  text: 'Click Me',
  align: DocxAlign.center,
)

DocxShapeBlock.ellipse(width: 100, height: 100, fillColor: DocxColor.green)
DocxShapeBlock.circle(diameter: 80, fillColor: DocxColor.red)
DocxShapeBlock.triangle(width: 100, height: 100, fillColor: DocxColor.yellow)
DocxShapeBlock.star(points: 5, fillColor: DocxColor.gold)
DocxShapeBlock.diamond(width: 80, fillColor: DocxColor.purple)
DocxShapeBlock.rightArrow(width: 100, height: 40, fillColor: DocxColor.blue)
DocxShapeBlock.leftArrow(width: 100, height: 40, fillColor: DocxColor.red)

// Inline shapes in paragraph
.add(DocxParagraph(children: [
  DocxShape.circle(diameter: 30, fillColor: DocxColor.red),
  DocxText(' Red circle '),
  DocxShape.star(points: 5, fillColor: DocxColor.gold),
  DocxText(' Gold star'),
]))

Shape Presets

Over 70 preset shapes including: rect, ellipse, triangle, diamond, star4, star5, star6, rightArrow, leftArrow, upArrow, downArrow, heart, lightning, flowChartProcess, flowChartDecision, and many more.


HTML Parser

Supported HTML Tags

Tag Output
<h1> - <h6> Headings
<p> Paragraph
<b>, <strong> Bold
<i>, <em> Italic
<u> Underline
<s>, <del> Strikethrough
<mark> Highlight
<sup> Superscript
<sub> Subscript
<a href=""> Hyperlink
<code> Inline code
<pre> Code block
<ul>, <ol> Lists
<table> Tables
<img> Images
<blockquote> Blockquote
<hr> Horizontal rule
<br> Line break
<div>, <span> Containers with styles

Supported CSS Properties

color: red;                    /* Text color */
color: #FF5722;               /* Hex color */
color: dodgerblue;            /* CSS named color (141 supported) */
background-color: yellow;      /* Background/shading */
font-size: 16px;              /* Font size */
font-weight: bold;            /* Bold */
font-style: italic;           /* Italic */
text-align: center;           /* Alignment */
text-decoration: underline;   /* Underline/strikethrough */

CSS Named Colors

All 141 W3C CSS3 Extended Color Keywords are supported:

<span style="color: dodgerblue;">DodgerBlue</span>
<span style="color: mediumvioletred;">MediumVioletRed</span>
<span style="color: darkolivegreen;">DarkOliveGreen</span>
<span style="color: papayawhip;">PapayaWhip</span>

Including grey/gray variations: grey, darkgrey, lightgrey, etc.

Example

final html = '''
<div style="background-color: #f0f0f0; padding: 10px;">
  <h1 style="color: navy;">Report Title</h1>
  <p>This is <span style="color: red; font-weight: bold;">important</span> text.</p>
  <table border="1">
    <tr style="background-color: #4472C4; color: white;">
      <th>Name</th>
      <th>Status</th>
    </tr>
    <tr>
      <td>Task 1</td>
      <td style="background-color: lightgreen;">Complete</td>
    </tr>
  </table>
</div>
''';

final elements = await DocxParser.fromHtml(html);

Markdown Parser

Supported Syntax

Markdown Output
# Heading H1-H6
**bold** Bold
*italic* Italic
~~strike~~ Strikethrough
[text](url) Links
`code` Inline code
``` Code blocks
- item Bullet list
1. item Numbered list
> quote Blockquote
--- Horizontal rule
` a
[ ] / [x] Task lists

Nested Lists

- Level 1
    - Level 2
        - Level 3
    - Level 2
- Level 1

Nested lists are automatically converted to multi-level Word lists with proper indentation.

Tables with Alignment

| Left | Center | Right |
|:-----|:------:|------:|
| L    | C      | R     |

DOCX Reader & Editor

Loading an Existing Document

// From file path
final doc = await DocxReader.load('existing.docx');

// From bytes
final bytes = await File('existing.docx').readAsBytes();
final doc = await DocxReader.loadFromBytes(bytes);

Accessing Elements

for (final element in doc.elements) {
  if (element is DocxParagraph) {
    for (final child in element.children) {
      if (child is DocxText) {
        print('Text: ${child.content}');
        print('Bold: ${child.fontWeight == DocxFontWeight.bold}');
        print('Color: ${child.color?.hex}');
      }
    }
  } else if (element is DocxTable) {
    print('Table with ${element.rows.length} rows');
  } else if (element is DocxList) {
    print('List with ${element.items.length} items');
  }
}

Modifying and Re-Saving

// Load document
final doc = await DocxReader.load('report.docx');

// Modify elements
final modifiedElements = <DocxNode>[];
for (final element in doc.elements) {
  if (element is DocxParagraph) {
    // Find and replace text
    final newChildren = element.children.map((child) {
      if (child is DocxText) {
        return DocxText(
          child.content.replaceAll('OLD', 'NEW'),
          fontWeight: child.fontWeight,
          color: child.color,
        );
      }
      return child;
    }).toList();
    modifiedElements.add(DocxParagraph(children: newChildren));
  } else {
    modifiedElements.add(element);
  }
}

// Add new content
modifiedElements.add(DocxParagraph.text('Added on: ${DateTime.now()}'));

// Create new document preserving metadata
final editedDoc = DocxBuiltDocument(
  elements: modifiedElements,
  // Preserve original document properties
  section: doc.section,
  stylesXml: doc.stylesXml,
  numberingXml: doc.numberingXml,
);

// Save
await DocxExporter().exportToFile(editedDoc, 'report_edited.docx');

Round-Trip Pipeline

// Load โ†’ Parse โ†’ Modify โ†’ Export
final original = await DocxReader.load('input.docx');

// All formatting, lists, tables, shapes are preserved
final elements = List<DocxNode>.from(original.elements);

// Add new content
elements.add(DocxParagraph.heading2('New Section'));
elements.add(DocxParagraph.text('Content added programmatically.'));

// Export with preserved metadata
final output = DocxBuiltDocument(
  elements: elements,
  stylesXml: original.stylesXml,
  numberingXml: original.numberingXml,
);

await DocxExporter().exportToFile(output, 'output.docx');

PDF Reader

Convert PDF documents into editable DocxBuiltDocument objects or extract content programmatically.

Basic Usage

// Load PDF
final pdf = await PdfReader.load('input.pdf');

// Convert to DOCX
final doc = pdf.toDocx();

// Save as DOCX
await DocxExporter().exportToFile(doc, 'converted.docx');

Content Extraction

You can also access the extracted elements directly:

final pdf = await PdfReader.load('input.pdf');

print('Pages: ${pdf.pageCount}');
print('PDF Version: ${pdf.version}');

// Iterate over extracted elements
for (final element in pdf.elements) {
  if (element is DocxParagraph) {
    print(element.text);
  } else if (element is DocxImage) {
    print('Image: ${element.width}x${element.height}');
  }
}

// Get all text
print(pdf.text);

Supported Features

  • Text Extraction: Preserves paragraphs, fonts, sizes, and colors.
  • Formatting: Bold, italic, underline, strikethrough.
  • Layout: Groups text into paragraphs based on position.
  • Images: Extracts embedded images/XObjects.
  • Tables: Basic table structure detection (beta).
  • Metadata: Page count, page size, PDF version.

Sections & Page Layout

final doc = DocxDocumentBuilder()
  .section(
    orientation: DocxPageOrientation.portrait,
    pageSize: DocxPageSize.a4,
    backgroundColor: DocxColor('#F0F8FF'),
    header: DocxHeader(children: [
      DocxParagraph.text('Company Name', align: DocxAlign.right),
    ]),
    footer: DocxFooter(children: [
      DocxParagraph.text('Page 1', align: DocxAlign.center),
    ]),
  )
  .h1('Document Title')
  .p('Content...')
  .build();

Multi-Section Documents

docx()
  .p('Portrait section content')
  .addSectionBreak(DocxSectionDef(
    orientation: DocxPageOrientation.portrait,
  ))
  .p('Landscape section content')
  .addSectionBreak(DocxSectionDef(
    orientation: DocxPageOrientation.landscape,
  ))
  .build();

Footnotes & Endnotes

Add academic citations and notes programmatically:

final doc = docx()
  .p('This statement needs a citation.')
  .addFootnote(DocxFootnote(
    footnoteId: 1,
    content: [
      DocxParagraph.text('Source: Official Documentation, 2024.'),
    ],
  ))
  .p('Unexpected finding.')
  .addEndnote(DocxEndnote(
    endnoteId: 1,
    content: [
      DocxParagraph.text('Further investigation required.'),
    ],
  ))
  .build();

Note: IDs must be unique. Word handles re-numbering automatically, but you must provide improved internal IDs for linking.


Font Embedding

Embed custom fonts with OOXML-compliant obfuscation:

import 'dart:io';

final fontBytes = await File('fonts/Roboto-Regular.ttf').readAsBytes();

final doc = DocxDocumentBuilder()
  .addFont('Roboto', fontBytes)
  .add(DocxParagraph(children: [
    DocxText('Custom font text', fontFamily: 'Roboto'),
  ]))
  .build();

.build();


> **Note:** Fonts are automatically obfuscated per the OpenXML specification.
> **High Fidelity:** When reading existing documents, `docx_creator` preserves embedded fonts byte-for-byte, ensuring exact visual fidelity during round-trip edits.

---

## API Reference

### DocxDocumentBuilder

| Method                              | Parameters                   | Description          |
| ----------------------------------- | ---------------------------- | -------------------- |
| `h1(text)`                        | `String text`              | Add H1 heading       |
| `h2(text)`                        | `String text`              | Add H2 heading       |
| `h3(text)`                        | `String text`              | Add H3 heading       |
| `heading(level, text)`            | `DocxHeadingLevel, String` | Add heading at level |
| `p(text, {align})`                | `String, DocxAlign?`       | Add paragraph        |
| `bullet(items)`                   | `List<String>`             | Add bullet list      |
| `numbered(items)`                 | `List<String>`             | Add numbered list    |
| `table(data, {hasHeader, style})` | `List<List<String>>`       | Add table            |
| `pageBreak()`                     | -                            | Add page break       |
| `hr()`                            | -                            | Add horizontal rule  |
| `quote(text)`                     | `String`                   | Add blockquote       |
| `code(code)`                      | `String`                   | Add code block       |
| `add(node)`                       | `DocxNode`                 | Add any node         |
| `addFont(name, bytes)`            | `String, Uint8List`        | Embed font           |
| `section({...})`                  | Various                      | Set page properties  |
| `build()`                         | -                            | Build document       |

### DocxExporter

| Method                      | Parameters                    | Description  |
| --------------------------- | ----------------------------- | ------------ |
| `exportToFile(doc, path)` | `DocxBuiltDocument, String` | Save to file |
| `exportToBytes(doc)`      | `DocxBuiltDocument`         | Get as bytes |

### DocxReader

| Method                   | Parameters    | Description         |
| ------------------------ | ------------- | ------------------- |
| `load(path)`           | `String`    | Load from file path |
| `loadFromBytes(bytes)` | `Uint8List` | Load from bytes     |

### DocxParser

| Method               | Parameters | Description             |
| -------------------- | ---------- | ----------------------- |
| `fromHtml(html)`   | `String` | Parse HTML to nodes     |
| `fromMarkdown(md)` | `String` | Parse Markdown to nodes |

### MarkdownParser

| Method              | Parameters | Description             |
| ------------------- | ---------- | ----------------------- |
| `parse(markdown)` | `String` | Parse Markdown to nodes |

---

## Troubleshooting

### Common Issues

**Q: Fonts don't display correctly in Word**

A: Ensure the font is embedded using `addFont()`. Embedded fonts are obfuscated per OpenXML spec.

**Q: Images don't appear**

A: Verify image bytes are valid and extension matches format (`png`, `jpg`, `gif`).

**Q: Lists don't have bullets/numbers**

A: Ensure you're using the fluent API (`bullet()`, `numbered()`) or properly structured `DocxList` with `DocxListItem`.

**Q: Colors look wrong**

A: Use 6-digit hex codes without # prefix for `shadingFill`. For `DocxColor`, you can use `#RRGGBB` or plain `RRGGBB`.

---

## Examples

See the `example/` directory for comprehensive examples:

- [`manual_builder_example.dart`](example/manual_builder_example.dart) - All builder API features
- [`html_parser_example.dart`](example/html_parser_example.dart) - HTML to DOCX
- [`markdown_parser_example.dart`](example/markdown_parser_example.dart) - Markdown to DOCX
- [`reader_editor_example.dart`](example/reader_editor_example.dart) - Read, edit, save workflow

---

## License

MIT License - see [LICENSE](LICENSE) for details.

## Contributing

Contributions welcome! Please read our contributing guidelines and submit PRs to the main repository.

Libraries

docx_creator
docx_creator - A developer-first DOCX generation library