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.
Files changed (113) hide show
  1. package/assets/skills/excel-live-control/SKILL.md +119 -152
  2. package/assets/skills/excel-live-control/domain_guidance/financial_models.md +42 -58
  3. package/assets/skills/excel-live-control/domain_guidance/healthcare.md +36 -42
  4. package/assets/skills/excel-live-control/domain_guidance/marketing_advertising.md +33 -34
  5. package/assets/skills/excel-live-control/domain_guidance/scientific_research.md +34 -36
  6. package/assets/skills/excel-live-control/references/office-automation.md +127 -153
  7. package/assets/skills/excel-live-control/references/read_only_qna.md +40 -45
  8. package/assets/skills/excel-live-control/style_guidelines.md +56 -64
  9. package/assets/skills/excel-live-control/workflows/create_workflows.md +40 -47
  10. package/assets/skills/excel-live-control/workflows/edit_workflows.md +37 -45
  11. package/assets/skills/office-documents/SKILL.md +24 -60
  12. package/assets/skills/office-documents/examples/end_to_end_smoke_test.md +5 -5
  13. package/assets/skills/office-documents/ooxml/comments.md +8 -8
  14. package/assets/skills/office-documents/ooxml/hyperlinks_and_fields.md +10 -10
  15. package/assets/skills/office-documents/ooxml/rels_and_content_types.md +7 -7
  16. package/assets/skills/office-documents/ooxml/tracked_changes.md +12 -12
  17. package/assets/skills/office-documents/references/docx-structure.md +11 -13
  18. package/assets/skills/office-documents/references/template-elicitation.md +11 -13
  19. package/assets/skills/office-documents/references/writing-quality.md +20 -20
  20. package/assets/skills/office-documents/tasks/accessibility_a11y.md +16 -22
  21. package/assets/skills/office-documents/tasks/captions_crossrefs.md +23 -26
  22. package/assets/skills/office-documents/tasks/clean_tracked_changes.md +17 -22
  23. package/assets/skills/office-documents/tasks/comments_manage.md +9 -11
  24. package/assets/skills/office-documents/tasks/compare_diff.md +10 -16
  25. package/assets/skills/office-documents/tasks/create_edit.md +14 -16
  26. package/assets/skills/office-documents/tasks/equations.md +17 -28
  27. package/assets/skills/office-documents/tasks/fields_update.md +14 -16
  28. package/assets/skills/office-documents/tasks/fixtures_edge_cases.md +19 -33
  29. package/assets/skills/office-documents/tasks/footnotes_endnotes.md +12 -14
  30. package/assets/skills/office-documents/tasks/forms_content_controls.md +16 -20
  31. package/assets/skills/office-documents/tasks/headings_numbering.md +17 -22
  32. package/assets/skills/office-documents/tasks/images_figures.md +15 -25
  33. package/assets/skills/office-documents/tasks/multi_doc_merge.md +13 -23
  34. package/assets/skills/office-documents/tasks/navigation_internal_links.md +18 -21
  35. package/assets/skills/office-documents/tasks/privacy_scrub_metadata.md +16 -22
  36. package/assets/skills/office-documents/tasks/protection_restrict_editing.md +19 -21
  37. package/assets/skills/office-documents/tasks/read_review.md +9 -20
  38. package/assets/skills/office-documents/tasks/redaction_anonymization.md +17 -18
  39. package/assets/skills/office-documents/tasks/sections_layout.md +16 -23
  40. package/assets/skills/office-documents/tasks/style_lint_normalize.md +18 -22
  41. package/assets/skills/office-documents/tasks/tables_spreadsheets.md +21 -31
  42. package/assets/skills/office-documents/tasks/templates_style_packs.md +17 -21
  43. package/assets/skills/office-documents/tasks/toc_workflow.md +10 -14
  44. package/assets/skills/office-documents/tasks/verify_render.md +11 -23
  45. package/assets/skills/office-documents/tasks/watermarks_background.md +11 -15
  46. package/assets/skills/office-documents/troubleshooting/libreoffice_headless.md +6 -6
  47. package/assets/skills/office-documents/troubleshooting/run_splitting.md +12 -12
  48. package/assets/skills/office-pdf/SKILL.md +36 -51
  49. package/assets/skills/office-pdf/references/form-fields.md +20 -20
  50. package/assets/skills/office-pdf/references/geometry.md +10 -10
  51. package/assets/skills/office-pdf/references/layout-quality.md +13 -13
  52. package/assets/skills/office-pdf/references/limits.md +12 -56
  53. package/assets/skills/office-pdf/tasks/annotations.md +5 -5
  54. package/assets/skills/office-pdf/tasks/create.md +6 -9
  55. package/assets/skills/office-pdf/tasks/edit-pages.md +14 -14
  56. package/assets/skills/office-pdf/tasks/forms.md +15 -15
  57. package/assets/skills/office-pdf/tasks/read.md +9 -9
  58. package/assets/skills/office-pdf/tasks/redact.md +18 -18
  59. package/assets/skills/office-pdf/tasks/stamp.md +10 -10
  60. package/assets/skills/office-presentations/SKILL.md +71 -91
  61. package/assets/skills/office-presentations/container_tools/render_slides.py +1 -1
  62. package/assets/skills/office-presentations/domain_guidance/finance.md +16 -16
  63. package/assets/skills/office-presentations/recipes/README.md +24 -35
  64. package/assets/skills/office-presentations/recipes/autolayout.md +12 -13
  65. package/assets/skills/office-presentations/recipes/connectors.md +11 -12
  66. package/assets/skills/office-presentations/recipes/images.md +11 -12
  67. package/assets/skills/office-presentations/recipes/master-and-layouts.md +18 -18
  68. package/assets/skills/office-presentations/recipes/native-charts.md +8 -8
  69. package/assets/skills/office-presentations/recipes/rich-text-runs.md +13 -13
  70. package/assets/skills/office-presentations/recipes/speaker-notes.md +7 -7
  71. package/assets/skills/office-presentations/recipes/tables.md +14 -14
  72. package/assets/skills/office-presentations/recipes/textbox-at-coordinate.md +9 -9
  73. package/assets/skills/office-presentations/recipes/theme-tokens.md +7 -8
  74. package/assets/skills/office-presentations/references/authoring-workflow.md +38 -43
  75. package/assets/skills/office-presentations/references/finalization.md +10 -12
  76. package/assets/skills/office-presentations/references/native-bullets.md +14 -18
  77. package/assets/skills/office-presentations/references/native-evidence.md +18 -32
  78. package/assets/skills/office-presentations/references/style-guidelines.md +27 -32
  79. package/assets/skills/office-presentations/references/templates.md +31 -60
  80. package/assets/skills/office-presentations/routing/google_slides.md +4 -4
  81. package/assets/skills/office-presentations/tasks/apply-annotations.md +17 -17
  82. package/assets/skills/office-presentations/tasks/charts-tables-notes.md +20 -23
  83. package/assets/skills/office-presentations/tasks/create-deck.md +19 -19
  84. package/assets/skills/office-presentations/tasks/edit-deck.md +14 -16
  85. package/assets/skills/office-presentations/tasks/inspect-and-verify.md +31 -34
  86. package/assets/skills/office-presentations/tasks/template-following.md +23 -28
  87. package/assets/skills/office-spreadsheets/SKILL.md +32 -39
  88. package/assets/skills/office-spreadsheets/recipes/charts.md +8 -26
  89. package/assets/skills/office-spreadsheets/recipes/conditional-formats.md +9 -26
  90. package/assets/skills/office-spreadsheets/recipes/data-tables.md +7 -23
  91. package/assets/skills/office-spreadsheets/recipes/named-ranges.md +8 -21
  92. package/assets/skills/office-spreadsheets/recipes/number-formats.md +7 -23
  93. package/assets/skills/office-spreadsheets/recipes/sparklines.md +7 -20
  94. package/assets/skills/office-spreadsheets/references/charts.md +15 -34
  95. package/assets/skills/office-spreadsheets/references/domain/financial-models.md +10 -25
  96. package/assets/skills/office-spreadsheets/references/domain/healthcare.md +8 -19
  97. package/assets/skills/office-spreadsheets/references/domain/marketing.md +8 -22
  98. package/assets/skills/office-spreadsheets/references/domain/research.md +8 -19
  99. package/assets/skills/office-spreadsheets/references/formula-patterns.md +20 -50
  100. package/assets/skills/office-spreadsheets/references/style-guidelines.md +19 -44
  101. package/assets/skills/office-spreadsheets/references/workbook-structure.md +12 -35
  102. package/assets/skills/office-spreadsheets/routing/google-sheets.md +11 -26
  103. package/assets/skills/office-spreadsheets/tasks/analyze-workbook.md +10 -25
  104. package/assets/skills/office-spreadsheets/tasks/annotations.md +12 -30
  105. package/assets/skills/office-spreadsheets/tasks/create-workbook.md +5 -5
  106. package/assets/skills/office-spreadsheets/tasks/diff-workbooks.md +2 -2
  107. package/assets/skills/office-spreadsheets/tasks/edit-workbook.md +5 -5
  108. package/assets/skills/office-spreadsheets/tasks/inspect-workbook.md +9 -9
  109. package/assets/skills/office-spreadsheets/tasks/recalc-and-check.md +10 -30
  110. package/assets/skills/shared/annotation-recipes.md +98 -120
  111. package/assets/skills/shared/common-workflow.md +70 -80
  112. package/dist/index.js +1 -1
  113. package/package.json +1 -1
