Skip to main content

GordonKit Document Converter

CI Python 3.12+ License: Apache-2.0 Development Status: Pre-Alpha

繁體中文 · 简体中文 · 日本語

Documentation

GordonKit Document Converter converts DOCX and other document formats to PDF, HTML, Markdown, images, and more. It provides a Python library, CLI, and HTTP API, using Microsoft Word, LibreOffice, Pandoc, or Gotenberg for rendering.

Supported format conversions

Input DOCX PDF ODT HTML Markdown YAML JSON Images
DOCX × Auto LO ✓ ✓ ✓ ✓ PDF
PDF — × — ✓ ✓ ✓ ✓ ✓
ODT LO LO × ✓ ✓ ✓ ✓ PDF
HTML P W LO × ✓ ✓ ✓ PDF
Markdown P W LO ✓ × ✓ ✓ PDF

Auto policy-based engine selection · ✓ built in · LO LibreOffice · P Pandoc · W wkhtmltopdf · PDF via an intermediate PDF · — not supported · × same format; not a conversion

Page-image output is available as PNG or JPEG. Markdown, HTML, YAML, JSON, and image files are output artifacts for DOCX, ODT, and PDF sources; Markdown and HTML are also accepted as input for PDF, DOCX, ODT, and page-image conversion. HTML input additionally converts to Markdown, YAML, and JSON through the same semantic extraction used for DOCX, ODT, and PDF; that route needs no external engine. Markdown input converts to HTML, YAML, and JSON through that same extraction, and to PDF, DOCX, ODT, and page images through the rendering route.

ODT semantic artifacts are read directly from the ODF package, so Markdown, HTML, YAML, and JSON need no external engine. ODT page images render the document to PDF first and therefore require LibreOffice.

DOCX-to-ODT, ODT-to-DOCX, and ODT-to-PDF conversion use LibreOffice. DOCX conversion follows these engine policies:

  • DOCX to PDF on interactive Windows: automatic mode prefers Word COM.
  • DOCX to PDF on servers: automatic mode prefers Gotenberg, then LibreOffice.
  • DOCX to PDF on other hosts: automatic mode prefers LibreOffice.
  • DOCX to HTML: semantic extraction is the default. On a Windows desktop with Word COM available, Word rendering provides higher visual fidelity.
  • Use --engine word-com to force Word COM HTML, or --mode server to force semantic extraction.
  • Explicit engine and strict modes never fall back.
  • Rendering may differ between engines.

ODT support targets ODF-CNS 15251 / ISO/IEC 26300 Writer documents. It validates package structure and content readability, but does not promise pixel-identical round trips.

DOCX output from markup requires Pandoc. PDF output requires wkhtmltopdf, which renders the document itself: Pandoc's HTML reader keeps only the body and the document metadata, so routing print HTML through it would discard the page setup and fonts the document carries. ODT output requires LibreOffice, and page images render the document to PDF first, so they need wkhtmltopdf too. Markdown is rendered through a print-ready A4 HTML intermediate, so its PDF, DOCX, ODT, and page images all share one page setup and CJK font stack.

Where wkhtmltopdf or Pandoc is missing — the container image carries LibreOffice alone — markup PDF and DOCX fall back to LibreOffice, and the result reports an ENGINE_FALLBACK warning naming the engine that was substituted. LibreOffice reads the same intermediate and keeps the A4 page setup, table grid, and CJK fonts; it renders headings in a different face and leaves table headers unshaded, so install wkhtmltopdf where the exact layout matters.

Create an editable starting point with gordon-doc template report.html or gordon-doc template notes.md, then convert it with gordon-doc convert report.html --to pdf, --to docx, --to odt, or --to images. Use --orientation landscape for an A4 horizontal layout; a Markdown starter carries no page setup of its own, so its orientation is chosen at conversion time.

HTML-to-Markdown/YAML/JSON conversion parses the document directly and requires no engine:

gordon-doc convert report.html --to markdown --to yaml --to json

