Annotations

Inline annotations for wording suggestions and similar callouts. Registers the wording inline block and stores annotation data keyed by data-ref on marked spans.

Click highlighted wording to open a callout with alternatives. Works with the AI Assistant better-wording action via ai:annotations:bind.

Load the bundle

<script src="/assets/redactor/redactor.js"></script>
<script src="/assets/redactor/plugins/annotation/annotation.js"></script>

Initialization

const app = Redactor('#entry', {
    plugins: ['annotation'],
    content: '<p>The <span data-block="wording" data-ref="ref1">quick brown fox</span> jumps over the lazy dog.</p>',
    annotation: {
        annotations: {
            ref1: {
                kind: 'wording',
                items: ['fast brown fox', 'swift brown fox'],
                ignore: true
            }
        }
    }
});

Options

  • annotations (object | false)
    • default false
    • Annotation store keyed by ref id. Each entry may include:
      • kind — annotation type (for example wording).
      • items — array of alternative strings or action objects.
      • ignore (boolean) — when true, adds Ignore to the callout dropdown; if several annotations of the same kind exist, Ignore all is shown too.
      • title, text, comments, actions, meta — optional callout data.
Redactor('#entry', {
    plugins: ['annotation'],
    annotation: {
        annotations: {
            abc: {
                kind: 'wording',
                items: ['Option A', 'Option B']
            }
        }
    }
});

Annotations are also read from JSON payloads with an annotations property alongside blocks.

Language strings

en: {
    blocks: {
        wording: 'Wording'
    },
    annot: {
        wording: 'Better wording',
        comment: 'Comment',
        ignore: 'Ignore',
        'ignore-all': 'Ignore all'
    }
}

Events

annotations:set

Fired when an annotation entry is stored.

Payload: id, data.

app.on('annotations:set', ({ id, data }) => {
    console.log('annotation stored', id, data.kind, data.items);
});

annotations:remove

Fired when an annotation is removed.

Payload: id.

app.on('annotations:remove', ({ id }) => {
    console.log('annotation removed', id);
});

annotations:clear

Fired when all annotations are cleared.

app.on('annotations:clear', () => {
    console.log('all annotations cleared');
});

annotations:apply

Fired when the user applies a wording alternative from the callout (or via annotation.applyChoice).

Payload: ref, kind, text (replacement), original, data (store snapshot before removal).

app.on('annotations:apply', ({ ref, kind, text, original }) => {
    console.log('applied', ref, kind, original, '→', text);
});

annotations:ignore

Fired when the user ignores a single annotation (keeps the original wording).

Payload: ref, kind, text, original, data.

app.on('annotations:ignore', ({ ref, kind }) => {
    console.log('ignored', ref, kind);
});

annotations:ignore-all

Fired when the user ignores all annotations of a kind via Ignore all in the callout.

Payload: kind, count (number of resolved spans).

app.on('annotations:ignore-all', ({ kind, count }) => {
    console.log('ignored all', kind, count);
});

annotation:callout

Hook when a callout is shown. Return { callout } to customize the dropdown (title, items, actions).

Payload: ref, block, kind, data, anchor, callout.

app.on('annotation:callout', ({ ref, kind, callout }) => {
    return {
        callout: {
            ...callout,
            title: kind === 'wording' ? 'Choose wording' : callout.title
        }
    };
});

ai:annotations:bind

Emitted by the AI core when applied issues include annotation alternatives. The plugin listens and binds wording spans automatically; use this event for custom handling.

Payload: root, entries, kind, ignore, issue, blocks.

app.on('ai:annotations:bind', ({ root, entries, kind, ignore }) => {
    console.log('bind annotations', kind, entries.length, ignore);
});

API

getAnnotations

Returns all annotation data keyed by ref id.

const data = app.annotation.getAnnotations();

setAnnotations

Replaces the annotation store and reloads it.

app.annotation.setAnnotations({
    ref1: { kind: 'wording', items: ['new wording'] }
});

applyChoice

Applies a wording alternative to the anchor span.

Parameters: text or content — replacement text; anchor — DOM node (optional in command context).

app.annotation.applyChoice({ text: 'fast brown fox', anchor: el });

ignoreChoice

Ignores a single annotation at the anchor.

app.annotation.ignoreChoice({ anchor: el });

ignoreAll

Ignores all annotations of a kind (defaults to the anchor block type).

app.annotation.ignoreAll({ kind: 'wording' });