@@ -5,14 +5,14 @@ The mechanics are the same as any deck; the failure modes are specific.
5
5
  ## What a finance audience checks first
6
6
 
7
7
  1. Does the total add up? A slide whose numbers do not sum loses the argument
8
- before the argument starts. Run the arithmetic gate on every declared total.
8
+ before it starts. Run the arithmetic gate on every declared total.
9
9
  2. Is the period stated? "Revenue up 12%" without a base period is not a claim.
10
- 3. Is the unit stated? Thousands, millions, currency, and whether it is gross or
11
- net. Put it in the header, once.
12
- 4. Is the comparison like-for-like? Full quarter against full quarter; do not
13
- put a 13-week quarter beside a 12-week one without saying so.
14
- 5. Does the chart axis start at zero? For bars, yes, always — a truncated bar
15
- chart in a finance deck reads as manipulation even when it is not.
10
+ 3. Is the unit stated? Thousands, millions, currency, gross or net. Put it in the
11
+ header, once.
12
+ 4. Is the comparison like-for-like? Full quarter against full quarter; do not put
13
+ a 13-week quarter beside a 12-week one without saying so.
14
+ 5. Does the chart axis start at zero? For bars, always — a truncated bar chart in
15
+ a finance deck reads as manipulation even when it is not.
16
16
 
17
17
  ## The financial slide kit
18
18
 
@@ -30,11 +30,11 @@ The mechanics are the same as any deck; the failure modes are specific.
30
30
  - Two significant figures is usually enough for a headline (`£2.4m`, not
31
31
  `£2,384,117`). Keep full precision in the appendix table.
32
32
  - Percentages: one decimal at most, and say what they are a percentage *of*.
