chore(deps): stable AngleSharp.Css 1.1.2 + latest everything (supersedes #373 #376 #377) - #378
Conversation
Supersedes Dependabot #373, #376 and #377, and goes further where they lagged: SkiaSharp 4.153.1 (+ matching HarfBuzzSharp 14.2.1.301), coverlet 10.1.0 and docfx 2.81.0 are newer than what Dependabot proposed. The headline is AngleSharp.Css: 1.0.0-beta.144 -> 1.1.2, the first STABLE release NetPdf can take. 1.0.0 and 1.0.1 were held because they broke background-image painting. 1.1.2 does not: all background tests and every rendering golden (LayoutSnapshots, PaginationGolden, RenderingCorpus) are byte-identical. Every runtime dependency is now stable, so the NU5104 prerelease-dependency exception is removed and that check is an error again. Both Dependabot PRs failed all five enforcing legs. Each failure, run down: 1. REAL REGRESSION, fixed. W3C Flexbox + Grid gates failed (flex-gap-main-axis, flex-gap-with-justify-end, grid-gap-shorthand-columns). AngleSharp.Css 1.1.x expands a single-value `gap: 20px` into `row-gap: 20px` + an EMPTY `column-gap` instead of repeating the value (CSS Box Alignment L3 8.3). NetPdf drops empty longhands, so every one-value flex row and grid silently lost its column gap. CssParserAdapter now repairs an empty column-gap / grid-column-gap from its row twin, carrying the importance. Safe: an empty standard longhand is never authored CSS, and a `gap: var(--g)` expansion leaves row-gap empty too, so the var() recovery path is unaffected. New tests pin 1-value, !important, grid-gap and the untouched 2-value form. 2. BEHAVIOUR GAIN, tests updated. 1.1.x parses @container and @layer as real grouping rules (the beta dropped them; only the preprocessor's opaque RawBody survived). The cascade already handles both shapes: - @container bodies are still SKIPPED with CSS-CONTAINER-QUERY-UNSUPPORTED-001. A new CascadeCorpusTests case pins this end to end, because with real child rules a naive grouping-rule walk would have started applying container styles unconditionally. - @layer bodies now APPLY in layer order, where they used to be dropped. The corpus test now asserts the unlayered rule still beats the layered one (Cascade L5 6.4) and that CSS-AT-RULE-UNKNOWN-001 no longer fires. The adapter tests now assert "the body survives in some form" rather than the beta's exact opaque shape. 3. KNOWN GAP CLOSED upstream. GridShorthandProductionTests pinned `grid-row-end: 6 !important; grid-row: 2 / 4` at end=4 because the beta's per-rule dedup discarded the !important longhand. 1.1.x keeps it; the test is flipped to the spec-correct 6, exactly as its own comment instructed. The Directory.Packages.props note now records all three facts so the next bump starts from them. Verified locally: build 0 errors / 0 warnings; UnitTests 8618 passed / 3 skipped; RealDocuments 106; W3cConformance 6; RenderingCorpus 41; LayoutSnapshots 30; PaginationGolden 1; PdfValidation 1; fuzz smoke 0 findings; AOT/JIT parity verified; pack clean with no NU5104. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The gap repair can produce incorrect cascade values, and the Docker image’s Playwright browser does not match its installed Python client.
Review effort: Balanced
Findings: 1
Open (5)
Align Playwright Python client with bundled browser version · New Recover omitted gap component from shorthand declaration · New Update SkiaSharp compatibility note after version bump · New Update setup comment for AngleSharp 1.1.x behavior · New Remove obsolete comment describing the closed gap · New
What changed in this PR
Upgrades runtime and tooling dependencies, notably adopting stable AngleSharp.Css 1.1.2, with compatibility handling and regression tests.
Changes:
- Updates AngleSharp, graphics/text, testing, Playwright, and documentation tooling.
- Repairs single-value CSS gap expansion and enables parsed
@layerbehavior. - Updates cascade, parser, and grid regression coverage.
| File | Description |
|---|---|
Directory.Build.props |
Restores NU5104 as an error. |
Directory.Packages.props |
Updates centralized package versions. |
.config/dotnet-tools.json |
Updates docfx. |
CHANGELOG.md |
Documents dependency and CSS behavior changes. |
src/NetPdf.Css/Parser/CssParserAdapter.cs |
Repairs empty column-gap expansion. |
tests/NetPdf.UnitTests/Css/Parser/CssParserAdapterPreprocessTests.cs |
Tests parser and gap behavior. |
tests/NetPdf.UnitTests/Css/Properties/GridShorthandProductionTests.cs |
Updates important-grid precedence expectation. |
tests/NetPdf.RealDocuments/Css/CascadeCorpusTests.cs |
Tests decomposed layer and container rules. |
tests/NetPdf.RenderingCorpus/docker/Dockerfile |
Updates the Playwright image. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e42148d7cd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
PR #378 review follow-up. All 7 threads were valid. [P2 x2] The single-value gap repair picked ANY surviving row-gap as the column value. For `gap: 20px; row-gap: 30px` it produced column-gap: 30px; the correct value is 20px. Probing AngleSharp.Css 1.1.2 showed why no adapter-side fix can be exact: for that rule it keeps only row-gap: 30px and an empty column-gap — the shorthand's 20px is gone from its object model. So `gap` / `grid-gap` are now re-expanded by the preprocessor from the RAW declaration (new GapShorthandExpander, paren-aware so calc()/var() stay one component) as shorthand-expansion recovery records. The adapter's existing source-order + !important merge then decides each longhand exactly like the cascade: pinned for gap-then-row, row-then-gap, important shorthand, gap-then -column, column-then-gap, and calc(). grid-gap emits the modern row-gap / column-gap names, the only ones the engine registers. The adapter repair stays only as a fallback for paths with no recovery data, and now carries the empty entry's own importance (the shorthand's), not the row twin's. [P2] @layer children skipped the recovery pass. The cascade now APPLIES layer bodies, but CssPreprocessor.GroupingAtRules excluded `layer`, so the body was captured as an opaque blob and child rules fell back to AngleSharp-only adaptation — modern colors, var()-bearing shorthands and gap inside a layer were lost. `layer` is now a grouping rule; a test proves the gap case inside a layer comes out right. @container stays opaque on purpose (the cascade skips its body). [Copilot] The reference-generator Dockerfile pip-installed playwright==1.49 inside the 1.63 image, so chromium.launch() would look for a browser the image does not contain. Pinned to 1.63.0, with a note that the two move together. [Copilot x3] Stale text: the PDFtoImage/SkiaSharp note (rewritten without hard-coded patch numbers so it cannot drift again), and two test comments that still described the old AngleSharp behavior. Verified: build 0 errors; UnitTests 8625 passed / 3 skipped; RealDocuments 106; W3cConformance 6; RenderingCorpus 41; LayoutSnapshots 30; PaginationGolden 1; PdfValidation 1; fuzz smoke 0 findings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>



Supersedes Dependabot #373, #376 and #377, and goes further where they lagged (SkiaSharp 4.153.1 + HarfBuzzSharp 14.2.1.301, coverlet 10.1.0, docfx 2.81.0).
Headline: AngleSharp.Css is finally stable
1.0.0-beta.144→1.1.2. Earlier stable releases were held back because they broke background-image painting. 1.1.2 does not — all background tests and every rendering golden are byte-identical. Every runtime dependency is now stable, so theNU5104prerelease exception is removed and that check is an error again.Why both Dependabot PRs were red, and what I did
gap)gap: 20pxtorow-gap: 20px+ an emptycolumn-gap(violates CSS Box Alignment §8.3)CssParserAdapterfrom the row twin; tests added@container/@layeradapter tests@container(new end-to-end guard);@layernow applies in layer order!importantknown-gap testVerification (local)
build 0 errors / 0 warnings · UnitTests 8618 · RealDocuments 106 · W3cConformance 6 · RenderingCorpus 41 · LayoutSnapshots 30 · PaginationGolden 1 · PdfValidation 1 · fuzz smoke 0 findings · AOT/JIT parity ✓ · pack clean, no NU5104.
🤖 Generated with Claude Code