Skip to content

MarkdownRenderer 1.0 native renderer and JitHub integration - #103

Draft
Xueyang-Song wants to merge 18 commits into
mainfrom
codex/markdown-renderer-1-0
Draft

Xueyang-Song wants to merge 18 commits into
mainfrom
codex/markdown-renderer-1-0

Conversation

@Xueyang-Song

Copy link
Copy Markdown
Collaborator

Replaces #99 with a clean history and a smaller scope. It keeps the renderer, its feature packs, and what's needed to keep developing them (tests, harness, UI test runners, performance gates, CI, docs), plus the JitHub integration the renderer needs. It drops the dev-time material from the correctness campaign.

Commits

  1. Core library: GFM parsing, layout and painting, selection and copy, accessibility, the virtualized viewport, images, the HTML subset, and GitHub profile styling. ThorVG is removed in favor of resvg.
  2. Feature packs: Math, Mermaid, SVG/raster through isolated resvg workers (vendored crates pinned by provenance), and TextMate.
  3. Tests: behavior, conformance, pixel and pack tests, plus NativeAOT smoke apps.
  4. Sample, performance harness, benchmarks.
  5. Engineering scripts and CI: packaging/release checks, performance gates, the Windows Sandbox UI runners and their self-tests, and markdown-renderer-preview.yml.
  6. JitHub integration:
    • runtime, theme, strings and notices
    • viewer lifecycle
    • leased image admission (Camo, raw CDN and Git LFS sources are woven into this pipeline, so they stay)
    • SVG previews on resvg
    • NativeAOT dependency pins and host contract tests
  7. Docs.