33
- - Round consistently: if the headline says 2.4m, the table should not say
34
- 2.38m in one row and 2.4m in the next.
35
- - Negative numbers: use a minus sign consistently (`−12%`) and keep
36
- parentheses for tables where accounting convention is expected.
37
- - A variance is meaningless without its sign and its direction; state whether
33
+ - Round consistently: if the headline says 2.4m, the table should not say 2.38m
34
+ in one row and 2.4m in the next.
35
+ - Negative numbers: one minus sign convention (`−12%`), parentheses kept for
36
+ tables where accounting convention is expected.
37
+ - A variance is meaningless without its sign and direction; state whether
38
38
  favourable is up or down (revenue vs cost).
39
39
 
40
40
  ## Charts that survive a CFO
@@ -45,14 +45,14 @@ The mechanics are the same as any deck; the failure modes are specific.
45
45
  - One series per chart unless the comparison *is* the point.
46
46
  - Do not chart a table of six numbers; the table is more honest and faster to
47
47
  read.
48
- - Forecast periods are visually distinct (lighter fill, dashed line) and named
49
- in the caption.
48
+ - Forecast periods are visually distinct (lighter fill, dashed line) and named in
49
+ the caption.
50
50
 
51
51
  ## Provenance
52
52
 
53
53
  Every non-obvious number gets a note with: source file or system, extraction
54
- date, period covered, and any adjustment made. The speaker notes are the right
55
- place; a footnote-heavy slide is a slide nobody reads.
54
+ date, period covered, any adjustment made. The speaker notes are the right place;
55
+ a footnote-heavy slide is a slide nobody reads.
56
56
 
57
57
  ## Check before delivery
58
58
 
@@ -1,12 +1,9 @@
1
1
  # Slide mechanics and paste-runnable recipes
2
2
 
3
- The helper CLI covers the common path: a small deck with a title, bullet slides,
4
- a table, a chart and a picture. Everything else — precise coordinates, master
5
- edits, notes, theme tokens, connectors — is ordinary `python-pptx` work, and
6
- these recipes are the honest route.
7
-
8
- Read the mechanics first, then paste the recipe. Every snippet runs as-is from a
9
- shell, from any working directory:
3
+ The helper CLI covers the common path: title, bullets, table, chart, picture.
4
+ Everything else — exact coordinates, master edits, notes, theme tokens,
5
+ connectors — is `python-pptx` work. These recipes are the route and run as-is
6
+ from a shell, from any working directory:
10
7
 
11
8
  ```bash
12
9
  "<python>" - <<'PY'
@@ -21,17 +18,16 @@ PY
21
18
  |---|---|
22
19
  | Where is this shape? | `left`, `top`, `width`, `height` in **EMU** (English Metric Units). |
23
20
  | What is an inch? | `914400` EMU. `pptx.util.Inches(1)` is the polite wrapper. |
24
- | What is a point? | `12700` EMU. Font sizes use points, geometry uses EMU, and mixing them silently breaks layout. |
21
+ | What is a point? | `12700` EMU. Font sizes use points, geometry uses EMU; mixing them silently breaks layout. |
25
22
  | What is a slide? | `prs.slide_width` / `prs.slide_height`; check them, never assume 16:9. |
26
23
 
27
- Helper conversions worth memorising: `Emu(914400) == Inches(1)`,
28
- `Pt(28) == Emu(355600)`, and a fraction of the slide is
24
+ `Emu(914400) == Inches(1)`, `Pt(28) == Emu(355600)`, and a slide fraction is
29
25
  `int(0.1 * prs.slide_width)`.
30
26
 
31
27
  ## Z-order
32
28
 
33
- Shapes paint in the order they live in `slide.shapes`. A shape added later
34
- covers one added earlier. To reorder without deleting:
29
+ Shapes paint in `slide.shapes` order; later covers earlier. Reorder without
30
+ deleting:
35
31
 
36
32
  ```python
37
33
  tree = slide.shapes._spTree
@@ -40,32 +36,25 @@ tree.remove(shape._element)
40
36
  tree.insert(2, shape._element) # after nvGrpSpPr and grpSpPr
41
37
  ```
42
38
 
43
- Index `2` is the first painted shape; that is where a full-bleed background
44
- image belongs.
39
+ Index `2` is the first painted shape — where a full-bleed background belongs.
45
40
 
46
41
  ## What this pack ships
47
42
 
48
43
  | Recipe | Use it when |
49
44
  |---|---|
50
45
  | [textbox-at-coordinate](textbox-at-coordinate.md) | Text must land on an exact rect, not "somewhere under the title". |
51
- | [autolayout](autolayout.md) | The same build has to fit 3 bullets or 9 without hand-tuning. |
52
- | [tables](tables.md) | Numbers need a grid with column widths and per-cell formatting. |
53
- | [native-charts](native-charts.md) | Data must stay editable, not become a picture of a chart. |
54
- | [master-and-layouts](master-and-layouts.md) | The whole deck changes at once: title bar, accent line, footer. |
55
- | [speaker-notes](speaker-notes.md) | The presenter needs a script attached to each slide. |
56
- | [theme-tokens](theme-tokens.md) | Colours and fonts must come from one place. |
57
- | [rich-text-runs](rich-text-runs.md) | One paragraph mixes bold, accent colour and a footnote. |
58
- | [images](images.md) | A picture needs a crop, a cover fit or a real alt text. |
59
- | [connectors](connectors.md) | Two boxes are joined by a line that must survive a move. |
60
-
61
- ## Order of work that keeps decks out of trouble
62
-
63
- 1. Read the target geometry off the template or the user's reference
64
- (`container_tools/inspect_presentation_layout_geometry.py` prints it as JSON).
65
- 2. Place shapes in EMU, top-down: background, chrome, title, body, evidence.
66
- 3. Set type sizes by the *smallest* screen the deck will be shown on; body 18 pt
67
- and up, footnotes 12 pt and up.
68
- 4. Fill every placeholder you keep and delete the ones you do not — an empty
69
- placeholder prints "Click to add text" in edit view and looks unfinished.
70
- 5. Render, look, then fix. `container_tools/render_slides.py` plus `read_image`
71
- is the loop; a deck nobody looked at is not verified.
46
+ | [autolayout](autolayout.md) | The same build must fit 3 bullets or 9 without hand-tuning. |
47
+ | [tables](tables.md) | Numbers need column widths and per-cell formatting. |
48
+ | [native-charts](native-charts.md) | Data must stay editable, not a chart picture. |
49
+ | [master-and-layouts](master-and-layouts.md) | Whole-deck changes: title bar, accent line, footer. |
50
+ | [speaker-notes](speaker-notes.md) | A script attached to each slide. |
51
+ | [theme-tokens](theme-tokens.md) | Colours and fonts from one place. |
52
+ | [rich-text-runs](rich-text-runs.md) | One paragraph mixes bold, accent colour, footnote. |
53
+ | [images](images.md) | A crop, a cover fit or real alt text. |
54
+ | [connectors](connectors.md) | A line between boxes that survives a move. |
55
+
56
+ ## Order of work
57
+
58
+ Follow the loop in [authoring-workflow](../references/authoring-workflow.md):
59
+ story → frame → place top-down in EMU → fill or delete placeholders → render and
60
+ look. Type sizes live in [style-guidelines](../references/style-guidelines.md).
@@ -2,19 +2,18 @@
2
2
 
3
3
  ## Mechanics
4
4
 
5
- PowerPoint has two different "autofit" ideas and mixing them up wastes a round
6
- trip:
5
+ PowerPoint has two "autofit" ideas; mixing them up wastes a round trip:
7
6
 
8
7
  - `word_wrap` decides whether text wraps inside the width. Turn it on for every
9
8
  authored box.
10
9
  - `auto_size` decides whether the *frame* follows the text (`MSO_AUTO_SIZE.
