or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

CKEditor 5 Autosave

CKEditor 5 Autosave is a plugin that automatically saves editor content when changes occur. It provides configurable debouncing, integration with CKEditor 5's pending actions system, and support for both callback and adapter-based save implementations.

Package Information

  • Package Name: @ckeditor/ckeditor5-autosave
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install ckeditor5 (this plugin is part of the main ckeditor5 package)

Core Imports

import { Autosave } from '@ckeditor/ckeditor5-autosave';

For type definitions:

import { Autosave, type AutosaveConfig, type AutosaveAdapter } from '@ckeditor/ckeditor5-autosave';

Basic Usage

Configuration-based Usage

import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
import { Autosave } from '@ckeditor/ckeditor5-autosave';

ClassicEditor
  .create(document.querySelector('#editor'), {
    plugins: [Autosave, /* other plugins */],
    autosave: {
      save(editor) {
        // Must return a promise
        return fetch('/save', {
          method: 'POST',
          body: JSON.stringify({ content: editor.getData() }),
          headers: { 'Content-Type': 'application/json' }
        });
      },
      waitingTime: 2000 // Wait 2 seconds after last change (default: 1000ms)
    }
  })
  .then(editor => {
    // Access autosave plugin
    const autosave = editor.plugins.get('Autosave');
    console.log(autosave.state); // 'synchronized', 'waiting', 'saving', or 'error'
  });

Adapter-based Usage

import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
import { Autosave, type AutosaveAdapter } from '@ckeditor/ckeditor5-autosave';

class CustomSaveAdapter implements AutosaveAdapter {
  save(editor) {
    return new Promise(resolve => {
      // Custom save logic
      localStorage.setItem('editor-content', editor.getData());
      setTimeout(resolve, 100);
    });
  }
}

ClassicEditor
  .create(document.querySelector('#editor'), {
    plugins: [Autosave, /* other plugins */]
  })
  .then(editor => {
    const autosave = editor.plugins.get('Autosave');
    autosave.adapter = new CustomSaveAdapter();
  });

Manual Save

// Trigger manual save
await editor.plugins.get('Autosave').save();

State Monitoring

const autosave = editor.plugins.get('Autosave');

// Monitor save state changes
autosave.on('change:state', () => {
  switch (autosave.state) {
    case 'synchronized':
      console.log('All changes saved');
      break;
    case 'waiting':
      console.log('Waiting to save changes...');
      break;
    case 'saving':
      console.log('Saving in progress...');
      break;
    case 'error':
      console.log('Save failed, will retry...');
      break;
  }
});

Core Types

// Core CKEditor 5 types used by Autosave plugin
interface Editor {
  readonly model: {
    readonly document: ModelDocument;
  };
  readonly config: EditorConfig;
  readonly plugins: PluginCollection;
  getData(): string;
}

abstract class Plugin {
  readonly editor: Editor;
  constructor(editor: Editor);
  init?(): void;
  destroy?(): void;
}

interface PendingActions extends Plugin {
  add(message: string): PendingAction;
  remove(action: PendingAction): void;
}

interface PendingAction {
  readonly message: string;
}

interface ModelDocument {
  readonly version: number;
}

interface PluginCollection {
  get<T extends Plugin>(plugin: string | { new(...args: any[]): T }): T;
}

interface EditorConfig {
  get(configName: string): any;
  autosave?: AutosaveConfig;
}

Capabilities

Autosave Plugin

The main plugin class that handles automatic saving of editor content.

class Autosave extends Plugin {
  /** Plugin identifier */
  static get pluginName(): 'Autosave';
  
  /** Marks this as an official CKEditor plugin */
  static get isOfficialPlugin(): true;
  
  /** Required plugin dependencies */
  static get requires(): [typeof PendingActions];
  
  /** Custom save adapter instance */
  adapter?: AutosaveAdapter;
  
  /** Current plugin state - observable and readonly */
  readonly state: 'synchronized' | 'waiting' | 'saving' | 'error';
  
  /** Initialize the plugin */
  constructor(editor: Editor);
  
  /** Set up event listeners and start autosave functionality */
  init(): void;
  
  /** Clean up resources when plugin is destroyed */
  destroy(): void;
  
  /** Manually trigger a save operation */
  save(): Promise<void>;
}

Save Adapter Interface

Interface for implementing custom save adapters.

interface AutosaveAdapter {
  /**
   * Save method called when editor data changes
   * @param editor - The editor instance containing the data to save
   * @returns Promise that resolves when save operation completes
   */
  save(editor: Editor): Promise<unknown>;
}

Configuration Interface

Configuration options for the autosave feature.

interface AutosaveConfig {
  /**
   * Callback function executed when data needs to be saved.
   * Must return a promise that resolves when save operation completes.
   */
  save?(editor: Editor): Promise<unknown>;
  
  /**
   * Minimum time in milliseconds to wait after last change before saving.
   * @default 1000
   */
  waitingTime?: number;
}

Plugin Behavior

The Autosave plugin operates with the following behavior:

  • Automatic Triggering: Listens to editor.model.document#change:data events to detect content changes
  • Debouncing: Uses configurable waitingTime (default 1000ms) to avoid excessive save calls
  • Browser Integration: Listens to window#beforeunload events to save before page unload
  • Pending Actions: Integrates with CKEditor 5's pending actions system to track save operations
  • State Management: Maintains observable state: synchronized, waiting, saving, or error
  • Error Handling: Automatically retries failed saves with exponential backoff
  • Dual Save Methods: Supports both configuration-based and adapter-based save implementations

States

The plugin maintains four distinct states:

  • synchronized: All changes have been successfully saved
  • waiting: Plugin is waiting for the debounce period before initiating save
  • saving: Save operation is currently in progress
  • error: Save operation failed, plugin will automatically retry

Integration Requirements

To use the Autosave plugin:

  1. Include in plugins array: Add Autosave to your editor's plugins configuration
  2. Provide save method: Either set config.autosave.save or assign an adapter to the plugin instance
  3. Handle promises: Save functions must return promises that resolve when the operation completes
  4. Error handling: Save functions should reject promises or throw errors for failed operations

Editor Types

The plugin extends the CKEditor 5 type system:

// Adds Autosave to the plugins map
declare module '@ckeditor/ckeditor5-core' {
  interface PluginsMap {
    Autosave: Autosave;
  }
}