Headings, paragraphs, lists, tables, links, <ins>/<del> revisions, and <title>/<meta> metadata are normalized into the same schema DOCX and PDF sources produce. Inline data: images become files in a <stem>.assets directory; images referenced by URL stay linked. Script, style, and embedded-object elements are omitted, and every omission or lossy mapping is reported as a machine-readable warning.

Markdown input takes the same route, parsing CommonMark with GFM tables and strikethrough:

gordon-doc convert notes.md --to html --to yaml --to json

Headings, paragraphs, nested lists, tables, links, emphasis, code spans and blocks, block quotes, and thematic breaks are normalized into that same schema. GFM task-list items keep their state as the □ and ☑ symbols, which every output can render. A leading YAML front-matter block becomes document metadata. Inline data: images become files in <stem>.assets; images referenced by path or URL stay linked. Raw HTML blocks are omitted, apart from the <ins>, <del>, and <br> tags the writers themselves emit.

Interfaces

Interface Intended use
Python library Embed typed conversion calls, batches, and engine diagnostics in Python applications
gordon-doc CLI Run local conversions from a terminal, script, or CI job
HTTP API Send authenticated conversion requests to a private service deployment
Container profiles Run the CLI or HTTP API with renderer dependencies in isolated images

Every interface enters through the same application service and preserves structured results, engine policy, and diagnostics. Choose the interface that matches where the conversion is initiated, then follow its quick start below.

Installation

Interface Installation
Python library python -m pip install gordon-doc-converter
gordon-doc CLI Included with gordon-doc-converter; verify with gordon-doc version
HTTP API python -m pip install "gordon-doc-converter[api]"
Container profiles Install Docker Engine or Docker Desktop with Compose v2; no local Python package is required

Rendering and output capabilities may require an optional extra: gordon-doc-converter[images], gordon-doc-converter[gotenberg], or gordon-doc-converter[word]. See the online documentation for engine and platform requirements.

Quick start

Python library

Use the library when conversion is part of a Python application:

from pathlib import Path

from gordon_doc_converter import ConversionRequest, convert

request = ConversionRequest.from_source(Path("example.docx"))
result = convert(request)
if not result.success:
    raise RuntimeError(result.error.message if result.error else "conversion failed")
print(result.artifacts[0].path)

convert() selects an engine according to the deployment policy, validates staged output, and publishes the PDF only after validation succeeds. Use DocumentConversionService for engine injection, convert_batch() for sequential failure-isolated batches, and probe_engines() for capability diagnostics.

CLI

Use the CLI for interactive use, shell scripts, and CI jobs:

gordon-doc convert example.docx --output example.pdf

Containers

Use the single container image when you do not want to install Python or LibreOffice on the host. The cli profile mounts the current directory at /work and does not require an API key. This command is the same in Bash and PowerShell:

docker compose -f docker/compose.yaml --profile cli run --rm cli convert /work/example.docx --output /work/example.pdf

For a private HTTP service with LibreOffice in the same image, set an API key and start the standalone-lo profile. A .env file works in Bash and PowerShell:

GORDON_DOC_API_KEY=replace-with-a-strong-random-value
docker compose -f docker/compose.yaml --env-file .env --profile standalone-lo up --build

Use gateway-gotenberg instead to run the same API image with a separate Gotenberg renderer on a shared Docker network. Setting GORDON_DOC_GOTENBERG_URL makes Gotenberg the API's explicit default; a failed Gotenberg request does not silently fall back to LibreOffice. Container profiles, security notes, and smoke checks are documented in container documentation. Tagged releases publish gordonkit/gordon-doc-converter to Docker Hub. The required repository variables, secrets, and release steps are documented there.

HTTP API

Once the API is running, submit the DOCX bytes with the original filename and bearer token:

curl --fail -H "Authorization: Bearer replace-me" \
    -H "Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document" \
    -H "X-Filename: example.docx" --data-binary @example.docx \
    http://localhost:8000/conversions --output example.pdf

