marshall-y-slate
Version:
Yjs bindings for Slate.
65 lines (53 loc) • 1.5 kB
text/typescript
import { Editor, Node, Text, TextOperation } from 'slate';
import invariant from 'tiny-invariant';
import * as Y from 'yjs';
import { toSlatePath } from '../utils/convert';
/**
* Translates a Yjs text event into a slate operations.
*
* @param event
*/
export default function translateTextEvent(
editor: Editor,
event: Y.YTextEvent
): TextOperation[] {
const targetPath = toSlatePath(event.path);
const targetText = Node.get(editor, targetPath);
invariant(
Text.isText(targetText),
'Cannot apply text event to non-text node'
);
let offset = 0;
let { text } = targetText;
const ops: TextOperation[] = [];
event.changes.delta.forEach((delta) => {
if ('retain' in delta) {
offset += delta.retain ?? 0;
}
if ('delete' in delta) {
const endOffset = offset + (delta.delete ?? 0);
ops.push({
type: 'remove_text',
offset,
path: targetPath,
text: text.slice(offset, endOffset)
});
text = text.slice(0, offset) + text.slice(endOffset);
}
if ('insert' in delta) {
invariant(
typeof delta.insert === 'string',
`Unexpected text insert content type: expected string, got ${typeof delta.insert}`
);
ops.push({
type: 'insert_text',
offset,
text: delta.insert,
path: targetPath
});
offset += delta.insert.length;
text = text.slice(0, offset) + delta.insert + text.slice(offset);
}
});
return ops;
}