odt

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 31, 2026 License: MIT Imports: 8 Imported by: 0

README

go-odt

Go Reference CI Go Report Card

Generate OpenDocument Text (.odt) files in Go. Zero dependencies.

Why ODT?

ODT is the open document standard (ISO/IEC 26300). LibreOffice, OpenOffice, Google Docs, and Microsoft Word all open it. Unlike DOCX, the format is straightforward: a ZIP archive containing XML files. If you need to generate documents programmatically and don't want to pull in a massive library, this does the job.

Install

go get github.com/CivNode/go-odt

Requires Go 1.22 or later. No external dependencies.

Quick start

package main

import (
    "os"
    "github.com/CivNode/go-odt"
)

func main() {
    doc := odt.New()
    doc.SetTitle("Quarterly Report")
    doc.SetAuthor("Engineering")

    doc.AddHeading(1, "Summary")
    doc.AddParagraph("Revenue grew ", odt.Bold("23%"), " quarter over quarter.")
    doc.AddParagraph("Details follow in the sections below.")

    doc.AddHeading(2, "Metrics")
    doc.AddTable(
        []string{"Metric", "Q1", "Q2"},
        [][]string{
            {"Users", "1,200", "1,850"},
            {"Revenue", "$45k", "$55k"},
        },
    )

    doc.AddHeading(2, "Next Steps")
    doc.AddList("Expand to EU markets", "Hire two more engineers", "Ship v2.0")

    data, err := doc.Render()
    if err != nil {
        panic(err)
    }
    os.WriteFile("report.odt", data, 0644)
}

API

Document
doc := odt.New()                                    // new document with sensible defaults
doc.SetTitle("My Document")                         // metadata: title
doc.SetAuthor("Jane Doe")                           // metadata: author
doc.SetGenerator("MyApp v1.0")                      // metadata: generator (defaults to "go-odt")
doc.SetFont("Georgia", 14)                          // font family and size in points
doc.SetLineSpacing(1.5)                             // line height multiplier
doc.SetMargins("1in", "1in", "1.25in", "1.25in")   // top, bottom, left, right
Block content
doc.AddHeading(1, "Chapter Title")                  // headings, levels 1-6
doc.AddParagraph("Text with ", odt.Bold("bold"))    // paragraphs with inline formatting
doc.AddBlockquote("A quoted passage.")              // indented italic block
doc.AddCodeBlock("func main() {}")                  // monospace preformatted block
doc.AddList("First", "Second", "Third")             // bullet list
doc.AddOrderedList("Step 1", "Step 2")              // numbered list
doc.AddTable(headers, rows)                         // table with headers
doc.AddHorizontalRule()                             // section separator (****)
doc.AddPageBreak()                                  // page break
Inline formatting

Constructor functions for single formats:

odt.Bold("text")
odt.Italic("text")
odt.Underline("text")
odt.Strikethrough("text")
odt.Code("text")
odt.Link("display text", "https://example.com")

Chain methods to combine formats:

odt.Text("important").Bold().Italic()               // bold + italic
odt.Text("deprecated").Strikethrough().Code()        // monospace strikethrough

AddParagraph, AddBlockquote, and list items all accept a mix of plain strings and Span values:

doc.AddParagraph(
    "See ",
    odt.Link("the docs", "https://example.com"),
    " for ",
    odt.Bold("complete"),
    " details.",
)
Render
data, err := doc.Render()       // returns []byte
n, err := doc.WriteTo(writer)   // writes to any io.Writer

ODF compliance

