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,77 +1,39 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Create, read, edit, render, and verify Word documents (.docx) — build new files, revise existing ones, and check the rendered pages.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Documents (.docx)
|
|
6
6
|
|
|
7
|
-
A `.docx` is a zip of XML parts: `word/document.xml` holds the body,
|
|
8
|
-
|
|
9
|
-
- **Fast path** — the helper CLI inspects, renders and creates: `docx create`, `docx read`, `docx render`. It performs no in-place mutation.
|
|
10
|
-
- **Structural path** — `scripts/*.py` in this skill do all editing: replace text, append blocks, set properties, and everything structural — comments, tracked changes, fields, protection, watermarks.
|
|
11
|
-
|
|
12
|
-
Pick the cheapest route that produces the structure the user asked for, then verify it visually. Never invent content, and never deliver a file you have not looked at.
|
|
7
|
+
A `.docx` is a zip of XML parts: `word/document.xml` holds the body, with headers, footers, footnotes, comments, styles and numbering beside it. Two routes reach them: the helper CLI (`docx create`, `docx read`, `docx render`, no in-place mutation) and `scripts/*.py`, which edits everything structural — text, blocks, properties, comments, tracked changes, fields, protection, watermarks. Pick the cheapest route that yields the requested structure, then look at the pages. Never invent content; never deliver a file you have not looked at.
|
|
13
8
|
|
|
14
9
|
## Before any file work
|
|
15
10
|
|
|
16
|
-
|
|
17
|
-
2. Read the `## Office runtime` block at the end of this file for the verified `python`, `cli`, `skill` and `shared` paths.
|
|
18
|
-
3. If that block says no runtime is available, stop and give the user the `node "..."` remedy command it names, then call `office_status` again. Do not fake a document or claim success.
|
|
19
|
-
|
|
20
|
-
Quote every path. Spaces, non-ASCII names and `&` are normal on Windows.
|
|
11
|
+
Call `office_status`, then read the `## Office runtime` block at the end of this file — it holds the verified `python`, `cli`, `skill` and `shared` paths for this install. If there is no runtime, stop, give the user the `node "..."` remedy command, and call `office_status` again — never fake a document or claim success. Quote every path: spaces, non-ASCII names and `&` are normal on Windows.
|
|
21
12
|
|
|
22
13
|
## Delivery
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- Creating a file: write it into the user's workspace, verify it, then `present`.
|
|
27
|
-
- Editing an existing file: never overwrite the original. Write `<original>-edited.<ext>` (or a name the user asked for), verify it, `present` it, and state both paths.
|
|
15
|
+
Deliver with `present` plus a one-sentence summary. A bare path is not delivery: the transcript renders `.docx`/`.pptx`/`.xlsx`/`.pdf` links as "二进制文件,无法显示改动". Write new files into the workspace, verify, `present`. Never overwrite an original — write `<original>-edited.<ext>` (or the user's name), verify, `present`, and state both paths.
|
|
28
16
|
|
|
29
17
|
## Annotations
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
When the payload cannot be mapped to a concrete object (the region is empty or the file has no geometry), do not guess silently — say what you could not locate.
|
|
34
|
-
|
|
35
|
-
For `.docx`, `page` is the page of the *rendered PDF preview*, not a Word page. Use `text` (and the paragraph text near it) to locate the target; the region is a hint for near-misses only. A region that lands on a table row, a caption or a header is ambiguous — state which object you picked before editing.
|
|
19
|
+
An `office-annotations` payload is `[{ page, text, requirement, region: { left, top, width, height } }]`: `region` normalised 0–1 against the rendered preview page, `requirement` free-form. Treat it as a change request, not editor state — find what the region covers, apply the smallest edit that satisfies `requirement`, re-render, confirm. Unmappable payload (empty region, no geometry): say what you could not locate; never guess. For `.docx`, `page` is a rendered PDF page, not a Word page: locate by `text` and its neighbouring paragraphs, use the region only for near-misses, and name the object you picked when a region lands on a table row, caption or header.
|
|
36
20
|
|
|
37
21
|
## Verify
|
|
38
22
|
|
|
39
|
-
Rendering is the only proof that a document looks right.
|
|
40
|
-
|
|
41
23
|
```bash
|
|
42
24
|
"<python>" "<cli>" docx render --input "<file.docx>" --out-dir "<render-dir>"
|
|
43
25
|
```
|
|
44
26
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- Iterate until the pages look correct, then deliver. "It parses" is not verification.
|
|
48
|
-
- If the runtime reports no renderer (`renderers.can_render.docx: false` — the DSH LibreOffice kit is missing), ask the user to fix the install, or fall back to `docx read` plus the audit scripts. Say plainly that layout was not visually verified — do not describe a page you did not see.
|
|
49
|
-
- After a script edits XML, re-render. A package can stay valid while the page it produces is broken.
|
|
50
|
-
|
|
51
|
-
## Choosing a route
|
|
52
|
-
|
|
53
|
-
| Job | Fast path | Structural path |
|
|
54
|
-
|---|---|---|
|
|
55
|
-
| New document from scratch | `docx create --spec` | `python-docx` snippet in `tasks/create_edit.md` |
|
|
56
|
-
| Replace or append text and blocks | — | `scripts/replace_text.py`, `scripts/append_blocks.py` |
|
|
57
|
-
| Document properties | — | `scripts/core_properties.py` |
|
|
58
|
-
| Read structure | `docx read` | `scripts/docx_kit.py text`, `style_lint`, audits |
|
|
59
|
-
| Comments, tracked changes | — | `scripts/comments_*.py`, `scripts/*tracked*.py` |
|
|
60
|
-
| Fields, TOC, cross-references | — | `scripts/insert_toc.py`, `insert_ref_fields.py`, `fields_*.py` |
|
|
61
|
-
| Footnotes, endnotes | — | `scripts/insert_note.py`, `footnotes_report.py` |
|
|
62
|
-
| Tables, layout geometry | `docx create` table block | `scripts/table_geometry.py`, `docx_table_to_csv.py` |
|
|
63
|
-
| Styles, templates | — | `scripts/style_*.py`, `apply_template_styles.py` |
|
|
64
|
-
| Protection, watermarks, privacy | — | `scripts/set_protection.py`, `watermark_*.py`, `privacy_scrub.py`, `redact_docx.py` |
|
|
65
|
-
|
|
66
|
-
Where no verb exists, the fallback is the listed script or a short `python-docx`/`lxml` snippet. Both are runnable with the runtime `python`; neither needs a new dependency.
|
|
27
|
+
Writes a PDF and one PNG per page and prints the paths. Open each PNG with `read_image`; check heading hierarchy, table width and cell wrapping, page breaks, header/footer, clipped or overflowing text, missing glyphs (dashes, CJK, symbols), equations, caption placement. Iterate, then deliver — "it parses" is not verification. Without a renderer (`office_status` reports `renderers.available: false`, with a `remedy`) ask the user to fix the install or fall back to `docx read` plus the audit scripts; say layout was not visually verified and never describe an unseen page. Re-render after every script edit: a package can be valid while its page is broken. Details: `tasks/verify_render.md`. Setup: `troubleshooting/libreoffice_headless.md`.
|
|
67
28
|
|
|
68
29
|
## Task index
|
|
69
30
|
|
|
70
|
-
|
|
|
31
|
+
| Job | Task doc | CLI or main tool |
|
|
71
32
|
|---|---|---|
|
|
72
|
-
| Create
|
|
73
|
-
| Read and review a file | `tasks/read_review.md` |
|
|
74
|
-
|
|
|
33
|
+
| Create a document | `tasks/create_edit.md` | `docx create --spec`, `python-docx` snippet, `append_blocks.py` |
|
|
34
|
+
| Read and review a file | `tasks/read_review.md` | `docx read`, `docx_kit.py text`, `style_lint`, audits |
|
|
35
|
+
| Edit text, blocks or properties | `tasks/create_edit.md` | `replace_text.py`, `append_blocks.py`, `core_properties.py` |
|
|
36
|
+
| Comments | `tasks/comments_manage.md` | `comments_*.py` |
|
|
75
37
|
| Tracked changes | `tasks/clean_tracked_changes.md` | `accept_tracked_changes.py`, `add_tracked_replacements.py` |
|
|
76
38
|
| Fields and updates | `tasks/fields_update.md` | `fields_report.py`, `fields_materialize.py` |
|
|
77
39
|
| Table of contents | `tasks/toc_workflow.md` | `insert_toc.py`, `fields_*.py` |
|
|
@@ -79,7 +41,7 @@ Where no verb exists, the fallback is the listed script or a short `python-docx`
|
|
|
79
41
|
| Navigation links | `tasks/navigation_internal_links.md` | `internal_nav.py` |
|
|
80
42
|
| Footnotes and endnotes | `tasks/footnotes_endnotes.md` | `insert_note.py`, `footnotes_report.py` |
|
|
81
43
|
| Headings and numbering | `tasks/headings_numbering.md` | `heading_audit.py` |
|
|
82
|
-
| Tables | `tasks/tables_spreadsheets.md` | `table_geometry.py`, `docx_table_to_csv.py`, `xlsx_to_docx_table.py` |
|
|
44
|
+
| Tables and geometry | `tasks/tables_spreadsheets.md` | `docx create` table block, `table_geometry.py`, `docx_table_to_csv.py`, `xlsx_to_docx_table.py` |
|
|
83
45
|
| Images and figures | `tasks/images_figures.md` | `images_audit.py` |
|
|
84
46
|
| Sections and page setup | `tasks/sections_layout.md` | `section_audit.py` |
|
|
85
47
|
| Styles | `tasks/style_lint_normalize.md` | `style_lint.py`, `style_normalize.py` |
|
|
@@ -91,24 +53,26 @@ Where no verb exists, the fallback is the listed script or a short `python-docx`
|
|
|
91
53
|
| Privacy and metadata | `tasks/privacy_scrub_metadata.md` | `privacy_scrub.py` |
|
|
92
54
|
| Redaction | `tasks/redaction_anonymization.md` | `redact_docx.py` |
|
|
93
55
|
| Merging documents | `tasks/multi_doc_merge.md` | `merge_docx_append.py` |
|
|
94
|
-
| Comparing versions | `tasks/compare_diff.md` | `render_and_diff.py` |
|
|
95
|
-
| Equations | `tasks/equations.md` |
|
|
96
|
-
| Visual verification | `tasks/verify_render.md` | `render_docx.py` (skill root) |
|
|
56
|
+
| Comparing versions | `tasks/compare_diff.md` | `docx render`, `render_and_diff.py` |
|
|
57
|
+
| Equations | `tasks/equations.md` | `docx create` `equation` block |
|
|
58
|
+
| Visual verification | `tasks/verify_render.md` | `docx render`, `render_docx.py` (skill root) |
|
|
97
59
|
| Fixtures and edge cases | `tasks/fixtures_edge_cases.md` | `make_fixtures.py` |
|
|
98
60
|
|
|
61
|
+
Where no verb exists, use the listed script or a short `python-docx`/`lxml` snippet — both run on the runtime `python` without a new dependency.
|
|
62
|
+
|
|
99
63
|
## Document defaults
|
|
100
64
|
|
|
101
65
|
- Letter 8.5×11 portrait (A4 when the user or template says so), 1in margins, body 11–12pt, single column.
|
|
102
|
-
- Black headings and body
|
|
103
|
-
- Tables:
|
|
104
|
-
- No
|
|
105
|
-
- Captions
|
|
106
|
-
- Prefer native
|
|
66
|
+
- Black headings and body; colour only for deliberate emphasis, links and chart series.
|
|
67
|
+
- Tables: `#D9D9D9` borders, bold header row, `w:tblHeader` repeat, no vertical merges in wide tables.
|
|
68
|
+
- No callout boxes, drop shadows or coloured sidebars — structure comes from headings, lists and tables.
|
|
69
|
+
- Captions under figures and above tables, `Caption` style, staying with the object.
|
|
70
|
+
- Prefer native headings, lists, tables and OMML equations over hand-positioned runs: the next edit depends on that structure.
|
|
107
71
|
|
|
108
72
|
## Writing quality
|
|
109
73
|
|
|
110
|
-
|
|
74
|
+
Plain sentences, no filler. Checklist `references/writing-quality.md`; package parts `references/docx-structure.md`.
|
|
111
75
|
|
|
112
76
|
## Shared workflow
|
|
113
77
|
|
|
114
|
-
Cross-format habits
|
|
78
|
+
Cross-format habits and annotation payloads: `"<shared>/common-workflow.md"`, `"<shared>/annotation-recipes.md"`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# End-to-end smoke test
|
|
2
2
|
|
|
3
|
-
A short job
|
|
3
|
+
A short job touching creation, inspection, structural change and verification. Run it after a runtime change, or as a template for "is this environment healthy".
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
PY="<python>"; CLI="<cli>"; S="<skill>/scripts"; R="<skill>"; W="/tmp/docx-smoke"
|
|
@@ -41,7 +41,7 @@ Expect `ok: true` and non-zero `headings`, `tables`, `equations`.
|
|
|
41
41
|
"$PY" "$S/style_lint.py" "$W/base.docx"
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Expect the sections,
|
|
44
|
+
Expect the sections, `word/document.xml` in the parts list, Letter 8.5×11 portrait, and an empty style-lint `counts`.
|
|
45
45
|
|
|
46
46
|
## 3. Change it structurally
|
|
47
47
|
|
|
@@ -63,7 +63,7 @@ Expect the sections, the parts list to include `word/document.xml`, Letter 8.5×
|
|
|
63
63
|
"$PY" "$S/table_geometry.py" "$W/with-toc.docx"
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
Audits may exit 1 with findings
|
|
66
|
+
Audits may exit 1 with findings: that is a report, not an environment failure. Every finding should be explainable.
|
|
67
67
|
|
|
68
68
|
## 5. Verify visually
|
|
69
69
|
|
|
@@ -71,7 +71,7 @@ Audits may exit 1 with findings — that is a report, not a failure of the envir
|
|
|
71
71
|
"$PY" "$R/render_docx.py" "$W/with-toc.docx" --output_dir "$W/render" --dpi 150
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
Open each PNG with `read_image`. Without the DSH LibreOffice kit the command exits 3 with `no_renderer`: a setup problem, not a document problem, and the rest of the test still stands.
|
|
75
75
|
|
|
76
76
|
## 6. Deliver
|
|
77
77
|
|
|
@@ -83,4 +83,4 @@ Copy the final file into the user's workspace, `present` it, and state what chan
|
|
|
83
83
|
rm -rf "$W"
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
Nothing under the workspace should be left behind
|
|
86
|
+
Nothing under the workspace should be left behind by a smoke test.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Comments in the package
|
|
2
2
|
|
|
3
|
-
A comment is three pieces that must agree: `word/comments.xml` holds the content, `word/document.xml` holds a range marking which text is discussed, and
|
|
3
|
+
A comment is three pieces that must agree: `word/comments.xml` holds the content, `word/document.xml` holds a range marking which text is discussed, and a relationship plus content-type override make the part exist at all.
|
|
4
4
|
|
|
5
5
|
## The markup
|
|
6
6
|
|
|
@@ -20,21 +20,21 @@ A comment is three pieces that must agree: `word/comments.xml` holds the content
|
|
|
20
20
|
|
|
21
21
|
Rules that matter in practice:
|
|
22
22
|
|
|
23
|
-
- `w:id`
|
|
24
|
-
- The comment reference run belongs at the end of the range, not
|
|
23
|
+
- `w:id` is unique across comments **and** matches in all three places. A range start without an end leaves Word showing a comment with no anchor; an end without a start can make the file refuse to open.
|
|
24
|
+
- The comment reference run belongs at the end of the range, not elsewhere in the paragraph.
|
|
25
25
|
- `word/comments.xml` needs an override in `[Content_Types].xml` and a relationship from `word/document.xml`; without both, the part is ignored or the file is corrupt.
|
|
26
|
-
- The file
|
|
26
|
+
- The file root lists `w14`/`w15` in `mc:Ignorable`; the `w15:done` "resolved" attribute is only legal with those namespaces declared.
|
|
27
27
|
|
|
28
28
|
## Resolved versus deleted
|
|
29
29
|
|
|
30
|
-
`w15:done="1"` on
|
|
30
|
+
`w15:done="1"` on `w:comment` keeps the comment in the file and shows it as resolved. Removing it is a different operation: delete the `w:comment`, both range markers and the reference run. Resolving hides the comment from the default pane; it does not remove the text from the file.
|
|
31
31
|
|
|
32
32
|
## Where comments hide
|
|
33
33
|
|
|
34
|
-
- Replies are comments too, linked by `w15:paraIdParent`;
|
|
34
|
+
- Replies are comments too, linked by `w15:paraIdParent`; removing the parent leaves an orphan.
|
|
35
35
|
- Anchors can sit in headers, footnotes and text boxes as well as the body.
|
|
36
|
-
- A comment deleted in Word leaves no trace
|
|
36
|
+
- A comment deleted in Word leaves no trace, but a comment whose range was deleted may remain in `comments.xml` with nothing anchoring it. That is why extraction reports anchors: a comment with empty anchored text is evidence of drift.
|
|
37
37
|
|
|
38
38
|
## Working from the scripts
|
|
39
39
|
|
|
40
|
-
`comments_extract.py` reads the pairing and prints anchored text per comment; `comments_add.py` writes all three pieces; `comments_apply_patch.py` edits content and the resolved flag; `comments_strip.py` removes every trace and the part itself. Use `docx_kit.py xml '<file.docx>' word/comments.xml`
|
|
40
|
+
`comments_extract.py` reads the pairing and prints anchored text per comment; `comments_add.py` writes all three pieces; `comments_apply_patch.py` edits content and the resolved flag; `comments_strip.py` removes every trace and the part itself. Use `docx_kit.py xml '<file.docx>' word/comments.xml` for the raw part.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Hyperlinks and fields
|
|
2
2
|
|
|
3
|
-
A hyperlink and a field are both "a run that looks like text but is a pointer", and both break
|
|
3
|
+
A hyperlink and a field are both "a run that looks like text but is a pointer", and both break the same way: the visible result is cached, so editing the text updates nothing.
|
|
4
4
|
|
|
5
5
|
## Hyperlinks
|
|
6
6
|
|
|
@@ -10,11 +10,11 @@ A hyperlink and a field are both "a run that looks like text but is a pointer",
|
|
|
10
10
|
</w:hyperlink>
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
- The target is a relationship in `word/_rels/document.xml.rels
|
|
13
|
+
- The target is a relationship in `word/_rels/document.xml.rels`: `TargetMode="External"` for a URL, a bare relative path for a file inside the package.
|
|
14
14
|
- An internal link uses `w:anchor="bookmarkName"` and no relationship at all.
|
|
15
|
-
- `w:hyperlink`
|
|
15
|
+
- `w:hyperlink` wraps runs; a link spanning paragraphs is not legal — one link per paragraph.
|
|
16
16
|
|
|
17
|
-
A link whose relationship is missing renders as blue underlined text that goes nowhere.
|
|
17
|
+
A link whose relationship is missing renders as blue underlined text that goes nowhere. Copy-paste between documents produces the same thing.
|
|
18
18
|
|
|
19
19
|
## Simple fields
|
|
20
20
|
|
|
@@ -24,7 +24,7 @@ A link whose relationship is missing renders as blue underlined text that goes n
|
|
|
24
24
|
</w:fldSimple>
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
The `w:t` inside is a cache, not the truth
|
|
27
|
+
The `w:t` inside is a cache, not the truth: change the text and the next field update overwrites it.
|
|
28
28
|
|
|
29
29
|
## Complex fields
|
|
30
30
|
|
|
@@ -36,13 +36,13 @@ The `w:t` inside is a cache, not the truth. Change the text and the next field u
|
|
|
36
36
|
<w:r><w:fldChar w:fldCharType="end"/></w:r>
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
The begin/instrText/separate/result/end sequence
|
|
39
|
+
The begin/instrText/separate/result/end sequence keeps that order inside one paragraph. Word shows the result between `separate` and `end`, or recomputes on open when `settings.xml` sets:
|
|
40
40
|
|
|
41
41
|
```xml
|
|
42
42
|
<w:updateFields w:val="true"/>
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
That makes Word prompt or update on open. A viewer that ignores it (PDF export, some libraries) keeps the cache — which is why a document delivered as PDF can show "1" for every page number.
|
|
46
46
|
|
|
47
47
|
## Which field for which job
|
|
48
48
|
|
|
@@ -57,9 +57,9 @@ Setting it makes Word prompt or update on open. A viewer that ignores it (a PDF
|
|
|
57
57
|
## Editing fields safely
|
|
58
58
|
|
|
59
59
|
- To freeze a result, replace the whole field span with a plain run (`fields_materialize.py`, `flatten_ref_fields.py`).
|
|
60
|
-
- To renumber, update the cached result and leave the instruction alone;
|
|
61
|
-
- `w:instrText
|
|
62
|
-
- Bookmarks referenced by `REF` must exist (`w:bookmarkStart
|
|
60
|
+
- To renumber, update the cached result and leave the instruction alone; never delete the begin/end markers.
|
|
61
|
+
- The instruction lives in `w:instrText`, so a search-and-replace over `w:t` will not find `TOC`.
|
|
62
|
+
- Bookmarks referenced by `REF` must exist (`w:bookmarkStart` / `w:bookmarkEnd` with matching `w:id`); a missing bookmark shows "Error! Reference source not found.".
|
|
63
63
|
|
|
64
64
|
## See also
|
|
65
65
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Relationships and content types
|
|
2
2
|
|
|
3
|
-
A `.docx` is a zip of parts, and every relationship between parts is declared twice: once as a relationship entry, once as a content type. Miss either and the file
|
|
3
|
+
A `.docx` is a zip of parts, and every relationship between parts is declared twice: once as a relationship entry, once as a content type. Miss either and the file loses the feature or refuses to open.
|
|
4
4
|
|
|
5
5
|
## The two registries
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ _rels/.rels # package -> document, core props
|
|
|
10
10
|
word/_rels/document.xml.rels # document -> styles, numbering, media, header, footer, comments, hyperlinks
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
`[Content_Types].xml`
|
|
13
|
+
`[Content_Types].xml` uses `<Default Extension="xml" ContentType="..."/>` for extension defaults and `<Override PartName="/word/comments.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml"/>` for parts that do not follow an extension rule.
|
|
14
14
|
|
|
15
15
|
A relationship:
|
|
16
16
|
|
|
@@ -20,7 +20,7 @@ A relationship:
|
|
|
20
20
|
Target="comments.xml"/>
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
`Id` is scoped to the part that owns the `.rels` file, so `rId5` in the document and `rId5` in a header are unrelated. `Target` is relative to the owner directory unless
|
|
23
|
+
`Id` is scoped to the part that owns the `.rels` file, so `rId5` in the document and `rId5` in a header are unrelated. `Target` is relative to the owner directory unless absolute (`/word/media/image1.png`) or external (`TargetMode="External"`, used for hyperlinks).
|
|
24
24
|
|
|
25
25
|
## What breaks
|
|
26
26
|
|
|
@@ -32,13 +32,13 @@ A relationship:
|
|
|
32
32
|
| Broken link | Relationship removed but `r:id` left in the body |
|
|
33
33
|
| Lost image | Media copied without a new relationship id |
|
|
34
34
|
|
|
35
|
-
Ids
|
|
35
|
+
Ids are unique within a `.rels` part. Read the existing ids and take `max+1`; reusing an id silently rewires an unrelated reference.
|
|
36
36
|
|
|
37
37
|
## The parts that exist only when used
|
|
38
38
|
|
|
39
|
-
`word/comments.xml`, `word/footnotes.xml`, `word/endnotes.xml`, `word/headerN.xml`, `word/footerN.xml`, `word/numbering.xml`, `docProps/custom.xml` — none are required, and each needs three pieces when added:
|
|
39
|
+
`word/comments.xml`, `word/footnotes.xml`, `word/endnotes.xml`, `word/headerN.xml`, `word/footerN.xml`, `word/numbering.xml`, `docProps/custom.xml` — none are required, and each needs three pieces when added: part, override, relationship. Removing one means removing all three, or Word reports corruption.
|
|
40
40
|
|
|
41
|
-
Headers and footers are referenced from the section properties, not
|
|
41
|
+
Headers and footers are referenced from the section properties, not the document root:
|
|
42
42
|
|
|
43
43
|
```xml
|
|
44
44
|
<w:sectPr>
|
|
@@ -59,4 +59,4 @@ Headers and footers are referenced from the section properties, not from the doc
|
|
|
59
59
|
|
|
60
60
|
## Rebuild rather than regenerate
|
|
61
61
|
|
|
62
|
-
When a package is broken,
|
|
62
|
+
When a package is broken, unzip it, fix the two registries and rezip with `[Content_Types].xml` first (stored, not deflated). The kit writes that order on save for this reason.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tracked changes
|
|
2
2
|
|
|
3
|
-
Tracked changes are markup, not a diff. The file
|
|
3
|
+
Tracked changes are markup, not a diff. The file holds both old and new text, wrapped in elements that say which is which, plus enough metadata for Word to show reviewer names and accept or reject each edit.
|
|
4
4
|
|
|
5
5
|
## The elements
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ Tracked changes are markup, not a diff. The file contains both the old and the n
|
|
|
13
13
|
| `w:delText` | The deleted characters — not `w:t` |
|
|
14
14
|
| `w:delInstrText` | A deleted field instruction |
|
|
15
15
|
|
|
16
|
-
Each carries `w:id`, `w:author
|
|
16
|
+
Each carries `w:id`, `w:author` and `w:date`. Ids are unique within the document; reusing one makes Word show the wrong reviewer.
|
|
17
17
|
|
|
18
18
|
A deletion is a `w:del` containing runs with `w:delText`, not a run with a strikethrough:
|
|
19
19
|
|
|
@@ -28,21 +28,21 @@ A deletion is a `w:del` containing runs with `w:delText`, not a run with a strik
|
|
|
28
28
|
|
|
29
29
|
## Tracking has to be on
|
|
30
30
|
|
|
31
|
-
`<w:trackRevisions/>` in `word/settings.xml` makes *Word* track subsequent edits
|
|
31
|
+
`<w:trackRevisions/>` in `word/settings.xml` makes *Word* track subsequent edits; it does not affect markup already in the file. Write the markup directly when generating a change; turn tracking on when the user will continue editing.
|
|
32
32
|
|
|
33
33
|
## Accepting and rejecting
|
|
34
34
|
|
|
35
|
-
- **Accept** — keep `w:ins` content and unwrap it
|
|
36
|
-
- **Reject** — delete `w:ins` content
|
|
37
|
-
- Either way, remove the revision containers afterwards;
|
|
38
|
-
- Format-change elements
|
|
35
|
+
- **Accept** — keep `w:ins` content and unwrap it, delete `w:del` entirely, and for moves keep `w:moveTo`.
|
|
36
|
+
- **Reject** — delete `w:ins` content, keep `w:del` content and convert `w:delText` back to `w:t` (unwrap the `w:del`).
|
|
37
|
+
- Either way, remove the revision containers afterwards; an empty `w:ins` shows a stray marker.
|
|
38
|
+
- Format-change elements are not content: accepting keeps the new properties, rejecting restores the old ones.
|
|
39
39
|
|
|
40
40
|
## Where tracking hides
|
|
41
41
|
|
|
42
|
-
- Inside headers, footers, footnotes, endnotes, table cells
|
|
43
|
-
- Table
|
|
44
|
-
- Paragraph
|
|
45
|
-
- Comments are separate markup; a comment can survive its being accepted.
|
|
42
|
+
- Inside headers, footers, footnotes, endnotes, table cells and text boxes.
|
|
43
|
+
- Table level: `w:trPr/w:ins` for an inserted row, `w:tcPr/w:cellIns` for a cell.
|
|
44
|
+
- Paragraph level: an inserted or deleted paragraph mark uses `w:rPr/w:ins` in `w:pPr`, so "delete this paragraph" is not a `w:del` around the paragraph.
|
|
45
|
+
- Comments are separate markup; a comment can survive its text being accepted.
|
|
46
46
|
|
|
47
47
|
## Reading markup without a renderer
|
|
48
48
|
|
|
@@ -50,4 +50,4 @@ A deletion is a `w:del` containing runs with `w:delText`, not a run with a strik
|
|
|
50
50
|
"<python>" "<skill>/scripts/accept_tracked_changes.py" "<file.docx>" --mode report
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
The report lists insertions and deletions with authors and the text on each side
|
|
53
|
+
The report lists insertions and deletions with authors and the text on each side — the honest answer to "what changed" with no rendered view, and the way to confirm a generated change landed as markup rather than as plain text.
|
|
@@ -19,9 +19,7 @@ word/comments.xml, footnotes.xml, endnotes.xml optional
|
|
|
19
19
|
|
|
20
20
|
## The body
|
|
21
21
|
|
|
22
|
-
`word/document.xml` is a sequence of block
|
|
23
|
-
|
|
24
|
-
A paragraph is:
|
|
22
|
+
`word/document.xml` is a sequence of block elements — `w:p` (paragraph), `w:tbl` (table), `w:sdt` (content control) — plus one `w:sectPr` per section: the last sits in the body, earlier ones inside a paragraph's `pPr`.
|
|
25
23
|
|
|
26
24
|
```xml
|
|
27
25
|
<w:p>
|
|
@@ -39,9 +37,9 @@ A paragraph is:
|
|
|
39
37
|
</w:p>
|
|
40
38
|
```
|
|
41
39
|
|
|
42
|
-
Everything a reader sees is a run inside a paragraph; everything that makes it
|
|
40
|
+
Everything a reader sees is a run inside a paragraph; everything that makes it differ from its style is direct formatting in `pPr`/`rPr`, which is why `style_normalize.py` exists (`tasks/style_lint_normalize.md`).
|
|
43
41
|
|
|
44
|
-
A table is `w:tbl` > `w:tblPr` (style, width, layout) + `w:tblGrid` (column widths) + `w:tr` > `w:tc` > `w:p`.
|
|
42
|
+
A table is `w:tbl` > `w:tblPr` (style, width, layout) + `w:tblGrid` (column widths) + `w:tr` > `w:tc` > `w:p`. Every cell holds at least one paragraph.
|
|
45
43
|
|
|
46
44
|
## Units
|
|
47
45
|
|
|
@@ -52,31 +50,31 @@ A table is `w:tbl` > `w:tblPr` (style, width, layout) + `w:tblGrid` (column widt
|
|
|
52
50
|
| eighth-point | border widths (`w:sz` on borders) | 8 per point |
|
|
53
51
|
| EMU (914400/in) | drawing extents | 914400 per inch |
|
|
54
52
|
|
|
55
|
-
A Letter page is 12240×15840 twips. Text width = page width − left − right margins (
|
|
53
|
+
A Letter page is 12240×15840 twips. Text width = page width − left − right margins (9360 twips at 1in margins).
|
|
56
54
|
|
|
57
55
|
## Styles
|
|
58
56
|
|
|
59
|
-
`w:style` with `w:type` of `paragraph`, `character`, `table` or `numbering
|
|
57
|
+
`w:style` with `w:type` of `paragraph`, `character`, `table` or `numbering`; attributes `w:styleId` (internal name), `w:name` (UI name), `w:basedOn`, `w:next`, `w:link`, plus `w:pPr` / `w:rPr`.
|
|
60
58
|
|
|
61
|
-
- `Normal` is the root; `Heading1`..`Heading9` drive
|
|
62
|
-
-
|
|
59
|
+
- `Normal` is the root; `Heading1`..`Heading9` drive outline level and the TOC.
|
|
60
|
+
- `w:outlineLvl` (0-based) in `pPr` sets an outline level explicitly: a paragraph can look like a heading without being one, and the TOC will not see it.
|
|
63
61
|
- Latent styles do not exist in the file until used; a document may reference `Heading3` while `styles.xml` has no definition for it.
|
|
64
62
|
|
|
65
63
|
## Numbering
|
|
66
64
|
|
|
67
|
-
`word/numbering.xml` holds `w:abstractNum` (
|
|
65
|
+
`word/numbering.xml` holds `w:abstractNum` (list definition: per level its format, text and indentation) and `w:num` (`w:numId` → `w:abstractNumId`, optionally overridden). A paragraph joins a list with `w:numPr` referencing a `numId`; two paragraphs with the same `numId` share a counter.
|
|
68
66
|
|
|
69
67
|
## Sections
|
|
70
68
|
|
|
71
|
-
`w:sectPr` carries page size (`w:pgSz`), margins (`w:pgMar`), orientation (implied by width vs height, or `w:orient`), columns
|
|
69
|
+
`w:sectPr` carries page size (`w:pgSz`), margins (`w:pgMar`), orientation (implied by width vs height, or `w:orient`), columns and header/footer references. A single-section document has one `sectPr`; a new section is a paragraph whose `pPr` contains the *previous* section's `sectPr`.
|
|
72
70
|
|
|
73
71
|
## Fields
|
|
74
72
|
|
|
75
|
-
Simple (`w:fldSimple`) and complex (`fldChar` begin/separate/end with `w:instrText`). The visible text is a cache
|
|
73
|
+
Simple (`w:fldSimple`) and complex (`fldChar` begin/separate/end with `w:instrText`). The visible text is a cache; `w:updateFields` in `settings.xml` asks the editor to refresh on open. See `ooxml/hyperlinks_and_fields.md`.
|
|
76
74
|
|
|
77
75
|
## Revision markup
|
|
78
76
|
|
|
79
|
-
`w:ins`, `w:del` (with `w:delText`), `w:moveFrom
|
|
77
|
+
`w:ins`, `w:del` (with `w:delText`), `w:moveFrom` / `w:moveTo`, `w:rPrChange` / `w:pPrChange`, each with author and date. See `ooxml/tracked_changes.md`.
|
|
80
78
|
|
|
81
79
|
## Minimum valid package
|
|
82
80
|
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# Eliciting a template
|
|
2
2
|
|
|
3
|
-
A user who says "use our house style" has a file somewhere.
|
|
3
|
+
A user who says "use our house style" has a file somewhere. One question gets it; guessing produces a document that has to be redone.
|
|
4
4
|
|
|
5
5
|
## Ask for the artefact, not the description
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
One sentence is enough:
|
|
7
|
+
A description ("blue headings, maybe 11pt") produces a different document every time. The artefact (`house-template.dotx`, an old `.docx` of the same kind, a PDF of the last report) carries the actual styles, margins and fonts.
|
|
10
8
|
|
|
11
9
|
> Is there an existing document in this style I should match? Send the file (`.dotx`, or any `.docx` in that style) and I will follow it exactly.
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
With no file, ask for two or three specifics that cannot be guessed and take the rest from `SKILL.md` defaults:
|
|
14
12
|
|
|
15
|
-
- page size and margins, if
|
|
16
|
-
-
|
|
13
|
+
- page size and margins, if the organisation is not US Letter,
|
|
14
|
+
- heading and body typeface and sizes,
|
|
17
15
|
- anything required by policy (logo in the header, classification mark in the footer).
|
|
18
16
|
|
|
19
17
|
## Read the template before using it
|
|
@@ -24,7 +22,7 @@ If they have no file, ask for two or three specifics that cannot be guessed and
|
|
|
24
22
|
"<python>" "<skill>/scripts/section_audit.py" "<template.docx>"
|
|
25
23
|
```
|
|
26
24
|
|
|
27
|
-
From `styles.xml`, note the `styleId` of what will be used: `Heading1`..`Heading3`, `Title`, `Caption`, `Quote`, `ListParagraph`. From the section audit, record page size, margins, header
|
|
25
|
+
From `styles.xml`, note the `styleId` of what will be used: `Heading1`..`Heading3`, `Title`, `Caption`, `Quote`, `ListParagraph`. From the section audit, record page size, margins, header and footer text, and whether the first page is different.
|
|
28
26
|
|
|
29
27
|
## Apply it
|
|
30
28
|
|
|
@@ -32,18 +30,18 @@ From `styles.xml`, note the `styleId` of what will be used: `Heading1`..`Heading
|
|
|
32
30
|
"<python>" "<skill>/scripts/apply_template_styles.py" --template "<template.docx>" --target "<draft.docx>" --out "<styled.docx>"
|
|
33
31
|
```
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
Merges style definitions (and numbering) by id; the body content is untouched, so anything written with direct formatting keeps it. Then:
|
|
36
34
|
|
|
37
35
|
```bash
|
|
38
|
-
"<python>" "<skill>/scripts/style_normalize.py" "<styled.docx>" --out "<styled-final.docx
|
|
36
|
+
"<python>" "<skill>/scripts/style_normalize.py" "<styled.docx>" --out "<styled-final.docx" --clear_paragraph_format --enforce_heading_spacing
|
|
39
37
|
```
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
The text now picks up the template's look instead of the draft's.
|
|
42
40
|
|
|
43
41
|
## When the template is a PDF or an image
|
|
44
42
|
|
|
45
|
-
Extract structure, not styles: heading hierarchy, section order, table layout, caption convention, margin proportions.
|
|
43
|
+
Extract structure, not styles: heading hierarchy, section order, table layout, caption convention, margin proportions. Reproduce them with named styles in a generated document. Say which parts were matched approximately — a PDF does not reveal a heading's font size, only how it looks.
|
|
46
44
|
|
|
47
45
|
## When there is no template and no details
|
|
48
46
|
|
|
49
|
-
Fall back to the
|
|
47
|
+
Fall back to the `SKILL.md` defaults (Letter, 1in margins, 11–12pt body, black headings, `#D9D9D9` table borders) and state the assumption in one line with the delivered file. Do not stall on a question the user may not care about.
|
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
# Writing quality
|
|
2
2
|
|
|
3
|
-
Content quality is the part of a document the format cannot fix.
|
|
3
|
+
Content quality is the part of a document the format cannot fix. Apply these rules while drafting, before any rendering.
|
|
4
4
|
|
|
5
5
|
## Structure before prose
|
|
6
6
|
|
|
7
|
-
- Every heading states a claim the reader can disagree with ("Services carried the quarter", not "Services").
|
|
7
|
+
- Every heading states a claim the reader can disagree with ("Services carried the quarter", not "Services").
|
|
8
8
|
- A section that cannot be summarised in one sentence is two sections.
|
|
9
|
-
- Three levels
|
|
10
|
-
- Nothing between a heading and its first paragraph
|
|
9
|
+
- Three heading levels is the practical maximum; a fourth means the content wants a table or an appendix.
|
|
10
|
+
- Nothing between a heading and its first paragraph — no label line, no restated title.
|
|
11
11
|
|
|
12
12
|
## Paragraphs
|
|
13
13
|
|
|
14
|
-
- One idea per paragraph, first sentence
|
|
15
|
-
- 3–6 sentences is
|
|
16
|
-
- No em-dash pile-ups, no "furthermore/moreover" chains, no sentence that only announces the next
|
|
17
|
-
- The last paragraph of a section says what
|
|
14
|
+
- One idea per paragraph, carried by the first sentence.
|
|
15
|
+
- 3–6 sentences is comfortable; a 1600-word paragraph is a formatting defect even when the prose is good.
|
|
16
|
+
- No em-dash pile-ups, no "furthermore/moreover" chains, no sentence that only announces the next one.
|
|
17
|
+
- The last paragraph of a section says what the section meant, not that it is finished.
|
|
18
18
|
|
|
19
19
|
## Lists and tables
|
|
20
20
|
|
|
21
21
|
- Bullets for parallel items of equal weight; never for a sequence (that is a numbered list).
|
|
22
|
-
-
|
|
23
|
-
- Table headers are nouns
|
|
22
|
+
- Items with two attributes belong in a table, not a bulleted list with parentheticals.
|
|
23
|
+
- Table headers are nouns with units ("Revenue ($m)"); numbers right-aligned.
|
|
24
24
|
- Every table earns its caption; a table without a purpose is a screenshot of data.
|
|
25
25
|
|
|
26
26
|
## Voice
|
|
27
27
|
|
|
28
|
-
- Active unless the actor is unknown or unimportant
|
|
28
|
+
- Active unless the actor is unknown or unimportant: "We found", not "It was found".
|
|
29
29
|
- Present tense for findings, past for actions taken.
|
|
30
|
-
- No unsupported superlatives
|
|
31
|
-
- Define an acronym once, then use it
|
|
30
|
+
- No unsupported superlatives: "18% growth" beats "strong growth"; if the number is unknown, say so instead of adding an adverb.
|
|
31
|
+
- Define an acronym once, then use it; never redefine it elsewhere.
|
|
32
32
|
|
|
33
33
|
## Numbers
|
|
34
34
|
|
|
35
|
-
- Consistent precision
|
|
35
|
+
- Consistent precision: do not mix "12.4%" and "8%" in one table unless the source did.
|
|
36
36
|
- Percentages below 1 take a leading zero (0.4%, not .4%).
|
|
37
|
-
- State
|
|
38
|
-
- A number
|
|
37
|
+
- State period and currency in the table or its caption, not in surrounding prose.
|
|
38
|
+
- A prose number must match the table number; rendering does not catch this, re-reading does.
|
|
39
39
|
|
|
40
40
|
## What to cut
|
|
41
41
|
|
|
42
|
-
- Opening paragraphs
|
|
43
|
-
- Closing paragraphs
|
|
42
|
+
- Opening paragraphs explaining that the document will explain something.
|
|
43
|
+
- Closing paragraphs thanking the reader.
|
|
44
44
|
- Bold on every second phrase: emphasis used everywhere is emphasis used nowhere.
|
|
45
|
-
- Sentences
|
|
45
|
+
- Sentences beginning "It is important to note that".
|
|
46
46
|
|
|
47
47
|
## Where this connects
|
|
48
48
|
|
|
49
|
-
`references/docx-structure.md` covers how
|
|
49
|
+
`references/docx-structure.md` covers how structure is expressed in Word — styles, captions, table layout. `tasks/verify_render.md` covers checking the result on a page. Neither replaces reading the text once asking whether a busy reader would get the point from the headings alone.
|