On PowerShell, use Invoke-WebRequest -InFile ... -OutFile .... Complete Bash and PowerShell examples for the LibreOffice and Gotenberg profiles, including shutdown, are in the container documentation.

Install .[images] for PDFium/Pillow rasterization, .[gotenberg] for the remote adapter, .[api] for FastAPI, or .[word] for Windows COM.

Command-line interface

gordon-doc doctor
gordon-doc engines --json
gordon-doc template report.html --orientation portrait
gordon-doc convert example.docx --output example.pdf
gordon-doc convert report.odt --to docx
gordon-doc convert report.odt --to markdown --to yaml --to json
gordon-doc convert report.odt --to images --dpi 144
gordon-doc convert example.docx --to odt --engine libreoffice
gordon-doc convert report.html --to pdf --orientation landscape
gordon-doc convert report.html --to docx
gordon-doc convert example.pdf --to images --dpi 144
gordon-doc convert example.docx --to markdown --to html --to yaml --to json
gordon-doc convert example.docx --to html --engine word-com
gordon-doc convert example.docx --to yaml --metadata layout --progress
gordon-doc convert example.docx --to json --json-lines
gordon-doc compare expected.pdf actual.pdf --diff-dir differences --json
gordon-doc batch one.docx two.docx --output-dir converted --json
gordon-doc version

Use --engine word-com, --engine libreoffice, or a configured --engine gotenberg for strict explicit selection. For DOCX-to-HTML, --engine word-com renders through Word COM; omit it or use --mode server for semantic extraction. Conversion options also include --mode, --revisions, --comments, --metadata, --timeout, --overwrite, image format/quality/page selection, and an optional --gotenberg-url. Page images use <stem>.pages/0001.png; semantic artifacts use .md, .html, .yaml, .json, shared .assets/, and an annotation sidecar when present. YAML and JSON share a versioned heading/paragraph/list/table schema intended for downstream indexing. --to json writes that document artifact; the separate --json flag emits the CLI result contract for automation.

Add --json-lines to write the JSON artifact as newline-delimited JSON to <stem>.jsonl instead of <stem>.json. It carries the same schema and content as the nested document, one self-describing record per line: a document record first, then every block in source order, then asset, annotation, and warning records. Each block record repeats the fields of its nested counterpart and adds section_path, the enclosing section identifiers, so the heading hierarchy stays reconstructable from a line stream. The flag applies to DOCX, PDF, and HTML sources, and affects only the JSON artifact; Markdown, HTML, and YAML outputs are unchanged.

PDF sources have no semantic tags, so blocks are inferred from layout. The converter rebuilds text lines from glyph positions, drops repeated running headers and footers, and classifies headings from the PDF outline, relative font size, weight, spacing, and ordinal markers. Markers are parsed by system, style, and unit, covering Arabic, Roman, Latin, circled, and CJK numerals, so heading levels follow the document's own numbering rather than font size alone. Inference is heuristic and reading order remains reported as inferred.

Metadata detail is none, basic (the default allowlisted document properties), or layout. PDF physical pages are one-based and identify pypdf as their provider. DOCX physical pages and display page labels are omitted with an explicit unavailable capability until a layout provider is configured; the converter does not present inferred page numbers as exact.

Structured artifacts include cross-format reverse locators. source.sha256 identifies the exact source file, while each source_anchor includes a normalized-content SHA-256 for verification. DOCX blocks locate word/document.xml elements (and table cells by row/cell); PDF blocks locate their one-based physical page. PDF anchors currently identify a page rather than a bounding box; a future layout provider can add page coordinates without changing the DOCX locator contract. Optional locator fields are omitted instead of being serialized as null.

schema_version: "1.3"
source: {format: "pdf", sha256: "<source-file-sha256>"}
root_blocks: [{
    id: "block-000001",
    source_order: 0,
    kind: "paragraph",
    physical_page_number: 1,
    text: "Page text",
    source_anchor: {
        locator: "pdf-page",
        page_number: 1,
        content_sha256: "<normalized-content-sha256>"
    }
}]