11
10
  SHAPE_TO_FIT_TEXT`) or the text shrinks to fit the frame
12
11
  (`TEXT_TO_FIT_SHAPE`). `TEXT_TO_FIT_SHAPE` is a **render-time** behaviour:
13
- PowerPoint recalculates it when the file is opened, so a deck that looks fine
14
- in a draft preview can still shrink to 8 pt on a real screen.
12
+ PowerPoint recalculates it when the file opens, so a deck that looks fine in a
13
+ draft preview can still shrink to 8 pt on a real screen.
15
14
 
16
- The reliable pattern is: fixed frame, explicit sizes, content measured against
17
- the frame, no text-to-fit. Estimate, then verify by rendering.
15
+ The reliable pattern: fixed frame, explicit sizes, content measured against the
16
+ frame, no text-to-fit. Estimate, then verify by rendering.
18
17
 
19
18
  ## Recipe: fit a variable number of bullets
20
19
 
@@ -66,7 +65,7 @@ PY
66
65
  ## Rules that hold regardless of content
67
66
 
68
67
  1. Body text is 18 pt or larger; below that the back row cannot read it.
69
- 2. Six bullets or three lines of body is the point where a slide should split.
68
+ 2. Six bullets or three lines of body is where a slide should split.
70
69
  3. Longer text shrinks the number of *words*, not the type size. If the fit loop
71
70
  lands below the body floor, cut copy or split the slide.
72
71
  4. Keep 0.5 in of bottom margin for the footer and for projectors that crop.
@@ -77,12 +76,12 @@ PY
77
76
  - `frame.text` then `paragraph.font.size` on paragraph 0 only: a multi-paragraph
78
77
  assignment leaves paragraphs 1..n at the inherited 18 pt.
79
78
  - Text-to-fit hiding the overflow: the file opens fine and the audience reads
80
- 9 pt. Measure, do not delegate the fit to the renderer.
81
- - A frame height that exactly equals the text height: one extra word on edit and
82
- the block runs into the evidence below. Reserve 10% slack.
79
+ 9 pt. Measure; do not delegate the fit to the renderer.
80
+ - A frame height exactly equal to the text height: one extra word on edit and the
81
+ block runs into the evidence below. Reserve 10% slack.
83
82
 
84
83
  ## CLI fast path
85
84
 
86
- `pptx create` with `layout: "bullets"` fills the layout's body placeholder at
87
- its own size. Use the loop above when the number of bullets is not known before
88
- the content is written.
85
+ `pptx create` with `layout: "bullets"` fills the layout's body placeholder at its
86
+ own size. Use the loop above when the number of bullets is unknown before the
87
+ content is written.
@@ -2,11 +2,10 @@
2
2
 
3
3
  ## Mechanics
4
4
 
5
- A connector is a line with two attachment sites. `add_connector` takes a begin
6
- and end shape *plus* connection indices, which is what makes the line follow the
7
- boxes when they move. If you pass coordinates instead, the line is a floating
8
- line: it looks right in the file you made and wrong the first time a box is
9
- nudged.
5
+ A connector is a line with two attachment sites. `add_connector` takes begin and
6
+ end shapes *plus* connection indices, which is what makes the line follow the
7
+ boxes when they move. Pass coordinates instead and you get a floating line: right
8
+ in the file you made, wrong the first time a box is nudged.
10
9
 
11
10
  - `MSO_CONNECTOR.STRAIGHT | ELBOW | CURVE`
12
11
  - `connector.begin_connect(shape, idx)` / `end_connect(shape, idx)`; `idx` is
@@ -59,19 +58,19 @@ PY
59
58
 
60
59
  ## Rules
61
60
 
62
- 1. Connect sides that face each other: right → left for a row, bottom → top for
63
- a column. A line crossing its own boxes reads as an error.
61
+ 1. Connect facing sides: right → left for a row, bottom → top for a column. A
62
+ line crossing its own boxes reads as an error.
64
63
  2. Elbow connectors for orthogonal flows, straight for a single hop, curve almost
65
64
  never.
66
- 3. Two crossing connectors in one diagram is the point where the diagram becomes
67
- a picture of a diagram; split it.
65
+ 3. Two crossing connectors in one diagram makes it a picture of a diagram; split
66
+ it.
68
67
  4. Label the connector ("12 min", "auto") with a small textbox near its middle,
69
68
  not with arrow direction alone.
70
69
 
71
70
  ## Pitfalls this avoids
72
71
 
73
72
  - `add_connector` with free coordinates: the line is positioned but unattached,
74
- and the deck's own edits break it silently.
73
+ and later edits break it silently.
75
74
  - Arrowhead index confusion: arrowhead values are a bitmask enum, not a boolean.
76
75
  - Connectors behind filled shapes because they were added before the boxes.
77
76
 
@@ -79,5 +78,5 @@ PY
79
78
 
80
79
  There is no connector verb in `pptx create`; this recipe is the route. After
81
80
  building, `container_tools/inspect_presentation_layout_geometry.py` flags
82
- `connector_over_text` when a line crosses a text shape, which is the failure
83
- mode you cannot see in a thumbnail.
81
+ `connector_over_text` when a line crosses a text shape — the failure mode you
82
+ cannot see in a thumbnail.
@@ -4,13 +4,13 @@
4
4
 
5
5
  `add_picture(path, left, top, width=…, height=…)`:
6
6
 
7
- - Give **width only** and the height follows the aspect ratio. Give both and
8
- the picture is stretched — a deliberate choice for a full-bleed background,
9
- a mistake for a product photo.
7
+ - Give **width only** and the height follows the aspect ratio. Give both and the
8
+ picture stretches — deliberate for a full-bleed background, a mistake for a
9
+ product photo.
10
10
  - `picture.crop_left/right/top/bottom` are fractions of the *source*; they crop
11
11
  without changing the frame, which is how a "cover" fit is done.
12
- - The bytes live in `ppt/media/`; the same file added twice is stored once,
13
- keyed by content hash.
12
+ - The bytes live in `ppt/media/`; the same file added twice is stored once, keyed
13
+ by content hash.
14
14
  - `picture._element.nvPicPr.cNvPr.set("descr", "…")` is the alt text. Decks get
15
15
  read aloud and exported; an untagged picture is an empty sentence.
16
16
 
@@ -57,11 +57,10 @@ PY
57
57
  ## Rules
58
58
 
59
59
  1. Never upscale past the source resolution: a 900 px wide image at 8 in is
60
- ~110 ppi and will look soft on a projector. Check `Image.open(...).size`.
61
- 2. One dominant image per slide. A slide with a hero and three thumbnails is two
62
- slides.
63
- 3. Full-bleed backgrounds need text contrast handled deliberately — a dark
64
- scrim rectangle between picture and text, not hope.
60
+ ~110 ppi and looks soft on a projector. Check `Image.open(...).size`.
61
+ 2. One dominant image per slide. A hero plus three thumbnails is two slides.
62
+ 3. Full-bleed backgrounds need deliberate text contrast — a dark scrim rectangle
63
+ between picture and text, not hope.
65
64
  4. Alt text on every picture, in the language of the deck.
66
65
 
67
66
  ## Pitfalls this avoids
@@ -70,8 +69,8 @@ PY
70
69
  name as the cause.
71
70
  - `add_picture` after the text: the picture covers the words. Add backgrounds
72
71
  first, or move them to index 2.
73
- - Re-using a screenshot of a chart or a table as "evidence": it is unreadable at
74
- projector size and unverifiable. Use a native chart or table.
72
+ - Re-using a screenshot of a chart or table as "evidence": unreadable at
73
+ projector size, unverifiable. Use a native chart or table.
75
74
 
76
75
  ## CLI fast path
77
76
 
@@ -2,15 +2,15 @@
2
2
 
3
3
  ## Mechanics
4
4
 
5
- A deck has three levels, and where you make a change decides how many slides it
5
+ A deck has three levels; where you make a change decides how many slides it
6
6
  fixes:
7
7
 
8
- - **Slide master** (`ppt/slideMasters/`) — theme fonts, colours, background,
9
- and the shapes every slide inherits (title bar, accent rule, logo).
8
+ - **Slide master** (`ppt/slideMasters/`) — theme fonts, colours, background, and
9
+ the shapes every slide inherits (title bar, accent rule, logo).
10
10
  - **Slide layout** (`ppt/slideLayouts/`) — one per slide family (title, title and
11
11
  content, section, blank…), each with named placeholders at fixed rects.
12
- - **Slide** — holds its own shapes plus *placeholder overrides*: text, and also
13
- position, if someone dragged a placeholder.
12
+ - **Slide** — its own shapes plus *placeholder overrides*: text, and position if
13
+ someone dragged a placeholder.
14
14
 
15
15
  Editing a placeholder's *text* is a per-slide change. Editing the layout's
16
16
  placeholder *rect* moves that frame on every slide of that family. Editing the
@@ -20,9 +20,9 @@ master's background moves it everywhere.
20
20
  To change a slide's family, delete it and add a new one from the target layout —
21
21
  losing its content, so plan families before filling them.
22
22
 
23
- **One quirk to know:** `master.shapes` and `layout.shapes` are read-only in
24
- `python-pptx` (`MasterShapes` has no `add_shape`). Chrome shapes are therefore
25
- built on a scratch slide and their XML moved into the master's shape tree.
23
+ **One quirk:** `master.shapes` and `layout.shapes` are read-only in `python-pptx`
24
+ (`MasterShapes` has no `add_shape`). Build chrome shapes on a scratch slide and
25
+ move their XML into the master's shape tree.
26
26
 
27
27
  ## Recipe: restyle a family from the master
28
28
 
@@ -88,36 +88,36 @@ print("removed:", removed)
88
88
  PY
89
89
  ```
