doctaculous

module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: MIT

README

doctaculous

A pure-Go, MIT-licensed document toolkit. No CGo, no native bindings — everything is Go.

The long-term goal is an "everything" document tool: convert between formats, author and sign PDF/DOCX/HTML, and rasterize pages to images.

Built for tinycld, where it powers document thumbnails and other format conversions.

Status

The PDF pipeline (parse → interpret → rasterize) and the reflow engine (HTML and DOCX through a shared CSS layout engine) work end-to-end and render real-world documents faithfully. Any supported input converts to any supported output — inputs: PDF, DOCX, XLSX, HTML, Markdown, plain text, CSV/TSV, http(s) URLs; outputs: PDF, DOCX, XLSX, HTML, Markdown, plain text, CSV/TSV (spreadsheet outputs carry the document's tables — including tables recovered from PDFs), PNG, JPEG:

doctaculous convert report.docx report.pdf
doctaculous convert https://example.com page.png
doctaculous convert input.pdf notes.md            # structure recovered by extraction
doctaculous rasterize input.pdf --page 1 --out page1.png --dpi 150

convert detects the input format from content and extension (--from overrides) and takes the output format from the output extension (--to overrides). Converting a document to its own format is not supported. The focused subcommands (rasterize, topdf, tomd, tohtml) remain.

See the "Status & roadmap" section of CLAUDE.md for the full, current feature list (filters, fonts, encryption, shadings, CSS coverage, …) and what's next. Unsupported features degrade gracefully (skipped with a debug log, or a typed error) rather than failing the render.

Why pure Go?

Existing high-fidelity renderers (PDFium, MuPDF, Poppler) require CGo and/or carry copyleft licenses. doctaculous renders PDF content streams itself in pure Go, so it builds as a single static binary, cross-compiles freely, and stays MIT-licensed.

Architecture

A layered pipeline; each layer is independently testable:

Layer Package Responsibility
Parse pkg/pdf Tokenizer, objects, xref, page tree
Filter pkg/pdf/filter Decode stream bytes (Flate, ASCII85, …)
Interpret pkg/pdf/content Content-stream tokenizer + graphics state
Device pkg/render Backend-agnostic paint ops (Device interface)
Raster pkg/render/raster Bitmap backend → image.Image
API pkg/doctaculous Public library entry point
CLI cmd/doctaculous Thin command-line wrapper

The Device interface is the seam that will let us add other backends (e.g. SVG) later.

Test fixtures

Test PDFs aren't committed — they're generated deterministically in testdata/gen, so each fixture is readable Go rather than an opaque blob. To materialize them as real .pdf files for inspection:

go run ./cmd/dumpfixtures -list           # show available fixtures
go run ./cmd/dumpfixtures                 # write the core set to ./fixtures-out
go run ./cmd/dumpfixtures -all -o /tmp    # include malformed fixtures too
go run ./cmd/dumpfixtures text objstm     # write only named fixtures

Development

make build   # build the CLI
make test    # go test ./... (with race detector)
make lint    # go vet + golangci-lint

License

MIT — see LICENSE.

The library and all its source code are MIT-licensed. One exception: the real-world PDF samples under testdata/external/ are third-party test inputs licensed CC-BY-SA-4.0 (from py-pdf/sample-files), kept isolated there with their own license text. They are test fixtures only — never compiled into or shipped with the module — so they don't affect the MIT licensing of the library. See that directory's README for details and attribution.

Third-party / vendored code

JBIG2 image decoding is provided by xiaoqidun/jbig2 — a pure-Go JBIG2 (ITU T.88) decoder under the Apache License 2.0 — vendored into pkg/pdf/filter/jbig2/ (a copy in-tree, not a module dependency). Apache-2.0 is MIT-compatible; the vendored directory retains the upstream LICENSE and NOTICE, and its README.md records the exact source and version. See that directory for full attribution.

Directories

Path Synopsis
cmd
doctaculous command
Command doctaculous is the command-line interface to the doctaculous document toolkit.
Command doctaculous is the command-line interface to the doctaculous document toolkit.
dumpfixtures command
Command dumpfixtures materializes the in-memory test PDF fixtures to disk so they can be inspected or opened in a viewer.
Command dumpfixtures materializes the in-memory test PDF fixtures to disk so they can be inspected or opened in a viewer.
pkg
css
Package css is a pure-Go, hand-written CSS engine: it tokenizes and parses CSS (CSS Syntax Level 3), matches selectors against a DOM with correct specificity, and runs the cascade and inheritance to compute the effective style of each element.
Package css is a pure-Go, hand-written CSS engine: it tokenizes and parses CSS (CSS Syntax Level 3), matches selectors against a DOM with correct specificity, and runs the cascade and inheritance to compute the effective style of each element.
doctaculous
Package doctaculous is the public API for the doctaculous document toolkit.
Package doctaculous is the public API for the doctaculous document toolkit.
docx
Package docx is a WordprocessingML (.docx) document model with a reader and a writer: Open/OpenBytes/OpenReaderAt parse a package into the exported model; Write/Bytes serialize a model back to a complete package.
Package docx is a WordprocessingML (.docx) document model with a reader and a writer: Open/OpenBytes/OpenReaderAt parse a package into the exported model; Write/Bytes serialize a model back to a complete package.
docx/cssbox
Package cssbox lowers a parsed DOCX document into the recursive cssbox tree the CSS layout engine consumes, replacing the flat pkg/docx/lower + pkg/layout/box path.
Package cssbox lowers a parsed DOCX document into the recursive cssbox tree the CSS layout engine consumes, replacing the flat pkg/docx/lower + pkg/layout/box path.
docx/style
Package style resolves WordprocessingML's style cascade into the effective run and paragraph properties used by the reflow layout engine.
Package style resolves WordprocessingML's style cascade into the effective run and paragraph properties used by the reflow layout engine.
epub
Package epub is a read-only EPUB reader: it opens the container, walks META-INF/container.xml to the OPF package document, and extracts the spine documents' body markup in reading order plus their stylesheets — the pieces the HTML pipeline lays out (EPUB content IS XHTML, so the reflow engine does the real work).
Package epub is a read-only EPUB reader: it opens the container, walks META-INF/container.xml to the OPF package document, and extracts the spine documents' body markup in reading order plus their stylesheets — the pieces the HTML pipeline lays out (EPUB content IS XHTML, so the reflow engine does the real work).
font
Package font turns embedded PDF font programs into glyph outlines.
Package font turns embedded PDF font programs into glyph outlines.
font/standard
Package standard bundles permissively-licensed substitute fonts for the PDF standard-14 base fonts (and common aliases) so that simple fonts which declare a standard /BaseFont but embed no font program can still be rendered.
Package standard bundles permissively-licensed substitute fonts for the PDF standard-14 base fonts (and common aliases) so that simple fonts which declare a standard /BaseFont but embed no font program can still be rendered.
html
Package html is the HTML frontend: it parses HTML bytes (via golang.org/x/net/html) into an owned, read-only DOM that implements the pkg/css Node interface, and collects the stylesheets the cascade needs (<style> contents, <link rel=stylesheet> hrefs, and inline style="").
Package html is the HTML frontend: it parses HTML bytes (via golang.org/x/net/html) into an owned, read-only DOM that implements the pkg/css Node interface, and collects the stylesheets the cascade needs (<style> contents, <link rel=stylesheet> hrefs, and inline style="").
layout/css
Package css is the box-generation stage: it walks an html.Document, drives the pkg/css cascade per element, and emits a cssbox tree.
Package css is the box-generation stage: it walks an html.Document, drives the pkg/css cascade per element, and emits a cssbox tree.
layout/cssbox
Package cssbox defines the recursive, format-neutral box tree that the CSS layout engine consumes.
Package cssbox defines the recursive, format-neutral box tree that the CSS layout engine consumes.
layout/font
Package font provides a concurrency-safe cache of resolved font faces for the reflow engine.
Package font provides a concurrency-safe cache of resolved font faces for the reflow engine.
layout/inline
Package inline is the format-neutral inline-layout core: text shaping, greedy line-breaking, and horizontal alignment math shared by every reflow engine.
Package inline is the format-neutral inline-layout core: text shaping, greedy line-breaking, and horizontal alignment math shared by every reflow engine.
layout/paint
Package paint draws a laid-out page (pkg/layout) onto a render.Device.
Package paint draws a laid-out page (pkg/layout) onto a render.Device.
markdown
Package markdown is the Markdown input frontend: it converts CommonMark + GFM source into a complete HTML document that the HTML pipeline (parse → box generation → CSS layout) renders.
Package markdown is the Markdown input frontend: it converts CommonMark + GFM source into a complete HTML document that the HTML pipeline (parse → box generation → CSS layout) renders.
pdf
Package pdf parses PDF file structure: the tokenizer, indirect objects, cross-reference tables and streams, object streams, and the page tree.
Package pdf parses PDF file structure: the tokenizer, indirect objects, cross-reference tables and streams, object streams, and the page tree.
pdf/content
Package content interprets a PDF page content stream.
Package content interprets a PDF page content stream.
pdf/extract
Package extract reconstructs document structure (paragraphs, headings, lists, tables) from a PDF's positioned glyphs and vector graphics, then builds a *cssbox.Box tree the existing conversion writers turn into Markdown/HTML.
Package extract reconstructs document structure (paragraphs, headings, lists, tables) from a PDF's positioned glyphs and vector graphics, then builds a *cssbox.Box tree the existing conversion writers turn into Markdown/HTML.
pdf/filter
Package filter decodes PDF stream data.
Package filter decodes PDF stream data.
pdf/filter/jbig2
Package jbig2 一个高性能、零依赖的纯 Go 语言 JBIG2 解码器
Package jbig2 一个高性能、零依赖的纯 Go 语言 JBIG2 解码器
pdf/function
Package function implements the PDF Function objects of ISO 32000-1 §7.10.
Package function implements the PDF Function objects of ISO 32000-1 §7.10.
pdf/pageres
Package pageres resolves the page-/Resources entries the raster and extract backends share: fonts, form XObjects, and their /Matrix and /BBox.
Package pageres resolves the page-/Resources entries the raster and extract backends share: fonts, form XObjects, and their /Matrix and /BBox.
pptx
Package pptx is a read-only PresentationML (.pptx) reader: it extracts each visible slide's shapes — text frames with their paragraph/run formatting and bullet levels, pictures, and tables — with positions resolved through the slide → layout → master placeholder inheritance, so a conversion frontend can lay each slide out as one fixed-size page.
Package pptx is a read-only PresentationML (.pptx) reader: it extracts each visible slide's shapes — text frames with their paragraph/run formatting and bullet levels, pictures, and tables — with positions resolved through the slide → layout → master placeholder inheritance, so a conversion frontend can lay each slide out as one fixed-size page.
render
Package render defines the device-independent graphics layer: the Device interface that the content interpreter drives, along with the geometry types (paths, matrices, paint) shared between the interpreter and concrete backends.
Package render defines the device-independent graphics layer: the Device interface that the content interpreter drives, along with the geometry types (paths, matrices, paint) shared between the interpreter and concrete backends.
render/csvwrite
Package csvwrite renders the TABLES of a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, XLSX, and PDF-extraction frontends) as delimiter-separated values.
Package csvwrite renders the TABLES of a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, XLSX, and PDF-extraction frontends) as delimiter-separated values.
render/docxwrite
Package docxwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to a WordprocessingML (.docx) package.
Package docxwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to a WordprocessingML (.docx) package.
render/epubwrite
Package epubwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to an EPUB 3 package.
Package epubwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to an EPUB 3 package.
render/htmlwrite
Package htmlwrite serializes a cssbox tree (the shared box model produced by the HTML and DOCX frontends) back to HTML.
Package htmlwrite serializes a cssbox tree (the shared box model produced by the HTML and DOCX frontends) back to HTML.
render/internal/boxwalk
Package boxwalk holds the format-neutral cssbox tree analysis shared by the markdown and htmlwrite writers.
Package boxwalk holds the format-neutral cssbox tree analysis shared by the markdown and htmlwrite writers.
render/markdown
Package markdown renders a cssbox tree (the shared box model produced by the HTML and DOCX frontends) to GitHub-Flavored Markdown, or to plain text.
Package markdown renders a cssbox tree (the shared box model produced by the HTML and DOCX frontends) to GitHub-Flavored Markdown, or to plain text.
render/pdfwrite
Package pdfwrite implements a render.Device that emits a PDF document instead of pixels.
Package pdfwrite implements a render.Device that emits a PDF document instead of pixels.
render/pptxwrite
Package pptxwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to a PresentationML (.pptx) deck.
Package pptxwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to a PresentationML (.pptx) deck.
render/raster
Package raster implements the render.Device interface on top of an image.RGBA.
Package raster implements the render.Device interface on top of an image.RGBA.
render/rtfwrite
Package rtfwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to a Rich Text Format document.
Package rtfwrite renders a cssbox tree (the shared box model produced by the HTML, DOCX, Markdown, and PDF-extraction frontends) to a Rich Text Format document.
render/xlsxwrite
Package xlsxwrite renders the TABLES of a cssbox tree (the shared box model produced by every frontend) as a SpreadsheetML (.xlsx) workbook: one worksheet per table, named from the table's caption when present.
Package xlsxwrite renders the TABLES of a cssbox tree (the shared box model produced by every frontend) as a SpreadsheetML (.xlsx) workbook: one worksheet per table, named from the table's caption when present.
resource
Package resource defines the seam by which a document's external references (stylesheets via <link>, images, and fonts) are resolved to bytes.
Package resource defines the seam by which a document's external references (stylesheets via <link>, images, and fonts) are resolved to bytes.
rtf
Package rtf reads Rich Text Format documents into HTML for the reflow pipeline — the same shape the CSV and XLSX frontends use: a dependency-free hand-rolled parser producing markup the HTML engine lays out, so every output format follows.
Package rtf reads Rich Text Format documents into HTML for the reflow pipeline — the same shape the CSV and XLSX frontends use: a dependency-free hand-rolled parser producing markup the HTML engine lays out, so every output format follows.
xlsx
Package xlsx is a read-only SpreadsheetML (.xlsx) reader: it extracts each visible sheet's CACHED cell values — the last value Excel computed, stored in the file — as display strings, along with the presentation facts a document conversion needs (bold/italic, fill color, alignment, merged ranges).
Package xlsx is a read-only SpreadsheetML (.xlsx) reader: it extracts each visible sheet's CACHED cell values — the last value Excel computed, stored in the file — as display strings, along with the presentation facts a document conversion needs (bold/italic, fill color, alignment, merged ranges).
xlsx/internal/xmlpart
Package xmlpart is the raw-fidelity XML layer the xlsx editor rewrites dirty parts through.
Package xmlpart is the raw-fidelity XML layer the xlsx editor rewrites dirty parts through.

Jump to

Keyboard shortcuts

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