pilcrow-docx 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pilcrow_docx-0.1.1/MANIFEST.in +3 -0
- pilcrow_docx-0.1.1/PKG-INFO +218 -0
- pilcrow_docx-0.1.1/README.md +210 -0
- pilcrow_docx-0.1.1/docs/example.md +48 -0
- pilcrow_docx-0.1.1/docs/limitations.md +109 -0
- pilcrow_docx-0.1.1/docs/manual-validation.md +40 -0
- pilcrow_docx-0.1.1/pyproject.toml +17 -0
- pilcrow_docx-0.1.1/scripts/bump_version.py +38 -0
- pilcrow_docx-0.1.1/setup.cfg +4 -0
- pilcrow_docx-0.1.1/src/pilcrow/__init__.py +3 -0
- pilcrow_docx-0.1.1/src/pilcrow/__main__.py +3 -0
- pilcrow_docx-0.1.1/src/pilcrow/cli.py +79 -0
- pilcrow_docx-0.1.1/src/pilcrow/extract.py +365 -0
- pilcrow_docx-0.1.1/src/pilcrow/files.py +152 -0
- pilcrow_docx-0.1.1/src/pilcrow/prose.py +34 -0
- pilcrow_docx-0.1.1/src/pilcrow_docx.egg-info/PKG-INFO +218 -0
- pilcrow_docx-0.1.1/src/pilcrow_docx.egg-info/SOURCES.txt +22 -0
- pilcrow_docx-0.1.1/src/pilcrow_docx.egg-info/dependency_links.txt +1 -0
- pilcrow_docx-0.1.1/src/pilcrow_docx.egg-info/entry_points.txt +2 -0
- pilcrow_docx-0.1.1/src/pilcrow_docx.egg-info/requires.txt +1 -0
- pilcrow_docx-0.1.1/src/pilcrow_docx.egg-info/top_level.txt +1 -0
- pilcrow_docx-0.1.1/tests/__init__.py +0 -0
- pilcrow_docx-0.1.1/tests/test_cli.py +610 -0
- pilcrow_docx-0.1.1/tests/test_release.py +47 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pilcrow-docx
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Readable DOCX companion diffs for ordinary Git workflows
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: defusedxml<1,>=0.7.1
|
|
8
|
+
|
|
9
|
+
# Pilcrow
|
|
10
|
+
|
|
11
|
+
Pilcrow makes Word text changes reviewable in GitHub Desktop. Keep editing the
|
|
12
|
+
`.docx`; export readable companion files and commit both through your normal Git
|
|
13
|
+
workflow. **The DOCX is authoritative.** The prose is a generated review artifact,
|
|
14
|
+
not an editable replacement or a round-trip format.
|
|
15
|
+
|
|
16
|
+
This is an independent, small Python implementation, conceptually inspired by the
|
|
17
|
+
companion-file approach of stet. No source or tests were copied from that project.
|
|
18
|
+
|
|
19
|
+
## Install locally
|
|
20
|
+
|
|
21
|
+
Requires Python 3.10 or later. Git is needed for repository discovery and the Git
|
|
22
|
+
workflow. Word is not required to export. From this project's directory:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
python -m pip install .
|
|
26
|
+
pilcrow --help
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Use `python3` instead of `python` on systems where needed. A virtual environment
|
|
30
|
+
is recommended (`python -m venv .venv`); activate it before installing:
|
|
31
|
+
|
|
32
|
+
- macOS/Linux: `source .venv/bin/activate`
|
|
33
|
+
- Windows PowerShell: `.venv\Scripts\Activate.ps1`
|
|
34
|
+
- Windows Command Prompt: `.venv\Scripts\activate.bat`
|
|
35
|
+
|
|
36
|
+
If activation is unavailable, invoke `.venv/bin/python` or
|
|
37
|
+
`.venv\Scripts\python.exe` directly with `-m pip install .`, then `-m pilcrow`.
|
|
38
|
+
For development, use `python -m pip install -e .`.
|
|
39
|
+
|
|
40
|
+
Pilcrow uses Python's ZIP reader and `defusedxml` for XML parsing. There is no Word
|
|
41
|
+
process, cloud service, AI connection, watcher, or background service. Extraction
|
|
42
|
+
never writes to the DOCX.
|
|
43
|
+
|
|
44
|
+
## Baseline, then review a change
|
|
45
|
+
|
|
46
|
+
In **your document repository**, choose an explicit scope. For example:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
pilcrow export --all --root .
|
|
50
|
+
pilcrow check --all --root .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or select documents (paths are relative to your current directory):
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
pilcrow export "report.docx" "chapters/Methods and results.docx" --root .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Outputs retain the complete source-relative filename:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
report.docx
|
|
63
|
+
chapters/Methods and results.docx
|
|
64
|
+
.pilcrow/report.docx.prose.md
|
|
65
|
+
.pilcrow/report.docx.meta.json
|
|
66
|
+
.pilcrow/chapters/Methods and results.docx.prose.md
|
|
67
|
+
.pilcrow/chapters/Methods and results.docx.meta.json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
1. Export a baseline. In GitHub Desktop, review and commit the DOCX and its two
|
|
71
|
+
companion files together. Do not put `.pilcrow/` in `.gitignore`.
|
|
72
|
+
2. Edit and save the DOCX in Word, or use a separate document-editing tool.
|
|
73
|
+
3. Run the same `pilcrow export` command again.
|
|
74
|
+
4. In Desktop's **Changes** view, select the `.prose.md` file to read the text diff;
|
|
75
|
+
inspect `.meta.json` for review/coverage changes. The DOCX may still say binary
|
|
76
|
+
changed. Review formatting/images in Word when relevant.
|
|
77
|
+
5. Commit the DOCX and both companions together through Desktop, then push and
|
|
78
|
+
branch normally. Desktop's **History** view can show committed companion diffs.
|
|
79
|
+
|
|
80
|
+
Pilcrow never stages, commits, pushes, switches branches, or merges. No direct
|
|
81
|
+
DOCX text converter is installed. The CLI and an ordinary Git diff have been
|
|
82
|
+
tested; **the Microsoft Word / GitHub Desktop GUI workflow has not been tested in
|
|
83
|
+
this Linux environment**. See [manual validation](docs/manual-validation.md).
|
|
84
|
+
See an [actual generated prose and Git diff example](docs/example.md).
|
|
85
|
+
Old commits without companions will not gain prose diffs automatically; there is
|
|
86
|
+
no backfill or history rewriting.
|
|
87
|
+
|
|
88
|
+
## Scope and discovery
|
|
89
|
+
|
|
90
|
+
- `--root` defaults to the **current directory**, never an automatically detected
|
|
91
|
+
repository top. It controls both discovery and the location of `.pilcrow/`.
|
|
92
|
+
Use the same root each time. From a subdirectory, pass `--root ..` deliberately
|
|
93
|
+
if the output belongs at the parent. Explicit paths remain relative to the
|
|
94
|
+
current directory, not to `--root`.
|
|
95
|
+
- Supply paths **or** `--all`. No arguments does not silently scan the machine.
|
|
96
|
+
Passing a directory as a document is an error; use `--all --root directory`.
|
|
97
|
+
- Inside Git, `--all` uses `git ls-files` for tracked and nonignored untracked
|
|
98
|
+
files within the selected root. Tracked files remain included even if an ignore
|
|
99
|
+
rule matches. An explicitly selected ignored DOCX is allowed.
|
|
100
|
+
- Outside Git, `--all` recursively walks the selected directory. Git ignore rules
|
|
101
|
+
only apply inside a Git worktree; there is no separate ignore syntax.
|
|
102
|
+
- Both modes exclude Word lock files (`~$…`), `.pilcrow`, `.git`, `.venv`, `venv`,
|
|
103
|
+
`env`, `node_modules`, `__pycache__`, `.tox`, `.nox`, `build`, and `dist`.
|
|
104
|
+
Extension matching is case-insensitive. Unicode and spaces are supported.
|
|
105
|
+
- Symlink files/paths are rejected; directory walking does not follow symlink
|
|
106
|
+
directories. Submodule documents are not recursively discovered from the parent
|
|
107
|
+
repository: select a root inside the submodule.
|
|
108
|
+
- `--all` reports orphan companions after source deletion/rename. Remove the old
|
|
109
|
+
companion files manually if the deletion was intentional and commit those
|
|
110
|
+
deletions together. Export never automatically deletes review history files.
|
|
111
|
+
Explicit-file mode checks only selected inputs, not unrelated orphans.
|
|
112
|
+
|
|
113
|
+
## Check before committing
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
pilcrow check --all --root .
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`check` is read-only, even when files are missing. It recomputes expected prose and
|
|
120
|
+
metadata and compares bytes, tolerating ZIP order/compression, run boundaries,
|
|
121
|
+
save timestamps, and other ignored Word metadata. It does not use a DOCX-byte hash.
|
|
122
|
+
|
|
123
|
+
| Exit | Meaning |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| 0 | Successful export, or companions match the supported normalized view |
|
|
126
|
+
| 1 | Missing/stale companions in `check`, or orphan companions in either command |
|
|
127
|
+
| 2 | Invalid selection, unreadable/malformed input, unsafe path, or write failure |
|
|
128
|
+
|
|
129
|
+
Errors identify the file; remaining selected documents are processed after a
|
|
130
|
+
per-document error. Retry after Word has finished saving if a file is temporarily
|
|
131
|
+
unreadable or changes during extraction. A fresh result means **no supported
|
|
132
|
+
prose/review changes detected**, never that the complete document is identical.
|
|
133
|
+
Warnings appear on stderr and in metadata even for fresh results. Known coverage
|
|
134
|
+
limitations do not themselves cause a nonzero exit.
|
|
135
|
+
|
|
136
|
+
Writes use a temporary file and atomic replacement in the destination directory.
|
|
137
|
+
Byte-identical outputs keep their existing modification times. Each file is
|
|
138
|
+
atomic, **not the whole pair or batch**: if interrupted between files, run `check`
|
|
139
|
+
and export again. Avoid concurrent exports into the same root.
|
|
140
|
+
|
|
141
|
+
## Branches and conflicts
|
|
142
|
+
|
|
143
|
+
Opt in to conservative merge rules once, from your document repository root:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
pilcrow setup --root .
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
This appends a managed block to `.gitattributes`, preserving other rules. Repeating
|
|
150
|
+
it is harmless. Review and commit the file through Desktop. Rules mark DOCX and
|
|
151
|
+
all `.pilcrow/` files `-merge` (Git's binary merge driver), and companion files as
|
|
152
|
+
`text eol=lf`. Both-sided modifications conflict instead of automatically merging
|
|
153
|
+
prose into a document that never existed. Normal one-sided changes still merge.
|
|
154
|
+
More-specific nested attributes can override these rules; inspect with
|
|
155
|
+
`git check-attr merge -- "report.docx" ".pilcrow/report.docx.prose.md"` if needed.
|
|
156
|
+
|
|
157
|
+
When branches conflict:
|
|
158
|
+
|
|
159
|
+
1. Preserve copies of both versions of the DOCX outside the conflicted path.
|
|
160
|
+
2. Choose the authoritative version or reconcile the documents manually in Word.
|
|
161
|
+
If using Git commands to select a side, make sure you understand that side in
|
|
162
|
+
the current merge/rebase. Pilcrow does not make this choice.
|
|
163
|
+
3. Put the resolved DOCX at its repository path. Regenerate its companions, even
|
|
164
|
+
if Git did not flag them as conflicted. Never independently accept a merged
|
|
165
|
+
prose artifact as the Word document.
|
|
166
|
+
4. Run `pilcrow check --all --root .`. Inspect the resulting text and Word file,
|
|
167
|
+
then mark resolutions and commit using your normal Git workflow.
|
|
168
|
+
|
|
169
|
+
Git commit identity attributes a snapshot, not every contributor between saves.
|
|
170
|
+
For basic snapshot attribution:
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
git blame -- ".pilcrow/report.docx.prose.md"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Word tracked-change authors (included in review metadata) are separate from Git
|
|
177
|
+
authors. Neither proves an edit came from an AI. Companion metadata can contain
|
|
178
|
+
comment authors and deleted text: review it before sharing, just as you would the
|
|
179
|
+
DOCX. No automatic OOXML merging or sentence-lineage system is provided.
|
|
180
|
+
|
|
181
|
+
## Coverage and maintenance
|
|
182
|
+
|
|
183
|
+
See [coverage, normalization, and backlog](docs/limitations.md). The prose retains
|
|
184
|
+
common headings, list indentation, tables, notes, headers, and footers. Tracked
|
|
185
|
+
insertions/move destinations are included and deletions/move sources omitted.
|
|
186
|
+
Complex tracked structure/layout is limited and reported. Images, equations,
|
|
187
|
+
text boxes, and embedded objects are not rendered. Formatting-only edits can
|
|
188
|
+
leave both companions unchanged and still matter in Word.
|
|
189
|
+
|
|
190
|
+
Run the generated-fixture suite:
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
python -m unittest discover -s tests -v
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The implementation has four small modules: `prose.py` (segmentation), `extract.py`
|
|
197
|
+
(OOXML coverage), `files.py` (scope and writes), and `cli.py` (commands). Tests
|
|
198
|
+
include temporary Git repositories and failure cases. Generated fixtures do not
|
|
199
|
+
establish complete Microsoft Word compatibility. No real/private document corpus
|
|
200
|
+
was available for this implementation.
|
|
201
|
+
|
|
202
|
+
## Releases
|
|
203
|
+
|
|
204
|
+
Every push to `main` runs `.github/workflows/publish.yml`. Release runs are queued
|
|
205
|
+
and each checks out the current `main`, including previous release version bumps.
|
|
206
|
+
The workflow increments the patch version in `pyproject.toml` and
|
|
207
|
+
`src/pilcrow/__init__.py`, builds and validates the distributions, runs the test
|
|
208
|
+
suite, and verifies the installed CLI version. It then commits the version bump, pushes
|
|
209
|
+
the commit and tag atomically, and creates a GitHub release with the wheel and
|
|
210
|
+
source archive. Release commits use `chore(release): ... [skip ci]` to avoid loops.
|
|
211
|
+
If `main` advances during a build, the push fails safely before publishing; the
|
|
212
|
+
queued run checks out the newer `main`.
|
|
213
|
+
|
|
214
|
+
A separate job uploads those same release files to PyPI using Trusted Publishing.
|
|
215
|
+
Configure the PyPI publisher for owner `omertekin2002`, repository `Pilcrow`,
|
|
216
|
+
workflow `publish.yml`, and GitHub environment `pypi`. No PyPI API token is needed.
|
|
217
|
+
If only the PyPI upload fails, fix its configuration and use **Re-run failed jobs**
|
|
218
|
+
on that workflow run to retry the existing release without bumping the version.
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Pilcrow
|
|
2
|
+
|
|
3
|
+
Pilcrow makes Word text changes reviewable in GitHub Desktop. Keep editing the
|
|
4
|
+
`.docx`; export readable companion files and commit both through your normal Git
|
|
5
|
+
workflow. **The DOCX is authoritative.** The prose is a generated review artifact,
|
|
6
|
+
not an editable replacement or a round-trip format.
|
|
7
|
+
|
|
8
|
+
This is an independent, small Python implementation, conceptually inspired by the
|
|
9
|
+
companion-file approach of stet. No source or tests were copied from that project.
|
|
10
|
+
|
|
11
|
+
## Install locally
|
|
12
|
+
|
|
13
|
+
Requires Python 3.10 or later. Git is needed for repository discovery and the Git
|
|
14
|
+
workflow. Word is not required to export. From this project's directory:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
python -m pip install .
|
|
18
|
+
pilcrow --help
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Use `python3` instead of `python` on systems where needed. A virtual environment
|
|
22
|
+
is recommended (`python -m venv .venv`); activate it before installing:
|
|
23
|
+
|
|
24
|
+
- macOS/Linux: `source .venv/bin/activate`
|
|
25
|
+
- Windows PowerShell: `.venv\Scripts\Activate.ps1`
|
|
26
|
+
- Windows Command Prompt: `.venv\Scripts\activate.bat`
|
|
27
|
+
|
|
28
|
+
If activation is unavailable, invoke `.venv/bin/python` or
|
|
29
|
+
`.venv\Scripts\python.exe` directly with `-m pip install .`, then `-m pilcrow`.
|
|
30
|
+
For development, use `python -m pip install -e .`.
|
|
31
|
+
|
|
32
|
+
Pilcrow uses Python's ZIP reader and `defusedxml` for XML parsing. There is no Word
|
|
33
|
+
process, cloud service, AI connection, watcher, or background service. Extraction
|
|
34
|
+
never writes to the DOCX.
|
|
35
|
+
|
|
36
|
+
## Baseline, then review a change
|
|
37
|
+
|
|
38
|
+
In **your document repository**, choose an explicit scope. For example:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pilcrow export --all --root .
|
|
42
|
+
pilcrow check --all --root .
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or select documents (paths are relative to your current directory):
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
pilcrow export "report.docx" "chapters/Methods and results.docx" --root .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Outputs retain the complete source-relative filename:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
report.docx
|
|
55
|
+
chapters/Methods and results.docx
|
|
56
|
+
.pilcrow/report.docx.prose.md
|
|
57
|
+
.pilcrow/report.docx.meta.json
|
|
58
|
+
.pilcrow/chapters/Methods and results.docx.prose.md
|
|
59
|
+
.pilcrow/chapters/Methods and results.docx.meta.json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
1. Export a baseline. In GitHub Desktop, review and commit the DOCX and its two
|
|
63
|
+
companion files together. Do not put `.pilcrow/` in `.gitignore`.
|
|
64
|
+
2. Edit and save the DOCX in Word, or use a separate document-editing tool.
|
|
65
|
+
3. Run the same `pilcrow export` command again.
|
|
66
|
+
4. In Desktop's **Changes** view, select the `.prose.md` file to read the text diff;
|
|
67
|
+
inspect `.meta.json` for review/coverage changes. The DOCX may still say binary
|
|
68
|
+
changed. Review formatting/images in Word when relevant.
|
|
69
|
+
5. Commit the DOCX and both companions together through Desktop, then push and
|
|
70
|
+
branch normally. Desktop's **History** view can show committed companion diffs.
|
|
71
|
+
|
|
72
|
+
Pilcrow never stages, commits, pushes, switches branches, or merges. No direct
|
|
73
|
+
DOCX text converter is installed. The CLI and an ordinary Git diff have been
|
|
74
|
+
tested; **the Microsoft Word / GitHub Desktop GUI workflow has not been tested in
|
|
75
|
+
this Linux environment**. See [manual validation](docs/manual-validation.md).
|
|
76
|
+
See an [actual generated prose and Git diff example](docs/example.md).
|
|
77
|
+
Old commits without companions will not gain prose diffs automatically; there is
|
|
78
|
+
no backfill or history rewriting.
|
|
79
|
+
|
|
80
|
+
## Scope and discovery
|
|
81
|
+
|
|
82
|
+
- `--root` defaults to the **current directory**, never an automatically detected
|
|
83
|
+
repository top. It controls both discovery and the location of `.pilcrow/`.
|
|
84
|
+
Use the same root each time. From a subdirectory, pass `--root ..` deliberately
|
|
85
|
+
if the output belongs at the parent. Explicit paths remain relative to the
|
|
86
|
+
current directory, not to `--root`.
|
|
87
|
+
- Supply paths **or** `--all`. No arguments does not silently scan the machine.
|
|
88
|
+
Passing a directory as a document is an error; use `--all --root directory`.
|
|
89
|
+
- Inside Git, `--all` uses `git ls-files` for tracked and nonignored untracked
|
|
90
|
+
files within the selected root. Tracked files remain included even if an ignore
|
|
91
|
+
rule matches. An explicitly selected ignored DOCX is allowed.
|
|
92
|
+
- Outside Git, `--all` recursively walks the selected directory. Git ignore rules
|
|
93
|
+
only apply inside a Git worktree; there is no separate ignore syntax.
|
|
94
|
+
- Both modes exclude Word lock files (`~$…`), `.pilcrow`, `.git`, `.venv`, `venv`,
|
|
95
|
+
`env`, `node_modules`, `__pycache__`, `.tox`, `.nox`, `build`, and `dist`.
|
|
96
|
+
Extension matching is case-insensitive. Unicode and spaces are supported.
|
|
97
|
+
- Symlink files/paths are rejected; directory walking does not follow symlink
|
|
98
|
+
directories. Submodule documents are not recursively discovered from the parent
|
|
99
|
+
repository: select a root inside the submodule.
|
|
100
|
+
- `--all` reports orphan companions after source deletion/rename. Remove the old
|
|
101
|
+
companion files manually if the deletion was intentional and commit those
|
|
102
|
+
deletions together. Export never automatically deletes review history files.
|
|
103
|
+
Explicit-file mode checks only selected inputs, not unrelated orphans.
|
|
104
|
+
|
|
105
|
+
## Check before committing
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
pilcrow check --all --root .
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`check` is read-only, even when files are missing. It recomputes expected prose and
|
|
112
|
+
metadata and compares bytes, tolerating ZIP order/compression, run boundaries,
|
|
113
|
+
save timestamps, and other ignored Word metadata. It does not use a DOCX-byte hash.
|
|
114
|
+
|
|
115
|
+
| Exit | Meaning |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| 0 | Successful export, or companions match the supported normalized view |
|
|
118
|
+
| 1 | Missing/stale companions in `check`, or orphan companions in either command |
|
|
119
|
+
| 2 | Invalid selection, unreadable/malformed input, unsafe path, or write failure |
|
|
120
|
+
|
|
121
|
+
Errors identify the file; remaining selected documents are processed after a
|
|
122
|
+
per-document error. Retry after Word has finished saving if a file is temporarily
|
|
123
|
+
unreadable or changes during extraction. A fresh result means **no supported
|
|
124
|
+
prose/review changes detected**, never that the complete document is identical.
|
|
125
|
+
Warnings appear on stderr and in metadata even for fresh results. Known coverage
|
|
126
|
+
limitations do not themselves cause a nonzero exit.
|
|
127
|
+
|
|
128
|
+
Writes use a temporary file and atomic replacement in the destination directory.
|
|
129
|
+
Byte-identical outputs keep their existing modification times. Each file is
|
|
130
|
+
atomic, **not the whole pair or batch**: if interrupted between files, run `check`
|
|
131
|
+
and export again. Avoid concurrent exports into the same root.
|
|
132
|
+
|
|
133
|
+
## Branches and conflicts
|
|
134
|
+
|
|
135
|
+
Opt in to conservative merge rules once, from your document repository root:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
pilcrow setup --root .
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
This appends a managed block to `.gitattributes`, preserving other rules. Repeating
|
|
142
|
+
it is harmless. Review and commit the file through Desktop. Rules mark DOCX and
|
|
143
|
+
all `.pilcrow/` files `-merge` (Git's binary merge driver), and companion files as
|
|
144
|
+
`text eol=lf`. Both-sided modifications conflict instead of automatically merging
|
|
145
|
+
prose into a document that never existed. Normal one-sided changes still merge.
|
|
146
|
+
More-specific nested attributes can override these rules; inspect with
|
|
147
|
+
`git check-attr merge -- "report.docx" ".pilcrow/report.docx.prose.md"` if needed.
|
|
148
|
+
|
|
149
|
+
When branches conflict:
|
|
150
|
+
|
|
151
|
+
1. Preserve copies of both versions of the DOCX outside the conflicted path.
|
|
152
|
+
2. Choose the authoritative version or reconcile the documents manually in Word.
|
|
153
|
+
If using Git commands to select a side, make sure you understand that side in
|
|
154
|
+
the current merge/rebase. Pilcrow does not make this choice.
|
|
155
|
+
3. Put the resolved DOCX at its repository path. Regenerate its companions, even
|
|
156
|
+
if Git did not flag them as conflicted. Never independently accept a merged
|
|
157
|
+
prose artifact as the Word document.
|
|
158
|
+
4. Run `pilcrow check --all --root .`. Inspect the resulting text and Word file,
|
|
159
|
+
then mark resolutions and commit using your normal Git workflow.
|
|
160
|
+
|
|
161
|
+
Git commit identity attributes a snapshot, not every contributor between saves.
|
|
162
|
+
For basic snapshot attribution:
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
git blame -- ".pilcrow/report.docx.prose.md"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Word tracked-change authors (included in review metadata) are separate from Git
|
|
169
|
+
authors. Neither proves an edit came from an AI. Companion metadata can contain
|
|
170
|
+
comment authors and deleted text: review it before sharing, just as you would the
|
|
171
|
+
DOCX. No automatic OOXML merging or sentence-lineage system is provided.
|
|
172
|
+
|
|
173
|
+
## Coverage and maintenance
|
|
174
|
+
|
|
175
|
+
See [coverage, normalization, and backlog](docs/limitations.md). The prose retains
|
|
176
|
+
common headings, list indentation, tables, notes, headers, and footers. Tracked
|
|
177
|
+
insertions/move destinations are included and deletions/move sources omitted.
|
|
178
|
+
Complex tracked structure/layout is limited and reported. Images, equations,
|
|
179
|
+
text boxes, and embedded objects are not rendered. Formatting-only edits can
|
|
180
|
+
leave both companions unchanged and still matter in Word.
|
|
181
|
+
|
|
182
|
+
Run the generated-fixture suite:
|
|
183
|
+
|
|
184
|
+
```sh
|
|
185
|
+
python -m unittest discover -s tests -v
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The implementation has four small modules: `prose.py` (segmentation), `extract.py`
|
|
189
|
+
(OOXML coverage), `files.py` (scope and writes), and `cli.py` (commands). Tests
|
|
190
|
+
include temporary Git repositories and failure cases. Generated fixtures do not
|
|
191
|
+
establish complete Microsoft Word compatibility. No real/private document corpus
|
|
192
|
+
was available for this implementation.
|
|
193
|
+
|
|
194
|
+
## Releases
|
|
195
|
+
|
|
196
|
+
Every push to `main` runs `.github/workflows/publish.yml`. Release runs are queued
|
|
197
|
+
and each checks out the current `main`, including previous release version bumps.
|
|
198
|
+
The workflow increments the patch version in `pyproject.toml` and
|
|
199
|
+
`src/pilcrow/__init__.py`, builds and validates the distributions, runs the test
|
|
200
|
+
suite, and verifies the installed CLI version. It then commits the version bump, pushes
|
|
201
|
+
the commit and tag atomically, and creates a GitHub release with the wheel and
|
|
202
|
+
source archive. Release commits use `chore(release): ... [skip ci]` to avoid loops.
|
|
203
|
+
If `main` advances during a build, the push fails safely before publishing; the
|
|
204
|
+
queued run checks out the newer `main`.
|
|
205
|
+
|
|
206
|
+
A separate job uploads those same release files to PyPI using Trusted Publishing.
|
|
207
|
+
Configure the PyPI publisher for owner `omertekin2002`, repository `Pilcrow`,
|
|
208
|
+
workflow `publish.yml`, and GitHub environment `pypi`. No PyPI API token is needed.
|
|
209
|
+
If only the PyPI upload fails, fix its configuration and use **Re-run failed jobs**
|
|
210
|
+
on that workflow run to retry the existing release without bumping the version.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Example review artifact
|
|
2
|
+
|
|
3
|
+
Generated from a small test fixture in a temporary Git repository. This shows
|
|
4
|
+
text-diff readability, not validation in Word or Desktop.
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
# Study results
|
|
8
|
+
|
|
9
|
+
Dr. Kaya measured 3.14 units.
|
|
10
|
+
The treatment did not improve the outcome.
|
|
11
|
+
The control was unchanged.
|
|
12
|
+
|
|
13
|
+
- Review the result.
|
|
14
|
+
|
|
15
|
+
[Table]
|
|
16
|
+
|
|
17
|
+
[Row]
|
|
18
|
+
|
|
19
|
+
[Cell]
|
|
20
|
+
|
|
21
|
+
Treatment
|
|
22
|
+
|
|
23
|
+
[Cell]
|
|
24
|
+
|
|
25
|
+
12 participants
|
|
26
|
+
|
|
27
|
+
[/Row]
|
|
28
|
+
|
|
29
|
+
[/Table]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
After changing one sentence, ordinary `git diff` produced:
|
|
33
|
+
|
|
34
|
+
```diff
|
|
35
|
+
diff --git a/.pilcrow/research.docx.prose.md b/.pilcrow/research.docx.prose.md
|
|
36
|
+
index 7f199a2..c8bf275 100644
|
|
37
|
+
--- a/.pilcrow/research.docx.prose.md
|
|
38
|
+
+++ b/.pilcrow/research.docx.prose.md
|
|
39
|
+
@@ -1,7 +1,7 @@
|
|
40
|
+
# Study results
|
|
41
|
+
|
|
42
|
+
Dr. Kaya measured 3.14 units.
|
|
43
|
+
-The treatment improved the outcome.
|
|
44
|
+
+The treatment did not improve the outcome.
|
|
45
|
+
The control was unchanged.
|
|
46
|
+
|
|
47
|
+
- Review the result.
|
|
48
|
+
```
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Coverage and design choices
|
|
2
|
+
|
|
3
|
+
Version 0.1 is a partial prose view. This is neither a visual comparison nor a
|
|
4
|
+
lossless Word-to-Markdown converter. There is no import path from prose to DOCX.
|
|
5
|
+
Only conventional Transitional OOXML packages with `word/document.xml` are
|
|
6
|
+
accepted. Strict OOXML, encrypted Office files, legacy `.doc`, and both single-file
|
|
7
|
+
Word XML dialects are unsupported. They must not be relabeled `.docx`.
|
|
8
|
+
|
|
9
|
+
## Supported view
|
|
10
|
+
|
|
11
|
+
| Content | v1 behavior |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Paragraphs | Runs joined without artificial spaces; blank line between nonempty paragraphs |
|
|
14
|
+
| Headings | Outline level, inherited paragraph styles, and conventional Heading1–9 style IDs; capped at six Markdown levels |
|
|
15
|
+
| Lists | Item and indentation boundaries from direct/inherited `numPr`; generic `-` marker; automatic numbers/bullet glyphs are not reconstructed and trigger a warning |
|
|
16
|
+
| Tables | Explicit table, row, and cell markers, including empty cells; nested tables and content-control wrappers; grid spans/vertical merge markers retained, no rendered grid/layout |
|
|
17
|
+
| Footnotes/endnotes | Related parts with reference markers; separator notes omitted; IDs retained, so renumbering can produce diffs |
|
|
18
|
+
| Headers/footers | Related parts shown as separate sections by part name; no page/section placement mapping |
|
|
19
|
+
| Tracked text | Include `ins` and `moveTo`, omit `del` and `moveFrom`; separate kind, author, and text records, without dates or revision IDs |
|
|
20
|
+
| Comments | Text and author in metadata; anchors, dates, threaded replies, rich formatting, and resolved state not compared |
|
|
21
|
+
| Hyperlinks | Accepted visible text in prose; label and destination in metadata, without fetching the URL |
|
|
22
|
+
| Fields/citations | Saved display text in prose; normalized instruction fingerprint and first command token in metadata; never recalculate fields or manage Zotero |
|
|
23
|
+
| Text boxes, drawings, images, embedded objects, equations | Omission warnings and placeholders for common inline constructs; no rendering, OCR, object execution, or asset-content comparison |
|
|
24
|
+
| Bold/italic, fonts, colors, other styles, pagination/layout | Not compared; always disclosed in coverage warning |
|
|
25
|
+
|
|
26
|
+
Tracked text inclusion is an **accept-insertions/omit-deletions view**, not Word's
|
|
27
|
+
complete Accept All Changes implementation. Paragraph-mark deletion, list/table
|
|
28
|
+
revisions, tracked formatting, moves expressed in unusual structures, and nesting
|
|
29
|
+
can differ from Word's result. These constructs are reported where detected;
|
|
30
|
+
review them in Word. Deleted table rows are omitted. Comment text is plain text;
|
|
31
|
+
hyperlinks/fields inside comments are not separately interpreted.
|
|
32
|
+
|
|
33
|
+
Hidden text is included and triggers a visibility warning; formatting is not used
|
|
34
|
+
to decide what Word would display. Unknown Word/XML constructs trigger conservative warnings. Extra package parts
|
|
35
|
+
are listed as unrendered; their bytes are not hashed. Some save-only parts
|
|
36
|
+
(`docProps`, settings, font tables, theme, numbering definitions) are deliberately
|
|
37
|
+
ignored. List values and layout can therefore change without a companion update.
|
|
38
|
+
Unsupported assets can change while warning text remains identical. The `partial-prose`
|
|
39
|
+
coverage marker and CLI wording apply even when there are no specific warnings.
|
|
40
|
+
No claim of a complete/unchanged document is made. This is a modest coverage report,
|
|
41
|
+
not an audit of every OOXML relationship or layout semantic.
|
|
42
|
+
|
|
43
|
+
Metadata contains only schema/view/coverage, warnings, review text/authors, link
|
|
44
|
+
destinations, and field fingerprints. Field fingerprints avoid huge Zotero JSON
|
|
45
|
+
payloads but only say a normalized code changed, not what that change means.
|
|
46
|
+
Arrays follow document traversal order; related parts and warnings sort
|
|
47
|
+
lexically. Internal part paths come from the package; no machine paths, save
|
|
48
|
+
counters, revision dates, or export timestamps are added. Hyperlink destinations
|
|
49
|
+
are retained literally and may themselves contain sensitive or local paths.
|
|
50
|
+
|
|
51
|
+
## Normalization and sentence lines
|
|
52
|
+
|
|
53
|
+
- UTF-8, LF endings, terminal newline. Unicode, punctuation, numbers, and negations
|
|
54
|
+
are retained. No stemming, case folding, Unicode composition, or spellchecking.
|
|
55
|
+
- Word run boundaries and run formatting do not introduce text boundaries.
|
|
56
|
+
- After joining runs, whitespace (including tabs and nonbreaking spaces) collapses
|
|
57
|
+
to ordinary single spaces; leading/trailing paragraph whitespace is removed.
|
|
58
|
+
Explicit Word line breaks create separate lines. XML source newlines are spaces.
|
|
59
|
+
Empty paragraphs are omitted. Thus spacing and blank-paragraph layout changes
|
|
60
|
+
are intentionally not reviewed. Nonbreaking and soft hyphen characters remain.
|
|
61
|
+
- Sentence breaks occur at `.`, `!`, or `?` followed by whitespace; closing quotes
|
|
62
|
+
or brackets stay with the sentence. A small English abbreviation list and
|
|
63
|
+
single-letter/initialism heuristic suppress common false splits. Decimals such
|
|
64
|
+
as `3.14` have no whitespace and stay intact. Question/exclamation sentences and
|
|
65
|
+
ordinary Unicode text are retained.
|
|
66
|
+
- This is English-oriented, not universal sentence detection. Unknown abbreviations
|
|
67
|
+
can split too soon; an abbreviation at sentence end can suppress a valid split.
|
|
68
|
+
CJK text without whitespace stays on one line. Citation punctuation, initials,
|
|
69
|
+
ellipses, and unusual scientific notation may need later tuning. An incorrect
|
|
70
|
+
split changes line boundaries, not the underlying words.
|
|
71
|
+
- Heading text stays on one line. Each list item starts with `-`; subsequent
|
|
72
|
+
sentences are indented. Table cells contain normal sentence/paragraph text.
|
|
73
|
+
There are no per-sentence positional IDs or automatic counters.
|
|
74
|
+
- The `.md` is optimized for the ordinary text diff, not faithful Markdown rendering:
|
|
75
|
+
literal Markdown metacharacters in Word are not escaped, and table/unsupported
|
|
76
|
+
markers can coincide with literal document text.
|
|
77
|
+
|
|
78
|
+
## Operational limits
|
|
79
|
+
|
|
80
|
+
Packages are limited to 4096 entries, 64 MiB total uncompressed, and 16 MiB per
|
|
81
|
+
part to bound memory. Large image-heavy documents may exceed these deliberately
|
|
82
|
+
conservative defaults. Duplicate ZIP entries and XML entity expansion are rejected.
|
|
83
|
+
Output/source symlink paths are rejected to avoid writing through unexpected
|
|
84
|
+
paths. Export checks source stat information before/after reading; it is not a
|
|
85
|
+
cross-process lock. Save completely before export, and rerun after a concurrent
|
|
86
|
+
save. No watcher retries or transactional multi-document snapshot is provided.
|
|
87
|
+
|
|
88
|
+
The output mapping preserves directory paths and the `.docx` extension. It does
|
|
89
|
+
not solve case-colliding filenames on case-insensitive filesystems; repositories
|
|
90
|
+
shared with Windows/macOS should avoid filenames differing only by case.
|
|
91
|
+
Git discovery requires an available working Git installation. A selected file
|
|
92
|
+
that disappears is an error; discovery treats deleted tracked files as absent and
|
|
93
|
+
reports any existing companions as orphans. Empty discovery can succeed with
|
|
94
|
+
“No DOCX documents selected”; verify the scope when that is unexpected.
|
|
95
|
+
|
|
96
|
+
## Revisit with real documents
|
|
97
|
+
|
|
98
|
+
1. Validate real Word saves on Windows/macOS and Desktop's companion diffs, including
|
|
99
|
+
save-without-editing and Zotero documents, before claiming GUI compatibility.
|
|
100
|
+
2. Tune sentence segmentation against collaborators' languages and abbreviation
|
|
101
|
+
conventions; keep fixtures for every regression.
|
|
102
|
+
3. Decide whether list values, comment anchors, field-code previews, or image hashes
|
|
103
|
+
justify more metadata. Avoid a dump of all OOXML.
|
|
104
|
+
4. Improve tracked structural revisions, note-reference validation, complex tables,
|
|
105
|
+
and relationship/path canonicalization only as actual documents require it.
|
|
106
|
+
5. Consider opt-in textconv and refresh-only watching after the primary workflow is
|
|
107
|
+
reliable. Desktop executable discovery needs its own validation.
|
|
108
|
+
6. If Word XML is wanted later, build a distinct dialect-detecting adapter. Do not
|
|
109
|
+
treat arbitrary XML as Word input. Automatic document merging stays separate.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Validate with Word and GitHub Desktop
|
|
2
|
+
|
|
3
|
+
Automated tests use generated ZIP/XML fixtures and a temporary Git repository.
|
|
4
|
+
They validate extraction and ordinary Git diffs, not Microsoft Word rendering or
|
|
5
|
+
GitHub Desktop itself. Neither Word nor Desktop was available for this validation;
|
|
6
|
+
no real document corpus was provided. Run this checklist on a copy of a document
|
|
7
|
+
you are allowed to share. Do not use the only copy of important work.
|
|
8
|
+
|
|
9
|
+
1. Put the copy in a disposable Git repository opened in Desktop. Install Pilcrow
|
|
10
|
+
in your Python environment, then export with `pilcrow export --all --root .`.
|
|
11
|
+
Read stderr and `.meta.json` warnings. Confirm headings, paragraphs, list items,
|
|
12
|
+
and table cells are understandable in `.prose.md`.
|
|
13
|
+
2. Commit the DOCX and companions in Desktop. Export again: the companions should
|
|
14
|
+
remain unchanged. Run `pilcrow check --all --root .`: expect exit 0.
|
|
15
|
+
3. Open/save/close the file in Word **without editing**. Export again. The DOCX may
|
|
16
|
+
change as a package, but ordinary prose and review metadata should stay stable.
|
|
17
|
+
Investigate any companion churn; keep a sanitized reproducible case if possible.
|
|
18
|
+
4. Change one sentence in a multi-sentence paragraph, save, and run `check`: expect
|
|
19
|
+
exit 1. Export, select the companion in Desktop Changes, and verify that only
|
|
20
|
+
the affected sentence changes. Confirm the original DOCX still opens normally.
|
|
21
|
+
5. Add a heading, a list item, a two-cell table row, a note, and a hyperlink. Export
|
|
22
|
+
and review boundaries. Change only the hyperlink URL: inspect the metadata diff.
|
|
23
|
+
6. Insert/delete text with Track Changes on, add a comment, then export. Prose
|
|
24
|
+
should include inserted text and omit deleted text. Review text/authors should
|
|
25
|
+
appear in metadata. Inspect complex tracked structures in Word directly.
|
|
26
|
+
7. Make a bold-only change and change an image. Export. No prose update is required;
|
|
27
|
+
coverage warnings should still make the limitation clear. Inspect in Word.
|
|
28
|
+
8. If using Zotero/fields, update citations/bibliography in Word before saving.
|
|
29
|
+
Confirm saved display text appears in prose and code changes can affect the
|
|
30
|
+
field fingerprints. Pilcrow does not refresh or verify the bibliography.
|
|
31
|
+
9. Commit the edited DOCX and companions together. Select the companion in Desktop
|
|
32
|
+
History and inspect the committed difference. Confirm branch/index/history
|
|
33
|
+
remain under your control.
|
|
34
|
+
10. In the disposable repository only, try two branches with changes to the same
|
|
35
|
+
document after committing `pilcrow setup` rules. Merge through your usual
|
|
36
|
+
workflow. Choose/reconcile the DOCX, regenerate companions, check, and complete
|
|
37
|
+
the merge. Never resolve Word content by editing only the companion.
|
|
38
|
+
|
|
39
|
+
Record OS, Word version, Desktop version, Python version, and sanitized symptoms
|
|
40
|
+
for failures. These manual results are needed before extending compatibility claims.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pilcrow-docx"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Readable DOCX companion diffs for ordinary Git workflows"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
dependencies = ["defusedxml>=0.7.1,<1"]
|
|
12
|
+
|
|
13
|
+
[project.scripts]
|
|
14
|
+
pilcrow = "pilcrow.cli:main"
|
|
15
|
+
|
|
16
|
+
[tool.setuptools.packages.find]
|
|
17
|
+
where = ["src"]
|