diff --git a/examples/stories/src/stories/Editor.stories.tsx b/examples/stories/src/stories/Editor.stories.tsx index 75cdb7f..49774c6 100644 --- a/examples/stories/src/stories/Editor.stories.tsx +++ b/examples/stories/src/stories/Editor.stories.tsx @@ -17,7 +17,7 @@ const meta = { export default meta; export const Basic = () => { - const loroARef = useRef(createLoro()); + const loroARef = useRef(new Loro()); const idA = loroARef.current.peerIdStr; const awarenessA = useRef(new CursorAwareness(idA)); return ( @@ -27,22 +27,11 @@ export const Basic = () => { ); }; -function createLoro() { - const doc = new Loro(); - doc.configTextStyle({ - em: { expand: "after" }, - strong: { expand: "after" }, - code: { expand: "none" }, - link: { expand: "none" }, - }); - return doc; -} - export const Sync = () => { - const loroARef = useRef(createLoro()); + const loroARef = useRef(new Loro()); const idA = loroARef.current.peerIdStr; const awarenessA = useRef(new CursorAwareness(idA)); - const loroBRef = useRef(createLoro()); + const loroBRef = useRef(new Loro()); const idB = loroBRef.current.peerIdStr; const awarenessB = useRef(new CursorAwareness(idB)); useEffect(() => { diff --git a/package.json b/package.json index 8037b09..3381356 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "author": "Loro Team", "license": "MIT", "dependencies": { + "just-map-values": "^3.2.0", "lib0": "^0.2.42" }, "peerDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ede028..f5cf8c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + just-map-values: + specifier: ^3.2.0 + version: 3.2.0 lib0: specifier: ^0.2.42 version: 0.2.93 @@ -5295,6 +5298,10 @@ packages: graceful-fs: 4.2.11 dev: true + /just-map-values@3.2.0: + resolution: {integrity: sha512-TyqCKtK3NxiUgOjRYMIKURvBTHesi3XzomDY0QVPZ3rYzLCF+nNq5rSi0B/L5aOd/WMTZo6ukzA4wih4HUbrDg==} + dev: false + /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: diff --git a/src/sync-plugin.ts b/src/sync-plugin.ts index 4347731..59962be 100644 --- a/src/sync-plugin.ts +++ b/src/sync-plugin.ts @@ -14,6 +14,7 @@ import { createNodeFromLoroObj, updateLoroToPmState, } from "./lib"; +import { configLoroTextStyle } from "./text-style"; export const loroSyncPluginKey = new PluginKey("loro-sync"); @@ -52,11 +53,15 @@ export const LoroSyncPlugin = (props: LoroSyncPluginProps): Plugin => { }, }, state: { - init: (config, editorState): LoroSyncPluginState => ({ - doc: props.doc, - mapping: props.mapping ?? new Map(), - changedBy: "local" - }), + init: (config, editorState): LoroSyncPluginState => { + configLoroTextStyle(props.doc, editorState.schema); + + return { + doc: props.doc, + mapping: props.mapping ?? new Map(), + changedBy: "local" + } + }, apply: (tr, state, oldEditorState, newEditorState) => { const meta = tr.getMeta( loroSyncPluginKey, diff --git a/src/text-style.ts b/src/text-style.ts new file mode 100644 index 0000000..6fec0e0 --- /dev/null +++ b/src/text-style.ts @@ -0,0 +1,23 @@ +import type { Schema } from "prosemirror-model"; +import mapValues from "just-map-values"; +import type { Loro } from "loro-crdt"; + +const LORO_TEXT_STYLE_CACHE = new WeakSet(); + +function getLoroTextStyle(schema: Schema): { + [mark: string]: { expand: "before" | "after" | "none" | "both" }; +} { + return mapValues(schema.marks, (mark) => { + return { expand: mark.spec.inclusive ? "after" : "none" }; + }); +} + +export function configLoroTextStyle(doc: Loro, schema: Schema) { + // Avoid reconfiguring the text style for the same Loro document. + if (LORO_TEXT_STYLE_CACHE.has(doc)) { + return; + } + LORO_TEXT_STYLE_CACHE.add(doc); + + doc.configTextStyle(getLoroTextStyle(schema)); +} diff --git a/src/undo-plugin.ts b/src/undo-plugin.ts index b0008e5..b3847ef 100644 --- a/src/undo-plugin.ts +++ b/src/undo-plugin.ts @@ -14,6 +14,7 @@ import { cursorToAbsolutePosition, } from "./cursor-plugin"; import { loroSyncPluginKey } from "./sync-plugin"; +import { configLoroTextStyle } from "./text-style"; export interface LoroUndoPluginProps { doc: Loro; @@ -41,6 +42,8 @@ export const LoroUndoPlugin = (props: LoroUndoPluginProps): Plugin => { key: loroUndoPluginKey, state: { init: (config, editorState): LoroUndoPluginState => { + configLoroTextStyle(props.doc, editorState.schema); + undoManager.addExcludeOriginPrefix("sys:init"); return { undoManager,