90
90
 
91
- This is what clears the `empty_placeholder` review finding in
91
+ This clears the `empty_placeholder` review finding in
92
92
  `container_tools/inspect_presentation_layout_geometry.py`. Keep a placeholder you
93
93
  still intend to fill, and never delete the one slide numbers are linked to.
94
94
 
95
95
  ## Reusing the source's own layouts
96
96
 
97
- When the user supplies a template, do not rebuild its look — put content into
98
- its placeholders. The inspection script prints each layout's placeholders with
99
- index, kind and rect, which is what you need to address them:
97
+ With a supplied template, do not rebuild its look — put content into its
98
+ placeholders. The inspection script prints each layout's placeholders with index,
99
+ kind and rect, which is what you need to address them:
100
100
 
101
101
  ```bash
102
102
  "<python>" container_tools/inspect_presentation_layout_geometry.py --input template.pptx --json-out geometry.json
103
103
  ```
104
104
 
105
105
  Then address a placeholder by index on the slide:
106
- `slide.placeholders[1].text = "..."`. Slides created from a layout always have
107
- a placeholder for every non-empty slot, so index-based addressing is stable.
106
+ `slide.placeholders[1].text = "..."`. Slides created from a layout always have a
107
+ placeholder for every non-empty slot, so index-based addressing is stable.
108
108
 
