Skip to content

Keep @page declarations that follow a margin box - #200

Merged
TylerBrinks merged 1 commit into
TylerBrinks:masterfrom
jhaygood86:bugfix/page-rule-margin-box-token-advance
Jul 23, 2026
Merged

Keep @page declarations that follow a margin box#200
TylerBrinks merged 1 commit into
TylerBrinks:masterfrom
jhaygood86:bugfix/page-rule-margin-box-token-advance

Conversation

@jhaygood86

Copy link
Copy Markdown
Contributor

Problem

Inside @page, any declaration that comes after a margin box is silently dropped:

@page { @top-center { content: "h" } margin: 1cm }   /* margin: 1cm lost */
@page { @top-left {…} @bottom-right {…} margin: 2cm }  /* margin: 2cm lost */

A margin box (@top-center, @bottom-right, …, per CSS Paged Media 3 §6) is parsed by CreateMarginStyle, whose inner FillDeclarations consumes the box's body through its closing }. But CreateMarginStyle takes the outer token by ref and leaves it pointing at the box's own { (where CreateMarginSelector left it). FillDeclarations then did:

var marginStyle = CreateMarginStyle(ref marginToken);
parentPageRule.AppendChild(marginStyle);
token = marginToken;   // <-- stale: the box's '{', already consumed

so the loop re-entered on a stale token and skipped past everything up to the @page block's own } — dropping any trailing declarations and any further margin boxes.

A margin box that appears last in the block (the shape the existing StyleSheetPageAtRulesAndProperties test uses) is unaffected, since there's nothing after it — which is why this went unnoticed.

Fix

Advance with NextToken() to the next real token after the consumed margin box. Declarations before a margin box already worked and are unchanged.

Tests

3 tests in Cases.cs: a declaration after one margin box, declarations both before and after, and two margin boxes followed by a declaration — asserting both the margin rules and the trailing longhands. All 3 fail on master. The existing @page test (margin box last) stays green, along with the other 1262 tests, and all seven target frameworks build with no new warnings.

Inside @page, a nested margin box (@top-center, @bottom-right, …) is
parsed by CreateMarginStyle, whose inner FillDeclarations consumes the
box's body through its closing '}' but leaves the ref token pointing at
the box's own '{'. FillDeclarations then did `token = marginToken`,
re-entering its loop on that stale token, so every declaration after the
margin box - and any further margin box - was silently dropped:

  @page { @top-center { content: "h" } margin: 1cm }   /* margin lost */

A margin box that comes last (the shape the existing test used) was
unaffected, which is why this went unnoticed.

Advance to the next real token with NextToken() instead. Declarations
before the box already worked and are unchanged.
@jhaygood86
jhaygood86 marked this pull request as ready for review July 22, 2026 22:20
@TylerBrinks
TylerBrinks merged commit 6ba5bcd into TylerBrinks:master Jul 23, 2026
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.

2 participants