Meziantou.Framework.WebPlatform 1.0.10

Prefix Reserved
dotnet add package Meziantou.Framework.WebPlatform --version 1.0.10
                    
NuGet\Install-Package Meziantou.Framework.WebPlatform -Version 1.0.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Meziantou.Framework.WebPlatform" Version="1.0.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Meziantou.Framework.WebPlatform" Version="1.0.10" />
                    
Directory.Packages.props
<PackageReference Include="Meziantou.Framework.WebPlatform" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Meziantou.Framework.WebPlatform --version 1.0.10
                    
#r "nuget: Meziantou.Framework.WebPlatform, 1.0.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Meziantou.Framework.WebPlatform@1.0.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Meziantou.Framework.WebPlatform&version=1.0.10
                    
Install as a Cake Addin
#tool nuget:?package=Meziantou.Framework.WebPlatform&version=1.0.10
                    
Install as a Cake Tool

Meziantou.Framework.WebPlatform

A spec-compliant, high-performance implementation of the web platform for .NET. It parses HTML, XML, SVG, MathML and CSS exactly as a browser does, and exposes the browser DOM API (the WebIDL surface of the WHATWG and W3C specifications) with .NET naming: queries (QuerySelector, XPath, live collections), mutations, events, the CSSOM and the computed styles, forms, custom elements, accessibility, and more. A managed layout engine computes the geometry exposed by the web APIs (CSSOM View, the observers...), and the documents are painted into a display list that a rendering backend (a managed rasterizer, in a separate package) rasterizes for the screenshots and the canvases. Documents can be loaded in a browsing context that fetches their resources over the network and runs their scripts with a pluggable JavaScript engine (Meziantou.Framework.JavaScriptEngine is provided).

Every public member mapping a WebIDL member is annotated with [IdlMember(name, specUrl)]. The WebIDL names follow the .NET naming guidelines: acronyms of 3 letters or more are PascalCased and acronyms of 2 letters stay upper case (HTMLElement.innerHTML → HtmlElement.InnerHtml, toJSON → ToJson, CDATASection → CDataSection, UIEvent and HTMLBRElement → HtmlBRElement). MathML and XPath keep their casing.

Examples

Parse HTML, query the nodes and the styles

HtmlDocumentParser is in the Meziantou.Framework.WebPlatform namespace, and the DOM types (BrowsingContext, Document, HtmlAnchorElement...) are in Meziantou.Framework.WebPlatform.Dom.

var document = HtmlDocumentParser.ParseDocument("""
    <style>.important { color: red; font-weight: bold }</style>
    <ul>
      <li><a href="https://example.com/a" class="important">A</a>
      <li><a href="/b" style="color: blue">B</a>
    </ul>
    """);

// CSS selectors, with typed overloads and LINQ
var links = document.QuerySelectorAll<HtmlAnchorElement>("li > a");
var external = links.Where(a => a.Href.StartsWith("https:", StringComparison.Ordinal)).Select(a => a.TextContent);
var first = document.GetElementsByTagName("li")[0];
Assert.Equal(["A"], external);
Assert.Same(first, links[0].ParentElement);

// XPath
var result = document.Evaluate("//a[@class='important']", document, type: XPathResult.FirstOrderedNodeType);
var important = (Element?)result.SingleNodeValue;
Assert.Equal("A", important?.TextContent);

// Inline style (style attribute)
var color = links[1].Style.GetPropertyValue("color");
Assert.Equal("blue", color);

The computed styles (cascade of the style sheets, inheritance, media queries) need a browsing context, which provides the window and the viewport:

var html = """
    <style>.important { color: red; font-weight: bold }</style>
    <p class="important">Hello</p>
    """;

using var context = new BrowsingContext(new BrowsingContextOptions
{
    Viewport = new ViewportOptions { Width = 1280, Height = 720 }, // optional, 800x600 by default
});