Byte offsets are deliberately not part of the stable locator contract. A DOCX offset points into a compressed ZIP member and changes when Office rewrites or recompresses the package. A PDF offset identifies serialized objects or streams and changes after optimization, linearization, or incremental saves. Use the source fingerprint plus OOXML element path or PDF page anchor instead. Byte offsets may be added later only as non-authoritative diagnostic hints.

convert and batch show conversion phases automatically on interactive terminals. Progress is written only to stderr and is automatically disabled for --json or redirected output; use --progress or --no-progress to override the automatic choice.

Stable exit codes are 0 for success, 2 for invalid input or an existing output, 3 for engine or capability unavailability, 4 for conversion failure, timeout, or missing output, and 5 for PDF validation failure.

Microsoft Word and LibreOffice can render the same document differently. The project will report the selected engine and fallback reason; it will never promise identical output or silently switch an explicitly selected engine.

Development setup

uv sync --dev
uv sync --dev --all-extras
uv run ruff format --check .
uv run ruff check .
uv run mypy src
uv run pytest
uv build

The real LibreOffice integration test is skipped when soffice is unavailable. Run it on a host with LibreOffice installed using uv run pytest -m integration tests/integration/libreoffice.

The Microsoft Word integration test requires Windows, licensed Microsoft Word, and the word optional dependency. Run it only in a controlled interactive environment using uv sync --dev --extra word --locked followed by uv run pytest -m integration tests/integration/word_com.

The static documentation is a React site built with Vite, Tailwind CSS, bundled Heroicons, and a bundled Swagger UI. Install the API and frontend dependencies before rebuilding docs/; the build exports the current FastAPI contract to openapi.json automatically:

uv sync --dev --extra api --locked
npm ci
npm run build

The generated site is self-contained under docs/ and is published at docs.gordonkit.com. It generates indexable pages under /en/<topic>/, /zh-TW/<topic>/, /zh-CN/<topic>/, and /ja/<topic>/ with localized metadata, canonical and alternate links, structured data, a sitemap, and robots directives. The site also supports a language dropdown for English, Traditional Chinese, Simplified Chinese, and Japanese, search, responsive layouts, and a light/dark theme. The generated API contract is available at docs/openapi.json, and the read-only Swagger UI is available at docs/swagger/index.html. Run npm run openapi:check to detect a stale export.

Browse the English documentation, Traditional Chinese documentation, Simplified Chinese documentation, or Japanese documentation for the technical reference, user guide, compatibility notes, and development standards.

License

Apache License 2.0. See LICENSE, NOTICE, and THIRD_PARTY_NOTICES.txt.

Metadata

Release files for gordon-doc-converter 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gordon-doc-converter 0.9.0
File Size Uploaded
gordon_doc_converter-0.9.0.tar.gz 930.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gordon-doc-converter 0.9.0
File Interpreter ABI Platform
gordon_doc_converter-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.1 MB

Release files / gordon_doc_converter-0.9.0.tar.gz

Download URL gordon_doc_converter-0.9.0.tar.gz
Size 930.2 kB
Tags Source
SHA-256 checksum
How to use checksums
e937cb45a18c1b197e20f2683856ccec3e34cd4ea5445601e9e617c3b86be69c
BLAKE2b-256 checksum
How to use checksums
ef35f8404be514c30d0867c7a9672bbff2fd989343b684685f09b88dca8ad09b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.

Transparency log

Release files / gordon_doc_converter-0.9.0-py3-none-any.whl

Download URL gordon_doc_converter-0.9.0-py3-none-any.whl
Size 135.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aa0aba6917b547fe656bb38bb223112542443e364b3b5e94d0401ab2e4c19981
BLAKE2b-256 checksum
How to use checksums
cada8cb01f17212249f68c1e7615719d5cddeca8e42bdeacbfc8f55be7583837
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.

Transparency log

Release history Release notifications | RSS feed

0.10.0

2 release files

This release

0.9.0 This release

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page