odf

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: BSD-3-Clause Imports: 10 Imported by: 0

README

odf

An ODT (OpenDocument Text) ⇄ richdoc converter, written in pure Go (CGO-free, including GOOS=js).

odf reads an .odt package (a ZIP of XML) into the neutral richdoc document model, and writes a minimal, valid OpenDocument Text package from a richdoc.Document. The two directions are designed as a faithful round-trip.

d, err := odf.Parse(src)   // .odt bytes -> *richdoc.Document
out, err := odf.Write(d)   // *richdoc.Document -> .odt bytes (valid ODF package)

src and the return of Write are the raw bytes of the .odt ZIP container.

API

func Parse(src []byte) (*richdoc.Document, error)
func Write(d *richdoc.Document) ([]byte, error)

Parse opens the ZIP, reads content.xml (resolving span formatting against the automatic styles there and the named styles in styles.xml), consults META-INF/manifest.xml for embedded image media types, and maps the office:text body onto richdoc blocks and inlines. Anything the model has no node for is preserved verbatim through RawInline/RawBlock with Format: "odf", so nothing in the source is silently lost.

Write produces a minimal, valid OpenDocument package: mimetype is the first entry and is stored uncompressed (the ODF package requirement), followed by META-INF/manifest.xml, content.xml, styles.xml, an optional meta.xml, and any embedded Pictures/.

Reference-library note

Before writing this converter, the maintained Go landscape was checked. No maintained library offers a bidirectional ODT reader/writer over a neutral model: sbinet.org/x/odf is read-only, knieriem/odf and AlexJarrah/go-ods target spreadsheets (ODS), kpmy/odf is a one-way generator, and the cat family only extracts plain text. An ODT is a ZIP of XML that the Go standard library (archive/zip + encoding/xml) handles directly, so an in-org converter that maps ODF onto richdoc is justified. The package depends only on the standard library and richdoc.

Construct mapping

Both directions map as follows:

ODF (content.xml) richdoc
text:h + text:outline-level Heading (level 1–6)
text:p Paragraph
text:spanfo:font-weight="bold" Strong
text:spanfo:font-style="italic" Emph
text:spanstyle:text-line-through-style (≠ none) Strikethrough
text:span → monospace style:font-name Code (inline)
text:a (xlink:href, office:title) Link
draw:frame/draw:image (+ svg:desc/svg:title) Image
text:line-break LineBreak
text:tab, text:s whitespace Text
text:list / text:list-item (number style ⇒ ordered) List / ListItem
table:table / table:table-row / table:table-cell Table
text:p + odfgo:code-language CodeBlock
text:section + odfgo:blockquote BlockQuote
text:p + odfgo:thematic-break ThematicBreak
text:p/text:span + odfgo:math MathBlock / Math
any unrecognized element RawBlock / RawInline (Format: "odf")

The odfgo: attributes live in a private namespace (https://github.com/go-odf/odf); ODF consumers ignore foreign attributes, and they let the converter re-recognize model nodes (code blocks, block quotes, thematic breaks, math) that OpenDocument has no dedicated element for on the way back in.

Model boundaries (routed through Raw)

OpenDocument constructs the richdoc model has no node for — footnotes and endnotes (text:note), bookmarks (text:bookmark), cross-references (text:reference-*), annotations, and any other unrecognized element — are carried through unchanged as RawInline/RawBlock with Format: "odf", captured as the exact original XML bytes so nothing is lost.

Embedded images have no byte field in richdoc.Image, so an embedded picture is surfaced as a data: URI in Image.URL (and re-embedded on write); external http(s) references pass through as-is.

License

BSD-3-Clause. Copyright (c) the go-odf authors.

Documentation

Overview

Package odf converts between ODT (OpenDocument Text) packages and the neutral github.com/go-richdoc/richdoc document model.

An ODT file is a ZIP container of XML parts. Parse opens the container, reads content.xml (resolving inline formatting against the automatic styles there and the named styles in styles.xml), consults META-INF/manifest.xml for embedded image media types, and maps the office:text body onto richdoc blocks and inlines. Write produces a minimal, valid OpenDocument Text package: the mimetype entry is written first and stored uncompressed, as the OpenDocument packaging specification requires.

The two directions are designed as a faithful round-trip: Parse(Write(d)) is semantically equal to d for the supported model.

OpenDocument has no dedicated element for several richdoc nodes (code blocks, block quotes, thematic breaks, inline/display math); those are written using standard ODF container elements tagged with attributes in a private namespace ("https://github.com/go-odf/odf"), which ODF consumers ignore and which let Parse re-recognize the node. Constructs the model has no node for at all (footnotes, bookmarks, cross-references, and any other unrecognized element) are preserved verbatim through richdoc.RawInline / richdoc.RawBlock with Format "odf", so nothing in the source is lost.

The package is pure Go and builds with CGO disabled, including for GOOS=js/GOARCH=wasm.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Parse

func Parse(src []byte) (*richdoc.Document, error)

Parse converts the bytes of an ODT (OpenDocument Text) package into a richdoc.Document.

It opens the ZIP container, resolves inline formatting in content.xml against the automatic styles there and the named styles in styles.xml, reads embedded image bytes (surfaced as data: URIs) using META-INF/manifest.xml for their media types, and reads document metadata from meta.xml. Unrecognized elements are preserved verbatim as richdoc.RawBlock / richdoc.RawInline with Format "odf". A container that is not a ZIP, that lacks content.xml, that holds a corrupt entry, or whose XML is malformed returns an error.

func Write

func Write(d *richdoc.Document) ([]byte, error)

Write renders a richdoc.Document as the bytes of a minimal, valid OpenDocument Text (.odt) package.

The returned ZIP always begins with a stored (uncompressed) mimetype entry, as the OpenDocument packaging specification requires, followed by META-INF/manifest.xml, content.xml, styles.xml, an optional meta.xml (when the document carries metadata) and any embedded Pictures/. Inline formatting is generated as automatic text styles in content.xml.

Write is the inverse of Parse over the supported model: parsing Write's output reproduces the input tree. An richdoc.Image whose URL is a data: URI is decoded and re-embedded; a malformed data: URI is the only input that makes Write fail.

Types

This section is empty.

Jump to

Keyboard shortcuts

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