From 1566cca50c33a59e0b7b40ac8f406ffa24481f60 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 00:10:08 +0000 Subject: [PATCH] Improve SEO: PyPI keywords, alternatives comparison, docs site - Expand PyPI keywords in packages/core/pyproject.toml with search-intent terms (docx-comparison, compare-word-documents, track-changes-api, python-docx-diff, legal-tech, docxodus) and a search-friendly package description; add Documentation/Demo project URLs. - Add docs/alternatives.md comparing Python-Redlines to Draftable API, Cloudmersive, and server-side MS Word automation, with a condensed version linked from the README. - Add a hyper-focused tutorial: docs/tutorials/how-to-compare-word-documents-python.md. - Stand up a MkDocs (Material) static docs site: mkdocs.yml, docs/index.md with SoftwareApplication JSON-LD schema markup, auto-generated sitemap.xml, and a GitHub Pages deploy workflow. - Link the redlines.opensource.legal demo site from the README and docs homepage. --- .github/workflows/docs.yml | 42 ++++++ .gitignore | 3 + README.md | 47 +++++- docs/alternatives.md | 123 ++++++++++++++++ docs/index.md | 88 ++++++++++++ docs/quickstart.md | 9 +- .../how-to-compare-word-documents-python.md | 135 ++++++++++++++++++ mkdocs.yml | 55 +++++++ packages/core/pyproject.toml | 19 ++- 9 files changed, 514 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/alternatives.md create mode 100644 docs/index.md create mode 100644 docs/tutorials/how-to-compare-word-documents-python.md create mode 100644 mkdocs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..0f18fa6 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,42 @@ +name: Deploy docs site + +on: + push: + branches: [main] + paths: + - "docs/**" + - "mkdocs.yml" + - "README.md" + - ".github/workflows/docs.yml" + workflow_dispatch: {} + +permissions: + contents: write + +concurrency: + group: docs-deploy + cancel-in-progress: true + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install MkDocs + run: pip install mkdocs-material + + - name: Configure git identity + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Build (strict) + run: mkdocs build --strict + + - name: Deploy to GitHub Pages + run: mkdocs gh-deploy --force --clean diff --git a/.gitignore b/.gitignore index 5d501c3..2dd6c46 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ docxodus/**/obj/* packages/*/src/*/_binaries/*.tar.gz packages/*/src/*/_binaries/*.zip +# MkDocs build output +site/ + # C extensions *.so diff --git a/README.md b/README.md index 1bfbde9..3b6ff26 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,21 @@ -# Python-Redlines: Docx Redlines (Tracked Changes) for the Python Ecosystem +# Python-Redlines: Open-Source DOCX Comparison for Python -Generate tracked-change "redline" `.docx` documents from Python — compare two Word files -and get back a third document showing every insertion, deletion, and (optionally) move as -native Word tracked changes. +Open-source DOCX comparison tool to generate native Word tracked changes (redlines) in +Python — compare two Word files and get back a third document showing every insertion, +deletion, and (optionally) move as native Word tracked changes, **without any MS Word +dependency**. Comparing `.docx` documents has long been dominated by commercial software, with cost barriers and little integration flexibility. Python-Redlines brings open-source `.docx` redlining to the Python ecosystem so legal hackers, hobbyists, and product teams can build on it freely: two documents in, one redline out. +**🔗 Try it now: [redlines.opensource.legal](https://redlines.opensource.legal)** — a +live browser demo of the comparison engine, no install required. See also the +[full documentation site](https://jsv4.github.io/Python-Redlines/) and +[Python-Redlines vs. commercial alternatives](docs/alternatives.md) (Draftable API, +Cloudmersive, server-side MS Word automation). + ## Quick Start The **default engine is [Docxodus](https://github.com/JSv4/Docxodus)** — a modernized, @@ -313,6 +320,38 @@ The engines produce slightly different stdout messages: The revision counts differ between the two Docxodus engines because the algorithms differ, not because either is wrong. +## Python-Redlines vs. Commercial Alternatives + +Looking for a `.docx` comparison tool and weighing it against a paid API? Short +version: Python-Redlines is a free, MIT-licensed, self-hosted library — your documents +never leave your process, there's no per-comparison fee, and it works fully offline. +The full write-up, including feature-by-feature tables, lives in +[docs/alternatives.md](docs/alternatives.md): + +### Python-Redlines vs Draftable API + +[Draftable](https://draftable.com/)'s document comparison API is metered per +comparison and requires sending your documents to a third-party cloud service. +Python-Redlines runs in-process with no per-call cost, no network dependency, and full +source availability (MIT license). See +[the detailed comparison](docs/alternatives.md#python-redlines-vs-draftable-api). + +### Why choose Python-Redlines over Cloudmersive + +[Cloudmersive](https://cloudmersive.com/)'s document comparison endpoint is one part +of a broader, metered, closed-source API. Python-Redlines has no API keys, no quotas, +and keeps document bytes local to your own infrastructure. See +[the detailed comparison](docs/alternatives.md#why-choose-python-redlines-over-cloudmersive). + +### The problem with server-side MS Word automation + +Driving a headless copy of MS Word via COM/Interop to generate tracked changes +violates Microsoft's Terms of Service for unattended server-side use and is +operationally fragile under concurrent load. Python-Redlines produces the same native +Word tracked-changes `.docx` output via a lightweight, self-contained comparison +engine — no Word installation, no TOS risk. See +[the full breakdown](docs/alternatives.md#the-problem-with-server-side-ms-word-automation). + ## Development ### Prerequisites diff --git a/docs/alternatives.md b/docs/alternatives.md new file mode 100644 index 0000000..fae6000 --- /dev/null +++ b/docs/alternatives.md @@ -0,0 +1,123 @@ +# Python-Redlines vs. Commercial DOCX Comparison Alternatives + +Developers evaluating a way to compare Word documents and produce tracked-changes +redlines programmatically usually land on one of a handful of commercial SDKs and +cloud APIs. This page compares **Python-Redlines** — a free, open-source, self-hosted +`.docx` comparison library for Python — against the most common alternatives, so you +can pick the right tool for your architecture, budget, and compliance requirements. + +Try the engine yourself before reading further: **[live demo at +redlines.opensource.legal](https://redlines.opensource.legal)** — upload two `.docx` +files and download a real tracked-changes redline, no signup required. + +## The short version + +| | Python-Redlines | Draftable API | Cloudmersive | Server-side MS Word automation | +|---|---|---|---|---| +| **License cost** | Free, MIT | Paid, per-comparison or subscription | Paid, per-call metered | Requires a licensed, running MS Word/Office install | +| **Where it runs** | In-process / self-hosted, any Python environment | Cloud API (your documents leave your infrastructure) | Cloud API (your documents leave your infrastructure) | Self-hosted, but against Microsoft's Terms of Service | +| **Data privacy** | Documents never leave your process | Documents transit a third-party cloud service | Documents transit a third-party cloud service | Self-hosted, but fragile and unsupported | +| **Output format** | Native Word tracked-changes `.docx` | Native Word tracked-changes `.docx` | Native Word tracked-changes `.docx` | Native Word tracked-changes `.docx` | +| **Offline / air-gapped use** | ✅ Yes | ❌ No — requires network access to the vendor | ❌ No — requires network access to the vendor | ✅ Yes, if you can keep Word running headless | +| **Rate limits / metering** | None — it's a local library call | Per-plan API quotas | Per-call billing | None, but see below | +| **Move detection** | ✅ Yes (Docxodus engine) | ✅ Yes | Limited | Depends on Word version | +| **Source availability** | ✅ Full source, MIT licensed | ❌ Closed source | ❌ Closed source | N/A | + +## Python-Redlines vs Draftable API + +[Draftable](https://draftable.com/) is a well-known commercial document comparison API +that supports Word, PDF, and PowerPoint. It's a capable product, but it comes with +trade-offs that matter for many Python teams: + +- **Cost scales with usage.** Draftable API pricing is metered by comparison volume. + For high-throughput legal-tech or document-automation pipelines — think a contract + lifecycle management platform diffing thousands of documents a day — that cost + compounds quickly. Python-Redlines has no per-comparison fee because it runs + in-process. +- **Documents leave your infrastructure.** Every comparison is a network call to a + third-party service. For legal, healthcare, and financial-services workloads + handling privileged or regulated content, that's an extra data-processing agreement + to negotiate and an extra party in your threat model. Python-Redlines never sends + document content over the network — it's a local `.docx` diff and `.docx` output. +- **No offline or air-gapped support.** Draftable requires live connectivity to its + API. Python-Redlines works in disconnected environments, CI pipelines, and + on-premise deployments because the comparison engine ships as a self-contained + binary embedded in the wheel. +- **Closed source.** You cannot audit, fork, or patch Draftable's comparison logic. + Python-Redlines (and its underlying [Docxodus](https://github.com/JSv4/Docxodus) + and [Open-XML-PowerTools](https://github.com/OpenXmlDev/Open-Xml-PowerTools) + engines) is fully open source under the MIT license. + +**Where Draftable may still be the right call:** if you need a single hosted endpoint +across many document formats (PDF, PPTX, images) with a support SLA and don't want to +own any infrastructure, a managed API has real appeal. Python-Redlines is Word-`.docx` +specific and you run it yourself. + +## Why choose Python-Redlines over Cloudmersive + +[Cloudmersive](https://cloudmersive.com/) offers a general-purpose document/file +processing API, including a document comparison endpoint, billed per API call. + +- **Per-call cloud pricing vs. a free library call.** Cloudmersive's document + comparison is one endpoint in a broad, metered API surface. Python-Redlines has no + API keys, no quotas, and no bill — it's a `pip install` and a function call. +- **Data privacy and residency.** Cloudmersive comparisons happen on Cloudmersive's + servers (or a licensed on-premise appliance, itself a paid tier). Python-Redlines + keeps document bytes in your own process the entire time — nothing to configure for + data residency because nothing leaves. +- **Redline fidelity.** Python-Redlines' default engine (Docxodus) supports move + detection, format-change detection, and structure-aware diffing (via the optional + `docxdiff` algorithm) — producing native Word tracked-changes output tuned + specifically for `.docx`, rather than a generic document-diff endpoint shared across + many file formats. +- **No vendor lock-in.** Cloudmersive's comparison logic is closed and proprietary. + Python-Redlines is MIT-licensed open source: inspect the C# comparison engines, + build them yourself, or contribute a fix upstream. + +## The problem with server-side MS Word automation + +Before dedicated comparison libraries existed, the common workaround was driving a +real, licensed copy of Microsoft Word headlessly on a server — via COM automation, +Office Interop, or similar — to generate tracked changes. + +- **It violates Microsoft's Terms of Service.** Microsoft explicitly does not support + or license unattended, server-side automation of desktop Office applications. This + is a real compliance and legal risk for any production system, not a theoretical + one. +- **It's operationally fragile.** Desktop Word was never designed to run headless at + scale — it crashes under concurrent load, leaves zombie processes, requires a GUI + session or virtual display, and needs a full Windows + Office license per + worker/VM. +- **It doesn't scale horizontally the way a library does.** Every comparison ties up + a full Office process; Python-Redlines' engines are lightweight, self-contained + .NET binaries invoked as subprocesses, safe to run concurrently and to containerize. + +Python-Redlines produces the same **native Word tracked-changes `.docx` output** — +insertions, deletions, and moves that Word renders as real revisions — without ever +launching Word, and without the TOS risk. + +## High-performance, cross-platform document diffing + +Python-Redlines' default engine, [Docxodus](https://github.com/JSv4/Docxodus), is a +modernized, actively-maintained .NET 10 fork of Open-XML-PowerTools' `WmlComparer` — +a high-performance document diffing engine purpose-built for cross-platform Word +document comparison. It ships as a prebuilt, self-contained binary embedded directly +in the Python wheel for Linux, macOS, and Windows (x64 and arm64), so there's no .NET +SDK to install and no compilation step for end users — just `pip install +python-redlines[docxodus]`. + +For enterprise developers evaluating open-source alternatives to commercial document +diffing SDKs, that combination — open-source licensing, in-process execution, native +Word tracked-changes output, and a high-performance comparison engine with move and +format-change detection — is the core value proposition. + +## Try it yourself + +The fastest way to evaluate Python-Redlines against your own documents is the hosted +demo: **[redlines.opensource.legal](https://redlines.opensource.legal)**. Upload an +original and a modified `.docx`, and download a genuine Word tracked-changes redline +generated by the same engine this library wraps. + +For local integration, see the [Quickstart guide](quickstart.md) or the +[tutorial: how to compare two Word documents programmatically in +Python](tutorials/how-to-compare-word-documents-python.md). diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..194a0ab --- /dev/null +++ b/docs/index.md @@ -0,0 +1,88 @@ +# Python-Redlines: Open-Source DOCX Comparison for Python + +**Python-Redlines** is an open-source DOCX comparison tool that generates native Word +tracked changes (redlines) in Python — without any MS Word dependency. Compare two +`.docx` files and get back a third document showing every insertion, deletion, and +(optionally) moved block of text as real Word tracked changes, openable in Microsoft +Word, LibreOffice, or Google Docs. + + + +**🔗 [Try the live demo](https://redlines.opensource.legal)** — upload two `.docx` +files in your browser and download a real tracked-changes redline, no install +required. + +## Why Python-Redlines + +- **Open source, MIT licensed** — inspect, fork, or contribute to the comparison + engines. No per-comparison fees, no API keys, no vendor lock-in. +- **Runs in-process** — document bytes never leave your infrastructure, unlike + cloud comparison APIs. Works fully offline and in air-gapped environments. +- **No Microsoft Word required** — no COM automation, no Office Interop, no Terms + of Service risk from server-side Word automation. +- **Native tracked-changes output** — the redline `.docx` opens in Word with real + insertions, deletions, and moves, attributable to an author tag. +- **Cross-platform, high-performance diffing engine** — the default + [Docxodus](https://github.com/JSv4/Docxodus) engine is a modernized .NET 10 + fork of Open-XML-PowerTools' `WmlComparer`, shipped as a prebuilt, self-contained + binary embedded in the wheel for Linux, macOS, and Windows (x64/arm64) — nothing to + compile. + +## Install + +```bash +pip install python-redlines[docxodus] +``` + +## Minimal example + +```python +from python_redlines import DocxodusEngine + +with open("original.docx", "rb") as f: + original = f.read() +with open("modified.docx", "rb") as f: + modified = f.read() + +engine = DocxodusEngine() +redline_bytes, stdout, stderr = engine.run_redline("Reviewer", original, modified) + +with open("redline.docx", "wb") as f: + f.write(redline_bytes) +``` + +## Where to go next + +- [How to compare two Word documents programmatically in Python](tutorials/how-to-compare-word-documents-python.md) — + a hands-on, step-by-step tutorial +- [Quickstart guide](quickstart.md) +- [Python-Redlines vs. commercial alternatives](alternatives.md) — Draftable API, + Cloudmersive, and why not to automate MS Word server-side +- [Developer guide](developer-guide.md) — repository layout, building the C# engines, + releasing +- [GitHub repository](https://github.com/JSv4/Python-Redlines) +- [PyPI package](https://pypi.org/project/python-redlines/) diff --git a/docs/quickstart.md b/docs/quickstart.md index b033a04..592cbb0 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -59,7 +59,7 @@ with open('/path/to/redline_output.docx', 'wb') as f: ### Step 4: Tune the Comparison (optional, DocxodusEngine only) `DocxodusEngine` accepts keyword arguments to control move detection, granularity, and -more. See the [main README](../README.md#comparison-settings-docxodusengine-only) for +more. See the [main README](https://github.com/JSv4/Python-Redlines#comparison-settings-docxodusengine-only) for the full table. ```python @@ -72,3 +72,10 @@ output = wrapper.run_redline( ``` `XmlPowerToolsEngine` silently ignores these kwargs — switch engines if you need them. + +### See also + +- [How to compare two Word documents programmatically in Python](tutorials/how-to-compare-word-documents-python.md) — + a step-by-step tutorial covering this same flow in more depth +- [Live demo](https://redlines.opensource.legal) — try a comparison in your browser +- [Python-Redlines vs. commercial alternatives](alternatives.md) diff --git a/docs/tutorials/how-to-compare-word-documents-python.md b/docs/tutorials/how-to-compare-word-documents-python.md new file mode 100644 index 0000000..78bd594 --- /dev/null +++ b/docs/tutorials/how-to-compare-word-documents-python.md @@ -0,0 +1,135 @@ +# How to compare two Word documents programmatically in Python + +This tutorial walks through comparing two `.docx` files in Python and producing a +native Word tracked-changes redline — the same kind of output you'd get from Word's +built-in "Compare Documents" feature, but scriptable, automatable, and free. + +We'll use [Python-Redlines](https://github.com/JSv4/Python-Redlines), an open-source +DOCX comparison library. You can try the underlying engine in your browser first at +**[redlines.opensource.legal](https://redlines.opensource.legal)** before writing any +code. + +## What you'll build + +A small Python script that takes an `original.docx` and a `modified.docx`, compares +them, and writes out `redline.docx` — a Word document where every insertion, deletion, +and (optionally) moved block of text is marked up as a real Word tracked change, +openable and reviewable in Microsoft Word, LibreOffice, or Google Docs. + +## Prerequisites + +- Python 3.9+ +- Two `.docx` files to compare (any two versions of the same Word document) + +No Microsoft Word installation, no COM automation, and no .NET SDK are required — the +comparison engine is a prebuilt, self-contained binary embedded in the wheel. + +## Step 1: Install the library + +```bash +pip install python-redlines[docxodus] +``` + +This installs the pure-Python wrapper (`python-redlines`) plus the default comparison +engine, [Docxodus](https://github.com/JSv4/Docxodus) — a modernized, high-performance +.NET 10 document diffing engine with move detection and cross-platform prebuilt +binaries for Linux, macOS, and Windows. + +## Step 2: Load the two documents + +```python +with open("original.docx", "rb") as f: + original_bytes = f.read() + +with open("modified.docx", "rb") as f: + modified_bytes = f.read() +``` + +You can also pass file paths directly to `run_redline` instead of reading bytes +yourself — both are supported. + +## Step 3: Run the comparison + +```python +from python_redlines import DocxodusEngine + +engine = DocxodusEngine() +redline_bytes, stdout, stderr = engine.run_redline( + "Reviewer", # author tag attributed to each tracked change + original_bytes, + modified_bytes, +) +``` + +`run_redline` returns a 3-tuple: the redline `.docx` as bytes, and the engine's raw +stdout/stderr (useful for logging or a revision count — see +[stdout differences](https://github.com/JSv4/Python-Redlines#stdout-differences)). + +## Step 4: Save the redline + +```python +with open("redline.docx", "wb") as f: + f.write(redline_bytes) +``` + +Open `redline.docx` in Word and you'll see standard tracked changes — insertions +underlined, deletions struck through, attributed to the `"Reviewer"` author tag you +passed in — exactly as if a human had compared the documents with Word's own Compare +feature. + +## Full script + +```python +from python_redlines import DocxodusEngine + +with open("original.docx", "rb") as f: + original_bytes = f.read() +with open("modified.docx", "rb") as f: + modified_bytes = f.read() + +engine = DocxodusEngine() +redline_bytes, stdout, stderr = engine.run_redline("Reviewer", original_bytes, modified_bytes) + +with open("redline.docx", "wb") as f: + f.write(redline_bytes) + +print(stdout) # e.g. "Redline complete: 9 revision(s) found" +``` + +## Tuning the comparison + +`DocxodusEngine` accepts keyword arguments for move detection, comparison +granularity, and more: + +```python +redline_bytes, stdout, stderr = engine.run_redline( + "Reviewer", original_bytes, modified_bytes, + detect_moves=True, + simplify_move_markup=True, # required alongside detect_moves for Word compatibility + detail_threshold=0.3, # lower = more detailed diff + case_insensitive=True, +) +``` + +See the [comparison settings reference](https://github.com/JSv4/Python-Redlines#comparison-settings-docxodusengine-only) +for every option and which engine supports it. + +## Why not automate MS Word instead? + +A common older approach is scripting Word itself (COM automation on Windows, or +Office Interop) to run its built-in comparison. This works on a single desktop but is +a poor fit for a server or pipeline: it violates Microsoft's Terms of Service for +unattended server-side use, requires a full licensed Office install per worker, and is +prone to crashes and zombie processes under concurrent load. Python-Redlines produces +the same native Word tracked-changes output without launching Word at all. See the +full [Python-Redlines vs. commercial alternatives](../alternatives.md) comparison for +more on this and other trade-offs (Draftable API, Cloudmersive, cloud data privacy). + +## Next steps + +- [Quickstart guide](../quickstart.md) — the same walkthrough with more detail on + engine choice +- [Comparison engines](https://github.com/JSv4/Python-Redlines#comparison-engines) — `wmlcomparer` vs + `docxdiff` vs the legacy Open-XML-PowerTools engine +- [Live demo](https://redlines.opensource.legal) — try a comparison in your browser + first diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..e36060a --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,55 @@ +site_name: Python-Redlines +site_url: https://jsv4.github.io/Python-Redlines/ +site_description: >- + Open-source DOCX comparison tool to generate native Word tracked changes (redlines) + in Python without MS Word dependencies. +site_author: John Scrudato IV +repo_name: JSv4/Python-Redlines +repo_url: https://github.com/JSv4/Python-Redlines +edit_uri: edit/main/docs/ +docs_dir: docs +copyright: MIT License + +theme: + name: material + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - navigation.instant + - navigation.tracking + - navigation.top + - search.suggest + - content.code.copy + - content.action.edit + +nav: + - Home: index.md + - Quickstart: quickstart.md + - Tutorials: + - How to compare two Word documents in Python: tutorials/how-to-compare-word-documents-python.md + - Alternatives: alternatives.md + - Developer Guide: developer-guide.md + +markdown_extensions: + - admonition + - tables + - toc: + permalink: true + - pymdownx.highlight + - pymdownx.superfences + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/JSv4/Python-Redlines + - icon: fontawesome/brands/python + link: https://pypi.org/project/python-redlines/ diff --git a/packages/core/pyproject.toml b/packages/core/pyproject.toml index 62d0bee..b0ba2b7 100644 --- a/packages/core/pyproject.toml +++ b/packages/core/pyproject.toml @@ -5,11 +5,24 @@ build-backend = "hatchling.build" [project] name = "python-redlines" dynamic = ["version"] -description = "Generate tracked-change redline .docx documents by comparing Word files." +description = "Open-source DOCX comparison tool to generate native Word tracked changes (redlines) in Python without MS Word dependencies." readme = "README.md" requires-python = ">=3.9" license = "MIT" -keywords = ["docx", "redline", "diff", "tracked-changes", "openxml", "word"] +keywords = [ + "docx", + "redline", + "diff", + "tracked-changes", + "openxml", + "word", + "docx-comparison", + "compare-word-documents", + "track-changes-api", + "python-docx-diff", + "legal-tech", + "docxodus", +] authors = [ { name = "John Scrudato IV" }, ] @@ -37,6 +50,8 @@ all = ["python-redlines-ooxmlpowertools", "python-redlines-docxodus"] [project.urls] Homepage = "https://github.com/JSv4/Python-Redlines" +Documentation = "https://jsv4.github.io/Python-Redlines/" +Demo = "https://redlines.opensource.legal" Issues = "https://github.com/JSv4/Python-Redlines/issues" Source = "https://github.com/JSv4/Python-Redlines"