jupyter-server / jupyter_ydoc

Jupyter document structures for collaborative editing using Yjs/pycrdt
https://jupyter-ydoc.readthedocs.io
BSD 3-Clause "New" or "Revised" License
27 stars 17 forks source link

Adds annotations #172

Open hbcarlos opened 1 year ago

hbcarlos commented 1 year ago

Fixes: https://github.com/QuantStack/jupytercad/issues/126

Creates a generic interface for annotations and adds annotations to the notebook's cells.

Description

The model I'm using for the annotations is based on the recommendations exposed in the W3C. An example of a notebook comment could be the following:

{
  "@context": "https://www.w3.org/ns/anno.jsonld",
  "id": "annotation_id",
  "type": "Annotation",
  "motivation": "commenting",
  "created": "2023-7-5T10:00:00Z",
  "creator": {
    "id": "user_0_id",
    "type": "Person",
    "name": "Jovyan 0",
    "nickname": "jovyan_0"
  },
  "body": [
    {
      "id": "body_id",
      "type": "TextualBody",
      "value": "Simple text comment",
      "purpose": "commenting",
      "created": "2023-7-5T10:00:00Z",
      "creator": {
        "id": "user_0_id",
        "type": "Person",
        "name": "Jovyan 0",
        "nickname": "jovyan_0"
      },
    },
    {
      "id": "body_id",
      "type": "TextualBody",
      "value": "Simple text comment",
      "purpose": "commenting",
      "created": "2023-7-5T10:00:00Z",
      "creator": {
        "id": "user_1_id",
        "type": "Person",
        "name": "Jovyan 1",
        "nickname": "jovyan_1"
      },
    }
  ],
  "target": {
    "source": "path/to/notebook",
    "selector": {
      "type": "FragmentSelector",
      "value": "cell_id",
      "refinedBy": {
        "type": "TextQuoteSelector",
        "exact": "selected text",
        "prefix": "text before the selection ",
        "suffix": " text after the selection"
      },
    }
  }
}

Attributes description

@context

Points to the definition of the schema used for the annotation

motivation and purpose

It is used to indicate the type of the annotation or body. We can use commenting to add comments threads and editing to add a change request.

created and creator

Identifies who created the annotation or body and when.

body

The body represents a resource that a user added to the annotation. For example, it can be a simple text comment or an audio, video, or image attachment. In this case, the body is a list of bodies to create a thread of comments or suggestions mixed with comments.

When the purpose of a body is tagged as editing, it is a change suggestion and can be applied to the document on the target position.

target

The target represents the position on the document where the annotation is pointing to.

Regarding the target, each document will have a different type selector. For the notebook, there are two possibilities. The above example assumes we store the annotation in the notebook's metadata (it also allows us to keep it outside the document, for example, a DB) and includes the path of the notebook, the cell, and the position of the selection in the text. Another possibility would be to use a simple TextQuoteSelector and store the annotation in the metadata of the cell.

Other attributes that we can use

generator

To indicate what client created the annotation. Moreover, this is optional for now since only jupyterlab will support annotations. See the example of the generator attribute:

{
  "@context": "https://www.w3.org/ns/anno.jsonld",
  "id": "annotation_id",
  ...,
  "generator": {
    "id": "client_id",
    "type": "Software",
    "name": "JupyterLab v4",
    "homepage": "https://jupyter.org"
  },
  ...
}