var document = context.Navigate("https://example.com/", _ => html);
var style = context.Window.GetComputedStyle(document.QuerySelector(".important")!);
Assert.Equal("rgb(255, 0, 0)", style.Color);
Assert.Equal("700", style.GetPropertyValue("font-weight"));

See docs/dom-helpers.md, docs/selectors.md, docs/computed-style.md and docs/css-typed-om.md.

Update the DOM

The formatters are in the Meziantou.Framework.WebPlatform.Formatting namespace.

var document = HtmlDocumentParser.ParseDocument("""
    <ul>
      <li><a href="/a">A</a>
      <li><a href="/b">B</a>
    </ul>
    """);
var list = document.QuerySelector("ul")!;

// Create elements
var item = document.CreateElement<HtmlLIElement>();
var link = document.CreateElement<HtmlAnchorElement>();
link.Href = "/c";
link.TextContent = "C";
link.ClassList.Add("important");
link.SetAttribute("data-id", "3");
item.Append(link);
list.Append(item);

// Parse markup into an element, edit the styles, remove nodes
list.InsertAdjacentHtml("beforeend", "<li><a href=/d>D</a>");
link.Style.SetProperty("text-decoration", "underline");
document.QuerySelector("a[href='/b']")?.Remove();

// Serialize the document
var html = document.GetHtml();
var indented = document.ToHtml(new HtmlPrettyFormatter());
var minified = document.ToHtml(new HtmlMinifyFormatter());
Assert.StartsWith("<html><head></head><body><ul>", html, StringComparison.Ordinal);
Assert.Equal("""
    <html>
      <head></head>
      <body>
        <ul>
          <li>
            <a href="/a">A</a>
          </li>
          <li></li>
          <li>
            <a href="/c" class="important" data-id="3" style="text-decoration: underline;">C</a>
          </li>
          <li>
            <a href="/d">D</a>
          </li>
        </ul>
      </body>
    </html>
    """, indented);
Assert.Equal("""<ul><li><a href=/a>A</a><li><li><a href=/c class=important data-id=3 style="text-decoration: underline;">C</a><li><a href=/d>D</a></ul>""", minified);

Element.SetHtml() and Document.ParseHtml() insert untrusted markup with the HTML Sanitizer API. See docs/html-formatting.md and docs/css-formatting.md for the serialization options.

Allow network requests

Nothing is fetched unless a DocumentLoader is configured. With a loader, the browsing context loads the documents of the navigations and the iframe elements, the style sheets (<link rel=stylesheet>, @import), the images and, when a script engine is configured, the scripts:

using var context = new BrowsingContext(new BrowsingContextOptions
{
    DocumentLoader = DocumentLoader.Create(),  // HTTP GET requests with a shared HttpClient (or pass your own)
    CookieJar = new CookieJar(),               // optional: the cookies (RFC 6265bis, document.cookie, cookieStore)
});

context.Navigate("https://example.com/");
await context.EventLoop.RunUntilIdleAsync(); // runs the tasks until the document and its resources are loaded

var document = context.Document;

DocumentLoader.Create() requests any URL. A custom loader can filter the requests (to prevent server-side request forgery with untrusted documents), serve them from a cache or from the disk:

internal sealed class SameHostLoader(string host) : DocumentLoader
{
    private static readonly DocumentLoader Http = DocumentLoader.Create();

    public override ValueTask<DocumentResource?> LoadAsync(DocumentRequest request, CancellationToken cancellationToken)
    {
        if (new Uri(request.Url).Host != host)
            return ValueTask.FromResult<DocumentResource?>(null); // network error

        return Http.LoadAsync(request, cancellationToken);
    }
}

See docs/browsing-context.md.

Execute scripts

Scripts only run when a JavaScript engine is plugged into the browsing context. The Meziantou.Framework.WebPlatform.JavaScript package provides one, based on Meziantou.Framework.JavaScriptEngine, in the Meziantou.Framework.WebPlatform.JavaScript namespace:

