<!-- Low level · Docs · clayjs · https://clayjs.com/docs/internals · generated from the page; every page has one at its path plus .md -->

[Docs](https://clayjs.com/docs) · Low level

# clay.internals

clay.internals, for code that sits inside the save lifecycle instead of calling it.

The pieces clayjs builds itself out of, for code that needs to sit _inside_ the save lifecycle rather than call it. Lower level than `clay.*`: it assumes you know the lifecycle. One extra script tag, and `clay.loaded.internals` resolves when it's ready.

```html
<script src="https://clayjs.com/v1/clay-internals.js"></script>
```

| Member | What it does |
| --- | --- |
| `captureSnapshot()` | The cloned document element, with form values synced, `onbeforesnapshot` handlers run, and `no-snapshot` regions plus browser-extension noise already removed. It is the shared base every lane starts from, not an untouched copy of the DOM. |
| `captureForSave()` | The exact bytes a save would send, stripping and all. |
| `addDocumentTransform(fn)` | Register a hook that runs on the clone during save preparation and on every change check, so keep it pure and repeatable. Same registry as `clay.addDocumentTransform`. |
| `region.resolveRegionPolicy(node)` | The resolved region axes for a node: `{watched, autosaveTriggered, dirtyTracked, undoable, persist, extension}`. `autosaveTriggered` is whether an edit here starts a save by itself; `dirtyTracked` is whether it counts as unsaved work at all. They differ only inside `no-trigger-autosave`, which is saved work waiting for a manual save; `no-dirty` clears both, for content that is saved but is not work. |
| `region.isInert(node)` | Whether a node is invisible to the whole mutation system (`no-watch` and extension noise). |
| `region.isSnapshotRemoved(node)` | Whether a node is dropped from every snapshot (`no-snapshot`). Ancestor-aware: a child of a marked region is just as absent as the region itself. |
| `region.addRegionToken(el, token)` | Add one token to an element's `clay` attribute, keeping the tokens already there. |
| `region.PERSIST` / `region.REGION_ATTRS` | The persist values (`full`, `frozen`, `none`) and the canonical token list. |
| `region.selectors` | `stripFromSave`, `stripFromComparison`, `stripFromDirtyCheck`, `noTriggerAutosave`, `snapshotRemove`, `freeze`: the selectors clayjs itself strips with, legacy spellings included. The same object is on `clay.region`, which also publishes them as `STRIP_FROM_SAVE`\-style constants. |
| `save.saveHtml(html, cb)` | Send an HTML string to the save endpoint. Resolves `{ok, msg, msgType, code, etag}`; never rejects. |
| `save.replacePageWith(url, cb)` | Fetch another URL's HTML and save it over the current file. Same result shape. |
| `save.isSaveInProgress()` | Whether a save is in flight right now. |

**`save.saveHtml` writes the bytes you hand it straight to the file**: it bypasses the snapshot pipeline entirely, so nothing is stripped and no hook runs. Check `save.isSaveInProgress()` first, because firing into an in-flight save is how you lose an edit. For a worked example of the region helpers, see [Advanced](https://clayjs.com/advanced#custom-attrs).
