Skip to content

fix(docx): ask a zone's page predicate of the layout's own pages - #918

Merged
DemchaAV merged 1 commit into
2.5-devfrom
fix/docx-zone-pages-and-bands
Oct 19, 2026
Merged

DemchaAV merged 1 commit into
2.5-devfrom
fix/docx-zone-pages-and-bands

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

Word paginates for itself, so a page zone's appliesTo predicate is asked over sample pages and
sorted into Word's first, even and other pages (DocxPageClasses). The sample is a document of six
pages, or of the layout's own page count where that is more. Every sample page was asked as one
of that document, so a shorter layout's pages too were asked as pages of a six-page document. The
page asks each of its pages as one of as many as the layout ran to (DocumentPageZones.apply).
A predicate that reads the total therefore answered one way for the export and another for the
page.

Measured in Word and LibreOffice on Windows, on a one-page document:

Footer predicate Page Word before LibreOffice before
page -> page.total() == 1 drawn, 19.95pt from the foot none none
page -> page.total() > 1 none drawn drawn

The first footer was skipped, with nothing in the report. The second got only the "not measured" note.

What changed

  • DocxPageClasses.of:

    • still asks the six-page sample, which decides whether the predicate follows Word's kinds at
      all: the last page, the third;
    • for a layout of fewer than six pages, also asks each of its pages as the page does,
      paginated(number, pageCount);
    • those answers decide the kinds of page the layout has, and the sample's decide the rest;
    • where the layout's own pages of one kind answer otherwise, the zone is written on every page
      and reported, as a sample that does so is;
    • a document of six pages or more, and an export with no layout, is asked exactly as before.

    Consequences:

    • one page:
      • total() == 1 sorts to the first page (the title page's footer);
      • total() > 1 sorts to the pages after the first;
      • isFirst() && !isLast() sorts to none;
    • two pages:
      • total() == 2 sorts to the first and even pages;
      • total() > 2 sorts to the later odd pages, which a two-page document has none of.

    Asking the layout's pages and the pages past them in one pass, each of its own total, puts two
    documents into one kind: total() > 2 on two pages answered no for page 2 and yes for page 4.
    So the layout is asked as a sample of its own.

  • Docs:

    • the DOCX recipe's zones section and the capability matrix's zone row say how the sample is asked;
    • CHANGELOG v2.5.0.

Verification

  • After the change, in Word and LibreOffice on Windows:
    • one page, total() == 1: the footer is on the one page, 19.92 and 19.96pt from its foot (the page: 19.95);
    • one page, total() > 1: on none;
    • two pages, total() == 2: on both, 19.92 and 19.96pt (the page: 19.95), with no zone note;
    • two pages, total() > 2: on neither;
    • two pages, total() > 1: where the page draws it, as before.
  • ./mvnw -B -ntp test -f render-docx/pom.xml:
    • DocxPageClassesTest, 1 new test:
      • one page: total() == 1, total() > 1, isFirst() && !isLast();
      • two pages: total() == 1, total() == 2, total() > 2;
      • three pages: total() == 3 (every kind), total() > 3 (none);
      • four pages, total() == 4 && number() == 2: unsorted;
      • eight pages: total() == 8.
    • DocxPageZoneKindsTest, 4 new tests: the one-page and two-page footers above, read from
      the exported parts. The total() > 2 footer is the later odd pages' footer, with different
      even and odd pages stated.
    • The existing page-class and zone suites stay green.
  • 6 sabotages, all caught:
    • the layout not asked;
    • no sample past the pages;
    • the layout asked as the sample;
    • its kinds answering otherwise ignored;
    • one-page layouts only;
    • the sample over the layout.
  • Corpus: 62/62 DOCX byte-identical; report notes 1246 → 1246.
  • ./mvnw -B -ntp clean verify: BUILD SUCCESS (core 821, render-docx 1775, examples 93, qa 1820).
    The knowledge pack's --check passes. Two test assertions, a Javadoc line and docs wording were
    added after it; ./mvnw -B -ntp test -f render-docx/pom.xml re-run after them: 1775, BUILD
    SUCCESS.

Lane: render-docx (semantic backend). DOCX output can change only in a document with a zone
whose predicate reads the page total (total(), isLast()) on fewer than six pages. The title
page a section states, and the different even and odd pages a document states, then reach that
section's and the document's other zones and bands, as they do for any zone filed so.

Word paginates for itself, so a page zone's appliesTo predicate is
asked over sample pages, a document of six pages or of the layout's own
count where that is more, and sorted into Word's first, even and other
pages. A shorter layout's pages were asked as pages of that six-page
document, while the page asks each of its pages as one of as many as
the layout ran to. A predicate that reads the total then answered
otherwise for the export than for the page. On a one-page document a
footer for one-page documents only (page.total() == 1) was not written,
with nothing said, and one for longer documents only (page.total() > 1)
was written on the one page, which the page draws none of. Measured in
Word and LibreOffice on Windows, both showed the second and not the
first.

DocxPageClasses still asks the six-page sample, which decides whether
the predicate follows Word's kinds at all. A layout of fewer than six
pages is now asked as well, as a document of its own, each page as the
page asks it; those answers decide the kinds of page the layout has,
and the sample's the rest. Both editors then show the first footer on
the one page, 19.92 and 19.96pt from its foot where the page sets it
19.95, and the second on none; on two pages a footer for two-page
documents only is on both and one for more than two pages on neither.
A document of six pages or more, and an export with no layout, is
asked as before.
@DemchaAV
DemchaAV merged commit 32d14a6 into 2.5-dev Oct 19, 2026
13 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-zone-pages-and-bands branch October 19, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant