remirror/remirror

View on GitHub
docs/extensions/annotation-extension.mdx

Summary

Maintainability
Test Coverage
---
hide_title: true
title: AnnotationExtension
---

import Basic from '../../website/extension-examples/extension-annotation/basic';

# `AnnotationExtension`

## Summary

This extension allows to annotate the content in your editor

## Features

## Annotate multiple text nodes

Annotation enrich parts of a document. For example, a user could annotate a sentence as "important" to find it back later on.

### Overlapping annotations

Annotations can be partially or fully overlapping. For example, a user could annotate the "important" sentence as well with "to be reviewed" or a word in the sentence as "customer X".

The annotation extension provides logic to visualize such overlapping annotations by mixing colors. See storybook for an example.

### Extendable data model

The extension defines only the minimal required fields: position where the annotation starts/ends and an ID. For convince, the annotation provides also the text covered by the annotation.

An app using the annotation-extension can extend the base data model. For example, it could add a label (like "important") or a color to each annotation. The annotation extension will pass these custom fields simply through to the app.

### Collaborative editing (Yjs)

As stated above, Annotations are _decorations_ - these are not part of the Prosemirror document model, they are part of the view. Whilst the model is syncronised between users, the _view_ is not.

To enable collaboration on annotations, additional logic has been added in the [Yjs extension](https://github.com/remirror/remirror/tree/main/packages/remirror__extension-yjs#readme), that modifies _this_ extension's options to utilise a [Yjs Map](https://docs.yjs.dev/api/shared-types/y.map). This is a shared data structure, meaning annotations can also be collaborated on.

This [proof of concept](https://github.com/collaborne/remirror-yjs-webrtc-demo/#readme) has a in-depth description of this approach.

## Implementation

Annotations are rendered as [decorations](https://prosemirror.net/docs/ref/#view.Decorations). In contrast to [marks](https://prosemirror.net/docs/ref/#model.Mark), they can span across multiple Prosemirror nodes.

Prosemirror stores all content in a [flat sequence of nodes](https://prosemirror.net/docs/guide/#doc). For example, the text "**bold _italic_ bold**" contains 3 different nodes (italic forces a split of the node).

| Text     | Marks            |
| -------- | ---------------- |
| `bold `  | `bold`           |
| `italic` | `bold`, `italic` |
| ` bold`  | `bold`           |

This means that modelling annotations as marks would lead to 3 different nodes, each with the same annotation mark. By rendering annotations as decorations, an annotation can cover **_multiple_** text nodes with a **_single_** decoration.

This is relevant for many use cases:

- Show a list of sentences marked as "important": Users expect each sentence to show once - not 3 separated items, one for each part of the annotation (in case of marks)
- Rename the "important" annotation to "very important": This would have to be done for all 3 nodes separately in case of marks.
- Brightening the background color of the annotion (styling) on mouse over: Users expect the complete annotation to lighten up - not only of the 3 parts where the mouse over happened. _Note: This breaks if you use overlapping annotations._

References:

- [Prosemirror forum: How to style overlapping inline decorations](https://discuss.prosemirror.net/t/how-to-style-overlapping-inline-decorations/3162)

## Usage

### Installation

This extension is installed for you when you install the main `remirror` package.

You can use the imports in the following way:

```ts
import { AnnotationExtension } from 'remirror/extensions';
```

The extension is provided by the `@remirror/extension-annotation` package.

### Examples

<Basic />

## API

- [AnnotationExtension](../api/extension-annotation)