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
<PackageReference Include="Meziantou.Framework.WebPlatform" Version="1.0.10" />
<PackageVersion Include="Meziantou.Framework.WebPlatform" Version="1.0.10" />
<PackageReference Include="Meziantou.Framework.WebPlatform" />
paket add Meziantou.Framework.WebPlatform --version 1.0.10
#r "nuget: Meziantou.Framework.WebPlatform, 1.0.10"
#:package Meziantou.Framework.WebPlatform@1.0.10
#addin nuget:?package=Meziantou.Framework.WebPlatform&version=1.0.10
#tool nuget:?package=Meziantou.Framework.WebPlatform&version=1.0.10
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);
}
}
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 | Versions 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. |
-
net10.0
- Meziantou.Framework.Fonts (>= 1.0.9)
- Meziantou.Framework.Hashing (>= 1.0.1)
- Meziantou.Framework.Unicode (>= 2.0.15)
- Meziantou.Framework.Unicode.Dictionaries (>= 1.0.4)
- System.IO.Hashing (>= 11.0.0-rc.2.26504.105)
-
net11.0
- Meziantou.Framework.Fonts (>= 1.0.9)
- Meziantou.Framework.Hashing (>= 1.0.1)
- Meziantou.Framework.Unicode (>= 2.0.15)
- Meziantou.Framework.Unicode.Dictionaries (>= 1.0.4)
- System.IO.Hashing (>= 11.0.0-rc.2.26504.105)
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.