Extensions

autosave

Behaviour takes options 0.81 kB gzipped

Save the document once typing pauses.

Every change marks the document dirty and starts the clock; the save runs `delay` after the last one, so a sentence costs one save rather than one per letter. `save()` saves now. When the page is hidden or unloaded a dirty document is saved before it goes, since a pause that never comes is the usual way an autosave loses the last paragraph.

The state is reduced from transactions like any other: a change marks it dirty, and the save reports back through `markSaved`, which is a command so that the report is a transaction too. A save that fails leaves the document dirty with `error` set and is not retried on its own — the next change, or `save()`, tries again — because retrying a server that is down every second is how a server that is down stays down.

A save runs outside any command, after the transaction that asked for it has landed, because `save` is application code and may do anything at all. `editor.can.save()` asks without saving. One `autosave()` per editor: it holds the editor it was mounted in.

autosave({
  delay: 800,
  save: (doc) => localStorage.setItem('draft', JSON.stringify(doc)),
  restore: () => JSON.parse(localStorage.getItem('draft') ?? 'null'),
})

1 · Install

One package for every extension · there is no @matrajs/autosave to install.

npm i @matrajs/core

2 · Add it to the editor

Import it and put it in the extensions array. That array is the whole feature list: what is not in it is not in your bundle and not in the document's schema.

import { createEditor, document, paragraph, text, autosave } from '@matrajs/core'

const editor = createEditor({
  extensions: [document, paragraph, text, autosave({ … })],
  element: document.querySelector('#editor'),
})

3 · Use it

Run a command, and give focus back · a click on a button takes it away.

editor.commands.save()
editor.focus()

Wired to a button:

const button = document.querySelector('#save')

button.addEventListener('click', () => {
  editor.commands.save()
  editor.focus()
})

Options

autosave is a function · call it with an options object.

Option Type What it does
save required (doc: DocNode, editor: Editor) => void | Promise<void> Persist the document. A returned promise is waited for; whatever it rejects with, or the function throws, is reported and never thrown on.
delay number How long typing has to pause before a save. Default 1000ms.
restore () => DocNode | string | null | undefined Content to load when the editor mounts — what the last save left behind. Loading it is not an edit: the document is not dirty afterwards.
onError (error: unknown) => void Told about every save that failed.
flushOnHide boolean Save at once when the page is hidden or unloaded. Default true.

Commands

Every one returns true if it changed the document and false if it could not · a command that does not apply where the caret is says so rather than throwing.

Command Call
save editor.commands.save()
markSaved editor.commands.markSaved(ok: boolean, error?: unknown)

← All 83 extensions

Edit this page on GitHub