The output conforms to ODF 1.2 (the version LibreOffice expects). Specifically:

  • mimetype entry is the first file in the ZIP, stored without compression, with no data descriptor and no extra field in the local header. This is the part most Go ZIP libraries get wrong (Go's archive/zip adds data descriptors by default). We use CreateRaw with pre-computed CRC32 to avoid it.
  • manifest.xml lists all content files with correct media types.
  • styles.xml defines named paragraph styles (headings, body, blockquote, code, etc.) and page layout with configurable margins.
  • content.xml uses automatic styles for combined inline formatting. If you use bold+italic on the same text, it generates a proper combined <style:style> rather than picking one and dropping the other.
  • All XML output is properly escaped and parses cleanly.

Files open without warnings in LibreOffice, OpenOffice, and Google Docs.

What this library does not do

  • Read or parse existing ODT files
  • Embed images (images are rendered as alt-text placeholders)
  • Generate spreadsheets (.ods) or presentations (.odp)
  • Handle right-to-left text layout
  • Produce PDF directly (use LibreOffice headless for that: libreoffice --convert-to pdf doc.odt)

These may come in future versions if there's demand.

Used in production

civnode.com uses go-odt for book export. The library was extracted from CivNode's internal export pipeline and published as a standalone package.

License

MIT

Documentation

Overview

Package odt generates OpenDocument Text (.odt) files.

ODT is the open standard document format (ISO/IEC 26300) used by LibreOffice, OpenOffice, Google Docs (import/export), and many other applications. This package produces ODF 1.2 compliant files that open cleanly in all major word processors.

Zero dependencies — uses only the Go standard library.

Quick start:

doc := odt.New()
doc.SetTitle("My Document")
doc.SetAuthor("Jane Doe")
doc.AddHeading(1, "Introduction")
doc.AddParagraph("Hello, world!")
data, err := doc.Render()

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Document

type Document struct {
	// contains filtered or unexported fields
}

Document represents an ODT document under construction. Create one with New, add content with the Add methods, then call Document.Render to produce the ODT bytes.

func New

func New() *Document

New creates a new empty ODT document with sensible defaults.

Example
doc := odt.New()
doc.SetTitle("My Document")
doc.SetAuthor("Jane Doe")
doc.AddHeading(1, "Introduction")
doc.AddParagraph("Hello, world!")
data, err := doc.Render()
if err != nil {
	panic(err)
}
fmt.Println(len(data) > 0)
Output:
true

func (*Document) AddBlockquote

func (d *Document) AddBlockquote(content ...any)

AddBlockquote adds a block quotation. Content arguments can be plain strings or Span values.

func (*Document) AddCodeBlock

func (d *Document) AddCodeBlock(text string)

AddCodeBlock adds a preformatted code block.

func (*Document) AddHeading

func (d *Document) AddHeading(level int, text string)

AddHeading adds a heading at the given outline level (1–6).

func (*Document) AddHorizontalRule

func (d *Document) AddHorizontalRule()

AddHorizontalRule adds a centered separator (e.g., "* * *").

func (*Document) AddList

func (d *Document) AddList(items ...any)

AddList adds a bullet list. Each item can be a string, a Span, or a []any of mixed strings and Spans.

func (*Document) AddOrderedList

func (d *Document) AddOrderedList(items ...any)

AddOrderedList adds a numbered list. Arguments are the same as Document.AddList.

func (*Document) AddPageBreak

func (d *Document) AddPageBreak()

AddPageBreak inserts a page break before the next content.

func (*Document) AddParagraph

func (d *Document) AddParagraph(content ...any)

AddParagraph adds a paragraph. Content arguments can be plain strings or Span values for inline formatting.

doc.AddParagraph("Hello, ", odt.Bold("world"), "!")
Example
doc := odt.New()
doc.AddParagraph("Plain text, ", odt.Bold("bold"), ", and ", odt.Text("bold italic").Bold().Italic(), ".")
doc.Render()

func (*Document) AddTable

func (d *Document) AddTable(headers []string, rows [][]string)

AddTable adds a table with column headers and data rows.

func (*Document) Render

func (d *Document) Render() ([]byte, error)

Render produces the complete ODT file as a byte slice.

func (*Document) SetAuthor

func (d *Document) SetAuthor(author string)

SetAuthor sets the document author (appears in file metadata).

func (*Document) SetFont

func (d *Document) SetFont(family string, sizePt int)

SetFont sets the default font family and size in points.

func (*Document) SetGenerator

func (d *Document) SetGenerator(gen string)

SetGenerator overrides the generator string in metadata (defaults to "go-odt").

func (*Document) SetLineSpacing

func (d *Document) SetLineSpacing(spacing float64)

SetLineSpacing sets line height as a multiplier (e.g., 1.5 for 150%).

func (*Document) SetMargins

func (d *Document) SetMargins(top, bottom, left, right string)

SetMargins sets page margins. Values use CSS-style units (e.g., "1in", "2.54cm").

func (*Document) SetTitle

func (d *Document) SetTitle(title string)

SetTitle sets the document title (appears in file metadata).

func (*Document) WriteTo

func (d *Document) WriteTo(w io.Writer) (int64, error)

WriteTo writes the complete ODT file to w.

Example
doc := odt.New()
doc.AddParagraph("Written to a file.")

f, err := os.CreateTemp("", "example-*.odt")
if err != nil {
	panic(err)
}
defer os.Remove(f.Name())
defer f.Close()

n, err := doc.WriteTo(f)
if err != nil {
	panic(err)
}
fmt.Println(n > 0)
Output:
true

type Span

type Span struct {
	// contains filtered or unexported fields
}

Span represents a run of inline text with optional formatting. Create spans with the constructor functions (Text, Bold, Italic, etc.) and combine formats with the chainable methods.

odt.Bold("important")                     // bold
odt.Text("key point").Bold().Italic()     // bold + italic
odt.Link("CivNode", "https://civnode.com") // hyperlink

func Bold

func Bold(s string) Span

Bold creates a bold text span.

func Code

func Code(s string) Span

Code creates a monospace code span.

func Italic

func Italic(s string) Span

Italic creates an italic text span.

func Link(text, href string) Span

Link creates a hyperlink span.

func Strikethrough

func Strikethrough(s string) Span

Strikethrough creates a struck-through text span.

func Text

func Text(s string) Span

Text creates a plain text span.

func Underline

func Underline(s string) Span

Underline creates an underlined text span.

func (Span) Bold

func (s Span) Bold() Span

Bold returns a copy of the span with bold enabled.

func (Span) Code

func (s Span) Code() Span

Code returns a copy of the span with monospace code formatting enabled.

func (Span) Italic

func (s Span) Italic() Span

Italic returns a copy of the span with italic enabled.

func (Span) Strikethrough

func (s Span) Strikethrough() Span

Strikethrough returns a copy of the span with strikethrough enabled.

func (Span) Underline

func (s Span) Underline() Span

Underline returns a copy of the span with underline enabled.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL