13 Commits

Author SHA1 Message Date
umbra audio
ed39c17eff Add Apache-2.0 LICENSE, NOTICE, and SPDX headers 2026-10-18 19:01:06 -07:00
bm
03945796bb fix: write w:next at XML level so self-referential next styles persist
python-docx's next_paragraph_style setter drops self-references (WA Nrml
Pgr -> itself, WA TOC -> itself), which would make Word continue those
paragraphs as Normal; the test now asserts the w:next element.
2026-09-24 08:01:09 -07:00
bm
166a4849da spec section 2.2 WA style family: authoritative styles + dynamic gutter
- spec: new section 2.2 style table (WA Chapter/Section/NChp Pgr/Nrml Pgr/
  Thkng + TOC mapping), margins 0.40/0.40/0.375 + 0.25 header-footer
  distance, dynamic gutter resolution procedure, header Caladea 10pt caps,
  footer 11pt, justified body without auto-hyphenation, WA Section reserved
  for scene breaks.
- formatter: WA_STYLES rebuilt to the spec values (next-style chain, outline
  level on WA Chapter, automatic color, widow control); content assigned by
  style reference with direct paragraph/run formatting removed; scene breaks
  use WA Section; TOC entries use WA TOC; auto-hyphenation removed; new page
  setup constants; header ALL CAPS 10pt / footer 11pt.
- format_document: inside/gutter margin now computed from the final page
  count (build -> render -> recompute fixed point, cap 3, settle on larger
  gutter on oscillation); inner_margin input ignored (UI selector removed).
- tests: 68 pass, incl. style-family value tests and mocked gutter-loop tests.
2026-09-24 07:53:19 -07:00
bm
16504d0b63 fix: drop per-field w:dirty, update fields on open via settings updateFields
Word's per-field dirty-driven field update crashes the full book with a hard
open error even at a single dirty PAGEREF (24-bisect isolation); the settings
level <w:updateFields w:val='true'/> batch path opens the same document with
correct TOC page numbers.
2026-09-23 11:21:32 -07:00
bm
d2ad88166a round-5 bisection: updateFields-path / mini-28-distinct / full-1field probes 2026-09-23 10:43:15 -07:00
bm
24ee7c34f5 round-4 bisection: no-validate / shared-hf-parts / mini-28fields probes 2026-09-23 09:15:20 -07:00
bm
9f08de1e5d Round 3 Word bisection: co-factor probes around the PAGEREF fields
The mini opens with 3 byte-identical fields while the full shell fails even
with 3 (bisect_12) or 1 target (bisect_11), so the co-factor is outside the
TOC. Six new candidates keep fields and strip the remaining families or
probe the field mechanism:

- 13 drop scene-break paragraphs
- 14 drop all bookmarkStart/End (fields keep, targets vanish)
- 15 full shell with the mini's own 3-entry TOC spliced in verbatim
- 16 drop chapter title paragraphs (WAChapter)
- 17 rewrite PAGEREF instructions to PAGE (structure unchanged)
- 18 remove w:dirty (no auto field update on open)
2026-09-23 08:45:30 -07:00
bm
284ebad6af Round 2 Word bisection: isolate the field-run co-factor
bisect_03 (fields removed) was the only round-1 file Word opened, and
document.xml becomes byte-identical between the full book and bisect_03
once field runs are removed — but the mini book opens with identical
PAGEREF fields, so the fields interact with a second factor. Add six
candidates that keep the 28 PAGEREF fields while peeling other layers:

- 07 drop deep-copied chapter prose (keep titles/bookmarks/fields)
- 08 drop numbering properties
- 09 inline hyperlink wrappers
- 10 remove the whole TOC section (cleaner no-fields control)
- 11 rewrite all PAGEREF targets to a single bookmark
- 12 keep fields only for the first 3 TOC entries
2026-09-23 07:57:21 -07:00
bm
0031acf59e Add Word bisection fixture batch for full-book open failure
Local audit of the full-book output is now exhaustive and clean (package
parts, content types, rels, styles, numbering, bookmark ids, fields,
sectPr/settings ordering, control chars, header/footer machine). LibreOffice
renders the file fine but Word hard-refuses it, so the trigger must be
isolated empirically: each candidate removes exactly one feature family.

- tests/make_bisect_files.py: regenerates six candidates from the final
  full-book output (no running heads; no oddPage/titlePg; no field runs;
  no style refs; first 8 sections only; no images).
- tests/word_bisect/bisect_0[1-6]_*.docx: the six fixtures (all verified to
  load via python-docx and convert via LibreOffice).
2026-09-23 07:43:58 -07:00
bm
9e35f24627 Fix Word refusal: dangling style references and pPr order in TOC
Root cause found by comparing the full-book output (Word refused) with the
new mini-book fixture (Word opened): the output's styles.xml was replaced
by the template's, yet deep-copied manuscript paragraphs still referenced
four KDP paragraph styles (WorstChapter, WrstNrmlChapText, WrstSection,
WAChpNrm) and the Hyperlink character style. Word validates every
referenced styleId and refuses files with dangling references; LibreOffice
silently falls back to Normal.

- Add _merge_missing_styles(): copy any w:style referenced by the output
  body but missing from styles.xml out of the source manuscript, resolving
  basedOn/next/link chains. Runs at the end of Pass 2.
- Fix TOC entry construction to use paragraph_format.tab_stops (python-docx
  inserts w:tabs in the schema-correct CT_PPr position instead of appending
  after w:jc/w:spacing).
- Regression tests: test_style_references_resolve (no undefined pStyle/
  rStyle) and test_body_pPr_children_schema_ordered (CT_PPr sequence).
  55 tests pass. Full-book output regenerated (332 pages; merged styles
  present; 0 undefined style refs; 0 pPr violations).
2026-09-23 07:26:32 -07:00
bm
005712e103 Add Word-validation test fixtures generated by the real formatter
tests/make_word_test_files.py regenerates three fixtures:
- tests/word_test_input.docx   - tagged mini manuscript (book start through
  req review, all section roles, <<<>>> scene breaks)
- tests/word_test_output.docx  - output of format_document() on the above
- tests/python_docx_control.docx - untouched python-docx save (baseline)

Purpose: bisect the Word-open failure. The full manuscript output is
structurally clean by every OOXML check (package rels, content types,
sectPr/settings ordering, header/footer parts, fields, hyperlinks, custom
parts all validate); the fixtures let Word itself tell us whether the
pipeline or the manuscript content is the trigger.
2026-09-23 07:05:54 -07:00
bm
dcd0716813 Fix Word-open failure: strict OOXML element ordering in sectPr and settings
sectPr children were emitted with headerReference/footerReference after
pgSz..mirrorMargins (SECTPR_ORDER), and w:settings had evenAndOddHeaders /
autoHyphenation appended after decimalSymbol/listSeparator. LibreOffice
tolerates out-of-order XML; Word validates CT_SectPr and CT_Settings
strictly and refuses the file.

- Move headerReference/footerReference to the head of SECTPR_ORDER per
  ECMA-376 CT_SectPr.
- Add SETTINGS_ORDER + _reorder_settings() using the full CT_Settings
  sequence (mathPr in the m: namespace) and apply it in Pass 2.
- Add regression tests asserting monotonic CT_SectPr and CT_Settings
  order for every section. 53 tests pass.
2026-09-23 06:27:21 -07:00
bm
0c32168231 Apply updated spec compliance and establish git/docker baseline
- Spec §4.1: running headers carry titles only (recto: chapter/section
  title; verso: author name + book title); page-number fields removed
  from headers.
- Spec §4.2: page numbers centered in the footer on both verso and recto
  pages; front-matter display pages (copyright, dedication, epigraph,
  TOC) show their Roman numeral on the opening page too.
- Spec §2.2: lowercase Roman numbering visible from the copyright page
  through the front matter; Chapter 1 restarts at Arabic 1.
- Chapter/back-matter sections keep running matter on body pages; only
  the first page of each chapter is suppressed (spec §4.3).
- Drop titlePg on single-page front-matter display sections so footer
  page numbers render in LibreOffice and Word alike.
- Preserve <<<>>> scene-break cues (centered, 12pt before/after) and
  first-word-only capitalization of chapter openers.
- UI: remove the obsolete "Page Numbers" selector; footer_mode is
  accepted-but-ignored for backward compatibility.
- Tests updated to the new spec behavior (51 pass).
2026-09-22 19:06:03 -07:00