109
109
  ## Pitfalls this avoids
110
110
 
111
111
  - Drawing the accent rule on every slide instead of the master: one edit later,
112
112
  half the deck has two rules.
113
- - Dragging a placeholder on a slide to fix one frame; the layout is untouched
114
- and the next slide of the same family misbehaves again.
113
+ - Dragging a placeholder on a slide to fix one frame; the layout is untouched and
114
+ the next slide of the same family misbehaves again.
115
115
  - Appending the scratch shape to the master without `drop_rel`: the orphan slide
116
116
  part stays in the package and `inspect_presentation_package_integrity.py`
117
117
  reports a slide count mismatch.
118
118
  - Adding a *blank* slide and a floating textbox where the template has a title
119
- placeholder: the deck no longer answers to its own master, and the outline
120
- view is empty.
119
+ placeholder: the deck no longer answers to its own master, and the outline view
120
+ is empty.
121
121
 
122
122
  ## CLI fast path
123
123
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  A chart added with `slide.shapes.add_chart` is a real chart part
6
6
  (`ppt/charts/chartN.xml`) with an embedded workbook
7
- (`ppt/embeddings/*.xlsx`). That matters for three reasons:
7
+ (`ppt/embeddings/*.xlsx`). That matters:
8
8
 
9
9
  - The audience can edit the numbers in PowerPoint; a picture of a chart cannot.
10
10
  - The data is in the file, so a gate can check it. A screenshot cannot be
@@ -12,9 +12,9 @@ A chart added with `slide.shapes.add_chart` is a real chart part
12
12
  - The chart inherits the slide's theme for colour and type, so charts match the
13
13
  deck without per-chart styling.
14
14
 
15
- `CategoryChartData` holds the numbers; `chart.plots[0]` holds the geometry of
16
- the marks. Category order is the series' own order — sort before you pass it,
17
- because a chart does not sort.
15
+ `CategoryChartData` holds the numbers; `chart.plots[0]` holds the geometry of the
16
+ marks. Category order is the series' own order — sort before you pass it, because
17
+ a chart does not sort.
18
18
 
19
19
  ## Recipe
20
20
 
@@ -63,18 +63,18 @@ PY
63
63
  ## Rules for charted numbers
64
64
 
65
65
  1. One idea per chart. Two series is fine; six is a table.
66
- 2. No chart title that repeats the slide title — the title says what the chart
66
+ 2. No chart title repeating the slide title — the slide title says what the chart
67
67
  *means* ("Throughput rose while touches fell"), the chart shows the numbers.
68
68
  3. Start the value axis at zero for bars, and say so in the notes if you do not.
69
69
  4. Data labels beat a value axis grid; pick one, not both.
70
- 5. Never leave the default "Chart Title" placeholder text in a shipped deck.
70
+ 5. Never leave the default "Chart Title" text in a shipped deck.
71
71
 
72
72
  ## Pitfalls this avoids
73
73
 
74
74
  - `number_format` without `number_format_is_linked = False` reverts to the
75
75
  workbook's format the next time PowerPoint refreshes the chart.
76
- - `legend.include_in_layout = False` is what stops the legend from stealing
77
- plot height and squashing the bars.
76
+ - `legend.include_in_layout = False` stops the legend stealing plot height and
77
+ squashing the bars.
78
78
  - Deleting the embedded workbook (by zipping/unzipping carelessly) turns the
79
79
  chart into an uneditable picture in every downstream viewer.
80
80
 
@@ -9,11 +9,11 @@ replaces every run, so **format runs, never paragraphs**:
9
9
  - `paragraph.text = "x"` — one run, all previous formatting gone.
10
10
  - `run = paragraph.add_run(); run.text = "x"; run.font.bold = True` — formatting
11
11
  survives and can differ inside the paragraph.
12
- - `paragraph.font.size` is not a thing PowerPoint respects for mixed content; it
12
+ - `paragraph.font.size` is not something PowerPoint respects for mixed content; it
13
13
  sets the default for later runs only. Set the size on every run you add.
14
14
 
15
- Paragraph-level properties (`alignment`, `level`, `space_after`,
16
- `line_spacing`) apply to the whole paragraph and are safe to set once.
15
+ Paragraph-level properties (`alignment`, `level`, `space_after`, `line_spacing`)
16
+ apply to the whole paragraph and are safe to set once.
17
17
 
