dsh-office-kit 0.4.2 → 0.4.3
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.
- package/assets/skills/excel-live-control/SKILL.md +119 -152
- package/assets/skills/excel-live-control/domain_guidance/financial_models.md +42 -58
- package/assets/skills/excel-live-control/domain_guidance/healthcare.md +36 -42
- package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +33 -34
- package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +34 -36
- package/assets/skills/excel-live-control/references/office-automation.md +127 -153
- package/assets/skills/excel-live-control/references/read_only_qna.md +40 -45
- package/assets/skills/excel-live-control/style_guidelines.md +56 -64
- package/assets/skills/excel-live-control/workflows/create_workflows.md +40 -47
- package/assets/skills/excel-live-control/workflows/edit_workflows.md +37 -45
- package/assets/skills/office-documents/SKILL.md +24 -60
- package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +5 -5
- package/assets/skills/office-documents/ooxml/comments.md +8 -8
- package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +10 -10
- package/assets/skills/office-documents/ooxml/rels_and_content_types.md +7 -7
- package/assets/skills/office-documents/ooxml/tracked_changes.md +12 -12
- package/assets/skills/office-documents/references/docx-structure.md +11 -13
- package/assets/skills/office-documents/references/template-elicitation.md +11 -13
- package/assets/skills/office-documents/references/writing-quality.md +20 -20
- package/assets/skills/office-documents/tasks/accessibility_a11y.md +16 -22
- package/assets/skills/office-documents/tasks/captions_crossrefs.md +23 -26
- package/assets/skills/office-documents/tasks/clean_tracked_changes.md +17 -22
- package/assets/skills/office-documents/tasks/comments_manage.md +9 -11
- package/assets/skills/office-documents/tasks/compare_diff.md +10 -16
- package/assets/skills/office-documents/tasks/create_edit.md +14 -16
- package/assets/skills/office-documents/tasks/equations.md +17 -28
- package/assets/skills/office-documents/tasks/fields_update.md +14 -16
- package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +19 -33
- package/assets/skills/office-documents/tasks/footnotes_endnotes.md +12 -14
- package/assets/skills/office-documents/tasks/forms_content_controls.md +16 -20
- package/assets/skills/office-documents/tasks/headings_numbering.md +17 -22
- package/assets/skills/office-documents/tasks/images_figures.md +15 -25
- package/assets/skills/office-documents/tasks/multi_doc_merge.md +13 -23
- package/assets/skills/office-documents/tasks/navigation_internal_links.md +18 -21
- package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +16 -22
- package/assets/skills/office-documents/tasks/protection_restrict_editing.md +19 -21
- package/assets/skills/office-documents/tasks/read_review.md +9 -20
- package/assets/skills/office-documents/tasks/redaction_anonymization.md +17 -18
- package/assets/skills/office-documents/tasks/sections_layout.md +16 -23
- package/assets/skills/office-documents/tasks/style_lint_normalize.md +18 -22
- package/assets/skills/office-documents/tasks/tables_spreadsheets.md +21 -31
- package/assets/skills/office-documents/tasks/templates_style_packs.md +17 -21
- package/assets/skills/office-documents/tasks/toc_workflow.md +10 -14
- package/assets/skills/office-documents/tasks/verify_render.md +11 -23
- package/assets/skills/office-documents/tasks/watermarks_background.md +11 -15
- package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +6 -6
- package/assets/skills/office-documents/troubleshooting/run_splitting.md +12 -12
- package/assets/skills/office-pdf/SKILL.md +36 -51
- package/assets/skills/office-pdf/references/form-fields.md +20 -20
- package/assets/skills/office-pdf/references/geometry.md +10 -10
- package/assets/skills/office-pdf/references/layout-quality.md +13 -13
- package/assets/skills/office-pdf/references/limits.md +12 -56
- package/assets/skills/office-pdf/tasks/annotations.md +5 -5
- package/assets/skills/office-pdf/tasks/create.md +6 -9
- package/assets/skills/office-pdf/tasks/edit-pages.md +14 -14
- package/assets/skills/office-pdf/tasks/forms.md +15 -15
- package/assets/skills/office-pdf/tasks/read.md +9 -9
- package/assets/skills/office-pdf/tasks/redact.md +18 -18
- package/assets/skills/office-pdf/tasks/stamp.md +10 -10
- package/assets/skills/office-presentations/SKILL.md +71 -91
- package/assets/skills/office-presentations/container_tools/render_slides.py +1 -1
- package/assets/skills/office-presentations/domain_guidance/finance.md +16 -16
- package/assets/skills/office-presentations/recipes/README.md +24 -35
- package/assets/skills/office-presentations/recipes/autolayout.md +12 -13
- package/assets/skills/office-presentations/recipes/connectors.md +11 -12
- package/assets/skills/office-presentations/recipes/images.md +11 -12
- package/assets/skills/office-presentations/recipes/master-and-layouts.md +18 -18
- package/assets/skills/office-presentations/recipes/native-charts.md +8 -8
- package/assets/skills/office-presentations/recipes/rich-text-runs.md +13 -13
- package/assets/skills/office-presentations/recipes/speaker-notes.md +7 -7
- package/assets/skills/office-presentations/recipes/tables.md +14 -14
- package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +9 -9
- package/assets/skills/office-presentations/recipes/theme-tokens.md +7 -8
- package/assets/skills/office-presentations/references/authoring-workflow.md +38 -43
- package/assets/skills/office-presentations/references/finalization.md +10 -12
- package/assets/skills/office-presentations/references/native-bullets.md +14 -18
- package/assets/skills/office-presentations/references/native-evidence.md +18 -32
- package/assets/skills/office-presentations/references/style-guidelines.md +27 -32
- package/assets/skills/office-presentations/references/templates.md +31 -60
- package/assets/skills/office-presentations/routing/google_slides.md +4 -4
- package/assets/skills/office-presentations/tasks/apply-annotations.md +17 -17
- package/assets/skills/office-presentations/tasks/charts-tables-notes.md +20 -23
- package/assets/skills/office-presentations/tasks/create-deck.md +19 -19
- package/assets/skills/office-presentations/tasks/edit-deck.md +14 -16
- package/assets/skills/office-presentations/tasks/inspect-and-verify.md +31 -34
- package/assets/skills/office-presentations/tasks/template-following.md +23 -28
- package/assets/skills/office-spreadsheets/SKILL.md +32 -39
- package/assets/skills/office-spreadsheets/recipes/charts.md +8 -26
- package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +9 -26
- package/assets/skills/office-spreadsheets/recipes/data-tables.md +7 -23
- package/assets/skills/office-spreadsheets/recipes/named-ranges.md +8 -21
- package/assets/skills/office-spreadsheets/recipes/number-formats.md +7 -23
- package/assets/skills/office-spreadsheets/recipes/sparklines.md +7 -20
- package/assets/skills/office-spreadsheets/references/charts.md +15 -34
- package/assets/skills/office-spreadsheets/references/domain/financial-models.md +10 -25
- package/assets/skills/office-spreadsheets/references/domain/healthcare.md +8 -19
- package/assets/skills/office-spreadsheets/references/domain/marketing.md +8 -22
- package/assets/skills/office-spreadsheets/references/domain/research.md +8 -19
- package/assets/skills/office-spreadsheets/references/formula-patterns.md +20 -50
- package/assets/skills/office-spreadsheets/references/style-guidelines.md +19 -44
- package/assets/skills/office-spreadsheets/references/workbook-structure.md +12 -35
- package/assets/skills/office-spreadsheets/routing/google-sheets.md +11 -26
- package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +10 -25
- package/assets/skills/office-spreadsheets/tasks/annotations.md +12 -30
- package/assets/skills/office-spreadsheets/tasks/create-workbook.md +5 -5
- package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +2 -2
- package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +5 -5
- package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +9 -9
- package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +10 -30
- package/assets/skills/shared/annotation-recipes.md +98 -120
- package/assets/skills/shared/common-workflow.md +70 -80
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# Accessibility
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
The accessibility tree in Word comes from structure, not appearance. Bold text announces as bold; a `Heading 1` announces as a heading and appears in the navigation pane. Alt text lives in `wp:docPr @descr`.
|
|
3
|
+
Accessibility comes from structure, not appearance: bold announces as bold, `Heading 1` announces as a heading and appears in the navigation pane. Alt text lives in `wp:docPr @descr`.
|
|
6
4
|
|
|
7
5
|
## Audit
|
|
8
6
|
|
|
@@ -10,36 +8,32 @@ The accessibility tree in Word comes from structure, not appearance. Bold text a
|
|
|
10
8
|
"<python>" "<skill>/scripts/a11y_audit.py" "<file.docx>" --out_json "<report.json>"
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
Checks
|
|
14
|
-
|
|
15
|
-
Exit code 1 means at least one finding; `--out_json` writes the same report for a larger pass.
|
|
11
|
+
Checks images without description or title, tables without a repeating header row, heading levels that jump, empty headings, link text that is only "click here", "here" or "link", and a missing core title. Exit 1 means at least one finding.
|
|
16
12
|
|
|
17
|
-
##
|
|
13
|
+
## Mechanical fixes
|
|
18
14
|
|
|
19
15
|
```bash
|
|
20
|
-
"<python>" "<skill>/scripts/a11y_audit.py" "<file.docx>"
|
|
21
|
-
--fix_image_alt from_filename --fix_table_headers first_row \
|
|
22
|
-
--out "<file-a11y.docx>"
|
|
16
|
+
"<python>" "<skill>/scripts/a11y_audit.py" "<file.docx>" --fix_image_alt from_filename --fix_table_headers first_row --out "<file-a11y.docx"
|
|
23
17
|
```
|
|
24
18
|
|
|
25
|
-
|
|
19
|
+
These are honest placeholders, not substitutes for real text.
|
|
26
20
|
|
|
27
|
-
##
|
|
21
|
+
## Judgement fixes
|
|
28
22
|
|
|
29
|
-
- **Alt text
|
|
30
|
-
- **Link text
|
|
31
|
-
- **Reading order
|
|
32
|
-
- **Colour
|
|
33
|
-
- **
|
|
23
|
+
- **Alt text** describes what the reader loses, e.g. "Bar chart: revenue by region, EMEA 4.1M ahead of APAC 3.2M". Decorative rules and dividers get an empty description.
|
|
24
|
+
- **Link text** names the destination: "Download the Q2 ledger", not "click here".
|
|
25
|
+
- **Reading order:** decorative text boxes and floating images land awkwardly; convert them to inline.
|
|
26
|
+
- **Colour alone** (red = bad) fails colour-blind readers; add a word.
|
|
27
|
+
- **Layout tables** announce as data tables; restructure them as paragraphs.
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
Longer documents also want a TOC (`tasks/toc_workflow.md`) and language tags.
|
|
36
30
|
|
|
37
31
|
## Verify
|
|
38
32
|
|
|
39
|
-
Re-run the audit to zero findings
|
|
33
|
+
Re-run the audit to zero findings and render. Heading hierarchy is visible; alt text is metadata and stays invisible; the header row must be distinct. With a screen reader available, navigate by heading.
|
|
40
34
|
|
|
41
35
|
## Pitfalls
|
|
42
36
|
|
|
43
|
-
- Alt text on a decorative image is worse than none
|
|
44
|
-
- A
|
|
45
|
-
- Images inside
|
|
37
|
+
- Alt text on a decorative image is worse than none: use an empty description plus `title` to mark it decorative.
|
|
38
|
+
- A header row is `w:tblHeader` on the row, not a bold first row.
|
|
39
|
+
- Images inside table cells still need descriptions.
|
|
@@ -1,49 +1,46 @@
|
|
|
1
|
-
# Captions and cross-references
|
|
1
|
+
# Captions and numbered cross-references
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Two parts: a caption paragraph with a `SEQ` field (`SEQ Table \* ARABIC`), and a bookmark around it that the prose reaches with a `REF` field. Without the bookmark a `REF` has nothing to point at.
|
|
3
|
+
A caption is a paragraph with a `SEQ` field (`SEQ Table \* ARABIC`) plus a bookmark; the prose reaches that bookmark with a `REF` field. Without the bookmark a `REF` has no target.
|
|
6
4
|
|
|
7
5
|
## Add captions
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
|
-
"<python>" "<skill>/scripts/captions_and_crossrefs.py" "<file.docx>" "<file-captioned.docx>"
|
|
11
|
-
--tables --figures --bookmarks --caption_text "Source: finance ledger"
|
|
8
|
+
"<python>" "<skill>/scripts/captions_and_crossrefs.py" "<file.docx>" "<file-captioned.docx>" --tables --figures --bookmarks --caption_text "Source: finance ledger"
|
|
12
9
|
```
|
|
13
10
|
|
|
14
|
-
- `--tables` adds `Table N` under each table
|
|
15
|
-
-
|
|
16
|
-
- `--bookmarks` names
|
|
17
|
-
- `--materialize` writes literal numbers
|
|
18
|
-
- `--caption_text` appends a fixed note
|
|
11
|
+
- `--tables` adds `Table N` under each table; `--figures` adds `Figure N` under each picture.
|
|
12
|
+
- Neither flag runs both.
|
|
13
|
+
- `--bookmarks` names them `tbl1`, `tbl2`, `fig1`, … — the `tblN`/`figN` pattern `insert_ref_fields.py` expects.
|
|
14
|
+
- `--materialize` writes literal numbers: for a frozen PDF export, not for a document that will change.
|
|
15
|
+
- `--caption_text` appends a fixed note.
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
Captions use the `Caption` style and stay in the same visual block as the object, so a page break cannot orphan them.
|
|
21
18
|
|
|
22
|
-
##
|
|
19
|
+
## Cross-reference
|
|
23
20
|
|
|
24
|
-
Write placeholders in
|
|
21
|
+
Write `[[REF:tbl1]]` placeholders in the prose, then:
|
|
25
22
|
|
|
26
23
|
```bash
|
|
27
|
-
"<python>" "<skill>/scripts/insert_ref_fields.py" "<file.docx>" "<file-refs.docx
|
|
24
|
+
"<python>" "<skill>/scripts/insert_ref_fields.py" "<file.docx>" "<file-refs.docx"
|
|
28
25
|
```
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
That produces a `REF tbl1 \h` field, so the number follows the table. `--pattern` accepts your own regex with the named group `bookmark`; `--prefix` prepends text such as `Table `.
|
|
31
28
|
|
|
32
|
-
If
|
|
29
|
+
If a reference should read "Table 2" rather than "2", set the REF field's `\n` behaviour off and put the label in the prose: a field cannot know whether it points at a table or a figure.
|
|
33
30
|
|
|
34
|
-
## Order
|
|
31
|
+
## Order
|
|
35
32
|
|
|
36
|
-
1. Add or restructure tables and figures.
|
|
37
|
-
2. Run `captions_and_crossrefs.py
|
|
38
|
-
3. Run `insert_ref_fields.py
|
|
39
|
-
4. Re-render
|
|
33
|
+
1. Add or restructure the tables and figures.
|
|
34
|
+
2. Run `captions_and_crossrefs.py`.
|
|
35
|
+
3. Run `insert_ref_fields.py`.
|
|
36
|
+
4. Re-render.
|
|
40
37
|
|
|
41
38
|
## Verify
|
|
42
39
|
|
|
43
|
-
`fields_report.py`: one
|
|
40
|
+
Run `fields_report.py`: one SEQ per caption, one REF per reference, and no REF with an empty result. Then render. The usual defects are a caption above its table, or a caption separated from it by a page break.
|
|
44
41
|
|
|
45
42
|
## Pitfalls
|
|
46
43
|
|
|
47
|
-
-
|
|
48
|
-
- A
|
|
49
|
-
- Bookmarks must be unique
|
|
44
|
+
- Numbering changes on field update, so two captions can claim `Table 2` until Word recalculates.
|
|
45
|
+
- A hand-typed caption number never renumbers.
|
|
46
|
+
- Bookmarks must be unique: copying a caption copies its bookmark name and breaks the reference.
|
|
@@ -1,49 +1,44 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Proposed and tracked changes
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A tracked edit is markup: an insertion wraps runs in `w:ins`, a deletion wraps `w:delText` in `w:del`, a move is `w:moveFrom`/`w:moveTo` paired by `w:name`, and a formatting change is `w:rPrChange`/`w:pPrChange`. `w:trackRevisions` in `word/settings.xml` makes Word record new edits.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Propose an edit
|
|
5
|
+
## Propose
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
|
-
"<python>" "<skill>/scripts/add_tracked_replacements.py" "<file.docx>" --out "<file-tracked.docx>"
|
|
11
|
-
--author "Review" --replace "18%=21%" --replace "flat=steady"
|
|
8
|
+
"<python>" "<skill>/scripts/add_tracked_replacements.py" "<file.docx>" --out "<file-tracked.docx>" --author "Review" --replace "18%=21%" --replace "flat=steady"
|
|
12
9
|
```
|
|
13
10
|
|
|
14
|
-
Each `--replace` is `OLD=NEW
|
|
11
|
+
Each `--replace` is `OLD=NEW`. The script splits runs at the match so only the changed characters are marked, keeps the surrounding formatting, and turns on `trackRevisions`. Quote the `--author` the reviewer should see.
|
|
15
12
|
|
|
16
|
-
Limit: one replacement per pattern per paragraph
|
|
13
|
+
Limit: one replacement per pattern per paragraph. A match split across runs is still found because the split is computed on paragraph text; reword if a paragraph repeats the phrase.
|
|
17
14
|
|
|
18
|
-
## Inspect
|
|
15
|
+
## Inspect
|
|
19
16
|
|
|
20
17
|
```bash
|
|
21
18
|
"<python>" "<skill>/scripts/accept_tracked_changes.py" "<file.docx>" --mode report
|
|
22
19
|
"<python>" "<skill>/scripts/docx_kit.py" xml "<file.docx>" word/document.xml
|
|
23
20
|
```
|
|
24
21
|
|
|
25
|
-
The report counts insertions, deletions, move pairs and format changes.
|
|
22
|
+
The report counts insertions, deletions, move pairs and format changes.
|
|
26
23
|
|
|
27
24
|
## Accept or reject
|
|
28
25
|
|
|
29
26
|
```bash
|
|
30
|
-
"<python>" "<skill>/scripts/accept_tracked_changes.py" "<file.docx>" --mode accept --out "<file-accepted.docx
|
|
31
|
-
"<python>" "<skill>/scripts/accept_tracked_changes.py" "<file.docx>" --mode reject --out "<file-rejected.docx
|
|
27
|
+
"<python>" "<skill>/scripts/accept_tracked_changes.py" "<file.docx>" --mode accept --out "<file-accepted.docx"
|
|
28
|
+
"<python>" "<skill>/scripts/accept_tracked_changes.py" "<file.docx>" --mode reject --out "<file-rejected.docx"
|
|
32
29
|
```
|
|
33
30
|
|
|
34
|
-
Accept keeps inserted text and drops deleted text; reject
|
|
35
|
-
|
|
36
|
-
## Before delivery
|
|
31
|
+
Accept keeps inserted text and drops deleted text; reject reverses that and restores `w:delText` as ordinary text. Format-only changes are discarded either way. `--keep_tracking_on` leaves `trackRevisions` enabled.
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
Before delivery: rendered pages contain no markup, so a file can look finished while carrying redlines. Always run `--mode report` on a file about to be sent, then accept or reject explicitly.
|
|
39
34
|
|
|
40
35
|
## Verify
|
|
41
36
|
|
|
42
|
-
After accepting, `docx_kit.py text`
|
|
37
|
+
After accepting, `docx_kit.py text` shows the new wording and `word/document.xml` contains no `w:ins`/`w:del`. Render the affected page.
|
|
43
38
|
|
|
44
39
|
## Pitfalls
|
|
45
40
|
|
|
46
|
-
- `w:del` contains `w:delText`, not `w:t`;
|
|
47
|
-
- Tables, headers and footnotes can each carry
|
|
48
|
-
- Accepting a move pair
|
|
49
|
-
- Comments are not tracked changes
|
|
41
|
+
- `w:del` contains `w:delText`, not `w:t`; extraction that reads only `w:t` loses deletions.
|
|
42
|
+
- Tables, headers and footnotes can each carry tracked changes. The script covers every text part; a hand edit can miss one.
|
|
43
|
+
- Accepting a move pair as two unrelated edits duplicates content. The script treats them as a pair.
|
|
44
|
+
- Comments are not tracked changes; see `comments_manage.md`.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# Comments
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Comments are not text: each one is a `w:comment` in `word/comments.xml`, anchored in the body by a `w:commentRangeStart` / `w:commentRangeEnd` pair plus a `w:commentReference` run. Editing the anchor without the comments part (or the reverse) leaves a document Word reports as corrupt.
|
|
3
|
+
Add, read, reply to, resolve or remove review comments. A comment is not text: each is a `w:comment` in `word/comments.xml`, anchored by a `w:commentRangeStart` / `w:commentRangeEnd` pair plus a `w:commentReference` run. Editing the anchor without the comments part, or the reverse, leaves a file Word reports as corrupt.
|
|
6
4
|
|
|
7
5
|
## Add
|
|
8
6
|
|
|
@@ -11,7 +9,7 @@ Comments are not text: each one is a `w:comment` in `word/comments.xml`, anchore
|
|
|
11
9
|
--author "Review" --add "Renewals=Check the source of this claim" --add "42 new accounts=Who verified this?"
|
|
12
10
|
```
|
|
13
11
|
|
|
14
|
-
Each `--add` is `NEEDLE=COMMENT
|
|
12
|
+
Each `--add` is `NEEDLE=COMMENT`, matched inside a paragraph; the anchored range covers exactly the matched text, so pick a distinctive phrase. `--ignore_case` relaxes matching; `--require_all` writes nothing and exits 1 if any needle is missing — for comment sets that must be complete.
|
|
15
13
|
|
|
16
14
|
## Extract
|
|
17
15
|
|
|
@@ -19,7 +17,7 @@ Each `--add` is `NEEDLE=COMMENT`. The needle is matched inside a paragraph; the
|
|
|
19
17
|
"<python>" "<skill>/scripts/comments_extract.py" "<file.docx>" --out "<comments.json>"
|
|
20
18
|
```
|
|
21
19
|
|
|
22
|
-
Returns `id`, `author`, `initials`, `date`, `text`, `anchored_text`, `part` and `resolved`. An empty array means the file has no comments
|
|
20
|
+
Returns `id`, `author`, `initials`, `date`, `text`, `anchored_text`, `part` and `resolved`. An empty array means the file has no comments; do not assume they exist because the user mentioned them.
|
|
23
21
|
|
|
24
22
|
## Patch or resolve
|
|
25
23
|
|
|
@@ -45,15 +43,15 @@ Returns `id`, `author`, `initials`, `date`, `text`, `anchored_text`, `part` and
|
|
|
45
43
|
"<python>" "<skill>/scripts/comments_strip.py" "<file.docx>" --out "<file-clean.docx>"
|
|
46
44
|
```
|
|
47
45
|
|
|
48
|
-
Removes every anchor
|
|
46
|
+
Removes every anchor and drops `word/comments.xml` with its relationship and content-type override. Required before sharing a file with a customer; see also `privacy_scrub_metadata.md`.
|
|
49
47
|
|
|
50
48
|
## Verify
|
|
51
49
|
|
|
52
|
-
`comments_extract.py` on the output (count and anchors), then render the page the comment sat on
|
|
50
|
+
`comments_extract.py` on the output (count and anchors), then render the page the comment sat on: a stripped anchor that leaves an empty run can show as a stray space.
|
|
53
51
|
|
|
54
52
|
## Pitfalls
|
|
55
53
|
|
|
56
|
-
- A comment anchored to a paragraph mark rather than text shows no `anchored_text
|
|
57
|
-
- Two comments cannot share an id
|
|
58
|
-
- The
|
|
59
|
-
-
|
|
54
|
+
- A comment anchored to a paragraph mark rather than to text shows no `anchored_text` — normal for "comment on the whole paragraph".
|
|
55
|
+
- Two comments cannot share an id; `comments_add.py` continues from the highest existing id.
|
|
56
|
+
- The body is ordinary paragraphs, so a long comment can hold several; `comments_extract.py` joins them with newlines.
|
|
57
|
+
- Threaded replies need Word's `commentsExtended` part; anchoring a new comment on the same phrase is the portable equivalent.
|
|
@@ -1,40 +1,34 @@
|
|
|
1
1
|
# Compare two versions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Two comparisons answer different questions: text-level (which words changed) and page-level (what the reader sees). A style-definition change can leave every word identical and move every paragraph.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Page-level diff
|
|
5
|
+
## Page-level
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
"<python>" "<skill>/scripts/render_and_diff.py" "<before.docx>" "<after.docx>" --outdir "<render-dir>" --dpi 120
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
Renders both through the helper CLI, pairs
|
|
14
|
-
|
|
15
|
-
The exit code is 3 when no renderer is available: render both files another way, or compare text only and say which comparison you could not run.
|
|
11
|
+
Renders both files through the helper CLI, pairs pages, writes `diff-NN.png` coloured by pixel difference, and reports changed pages, the fraction of differing pixels and the page-count delta. Exit code 3 means no renderer: render another way, or compare text only and say which comparison you could not run.
|
|
16
12
|
|
|
17
|
-
## Text-level
|
|
13
|
+
## Text-level
|
|
18
14
|
|
|
19
15
|
```bash
|
|
20
16
|
"<python>" "<skill>/scripts/docx_kit.py" text '<before.docx>' > before.json
|
|
21
17
|
"<python>" "<skill>/scripts/docx_kit.py" text '<after.docx>' > after.json
|
|
22
18
|
```
|
|
23
19
|
|
|
24
|
-
|
|
20
|
+
Then diff the paragraph dumps with any diff tool or a few lines of Python. This is the reliable way to separate content from layout changes.
|
|
25
21
|
|
|
26
22
|
## Review mode versus diff mode
|
|
27
23
|
|
|
28
|
-
If the
|
|
29
|
-
|
|
30
|
-
For a version that arrived with markup, `accept_tracked_changes.py --mode report` is the change list, with reviewer names and where each edit sits.
|
|
24
|
+
If the document should carry the changes, use tracked changes (`tasks/clean_tracked_changes.md`): a diff is evidence for a conversation, tracked changes are the artefact. For a version that arrived with markup, `accept_tracked_changes.py --mode report` is the change list with reviewer names and positions.
|
|
31
25
|
|
|
32
26
|
## Verify
|
|
33
27
|
|
|
34
|
-
Open the diff PNGs with `read_image
|
|
28
|
+
Open the diff PNGs with `read_image`. A coloured block on a page that should not change usually means font substitution or a margin change — cross-check the text diff before concluding.
|
|
35
29
|
|
|
36
30
|
## Pitfalls
|
|
37
31
|
|
|
38
|
-
- Different renderers paginate differently; compare
|
|
39
|
-
- Metadata and revision ids differ between saves and never appear on a page
|
|
40
|
-
- An image replaced in place keeps
|
|
32
|
+
- Different renderers paginate differently; compare with the same renderer and settings.
|
|
33
|
+
- Metadata and revision ids differ between saves and never appear on a page, so a raw `word/document.xml` diff is mostly noise.
|
|
34
|
+
- An image replaced in place keeps its relationship and position — only a pixel comparison notices.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Create or edit a document
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Produce a `.docx` that opens cleanly in Word with real heading styles, lists and tables — and change it later without destroying what is there.
|
|
4
4
|
|
|
5
5
|
## Create
|
|
6
6
|
|
|
@@ -35,7 +35,7 @@ The command prints counts for headings, paragraphs, list items, tables, images a
|
|
|
35
35
|
|
|
36
36
|
## Edit
|
|
37
37
|
|
|
38
|
-
The helper CLI
|
|
38
|
+
The helper CLI never mutates a document: every edit reads the original, writes a copy, and refuses to overwrite its input. Without `--out` the copy lands next to the source as `<name>-edited.docx`.
|
|
39
39
|
|
|
40
40
|
Replace text — body, tables, and every header and footer:
|
|
41
41
|
|
|
@@ -44,7 +44,7 @@ Replace text — body, tables, and every header and footer:
|
|
|
44
44
|
--find "18%" --replace "21%" --find "Hardware flat" --replace "Hardware steady"
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
`--find` / `--replace`
|
|
47
|
+
`--find` / `--replace` pair up in order; `--spec edits.json` takes `{"replace": [{"find": "...", "replace": "..."}]}` instead. The command prints a count per pair. A match inside one run keeps that run's formatting; a match straddling runs collapses the paragraph into its first run, so keep needles inside a single styled span when formatting matters. `--require-all` exits 1 if a pair matched nothing — the check for a scripted edit.
|
|
48
48
|
|
|
49
49
|
Append blocks — the same block types `docx create` accepts:
|
|
50
50
|
|
|
@@ -56,26 +56,24 @@ Append blocks — the same block types `docx create` accepts:
|
|
|
56
56
|
[{ "type": "heading", "level": 1, "text": "Appendix" }, { "type": "table", "headers": ["Region", "Revenue"], "rows": [["EMEA", "4.1M"]] }]
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
`--spec` takes a full document spec and appends its `blocks` array. The builder is the CLI's own, so anything that works in `docx create` works here,
|
|
59
|
+
`--spec` takes a full document spec and appends its `blocks` array. The builder is the CLI's own, so anything that works in `docx create` works here, images (`path`, `width`) and equations (`latex`) included.
|
|
60
60
|
|
|
61
61
|
Set properties:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
"<python>" "<skill>/scripts/core_properties.py" --input "<original.docx>" --out "<original-edited.docx
|
|
64
|
+
"<python>" "<skill>/scripts/core_properties.py" --input "<original.docx>" --out "<original-edited.docx" \
|
|
65
65
|
--title "Regional revenue review (final)" --author "Finance" --keywords "revenue, FY26"
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
`--show` reports the current properties without writing; the same names work in `--spec core.json` under a `core` object.
|
|
69
|
-
|
|
70
|
-
Three independent scripts means a pipeline writes an intermediate copy (append, then properties). That is deliberate: each step is re-runnable and its output is a valid document you can inspect.
|
|
68
|
+
`--show` reports the current properties without writing; the same names work in `--spec core.json` under a `core` object. Each step writes a valid document, so a pipeline is append, then properties, and every stage is re-runnable and inspectable.
|
|
71
69
|
|
|
72
70
|
## When the CLI is not enough
|
|
73
71
|
|
|
74
72
|
| Need | Route |
|
|
75
73
|
|---|---|
|
|
76
|
-
| Edit inside a header, footer, footnote or comment | `
|
|
77
|
-
| Mark edits as tracked changes | `
|
|
78
|
-
| Header date, footer page numbers, first hyperlink | `
|
|
74
|
+
| Edit inside a header, footer, footnote or comment | `docx_kit.py xml <file> <part>` to inspect, then the snippet below |
|
|
75
|
+
| Mark edits as tracked changes | `add_tracked_replacements.py` (`tasks/clean_tracked_changes.md`) |
|
|
76
|
+
| Header date, footer page numbers, first hyperlink | `docx_ooxml_patch.py` |
|
|
79
77
|
| Replace a paragraph but keep its formatting | `python-docx` snippet below |
|
|
80
78
|
|
|
81
79
|
```bash
|
|
@@ -93,15 +91,15 @@ d.save(r"<file-edited.docx>")
|
|
|
93
91
|
PY
|
|
94
92
|
```
|
|
95
93
|
|
|
96
|
-
|
|
94
|
+
Plain word swaps can edit `w:t` through `docx_kit` directly; anything that changes paragraph structure goes through `python-docx` so the surrounding XML stays consistent.
|
|
97
95
|
|
|
98
96
|
## Verify
|
|
99
97
|
|
|
100
|
-
`docx read` to confirm text and counts, then render
|
|
98
|
+
`docx read` to confirm text and counts, then render every page (`tasks/verify_render.md`). A spec that produces three pages instead of two means the table or margins need work, not that the renderer is wrong.
|
|
101
99
|
|
|
102
100
|
## Pitfalls
|
|
103
101
|
|
|
104
|
-
- Deleting and retyping a heading loses its outline level; edit the text
|
|
102
|
+
- Deleting and retyping a heading loses its outline level; edit the text and keep the style.
|
|
105
103
|
- `append_blocks.py` inserts before the final section properties, so a trailing landscape section or page setup keeps working.
|
|
106
|
-
- Replacing text
|
|
107
|
-
- Copying content between documents by hand drops styles and relationships — use `
|
|
104
|
+
- Replacing text in a field result changes only the cached value; the field recalculates on open in Word.
|
|
105
|
+
- Copying content between documents by hand drops styles and relationships — use `merge_docx_append.py`.
|
|
@@ -1,59 +1,48 @@
|
|
|
1
1
|
# Equations
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Word stores native equations as OMML inside `m:oMathPara`/`m:oMath`. The helper CLI converts LaTeX to OMML on creation; a picture of an equation cannot be edited by the user and scales badly.
|
|
3
|
+
Word stores native equations as OMML inside `m:oMathPara`/`m:oMath`. The CLI converts LaTeX to OMML on creation. A picture of an equation cannot be edited and scales badly.
|
|
6
4
|
|
|
7
5
|
## Create
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
"<python>" "<cli>" docx create --spec "<spec.json>" --out "<out.docx>"
|
|
11
|
-
```
|
|
7
|
+
`docx create --spec` block:
|
|
12
8
|
|
|
13
9
|
```json
|
|
14
|
-
{
|
|
15
|
-
"blocks": [
|
|
16
|
-
{ "type": "heading", "level": 1, "text": "Model" },
|
|
17
|
-
{ "type": "equation", "latex": "E = mc^2" },
|
|
18
|
-
{ "type": "equation", "latex": "\\frac{a^2+b^2}{c^2}" }
|
|
19
|
-
]
|
|
20
|
-
}
|
|
10
|
+
{ "type": "equation", "latex": "\\frac{a^2+b^2}{c^2}" }
|
|
21
11
|
```
|
|
22
12
|
|
|
23
|
-
The command reports `equations` and `equation_fallbacks`.
|
|
13
|
+
Supported: fractions, superscripts, subscripts, roots, sums, Greek letters and common operators. The command reports `equations` and `equation_fallbacks`. A non-zero `equation_fallbacks` means the expression was emitted as italic text: check the counter, then simplify the LaTeX.
|
|
24
14
|
|
|
25
|
-
Displayed equations belong in their own paragraph
|
|
15
|
+
Displayed equations belong in their own paragraph. Inline maths is ordinary runs plus OMML, harder to place and easy to break.
|
|
26
16
|
|
|
27
|
-
## Check
|
|
17
|
+
## Check the contents
|
|
28
18
|
|
|
29
19
|
```bash
|
|
30
20
|
"<python>" "<cli>" docx read --input "<file.docx>"
|
|
31
21
|
"<python>" "<skill>/scripts/docx_kit.py" xml '<file.docx>' word/document.xml | grep -c "oMath"
|
|
32
22
|
```
|
|
33
23
|
|
|
34
|
-
`oMath` in the XML is the honest test
|
|
24
|
+
`oMath` in the XML is the honest test; lookalike italic Times text is not an equation.
|
|
35
25
|
|
|
36
26
|
## When the converter cannot express it
|
|
37
27
|
|
|
38
|
-
Build the OMML by hand for
|
|
28
|
+
- Build the OMML by hand for that construct.
|
|
29
|
+
- Split the expression: a matrix or piecewise definition is often clearer as a small table.
|
|
30
|
+
- Otherwise render it as an image with a caption and tell the user it is no longer editable.
|
|
39
31
|
|
|
40
|
-
The runtime ships
|
|
32
|
+
The runtime ships `latex2mathml` and `mathml2omml`, so a custom snippet can produce OMML:
|
|
41
33
|
|
|
42
|
-
```
|
|
43
|
-
"<python>" - <<'PY'
|
|
34
|
+
```python
|
|
44
35
|
from latex2mathml.converter import convert
|
|
45
36
|
from mathml2omml import convert as to_omml
|
|
46
|
-
|
|
47
|
-
print(to_omml(mathml)[:200])
|
|
48
|
-
PY
|
|
37
|
+
print(convert(r"\sum_{i=1}^{n} x_i")[:200])
|
|
49
38
|
```
|
|
50
39
|
|
|
51
40
|
## Verify
|
|
52
41
|
|
|
53
|
-
Render
|
|
42
|
+
Render: fractions stacked, limits above and below, Greek glyphs instead of boxes, nothing clipped at the right margin. A fallback shows as italic Latin text.
|
|
54
43
|
|
|
55
44
|
## Pitfalls
|
|
56
45
|
|
|
57
|
-
- An equation
|
|
58
|
-
- Copying OMML between documents is safe; copying a picture
|
|
59
|
-
- Numeric labels belong in the text (`(3)` right-aligned)
|
|
46
|
+
- An equation in a table cell or caption is legal but usually wrong.
|
|
47
|
+
- Copying OMML between documents is safe; copying a picture is not.
|
|
48
|
+
- Numeric labels belong in the text (`(3)` right-aligned) if the user will renumber.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Update or freeze fields
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
A field is an instruction the reader's Word evaluates: `SEQ` numbers captions, `REF` repeats a bookmark, `PAGE`/`NUMPAGES` count pages, `TOC` builds the contents list, `DATE` prints today. Until Word recalculates it, the file shows a cached result — which is why a TOC in a freshly edited file can look stale.
|
|
3
|
+
A field is an instruction Word evaluates: `SEQ` numbers captions, `REF` repeats a bookmark, `PAGE`/`NUMPAGES` count pages, `TOC` builds contents, `DATE` prints today. The reader sees a cached result until something recalculates.
|
|
6
4
|
|
|
7
5
|
## Inspect
|
|
8
6
|
|
|
@@ -10,35 +8,35 @@ A field is an instruction the reader's Word evaluates: `SEQ` numbers captions, `
|
|
|
10
8
|
"<python>" "<skill>/scripts/fields_report.py" "<file.docx>" --max-examples 5
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
The report gives each instruction, whether the field is simple (`w:fldSimple`, one attribute) or complex (begin/separate/end runs), and the cached result. To read the raw runs yourself, dump `docx_kit.py xml` for `word/document.xml` and filter `instrText`:
|
|
14
12
|
|
|
15
13
|
```bash
|
|
16
14
|
"<python>" "<skill>/scripts/docx_kit.py" xml '<file.docx>' word/document.xml | grep -o 'instrText[^<]*' | head
|
|
17
15
|
```
|
|
18
16
|
|
|
19
|
-
## Freeze
|
|
17
|
+
## Freeze
|
|
20
18
|
|
|
21
19
|
```bash
|
|
22
20
|
"<python>" "<skill>/scripts/fields_materialize.py" "<file.docx>" --out "<file-static.docx>" --only SEQ REF
|
|
23
|
-
"<python>" "<skill>/scripts/flatten_ref_fields.py" "<file.docx>" --out "<file-static.docx
|
|
21
|
+
"<python>" "<skill>/scripts/flatten_ref_fields.py" "<file.docx>" --out "<file-static.docx"
|
|
24
22
|
```
|
|
25
23
|
|
|
26
|
-
Materialising replaces the field span with one run holding the cached text
|
|
24
|
+
Materialising replaces the field span with one run holding the cached text and keeps the run formatting. `flatten_ref_fields.py` is the narrower tool for `REF`/`PAGEREF` only.
|
|
25
|
+
|
|
26
|
+
Freeze when a reader must see exactly this number, when the target bookmark is about to be deleted, or when a downstream tool mangles fields. Keep fields live when the document will be edited again: a frozen caption number stops following its table.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
## Keep fields live
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Set `w:updateFields val="true"` in `word/settings.xml`; `insert_toc.py` does it for a new TOC, and you add the element yourself otherwise — the first open then prompts the user. LibreOffice and the renderer also refresh fields, so a stale cached value usually means the document was never recalculated, not that fields are broken.
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
- LibreOffice and the renderer also refresh fields; a stale cached value in a preview usually means the field was never recalculated, not that the field is broken.
|
|
34
|
-
- `insert_ref_fields.py` converts `[[REF:bookmark]]` placeholders into real `REF` fields, which is the reliable way to build cross-references after restructuring.
|
|
32
|
+
`insert_ref_fields.py` converts `[[REF:bookmark]]` placeholders into real REF fields — the reliable way to build cross-references after a restructure.
|
|
35
33
|
|
|
36
34
|
## Verify
|
|
37
35
|
|
|
38
|
-
`fields_report.py`
|
|
36
|
+
Run `fields_report.py` again: frozen fields disappear from the report, live ones keep their instruction. Then render or read the page.
|
|
39
37
|
|
|
40
38
|
## Pitfalls
|
|
41
39
|
|
|
42
40
|
- A field split across paragraphs is invalid; keep begin/separate/end together.
|
|
43
|
-
- `w:fldSimple` and complex fields
|
|
44
|
-
- Copying a field
|
|
41
|
+
- Both `w:fldSimple` and complex fields appear in the report; handle both.
|
|
42
|
+
- Copying a field copies the instruction but not its bookmark.
|