using var engine = new JavaScriptScriptEngine(new JavaScriptScriptEngineOptions
{
    Timeout = TimeSpan.FromSeconds(5), // per script or callback
});

using var context = new BrowsingContext(new BrowsingContextOptions
{
    ScriptEngine = engine,
    DocumentLoader = DocumentLoader.Create(), // optional: external scripts, modules, fetch, XMLHttpRequest, WebSocket, EventSource...
    UnhandledScriptError = (_, error) => Console.Error.WriteLine(error),
    ConsoleMessage = (_, message) => Console.WriteLine(message.Text), // console.log(), console.count()...
});

var document = await context.NavigateAsync("https://example.com/", _ => """
    <title>Example</title>
    <ul id=list></ul>
    <script>
      setTimeout(() => document.getElementById('list').innerHTML = '<li>a<li>b', 100);
    </script>
    """);

// Run the tasks and the timers until there is nothing left
do { await context.EventLoop.RunUntilIdleAsync(); } while (await context.EventLoop.WaitForNextTimerAsync());

Assert.Equal("<li>a</li><li>b</li>", document.GetElementById("list")!.InnerHtml);

// Evaluate code in the realm of a window
var title = engine.Evaluate(context.Window, "document.title");
Assert.Equal("Example", title.AsString());

The scripts run in the process: read the threat model in docs/scripting.md before running untrusted documents.

Take screenshots

The documents are painted by the library into a backend-agnostic display list; the Meziantou.Framework.WebPlatform.Imaging package draws them, and decodes and encodes the images, with Meziantou.Framework.Imaging, a fully managed library (no native dependency: the same pixels on every platform). ImagingRenderingBackend and the screenshot methods are in the Meziantou.Framework.WebPlatform.Imaging namespace:

using var context = new BrowsingContext(new BrowsingContextOptions
{
    Viewport = new ViewportOptions { Width = 1280, Height = 720, DevicePixelRatio = 2 },
    DocumentLoader = DocumentLoader.Create(),
    RenderingBackend = new ImagingRenderingBackend(),
});

context.Navigate("https://example.com/");
await context.EventLoop.RunUntilIdleAsync();

await File.WriteAllBytesAsync("page.png", context.TakeScreenshotAsPng());            // the viewport: 2560x1440 pixels
using var title = context.Document.QuerySelector("h1")!.TakeScreenshot();           // an element, as an Image<Rgba32>

// Print the document: the print media type, the @page rules, one image per page
var pages = context.RenderPagesAsPng(new PrintOptions { PageWidth = 794, PageHeight = 1123 }); // A4 at 96 dpi

See docs/rendering.md for what is painted, and Printing for the pages.

Limitations

The limitations of the library are listed in the documentation.

Specifications

Area Specification Status
Encoding WHATWG Encoding Done
URL WHATWG URL, UTS #46 Done
URL Pattern URL Pattern Done (UrlPattern; the patterns are compiled to .NET regular expressions with the semantics of the ECMAScript v flag, the Unicode property escapes of the custom groups are limited to the General_Category values; tentative compareComponent() and generate() are experimental)
HTML parsing WHATWG HTML Done (the encoding declared by a <meta> element is found by tokenizing the head, as the browsers do and as proposed by whatwg/html#6962, rather than by the prescan of the first 1024 bytes; a <meta> element of the head after the first 1024 bytes changes the encoding when the parser inserts it, without the re-parse of the specification; the encoding of a document that does not declare it is detected from its content by a port of chardetng, the detector of Firefox, see Encoding detection)
HTML serialization WHATWG HTML Done (innerHTML, outerHTML, getHTML(); Document.GetHtml() and Document.WriteHtml(TextWriter) serialize a whole document)
HTML formatting WHATWG HTML Done (Node.ToHtml(HtmlFormatter): minified output, pretty printing and custom formatters): see docs/html-formatting.md
CSS formatting CSSOM Done (CssStyleSheet.ToCss(CssFormatter), CssRule.ToCss, CssStyleDeclaration.ToCss: minified output, pretty printing and custom formatters): see docs/css-formatting.md
DOM WHATWG DOM Done (LINQ helpers: tree walks, typed queries, CreateElement<T>()): see docs/dom-helpers.md
Selectors Selectors Level 4, CSS Syntax Done (read-only selector object model: SelectorList.Parse, CssStyleRule.Selectors, specificity, matching with a parsed selector): see docs/selectors.md
XML, DOMParser, XMLSerializer HTML XML syntax, DOM Parsing Done
DOM XPath DOM over System.Xml.XPath Done
HTML element interfaces, reflection WHATWG HTML Done
SVG and MathML element interfaces SVG 2, SVG Paths, Filter Effects, Geometry, MathML Core Done (path data API: getPathData, setPathData; the length of the paths is computed from the d property, which maps the d attribute; getBBox(), the text layout, the transforms and the hit testing are computed from the geometry: see docs/layout.md and docs/computed-style.md)
Forms WHATWG HTML, XHR FormData Done (the submission navigates the target browsing context, with the DocumentLoader for the network requests; no user interaction states)
CSS syntax, CSSOM CSS Syntax, CSSOM, CSS Values, CSS Color Done (the style sheets of <link rel=stylesheet>, of the @import rules and of the xml-stylesheet processing instructions are fetched by the DocumentLoader)
CSS Typed OM CSS Typed OM Done (attributeStyleMap, styleMap, computedStyleMap(), the numeric, keyword, unparsed, transform, image and color values; the colors of the properties are not reified, like in the browsers): see docs/css-typed-om.md
CSS Parser API CSS Parser API (WICG draft) Done on the parser of CSS Syntax (CSS.parseStylesheet(), parseRule(), parseDeclaration(), parseValue()..., the CSSParser* objects; the draft's inconsistent types follow CSS Syntax; can be hidden from the scripts): see docs/css-parser-api.md
Cascade, computed style CSS Cascade, Media Queries, CSSOM, CSS Mixins (custom functions), CSS Color Adjustment (color schemes, forced colors mode) Done (getComputedStyle with the layout-dependent resolved values from the layout, innerText; the :visited links with a history provided by the application, painted only): see docs/computed-style.md
Layout, CSSOM View CSS 2, CSS Display, CSS Flexbox, CSS Grid, CSS Grid 3 (grid lanes), CSS Gap Decorations, CSS Tables, CSS Ruby, CSS Text, CSS Writing Modes, CSS Paged Media, CSS Anchor Positioning, CSSOM View, Resize Observer, Intersection Observer Done (internal layout engine exposed through the web APIs, the user input and the printing): see docs/layout.md
Rendering CSS Backgrounds, Filter Effects, CSS Masking, SVG 2, HTML canvas, Paint Timing Opt-in (a backend-agnostic display list rasterized by the Meziantou.Framework.WebPlatform.Imaging package: screenshots, 2D canvases, image decoding): see docs/rendering.md
Animations Web Animations, CSS Animations, CSS Transitions Done (Element.animate(), getAnimations(), the CSS animations and transitions in the computed styles, their events; the animations follow the clock of the event loop; the scroll and view timelines of Scroll-driven Animations follow the scroll positions; no animation triggers), and the SVG animations (SMIL: animate, set, animateMotion, animateTransform, the timing model, animVal, the timing events): see docs/animations.md
View transitions CSS View Transitions 1, 2 Done for the transitions of a document (document.startViewTransition(), ViewTransition, the ::view-transition-*() pseudo-element tree with its user agent style sheet and animations, the snapshots rasterized by the rendering backend, the transition types, view-transition-class, the nested groups), for the scoped transitions (element.startViewTransition(), element.activeViewTransition, view-transition-scope, the pseudo-element tree painted above the contents of its root element, the rendering paused within it) and for the cross-document transitions (@view-transition, pageswap, pagereveal, revealed once the document is not render-blocked): see docs/view-transitions.md
Compatibility WHATWG Compatibility Done (the -webkit- prefixed properties, keywords, gradients, at-rules and media features; -webkit-gradient(); the legacy -webkit-box is laid out as a flex container; window.orientation is not exposed, as in the desktop browsers)
Accessibility WAI-ARIA, HTML-AAM, Accessible Name Done (Element.ComputedRole, Element.ComputedName): see docs/accessibility.md
Media elements WHATWG HTML Done on top of a media backend provided by the application (audio, video, source, resource selection, events, playback state, TimeRanges, audio and video tracks, media documents, and the Media Source Extensions: MediaSource, SourceBuffer, ManagedMediaSource, in the windows and the dedicated workers): see docs/browsing-context.md. Not done: the controls
Web Audio Web Audio API Partial (AudioContext and OfflineAudioContext, the nodes of the graph, the automation of the parameters, AudioWorklet, decodeAudioData() of WAV and FLAC files; rendered without audio device on the event loop of the window, at the pace of its clock for an AudioContext): see docs/web-audio.md. Not done: MediaElementAudioSourceNode and the MediaStream nodes
Text tracks and WebVTT WHATWG HTML, WebVTT Done (track, TextTrack, VTTCue, VTTRegion, the WebVTT parsers, the cue events, the rendering of the cues over the videos, ::cue, ::cue(), ::cue-region, :past, :future): see docs/browsing-context.md. Not done: the user preferences for the track selection, the animation of the scrolling regions
HTML Sanitizer API WHATWG HTML Done (setHTML, parseHTML, Sanitizer)
HTML insertion methods, partial updates WHATWG HTML (<template for>, HTML insertion methods), proposal whatwg/html#12758 Done (appendHTML(), beforeHTML()... and the streaming methods streamAppendHTMLUnsafe()..., the tentative buffer, sanitize and src attributes of <template for>; no in-place <template for="">): see docs/partial-updates.md
Trusted Types Trusted Types Done (enforcement is opt-in): see docs/trusted-types.md
Selection API Selection API Done (modify() moves the selection over the layout; the selection also changes with the caret movement keys of the editable content, not with the pointer; toString() returns the rendered text of the range)
Custom elements WHATWG HTML (CustomElementRegistry, ElementInternals, form-associated custom elements, :state()) Done (the elements are defined with .NET constructors): see docs/custom-elements.md
Popover API, invoker commands WHATWG HTML Done (focus, light dismiss and close requests are processed for the events dispatched by the library or the scripts: there is no user input)
Text directives URL Fragment Text Directives Done (#:~:text=, ::target-text, document.fragmentDirective, the user activation and cross-origin restrictions, force-load-at-top; the collation of the locale is not used): see docs/browsing-context.md
Fullscreen API Fullscreen Done (requestFullscreen(), exitFullscreen(), fullscreenElement, the events of the rendering update, :fullscreen, the top layer and ::backdrop, the fullscreen permissions policy feature, the keyboard lock of the Escape key; nothing is displayed: the host resizes the viewport with BrowsingContextOptions.EnterFullscreen): see docs/browsing-context.md
Pointer Lock API Pointer Lock Done (requestPointerLock(), exitPointerLock(), pointerLockElement, pointerlockchange and pointerlockerror, movementX and movementY, the events of the locked mouse; the host locks its pointer with BrowsingContextOptions.RequestPointerLock): see docs/browsing-context.md
Web Locks Web Locks API Done (navigator.locks in the windows and the workers, request() with the modes, ifAvailable, steal and signal, query(), the lock managers per storage key of a browsing context group, partitioned for the third-party contexts, the release when a document or a worker is discarded): see docs/browsing-context.md
Deferred fetching Fetch Done (fetchLater() and FetchLaterResult: the requests are sent when the document is destroyed or after activateAfter, the quota shared by the documents of an origin and delegated to the cross-origin frames by the deferred-fetch and deferred-fetch-minimal policy-controlled features; no back/forward cache): see docs/browsing-context.md
Storage manager Storage Done (navigator.storage in the windows and the workers: estimate() from the usage that the storage backends report, persisted(), persist() answered by the host; no storage buckets): see docs/browsing-context.md
Origin private file system File System Done (getDirectory(), the file and directory handles, the async iteration, FileSystemWritableFileStream, FileSystemSyncAccessHandle in the dedicated workers, the locks, the serialization of the handles, move() and remove(), on a delegated FileSystemBackend; no FileSystemObserver): see docs/browsing-context.md
Prioritized Task Scheduling Prioritized Task Scheduling Done (scheduler.postTask(), scheduler.yield(), TaskController, TaskSignal, TaskSignal.any(), the priorities in the event loop, in the windows and the workers; the scheduling state is not propagated by the await of a promise that another task settles: it is not attached to the promise jobs yet): see docs/browsing-context.md
Idle callbacks requestIdleCallback() Done (requestIdleCallback(), cancelIdleCallback(), IdleDeadline, the idle periods of the event loop, the timeouts): see docs/browsing-context.md
Permissions Permissions Done (navigator.permissions.query() in the windows and the workers, PermissionStatus and its change event, the permission store of the browsing context, the permission prompts answered by BrowsingContextOptions.RequestPermission; request() and revoke() are not implemented): see docs/browsing-context.md
Web Share, Vibration Web Share API, Vibration API Done (navigator.share(), navigator.canShare() and navigator.vibrate(), answered by the host with BrowsingContextOptions.Share and BrowsingContextOptions.Vibrate): see docs/browsing-context.md
Geolocation Geolocation Done (navigator.geolocation with the timeouts, the cached positions and the watches, on a GeolocationProvider set by the host; no accuracyMode): see docs/browsing-context.md
Notifications Notifications API Partial (Notification in the windows and the workers, requestPermission(), the tags and the events, displayed by the host with BrowsingContextOptions.ShowNotification; no persistent notifications nor actions): see docs/browsing-context.md
Badging, Battery Status Badging API, Battery Status API Done (navigator.setAppBadge() and clearAppBadge() in the windows and the workers, shown by the host with BrowsingContextOptions.Badging; navigator.getBattery() and BatteryManager with its events, on a BatteryStatusProvider set by the host): see docs/browsing-context.md
Screen Wake Lock, Keyboard Lock Screen Wake Lock API, Keyboard Lock Done (navigator.wakeLock and WakeLockSentinel, released when the document is hidden, with BrowsingContextOptions.WakeLock; navigator.keyboard.lock() and unlock() with BrowsingContextOptions.KeyboardLock): see docs/browsing-context.md
Keyboard Map, Media Session Keyboard Map, Media Session Done (navigator.keyboard.getLayoutMap() and layoutchange, on a KeyboardLayoutProvider set by the host, US QWERTY by default; navigator.mediaSession and MediaMetadata, reported to the host with BrowsingContextOptions.MediaSession, which triggers the actions; the artwork is not fetched): see docs/browsing-context.md
Page Lifecycle, Document Policy Page Lifecycle, Document Policy Partial (BrowsingContext.IsFrozen and Discard(), the freeze and resume events, wasDiscarded, the frozen documents of the back/forward cache and of the hidden iframes; the dedicated workers are not blocked. The document policy headers, Sec-Required-Document-Policy and the iframe policy attribute, with the sync-xhr and force-load-at-top features): see docs/browsing-context.md
Sensors, Device orientation Generic Sensor API, Accelerometer, Gyroscope, Magnetometer, Ambient Light Sensor, Orientation Sensor, Proximity Sensor, DeviceOrientation Event Done (the sensor objects, with the permissions, the frequencies, the quantization and the visibility and focus rules, and the deviceorientation, deviceorientationabsolute and devicemotion events, read from a DeviceSensorProvider set by the host with BrowsingContextOptions.Sensors): see docs/browsing-context.md
Network Information, Device Memory, Global Privacy Control Network Information API, Save Data API, Device Memory, GPC Done (navigator.connection with its change event, on a NetworkInformationProvider set by the host; navigator.deviceMemory and saveData from BrowsingContextOptions.ClientHints; navigator.globalPrivacyControl and the Sec-GPC header with BrowsingContextOptions.GlobalPrivacyControl): see docs/browsing-context.md
Clear-Site-Data Clear Site Data Done (the HTTP cache, the back/forward cache, the cookies, the local and session storage, IndexedDB, the Cache API, the service worker registrations, the client hints, the speculative loads and the reload of the documents; only the partitioned data in a third-party context; no origin private file system): see docs/browsing-context.md
Compute Pressure, Idle Detection, Device Posture Compute Pressure, Idle Detection API, Device Posture API Done (PressureObserver in the windows and the workers, on a PressureSourceProvider set by the host, with the sample interval and the focus rules, no rate obfuscation; IdleDetector on an IdleStateProvider; navigator.devicePosture and the device-posture media feature on a DevicePostureProvider): see docs/browsing-context.md
Screen Orientation, VirtualKeyboard, Viewport segments Screen Orientation, VirtualKeyboard API, CSS Viewport Done (screen.orientation with lock() and unlock() on a ScreenOrientationProvider set by the host; navigator.virtualKeyboard and the keyboard-inset-* variables, with BrowsingContextOptions.VirtualKeyboard; viewport.segments, the *-viewport-segments media features and the viewport-segment-* variables from the display features of a DisplayFeaturesProvider; the viewport is not resized by a rotation nor by the keyboard): see docs/browsing-context.md
Performance timeline Performance Timeline, Resource Timing, Navigation Timing, User Timing, Event Timing, Server Timing, Long Tasks API Done (performance and PerformanceObserver in the windows and the workers, the resource, navigation, mark, measure, event, first-input and longtask entries, the Server-Timing metrics, measured with the clock of the event loop; the long tasks are the tasks that run scripts; no Long Animation Frames): see docs/browsing-context.md
Early detection of input events isInputPending() Done (navigator.scheduling.isInputPending(), answered by the host with BrowsingContextOptions.PendingInput; false by default): see docs/browsing-context.md
Close watchers WHATWG HTML Done (CloseWatcher, the close watcher manager shared with the dialogs, the popovers and the pickers of the select elements; the close request is the Escape key): see docs/browsing-context.md
Editing, drag and drop WHATWG HTML, execCommand, Drag and drop Partial (editing hosts, designMode, the delete, forwardDelete, insertText and selectAll commands, hidden=until-found; DataTransfer and the drag-and-drop processing model, driven by the host with DragAndDropOperation): see docs/browsing-context.md
Browsing contexts WHATWG HTML (Window, iframe, Location, History) Opt-in (nested documents, navigations, window.open(), focus; the resources are fetched only with a DocumentLoader): see docs/browsing-context.md
Client Hints Client Hints Infrastructure, User-Agent Client Hints Done (the Accept-CH cache, the Sec-CH-* request headers with the values of BrowsingContextOptions.ClientHints and of the viewport, their delegation with the permissions policy and <meta http-equiv="delegate-ch">, the Critical-CH restarts and navigator.userAgentData; the requests of the workers have no hint): see docs/browsing-context.md
Scripting WHATWG HTML (script elements, event handlers, javascript: URLs, timers, error reporting) Opt-in: a JavaScript engine is plugged into the browsing contexts (Meziantou.Framework.WebPlatform.JavaScript for Meziantou.Framework.JavaScriptEngine), with module scripts and import maps: see docs/scripting.md
Speculation rules WHATWG HTML, Prefetch, Prerendering Done (<script type="speculationrules"> and the Speculation-Rules header, list and document rules, eagerness with the pointer of the user, navigational prefetches used by the navigations, prerendering traversables activated by the navigations, document.prerendering, prerenderingchange, activationStart: see docs/browsing-context.md); the workers and the media elements of a prerendering document are not suspended
Worklets, CSS Painting API, CSS Layout API, Animation Worklet WHATWG HTML, CSS Painting API, CSS Layout API, CSS Animation Worklet API Done with a script engine that supports the module scripts (Worklet.addModule(); CSS.paintWorklet, registerPaint(), PaintRenderingContext2D and the paint() images, which need a rendering backend; CSS.layoutWorklet, registerLayout() and the display: layout() boxes, without fragmentation by the layout; CSS.animationWorklet, registerAnimator() and WorkletAnimation: see docs/scripting.md, docs/rendering.md, docs/layout.md and docs/animations.md); the global scopes of a worklet are realms of the script engine of the document. The audio worklet is part of Web Audio
Web Cryptography Web Cryptography API, Secure Curves, Modern Algorithms Done (implemented in JavaScript in the WebIDL bindings, with managed primitives; no SLH-DSA): see docs/scripting.md
WebAssembly WebAssembly JavaScript Interface, Web API Opt-in: a WebAssembly runtime is plugged into the browsing contexts (Meziantou.Framework.WebPlatform.Wasmtime for Wasmtime, WebAssembly 3.0 without the threads): see docs/scripting.md
Streams WHATWG Streams, TextEncoderStream, TextDecoderStream, Blob.stream(), WHATWG Compression (CompressionStream, DecompressionStream) Done (implemented in JavaScript in the WebIDL bindings; streams cannot be transferred): see docs/scripting.md

Building

./eng/webplatform/fetch-tests.sh
dotnet test --project tests/Meziantou.Framework.WebPlatform.Tests
dotnet test --project tests/Meziantou.Framework.WebPlatform.Imaging.Tests
dotnet test --project tests/Meziantou.Framework.WebPlatform.Wpt

The web-platform-tests (testharness.js tests and reftests, the reftests being rendered by the Imaging backend) run with the script engine of Meziantou.Framework.WebPlatform.JavaScript: see docs/web-platform-tests.md.

See docs/updating-specs.md to update the specification data, docs/fuzzing.md to fuzz the parsers, and docs/performance.md for the benchmarks.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed.  net11.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (8)

Showing the top 5 NuGet packages that depend on Meziantou.Framework.WebPlatform:

Package Downloads
Meziantou.Framework.HtmlSanitizer

Provide helpers to sanitize HTML fragment

Meziantou.Framework.HtmlToMarkdown

Convert HTML fragments to Markdown

Meziantou.Framework.HumanReadableSerializer.Html

Formats the HTML values (text/html) serialized by Meziantou.Framework.HumanReadableSerializer, using the spec-compliant HTML parser of Meziantou.Framework.WebPlatform

Meziantou.Framework.WebPlatform.Imaging

Rasterizes the documents of Meziantou.Framework.WebPlatform with the fully managed drawing API of Meziantou.Framework.Imaging (a RenderingBackend): screenshots of the pages and of the elements, 2D canvases, image decoding and encoding.

Meziantou.Framework.WebPlatform.JavaScript

Runs the scripts of the documents of Meziantou.Framework.WebPlatform with Meziantou.Framework.JavaScriptEngine (a ScriptEngine with the WebIDL bindings of the DOM).

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.10 0 11/8/2026
1.0.9 115 11/5/2026
1.0.8 116 11/1/2026
1.0.7 111 10/31/2026
1.0.6 115 10/31/2026
1.0.5 243 10/28/2026
1.0.4 230 10/25/2026
1.0.3 223 10/25/2026
1.0.2 123 10/24/2026
1.0.1 138 10/21/2026
1.0.0 181 10/18/2026