# source

> Saves the file instead of reprinting the page, so an unchanged save changes nothing.

Source: https://clayjs.com/docs/plugins/source/

Saves the file rather than a fresh printout of the page, so a save that changes nothing changes nothing. On by default; `?exclude=source` turns it off.

## What it does

Without it, every save rebuilds the document from the browser's DOM, which reorders attributes, renormalises quoting and reprints every tag: a save that changes nothing rewrites about 88% of a hand-written file's lines. With it, clay keeps the bytes the file was loaded from, pairs each element to its place in them, and reprints only what actually changed. A save that changes nothing changes nothing.

## Turning it off

```html
<!-- on by default; this is how you turn it off -->
<script src="https://clayjs.com/v1/clay.js?exclude=source"></script>
```

## Reading the file clay believes is on disk

```js
clay.source.stats();   // { paired, saves, reprints, lastReprint, ... }
document.addEventListener("clay:save-reprinted", (e) => console.warn(e.detail.reason));

clay.source.text();      // the bytes clay believes are on disk right now
clay.source.locate(el);  // { from, to, line, column } for a live element, or null
```

`text()` and `locate()` are what an editing tool needs: read the file as it will be written, point at an element in the live page, and express the change as a range in those bytes instead of as a DOM mutation. The offsets and `column` are **UTF-16 code units** into `text()`, not bytes, so slice the string `text()` hands you and the answer is exact. `locate()` returns `null` for an element that is not in the file, which includes one the page created after load.

Every save is reparsed and compared to the page before it is sent, and anything that does not match exactly is sent as the ordinary full serialization instead, so the worst case is the behaviour you already have. `clay:save-reprinted` fires when that happens and `clay.source.stats()` counts it. Edit mode only, and it costs an HTML parser (about 48 KB compressed) plus one request for the file's own bytes at load, which is what `exclude=source` is for.
