Repository navigation
test(docx): hold every drawing of a block that writes text to a paragraph of that text - #979
Merged
Merged
Conversation
…raph of that text A drawing placed from its paragraph moves with that paragraph when a reader edits the text above it; one placed from the page keeps its place on the sheet while the text it belongs to is edited away from under it. Four changes taught the export to carry such drawings, bringing the template corpus from 465 drawings placed from the page down to 32, and nothing held what they won: a change putting one back on the sheet would have left every suite green, no test reading where a drawing is placed from at all. DocxDrawingPlacements reads every drawing of a DOCX from every XML part — the body, its headers and footers, and the tables and text boxes nested in them, a drawing inside another's text box included — with what each is placed from and across, whether it floats, and the name the export writes it under, which tells a drawing a node paints from a page's own fill. It reads simplePos as well, because at simplePos="1" the editors take the place from wp:simplePos and read neither positionH nor positionV, so a drawing nailed to the sheet that way still says relativeFrom="paragraph" in the file. An anchor it cannot classify is a problem it reports rather than a silence. DocxDrawingAnchorGuardTest holds the rule two ways. Over the template corpus, where 728 of the 760 floating drawings a node paints are carried by a paragraph, the 32 still placed from the page must equal, document for document and drawing for drawing, a ledger naming the reason each is there — work still to do, not a set of cases where the page is right. Over six documents of its own, one for each writer of a paragraph that carries a drawing today — a paragraph of the body, a panel's, a column of a row, an item of a list, the one line two halves of a band share, and a table cell a drawing is all of — every drawing must be placed down from a paragraph, since one written into the text instead would satisfy a rule that only kept it off the page. DocxFixtures holds what this guard and DocxPageReferenceGuardTest both need to write a DOCX by hand, which were about to exist twice; the page-reference guard now uses it. No engine code changes, so the corpus is unmoved and no baseline is retaken. The recipe now says what being placed from the page costs a drawing.
… keyword where an offset belongs The document for a drawing that is all a table cell holds put a bare EllipseNode in the cell, which is not what the export's exception asks for: it fires only for a layer stack or a shape container that only draws, so the disc was anchored by the ordinary walk instead and the exception had no document at all. The disc is now a layer stack of one layer, which meets every condition the exception states. A wp:positionV may say wp:align — a keyword, "bottom" — where the export says a wp:posOffset. Read as a missing offset that came out as nought, a drawing sitting exactly on its paragraph's top: a reading, and a wrong one. The reader now tracks whether an offset was given at all and reports an anchor that gave none, which leaves the missing-offset problem to anchors that do name something to be placed down from, an anchor with no wp:positionV being that one problem and not two. The ledger's reasons reach the failure: they were recorded against each document and read nowhere, so a red named the drawings and not what the ledger claims about them. The floor on the corpus's floating drawings is held at 750 against the 760 measured rather than 700, since the slack is what a drawing could go missing in. DocxPageReferenceGuardTest drops the four imports left dead by moving its hand-written-file helpers out.
…hor placed down twice The document for a drawing that is all a table cell holds named the wrong gate. It said drawingCellFor, and that a shape container would do as well as a layer stack. Neither is so: drawingCellFor wants a placement of its own and content composed in a cell has none, so the gate that fires is anchorComposedDrawing, and the shapes are collected by DocxCellDrawings.shapesOf, whose parameter is a layer stack. A shape container in that cell would stop the exception firing while the ordinary walk carried the drawing anyway — green, and covering nothing. The document was already a layer stack of one layer; now the Javadoc says which gate that satisfies and that a shape container is not one of them. The reason recorded for the one drawing whose own block does write paragraphs on its page said how far it rises, within what a drawing is allowed. The rise is not what refuses it, and not because it is within the allowance: risesNoFurther is reached only from Seat.place, which a composed cell's drawing takes by way of placeBeside, while a drawing a node paints is placed by Seat.placeHeld, which never asks. The reason now names what placeHeld does refuse on, with the one of those that is measured out. An anchor carrying two wp:positionV left this reader saying what one of them names and how far down the other says, silently; it is now a problem. An inline drawing's offset reads 0 as its contract says, rather than the value a floating anchor gets when its offset cannot be read. The ledger's record holds its drawings as a list, not an array, so its equality is its drawings. The documents of the rule are all read before the test fails, since a document for each writer of text is there to name the writer that stopped offering its paragraph.
…ng's places down The documents were described as one for each writer of a paragraph that carries a drawing. They are not: offerASeat is keyed on a paragraph node, so the body's paragraph, a panel's and a column of a row are the same writer, and what those three vary is the holder whose paragraph the walk must find. The six do cover all three writers that offer a paragraph — a paragraph node, a list's item, the line two halves of a band share — and the exception for a drawing that is all a cell holds, which offers none, and they are now described that way. The record's component is named for what carries the drawing rather than for a writer. Both ledger reasons named only the first leg of the walk. A drawing is left on the page only once the fall back to the text nearest it has refused it as well, so both now say so. A second wp:positionV is counted rather than inferred from whether the last one named anything to be placed from: a first element without relativeFrom would otherwise pass unnoticed and leave its offset read against the second's name. The page-reference guard takes its header parts from the shared fixtures too, which is what moving them out was for.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A drawing placed from its paragraph moves with that paragraph when a reader edits the text above
it. One placed from the page keeps its place on the sheet while the text it belongs to is edited
away from under it — the card walks down the page and the icon over its corner stays behind.
Four changes in a row taught the export to carry such drawings, bringing the template corpus from
465 drawings placed from the page down to 32. Nothing held what they won: no test read where a
drawing is placed from at all, so a change putting one back on the sheet would have left every
suite green.
What changed
Test code only — no engine change, so the corpus is byte-identical and no baseline moves.
DocxDrawingPlacements(new) reads every drawing of a DOCX from every XML part — the body, itsheaders and footers, and the tables and text boxes nested in them — with what each is placed from
and across, whether it floats, and the
wp:docPrname the export writes it under, which is whattells a drawing a node paints (
Drawing N) from a page's own fill (Page background N). A drawingstanding in another's text box is read in its own right, each anchor in its own frame.
It also reads
simplePos, which the rest of this would be blind without: atsimplePos="1"Wordand LibreOffice take the place from
wp:simplePosand read neitherpositionHnorpositionV, soa drawing nailed to the sheet that way still says
relativeFrom="paragraph"in the file. A truthyvalue is reported as a problem; left out, the attribute means what
"0"means, as the schema hasit.
An anchor the reader cannot classify — nothing to be placed down from, no name, a name that is
neither a drawing nor a page fill, an offset that is no number, a place it was not written to judge
— is reported as a problem rather than passed over.
FlowOwnerDrawingDocuments(new) holds six small documents, one for each paragraph that carriesa drawing today: a paragraph of the body, a panel's, a column of a row, an item of a list, the one
line two halves of a band share, and a table cell a drawing is all of. Between them they cover all
three writers of text that offer a paragraph to the drawings beside it — a paragraph node, a list's
item, a band's shared line — and the exception for a drawing that is all a cell holds, which offers
no paragraph at all; the first three share the paragraph node as their writer and differ in the
holder whose paragraph the walk must find. Each is small enough that a failure names what stopped
carrying the drawing. They are deliberately not in the fidelity corpus — they hold the rule, where
the corpus fixes what the export does today, and adding documents to the corpus moves its
baselines.
DocxDrawingAnchorGuardTest(new) holds both. Over the corpus, the drawings still placed fromthe page must equal, document for document and drawing for drawing, a ledger that names the reason
each is there:
no paragraph of that cell it can be placed from and the fall back to the nearest text does not
place it either —
invoice-payments13,invoice-workspace8,invoice-merchant4, each with92 or more paragraphs on its page, so it is not for want of one. Which step gives up is not
pinned down, and the entry states the outcome rather than guessing at a mechanism.
a closing banner's two, laid over the flow and set in a text box where the page sets them — so
that no paragraph of the blocks holding them stands on their page at all.
far it rises is not what refuses it:
risesNoFurtheris reached only fromSeat.place, which acomposed cell's drawing takes by way of
placeBeside, while a drawing a node paints is placed bySeat.placeHeld, which never asks. Of whatplaceHelddoes refuse on, one is measured out — thenearest paragraph's top is known, 52.80pt — and the rest are named in the entry, unmeasured.
The ledger names each drawing rather than counting them, so a change fixing one and breaking
another in the same document cannot pass on a tally that comes out the same. The equality holds
both ways: it is a record of work still to do, not a licence, and when the export learns to carry
those drawings the test fails until the ledger is brought down to match.
Over the six documents nothing may be placed from the page, and every drawing must be placed down
from a paragraph — not merely kept off the page, since an export that wrote these shapes into the
text instead would satisfy the weaker claim.
DocxFixtures(new) holds what this guard andDocxPageReferenceGuardTestboth need to write aDOCX by hand — the namespaces, a body, a header, a footer, a paragraph, the zip, and the check that
an export was made from its layout — which were about to exist twice. The page-reference guard now
uses it instead of its own copies.
docs/recipes/docx-export.mdnow says what being placed from the page costs a drawing, which therules around it described without naming the consequence.
Verification
Run on this branch,
./mvnwfrom the worktree:DocxDrawingAnchorGuardTest15 tests andDocxPageReferenceGuardTest11, 26 of 26 passing.test -pl :graph-compose-render-docx -am— 2363 tests, 0 failures, 1 skipped.test -f qa/pom.xml— 1871 tests, 0 failures, 1 skipped.Each rule the guard holds was broken once, alone, and the guard had to go red on a reported test
failure — an exit code was not accepted as proof, after a scripting fault turned a Maven that never
started into a false "caught":
simplePos="1")simplePoswp:positionVEach was applied alone, to the final tree, and the set was re-run after every round of review
fixes, since both the reader and one document changed.
The corpus figures above were measured over the 71 exported documents: 760 floating drawings a node
paints, of which 728 are carried and 32 are placed from the page — the ledgered ones; 381 inline
drawings, which are placed from nothing and are not this guard's subject; and, separately, 32 page
fills, every one of them on the sheet, which is how the reader proves it can read a page-placed
drawing at all. The two 32s are different measurements that happen to agree.