From 0571b838d039842f68f7e0279daa697ded67f6ec Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 19 May 2026 17:44:01 +0100 Subject: [PATCH 1/3] Fix patching explainer markup --- patching-explainer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patching-explainer.md b/patching-explainer.md index b775b64..1a8a3bc 100644 --- a/patching-explainer.md +++ b/patching-explainer.md @@ -224,7 +224,7 @@ Enabling remote fetching of patch content would act as a script in terms of CSP, ## Alternatives considered -### A `marker` attribute +### A `marker` attribute Having to name the marker as an element attribute on the processing instruction parent element was considered as an mXSS protection, in case downstream sanitizers let processing instructions pass through. However, as mainstream up to date sanitizers don't let processing instructions through in their default configuration it was felt this was an non-issue. @@ -265,7 +265,7 @@ Weaknesses of this design are: These constraint seemed to restrictive for early adopters and frameworks looking at this API - a range of the DOM to be later updated cannot be constrained in advance to an "append"/"prepend"/"replace all" - often this range is an arbitrary range in the DOM defined by the user of the platform/framework. -### Using a new node type +### Using a new node type Instead of using processing instructions, one of the alternatives was treating it as a node type, and perhaps allowing something like ``. However, creating a new type can be incompatible with tools and extensions that rely on XML and HTML being roughly compatible in terms of DOM, From 945193ecb33040b9ac1b02e1622a42e43b1a125d Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 19 May 2026 18:15:25 +0100 Subject: [PATCH 2/3] Update fragment-include-explainer.md --- fragment-include-explainer.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fragment-include-explainer.md b/fragment-include-explainer.md index 8ae8d7b..96a4ea6 100644 --- a/fragment-include-explainer.md +++ b/fragment-include-explainer.md @@ -8,7 +8,7 @@ While this opens up a lot of new options, this has a few limitations that were s 2. A patch is interleaved within the original response, requiring the server to multiplex content from different sources. 3. A patch cannot be independently sanitized. It inherits the safety features of its embedder. -## Proposed solution +## Proposed solution See also https://github.com/WICG/webcomponents/issues/645 and https://github.com/whatwg/html/issues/2791 @@ -23,14 +23,14 @@ Taking from the [HTML modules](https://github.com/WICG/webcomponents/issues/645) - The above means that you can also `import fragment from "something.html" { type: "fragment" }` and it would clone a `DocumentFragment` to your JS. - The `async` and `defer` attributes work the same way as for JS scripts. -## Performance +## Performance The main issue with this approach is that overuse of client-side includes can be a performance anti-pattern vs. multiplexing in the server. However, this performance drawback is very context dependent. In some cases, adding markup asynchronously rather than having to multiplex it in the server or passing it through JS setters can be a performance win. Like with JS modules, bundlers are very mature and authors can make the decision of whether to bundle the markup or fetch it client-side based on their specific context, and we should look at adding this to the toolbox as an expansion of the options rather than as a footgun. -## Relative paths in fragment +## Relative paths in fragment This proposal deliberately *does not* deal with resolving relative paths in the fragment, which is an issue discussed extensively in https://github.com/WICG/webcomponents/issues/645. For keeping this solution focused on the problem space of updating the DOM declaratively, the current semantics of inserting fragments to the document are maintained. @@ -43,7 +43,7 @@ A future opt-in enhancement of this can try to tackle re-basing URLs but it's a In some sense, this is more of a [client side include](https://github.com/whatwg/html/issues/2791) than an HTML module, because of theh important fact the imported fragment is cloned and applied in place. The "module-ness" of this is similar to text or JSON modules, where the content is in the module tree and fetched like a module, but is not mutable in a way that affects all of its importers. -## Security +## Security As mentioned before, this proposal makes use of the sanitizer by default, and unsafe inclusion of HTML should be opted in with an "unsafe" attribute. From 4fc7c51ff11bb215f05a01f1cc0ce8fc2e96eaa8 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 19 May 2026 18:16:13 +0100 Subject: [PATCH 3/3] Update preserve-explainer.md --- preserve-explainer.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/preserve-explainer.md b/preserve-explainer.md index 75f1208..094a8b5 100644 --- a/preserve-explainer.md +++ b/preserve-explainer.md @@ -1,15 +1,15 @@ -# DOM preservation +# DOM preservation (Initial draft) -## Overview +## Overview One of the features that was marked as a "future enhancement" was content preservation - preventing a partial update from overwriting existing content. The use case for this is, e.g., being able to replace a whole range of DOM without reloading some of the iframes or videos inside of it. A model that was proposed for this was a `preserve` attribute. If an element has a `preserve` attribute, and the new content contains an element with that same `preserve`, the element should be preserved rather than be overwritten, and only its attributes would be set. -## Example +## Example ```html
@@ -27,7 +27,7 @@ Some other text In the above example, after the navigation, the text would read "Some other text" but the chat widget wouldn't reload, because the `preserve` attribute would make the patch skip it. -## Islands vs. morphing +## Islands vs. morphing The example above uses the `preserve` attribute as an ID of sorts, and the model is binary - either replace the contents or keep it the same. This is similar to the "islands of interactivity" architecture common in some frameworks today, rather than a merge/morph/virtual-DOM architecture. @@ -37,7 +37,7 @@ This would allow extending this concept to being a lightweight "morph" in the fu The advantage of going with a more island-ish architecture is that it keeps the simple and effective "overwrite by default" architecture of MPAs and creates exceptions to it, rather than tries to become a full SPA merging mechanism. -## Prior art +## Prior art * [`hx-preserve` in HTMX](https://htmx.org/attributes/hx-preserve/): preserves element identity using the ID attribute as a key * [Islands architecture in Astro](https://docs.astro.build/en/concepts/islands/): poking "holes" in the otherwise static replacement rather than a whole DOM diff