diff --git a/.github/workflows/chromatic.yaml b/.github/workflows/chromatic.yaml index ce4d3b9..c3f6679 100644 --- a/.github/workflows/chromatic.yaml +++ b/.github/workflows/chromatic.yaml @@ -20,8 +20,9 @@ jobs: with: version: 8 - name: Install dependencies - # ⚠️ See your package manager's documentation for the correct command to install dependencies in a CI environment. - run: pnpm install && cd examples/stories && pnpm install + run: pnpm install + - name: Build + run: pnpm build - name: Run Chromatic uses: chromaui/action@latest with: 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/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..e4b8184 --- /dev/null +++ b/src/text-style.ts @@ -0,0 +1,25 @@ +import type { Loro } from "loro-crdt"; +import type { Schema } from "prosemirror-model"; + +const LORO_TEXT_STYLE_CACHE = new WeakSet(); + +function getLoroTextStyle(schema: Schema): { + [mark: string]: { expand: "before" | "after" | "none" | "both" }; +} { + return Object.fromEntries( + Object.entries(schema.marks).map(([markName, markType]) => [ + markName, + { expand: markType.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,