Skip to content

Commit e1fefaa

Browse files
authored
Merge pull request #37 from JSv4/chore/docxodus-v14.1.0
Upgrade Docxodus engine to v14.1.0
2 parents 8de8ab3 + 95c0459 commit e1fefaa

6 files changed

Lines changed: 41 additions & 7 deletions

File tree

‎CLAUDE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Python-Redlines generates `.docx` redline/tracked-changes documents by comparing
99
Two comparison engines are available:
1010
- **XmlPowerToolsEngine** — wraps Open-XML-PowerTools WmlComparer (original engine).
1111
Deprecated as of 1.0.0: instantiating it emits a `DeprecationWarning`. Still published.
12-
- **DocxodusEngine** — wraps Docxodus, a modernized .NET 10.0 fork with better move detection.
12+
- **DocxodusEngine** — wraps Docxodus v14.1.0, a modernized .NET 10.0 fork with better move detection.
1313
Runs `DocxDiff`, its only algorithm — Docxodus v11.0.0 deleted `WmlComparer`.
1414

1515
## Monorepo structure — three published packages

‎README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,9 @@ argument raises `ValueError`.
164164
### 1. `DocxodusEngine` — the default
165165

166166
**[Docxodus](https://github.com/JSv4/Docxodus)** is an actively-maintained .NET 10.0 document
167-
toolchain. Its `DocxDiff` algorithm models the document as an intermediate representation rather
168-
than a stream of runs, which lets it attribute a change to the exact paragraph, cell, row, or
169-
section it touched:
167+
toolchain. Python-Redlines 1.1.0 bundles Docxodus v14.1.0. Its `DocxDiff` algorithm
168+
models the document as an intermediate representation rather than a stream of runs,
169+
which lets it attribute a change to the exact paragraph, cell, row, or section it touched:
170170

171171
- **Structure-aware** — tracks table cell and row properties, section properties, and header and
172172
footer content that a run-stream diff reports coarsely or not at all

‎docxodus‎

Submodule docxodus updated 1278 files
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-FileCopyrightText: 2024-present U.N. Owen <void@some.where>
22
#
33
# SPDX-License-Identifier: MIT
4-
__version__ = "1.0.1"
4+
__version__ = "1.1.0"

‎packages/docxodus/README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
Compiled Docxodus redline engine binary for
44
[`python-redlines`](https://pypi.org/project/python-redlines/).
55

6+
Version 1.1.0 bundles the engine built from Docxodus v14.1.0.
7+
68
This package only contains the platform-specific engine binary. Install it via
79
the `python-redlines` extra rather than directly:
810

‎tests/test_docxodus_engine.py‎

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import io
22
import re
33
import zipfile
4+
import xml.etree.ElementTree as ET
45

56
import pytest
67

78
from python_redlines.engines import DocxodusEngine
89

9-
# Measured against the Docxodus v12.1.0 binary on tests/fixtures/. Docxodus
10+
# Measured against the Docxodus v14.1.0 binary on tests/fixtures/. Docxodus
1011
# v11.0.0 removed WmlComparer, so DocxDiff is the only algorithm; the count is
1112
# neither the 9 the old default reported nor the 11 the old opt-in reported.
1213
EXPECTED_REVISIONS = 10
@@ -71,6 +72,37 @@ def test_docxodus_output_is_a_valid_docx_with_tracked_changes(original_docx, mod
7172
assert "<w:del " in document_xml
7273

7374

75+
def test_docxodus_marks_a_single_changed_cjk_character(original_docx):
76+
"""Guard the CJK granularity fix needed by users upgrading from 0.3.0 (#34)."""
77+
namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
78+
ns = {"w": namespace}
79+
80+
def make_document(text):
81+
output = io.BytesIO()
82+
with zipfile.ZipFile(io.BytesIO(original_docx)) as template:
83+
document = ET.Element(f"{{{namespace}}}document")
84+
body = ET.SubElement(document, f"{{{namespace}}}body")
85+
paragraph = ET.SubElement(body, f"{{{namespace}}}p")
86+
run = ET.SubElement(paragraph, f"{{{namespace}}}r")
87+
ET.SubElement(run, f"{{{namespace}}}t").text = text
88+
with zipfile.ZipFile(output, "w") as archive:
89+
for member in template.infolist():
90+
data = (ET.tostring(document, encoding="utf-8", xml_declaration=True)
91+
if member.filename == "word/document.xml"
92+
else template.read(member.filename))
93+
archive.writestr(member, data)
94+
return output.getvalue()
95+
96+
before = make_document("本合同的交付日期为三月十五日,双方应按约履行。")
97+
after = make_document("本合同的交付日期为一月十五日,双方应按约履行。")
98+
redline, _, stderr = DocxodusEngine().run_redline("Reviewer", before, after)
99+
assert stderr is None
100+
with zipfile.ZipFile(io.BytesIO(redline)) as archive:
101+
document = ET.fromstring(archive.read("word/document.xml"))
102+
assert "".join(node.text or "" for node in document.findall(".//w:delText", ns)) == "三"
103+
assert "".join(node.text or "" for node in document.findall(".//w:ins//w:t", ns)) == "一"
104+
105+
74106
# --- Integration tests for comparison settings ---
75107

76108
def test_docxodus_with_detect_moves(original_docx, modified_docx):

0 commit comments

Comments
 (0)