18
18
  ## Recipe
19
19
 
@@ -62,22 +62,22 @@ PY
62
62
 
63
63
  ## Rules
64
64
 
65
- 1. A number you want the reader to remember gets its own run, and usually a
66
- weight change — not a second bullet.
65
+ 1. A number the reader should remember gets its own run, usually with a weight
66
+ change — not a second bullet.
67
67
  2. Superscripts, footnote markers and unit symbols are runs, not characters
68
68
  smuggled into the sentence.
69
- 3. Keep one family of emphasis per deck: bold+accent for numbers, italic+muted
70
- for provenance. Three competing emphases read as decoration.
71
- 4. Strings that repeat (units, currency, product names) belong in a variable so
72
- a later edit does not leave two spellings.
69
+ 3. One family of emphasis per deck: bold+accent for numbers, italic+muted for
70
+ provenance. Three competing emphases read as decoration.
71
+ 4. Repeated strings (units, currency, product names) belong in a variable so a
72
+ later edit does not leave two spellings.
73
73
 
74
74
  ## Pitfalls this avoids
75
75
 
76
76
  - `paragraph.text = "Total: "` then `add_run()`: the first assignment already
77
- replaced the frame's runs, so formatting set beforehand is gone.
78
- - A run with no `font.size` inherits the layout's size, which is 44 pt on a
79
- title layout — footnote markers become headlines.
80
- - Building the paragraph by f-string with `**` markers that PowerPoint does not
77
+ replaced the frame's runs, so earlier formatting is gone.
78
+ - A run with no `font.size` inherits the layout's size, which is 44 pt on a title
79
+ layout — footnote markers become headlines.
80
+ - Building the paragraph by f-string with `**` markers PowerPoint does not
81
81
  interpret; markup in a deck is a run, not a syntax.
82
82
 
83
83
  ## CLI fast path
@@ -6,10 +6,10 @@ Notes live in `ppt/notesMasters/` plus one `ppt/notesSlides/notesSlideN.xml` per
6
6
  slide, tied to the slide by a relationship. In `python-pptx` this is
7
7
  `slide.notes_slide.notes_text_frame` — the notes slide is created on first
8
8
  access, so reading it in a loop silently adds one per slide. Only touch it when
9
- you are writing.
9
+ writing.
10
10
 
11
- Notes are not visible in the render. That means a notes problem cannot be caught
12
- by looking at the PNGs: check them with `pptx read` or by reading the XML back.
11
+ Notes are invisible in the render, so a notes problem cannot be caught by looking
12
+ at the PNGs: check them with `pptx read` or by reading the XML back.
13
13
 
14
14
  ## Recipe
15
15
 
@@ -45,21 +45,21 @@ PY
45
45
  12 sites").
46
46
  - The answer to the question the slide invites.
47
47
  - Nothing that belongs on the slide: if the audience needs it, put it on the
48
- slide, notes are invisible when the deck is sent as a PDF.
48
+ slide — notes are invisible when the deck is sent as a PDF.
49
49
 
50
50
  ## Pitfalls this avoids
51
51
 
52
52
  - Iterating `prs.slides` and *reading* `notes_slide` on a template with none:
53
53
  every slide gains an empty notes part and the file grows.
54
54
  - Long notes pasted as one paragraph with line breaks that only look like
55
- paragraphs; each intended paragraph should be `add_paragraph()` so the notes
56
- pane and the presenter view indent them.
55
+ paragraphs; use `add_paragraph()` per intended paragraph so the notes pane and
56
+ presenter view indent them.
57
57
  - Assuming notes render into the preview: they do not, so verify them from the
58
58
  file.
59
59
 
60
60
  ## CLI fast path
61
61
 
62
62
  `pptx create` writes slides without notes. The recipe above is the route; then
63
- `pptx read --input deck-notes.pptx` does not print notes, so read them back with
63
+ `pptx read --input deck-notes.pptx` does not print notes, so read them back from
64
64
  `ppt/slides` sibling `notesSlide` parts via
65
65
  `inspect_presentation_package_integrity.py` (it counts `notesSlides`).
@@ -6,11 +6,11 @@ A table in a deck is a grid of cells on a canvas; it does not reflow. Three
6
6
  properties decide whether it reads as a table or as soup:
7
7
 
8
8
  - **Column widths** are the layout. `table.columns[i].width = Inches(3.2)` —
9
- setting them is mandatory, because `add_table` splits the width evenly.
9
+ mandatory, because `add_table` splits the width evenly.
10
10
  - **Row heights** are a minimum. Text taller than the row pushes it open, which
11
- then runs into whatever sits below.
11
+ runs into whatever sits below.
12
12
  - **Cell margins** default to 0.1 in left/right and 0.05 in top/bottom on a
13
- 0.5 in row, which is most of the row. Reduce them when rows are tight.
13
+ 0.5 in row — most of the row. Reduce them when rows are tight.
14
14
 
15
15
  Header row emphasis (`table.first_row = True`) is a table style switch, not a
16
16
  formatting guess: it turns on the theme's header fill and bold.
@@ -66,23 +66,23 @@ PY
66
66
 
67
67
  ## Numbers people trust
68
68
 
69
- - Right-align numeric columns, left-align the label column, and keep decimals
69
+ - Right-align numeric columns, left-align the label column, keep decimals
70
70
  consistent per column (`553`, not `553.0` next to `171`).
71
- - A total row is a claim. Show enough rows that the reader can check it, and
72
- let `container_tools/native_table_arithmetic_gate.py` prove it from the file.
73
- - Units belong in the header (`Orders`, `Touches`), not repeated in every cell.
74
- - Money keeps its currency in the header or the first row; `¥1,240` in every
75
- cell of a dense table is noise.
71
+ - A total row is a claim. Show enough rows that the reader can check it, and let
72
+ `container_tools/native_table_arithmetic_gate.py` prove it from the file.
73
+ - Units belong in the header (`Orders`, `Touches`), not in every cell.
74
+ - Money keeps its currency in the header or first row; `¥1,240` in every cell of
75
+ a dense table is noise.
76
76
 
