Extensions
comment
Threaded comments, anchored to ranges.
The thread itself — author, body, replies, resolution — belongs to the host application, not the document. All that lives here is the anchor: a mark carrying a thread id. That separation is deliberate. Comment bodies in the document would travel with every copy, paste and export of the text, and would need migrating whenever the comment schema changed.
Because the anchor is a mark, position mapping keeps it correct for free: edit the paragraph around a comment and the highlight follows the words.
1 · Install
One package for every extension · there is no @matrajs/comment to install.
npm i @matrajs/core2 · 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, comment } from '@matrajs/core'
const editor = createEditor({
extensions: [document, paragraph, text, comment],
element: document.querySelector('#editor'),
})3 · Use it
Run a command, and give focus back · a click on a button takes it away.
editor.commands.addComment('block-1')
editor.focus()Wired to a button, with the pressed state kept in step:
const button = document.querySelector('#addComment')
button.addEventListener('click', () => {
editor.commands.addComment('block-1')
editor.focus()
})
const read = () => button.setAttribute('aria-pressed', String(editor.isActive('comment')))
editor.on('selectionChange', read)
editor.on('change', read)
read()
Both events, not one. selectionChange covers the caret moving into
it;
change covers the command that changed it without moving anything. A
toolbar wired to only the first goes stale the moment someone uses the keyboard.
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 |
|---|---|
addComment |
editor.commands.addComment(threadId: string)
|
removeComment |
editor.commands.removeComment(threadId: string)
|
Styling
This one needs CSS to look right, and ships the minimum as a string rather than a file · nothing loads unless you load it, and you can ignore it and write your own.
import { commentCSS } from '@matrajs/core'
const style = document.createElement('style')
style.textContent = commentCSS
document.head.append(style)In the document
| Attribute | Default |
|---|---|
threadId | none |
-
Reads
span[data-comment]when HTML is pasted or loaded. -
Writes
spaningetHTML()andrenderToHTML().