Not in this PR (vs #99)

  • Removed:
    • README-audit machinery: eng/readme-audit, the audit app, the top-500 audit runners, and the audit code in JitHub (same-byte resolvers, first-viewport probes, launch/auth audit hooks, audit automation probes)
    • evidence receipts and checkpoint JSON
    • investigation-only switches, probes and launch flags
    • source-text contract tests
    • the physical perf release workflow and its scripts
    • the live Sandbox touch and DPI runners
  • Split out to later PRs (still on the Complete MarkdownRenderer 1.0 native feature set #99 branch):
    • README fidelity: rst/adoc rendered HTML, the dedicated README endpoint and raw fallback
    • default-branch navigation
    • Store telemetry lazy init and the release Sandbox smoke
    • the task-coordinator lock
    • the WinApp CLI 0.7 migration of the app
    • the PersonPicture style move
    • JitHub.Web lock churn

Local verification (Release x64, SDK 10.0.403)

  • Renderer tests, 0 failures in each:

    Suite Passed
    GitHub.Tests 3120
    Tests 1483 (PerformanceExternalGateFixtureTests skipped locally; CI runs it)
    Svg.Resvg 749
    Mermaid 259
    Math 80
    TextMate 74
    Html 10
    Conformance 9
  • JitHub.WinUI.Tests: 3141 passed (Debug x64, as in CI).

  • App builds: Debug and Release builds of JitHub.WinUI pass, including the release security gate. The x64 NativeAOT publish and Verify-NativeAotArtifact pass.

  • Other builds and checks: the Sample, PerformanceHarness, Automation and PerformanceGate builds pass, and all 5 engineering script self-tests pass.

  • Binaries: the committed native binaries are byte-identical to Complete MarkdownRenderer 1.0 native feature set #99.

  • Not run locally: PixelTests (Edge headless times out on this machine), MSIX packaging, and the live Sandbox UI runners.

🤖 Generated with Claude Code

Xueyang-Song and others added 7 commits October 27, 2026 05:48
The native WinUI Markdown renderer: GFM parsing, layout and painting, selection and copy, accessibility, virtualized viewport, images, HTML subset, GitHub profile styling, and the package metadata.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Optional packs: native TeX math, Mermaid diagrams via committed merman DLLs, SVG and raster decode through isolated resvg worker processes (vendored crates pinned by provenance), and TextMate syntax highlighting with bundled grammars.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Behavior, conformance, pixel and pack test projects for the renderer and its feature packs, plus NativeAOT smoke apps that publish each pack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sample app and its automation helper used by the UI test scripts, the WinUI performance harness, and BenchmarkDotNet benchmarks used by the CI performance gates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Packaging, release-readiness and performance-gate scripts, the Windows Sandbox UI test runners and their self-tests, and the MarkdownRenderer preview CI workflow. The product performance gate now runs on push only for main, since pull requests already cover feature branches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JitHub renders README and Markdown previews with the new renderer and its packs: runtime and theme wiring, the viewer lifecycle, the leased image admission pipeline (Camo, raw CDN and Git LFS sources), SVG previews on resvg, NativeAOT dependency pins and notices, and host contract tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Architecture, API, feature-pack, testing, performance and release documentation for MarkdownRenderer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ublic API and structure checks (#104)

* Add code structure standards to AGENTS.md

Rules for project ownership, dependency direction, InternalsVisibleTo, public API tracking, file and class size, and test structure, so changes are reviewed against an explicit bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move MarkdownRenderer projects into src, tests, samples, perf and tools

Pure moves: shipping libraries to src/, tests to tests/ (AOT smoke apps to tests/aot/), the sample apps to samples/, the harness and benchmarks to perf/, and the conformance runner to tools/. Also removes 243 old SVG pixel-diff images that were committed into the Git-ignored artifacts folder. Path fixes follow in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Update paths for the new MarkdownRenderer layout

Fixes project references, linked items, workflow paths, scripts, runtime path lookups in tests and tools, and docs for the moved projects. Adds MarkdownRenderer.slnx with solution folders that mirror the disk layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Allow benchmark projects and an executable's own tests in the standards

Matches established .NET practice: microbenchmark projects may see internals, and an executable may be referenced by its own test project only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix resvg supply-chain policy path after the move

Generate-/Verify-ResvgSupplyChain.ps1 found the repository license policy relative to the provider's parent folder, which is now src/. Both scripts are listed inputs of the worker source fingerprint, so RESVG_WORKER_IDENTITY.json gets new source and build fingerprints computed by ResvgWorkerIdentity.psm1. The worker executables and their hashes are unchanged; CI rebuilds all three workers from source and compares them with the committed binaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Make every source file owned by the project that compiles it

- MarkdownRenderer.Core now physically holds the document model, engine,
  extensions, SourceSpan and MarkdownStyleRole instead of compiling them
  out of the WinUI project's folder. The WinUI project no longer removes
  them, and Core has one AssemblyInfo file.
- The 8 Performance files and the 3 SVG snapshot/budget files move into
  MarkdownRenderer.Performance and MarkdownRenderer.Svg.Resvg, the only
  assemblies that compiled them.
- GfmChildBuilder becomes one internal class in the WinUI renderer instead
  of two copies (Gfm and Html) behind an #if that switched its namespace.
  HtmlBlockRenderer and HtmlPreformattedTextProjection move into Html;
  AlertRenderer and FootnoteRenderer into GitHub.
- New perf/MarkdownRenderer.PerformanceHarness.Core holds the harness's
  WinUI-free measurement logic, referenced by the harness and the tests.
- New tests/MarkdownRenderer.Svg.Resvg.TestSupport holds raster fixtures
  shared by the resvg tests and its AOT smoke app.
- MarkdownRenderer.Tests references the real assemblies instead of
  compiling 112 product files with diagnostics forced on. Tests move to the
  project that owns their subject (resvg budget tests to Svg.Resvg.Tests,
  TextMate highlighter tests to TextMate.Tests, process-exit tests to a new
  Sample.Automation.Tests). Duplicate runs in GitHub.Tests are removed.
- JitHub.WinUI.Tests references the renderer instead of linking 10 of its
  files. Benchmarks reference the renderer instead of linking a file.
- Deleted SvgThemeInjector and RasterImageTilePlanner, which no shipping
  assembly compiled, with their 23 tests, and 11 tests of the sample app's
  link-routing glue.

Two links remain, each documented in its project file with a removal
plan: the TextMate grammar loader shared by both grammar packs, and the
harness performance listener compiled into GitHub.Tests. Both need a
public API decision (step 2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Share renderer build settings and pin package versions centrally

- MarkdownRenderer/Directory.Build.props imports the repository props
  instead of repeating the build-tools version, so the renderer follows
  the same lock-file, audit and locked-restore policy as the app.
- Folder props for src, tests, tests/aot, samples, perf and tools hold
  what each kind of project shares. Project files keep only what is
  unique to them (691 lines removed, 100 added).
- Directory.Packages.props turns on central package management with one
  version per package. WindowsAppSDK and its runtime are unified on
  1.8.260710003.
- Every renderer package ships as 1.0.0-preview.1. Html, Math and
  Mermaid were 0.1.0-preview.1.
- The package icon lives in MarkdownRenderer/assets instead of being
  taken from JitHub.Web.
- Shipping libraries treat warnings as errors, and the trim and AOT
  warnings fail every AOT-compatible library and smoke. Non-shipping
  projects are not packable.
- Removed a dead variable in MarkdownPerformanceSession that only
  compiled in the layout-diagnostics build.

Lock files change format (CPM writes v2 and marks centrally managed
indirect packages CentralTransitive). Resolved versions and hashes are
unchanged apart from the WindowsAppSDK unification and the Html version
bump. Packed nuspecs and file lists are identical apart from the
version change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Track the public API with PublicApiAnalyzers

- Every shipping assembly declares its public and protected surface in
  PublicAPI.Shipped.txt and PublicAPI.Unshipped.txt, checked by
  Microsoft.CodeAnalysis.PublicApiAnalyzers 5.6.0. Nothing has shipped,
  so every entry is unshipped. Undeclared, removed, duplicate and
  nullability-oblivious entries are errors (src/PublicApiAnalyzers
  .globalconfig), and a shipping project without the files fails the
  build (src/Directory.Build.targets).
- The generated files cover all 2,532 symbols of the old reflection
  baselines with the same modifiers, nullability, defaults and constant
  values, plus the 29 implicit struct constructors reflection missed.
- Removed the custom gate: PublicApiSurface.cs, PublicApiBaselineTests,
  StablePublicApiTests, the 12 baseline files and
  Update-PublicApiBaselines.ps1. Three theming behaviour tests from it
  moved to ThemingCompatibilityContractTests.
- New MarkdownRenderer.PublicApi.Tests checks the design rules the API
  files cannot express: no third-party or renderer-internal types in
  public signatures, readonly structs with default layout, sealed or
  static classes, paired IEquatable/Equals, unique resource keys. It
  uses only reflection over exported types. Binary compatibility beyond
  signatures is left to SDK package validation once a version ships
  (release checklist).
- RS0026 and RS0027 are suggestions until step 2 fixes the three Core
  constructors that break them.
- Removed the obj-*/bin-* DefaultItemExcludes from the repository and
  renderer props, five renderer projects and JitHub.WinUI.Tests. They
  only existed for the baseline script's separate output tree; builds
  that need one use ArtifactsPath.
- Removed the ManagedPacksOnly lane from GitHub.Tests. Nothing set it,
  and it existed only to Compile Remove 16 test files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Make renderer structure exceptions explicit and fail the build on new ones

- Every InternalsVisibleTo grant is an item in the owning project file.
  The eight AssemblyInfo.cs files that held only grants are deleted.
- Two unused grants are removed: Core to MarkdownRenderer.Conformance.Tests
  and Performance to JitHub.WinUI. Their grantees build without them, and
  the compiled assemblies differ from before only by these two attributes.
- Grants to an assembly that is not a .Tests or .Benchmarks project carry
  ProjectStructureException metadata with the reason and the step that
  removes them (public extension API in step 2, the PixelTests rename in
  step 6). So do the two remaining compile links, whose reasons move from
  comments into the metadata.
- MarkdownRenderer/Directory.Build.targets checks every renderer project
  before PrepareForBuild: MRS0001 fails on a Compile, Page or
  ApplicationDefinition item outside the project folder, MRS0002 on a grant
  to a non-test, non-benchmark assembly, unless the item declares an
  exception. Generated sources in the intermediate output and sources that
  NuGet packages add are skipped by path. Design-time builds skip the check.
- eng/Test-ProjectStructure.ps1 checks what one project build cannot see:
  no [assembly: InternalsVisibleTo] in source (MRS0003), no source folder
  without a project unless a declared exception compiles it (MRS0004), the
  solution lists every project and each entry exists (MRS0005, MRS0006),
  and exceptions name literal files (MRS0007). It runs first in the preview
  workflow; its self-test runs with the other engineering self-tests.
- testing-and-diagnostics.md describes the layout, both checks and the
  exception metadata.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Check central package versions in the release security gate

Verify-DependencySecurity.ps1 required a Version attribute on every
PackageReference, so the JitHub.WinUI Release build failed once the
renderer moved its versions to Directory.Packages.props. The gate now
checks each PackageVersion in every Directory.Packages.props with the
same floating and prerelease rules, accepts VersionOverride, and still
fails a PackageReference that has no version in the project or in the
central file above it.

The gate's nested test run also built JitHub.WinUI.Tests as AnyCPU: its
x64 default only applied to an empty Platform, but the SDK sets AnyCPU
first. Now that the tests reference the renderer, Win2D warned about
it. The default now covers AnyCPU, as the renderer props already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Give the TextMate AOT smoke the SDK build tools

The smoke reaches the Windows App SDK through the renderer, whose
self-contained manifest step runs mt.exe. Without the build-tools
package mt.exe had to be on PATH, so MarkdownRenderer.slnx only built
from a Developer PowerShell. The Svg.Resvg smoke already references the
package for the same reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…nsion and lifetime API (#105)

* Ship the engine, profiles and WinUI renderer as one MarkdownRenderer assembly

The WinUI layout walks the parser's Markdig syntax tree. With that tree
kept out of the public API, and no internals grants allowed between
shipping assemblies, Core and the renderer could not stay separate
assemblies. Gfm, GitHub, Html and Performance were renderer code in
their own DLLs, plugged in through internal types.

Core, Gfm, GitHub, Html and Performance now live in
src/MarkdownRenderer, in folders that match their namespaces.
Namespaces are unchanged. The package that ships MarkdownRenderer.dll
is now called MarkdownRenderer (it was MarkdownRenderer.WinUI), and the
dependency-only MarkdownRenderer package is gone. Packages drop from
14 to 8: MarkdownRenderer, the Math, Mermaid, resvg and TextMate packs,
the two grammar packs and MarkdownRenderer.All.

Consequences:
- Math and Mermaid reference the renderer package, so they pull in the
  Windows App SDK and Win2D. Their test projects reference the Windows
  App SDK runtime like the other renderer tests, and the Math, Mermaid
  and conformance executables reference the SDK build tools for mt.exe.
- Core.AotSmoke and ManagedPacks.AotSmoke covered the same assembly and
  are now one MarkdownRenderer.AotSmoke that runs both sets of checks.
- The performance harness no longer records a Core DLL hash.
- SafeHtmlFeature.PackageId and SafeHtmlCapabilityDescriptor.PackageId
  named a package that no longer exists and are removed.
- Tests that asserted which assembly a type lived in now assert the
  behavior instead, or are removed where the strict-GFM and GitHub
  registry tests already cover it.

Lock files are regenerated for the new project graph. No resolved
package version or hash changed; the only additions are the Windows App
SDK and Win2D packages, at their pinned versions, in the projects that
used to reference only Core.

The remaining internals grants are listed with reasons in the renderer
project and are removed by the next commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Give Math and Mermaid a public API for deferred scenes

Math and Mermaid read the internal MarkdownExtensionContext.
ShouldDeferOffscreenScenes and tagged their placeholders with an
undocumented "renderer.internal.deferred-scene" attribute. The renderer
kept its own copy of that string in four files, and each pack kept its
own marker counter.

The protocol is now public and documented:
- MarkdownExtensionContext.CanDeferOffscreenScenes says whether this
  render pass may emit a placeholder.
- MarkdownExtensionContext.CreateDeferredSceneMarker() returns a new
  marker, unique across the engine's documents and prefixed with the
  node kind, as the progressive scene plan expects. It throws when the
  pass cannot defer.
- MarkdownContentAttributes.DeferredScene is the attribute key, next to
  the other declarative attribute keys.

The attribute stays a plain attribute, so the progressive-scene tests
can still feed malformed markers to the renderer's defensive paths.
The Math and Mermaid internals grants are removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Remove the TextMate pack's compatibility helpers and internal hooks

The TextMate pack reached internal control and builder hooks
(SetOwnedCodeHighlighter, WithOwnedCodeHighlighterFactory) only from its
[Obsolete] compatibility overloads, which created and owned a highlighter
per view. Those overloads also found grammar packs by type name through
TextMateGrammarProviderFactory, which needed RequiresUnreferencedCode.

Removed:
- the six obsolete UseTextMateSyntaxHighlighting overloads,
- the parameterless TextMateCodeBlockSyntaxHighlighter constructor,
- TextMateGrammarProviderFactory,
- the control's owned-highlighter fields, transfer and retirement code,
  the builder's owned-highlighter factory, and
  OwnedCodeHighlighterAssignment, which only they used.

The three UseTextMateSyntaxHighlighting overloads that take an explicit
TextMateCodeBlockSyntaxHighlighter stay; the caller owns the highlighter.
Tests that only checked the removed members are removed, and the
highlighter tests construct CommonTextMateGrammarProvider directly. The
TextMate internals grant is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Update scripts, CI and docs for the single MarkdownRenderer package

- CI publishes MarkdownRenderer.AotSmoke with NativeAOT in place of the
  Core smoke, restoring it for the target RID because it now consumes
  the Windows App SDK. The package-consumption step tests only the
  MarkdownRenderer package, and the restore and pack lists name the
  eight shipping projects.
- Release, compliance, architecture and performance-gate scripts use
  the new package set. Math's release evidence expects one dependency,
  MarkdownRenderer, and the Math and Mermaid evidence scripts put mt.exe
  on PATH like the resvg script. The size-gate package lookup no longer
  treats every feature pack as a MarkdownRenderer package.
- The MarkdownRenderer managed-size budget is the measured DLL plus
  about 10%, the rule the other budgets follow. The GFM, GitHub, HTML and
  performance code it now holds never had a managed budget, so the
  earlier engine and viewer budget did not cover it.
- Docs describe one MarkdownRenderer package plus feature packs, with a
  decision note on why the renderer is one assembly. The deleted GitHub
  and Html package READMEs are folded into supported-markdown.md, and
  the AOT section no longer describes the removed grammar-pack discovery.
- The line-ending rule for the fingerprinted Primer CSS follows the
  files to their new folder.
- The standards in AGENTS.md describe the new dependency order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move the conformance harness and pixel tests to ordinary test projects

Both needed internals grants with exceptions:
- The conformance harness was an executable in tools/ that called the
  engine's internal spec-HTML oracle. It is test code, so it now lives in
  MarkdownRenderer.Conformance.Tests. Its command-line run over the
  official corpora is now an opt-in test (MARKDOWN_RENDERER_CONFORMANCE=1,
  Category=Conformance) that writes the same report. The tools folder is
  gone. All 1,322 official CommonMark and GFM examples pass.
- MarkdownRenderer.PixelTests is now MarkdownRenderer.Pixel.Tests, so its
  name ends in .Tests like every other test project.

The renderer grants both test projects internals without an exception.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Delete the obsolete members and make the renderer control an abstract base

Nothing has shipped, so a 1.0 should not start with [Obsolete] surface.

- MarkdownRendererControl was an obsolete class (MR1001) that apps could
  construct, and the base of MarkdownScrollView and MarkdownDocumentView.
  It is now an abstract base with a private protected constructor, so
  only the two views derive from it. MarkdownRendererControlBuilder.Build()
  is removed; BuildScrollView and BuildDocumentView remain. The MR1001
  suppressions in the renderer, tests, sample and app are gone.
- ICodeBlockSyntaxHighlighter, the CodeBlockSyntaxHighlighter property and
  dependency property, WithCodeBlockSyntaxHighlighter and the adapter
  that bridged them are removed. ICodeHighlighter now declares Revision
  itself, and CreateDefault takes an ICodeHighlighter.
- CodeBlockHighlightRequest no longer carries a cancellation token; the
  token is passed only to HighlightAsync. The TextMate highlighter drops
  its single-argument overload and the code that linked the two tokens,
  and still throws ObjectDisposedException after disposal.

The API test that allowed one reviewed inheritable class now checks the
rule itself: an exported class is sealed, static, or has no constructor
that code outside its assembly can call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Give the views a public disposal API and drop the app's internals grant

The JitHub app reached two internal members to shut a view down: the
DisposalCompleted event, to learn that Dispose had finished teardown,
and DrainRetiredSnapshotsAsync, to wait until the released Win2D
resources were freed. The sample used the same event. The library had
to name the app in an internals grant.

MarkdownRendererControl now implements IAsyncDisposable:
- DisposeAsync() disposes the view and returns a task that completes
  when the resources it released are freed, or faults if one could not
  be released. It throws when teardown did not finish, including after
  an earlier Dispose that failed part way, which a plain Dispose retry
  cannot report.
- The public Disposed event replaces the internal DisposalCompleted
  event, for teardown that the view's window starts.

The app feeds DisposeAsync into its existing retirement sequence and no
longer tracks the event; the sample's disposal evidence uses Disposed.
The JitHub.WinUI internals grant is removed, so the library no longer
names the app. One app test that asserts on source text is updated to
the new calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #108, which refreshed main's Native AOT lock files and the AOT
dependency ledger from 10.0.12 to 10.0.14. This branch had already
regenerated the same files for its new project layout at 10.0.14, so every
conflict resolves to this branch's side. Locked Native AOT restore (x64) and
Update-NativeAotDependencyLedger.ps1 -Verify pass on the merged tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#106)

The resvg pack plugged into the renderer through internal types in three
groups. Each is now public API in MarkdownRenderer.Images, and resvg
uses only public API.

Memory admission and render priority. These are optional capabilities
an IMarkdownSvgRenderer can implement; the views detect them:
- IMarkdownSvgAdmission (TryOpenAsync, WaitForCapacityAsync), so the
  view waits for capacity instead of failing an image when the provider
  is full.
- IMarkdownSvgPreparationAdmission and IMarkdownSvgPreparationLease,
  for PrepareSource scratch memory from the same capacity.
- IMarkdownSvgPrioritizedDocument and MarkdownSvgRenderDemand, so
  queued renders move ahead when their image scrolls into view. Only
  Priority and RegisterPromotion are public; the view creates and raises
  demands.
- MarkdownSvgAdmissionResult and MarkdownSvgAdmissionStatus.
The internal names said "host" (OpenForHostAsync, MarkdownSvgDemandTicket
and so on); the public names drop it.

Raster checks. MarkdownRasterImageInspection.Inspect applies the
renderer's own decode budget to encoded bytes without decoding them.
resvg uses it before sending WebP and SVG-embedded rasters to its
worker, instead of calling the renderer's internal budget parser.
MarkdownRasterFormat gains Ico, which the parser already recognized.

SVG source information. resvg reads an SVG's title, description and
root size during its own validation pass, which a test holds to at
least 30% fewer allocations than separate passes. It now does that with
the public MarkdownSvgSourceInfoReader and hands the result over with
MarkdownSvgSourcePreparation.Admit(bytes, info). The view's own fallback
uses the same collector, so there is still one implementation.

The opt-in layout-diagnostics build, which was already failing and is
not part of CI, still stops in resvg: its #if diagnostics blocks write
worker events into the renderer's internal event source and read its
correlation ID. Step 4 replaces those blocks.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Xueyang-Song and others added 5 commits October 29, 2026 10:17
…st (#110)

The sample app and the performance harness were the last projects that read
renderer internals through ProjectStructureException grants.

Sample: public API only.
- MarkdownTheme.ForcedContrastColors (MarkdownContrastColors) replaces the
  process-wide ThemeResolver.SystemThemeProviderOverride. Setting it raises
  the theme's Changed notification, so views restyle as for a Windows
  contrast switch.
- MarkdownRendererControl.RenderedContentSize and RenderedThemeVariant report
  what the view last displayed, which the sample's UI-test status and touch
  layout capture use as checks.
- The touch capture reads scroll position through the UI Automation scroll
  pattern.
- CodeBlockThemeVariant becomes MarkdownThemeVariant in Theming, shared by
  RenderedThemeVariant and CodeBlockHighlightRequest.ThemeVariant.

Performance harness: a white-box performance test.
- MRS0002 now allows grants only to the renderer's own projects at
  tests\<name>\<name>.csproj or perf\<name>\<name>.csproj, which never ship,
  instead of to any name ending in .Tests or .Benchmarks.
- PerformanceEventListener moves into PerformanceHarness.Core, which
  GitHub.Tests references instead of linking the harness's source file.
- The harness's measured code is unchanged, so results stay comparable with
  the existing baselines.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…th expose configuration only (#112)

* Give the sample public diagnostics and class the perf harness as a test

The sample app and the performance harness were the last projects that read
renderer internals through ProjectStructureException grants.

Sample: public API only.
- MarkdownTheme.ForcedContrastColors (MarkdownContrastColors) replaces the
  process-wide ThemeResolver.SystemThemeProviderOverride. Setting it raises
  the theme's Changed notification, so views restyle as for a Windows
  contrast switch.
- MarkdownRendererControl.RenderedContentSize and RenderedThemeVariant report
  what the view last displayed, which the sample's UI-test status and touch
  layout capture use as checks.
- The touch capture reads scroll position through the UI Automation scroll
  pattern.
- CodeBlockThemeVariant becomes MarkdownThemeVariant in Theming, shared by
  RenderedThemeVariant and CodeBlockHighlightRequest.ThemeVariant.

Performance harness: a white-box performance test.
- MRS0002 now allows grants only to the renderer's own projects at
  tests\<name>\<name>.csproj or perf\<name>\<name>.csproj, which never ship,
  instead of to any name ending in .Tests or .Benchmarks.
- PerformanceEventListener moves into PerformanceHarness.Core, which
  GitHub.Tests references instead of linking the harness's source file.
- The harness's measured code is unchanged, so results stay comparable with
  the existing baselines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* MarkdownRenderer structure step 2d: enforce optional-parameter overload rules, hide Mermaid and Math processors

Turn RS0026/RS0027 back into errors and fix what they find: one constructor
each for MarkdownVectorTextStyle, MarkdownStyleContext and MarkdownStyleSelector
with the role/ancestor qualifier as a trailing optional parameter, and explicit
MarkdownVectorScene overloads. The feature extension classes suppress the rules
at class level, and a new PublicApi test checks the property they rely on for
each receiver.

Mermaid and Math now expose only host configuration. The headless processors,
their results, diagnostics, scene formats and decoders become internal; Math
grants internal access to its tests and the benchmarks. The Mermaid and Math
NativeAOT smokes now render through UseMermaid/UseMathematics. EmbedVisibility
becomes internal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…hrough an engine package (#113)

* Give the sample public diagnostics and class the perf harness as a test

The sample app and the performance harness were the last projects that read
renderer internals through ProjectStructureException grants.

Sample: public API only.
- MarkdownTheme.ForcedContrastColors (MarkdownContrastColors) replaces the
  process-wide ThemeResolver.SystemThemeProviderOverride. Setting it raises
  the theme's Changed notification, so views restyle as for a Windows
  contrast switch.
- MarkdownRendererControl.RenderedContentSize and RenderedThemeVariant report
  what the view last displayed, which the sample's UI-test status and touch
  layout capture use as checks.
- The touch capture reads scroll position through the UI Automation scroll
  pattern.
- CodeBlockThemeVariant becomes MarkdownThemeVariant in Theming, shared by
  RenderedThemeVariant and CodeBlockHighlightRequest.ThemeVariant.

Performance harness: a white-box performance test.
- MRS0002 now allows grants only to the renderer's own projects at
  tests\<name>\<name>.csproj or perf\<name>\<name>.csproj, which never ship,
  instead of to any name ending in .Tests or .Benchmarks.
- PerformanceEventListener moves into PerformanceHarness.Core, which
  GitHub.Tests references instead of linking the harness's source file.
- The harness's measured code is unchanged, so results stay comparable with
  the existing baselines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* MarkdownRenderer structure step 2d: enforce optional-parameter overload rules, hide Mermaid and Math processors

Turn RS0026/RS0027 back into errors and fix what they find: one constructor
each for MarkdownVectorTextStyle, MarkdownStyleContext and MarkdownStyleSelector
with the role/ancestor qualifier as a trailing optional parameter, and explicit
MarkdownVectorScene overloads. The feature extension classes suppress the rules
at class level, and a new PublicApi test checks the property they rely on for
each receiver.

Mermaid and Math now expose only host configuration. The headless processors,
their results, diagnostics, scene formats and decoders become internal; Math
grants internal access to its tests and the benchmarks. The Mermaid and Math
NativeAOT smokes now render through UseMermaid/UseMathematics. EmbedVisibility
becomes internal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* MarkdownRenderer structure step 2e: share the TextMateSharp adapter through an engine package

Move the TextMateSharp-backed grammar provider that Grammars.Common and
Grammars.All compiled from one linked source file into a new shipping package,
MarkdownRenderer.SyntaxHighlighting.TextMate.Engine, as the public
TextMateSharpGrammarProvider. Both packs reference it, and no file link or
ProjectStructureException remains.

The engine is the one package whose public API names TextMateSharp types; the
forbidden-contract test allows that for this assembly only and fails if the
exception stops being needed. Wire the ninth package into both solutions, CI
restore and pack lists, the release package set, the managed-architecture map,
the TextMate release evidence (dependency rules and the Common selected-RID
payload), the compliance self-tests, the app security gate test, lock files
and the packaging docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
HealthyBusySnapshotIsRetryableAndDoesNotClaimRecovery queued its blocking
measure on the thread pool and gave it 2 s to start. In CI's parallel
GitHub testhost the pool can be saturated for longer, so the handshake
timed out before the snapshot was ever busy.

The measure now runs on a LongRunning task, which gets its own thread.
The file's 2 s waits were hang guards, not deadlines under test, so they
share one 30 s HangGuard. Every assertion is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps the integration branch's removal of SkiaSharp and Svg.Skia from JitHub.WinUI.Tests and adds main's Microsoft.Extensions.TimeProvider.Testing reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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