mirror of https://github.com/fantasticit/think.git
Merge pull request #7 from fantasticit/collobration
commit
c0533bb8f8
|
@ -23,8 +23,6 @@
|
|||
"@tiptap/extension-code": "^2.0.0-beta.26",
|
||||
"@tiptap/extension-code-block": "^2.0.0-beta.37",
|
||||
"@tiptap/extension-code-block-lowlight": "^2.0.0-beta.68",
|
||||
"@tiptap/extension-collaboration": "^2.0.0-beta.33",
|
||||
"@tiptap/extension-collaboration-cursor": "^2.0.0-beta.34",
|
||||
"@tiptap/extension-color": "^2.0.0-beta.9",
|
||||
"@tiptap/extension-document": "^2.0.0-beta.15",
|
||||
"@tiptap/extension-dropcursor": "^2.0.0-beta.25",
|
||||
|
@ -60,6 +58,7 @@
|
|||
"dompurify": "^2.3.5",
|
||||
"interactjs": "^1.10.11",
|
||||
"katex": "^0.15.2",
|
||||
"lib0": "^0.2.47",
|
||||
"lowlight": "^2.5.0",
|
||||
"markdown-it": "^12.3.2",
|
||||
"markdown-it-anchor": "^8.4.1",
|
||||
|
@ -78,7 +77,9 @@
|
|||
"react-split-pane": "^0.1.92",
|
||||
"scroll-into-view-if-needed": "^2.2.29",
|
||||
"swr": "^1.2.0",
|
||||
"tippy.js": "^6.3.7"
|
||||
"tippy.js": "^6.3.7",
|
||||
"y-prosemirror": "^1.0.14",
|
||||
"yjs": "^13.5.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "17.0.13",
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
import { Extension } from '@tiptap/core';
|
||||
import { UndoManager } from 'yjs';
|
||||
import { redo, undo, ySyncPlugin, yUndoPlugin, yUndoPluginKey } from 'y-prosemirror';
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
interface Commands<ReturnType> {
|
||||
collaboration: {
|
||||
/**
|
||||
* Undo recent changes
|
||||
*/
|
||||
undo: () => ReturnType;
|
||||
/**
|
||||
* Reapply reverted changes
|
||||
*/
|
||||
redo: () => ReturnType;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface CollaborationOptions {
|
||||
/**
|
||||
* An initialized Y.js document.
|
||||
*/
|
||||
document: any;
|
||||
/**
|
||||
* Name of a Y.js fragment, can be changed to sync multiple fields with one Y.js document.
|
||||
*/
|
||||
field: string;
|
||||
/**
|
||||
* A raw Y.js fragment, can be used instead of `document` and `field`.
|
||||
*/
|
||||
fragment: any;
|
||||
}
|
||||
|
||||
export const Collaboration = Extension.create<CollaborationOptions>({
|
||||
name: 'collaboration',
|
||||
|
||||
priority: 1000,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
document: null,
|
||||
field: 'default',
|
||||
fragment: null,
|
||||
};
|
||||
},
|
||||
|
||||
onCreate() {
|
||||
if (this.editor.extensionManager.extensions.find((extension) => extension.name === 'history')) {
|
||||
console.warn(
|
||||
'[tiptap warn]: "@tiptap/extension-collaboration" comes with its own history support and is not compatible with "@tiptap/extension-history".'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
addCommands() {
|
||||
return {
|
||||
undo:
|
||||
() =>
|
||||
({ tr, state, dispatch }) => {
|
||||
tr.setMeta('preventDispatch', true);
|
||||
|
||||
const undoManager: UndoManager = yUndoPluginKey.getState(state).undoManager;
|
||||
|
||||
if (undoManager.undoStack.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dispatch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return undo(state);
|
||||
},
|
||||
redo:
|
||||
() =>
|
||||
({ tr, state, dispatch }) => {
|
||||
tr.setMeta('preventDispatch', true);
|
||||
|
||||
const undoManager: UndoManager = yUndoPluginKey.getState(state).undoManager;
|
||||
|
||||
if (undoManager.redoStack.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dispatch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return redo(state);
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
addKeyboardShortcuts() {
|
||||
return {
|
||||
'Mod-z': () => this.editor.commands.undo(),
|
||||
'Mod-y': () => this.editor.commands.redo(),
|
||||
'Shift-Mod-z': () => this.editor.commands.redo(),
|
||||
};
|
||||
},
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
const fragment = this.options.fragment
|
||||
? this.options.fragment
|
||||
: this.options.document.getXmlFragment(this.options.field);
|
||||
|
||||
return [ySyncPlugin(fragment), yUndoPlugin()];
|
||||
},
|
||||
});
|
|
@ -0,0 +1,6 @@
|
|||
import { ySyncPluginKey } from 'y-prosemirror';
|
||||
import { Transaction } from 'prosemirror-state';
|
||||
|
||||
export function isChangeOrigin(transaction: Transaction): boolean {
|
||||
return !!transaction.getMeta(ySyncPluginKey);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * from './collaboration';
|
||||
export * from './helpers/isChangeOrigin';
|
|
@ -0,0 +1,131 @@
|
|||
import { Extension } from '@tiptap/core';
|
||||
import { yCursorPlugin } from 'y-prosemirror';
|
||||
|
||||
type CollaborationCursorStorage = {
|
||||
users: { clientId: number; [key: string]: any }[];
|
||||
};
|
||||
|
||||
export interface CollaborationCursorOptions {
|
||||
provider: any;
|
||||
user: Record<string, any>;
|
||||
render(user: Record<string, any>): HTMLElement;
|
||||
/**
|
||||
* @deprecated The "onUpdate" option is deprecated. Please use `editor.storage.collaborationCursor.users` instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor
|
||||
*/
|
||||
onUpdate: (users: { clientId: number; [key: string]: any }[]) => null;
|
||||
}
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
interface Commands<ReturnType> {
|
||||
collaborationCursor: {
|
||||
/**
|
||||
* Update details of the current user
|
||||
*/
|
||||
updateUser: (attributes: Record<string, any>) => ReturnType;
|
||||
/**
|
||||
* Update details of the current user
|
||||
*
|
||||
* @deprecated The "user" command is deprecated. Please use "updateUser" instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor
|
||||
*/
|
||||
user: (attributes: Record<string, any>) => ReturnType;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const awarenessStatesToArray = (states: Map<number, Record<string, any>>) => {
|
||||
return Array.from(states.entries()).map(([key, value]) => {
|
||||
return {
|
||||
clientId: key,
|
||||
...value.user,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const defaultOnUpdate = () => null;
|
||||
|
||||
export const CollaborationCursor = Extension.create<CollaborationCursorOptions, CollaborationCursorStorage>({
|
||||
name: 'collaborationCursor',
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
provider: null,
|
||||
user: {
|
||||
name: null,
|
||||
color: null,
|
||||
},
|
||||
render: (user) => {
|
||||
const cursor = document.createElement('span');
|
||||
|
||||
cursor.classList.add('collaboration-cursor__caret');
|
||||
cursor.setAttribute('style', `border-color: ${user.color}`);
|
||||
|
||||
const label = document.createElement('div');
|
||||
|
||||
label.classList.add('collaboration-cursor__label');
|
||||
label.setAttribute('style', `background-color: ${user.color}`);
|
||||
label.insertBefore(document.createTextNode(user.name), null);
|
||||
cursor.insertBefore(label, null);
|
||||
|
||||
return cursor;
|
||||
},
|
||||
onUpdate: defaultOnUpdate,
|
||||
};
|
||||
},
|
||||
|
||||
onCreate() {
|
||||
if (this.options.onUpdate !== defaultOnUpdate) {
|
||||
console.warn(
|
||||
'[tiptap warn]: DEPRECATED: The "onUpdate" option is deprecated. Please use `editor.storage.collaborationCursor.users` instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
addStorage() {
|
||||
return {
|
||||
users: [],
|
||||
};
|
||||
},
|
||||
|
||||
addCommands() {
|
||||
return {
|
||||
updateUser: (attributes) => () => {
|
||||
this.options.user = attributes;
|
||||
|
||||
this.options.provider.awareness.setLocalStateField('user', this.options.user);
|
||||
|
||||
return true;
|
||||
},
|
||||
user:
|
||||
(attributes) =>
|
||||
({ editor }) => {
|
||||
console.warn(
|
||||
'[tiptap warn]: DEPRECATED: The "user" command is deprecated. Please use "updateUser" instead. Read more: https://tiptap.dev/api/extensions/collaboration-cursor'
|
||||
);
|
||||
|
||||
return editor.commands.updateUser(attributes);
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
return [
|
||||
yCursorPlugin(
|
||||
(() => {
|
||||
this.options.provider.awareness.setLocalStateField('user', this.options.user);
|
||||
|
||||
this.storage.users = awarenessStatesToArray(this.options.provider.awareness.states);
|
||||
|
||||
this.options.provider.awareness.on('update', () => {
|
||||
this.storage.users = awarenessStatesToArray(this.options.provider.awareness.states);
|
||||
});
|
||||
|
||||
return this.options.provider.awareness;
|
||||
})(),
|
||||
// @ts-ignore
|
||||
{
|
||||
cursorBuilder: this.options.render,
|
||||
}
|
||||
),
|
||||
];
|
||||
},
|
||||
});
|
|
@ -0,0 +1,187 @@
|
|||
import * as Y from 'yjs';
|
||||
import { Decoration, DecorationSet } from 'prosemirror-view'; // eslint-disable-line
|
||||
import { Plugin } from 'prosemirror-state'; // eslint-disable-line
|
||||
import * as math from 'lib0/math';
|
||||
import {
|
||||
absolutePositionToRelativePosition,
|
||||
relativePositionToAbsolutePosition,
|
||||
setMeta,
|
||||
yCursorPluginKey,
|
||||
ySyncPluginKey,
|
||||
} from 'y-prosemirror';
|
||||
|
||||
/**
|
||||
* Default generator for a cursor element
|
||||
*
|
||||
* @param {any} user user data
|
||||
* @return HTMLElement
|
||||
*/
|
||||
export const defaultCursorBuilder = (user) => {
|
||||
const cursor = document.createElement('span');
|
||||
cursor.classList.add('ProseMirror-yjs-cursor');
|
||||
cursor.setAttribute('style', `border-color: ${user.color}`);
|
||||
const userDiv = document.createElement('div');
|
||||
userDiv.setAttribute('style', `background-color: ${user.color}`);
|
||||
userDiv.insertBefore(document.createTextNode(user.name), null);
|
||||
cursor.insertBefore(userDiv, null);
|
||||
return cursor;
|
||||
};
|
||||
|
||||
const rxValidColor = /^#[0-9a-fA-F]{6}$/;
|
||||
|
||||
/**
|
||||
* @param {any} state
|
||||
* @param {Awareness} awareness
|
||||
* @return {any} DecorationSet
|
||||
*/
|
||||
export const createDecorations = (state, awareness, createCursor) => {
|
||||
const ystate = ySyncPluginKey.getState(state) || state['y-sync$'];
|
||||
const y = ystate.doc;
|
||||
const decorations = [];
|
||||
if (ystate.snapshot != null || ystate.prevSnapshot != null || ystate.binding === null) {
|
||||
// do not render cursors while snapshot is active
|
||||
return DecorationSet.create(state.doc, []);
|
||||
}
|
||||
awareness.getStates().forEach((aw, clientId) => {
|
||||
if (clientId === y.clientID) {
|
||||
return;
|
||||
}
|
||||
if (aw.cursor != null) {
|
||||
const user = aw.user || {};
|
||||
if (user.color == null) {
|
||||
user.color = '#ffa500';
|
||||
} else if (!rxValidColor.test(user.color)) {
|
||||
// We only support 6-digit RGB colors in y-prosemirror
|
||||
console.warn('A user uses an unsupported color format', user);
|
||||
}
|
||||
if (user.name == null) {
|
||||
user.name = `User: ${clientId}`;
|
||||
}
|
||||
let anchor = relativePositionToAbsolutePosition(
|
||||
y,
|
||||
ystate.type,
|
||||
Y.createRelativePositionFromJSON(aw.cursor.anchor),
|
||||
ystate.binding.mapping
|
||||
);
|
||||
let head = relativePositionToAbsolutePosition(
|
||||
y,
|
||||
ystate.type,
|
||||
Y.createRelativePositionFromJSON(aw.cursor.head),
|
||||
ystate.binding.mapping
|
||||
);
|
||||
if (anchor !== null && head !== null) {
|
||||
const maxsize = math.max(state.doc.content.size - 1, 0);
|
||||
anchor = math.min(anchor, maxsize);
|
||||
head = math.min(head, maxsize);
|
||||
decorations.push(Decoration.widget(head, () => createCursor(user), { key: clientId + '', side: 10 }));
|
||||
const from = math.min(anchor, head);
|
||||
const to = math.max(anchor, head);
|
||||
decorations.push(
|
||||
Decoration.inline(
|
||||
from,
|
||||
to,
|
||||
{ style: `background-color: ${user.color}70` },
|
||||
{ inclusiveEnd: true, inclusiveStart: false }
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
return DecorationSet.create(state.doc, decorations);
|
||||
};
|
||||
|
||||
/**
|
||||
* A prosemirror plugin that listens to awareness information on Yjs.
|
||||
* This requires that a `prosemirrorPlugin` is also bound to the prosemirror.
|
||||
*
|
||||
* @public
|
||||
* @param {Awareness} awareness
|
||||
* @param {object} [opts]
|
||||
* @param {function(any):HTMLElement} [opts.cursorBuilder]
|
||||
* @param {function(any):any} [opts.getSelection]
|
||||
* @param {string} [opts.cursorStateField] By default all editor bindings use the awareness 'cursor' field to propagate cursor information.
|
||||
* @return {any}
|
||||
*/
|
||||
export const yCursorPlugin = (
|
||||
awareness,
|
||||
{ cursorBuilder = defaultCursorBuilder, getSelection = (state) => state.selection } = {},
|
||||
cursorStateField = 'cursor'
|
||||
) =>
|
||||
new Plugin({
|
||||
key: yCursorPluginKey,
|
||||
state: {
|
||||
init(_, state) {
|
||||
return createDecorations(state, awareness, cursorBuilder);
|
||||
},
|
||||
apply(tr, prevState, oldState, newState) {
|
||||
const ystate = ySyncPluginKey.getState(newState);
|
||||
const yCursorState = tr.getMeta(yCursorPluginKey);
|
||||
if ((ystate && ystate.isChangeOrigin) || (yCursorState && yCursorState.awarenessUpdated)) {
|
||||
return createDecorations(newState, awareness, cursorBuilder);
|
||||
}
|
||||
return prevState.map(tr.mapping, tr.doc);
|
||||
},
|
||||
},
|
||||
props: {
|
||||
decorations: (state) => {
|
||||
return yCursorPluginKey.getState(state);
|
||||
},
|
||||
},
|
||||
view: (view) => {
|
||||
const awarenessListener = () => {
|
||||
// @ts-ignore
|
||||
if (view.docView) {
|
||||
setMeta(view, yCursorPluginKey, { awarenessUpdated: true });
|
||||
}
|
||||
};
|
||||
const updateCursorInfo = () => {
|
||||
const ystate = ySyncPluginKey.getState(view.state) || view.state['y-sync$'];
|
||||
// @note We make implicit checks when checking for the cursor property
|
||||
const current = awareness.getLocalState() || {};
|
||||
if (view.hasFocus() && ystate.binding !== null) {
|
||||
const selection = getSelection(view.state);
|
||||
/**
|
||||
* @type {Y.RelativePosition}
|
||||
*/
|
||||
const anchor = absolutePositionToRelativePosition(selection.anchor, ystate.type, ystate.binding.mapping);
|
||||
/**
|
||||
* @type {Y.RelativePosition}
|
||||
*/
|
||||
const head = absolutePositionToRelativePosition(selection.head, ystate.type, ystate.binding.mapping);
|
||||
if (
|
||||
current.cursor == null ||
|
||||
!Y.compareRelativePositions(Y.createRelativePositionFromJSON(current.cursor.anchor), anchor) ||
|
||||
!Y.compareRelativePositions(Y.createRelativePositionFromJSON(current.cursor.head), head)
|
||||
) {
|
||||
awareness.setLocalStateField(cursorStateField, {
|
||||
anchor,
|
||||
head,
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
current.cursor != null &&
|
||||
relativePositionToAbsolutePosition(
|
||||
ystate.doc,
|
||||
ystate.type,
|
||||
Y.createRelativePositionFromJSON(current.cursor.anchor),
|
||||
ystate.binding.mapping
|
||||
) !== null
|
||||
) {
|
||||
// delete cursor information if current cursor information is owned by this editor binding
|
||||
awareness.setLocalStateField(cursorStateField, null);
|
||||
}
|
||||
};
|
||||
awareness.on('change', awarenessListener);
|
||||
view.dom.addEventListener('focusin', updateCursorInfo);
|
||||
view.dom.addEventListener('focusout', updateCursorInfo);
|
||||
return {
|
||||
update: updateCursorInfo,
|
||||
destroy: () => {
|
||||
view.dom.removeEventListener('focusin', updateCursorInfo);
|
||||
view.dom.removeEventListener('focusout', updateCursorInfo);
|
||||
awareness.off('change', awarenessListener);
|
||||
awareness.setLocalStateField(cursorStateField, null);
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import { HocuspocusProvider } from '@hocuspocus/provider';
|
||||
import Collaboration from '@tiptap/extension-collaboration';
|
||||
import CollaborationCursor from '@tiptap/extension-collaboration-cursor';
|
||||
import { Collaboration } from './collaboration';
|
||||
import { CollaborationCursor } from './collaborationCursor';
|
||||
import History from '@tiptap/extension-history';
|
||||
import { getRandomColor } from 'helpers/color';
|
||||
import { Document } from './extensions/document';
|
||||
|
|
|
@ -57,8 +57,6 @@ importers:
|
|||
'@tiptap/extension-code': ^2.0.0-beta.26
|
||||
'@tiptap/extension-code-block': ^2.0.0-beta.37
|
||||
'@tiptap/extension-code-block-lowlight': ^2.0.0-beta.68
|
||||
'@tiptap/extension-collaboration': ^2.0.0-beta.33
|
||||
'@tiptap/extension-collaboration-cursor': ^2.0.0-beta.34
|
||||
'@tiptap/extension-color': ^2.0.0-beta.9
|
||||
'@tiptap/extension-document': ^2.0.0-beta.15
|
||||
'@tiptap/extension-dropcursor': ^2.0.0-beta.25
|
||||
|
@ -96,6 +94,7 @@ importers:
|
|||
dompurify: ^2.3.5
|
||||
interactjs: ^1.10.11
|
||||
katex: ^0.15.2
|
||||
lib0: ^0.2.47
|
||||
lowlight: ^2.5.0
|
||||
markdown-it: ^12.3.2
|
||||
markdown-it-anchor: ^8.4.1
|
||||
|
@ -117,6 +116,8 @@ importers:
|
|||
tippy.js: ^6.3.7
|
||||
tsconfig-paths-webpack-plugin: ^3.5.2
|
||||
typescript: 4.5.5
|
||||
y-prosemirror: ^1.0.14
|
||||
yjs: ^13.5.24
|
||||
dependencies:
|
||||
'@douyinfe/semi-icons': 2.3.1_react@17.0.2
|
||||
'@douyinfe/semi-next': 2.3.1
|
||||
|
@ -132,8 +133,6 @@ importers:
|
|||
'@tiptap/extension-code': 2.0.0-beta.26_@tiptap+core@2.0.0-beta.171
|
||||
'@tiptap/extension-code-block': 2.0.0-beta.37_@tiptap+core@2.0.0-beta.171
|
||||
'@tiptap/extension-code-block-lowlight': 2.0.0-beta.68_@tiptap+core@2.0.0-beta.171
|
||||
'@tiptap/extension-collaboration': 2.0.0-beta.33_24052c2d57881e244a8dbd08d556b4fc
|
||||
'@tiptap/extension-collaboration-cursor': 2.0.0-beta.34_24052c2d57881e244a8dbd08d556b4fc
|
||||
'@tiptap/extension-color': 2.0.0-beta.9_e32f4205d0966701340db1456434a591
|
||||
'@tiptap/extension-document': 2.0.0-beta.15_@tiptap+core@2.0.0-beta.171
|
||||
'@tiptap/extension-dropcursor': 2.0.0-beta.25_@tiptap+core@2.0.0-beta.171
|
||||
|
@ -169,6 +168,7 @@ importers:
|
|||
dompurify: 2.3.5
|
||||
interactjs: 1.10.11
|
||||
katex: 0.15.2
|
||||
lib0: 0.2.47
|
||||
lowlight: 2.5.0
|
||||
markdown-it: 12.3.2
|
||||
markdown-it-anchor: 8.4.1_markdown-it@12.3.2
|
||||
|
@ -188,6 +188,8 @@ importers:
|
|||
scroll-into-view-if-needed: 2.2.29
|
||||
swr: 1.2.0_react@17.0.2
|
||||
tippy.js: 6.3.7
|
||||
y-prosemirror: 1.0.14_0fedec857d2fb730ad5b02a71124bf2a
|
||||
yjs: 13.5.24
|
||||
devDependencies:
|
||||
'@types/node': 17.0.13
|
||||
'@types/react': 17.0.38
|
||||
|
@ -917,7 +919,7 @@ packages:
|
|||
dependencies:
|
||||
'@hocuspocus/common': 1.0.0-alpha.4
|
||||
'@lifeomic/attempt': 3.0.2
|
||||
lib0: 0.2.43
|
||||
lib0: 0.2.47
|
||||
y-protocols: 1.0.5
|
||||
yjs: 13.5.24
|
||||
dev: false
|
||||
|
@ -1650,36 +1652,6 @@ packages:
|
|||
'@tiptap/core': 2.0.0-beta.171
|
||||
dev: false
|
||||
|
||||
/@tiptap/extension-collaboration-cursor/2.0.0-beta.34_24052c2d57881e244a8dbd08d556b4fc:
|
||||
resolution: {integrity: sha512-6jxM8jxOXEwRHv7rkWsacC8Q3km83opEK/2udiMEC7a/yFeMKpYjOP+sAvzdGBposlIof/VgjXhbIUBRBqmqLw==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^2.0.0-beta.1
|
||||
dependencies:
|
||||
'@tiptap/core': 2.0.0-beta.171
|
||||
y-prosemirror: 1.0.14_prosemirror-view@1.23.6
|
||||
transitivePeerDependencies:
|
||||
- prosemirror-model
|
||||
- prosemirror-state
|
||||
- prosemirror-view
|
||||
- y-protocols
|
||||
- yjs
|
||||
dev: false
|
||||
|
||||
/@tiptap/extension-collaboration/2.0.0-beta.33_24052c2d57881e244a8dbd08d556b4fc:
|
||||
resolution: {integrity: sha512-KMHJxsS/FSVyum2ds3gfu0WFU1Zu7xQ5YmsSCLXyBxkhDtBGWBZTcpcSh9siWfs26+Fk1ZvcEssNyRYMEummpQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^2.0.0-beta.1
|
||||
dependencies:
|
||||
'@tiptap/core': 2.0.0-beta.171
|
||||
prosemirror-state: 1.3.4
|
||||
y-prosemirror: 1.0.14_fb8440a343abf572e136ee4e217d51fa
|
||||
transitivePeerDependencies:
|
||||
- prosemirror-model
|
||||
- prosemirror-view
|
||||
- y-protocols
|
||||
- yjs
|
||||
dev: false
|
||||
|
||||
/@tiptap/extension-color/2.0.0-beta.9_e32f4205d0966701340db1456434a591:
|
||||
resolution: {integrity: sha512-c8zcaNCdwUwbgrutfsG7LD9KH7ZvDVwKOZHbOL4gMSwdH9s+6r1ThRFLEbKgHIJlTa2jd96qoo+lVfj1Qwp7ww==}
|
||||
peerDependencies:
|
||||
|
@ -5811,6 +5783,13 @@ packages:
|
|||
isomorphic.js: 0.2.4
|
||||
dev: false
|
||||
|
||||
/lib0/0.2.47:
|
||||
resolution: {integrity: sha512-RXprIyaflw7OmFNMpb8HmvDhuRVUFXYCXrmynQN8OGbGevgMx9u6tjQG/yB0dOoDcuB1XXgqFn8Oy3RlKF/Qhg==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
isomorphic.js: 0.2.4
|
||||
dev: false
|
||||
|
||||
/libphonenumber-js/1.9.46:
|
||||
resolution: {integrity: sha512-QqTX4UVsGy24njtCgLRspiKpxfRniRBZE/P+d0vQXuYWQ+hwDS6X0ouo0O/SRyf7bhhMCE71b6vAvLMtY5PfEw==}
|
||||
dev: false
|
||||
|
@ -8521,6 +8500,20 @@ packages:
|
|||
engines: {node: '>=0.4'}
|
||||
dev: false
|
||||
|
||||
/y-prosemirror/1.0.14_0fedec857d2fb730ad5b02a71124bf2a:
|
||||
resolution: {integrity: sha512-fJQn/XT+z/gks9sd64eB+Mf1UQP0d5SHQ8RwbrzIwYFW+FgU/nx8/hJm+nrBAoO9azHOY5aDeoffeLmOFXLD9w==}
|
||||
peerDependencies:
|
||||
prosemirror-model: ^1.7.1
|
||||
prosemirror-state: ^1.2.3
|
||||
prosemirror-view: ^1.9.10
|
||||
y-protocols: ^1.0.1
|
||||
yjs: ^13.3.2
|
||||
dependencies:
|
||||
lib0: 0.2.47
|
||||
prosemirror-view: 1.23.6
|
||||
yjs: 13.5.24
|
||||
dev: false
|
||||
|
||||
/y-prosemirror/1.0.14_8fd72c89aecefb95d86a797b5207d945:
|
||||
resolution: {integrity: sha512-fJQn/XT+z/gks9sd64eB+Mf1UQP0d5SHQ8RwbrzIwYFW+FgU/nx8/hJm+nrBAoO9azHOY5aDeoffeLmOFXLD9w==}
|
||||
peerDependencies:
|
||||
|
@ -8535,37 +8528,10 @@ packages:
|
|||
yjs: 13.5.24
|
||||
dev: false
|
||||
|
||||
/y-prosemirror/1.0.14_fb8440a343abf572e136ee4e217d51fa:
|
||||
resolution: {integrity: sha512-fJQn/XT+z/gks9sd64eB+Mf1UQP0d5SHQ8RwbrzIwYFW+FgU/nx8/hJm+nrBAoO9azHOY5aDeoffeLmOFXLD9w==}
|
||||
peerDependencies:
|
||||
prosemirror-model: ^1.7.1
|
||||
prosemirror-state: ^1.2.3
|
||||
prosemirror-view: ^1.9.10
|
||||
y-protocols: ^1.0.1
|
||||
yjs: ^13.3.2
|
||||
dependencies:
|
||||
lib0: 0.2.43
|
||||
prosemirror-state: 1.3.4
|
||||
prosemirror-view: 1.23.6
|
||||
dev: false
|
||||
|
||||
/y-prosemirror/1.0.14_prosemirror-view@1.23.6:
|
||||
resolution: {integrity: sha512-fJQn/XT+z/gks9sd64eB+Mf1UQP0d5SHQ8RwbrzIwYFW+FgU/nx8/hJm+nrBAoO9azHOY5aDeoffeLmOFXLD9w==}
|
||||
peerDependencies:
|
||||
prosemirror-model: ^1.7.1
|
||||
prosemirror-state: ^1.2.3
|
||||
prosemirror-view: ^1.9.10
|
||||
y-protocols: ^1.0.1
|
||||
yjs: ^13.3.2
|
||||
dependencies:
|
||||
lib0: 0.2.43
|
||||
prosemirror-view: 1.23.6
|
||||
dev: false
|
||||
|
||||
/y-protocols/1.0.5:
|
||||
resolution: {integrity: sha512-Wil92b7cGk712lRHDqS4T90IczF6RkcvCwAD0A2OPg+adKmOe+nOiT/N2hvpQIWS3zfjmtL4CPaH5sIW1Hkm/A==}
|
||||
dependencies:
|
||||
lib0: 0.2.43
|
||||
lib0: 0.2.47
|
||||
dev: false
|
||||
|
||||
/y18n/5.0.8:
|
||||
|
@ -8626,7 +8592,7 @@ packages:
|
|||
resolution: {integrity: sha512-f6DqRfnhjihj4+iQv5zjhsYqOpkcM9SGroqluq6J6eEUTq7ipbgECKf+h5W4P+LU4fKawWFdQH8mxgJ7baZPJw==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
lib0: 0.2.43
|
||||
lib0: 0.2.47
|
||||
dev: false
|
||||
|
||||
/yn/3.1.1:
|
||||
|
|
Loading…
Reference in New Issue