77
77
  ## Pitfalls this avoids
78
78
 
79
79
  - Even column widths turning "Q1" into a 4 in column while numbers crowd.
80
- - A table whose declared height is smaller than its content: the last row is
81
- drawn below the intended block and collides with the footer.
80
+ - A declared height smaller than the content: the last row is drawn below the
81
+ intended block and collides with the footer.
82
82
  - Colouring cells individually instead of letting `first_row` do the header.
83
83
 
84
84
  ## CLI fast path
85
85
 
86
- `pptx create` accepts `{"table": {"headers": [...], "rows": [[...]]}}` and
87
- places it at 0.8 in from the left, full content width, at the running cursor.
88
- For a chosen rect, column widths or right-aligned numbers, use the recipe.
86
+ `pptx create` accepts `{"table": {"headers": [...], "rows": [[...]]}}` and places
87
+ it at 0.8 in from the left, full content width, at the running cursor. For a
88
+ chosen rect, column widths or right-aligned numbers, use the recipe.
@@ -7,10 +7,10 @@ what you see:
7
7
 
8
8
  - `left`/`top` are the **top-left corner** of the frame, not of the glyphs. A
9
9
  28 pt line has roughly 4 pt of space above the cap height inside its frame.
10
- - `width` is the wrap width. `word_wrap = True` must be set explicitly on a new
11
- box or long lines run past the slide edge instead of wrapping.
10
+ - `width` is the wrap width. Set `word_wrap = True` explicitly on a new box or
11
+ long lines run past the slide edge instead of wrapping.
12
12
  - `height` is the *frame*, not the content: PowerPoint lets text spill below it
13
- (which overlaps whatever is under the box) unless autosize is turned on.
13
+ (overlapping whatever is under the box) unless autosize is on.
14
14
  - Interior margins default to 0.1 in left/right and 0.05 in top/bottom. Setting
15
15
  them to 0 makes the rect mean exactly what you measured.
16
16
 
@@ -44,10 +44,10 @@ PY
44
44
 
45
45
  ## Measuring before you place
46
46
 
47
- Do not guess whether the text fits — compute it. A line of 28 pt text fits
48
- about `width_in * 96 / (0.55 * 28)` characters (0.55 average advance for a
49
- humanist sans), and each line needs `1.2 * 28 / 72` inches of height. Leave the
50
- estimate in the script, then let the render confirm it.
47
+ Do not guess whether the text fits — compute it. A line of 28 pt text fits about
48
+ `width_in * 96 / (0.55 * 28)` characters (0.55 average advance for a humanist
49
+ sans), and each line needs `1.2 * 28 / 72` inches of height. Leave the estimate
50
+ in the script, then let the render confirm it.
51
51
 
52
52
  ```python
53
53
  def fits(text: str, width_in: float, height_in: float, size_pt: float) -> bool:
@@ -58,8 +58,8 @@ def fits(text: str, width_in: float, height_in: float, size_pt: float) -> bool:
58
58
 
59
59
  ## Pitfalls this avoids
60
60
 
61
- - A box sized to the text at 18 pt, later edited to 32 pt, now overlaps the
62
- table below. Frame height follows the *largest* run, so size text first.
61
+ - A box sized to text at 18 pt, later edited to 32 pt, now overlaps the table
62
+ below. Frame height follows the *largest* run, so size text first.
63
63
  - `add_textbox` with `width=Inches(13.3)` on a 13.333 in slide plus default
64
64
  margins = 0.2 in of overflow past the right edge. Subtract the margins.
65
65
  - `MSO_ANCHOR.MIDDLE` on a title looks intentional on a cover and wrong on a
@@ -10,10 +10,9 @@ The theme part (`ppt/theme/theme1.xml`) holds two palettes and two font lists:
10
10
  - `majorFont` / `minorFont` — the heading and body typefaces inherited by every
11
11
  run without an explicit font.
12
12
 
13
- So: write `RGBColor.rgb` when a colour must never change, and reference a theme
14
- colour when the user may re-skin the deck. A deck with hard-coded hex
15
- everywhere cannot be re-branded, which is usually why the user supplied a
16
- template.
13
+ Write `RGBColor.rgb` when a colour must never change; reference a theme colour
14
+ when the user may re-skin the deck. A deck with hard-coded hex everywhere cannot
15
+ be re-branded — usually why the user supplied a template.
17
16
 
18
17
  ## Recipe: define the palette once, use it everywhere
19
18
 
@@ -73,12 +72,12 @@ names it finds in the theme, so check there before introducing a new typeface.
73
72
 
74
73
  ## Pitfalls this avoids
75
74
 
76
- - Two similar hexes drifting apart across slides (`#161d28` on one slide,
77
- `#171e29` on the next) because the colour was retyped instead of referenced.
75
+ - Two similar hexes drifting apart across slides (`#161d28` here, `#171e29`
76
+ there) because the colour was retyped instead of referenced.
78
77
  - A serif body font set from taste rather than from the theme, so the deck
79
78
  contradicts the template it was built in.
80
- - `font.color.theme_color = MSO_THEME_COLOR.ACCENT_1` *and* `font.color.rgb`
81
- on the same run: the last assignment wins and the theme reference vanishes.
79
+ - `font.color.theme_color = MSO_THEME_COLOR.ACCENT_1` *and* `font.color.rgb` on
80
+ the same run: the last assignment wins and the theme reference vanishes.
82
81
 
83
82
  ## CLI fast path
84
83