0.10.0: Archify Sync, optional live collaboration on a model
Several people edit one model at once through a server you run yourself (archify-vscode-ext-sync); the files stay ordinary files on each disk. Sign-in through the browser, offline-first with later merge, teammates' cursors in the Source view and text editors, and a Shared section on the model page with people, versions, Compare and Restore. Without a server nothing changes: the sync code is a separate bundle that loads only when a model is shared, after a sign-in, or when a sync command or invite link is used.
This commit is contained in:
1 parent
a9021312b0
commit
c99f3e5fe8
27 files changed
+2899
-14
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import * as Y from 'yjs';
|
||||
import { TextChange, minimalChange } from '../util/textDiff';
|
||||
|
||||
const isHigh = (code: number) => code >= 0xd800 && code <= 0xdbff;
|
||||
const isLow = (code: number) => code >= 0xdc00 && code <= 0xdfff;
|
||||
|
||||
/**
|
||||
* `minimalChange`, widened so it never splits a surrogate pair: Yjs would
|
||||
* replace half a pair with U+FFFD, and every copy would get the broken text.
|
||||
*/
|
||||
export function safeChange(before: string, after: string): TextChange | undefined {
|
||||
const change = minimalChange(before, after);
|
||||
if (!change) return undefined;
|
||||
let { from, to } = change;
|
||||
let endAfter = after.length - (before.length - to);
|
||||
// A common start ending in a high surrogate, or a common end starting with
|
||||
// a low one, would split a pair: take the whole character into the change.
|
||||
if (from > 0 && isHigh(before.charCodeAt(from - 1))) from--;
|
||||
if (to < before.length && isLow(before.charCodeAt(to))) {
|
||||
to++;
|
||||
endAfter++;
|
||||
}
|
||||
return { from, to, insert: after.slice(from, endAfter) };
|
||||
}
|
||||
|
||||
/** Makes the Y.Text read `after` with one minimal edit; false when it already does. */
|
||||
export function applyToYText(text: Y.Text, after: string): boolean {
|
||||
const change = safeChange(text.toString(), after);
|
||||
if (!change) return false;
|
||||
if (change.to > change.from) text.delete(change.from, change.to - change.from);
|
||||
if (change.insert) text.insert(change.from, change.insert);
|
||||
return true;
|
||||
}
|
||||
Reference in new issue
Block a user