The snapshot algorithm

Normative companion to The Malleable HTML File Specification, section 2. Version 1, draft. July 2026. Public domain (CC0).

The main specification names the steps; this page fixes their exact behavior and order. Two independently written clients that both follow this page produce the same bytes from the same DOM. When prose and fixtures disagree, the conformance fixtures win.

The two artifacts

One capture pipeline produces two artifacts:

The algorithm

A client must perform these steps in this order.

1. Settle. Give the page a chance to reach a clean boundary before capture. A client that batches undo history must flush any open batch here, so the captured state never straddles an undo boundary. A client with no such machinery skips this step.

2. Clone. Deep-clone document.documentElement. Never mutate the live DOM during capture; every following step operates on the clone. If cloning can trigger page-defined side effects (custom element callbacks, clone guards), the client must suppress them for the duration of the clone.

3. Sync form state into markup. Live form values exist only in JavaScript object properties and would not survive serialization. Reflect them into the clone's attributes and content:

Control Rule
<input type=text> and other textual inputs set the value attribute to the live .value
<input type=checkbox> and type=radio set or remove the checked attribute per the live .checked
<select> set the selected attribute on the option matching the live selection; remove it from the others
<textarea> replace child text with the live .value
<input type=password> never written into markup
<input type=file> cannot be persisted; never written into markup

A client may scope this to elements that opt in (the reference client uses a persist marker) or apply it broadly, but the password and file rules are absolute.

4. Run the page's pre-snapshot hooks. The document may reshape the clone before capture. The reference client supports both registered callbacks and an inline onbeforesnapshot attribute, invoked with the element as this. Hooks see the clone, never the live DOM.

5. Strip [no-snapshot] elements. Remove every element bearing the no-snapshot marker from the clone. This content exists only on the live page and never leaves it: not to disk, not to sync, not to comparison.

6. Strip extension debris. Browser extensions (password managers, grammar checkers) inject elements and stamp attributes into pages they touch. Remove known debris: injected elements that are not part of the document, and marker attributes stamped onto real elements. This step is a SHOULD with teeth: in a format where the file is the database, anything not removed here is saved into the document forever. The conformance fixtures include representative debris.

The serialization of the clone at this point, prefixed with <!DOCTYPE html>, is the snapshot. A client implementing live sync emits it here, before any save-time stripping.

7. Run the page's save-time hooks, then strip [no-save] elements. Save-time hooks (the reference client's inline onbeforesave attribute, then its registered save callbacks) run only when producing a document, never for a bare snapshot. Then remove every element bearing the no-save marker. This content is real page state that other live editors may see through sync, but it never reaches disk.

8. Serialize. The document is:

"<!DOCTYPE html>" + clone.outerHTML

The doctype string is emitted literally. The format is HTML5; whatever doctype the source file carried, the saved document begins <!DOCTYPE html>. Nothing outside the root <html> element survives: comments or processing instructions above the root are not durable state.

Required properties

Marker summary

Marker Stripped from snapshot Stripped from document Meaning
no-snapshot yes yes never leaves the live page
no-save no yes live state, shared with editors, never on disk

Both are attribute markers matched by presence. Clients must strip both; a client that strips only no-save leaks live-only content into sync, and a client that strips neither corrupts the saved file with interface chrome.

Fixtures

The conformance fixtures are input documents, the expected snapshot bytes, and the expected document bytes for each. A client passes when its output is byte-identical. The fixtures are the arbiter; this prose is the explanation.

The fixtures are indexed at malleablehtmlfile.com/fixtures/manifest.json.


Canonical: malleablehtmlfile.com/snapshot-algorithm.txt · Main specification: The Malleable HTML File Specification