From 8cbfbd71d17644e7f940d27859f8a6ac583f54e8 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Wed, 4 May 2022 00:52:33 +0800 Subject: [PATCH] refactor: improve tiptap --- packages/client/package.json | 1 + .../src/components/data-render/index.tsx | 5 +- .../src/components/data-render/loading.tsx | 19 +- .../components/document/comments/index.tsx | 5 +- .../src/components/document/editor/editor.tsx | 219 +++--------------- .../document/editor/index.module.scss | 61 ++--- .../src/components/document/editor/index.tsx | 7 +- .../src/components/document/reader/editor.tsx | 117 ---------- .../src/components/document/reader/index.tsx | 124 +++++++--- .../document/reader/public/content.tsx | 34 --- .../document/reader/public/index.tsx | 25 +- .../src/components/document/reader/user.tsx | 48 ---- .../src/components/document/version/index.tsx | 4 +- .../src/components/template/editor/editor.tsx | 78 +------ .../template/editor/index.module.scss | 63 ++--- .../components/template/editor/useEditor.tsx | 35 --- .../src/components/template/reader/editor.tsx | 79 ------- .../template/reader/index.module.scss | 32 --- .../src/components/template/reader/index.tsx | 10 +- .../client/src/components/wiki/tocs/tree.tsx | 2 +- packages/client/src/data/comment.ts | 4 +- packages/client/src/data/document.ts | 12 +- packages/client/src/data/template.ts | 4 +- packages/client/src/data/wiki.tsx | 14 +- packages/client/src/pages/_app.tsx | 3 +- .../client/src/pages/feature/editor/index.tsx | 29 +++ packages/client/src/styles/reset.scss | 37 --- .../color-picker/index.tsx | 0 .../color-picker/style.module.scss | 0 .../src/tiptap/{ => components}/divider.tsx | 0 .../_components => components}/size.tsx | 0 .../src/tiptap/{ => components}/skeleton.tsx | 0 .../client/src/tiptap/{ => core}/constants.ts | 0 .../{ => core}/extensions/attachment.ts | 2 +- .../{ => core}/extensions/background-color.ts | 0 .../{ => core}/extensions/blockquote.ts | 3 +- .../src/tiptap/{ => core}/extensions/bold.ts | 0 .../{ => core}/extensions/bullet-list.ts | 2 +- .../tiptap/{ => core}/extensions/callout.ts | 2 +- .../{ => core}/extensions/code-block.ts | 2 +- .../src/tiptap/{ => core}/extensions/code.ts | 2 +- .../cursor-plugin/index.ts | 0 .../extensions/collaboration-cursor/index.ts | 0 .../extensions/collaboration/collaboration.ts | 0 .../collaboration/helpers/is-change-origin.ts | 0 .../extensions/collaboration/index.ts | 0 .../extensions/color-highlighter.ts | 0 .../src/tiptap/{ => core}/extensions/color.ts | 0 .../tiptap/{ => core}/extensions/countdown.ts | 2 +- .../extensions/document-children.ts | 2 +- .../extensions/document-reference.ts | 2 +- .../tiptap/{ => core}/extensions/document.ts | 0 .../{ => core}/extensions/dropcursor.ts | 0 .../src/tiptap/{ => core}/extensions/emoji.ts | 6 +- .../tiptap/core/extensions/event-emitter.ts | 19 ++ .../src/tiptap/{ => core}/extensions/focus.ts | 0 .../tiptap/{ => core}/extensions/font-size.ts | 0 .../tiptap/{ => core}/extensions/gapcursor.ts | 0 .../{ => core}/extensions/hard-break.ts | 0 .../tiptap/{ => core}/extensions/heading.ts | 0 .../{ => core}/extensions/horizontal-rule.ts | 0 .../{ => core}/extensions/html-marks.ts | 2 +- .../tiptap/{ => core}/extensions/iframe.ts | 2 +- .../src/tiptap/{ => core}/extensions/image.ts | 2 +- .../tiptap/{ => core}/extensions/indent.ts | 0 .../tiptap/{ => core}/extensions/italic.ts | 0 .../src/tiptap/{ => core}/extensions/katex.ts | 2 +- .../src/tiptap/{ => core}/extensions/link.ts | 0 .../tiptap/{ => core}/extensions/listItem.ts | 0 .../tiptap/{ => core}/extensions/loading.ts | 2 +- .../tiptap/{ => core}/extensions/mention.ts | 2 +- .../src/tiptap/{ => core}/extensions/mind.ts | 2 +- .../{ => core}/extensions/ordered-list.ts | 2 +- .../tiptap/{ => core}/extensions/paragraph.ts | 0 .../src/tiptap/{ => core}/extensions/paste.ts | 59 +++-- .../{ => core}/extensions/placeholder.ts | 0 .../{ => core}/extensions/quick-insert.tsx | 6 +- .../tiptap/{ => core}/extensions/search.ts | 0 .../tiptap/{ => core}/extensions/selection.ts | 2 +- .../tiptap/{ => core}/extensions/status.ts | 2 +- .../tiptap/{ => core}/extensions/strike.ts | 0 .../tiptap/{ => core}/extensions/subscript.ts | 0 .../{ => core}/extensions/superscript.ts | 0 .../{ => core}/extensions/table-cell.tsx | 0 .../{ => core}/extensions/table-header.tsx | 0 .../tiptap/{ => core}/extensions/table-row.ts | 0 .../src/tiptap/{ => core}/extensions/table.ts | 0 .../tiptap/{ => core}/extensions/task-item.ts | 2 +- .../tiptap/{ => core}/extensions/task-list.ts | 2 +- .../{ => core}/extensions/text-align.ts | 0 .../{ => core}/extensions/text-style.ts | 0 .../src/tiptap/{ => core}/extensions/text.ts | 0 .../tiptap/{ => core}/extensions/title.tsx | 0 .../{ => core}/extensions/trailing-node.ts | 0 .../tiptap/{ => core}/extensions/underline.ts | 0 .../src/tiptap/{ => core}/styles/base.scss | 0 .../src/tiptap/{ => core}/styles/code.scss | 0 .../{ => core}/styles/collaboration.scss | 0 .../src/tiptap/{ => core}/styles/color.scss | 0 .../src/tiptap/{ => core}/styles/heading.scss | 0 .../src/tiptap/{ => core}/styles/index.scss | 0 .../src/tiptap/{ => core}/styles/katex.scss | 0 .../src/tiptap/{ => core}/styles/list.scss | 0 .../src/tiptap/{ => core}/styles/lock.scss | 0 .../src/tiptap/{ => core}/styles/mention.scss | 0 .../src/tiptap/{ => core}/styles/menu.scss | 0 .../{ => core}/styles/mind/context-menu.scss | 0 .../tiptap/{ => core}/styles/mind/index.scss | 0 .../tiptap/{ => core}/styles/mind/mind.scss | 0 .../{ => core}/styles/mind/mobile-menu.scss | 0 .../{ => core}/styles/mind/node-menu.scss | 0 .../{ => core}/styles/mind/toolbar.scss | 0 .../src/tiptap/{ => core}/styles/node.scss | 0 .../tiptap/{ => core}/styles/placeholder.scss | 0 .../src/tiptap/{ => core}/styles/search.scss | 0 .../tiptap/{ => core}/styles/selection.scss | 0 .../src/tiptap/{ => core}/styles/table.scss | 2 + .../src/tiptap/{ => core}/styles/title.scss | 0 .../src/tiptap/{ => core}/styles/var.scss | 0 .../wrappers/attachment/file-icon.tsx | 0 .../wrappers/attachment/index.module.scss | 0 .../{ => core}/wrappers/attachment/index.tsx | 0 .../attachment/player/index.module.scss | 0 .../wrappers/attachment/player/index.tsx | 0 .../player/pdf-player/index.module.scss | 0 .../attachment/player/pdf-player/index.tsx | 0 .../wrappers/callout/index.module.scss | 0 .../{ => core}/wrappers/callout/index.tsx | 0 .../wrappers/code-block/index.module.scss | 0 .../{ => core}/wrappers/code-block/index.tsx | 0 .../wrappers/countdown/index.module.scss | 0 .../{ => core}/wrappers/countdown/index.tsx | 0 .../document-children/index.module.scss | 0 .../wrappers/document-children/index.tsx | 0 .../document-reference/index.module.scss | 0 .../wrappers/document-reference/index.tsx | 0 .../{ => core}/wrappers/emoji-list/emojis.ts | 0 .../wrappers/emoji-list/index.module.scss | 0 .../{ => core}/wrappers/emoji-list/index.tsx | 0 .../wrappers/iframe/index.module.scss | 0 .../{ => core}/wrappers/iframe/index.tsx | 0 .../wrappers/image/index.module.scss | 0 .../{ => core}/wrappers/image/index.tsx | 0 .../wrappers/katex/index.module.scss | 0 .../{ => core}/wrappers/katex/index.tsx | 0 .../tiptap/{ => core}/wrappers/loading.tsx | 0 .../wrappers/mention-list/index.module.scss | 0 .../wrappers/mention-list/index.tsx | 0 .../wrappers/menu-list/index.module.scss | 0 .../{ => core}/wrappers/menu-list/index.tsx | 0 .../wrappers/mind/index.module.scss | 0 .../tiptap/{ => core}/wrappers/mind/index.tsx | 2 +- .../wrappers/mind/mind-elixir/const.ts | 0 .../wrappers/mind/mind-elixir/customLink.ts | 0 .../wrappers/mind/mind-elixir/i18n.ts | 0 .../mind/mind-elixir/iconfont/iconfont.js | 61 +++++ .../wrappers/mind/mind-elixir/index.ts | 2 +- .../wrappers/mind/mind-elixir/interact.ts | 0 .../wrappers/mind/mind-elixir/linkDiv.ts | 0 .../wrappers/mind/mind-elixir/mouse.ts | 0 .../mind/mind-elixir/nodeOperation.ts | 0 .../mind/mind-elixir/plugin/contextMenu.ts | 0 .../mind/mind-elixir/plugin/keypress.ts | 0 .../mind/mind-elixir/plugin/mobileMenu.ts | 0 .../mind/mind-elixir/plugin/nodeDraggable.ts | 0 .../mind/mind-elixir/plugin/nodeMenu.tsx | 2 +- .../mind/mind-elixir/plugin/toolBar.tsx | 2 +- .../wrappers/mind/mind-elixir/utils/dom.ts | 2 +- .../wrappers/mind/mind-elixir/utils/index.ts | 0 .../wrappers/mind/mind-elixir/utils/pubsub.ts | 0 .../wrappers/mind/mind-elixir/utils/svg.ts | 0 .../wrappers/status/index.module.scss | 0 .../{ => core}/wrappers/status/index.tsx | 0 .../wrappers/task-item/index.module.scss | 0 .../{ => core}/wrappers/task-item/index.tsx | 0 .../collaboration/collaboration/editor.tsx | 115 +++++++++ .../collaboration/index.module.scss | 26 +++ .../collaboration/collaboration/index.tsx | 140 +++++++++++ .../collaboration/collaboration/menubar.tsx | 119 ++++++++++ .../collaboration/collaboration/type.ts | 48 ++++ .../src/tiptap/editor/collaboration/index.tsx | 4 + .../src/tiptap/editor/collaboration/kit.ts | 144 ++++++++++++ .../tiptap/editor/collaboration/reader.tsx | 27 +++ .../client/src/tiptap/editor/comment/index.ts | 2 + .../client/src/tiptap/editor/comment/kit.ts | 103 ++++++++ .../src/tiptap/editor/comment/menubar.tsx | 48 ++++ .../tiptap/{ => editor}/hooks/use-active.tsx | 0 .../{ => editor}/hooks/use-attributes.tsx | 0 packages/client/src/tiptap/editor/index.tsx | 3 + .../client/src/tiptap/editor/menus/_event.ts | 34 +++ .../tiptap/{ => editor}/menus/align/index.tsx | 6 +- .../{ => editor}/menus/attachment/bubble.tsx | 6 +- .../{ => editor}/menus/attachment/index.tsx | 2 +- .../menus/background-color/index.tsx | 10 +- .../{ => editor}/menus/blockquote/index.tsx | 8 +- .../tiptap/{ => editor}/menus/bold/index.tsx | 8 +- .../{ => editor}/menus/bullet-list/index.tsx | 8 +- .../menus/callout/bubble.module.scss | 0 .../{ => editor}/menus/callout/bubble.tsx | 8 +- .../{ => editor}/menus/callout/index.tsx | 2 +- .../menus/clear-node-and-marks/index.tsx | 2 +- .../{ => editor}/menus/code-block/bubble.tsx | 6 +- .../{ => editor}/menus/code-block/index.tsx | 2 +- .../tiptap/{ => editor}/menus/code/index.tsx | 8 +- .../{ => editor}/menus/countdown/bubble.tsx | 12 +- .../{ => editor}/menus/countdown/index.tsx | 2 +- .../{ => editor}/menus/countdown/modal.tsx | 10 +- .../{ => editor}/menus/countdown/service.ts | 2 +- .../menus/document-children/bubble.tsx | 6 +- .../menus/document-children/index.tsx | 2 +- .../menus/document-reference/bubble.tsx | 6 +- .../menus/document-reference/index.tsx | 2 +- .../tiptap/{ => editor}/menus/emoji/index.tsx | 2 +- .../{ => editor}/menus/fontsize/index.tsx | 8 +- .../{ => editor}/menus/heading/index.tsx | 6 +- .../menus/horizontal-rule/index.tsx | 6 +- .../tiptap/{ => editor}/menus/ident/index.tsx | 6 +- .../{ => editor}/menus/iframe/bubble.tsx | 10 +- .../{ => editor}/menus/iframe/index.tsx | 2 +- .../{ => editor}/menus/image/bubble.tsx | 10 +- .../tiptap/{ => editor}/menus/image/index.tsx | 2 +- .../{ => editor}/menus/insert/index.tsx | 6 +- .../{ => editor}/menus/italic/index.tsx | 8 +- .../tiptap/{ => editor}/menus/link/bubble.tsx | 8 +- .../tiptap/{ => editor}/menus/link/index.tsx | 8 +- .../tiptap/{ => editor}/menus/link/modal.tsx | 8 +- .../tiptap/{ => editor}/menus/link/service.ts | 4 +- .../tiptap/{ => editor}/menus/mind/bubble.tsx | 10 +- .../tiptap/{ => editor}/menus/mind/index.tsx | 2 +- .../{ => editor}/menus/ordered-list/index.tsx | 8 +- .../{ => editor}/menus/quick-insert.tsx | 2 +- .../tiptap/{ => editor}/menus/redo/index.tsx | 2 +- .../{ => editor}/menus/search/index.tsx | 4 +- .../{ => editor}/menus/strike/index.tsx | 8 +- .../{ => editor}/menus/subscript/index.tsx | 6 +- .../{ => editor}/menus/superscript/index.tsx | 6 +- .../{ => editor}/menus/table/bubble.tsx | 6 +- .../tiptap/{ => editor}/menus/table/index.tsx | 2 +- .../{ => editor}/menus/task-list/index.tsx | 8 +- .../{ => editor}/menus/text-color/index.tsx | 12 +- .../{ => editor}/menus/underline/index.tsx | 6 +- .../tiptap/{ => editor}/menus/undo/index.tsx | 2 +- .../client/src/tiptap/editor/react/index.tsx | 4 + .../tiptap/{ => editor}/react/useEditor.tsx | 8 +- .../views/bubble-menu/bubble-menu-plugin.tsx | 1 - .../{ => editor}/views/bubble-menu/index.tsx | 0 .../tiptap/{ => editor}/views/float-menu.tsx | 0 .../tiptap/{index.ts => fix-match-nodes.ts} | 8 - packages/client/src/tiptap/indexdb.ts | 20 -- .../html-to-prosemirror/all-kit.tsx | 133 +++++++++++ .../html-to-prosemirror/utils.ts | 4 +- .../markdown-to-prosemirror/index.tsx | 3 - .../markdown/prosemirror-to-markdown/index.ts | 77 +++--- packages/client/src/tiptap/menubar.tsx | 147 ------------ packages/client/src/tiptap/menus/_event.ts | 13 -- .../src/tiptap/prose-utils/copy-node.ts | 7 +- .../client/src/tiptap/prose-utils/index.ts | 2 + .../markdown-source-map.ts | 0 .../helpers.ts => prose-utils/markdown.ts} | 2 +- .../client/src/tiptap/prose-utils/mention.ts | 2 +- .../client/src/tiptap/prose-utils/upload.ts | 6 +- packages/client/src/tiptap/provider.ts | 64 ----- packages/client/src/tiptap/react/index.tsx | 4 - packages/client/src/tiptap/start-kit.tsx | 198 ---------------- .../mind/mind-elixir/iconfont/iconfont.js | 1 - packages/client/tsconfig.json | 1 + .../src/services/collaboration.service.ts | 37 +-- .../src/services/document-version.service.ts | 6 +- pnpm-lock.yaml | 10 + 269 files changed, 1617 insertions(+), 1527 deletions(-) delete mode 100644 packages/client/src/components/document/reader/editor.tsx delete mode 100644 packages/client/src/components/document/reader/public/content.tsx delete mode 100644 packages/client/src/components/document/reader/user.tsx delete mode 100644 packages/client/src/components/template/editor/useEditor.tsx delete mode 100644 packages/client/src/components/template/reader/editor.tsx delete mode 100644 packages/client/src/components/template/reader/index.module.scss create mode 100644 packages/client/src/pages/feature/editor/index.tsx rename packages/client/src/tiptap/{menus/_components => components}/color-picker/index.tsx (100%) rename packages/client/src/tiptap/{menus/_components => components}/color-picker/style.module.scss (100%) rename packages/client/src/tiptap/{ => components}/divider.tsx (100%) rename packages/client/src/tiptap/{menus/_components => components}/size.tsx (100%) rename packages/client/src/tiptap/{ => components}/skeleton.tsx (100%) rename packages/client/src/tiptap/{ => core}/constants.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/attachment.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/background-color.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/blockquote.ts (88%) rename packages/client/src/tiptap/{ => core}/extensions/bold.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/bullet-list.ts (84%) rename packages/client/src/tiptap/{ => core}/extensions/callout.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/code-block.ts (99%) rename packages/client/src/tiptap/{ => core}/extensions/code.ts (81%) rename packages/client/src/tiptap/{ => core}/extensions/collaboration-cursor/cursor-plugin/index.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/collaboration-cursor/index.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/collaboration/collaboration.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/collaboration/helpers/is-change-origin.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/collaboration/index.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/color-highlighter.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/color.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/countdown.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/document-children.ts (94%) rename packages/client/src/tiptap/{ => core}/extensions/document-reference.ts (95%) rename packages/client/src/tiptap/{ => core}/extensions/document.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/dropcursor.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/emoji.ts (94%) create mode 100644 packages/client/src/tiptap/core/extensions/event-emitter.ts rename packages/client/src/tiptap/{ => core}/extensions/focus.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/font-size.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/gapcursor.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/hard-break.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/heading.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/horizontal-rule.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/html-marks.ts (94%) rename packages/client/src/tiptap/{ => core}/extensions/iframe.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/image.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/indent.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/italic.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/katex.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/link.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/listItem.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/loading.ts (85%) rename packages/client/src/tiptap/{ => core}/extensions/mention.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/mind.ts (98%) rename packages/client/src/tiptap/{ => core}/extensions/ordered-list.ts (81%) rename packages/client/src/tiptap/{ => core}/extensions/paragraph.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/paste.ts (81%) rename packages/client/src/tiptap/{ => core}/extensions/placeholder.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/quick-insert.tsx (95%) rename packages/client/src/tiptap/{ => core}/extensions/search.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/selection.ts (98%) rename packages/client/src/tiptap/{ => core}/extensions/status.ts (96%) rename packages/client/src/tiptap/{ => core}/extensions/strike.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/subscript.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/superscript.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/table-cell.tsx (100%) rename packages/client/src/tiptap/{ => core}/extensions/table-header.tsx (100%) rename packages/client/src/tiptap/{ => core}/extensions/table-row.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/table.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/task-item.ts (98%) rename packages/client/src/tiptap/{ => core}/extensions/task-list.ts (79%) rename packages/client/src/tiptap/{ => core}/extensions/text-align.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/text-style.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/text.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/title.tsx (100%) rename packages/client/src/tiptap/{ => core}/extensions/trailing-node.ts (100%) rename packages/client/src/tiptap/{ => core}/extensions/underline.ts (100%) rename packages/client/src/tiptap/{ => core}/styles/base.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/code.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/collaboration.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/color.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/heading.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/index.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/katex.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/list.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/lock.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/mention.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/menu.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/mind/context-menu.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/mind/index.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/mind/mind.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/mind/mobile-menu.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/mind/node-menu.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/mind/toolbar.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/node.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/placeholder.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/search.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/selection.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/table.scss (96%) rename packages/client/src/tiptap/{ => core}/styles/title.scss (100%) rename packages/client/src/tiptap/{ => core}/styles/var.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/attachment/file-icon.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/attachment/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/attachment/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/attachment/player/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/attachment/player/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/attachment/player/pdf-player/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/attachment/player/pdf-player/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/callout/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/callout/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/code-block/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/code-block/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/countdown/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/countdown/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/document-children/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/document-children/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/document-reference/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/document-reference/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/emoji-list/emojis.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/emoji-list/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/emoji-list/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/iframe/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/iframe/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/image/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/image/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/katex/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/katex/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/loading.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mention-list/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mention-list/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/menu-list/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/menu-list/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/index.tsx (98%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/const.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/customLink.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/i18n.ts (100%) create mode 100644 packages/client/src/tiptap/core/wrappers/mind/mind-elixir/iconfont/iconfont.js rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/index.ts (99%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/interact.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/linkDiv.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/mouse.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/nodeOperation.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/plugin/contextMenu.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/plugin/keypress.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/plugin/mobileMenu.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/plugin/nodeDraggable.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/plugin/nodeMenu.tsx (99%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/plugin/toolBar.tsx (98%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/utils/dom.ts (99%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/utils/index.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/utils/pubsub.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/mind/mind-elixir/utils/svg.ts (100%) rename packages/client/src/tiptap/{ => core}/wrappers/status/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/status/index.tsx (100%) rename packages/client/src/tiptap/{ => core}/wrappers/task-item/index.module.scss (100%) rename packages/client/src/tiptap/{ => core}/wrappers/task-item/index.tsx (100%) create mode 100644 packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx create mode 100644 packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss create mode 100644 packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx create mode 100644 packages/client/src/tiptap/editor/collaboration/collaboration/menubar.tsx create mode 100644 packages/client/src/tiptap/editor/collaboration/collaboration/type.ts create mode 100644 packages/client/src/tiptap/editor/collaboration/index.tsx create mode 100644 packages/client/src/tiptap/editor/collaboration/kit.ts create mode 100644 packages/client/src/tiptap/editor/collaboration/reader.tsx create mode 100644 packages/client/src/tiptap/editor/comment/index.ts create mode 100644 packages/client/src/tiptap/editor/comment/kit.ts create mode 100644 packages/client/src/tiptap/editor/comment/menubar.tsx rename packages/client/src/tiptap/{ => editor}/hooks/use-active.tsx (100%) rename packages/client/src/tiptap/{ => editor}/hooks/use-attributes.tsx (100%) create mode 100644 packages/client/src/tiptap/editor/index.tsx create mode 100644 packages/client/src/tiptap/editor/menus/_event.ts rename packages/client/src/tiptap/{ => editor}/menus/align/index.tsx (92%) rename packages/client/src/tiptap/{ => editor}/menus/attachment/bubble.tsx (86%) rename packages/client/src/tiptap/{ => editor}/menus/attachment/index.tsx (85%) rename packages/client/src/tiptap/{ => editor}/menus/background-color/index.tsx (82%) rename packages/client/src/tiptap/{ => editor}/menus/blockquote/index.tsx (76%) rename packages/client/src/tiptap/{ => editor}/menus/bold/index.tsx (74%) rename packages/client/src/tiptap/{ => editor}/menus/bullet-list/index.tsx (75%) rename packages/client/src/tiptap/{ => editor}/menus/callout/bubble.module.scss (100%) rename packages/client/src/tiptap/{ => editor}/menus/callout/bubble.tsx (94%) rename packages/client/src/tiptap/{ => editor}/menus/callout/index.tsx (84%) rename packages/client/src/tiptap/{ => editor}/menus/clear-node-and-marks/index.tsx (93%) rename packages/client/src/tiptap/{ => editor}/menus/code-block/bubble.tsx (87%) rename packages/client/src/tiptap/{ => editor}/menus/code-block/index.tsx (85%) rename packages/client/src/tiptap/{ => editor}/menus/code/index.tsx (74%) rename packages/client/src/tiptap/{ => editor}/menus/countdown/bubble.tsx (82%) rename packages/client/src/tiptap/{ => editor}/menus/countdown/index.tsx (89%) rename packages/client/src/tiptap/{ => editor}/menus/countdown/modal.tsx (83%) rename packages/client/src/tiptap/{ => editor}/menus/countdown/service.ts (83%) rename packages/client/src/tiptap/{ => editor}/menus/document-children/bubble.tsx (86%) rename packages/client/src/tiptap/{ => editor}/menus/document-children/index.tsx (86%) rename packages/client/src/tiptap/{ => editor}/menus/document-reference/bubble.tsx (94%) rename packages/client/src/tiptap/{ => editor}/menus/document-reference/index.tsx (86%) rename packages/client/src/tiptap/{ => editor}/menus/emoji/index.tsx (95%) rename packages/client/src/tiptap/{ => editor}/menus/fontsize/index.tsx (80%) rename packages/client/src/tiptap/{ => editor}/menus/heading/index.tsx (92%) rename packages/client/src/tiptap/{ => editor}/menus/horizontal-rule/index.tsx (81%) rename packages/client/src/tiptap/{ => editor}/menus/ident/index.tsx (87%) rename packages/client/src/tiptap/{ => editor}/menus/iframe/bubble.tsx (93%) rename packages/client/src/tiptap/{ => editor}/menus/iframe/index.tsx (84%) rename packages/client/src/tiptap/{ => editor}/menus/image/bubble.tsx (92%) rename packages/client/src/tiptap/{ => editor}/menus/image/index.tsx (84%) rename packages/client/src/tiptap/{ => editor}/menus/insert/index.tsx (97%) rename packages/client/src/tiptap/{ => editor}/menus/italic/index.tsx (74%) rename packages/client/src/tiptap/{ => editor}/menus/link/bubble.tsx (92%) rename packages/client/src/tiptap/{ => editor}/menus/link/index.tsx (81%) rename packages/client/src/tiptap/{ => editor}/menus/link/modal.tsx (89%) rename packages/client/src/tiptap/{ => editor}/menus/link/service.ts (77%) rename packages/client/src/tiptap/{ => editor}/menus/mind/bubble.tsx (86%) rename packages/client/src/tiptap/{ => editor}/menus/mind/index.tsx (84%) rename packages/client/src/tiptap/{ => editor}/menus/ordered-list/index.tsx (76%) rename packages/client/src/tiptap/{ => editor}/menus/quick-insert.tsx (99%) rename packages/client/src/tiptap/{ => editor}/menus/redo/index.tsx (92%) rename packages/client/src/tiptap/{ => editor}/menus/search/index.tsx (96%) rename packages/client/src/tiptap/{ => editor}/menus/strike/index.tsx (74%) rename packages/client/src/tiptap/{ => editor}/menus/subscript/index.tsx (76%) rename packages/client/src/tiptap/{ => editor}/menus/superscript/index.tsx (76%) rename packages/client/src/tiptap/{ => editor}/menus/table/bubble.tsx (96%) rename packages/client/src/tiptap/{ => editor}/menus/table/index.tsx (82%) rename packages/client/src/tiptap/{ => editor}/menus/task-list/index.tsx (76%) rename packages/client/src/tiptap/{ => editor}/menus/text-color/index.tsx (81%) rename packages/client/src/tiptap/{ => editor}/menus/underline/index.tsx (80%) rename packages/client/src/tiptap/{ => editor}/menus/undo/index.tsx (92%) create mode 100644 packages/client/src/tiptap/editor/react/index.tsx rename packages/client/src/tiptap/{ => editor}/react/useEditor.tsx (73%) rename packages/client/src/tiptap/{ => editor}/views/bubble-menu/bubble-menu-plugin.tsx (99%) rename packages/client/src/tiptap/{ => editor}/views/bubble-menu/index.tsx (100%) rename packages/client/src/tiptap/{ => editor}/views/float-menu.tsx (100%) rename packages/client/src/tiptap/{index.ts => fix-match-nodes.ts} (61%) delete mode 100644 packages/client/src/tiptap/indexdb.ts create mode 100644 packages/client/src/tiptap/markdown/markdown-to-prosemirror/html-to-prosemirror/all-kit.tsx delete mode 100644 packages/client/src/tiptap/menubar.tsx delete mode 100644 packages/client/src/tiptap/menus/_event.ts rename packages/client/src/tiptap/{markdown/markdown-to-prosemirror => prose-utils}/markdown-source-map.ts (100%) rename packages/client/src/tiptap/{markdown/markdown-to-prosemirror/helpers.ts => prose-utils/markdown.ts} (94%) delete mode 100644 packages/client/src/tiptap/provider.ts delete mode 100644 packages/client/src/tiptap/react/index.tsx delete mode 100644 packages/client/src/tiptap/start-kit.tsx delete mode 100644 packages/client/src/tiptap/wrappers/mind/mind-elixir/iconfont/iconfont.js diff --git a/packages/client/package.json b/packages/client/package.json index 4dfb0088..bfe92824 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -83,6 +83,7 @@ "react-split-pane": "^0.1.92", "scroll-into-view-if-needed": "^2.2.29", "swr": "^1.2.0", + "tilg": "^0.1.1", "tippy.js": "^6.3.7", "toggle-selection": "^1.0.6", "viewerjs": "^1.10.4", diff --git a/packages/client/src/components/data-render/index.tsx b/packages/client/src/components/data-render/index.tsx index 0e3db44a..78465e76 100644 --- a/packages/client/src/components/data-render/index.tsx +++ b/packages/client/src/components/data-render/index.tsx @@ -69,8 +69,9 @@ export const DataRender: React.FC = ({ return ( ); }; diff --git a/packages/client/src/components/data-render/loading.tsx b/packages/client/src/components/data-render/loading.tsx index dc4fae56..480c6273 100644 --- a/packages/client/src/components/data-render/loading.tsx +++ b/packages/client/src/components/data-render/loading.tsx @@ -1,14 +1,15 @@ import React, { useEffect, useRef } from 'react'; import { useToggle } from 'hooks/use-toggle'; -interface IProps { - loading: boolean; - delay?: number; - loadingContent: React.ReactElement; - normalContent: React.ReactElement; -} +// interface IProps { +// loading: boolean; +// delay?: number; +// runRender +// loadingContent: React.ReactElement; +// normalContent: React.ReactElement; +// } -export const LoadingWrap: React.FC = ({ loading, delay = 200, loadingContent, normalContent }) => { +export const LoadingWrap = ({ loading, delay = 200, runRender, loadingContent, normalContent }) => { const timer = useRef>(null); const [showLoading, toggleShowLoading] = useToggle(false); @@ -31,8 +32,8 @@ export const LoadingWrap: React.FC = ({ loading, delay = 200, loadingCon }, [delay, loading, toggleShowLoading]); if (loading) { - return showLoading ? loadingContent : null; + return showLoading ? runRender(loadingContent) : null; } - return normalContent; + return runRender(normalContent); }; diff --git a/packages/client/src/components/document/comments/index.tsx b/packages/client/src/components/document/comments/index.tsx index 92130739..74912aa5 100644 --- a/packages/client/src/components/document/comments/index.tsx +++ b/packages/client/src/components/document/comments/index.tsx @@ -1,8 +1,7 @@ import React, { useRef, useState } from 'react'; -import { useEditor, EditorContent } from '@tiptap/react'; import { Avatar, Button, Space, Typography, Banner, Pagination } from '@douyinfe/semi-ui'; import { useToggle } from 'hooks/use-toggle'; -import { CommentKit, Document, History, CommentMenuBar } from 'tiptap'; +import { CommentKit, CommentMenuBar, useEditor, EditorContent } from 'tiptap/editor'; import { DataRender } from 'components/data-render'; import { useUser } from 'data/user'; import { useComments } from 'data/comment'; @@ -34,7 +33,7 @@ export const CommentEditor: React.FC = ({ documentId }) => { const editor = useEditor({ editable: true, - extensions: [...CommentKit, Document, History], + extensions: CommentKit, }); const openEditor = () => { diff --git a/packages/client/src/components/document/editor/editor.tsx b/packages/client/src/components/document/editor/editor.tsx index 65b480f3..160b3014 100644 --- a/packages/client/src/components/document/editor/editor.tsx +++ b/packages/client/src/components/document/editor/editor.tsx @@ -1,33 +1,12 @@ import Router from 'next/router'; -import React, { useMemo, useEffect, useState, useRef } from 'react'; +import React, { useEffect, useState, useRef } from 'react'; import cls from 'classnames'; -import deepEqual from 'deep-equal'; -import { BackTop, Toast, Spin, Typography } from '@douyinfe/semi-ui'; import { ILoginUser, IAuthority } from '@think/domains'; -import { SecureDocumentIllustration } from 'illustrations/secure-document'; import { useToggle } from 'hooks/use-toggle'; -import { useNetwork } from 'hooks/use-network'; -import { - useEditor, - EditorContent, - MenuBar, - BaseKit, - DocumentWithTitle, - getCollaborationExtension, - getCollaborationCursorExtension, - getProvider, - destoryProvider, - ProviderStatus, - getIndexdbProvider, - destoryIndexdbProvider, -} from 'tiptap'; import { findMentions } from 'tiptap/prose-utils'; import { useCollaborationDocument } from 'data/document'; -import { DataRender } from 'components/data-render'; -import { Banner } from 'components/banner'; -import { LogoName } from 'components/logo'; -import { debounce } from 'helpers/debounce'; import { event, triggerChangeDocumentTitle, triggerJoinUser, USE_DOCUMENT_VERSION } from 'event'; +import { CollaborationEditor, ICollaborationRefProps } from 'tiptap/editor'; import { DocumentUserSetting } from './users'; import styles from './index.module.scss'; @@ -39,93 +18,31 @@ interface IProps { style: React.CSSProperties; } -const { Text } = Typography; - -export const _Editor: React.FC = ({ user: currentUser, documentId, authority, className, style }) => { +export const Editor: React.FC = ({ user: currentUser, documentId, authority, className, style }) => { const $hasShowUserSettingModal = useRef(false); + const $editor = useRef(); const { users, addUser, updateUser } = useCollaborationDocument(documentId); - const [status, setStatus] = useState('connecting'); - const { online } = useNetwork(); - const [loading, toggleLoading] = useToggle(true); - const [error, setError] = useState(null); - const provider = useMemo(() => { - return getProvider({ - targetId: documentId, - token: currentUser.token, - cacheType: 'EDITOR', - user: currentUser, - docType: 'document', - events: { - onAwarenessUpdate({ states }) { - triggerJoinUser(states); - }, - onAuthenticationFailed() { - toggleLoading(false); - setError(new Error('鉴权失败!暂时无法提供服务')); - }, - onSynced() { - toggleLoading(false); - }, - onStatus({ status }) { - setStatus(status); - }, - }, - }); - }, [documentId, currentUser, toggleLoading]); - const editor = useEditor( - { - editable: authority && authority.editable, - extensions: [ - ...BaseKit, - DocumentWithTitle, - getCollaborationExtension(provider), - getCollaborationCursorExtension(provider, currentUser), - ], - onTransaction: debounce(({ transaction }) => { - try { - const title = transaction.doc.content.firstChild.content.firstChild.textContent; - triggerChangeDocumentTitle(title); - } catch (e) { - // - } - }, 50), - onDestroy() { - destoryProvider(provider, 'EDITOR'); - }, - }, - [authority, provider] - ); const [mentionUsersSettingVisible, toggleMentionUsersSettingVisible] = useToggle(false); const [mentionUsers, setMentionUsers] = useState([]); useEffect(() => { - if (!authority || !authority.editable) return; - - const indexdbProvider = getIndexdbProvider(documentId, provider.document); - - indexdbProvider.on('synced', () => { - setStatus('loadCacheSuccess'); - }); - - return () => { - destoryIndexdbProvider(documentId); + const handler = (data) => { + const editor = $editor.current && $editor.current.getEditor(); + if (!editor) return; + editor.commands.setContent(data); }; - }, [documentId, provider, authority]); - - useEffect(() => { - if (!editor) return; - const handler = (data) => editor.commands.setContent(data); event.on(USE_DOCUMENT_VERSION, handler); return () => { event.off(USE_DOCUMENT_VERSION, handler); }; - }, [editor]); + }, []); useEffect(() => { - if (!editor) return; - const handler = () => { + const editor = $editor.current && $editor.current.getEditor(); + if (!editor) return; + // 已经拦截过一次,不再拦截 if ($hasShowUserSettingModal.current) return; @@ -169,98 +86,28 @@ export const _Editor: React.FC = ({ user: currentUser, documentId, autho Router.events.off('routeChangeStart', handler); window.removeEventListener('unload', handler); }; - }, [editor, users, currentUser, toggleMentionUsersSettingVisible]); - - useEffect(() => { - const listener = (event: KeyboardEvent) => { - if ((event.ctrlKey || event.metaKey) && event.keyCode == 83) { - event.preventDefault(); - Toast.info(`${LogoName}会实时保存你的数据,无需手动保存。`); - return false; - } - }; - - window.document.addEventListener('keydown', listener); - - return () => { - window.document.removeEventListener('keydown', listener); - }; - }, []); + }, [users, currentUser, toggleMentionUsersSettingVisible]); return ( - - - {/* FIXME: semi-design 的问题,不加 div,文字会换行! */} -
-
- - } - error={error} - errorContent={(error) => ( -
- - - {(error && error.message) || '未知错误'} - -
- )} - normalContent={() => { - return ( -
- {(!online || status === 'disconnected') && ( - - )} - {authority && !authority.editable && ( - - )} -
-
- -
-
-
-
- -
- document.querySelector('#js-template-editor-container')} /> -
- -
- ); - }} - /> +
+ + +
); }; - -export const Editor = React.memo(_Editor, (prevProps, nextProps) => { - if (deepEqual(prevProps, nextProps)) return true; - Toast.info({ - content: '信息已更新,我们将为您重新加载页面!', - duration: 3, - onClose() { - Router.reload(); - }, - }); - return false; -}); diff --git a/packages/client/src/components/document/editor/index.module.scss b/packages/client/src/components/document/editor/index.module.scss index bd89c012..45308925 100644 --- a/packages/client/src/components/document/editor/index.module.scss +++ b/packages/client/src/components/document/editor/index.module.scss @@ -1,3 +1,4 @@ +/* stylelint-disable no-descending-specificity */ .wrap { display: flex; flex-direction: column; @@ -30,51 +31,31 @@ height: 100%; overflow: hidden; - > header { - position: relative; - z-index: 110; - display: flex; - height: 50px; - padding: 0 24px; - overflow: hidden; - background-color: var(--semi-color-nav-bg); - align-items: center; - border-bottom: 1px solid var(--semi-color-border); - user-select: none; - - &.isStandardWidth { - justify-content: center; - } - - &.isFullWidth { - justify-content: flex-start; - } - - > div { - display: inline-flex; - align-items: center; - height: 100%; - overflow: auto; + > div { + > main { + padding: 24px 24px 96px; } } - > main { - flex: 1; - height: calc(100% - 50px); - overflow: auto; - - .contentWrap { - padding: 24px 24px 96px; - - &.isStandardWidth { - width: 96%; - max-width: 750px; - margin: 0 auto; + &.isStandardWidth { + > div { + > main { + > div:first-of-type { + width: 96%; + max-width: 750px; + margin: 0 auto; + } } + } + } - &.isFullWidth { - width: 100%; - margin: 0 auto; + &.isFullWidth { + width: 100%; + margin: 0 auto; + + > div { + > header { + justify-content: flex-start; } } } diff --git a/packages/client/src/components/document/editor/index.tsx b/packages/client/src/components/document/editor/index.tsx index db806e21..20679587 100644 --- a/packages/client/src/components/document/editor/index.tsx +++ b/packages/client/src/components/document/editor/index.tsx @@ -70,7 +70,12 @@ export const DocumentEditor: React.FC = ({ documentId }) => { } loading={true} /> } normalContent={() => ( - + {title} )} diff --git a/packages/client/src/components/document/reader/editor.tsx b/packages/client/src/components/document/reader/editor.tsx deleted file mode 100644 index ad01c841..00000000 --- a/packages/client/src/components/document/reader/editor.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import React, { useMemo, useEffect, useState } from 'react'; -import { Layout, Spin, Typography } from '@douyinfe/semi-ui'; -import { IDocument, ILoginUser } from '@think/domains'; -import { useToggle } from 'hooks/use-toggle'; -import { - useEditor, - EditorContent, - BaseKit, - DocumentWithTitle, - getCollaborationExtension, - getCollaborationCursorExtension, - getProvider, - destoryProvider, -} from 'tiptap'; -import { SecureDocumentIllustration } from 'illustrations/secure-document'; -import { DataRender } from 'components/data-render'; -import { ImageViewer } from 'components/image-viewer'; -import { triggerJoinUser } from 'event'; -import { CreateUser } from './user'; -import styles from './index.module.scss'; - -const { Content } = Layout; -const { Text } = Typography; - -interface IProps { - user: ILoginUser; - documentId: string; - document: IDocument; -} - -export const Editor: React.FC = ({ user, documentId, document, children }) => { - const [loading, toggleLoading] = useToggle(true); - const [error, setError] = useState(null); - const provider = useMemo(() => { - return getProvider({ - targetId: documentId, - token: user.token, - cacheType: 'READER', - user, - docType: 'document', - events: { - onAwarenessUpdate({ states }) { - triggerJoinUser(states); - }, - onAuthenticationFailed() { - toggleLoading(false); - setError(new Error('鉴权失败!暂时无法提供服务')); - }, - onSynced() { - toggleLoading(false); - }, - }, - }); - }, [documentId, user, toggleLoading]); - const editor = useEditor({ - editable: false, - extensions: [ - ...BaseKit, - DocumentWithTitle, - getCollaborationExtension(provider), - getCollaborationCursorExtension(provider, user), - ], - editorProps: { - // @ts-ignore - taskItemClickable: true, - }, - onDestroy() { - destoryProvider(provider, 'READER'); - }, - }); - - return ( - - - {/* FIXME: semi-design 的问题,不加 div,文字会换行! */} -
- -
- } - error={error} - errorContent={(error) => ( -
- - - {(error && error.message) || '未知错误'} - -
- )} - normalContent={() => { - return ( - -
- - -
- window.document.querySelector('#js-reader-container .ProseMirror .title')} - /> - {children} -
- ); - }} - /> - ); -}; diff --git a/packages/client/src/components/document/reader/index.tsx b/packages/client/src/components/document/reader/index.tsx index 43238309..977282a3 100644 --- a/packages/client/src/components/document/reader/index.tsx +++ b/packages/client/src/components/document/reader/index.tsx @@ -1,8 +1,22 @@ import Router from 'next/router'; -import React, { useCallback, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; +import { createPortal } from 'react-dom'; import cls from 'classnames'; -import { Layout, Nav, Space, Button, Typography, Skeleton, Tooltip, Popover, BackTop, Spin } from '@douyinfe/semi-ui'; -import { IconEdit, IconArticle } from '@douyinfe/semi-icons'; +import { + Layout, + Nav, + Space, + Avatar, + Button, + Typography, + Skeleton, + Tooltip, + Popover, + BackTop, + Spin, +} from '@douyinfe/semi-ui'; +import { LocaleTime } from 'components/locale-time'; +import { IconUser, IconEdit, IconArticle } from '@douyinfe/semi-icons'; import { Seo } from 'components/seo'; import { DataRender } from 'components/data-render'; import { DocumentShare } from 'components/document/share'; @@ -15,11 +29,24 @@ import { useDocumentStyle } from 'hooks/use-document-style'; import { useWindowSize } from 'hooks/use-window-size'; import { useUser } from 'data/user'; import { useDocumentDetail } from 'data/document'; -import { Editor } from './editor'; +import { triggerJoinUser } from 'event'; +import { CollaborationEditor } from 'tiptap/editor'; import styles from './index.module.scss'; const { Header } = Layout; const { Text } = Typography; +const EditBtnStyle = { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: 30, + width: 30, + borderRadius: '100%', + backgroundColor: '#0077fa', + color: '#fff', + bottom: 100, + transform: 'translateY(-50px)', +}; interface IProps { documentId: string; @@ -36,6 +63,51 @@ export const DocumentReader: React.FC = ({ documentId }) => { const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId); const { document, authority } = documentAndAuth || {}; + const renderAuthor = useCallback( + (element) => { + if (!document) return null; + + const target = element && element.querySelector('.ProseMirror .title'); + + if (target) { + return createPortal( +
+ + + + +
+

+ 创建者: + {document.createUser && document.createUser.name} +

+

+ 最近更新日期: + + {' ⦁ '}阅读量: + {document.views} +

+
+
+
, + target + ); + } + + return null; + }, + [document] + ); + const gotoEdit = useCallback(() => { Router.push(`/wiki/${document.wikiId}/document/${document.id}/edit`); }, [document]); @@ -54,7 +126,13 @@ export const DocumentReader: React.FC = ({ documentId }) => { error={docAuthError} loadingContent={} loading={true} />} normalContent={() => ( - + {document.title} )} @@ -103,30 +181,22 @@ export const DocumentReader: React.FC = ({ documentId }) => { <> {user && ( - -
- -
-
+ + )} + {user && ( +
+ +
)} {authority && authority.editable && container && ( - container} - visibilityHeight={200} - > + container} visibilityHeight={200}> )} diff --git a/packages/client/src/components/document/reader/public/content.tsx b/packages/client/src/components/document/reader/public/content.tsx deleted file mode 100644 index 44057e5b..00000000 --- a/packages/client/src/components/document/reader/public/content.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { useMemo } from 'react'; -import { IDocument } from '@think/domains'; -import { useEditor, EditorContent, BaseKit, DocumentWithTitle } from 'tiptap'; -import { safeJSONParse } from 'helpers/json'; -import { CreateUser } from '../user'; - -interface IProps { - document: IDocument; - createUserContainerSelector: string; -} - -export const DocumentContent: React.FC = ({ document, createUserContainerSelector }) => { - const json = useMemo(() => { - const c = safeJSONParse(document.content); - const json = c.default || c; - return json; - }, [document]); - - const editor = useEditor( - { - editable: false, - extensions: [...BaseKit, DocumentWithTitle], - content: json, - }, - [json] - ); - - return ( - <> - - window.document.querySelector(createUserContainerSelector)} /> - - ); -}; diff --git a/packages/client/src/components/document/reader/public/index.tsx b/packages/client/src/components/document/reader/public/index.tsx index 97d99ab5..cea85f92 100644 --- a/packages/client/src/components/document/reader/public/index.tsx +++ b/packages/client/src/components/document/reader/public/index.tsx @@ -24,8 +24,8 @@ import { Theme } from 'components/theme'; import { ImageViewer } from 'components/image-viewer'; import { useDocumentStyle } from 'hooks/use-document-style'; import { usePublicDocument } from 'data/document'; -import { DocumentSkeleton } from 'tiptap'; -import { DocumentContent } from './content'; +import { DocumentSkeleton } from 'tiptap/components/skeleton'; +import { CollaborationEditor } from 'tiptap/editor'; import styles from './index.module.scss'; const { Header, Content } = Layout; @@ -121,26 +121,21 @@ export const DocumentPublicReader: React.FC = ({ documentId, hideLogo = }} loadingContent={
- + 1
} normalContent={() => { return ( - <> +
-
- -
+ document.querySelector('#js-share-document-editor-container').parentNode} /> - +
); }} /> diff --git a/packages/client/src/components/document/reader/user.tsx b/packages/client/src/components/document/reader/user.tsx deleted file mode 100644 index c8a76c04..00000000 --- a/packages/client/src/components/document/reader/user.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { createPortal } from 'react-dom'; -import { Space, Avatar } from '@douyinfe/semi-ui'; -import { IconUser } from '@douyinfe/semi-icons'; -import { IDocument } from '@think/domains'; -import { LocaleTime } from 'components/locale-time'; - -export const CreateUser: React.FC<{ document: IDocument; container: () => HTMLElement }> = ({ - document, - container = null, -}) => { - if (!document.createUser) return null; - - const content = ( -
- - - - -
-

- 创建者: - {document.createUser && document.createUser.name} -

-

- 最近更新日期: - - {' ⦁ '}阅读量: - {document.views} -

-
-
-
- ); - - const el = container && container(); - - if (!el) return content; - return createPortal(content, el); -}; diff --git a/packages/client/src/components/document/version/index.tsx b/packages/client/src/components/document/version/index.tsx index 08acdb3f..3227f81a 100644 --- a/packages/client/src/components/document/version/index.tsx +++ b/packages/client/src/components/document/version/index.tsx @@ -3,7 +3,7 @@ import { Button, Modal, Typography } from '@douyinfe/semi-ui'; import { IconChevronLeft } from '@douyinfe/semi-icons'; import { useEditor, EditorContent } from '@tiptap/react'; import cls from 'classnames'; -import { BaseKit, DocumentWithTitle } from 'tiptap'; +import { CollaborationKit } from 'tiptap/editor'; import { safeJSONParse } from 'helpers/json'; import { DataRender } from 'components/data-render'; import { LocaleTime } from 'components/locale-time'; @@ -25,7 +25,7 @@ export const DocumentVersion: React.FC = ({ documentId, onSelect }) => { const editor = useEditor({ editable: false, - extensions: [...BaseKit, DocumentWithTitle], + extensions: CollaborationKit, content: { type: 'doc', content: [] }, }); diff --git a/packages/client/src/components/template/editor/editor.tsx b/packages/client/src/components/template/editor/editor.tsx index 9d22935c..d7cc4fee 100644 --- a/packages/client/src/components/template/editor/editor.tsx +++ b/packages/client/src/components/template/editor/editor.tsx @@ -1,35 +1,15 @@ import React, { useMemo, useCallback, useState, useEffect } from 'react'; import Router from 'next/router'; import cls from 'classnames'; -import { - Button, - Nav, - Space, - Typography, - Tooltip, - Switch, - Popover, - Popconfirm, - BackTop, - Toast, -} from '@douyinfe/semi-ui'; +import { Button, Nav, Space, Typography, Tooltip, Switch, Popover, Popconfirm } from '@douyinfe/semi-ui'; import { IconChevronLeft, IconArticle } from '@douyinfe/semi-icons'; import { ILoginUser, ITemplate } from '@think/domains'; import { Theme } from 'components/theme'; -import { - useEditor, - EditorContent, - BaseKit, - DocumentWithTitle, - getCollaborationExtension, - getProvider, - MenuBar, -} from 'tiptap'; import { User } from 'components/user'; import { DocumentStyle } from 'components/document/style'; -import { LogoName } from 'components/logo'; import { useDocumentStyle } from 'hooks/use-document-style'; import { useWindowSize } from 'hooks/use-window-size'; +import { CollaborationEditor } from 'tiptap/editor'; import styles from './index.module.scss'; const { Text } = Typography; @@ -44,30 +24,6 @@ interface IProps { export const Editor: React.FC = ({ user, data, updateTemplate, deleteTemplate }) => { const { width: windowWidth } = useWindowSize(); const [title, setTitle] = useState(data.title); - const provider = useMemo(() => { - return getProvider({ - targetId: data.id, - token: user.token, - cacheType: 'READER', - user, - docType: 'template', - }); - }, []); - const editor = useEditor( - { - editable: true, - extensions: [...BaseKit, DocumentWithTitle, getCollaborationExtension(provider)], - onTransaction: ({ transaction }) => { - try { - const title = transaction.doc.content.firstChild.content.firstChild.textContent; - setTitle(title); - } catch (e) { - // - } - }, - }, - [provider] - ); const [isPublic, setPublic] = useState(false); const { width, fontSize } = useDocumentStyle(); const editorWrapClassNames = useMemo(() => { @@ -89,22 +45,6 @@ export const Editor: React.FC = ({ user, data, updateTemplate, deleteTem setPublic(data.isPublic); }, [data]); - useEffect(() => { - const listener = (event: KeyboardEvent) => { - if ((event.ctrlKey || event.metaKey) && event.keyCode == 83) { - event.preventDefault(); - Toast.info(`${LogoName}会实时保存你的数据,无需手动保存。`); - return false; - } - }; - - window.document.addEventListener('keydown', listener); - - return () => { - window.document.removeEventListener('keydown', listener); - }; - }, []); - return (
@@ -140,17 +80,9 @@ export const Editor: React.FC = ({ user, data, updateTemplate, deleteTem
-
-
- -
-
-
-
- -
- document.querySelector('#js-template-editor-container')} /> -
+
+ +
diff --git a/packages/client/src/components/template/editor/index.module.scss b/packages/client/src/components/template/editor/index.module.scss index dc41c83a..983ce25e 100644 --- a/packages/client/src/components/template/editor/index.module.scss +++ b/packages/client/src/components/template/editor/index.module.scss @@ -1,3 +1,4 @@ +/* stylelint-disable no-descending-specificity */ .wrap { display: flex; flex-direction: column; @@ -30,55 +31,33 @@ height: 100%; overflow: hidden; - > header { - position: relative; - z-index: 110; - display: flex; - height: 50px; - padding: 0 24px; - overflow: hidden; - background-color: var(--semi-color-nav-bg); - align-items: center; - border-bottom: 1px solid var(--semi-color-border); - user-select: none; + > div { + height: 100%; + > div:first-of-type > main { + padding: 24px 24px 96px; + } + } + + .isStandardWidth { > div { - display: inline-flex; - align-items: center; - height: 100%; - overflow: auto; - } - - &.isStandardWidth { - > div { - margin: 0 auto; - } - } - - &.isFullWidth { - > div { - margin: 0; + > main { + > div:first-of-type { + width: 96%; + max-width: 750px; + margin: 0 auto; + } } } } - > main { - flex: 1; - height: calc(100% - 50px); - overflow: auto; + .isFullWidth { + width: 100%; + margin: 0 auto; - .contentWrap { - padding: 24px 24px 96px; - - &.isStandardWidth { - width: 96%; - max-width: 750px; - margin: 0 auto; - } - - &.isFullWidth { - width: 100%; - margin: 0 auto; + > div { + > header { + justify-content: flex-start; } } } diff --git a/packages/client/src/components/template/editor/useEditor.tsx b/packages/client/src/components/template/editor/useEditor.tsx deleted file mode 100644 index eab529f8..00000000 --- a/packages/client/src/components/template/editor/useEditor.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useState, useEffect, DependencyList } from 'react'; -import { EditorOptions } from '@tiptap/core'; -import { Editor } from '@tiptap/react'; - -function useForceUpdate() { - const [, setValue] = useState(0); - - return () => setValue((value) => value + 1); -} - -export const useEditor = (options: Partial = {}, deps: DependencyList = []) => { - const [editor, setEditor] = useState(null); - const forceUpdate = useForceUpdate(); - - useEffect(() => { - const instance = new Editor(options); - - setEditor(instance); - - // instance.on('transaction', () => { - // requestAnimationFrame(() => { - // requestAnimationFrame(() => { - // console.log('update'); - // forceUpdate(); - // }); - // }); - // }); - - return () => { - instance.destroy(); - }; - }, deps); - - return editor; -}; diff --git a/packages/client/src/components/template/reader/editor.tsx b/packages/client/src/components/template/reader/editor.tsx deleted file mode 100644 index fff033ef..00000000 --- a/packages/client/src/components/template/reader/editor.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React, { useMemo } from 'react'; -import cls from 'classnames'; -import { Layout, Spin, Typography } from '@douyinfe/semi-ui'; -import { IUser, ITemplate } from '@think/domains'; -import { useEditor, EditorContent, BaseKit, DocumentWithTitle } from 'tiptap'; -import { DataRender } from 'components/data-render'; -import { ImageViewer } from 'components/image-viewer'; -import { useDocumentStyle } from 'hooks/use-document-style'; -import { safeJSONParse } from 'helpers/json'; -import styles from './index.module.scss'; - -const { Content } = Layout; -const { Title } = Typography; - -interface IProps { - user: IUser; - data: ITemplate; - loading: boolean; - error: Error | null; -} - -export const Editor: React.FC = ({ user, data, loading, error }) => { - const json = useMemo(() => { - const c = safeJSONParse(data.content); - let json = c.default || c; - - if (json && json.content) { - json = { - type: 'doc', - content: json.content.slice(1), - }; - } - - return json; - }, [data]); - - const editor = useEditor( - { - editable: false, - extensions: [...BaseKit, DocumentWithTitle], - content: json, - }, - [json] - ); - - const { width, fontSize } = useDocumentStyle(); - const editorWrapClassNames = useMemo(() => { - return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth; - }, [width]); - - if (!user) return null; - - return ( -
- - - -
- } - error={error} - normalContent={() => { - return ( - -
- {data.title} - -
- -
- ); - }} - /> - - - ); -}; diff --git a/packages/client/src/components/template/reader/index.module.scss b/packages/client/src/components/template/reader/index.module.scss deleted file mode 100644 index 5f90ebcf..00000000 --- a/packages/client/src/components/template/reader/index.module.scss +++ /dev/null @@ -1,32 +0,0 @@ -.wrap { - display: flex; - flex-direction: column; - height: 100%; - - .contentWrap { - flex: 1; - overflow: hidden; - - > div { - display: flex; - flex-direction: column; - height: 100%; - } - - .editorWrap { - flex: 1; - overflow: auto; - } - } -} - -.isStandardWidth { - width: 96%; - max-width: 750px; - margin: 0 auto; -} - -.isFullWidth { - width: 100%; - margin: 0 auto; -} diff --git a/packages/client/src/components/template/reader/index.tsx b/packages/client/src/components/template/reader/index.tsx index 759a1f75..645da9cc 100644 --- a/packages/client/src/components/template/reader/index.tsx +++ b/packages/client/src/components/template/reader/index.tsx @@ -1,17 +1,16 @@ import React from 'react'; import { Spin } from '@douyinfe/semi-ui'; -import { useUser } from 'data/user'; import { Seo } from 'components/seo'; import { DataRender } from 'components/data-render'; import { useTemplate } from 'data/template'; -import { Editor } from './editor'; +import { ImageViewer } from 'components/image-viewer'; +import { ReaderEditor } from 'tiptap/editor'; interface IProps { templateId: string; } export const TemplateReader: React.FC = ({ templateId }) => { - const { user } = useUser(); const { data, loading, error } = useTemplate(templateId); return ( @@ -25,9 +24,10 @@ export const TemplateReader: React.FC = ({ templateId }) => { error={error} normalContent={() => { return ( -
+
- + +
); }} diff --git a/packages/client/src/components/wiki/tocs/tree.tsx b/packages/client/src/components/wiki/tocs/tree.tsx index 1bd09ca4..485497f0 100644 --- a/packages/client/src/components/wiki/tocs/tree.tsx +++ b/packages/client/src/components/wiki/tocs/tree.tsx @@ -75,7 +75,7 @@ export const Tree = ({ data, docAsLink, getDocLink, parentIds, activeId, isShare {label} diff --git a/packages/client/src/data/comment.ts b/packages/client/src/data/comment.ts index 324b4ded..22b3ad2c 100644 --- a/packages/client/src/data/comment.ts +++ b/packages/client/src/data/comment.ts @@ -29,7 +29,7 @@ export const useComments = (documentId) => { mutate(); return ret; }, - [mutate] + [mutate, documentId] ); const updateComment = useCallback( @@ -41,7 +41,7 @@ export const useComments = (documentId) => { mutate(); return ret; }, - [mutate] + [mutate, documentId] ); const deleteComment = useCallback( diff --git a/packages/client/src/data/document.ts b/packages/client/src/data/document.ts index af888563..e2e9667e 100644 --- a/packages/client/src/data/document.ts +++ b/packages/client/src/data/document.ts @@ -59,7 +59,7 @@ export const useDocumentDetail = (documentId, options = null) => { mutate(); return res; }, - [mutate] + [mutate, documentId] ); const toggleStatus = useCallback( @@ -68,7 +68,7 @@ export const useDocumentDetail = (documentId, options = null) => { mutate(); return ret; }, - [mutate] + [mutate, documentId] ); return { data, loading, error, update, toggleStatus }; @@ -118,7 +118,7 @@ export const useDocumentStar = (documentId) => { targetId: documentId, }); mutate(); - }, [mutate]); + }, [mutate, documentId]); return { data, error, toggleStar }; }; @@ -198,7 +198,7 @@ export const useCollaborationDocument = (documentId) => { mutate(); return ret; }, - [mutate] + [mutate, documentId] ); const updateUser = useCallback( @@ -210,7 +210,7 @@ export const useCollaborationDocument = (documentId) => { mutate(); return ret; }, - [mutate] + [mutate, documentId] ); const deleteUser = useCallback( @@ -222,7 +222,7 @@ export const useCollaborationDocument = (documentId) => { mutate(); return ret; }, - [mutate] + [mutate, documentId] ); return { users: data, loading, error, addUser, updateUser, deleteUser }; diff --git a/packages/client/src/data/template.ts b/packages/client/src/data/template.ts index b2fa106c..68d4d4ef 100644 --- a/packages/client/src/data/template.ts +++ b/packages/client/src/data/template.ts @@ -62,12 +62,12 @@ export const useTemplate = (templateId) => { mutate(); return ret as unknown as ITemplate; }, - [mutate] + [mutate, templateId] ); const deleteTemplate = useCallback(async () => { await HttpClient.post(`/template/delete/${templateId}`); - }, []); + }, [templateId]); return { data, diff --git a/packages/client/src/data/wiki.tsx b/packages/client/src/data/wiki.tsx index 3be1ea6b..cc4c955d 100644 --- a/packages/client/src/data/wiki.tsx +++ b/packages/client/src/data/wiki.tsx @@ -104,7 +104,7 @@ export const useWikiTocs = (wikiId) => { mutate(); return res; }, - [mutate] + [mutate, wikiId] ); return { data, loading, error, refresh: mutate, update }; @@ -143,7 +143,7 @@ export const useWikiDetail = (wikiId) => { mutate(); return res; }, - [mutate] + [mutate, wikiId] ); /** @@ -157,7 +157,7 @@ export const useWikiDetail = (wikiId) => { mutate(); return res; }, - [mutate] + [mutate, wikiId] ); return { data, loading, error, update, toggleStatus }; @@ -178,7 +178,7 @@ export const useWikiUsers = (wikiId) => { mutate(); return ret; }, - [mutate] + [mutate, wikiId] ); const updateUser = useCallback( @@ -187,7 +187,7 @@ export const useWikiUsers = (wikiId) => { mutate(); return ret; }, - [mutate] + [mutate, wikiId] ); const deleteUser = useCallback( @@ -196,7 +196,7 @@ export const useWikiUsers = (wikiId) => { mutate(); return ret; }, - [mutate] + [mutate, wikiId] ); return { @@ -229,7 +229,7 @@ export const useWikiStar = (wikiId) => { targetId: wikiId, }); mutate(); - }, [mutate]); + }, [mutate, wikiId]); return { data, error, toggleStar }; }; diff --git a/packages/client/src/pages/_app.tsx b/packages/client/src/pages/_app.tsx index 5493bace..f089844d 100644 --- a/packages/client/src/pages/_app.tsx +++ b/packages/client/src/pages/_app.tsx @@ -2,9 +2,10 @@ import type { AppProps } from 'next/app'; import Head from 'next/head'; import React from 'react'; import { useTheme } from 'hooks/use-theme'; +import 'tiptap/fix-match-nodes'; import 'viewerjs/dist/viewer.css'; import 'styles/globals.scss'; -import 'tiptap/styles/index.scss'; +import 'tiptap/core/styles/index.scss'; function MyApp({ Component, pageProps }: AppProps) { useTheme(); diff --git a/packages/client/src/pages/feature/editor/index.tsx b/packages/client/src/pages/feature/editor/index.tsx new file mode 100644 index 00000000..b2a073f1 --- /dev/null +++ b/packages/client/src/pages/feature/editor/index.tsx @@ -0,0 +1,29 @@ +import React, { useRef } from 'react'; +import { useRouter } from 'next/router'; +import { SingleColumnLayout } from 'layouts/single-column'; +import { ICollaborationEditorProps, CollaborationEditor, ICollaborationRefProps } from 'tiptap/editor'; +import { useUser } from 'data/user'; + +const Page = () => { + const $container = useRef(); + const { user } = useUser(); + + const { query } = useRouter(); + const { type, id } = query as { type: ICollaborationEditorProps['type']; id: string }; + + return ( + +
+ {type && id ? ( + <> + {user && } +
+ {user && } + + ) : null} +
+
+ ); +}; + +export default Page; diff --git a/packages/client/src/styles/reset.scss b/packages/client/src/styles/reset.scss index 86c51556..4285162b 100644 --- a/packages/client/src/styles/reset.scss +++ b/packages/client/src/styles/reset.scss @@ -87,40 +87,3 @@ select { scroll-behavior: auto !important; } } - -::-webkit-scrollbar { - width: 6px; - height: 6px; - background-color: transparent; -} - -::-webkit-scrollbar-button { - width: 6px; - height: 6px; - background-color: transparent; -} - -::-webkit-scrollbar-track { - background-color: transparent; -} - -::-webkit-scrollbar-track-piece { - background-color: transparent; -} - -::-webkit-scrollbar-thumb { - background-color: transparent; - border-radius: 5px; -} - -::-webkit-scrollbar-corner, -::-webkit-resizer { - background-color: transparent; -} - -*:hover { - &::-webkit-scrollbar-thumb &::-webkit-scrollbar-corner, - &::-webkit-resizer { - background-color: var(--scrollbar-bg); - } -} diff --git a/packages/client/src/tiptap/menus/_components/color-picker/index.tsx b/packages/client/src/tiptap/components/color-picker/index.tsx similarity index 100% rename from packages/client/src/tiptap/menus/_components/color-picker/index.tsx rename to packages/client/src/tiptap/components/color-picker/index.tsx diff --git a/packages/client/src/tiptap/menus/_components/color-picker/style.module.scss b/packages/client/src/tiptap/components/color-picker/style.module.scss similarity index 100% rename from packages/client/src/tiptap/menus/_components/color-picker/style.module.scss rename to packages/client/src/tiptap/components/color-picker/style.module.scss diff --git a/packages/client/src/tiptap/divider.tsx b/packages/client/src/tiptap/components/divider.tsx similarity index 100% rename from packages/client/src/tiptap/divider.tsx rename to packages/client/src/tiptap/components/divider.tsx diff --git a/packages/client/src/tiptap/menus/_components/size.tsx b/packages/client/src/tiptap/components/size.tsx similarity index 100% rename from packages/client/src/tiptap/menus/_components/size.tsx rename to packages/client/src/tiptap/components/size.tsx diff --git a/packages/client/src/tiptap/skeleton.tsx b/packages/client/src/tiptap/components/skeleton.tsx similarity index 100% rename from packages/client/src/tiptap/skeleton.tsx rename to packages/client/src/tiptap/components/skeleton.tsx diff --git a/packages/client/src/tiptap/constants.ts b/packages/client/src/tiptap/core/constants.ts similarity index 100% rename from packages/client/src/tiptap/constants.ts rename to packages/client/src/tiptap/core/constants.ts diff --git a/packages/client/src/tiptap/extensions/attachment.ts b/packages/client/src/tiptap/core/extensions/attachment.ts similarity index 96% rename from packages/client/src/tiptap/extensions/attachment.ts rename to packages/client/src/tiptap/core/extensions/attachment.ts index f23a58f6..2f02970d 100644 --- a/packages/client/src/tiptap/extensions/attachment.ts +++ b/packages/client/src/tiptap/core/extensions/attachment.ts @@ -1,7 +1,7 @@ import { Node, mergeAttributes } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; import { getDatasetAttribute } from 'tiptap/prose-utils'; -import { AttachmentWrapper } from 'tiptap/wrappers/attachment'; +import { AttachmentWrapper } from 'tiptap/core/wrappers/attachment'; declare module '@tiptap/core' { interface Commands { diff --git a/packages/client/src/tiptap/extensions/background-color.ts b/packages/client/src/tiptap/core/extensions/background-color.ts similarity index 100% rename from packages/client/src/tiptap/extensions/background-color.ts rename to packages/client/src/tiptap/core/extensions/background-color.ts diff --git a/packages/client/src/tiptap/extensions/blockquote.ts b/packages/client/src/tiptap/core/extensions/blockquote.ts similarity index 88% rename from packages/client/src/tiptap/extensions/blockquote.ts rename to packages/client/src/tiptap/core/extensions/blockquote.ts index 4cc04be1..31002b6a 100644 --- a/packages/client/src/tiptap/extensions/blockquote.ts +++ b/packages/client/src/tiptap/core/extensions/blockquote.ts @@ -1,7 +1,6 @@ import { Blockquote as BuiltInBlockquote } from '@tiptap/extension-blockquote'; import { wrappingInputRule } from '@tiptap/core'; -import { getParents } from 'tiptap/prose-utils'; -import { getMarkdownSource } from 'tiptap/markdown/markdown-to-prosemirror'; +import { getParents, getMarkdownSource } from 'tiptap/prose-utils'; export const Blockquote = BuiltInBlockquote.extend({ addAttributes() { diff --git a/packages/client/src/tiptap/extensions/bold.ts b/packages/client/src/tiptap/core/extensions/bold.ts similarity index 100% rename from packages/client/src/tiptap/extensions/bold.ts rename to packages/client/src/tiptap/core/extensions/bold.ts diff --git a/packages/client/src/tiptap/extensions/bullet-list.ts b/packages/client/src/tiptap/core/extensions/bullet-list.ts similarity index 84% rename from packages/client/src/tiptap/extensions/bullet-list.ts rename to packages/client/src/tiptap/core/extensions/bullet-list.ts index 583ff579..f64a30fd 100644 --- a/packages/client/src/tiptap/extensions/bullet-list.ts +++ b/packages/client/src/tiptap/core/extensions/bullet-list.ts @@ -1,5 +1,5 @@ import { BulletList as BuiltInBulletList } from '@tiptap/extension-bullet-list'; -import { getMarkdownSource } from 'tiptap/markdown/markdown-to-prosemirror'; +import { getMarkdownSource } from 'tiptap/prose-utils'; export const BulletList = BuiltInBulletList.extend({ addAttributes() { diff --git a/packages/client/src/tiptap/extensions/callout.ts b/packages/client/src/tiptap/core/extensions/callout.ts similarity index 96% rename from packages/client/src/tiptap/extensions/callout.ts rename to packages/client/src/tiptap/core/extensions/callout.ts index b5bfb67c..afa83c29 100644 --- a/packages/client/src/tiptap/extensions/callout.ts +++ b/packages/client/src/tiptap/core/extensions/callout.ts @@ -1,6 +1,6 @@ import { Node, mergeAttributes, wrappingInputRule } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { CalloutWrapper } from 'tiptap/wrappers/callout'; +import { CalloutWrapper } from 'tiptap/core/wrappers/callout'; declare module '@tiptap/core' { interface Commands { diff --git a/packages/client/src/tiptap/extensions/code-block.ts b/packages/client/src/tiptap/core/extensions/code-block.ts similarity index 99% rename from packages/client/src/tiptap/extensions/code-block.ts rename to packages/client/src/tiptap/core/extensions/code-block.ts index dadfa9a0..f5e146f7 100644 --- a/packages/client/src/tiptap/extensions/code-block.ts +++ b/packages/client/src/tiptap/core/extensions/code-block.ts @@ -3,7 +3,7 @@ import { Plugin, PluginKey, TextSelection } from 'prosemirror-state'; import { ReactNodeViewRenderer } from '@tiptap/react'; import { lowlight } from 'lowlight/lib/all'; import { LowlightPlugin } from 'tiptap/prose-utils'; -import { CodeBlockWrapper } from 'tiptap/wrappers/code-block'; +import { CodeBlockWrapper } from 'tiptap/core/wrappers/code-block'; export interface CodeBlockOptions { /** diff --git a/packages/client/src/tiptap/extensions/code.ts b/packages/client/src/tiptap/core/extensions/code.ts similarity index 81% rename from packages/client/src/tiptap/extensions/code.ts rename to packages/client/src/tiptap/core/extensions/code.ts index 097ed8bd..2afdee3c 100644 --- a/packages/client/src/tiptap/extensions/code.ts +++ b/packages/client/src/tiptap/core/extensions/code.ts @@ -1,5 +1,5 @@ import BuiltInCode from '@tiptap/extension-code'; -import { EXTENSION_PRIORITY_LOWER } from 'tiptap/constants'; +import { EXTENSION_PRIORITY_LOWER } from 'tiptap/core/constants'; export const Code = BuiltInCode.extend({ excludes: null, diff --git a/packages/client/src/tiptap/extensions/collaboration-cursor/cursor-plugin/index.ts b/packages/client/src/tiptap/core/extensions/collaboration-cursor/cursor-plugin/index.ts similarity index 100% rename from packages/client/src/tiptap/extensions/collaboration-cursor/cursor-plugin/index.ts rename to packages/client/src/tiptap/core/extensions/collaboration-cursor/cursor-plugin/index.ts diff --git a/packages/client/src/tiptap/extensions/collaboration-cursor/index.ts b/packages/client/src/tiptap/core/extensions/collaboration-cursor/index.ts similarity index 100% rename from packages/client/src/tiptap/extensions/collaboration-cursor/index.ts rename to packages/client/src/tiptap/core/extensions/collaboration-cursor/index.ts diff --git a/packages/client/src/tiptap/extensions/collaboration/collaboration.ts b/packages/client/src/tiptap/core/extensions/collaboration/collaboration.ts similarity index 100% rename from packages/client/src/tiptap/extensions/collaboration/collaboration.ts rename to packages/client/src/tiptap/core/extensions/collaboration/collaboration.ts diff --git a/packages/client/src/tiptap/extensions/collaboration/helpers/is-change-origin.ts b/packages/client/src/tiptap/core/extensions/collaboration/helpers/is-change-origin.ts similarity index 100% rename from packages/client/src/tiptap/extensions/collaboration/helpers/is-change-origin.ts rename to packages/client/src/tiptap/core/extensions/collaboration/helpers/is-change-origin.ts diff --git a/packages/client/src/tiptap/extensions/collaboration/index.ts b/packages/client/src/tiptap/core/extensions/collaboration/index.ts similarity index 100% rename from packages/client/src/tiptap/extensions/collaboration/index.ts rename to packages/client/src/tiptap/core/extensions/collaboration/index.ts diff --git a/packages/client/src/tiptap/extensions/color-highlighter.ts b/packages/client/src/tiptap/core/extensions/color-highlighter.ts similarity index 100% rename from packages/client/src/tiptap/extensions/color-highlighter.ts rename to packages/client/src/tiptap/core/extensions/color-highlighter.ts diff --git a/packages/client/src/tiptap/extensions/color.ts b/packages/client/src/tiptap/core/extensions/color.ts similarity index 100% rename from packages/client/src/tiptap/extensions/color.ts rename to packages/client/src/tiptap/core/extensions/color.ts diff --git a/packages/client/src/tiptap/extensions/countdown.ts b/packages/client/src/tiptap/core/extensions/countdown.ts similarity index 96% rename from packages/client/src/tiptap/extensions/countdown.ts rename to packages/client/src/tiptap/core/extensions/countdown.ts index 95e29fb2..373a641a 100644 --- a/packages/client/src/tiptap/extensions/countdown.ts +++ b/packages/client/src/tiptap/core/extensions/countdown.ts @@ -1,6 +1,6 @@ import { Node, mergeAttributes } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { CountdownWrapper } from 'tiptap/wrappers/countdown'; +import { CountdownWrapper } from 'tiptap/core/wrappers/countdown'; import { getDatasetAttribute } from 'tiptap/prose-utils'; declare module '@tiptap/core' { diff --git a/packages/client/src/tiptap/extensions/document-children.ts b/packages/client/src/tiptap/core/extensions/document-children.ts similarity index 94% rename from packages/client/src/tiptap/extensions/document-children.ts rename to packages/client/src/tiptap/core/extensions/document-children.ts index f2498d41..9bd3d99b 100644 --- a/packages/client/src/tiptap/extensions/document-children.ts +++ b/packages/client/src/tiptap/core/extensions/document-children.ts @@ -1,6 +1,6 @@ import { Node, mergeAttributes, wrappingInputRule } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { DocumentChildrenWrapper } from 'tiptap/wrappers/document-children'; +import { DocumentChildrenWrapper } from 'tiptap/core/wrappers/document-children'; import { getDatasetAttribute } from 'tiptap/prose-utils'; declare module '@tiptap/core' { diff --git a/packages/client/src/tiptap/extensions/document-reference.ts b/packages/client/src/tiptap/core/extensions/document-reference.ts similarity index 95% rename from packages/client/src/tiptap/extensions/document-reference.ts rename to packages/client/src/tiptap/core/extensions/document-reference.ts index 9ea65d77..2113906e 100644 --- a/packages/client/src/tiptap/extensions/document-reference.ts +++ b/packages/client/src/tiptap/core/extensions/document-reference.ts @@ -1,6 +1,6 @@ import { Node, mergeAttributes, wrappingInputRule } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { DocumentReferenceWrapper } from 'tiptap/wrappers/document-reference'; +import { DocumentReferenceWrapper } from 'tiptap/core/wrappers/document-reference'; import { getDatasetAttribute } from 'tiptap/prose-utils'; declare module '@tiptap/core' { diff --git a/packages/client/src/tiptap/extensions/document.ts b/packages/client/src/tiptap/core/extensions/document.ts similarity index 100% rename from packages/client/src/tiptap/extensions/document.ts rename to packages/client/src/tiptap/core/extensions/document.ts diff --git a/packages/client/src/tiptap/extensions/dropcursor.ts b/packages/client/src/tiptap/core/extensions/dropcursor.ts similarity index 100% rename from packages/client/src/tiptap/extensions/dropcursor.ts rename to packages/client/src/tiptap/core/extensions/dropcursor.ts diff --git a/packages/client/src/tiptap/extensions/emoji.ts b/packages/client/src/tiptap/core/extensions/emoji.ts similarity index 94% rename from packages/client/src/tiptap/extensions/emoji.ts rename to packages/client/src/tiptap/core/extensions/emoji.ts index 4e46af3a..9d0d8cb0 100644 --- a/packages/client/src/tiptap/extensions/emoji.ts +++ b/packages/client/src/tiptap/core/extensions/emoji.ts @@ -3,9 +3,9 @@ import { ReactRenderer } from '@tiptap/react'; import { Plugin, PluginKey } from 'prosemirror-state'; import Suggestion from '@tiptap/suggestion'; import tippy from 'tippy.js'; -import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/constants'; -import { EmojiList } from 'tiptap/wrappers/emoji-list'; -import { emojiSearch, emojisToName } from 'tiptap/wrappers/emoji-list/emojis'; +import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/core/constants'; +import { EmojiList } from 'tiptap/core/wrappers/emoji-list'; +import { emojiSearch, emojisToName } from 'tiptap/core/wrappers/emoji-list/emojis'; declare module '@tiptap/core' { interface Commands { diff --git a/packages/client/src/tiptap/core/extensions/event-emitter.ts b/packages/client/src/tiptap/core/extensions/event-emitter.ts new file mode 100644 index 00000000..5e24f131 --- /dev/null +++ b/packages/client/src/tiptap/core/extensions/event-emitter.ts @@ -0,0 +1,19 @@ +import { Extension } from '@tiptap/core'; +import { EventEmitter as Em } from 'helpers/event-emitter'; +import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/core/constants'; + +const event = new Em(); + +/** + * 添加事件能力 + */ +export const EventEmitter = Extension.create({ + name: 'eventEmitter', + priority: EXTENSION_PRIORITY_HIGHEST, + addOptions() { + return { eventEmitter: event }; + }, + addStorage() { + return this.options; + }, +}); diff --git a/packages/client/src/tiptap/extensions/focus.ts b/packages/client/src/tiptap/core/extensions/focus.ts similarity index 100% rename from packages/client/src/tiptap/extensions/focus.ts rename to packages/client/src/tiptap/core/extensions/focus.ts diff --git a/packages/client/src/tiptap/extensions/font-size.ts b/packages/client/src/tiptap/core/extensions/font-size.ts similarity index 100% rename from packages/client/src/tiptap/extensions/font-size.ts rename to packages/client/src/tiptap/core/extensions/font-size.ts diff --git a/packages/client/src/tiptap/extensions/gapcursor.ts b/packages/client/src/tiptap/core/extensions/gapcursor.ts similarity index 100% rename from packages/client/src/tiptap/extensions/gapcursor.ts rename to packages/client/src/tiptap/core/extensions/gapcursor.ts diff --git a/packages/client/src/tiptap/extensions/hard-break.ts b/packages/client/src/tiptap/core/extensions/hard-break.ts similarity index 100% rename from packages/client/src/tiptap/extensions/hard-break.ts rename to packages/client/src/tiptap/core/extensions/hard-break.ts diff --git a/packages/client/src/tiptap/extensions/heading.ts b/packages/client/src/tiptap/core/extensions/heading.ts similarity index 100% rename from packages/client/src/tiptap/extensions/heading.ts rename to packages/client/src/tiptap/core/extensions/heading.ts diff --git a/packages/client/src/tiptap/extensions/horizontal-rule.ts b/packages/client/src/tiptap/core/extensions/horizontal-rule.ts similarity index 100% rename from packages/client/src/tiptap/extensions/horizontal-rule.ts rename to packages/client/src/tiptap/core/extensions/horizontal-rule.ts diff --git a/packages/client/src/tiptap/extensions/html-marks.ts b/packages/client/src/tiptap/core/extensions/html-marks.ts similarity index 94% rename from packages/client/src/tiptap/extensions/html-marks.ts rename to packages/client/src/tiptap/core/extensions/html-marks.ts index 5ed3c868..ffc637fe 100644 --- a/packages/client/src/tiptap/extensions/html-marks.ts +++ b/packages/client/src/tiptap/core/extensions/html-marks.ts @@ -1,5 +1,5 @@ import { Mark, mergeAttributes, markInputRule } from '@tiptap/core'; -import { PARSE_HTML_PRIORITY_LOWEST } from 'tiptap/constants'; +import { PARSE_HTML_PRIORITY_LOWEST } from 'tiptap/core/constants'; import { markInputRegex, extractMarkAttributesFromMatch } from 'tiptap/prose-utils'; export const marks = [{ name: 'underline', tag: 'u' }]; diff --git a/packages/client/src/tiptap/extensions/iframe.ts b/packages/client/src/tiptap/core/extensions/iframe.ts similarity index 96% rename from packages/client/src/tiptap/extensions/iframe.ts rename to packages/client/src/tiptap/core/extensions/iframe.ts index 9fc37937..f3949bda 100644 --- a/packages/client/src/tiptap/extensions/iframe.ts +++ b/packages/client/src/tiptap/core/extensions/iframe.ts @@ -1,6 +1,6 @@ import { Node, mergeAttributes } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { IframeWrapper } from 'tiptap/wrappers/iframe'; +import { IframeWrapper } from 'tiptap/core/wrappers/iframe'; import { getDatasetAttribute } from 'tiptap/prose-utils'; declare module '@tiptap/core' { diff --git a/packages/client/src/tiptap/extensions/image.ts b/packages/client/src/tiptap/core/extensions/image.ts similarity index 96% rename from packages/client/src/tiptap/extensions/image.ts rename to packages/client/src/tiptap/core/extensions/image.ts index c3721553..2d252ed5 100644 --- a/packages/client/src/tiptap/extensions/image.ts +++ b/packages/client/src/tiptap/core/extensions/image.ts @@ -1,6 +1,6 @@ import { Image as BuiltInImage } from '@tiptap/extension-image'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { ImageWrapper } from 'tiptap/wrappers/image'; +import { ImageWrapper } from 'tiptap/core/wrappers/image'; const resolveImageEl = (element) => (element.nodeName === 'IMG' ? element : element.querySelector('img')); diff --git a/packages/client/src/tiptap/extensions/indent.ts b/packages/client/src/tiptap/core/extensions/indent.ts similarity index 100% rename from packages/client/src/tiptap/extensions/indent.ts rename to packages/client/src/tiptap/core/extensions/indent.ts diff --git a/packages/client/src/tiptap/extensions/italic.ts b/packages/client/src/tiptap/core/extensions/italic.ts similarity index 100% rename from packages/client/src/tiptap/extensions/italic.ts rename to packages/client/src/tiptap/core/extensions/italic.ts diff --git a/packages/client/src/tiptap/extensions/katex.ts b/packages/client/src/tiptap/core/extensions/katex.ts similarity index 96% rename from packages/client/src/tiptap/extensions/katex.ts rename to packages/client/src/tiptap/core/extensions/katex.ts index 06f74b40..959fc3ef 100644 --- a/packages/client/src/tiptap/extensions/katex.ts +++ b/packages/client/src/tiptap/core/extensions/katex.ts @@ -1,6 +1,6 @@ import { Node, mergeAttributes, nodeInputRule } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { KatexWrapper } from 'tiptap/wrappers/katex'; +import { KatexWrapper } from 'tiptap/core/wrappers/katex'; type IKatexAttrs = { text?: string; diff --git a/packages/client/src/tiptap/extensions/link.ts b/packages/client/src/tiptap/core/extensions/link.ts similarity index 100% rename from packages/client/src/tiptap/extensions/link.ts rename to packages/client/src/tiptap/core/extensions/link.ts diff --git a/packages/client/src/tiptap/extensions/listItem.ts b/packages/client/src/tiptap/core/extensions/listItem.ts similarity index 100% rename from packages/client/src/tiptap/extensions/listItem.ts rename to packages/client/src/tiptap/core/extensions/listItem.ts diff --git a/packages/client/src/tiptap/extensions/loading.ts b/packages/client/src/tiptap/core/extensions/loading.ts similarity index 85% rename from packages/client/src/tiptap/extensions/loading.ts rename to packages/client/src/tiptap/core/extensions/loading.ts index 6edaafb2..5965ffe1 100644 --- a/packages/client/src/tiptap/extensions/loading.ts +++ b/packages/client/src/tiptap/core/extensions/loading.ts @@ -1,6 +1,6 @@ import { Node } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { LoadingWrapper } from 'tiptap/wrappers/loading'; +import { LoadingWrapper } from 'tiptap/core/wrappers/loading'; export const Loading = Node.create({ name: 'loading', diff --git a/packages/client/src/tiptap/extensions/mention.ts b/packages/client/src/tiptap/core/extensions/mention.ts similarity index 96% rename from packages/client/src/tiptap/extensions/mention.ts rename to packages/client/src/tiptap/core/extensions/mention.ts index e4af7f9a..bd30c28c 100644 --- a/packages/client/src/tiptap/extensions/mention.ts +++ b/packages/client/src/tiptap/core/extensions/mention.ts @@ -3,7 +3,7 @@ import { ReactRenderer } from '@tiptap/react'; import tippy from 'tippy.js'; import { getUsers } from 'services/user'; import { getDatasetAttribute } from 'tiptap/prose-utils'; -import { MentionList } from 'tiptap/wrappers/mention-list'; +import { MentionList } from 'tiptap/core/wrappers/mention-list'; const suggestion = { items: async ({ query }) => { diff --git a/packages/client/src/tiptap/extensions/mind.ts b/packages/client/src/tiptap/core/extensions/mind.ts similarity index 98% rename from packages/client/src/tiptap/extensions/mind.ts rename to packages/client/src/tiptap/core/extensions/mind.ts index 0d0ec1ae..bf94f61d 100644 --- a/packages/client/src/tiptap/extensions/mind.ts +++ b/packages/client/src/tiptap/core/extensions/mind.ts @@ -1,7 +1,7 @@ import { Node, mergeAttributes, nodeInputRule } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; import { Plugin, PluginKey } from 'prosemirror-state'; -import { MindWrapper } from 'tiptap/wrappers/mind'; +import { MindWrapper } from 'tiptap/core/wrappers/mind'; import { getDatasetAttribute } from 'tiptap/prose-utils'; const DEFAULT_MIND_DATA = { diff --git a/packages/client/src/tiptap/extensions/ordered-list.ts b/packages/client/src/tiptap/core/extensions/ordered-list.ts similarity index 81% rename from packages/client/src/tiptap/extensions/ordered-list.ts rename to packages/client/src/tiptap/core/extensions/ordered-list.ts index 8fe72ca9..bc8bcf2a 100644 --- a/packages/client/src/tiptap/extensions/ordered-list.ts +++ b/packages/client/src/tiptap/core/extensions/ordered-list.ts @@ -1,5 +1,5 @@ import { OrderedList as BuiltInOrderedList } from '@tiptap/extension-ordered-list'; -import { getMarkdownSource } from 'tiptap/markdown/markdown-to-prosemirror'; +import { getMarkdownSource } from 'tiptap/prose-utils'; export const OrderedList = BuiltInOrderedList.extend({ addAttributes() { diff --git a/packages/client/src/tiptap/extensions/paragraph.ts b/packages/client/src/tiptap/core/extensions/paragraph.ts similarity index 100% rename from packages/client/src/tiptap/extensions/paragraph.ts rename to packages/client/src/tiptap/core/extensions/paragraph.ts diff --git a/packages/client/src/tiptap/extensions/paste.ts b/packages/client/src/tiptap/core/extensions/paste.ts similarity index 81% rename from packages/client/src/tiptap/extensions/paste.ts rename to packages/client/src/tiptap/core/extensions/paste.ts index 30535081..6f3dce54 100644 --- a/packages/client/src/tiptap/extensions/paste.ts +++ b/packages/client/src/tiptap/core/extensions/paste.ts @@ -1,16 +1,30 @@ import { Extension } from '@tiptap/core'; import { Plugin, PluginKey } from 'prosemirror-state'; -import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/constants'; +import { Schema, Fragment } from 'prosemirror-model'; +import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/core/constants'; import { handleFileEvent, isInCode, LANGUAGES, isTitleNode } from 'tiptap/prose-utils'; -import { - isMarkdown, - normalizePastedMarkdown, - markdownToProsemirror, - prosemirrorToMarkdown, -} from 'tiptap/markdown/markdown-to-prosemirror'; -import { copyNode } from 'tiptap/prose-utils'; +import { copyNode, isMarkdown, normalizeMarkdown } from 'tiptap/prose-utils'; import { safeJSONParse } from 'helpers/json'; +interface IPasteOptions { + /** + * + * 将 markdown 转换为 html + */ + markdownToHTML: (arg: string) => string; + + /** + * 将 markdown 转换为 prosemirror 节点 + * FIXME: prosemirror 节点的类型是什么? + */ + markdownToProsemirror: (arg: { schema: Schema; content: string; hasTitle: boolean }) => unknown; + + /** + * 将 prosemirror 转换为 markdown + */ + prosemirrorToMarkdown: (arg: { content: Fragment }) => string; +} + const isPureText = (content): boolean => { if (!content) return false; @@ -27,11 +41,25 @@ const isPureText = (content): boolean => { return content['type'] === 'text'; }; -export const Paste = Extension.create({ +export const Paste = Extension.create({ name: 'paste', priority: EXTENSION_PRIORITY_HIGHEST, + + addOptions() { + return { + markdownToHTML: (arg) => arg, + markdownToProsemirror: (arg) => arg.content, + prosemirrorToMarkdown: (arg) => String(arg.content), + }; + }, + + addStorage() { + return this.options; + }, + addProseMirrorPlugins() { - const { editor } = this; + const extensionThis = this; + const { editor } = extensionThis; return [ new Plugin({ @@ -41,9 +69,8 @@ export const Paste = Extension.create({ if (view.props.editable && !view.props.editable(view.state)) { return false; } - if (!event.clipboardData) return false; - + // 文件 const files = Array.from(event.clipboardData.files); if (files.length) { event.preventDefault(); @@ -53,12 +80,14 @@ export const Paste = Extension.create({ return true; } + const { markdownToProsemirror } = extensionThis.options; const text = event.clipboardData.getData('text/plain'); const html = event.clipboardData.getData('text/html'); const vscode = event.clipboardData.getData('vscode-editor-data'); const node = event.clipboardData.getData('text/node'); const markdownText = event.clipboardData.getData('text/markdown'); + // 直接复制节点 if (node) { const doc = safeJSONParse(node); const tr = view.state.tr; @@ -98,7 +127,7 @@ export const Paste = Extension.create({ const schema = view.props.state.schema; const doc = markdownToProsemirror({ schema, - content: normalizePastedMarkdown(markdownText || text), + content: normalizeMarkdown(markdownText || text), hasTitle, }); let tr = view.state.tr; @@ -111,13 +140,11 @@ export const Paste = Extension.create({ view.dispatch(tr.scrollIntoView()); return true; } - if (text.length !== 0) { event.preventDefault(); view.dispatch(view.state.tr.insertText(text)); return true; } - return false; }, handleDrop: (view, event: any) => { @@ -171,7 +198,7 @@ export const Paste = Extension.create({ if (!doc) { return ''; } - const content = prosemirrorToMarkdown({ + const content = extensionThis.options.prosemirrorToMarkdown({ content: doc, }); return content; diff --git a/packages/client/src/tiptap/extensions/placeholder.ts b/packages/client/src/tiptap/core/extensions/placeholder.ts similarity index 100% rename from packages/client/src/tiptap/extensions/placeholder.ts rename to packages/client/src/tiptap/core/extensions/placeholder.ts diff --git a/packages/client/src/tiptap/extensions/quick-insert.tsx b/packages/client/src/tiptap/core/extensions/quick-insert.tsx similarity index 95% rename from packages/client/src/tiptap/extensions/quick-insert.tsx rename to packages/client/src/tiptap/core/extensions/quick-insert.tsx index edb1131d..f1ea1bf8 100644 --- a/packages/client/src/tiptap/extensions/quick-insert.tsx +++ b/packages/client/src/tiptap/core/extensions/quick-insert.tsx @@ -3,9 +3,9 @@ import { Node } from '@tiptap/core'; import { ReactRenderer } from '@tiptap/react'; import { Plugin, PluginKey } from 'prosemirror-state'; import Suggestion from '@tiptap/suggestion'; -import { MenuList } from 'tiptap/wrappers/menu-list'; -import { QUICK_INSERT_ITEMS } from 'tiptap/menus/quick-insert'; -import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/constants'; +import { MenuList } from 'tiptap/core/wrappers/menu-list'; +import { QUICK_INSERT_ITEMS } from 'tiptap/editor/menus/quick-insert'; +import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/core/constants'; export const QuickInsertPluginKey = new PluginKey('quickInsert'); diff --git a/packages/client/src/tiptap/extensions/search.ts b/packages/client/src/tiptap/core/extensions/search.ts similarity index 100% rename from packages/client/src/tiptap/extensions/search.ts rename to packages/client/src/tiptap/core/extensions/search.ts diff --git a/packages/client/src/tiptap/extensions/selection.ts b/packages/client/src/tiptap/core/extensions/selection.ts similarity index 98% rename from packages/client/src/tiptap/extensions/selection.ts rename to packages/client/src/tiptap/core/extensions/selection.ts index 0c77e734..e612c903 100644 --- a/packages/client/src/tiptap/extensions/selection.ts +++ b/packages/client/src/tiptap/core/extensions/selection.ts @@ -2,7 +2,7 @@ import { Extension } from '@tiptap/core'; import { Plugin, PluginKey, NodeSelection, TextSelection, Selection, AllSelection } from 'prosemirror-state'; import { Decoration, DecorationSet } from 'prosemirror-view'; import { getCurrentNode, isInCodeBlock, isInCallout } from 'tiptap/prose-utils'; -import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/constants'; +import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/core/constants'; export const selectionPluginKey = new PluginKey('selection'); diff --git a/packages/client/src/tiptap/extensions/status.ts b/packages/client/src/tiptap/core/extensions/status.ts similarity index 96% rename from packages/client/src/tiptap/extensions/status.ts rename to packages/client/src/tiptap/core/extensions/status.ts index 9e02fb2e..de5be4b9 100644 --- a/packages/client/src/tiptap/extensions/status.ts +++ b/packages/client/src/tiptap/core/extensions/status.ts @@ -1,6 +1,6 @@ import { Node, mergeAttributes } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; -import { StatusWrapper } from 'tiptap/wrappers/status'; +import { StatusWrapper } from 'tiptap/core/wrappers/status'; import { getDatasetAttribute } from 'tiptap/prose-utils'; type IStatusAttrs = { diff --git a/packages/client/src/tiptap/extensions/strike.ts b/packages/client/src/tiptap/core/extensions/strike.ts similarity index 100% rename from packages/client/src/tiptap/extensions/strike.ts rename to packages/client/src/tiptap/core/extensions/strike.ts diff --git a/packages/client/src/tiptap/extensions/subscript.ts b/packages/client/src/tiptap/core/extensions/subscript.ts similarity index 100% rename from packages/client/src/tiptap/extensions/subscript.ts rename to packages/client/src/tiptap/core/extensions/subscript.ts diff --git a/packages/client/src/tiptap/extensions/superscript.ts b/packages/client/src/tiptap/core/extensions/superscript.ts similarity index 100% rename from packages/client/src/tiptap/extensions/superscript.ts rename to packages/client/src/tiptap/core/extensions/superscript.ts diff --git a/packages/client/src/tiptap/extensions/table-cell.tsx b/packages/client/src/tiptap/core/extensions/table-cell.tsx similarity index 100% rename from packages/client/src/tiptap/extensions/table-cell.tsx rename to packages/client/src/tiptap/core/extensions/table-cell.tsx diff --git a/packages/client/src/tiptap/extensions/table-header.tsx b/packages/client/src/tiptap/core/extensions/table-header.tsx similarity index 100% rename from packages/client/src/tiptap/extensions/table-header.tsx rename to packages/client/src/tiptap/core/extensions/table-header.tsx diff --git a/packages/client/src/tiptap/extensions/table-row.ts b/packages/client/src/tiptap/core/extensions/table-row.ts similarity index 100% rename from packages/client/src/tiptap/extensions/table-row.ts rename to packages/client/src/tiptap/core/extensions/table-row.ts diff --git a/packages/client/src/tiptap/extensions/table.ts b/packages/client/src/tiptap/core/extensions/table.ts similarity index 100% rename from packages/client/src/tiptap/extensions/table.ts rename to packages/client/src/tiptap/core/extensions/table.ts diff --git a/packages/client/src/tiptap/extensions/task-item.ts b/packages/client/src/tiptap/core/extensions/task-item.ts similarity index 98% rename from packages/client/src/tiptap/extensions/task-item.ts rename to packages/client/src/tiptap/core/extensions/task-item.ts index 1915b7cf..3d1c09b0 100644 --- a/packages/client/src/tiptap/extensions/task-item.ts +++ b/packages/client/src/tiptap/core/extensions/task-item.ts @@ -2,7 +2,7 @@ import { wrappingInputRule } from '@tiptap/core'; import { TaskItem as BuiltInTaskItem } from '@tiptap/extension-task-item'; import { Plugin } from 'prosemirror-state'; import { findParentNodeClosestToPos } from 'prosemirror-utils'; -import { PARSE_HTML_PRIORITY_HIGHEST } from 'tiptap/constants'; +import { PARSE_HTML_PRIORITY_HIGHEST } from 'tiptap/core/constants'; const CustomTaskItem = BuiltInTaskItem.extend({ parseHTML() { diff --git a/packages/client/src/tiptap/extensions/task-list.ts b/packages/client/src/tiptap/core/extensions/task-list.ts similarity index 79% rename from packages/client/src/tiptap/extensions/task-list.ts rename to packages/client/src/tiptap/core/extensions/task-list.ts index dedb4e99..04743e4b 100644 --- a/packages/client/src/tiptap/extensions/task-list.ts +++ b/packages/client/src/tiptap/core/extensions/task-list.ts @@ -1,5 +1,5 @@ import { TaskList as BuiltInTaskList } from '@tiptap/extension-task-list'; -import { PARSE_HTML_PRIORITY_HIGHEST } from 'tiptap/constants'; +import { PARSE_HTML_PRIORITY_HIGHEST } from 'tiptap/core/constants'; export const TaskList = BuiltInTaskList.extend({ parseHTML() { diff --git a/packages/client/src/tiptap/extensions/text-align.ts b/packages/client/src/tiptap/core/extensions/text-align.ts similarity index 100% rename from packages/client/src/tiptap/extensions/text-align.ts rename to packages/client/src/tiptap/core/extensions/text-align.ts diff --git a/packages/client/src/tiptap/extensions/text-style.ts b/packages/client/src/tiptap/core/extensions/text-style.ts similarity index 100% rename from packages/client/src/tiptap/extensions/text-style.ts rename to packages/client/src/tiptap/core/extensions/text-style.ts diff --git a/packages/client/src/tiptap/extensions/text.ts b/packages/client/src/tiptap/core/extensions/text.ts similarity index 100% rename from packages/client/src/tiptap/extensions/text.ts rename to packages/client/src/tiptap/core/extensions/text.ts diff --git a/packages/client/src/tiptap/extensions/title.tsx b/packages/client/src/tiptap/core/extensions/title.tsx similarity index 100% rename from packages/client/src/tiptap/extensions/title.tsx rename to packages/client/src/tiptap/core/extensions/title.tsx diff --git a/packages/client/src/tiptap/extensions/trailing-node.ts b/packages/client/src/tiptap/core/extensions/trailing-node.ts similarity index 100% rename from packages/client/src/tiptap/extensions/trailing-node.ts rename to packages/client/src/tiptap/core/extensions/trailing-node.ts diff --git a/packages/client/src/tiptap/extensions/underline.ts b/packages/client/src/tiptap/core/extensions/underline.ts similarity index 100% rename from packages/client/src/tiptap/extensions/underline.ts rename to packages/client/src/tiptap/core/extensions/underline.ts diff --git a/packages/client/src/tiptap/styles/base.scss b/packages/client/src/tiptap/core/styles/base.scss similarity index 100% rename from packages/client/src/tiptap/styles/base.scss rename to packages/client/src/tiptap/core/styles/base.scss diff --git a/packages/client/src/tiptap/styles/code.scss b/packages/client/src/tiptap/core/styles/code.scss similarity index 100% rename from packages/client/src/tiptap/styles/code.scss rename to packages/client/src/tiptap/core/styles/code.scss diff --git a/packages/client/src/tiptap/styles/collaboration.scss b/packages/client/src/tiptap/core/styles/collaboration.scss similarity index 100% rename from packages/client/src/tiptap/styles/collaboration.scss rename to packages/client/src/tiptap/core/styles/collaboration.scss diff --git a/packages/client/src/tiptap/styles/color.scss b/packages/client/src/tiptap/core/styles/color.scss similarity index 100% rename from packages/client/src/tiptap/styles/color.scss rename to packages/client/src/tiptap/core/styles/color.scss diff --git a/packages/client/src/tiptap/styles/heading.scss b/packages/client/src/tiptap/core/styles/heading.scss similarity index 100% rename from packages/client/src/tiptap/styles/heading.scss rename to packages/client/src/tiptap/core/styles/heading.scss diff --git a/packages/client/src/tiptap/styles/index.scss b/packages/client/src/tiptap/core/styles/index.scss similarity index 100% rename from packages/client/src/tiptap/styles/index.scss rename to packages/client/src/tiptap/core/styles/index.scss diff --git a/packages/client/src/tiptap/styles/katex.scss b/packages/client/src/tiptap/core/styles/katex.scss similarity index 100% rename from packages/client/src/tiptap/styles/katex.scss rename to packages/client/src/tiptap/core/styles/katex.scss diff --git a/packages/client/src/tiptap/styles/list.scss b/packages/client/src/tiptap/core/styles/list.scss similarity index 100% rename from packages/client/src/tiptap/styles/list.scss rename to packages/client/src/tiptap/core/styles/list.scss diff --git a/packages/client/src/tiptap/styles/lock.scss b/packages/client/src/tiptap/core/styles/lock.scss similarity index 100% rename from packages/client/src/tiptap/styles/lock.scss rename to packages/client/src/tiptap/core/styles/lock.scss diff --git a/packages/client/src/tiptap/styles/mention.scss b/packages/client/src/tiptap/core/styles/mention.scss similarity index 100% rename from packages/client/src/tiptap/styles/mention.scss rename to packages/client/src/tiptap/core/styles/mention.scss diff --git a/packages/client/src/tiptap/styles/menu.scss b/packages/client/src/tiptap/core/styles/menu.scss similarity index 100% rename from packages/client/src/tiptap/styles/menu.scss rename to packages/client/src/tiptap/core/styles/menu.scss diff --git a/packages/client/src/tiptap/styles/mind/context-menu.scss b/packages/client/src/tiptap/core/styles/mind/context-menu.scss similarity index 100% rename from packages/client/src/tiptap/styles/mind/context-menu.scss rename to packages/client/src/tiptap/core/styles/mind/context-menu.scss diff --git a/packages/client/src/tiptap/styles/mind/index.scss b/packages/client/src/tiptap/core/styles/mind/index.scss similarity index 100% rename from packages/client/src/tiptap/styles/mind/index.scss rename to packages/client/src/tiptap/core/styles/mind/index.scss diff --git a/packages/client/src/tiptap/styles/mind/mind.scss b/packages/client/src/tiptap/core/styles/mind/mind.scss similarity index 100% rename from packages/client/src/tiptap/styles/mind/mind.scss rename to packages/client/src/tiptap/core/styles/mind/mind.scss diff --git a/packages/client/src/tiptap/styles/mind/mobile-menu.scss b/packages/client/src/tiptap/core/styles/mind/mobile-menu.scss similarity index 100% rename from packages/client/src/tiptap/styles/mind/mobile-menu.scss rename to packages/client/src/tiptap/core/styles/mind/mobile-menu.scss diff --git a/packages/client/src/tiptap/styles/mind/node-menu.scss b/packages/client/src/tiptap/core/styles/mind/node-menu.scss similarity index 100% rename from packages/client/src/tiptap/styles/mind/node-menu.scss rename to packages/client/src/tiptap/core/styles/mind/node-menu.scss diff --git a/packages/client/src/tiptap/styles/mind/toolbar.scss b/packages/client/src/tiptap/core/styles/mind/toolbar.scss similarity index 100% rename from packages/client/src/tiptap/styles/mind/toolbar.scss rename to packages/client/src/tiptap/core/styles/mind/toolbar.scss diff --git a/packages/client/src/tiptap/styles/node.scss b/packages/client/src/tiptap/core/styles/node.scss similarity index 100% rename from packages/client/src/tiptap/styles/node.scss rename to packages/client/src/tiptap/core/styles/node.scss diff --git a/packages/client/src/tiptap/styles/placeholder.scss b/packages/client/src/tiptap/core/styles/placeholder.scss similarity index 100% rename from packages/client/src/tiptap/styles/placeholder.scss rename to packages/client/src/tiptap/core/styles/placeholder.scss diff --git a/packages/client/src/tiptap/styles/search.scss b/packages/client/src/tiptap/core/styles/search.scss similarity index 100% rename from packages/client/src/tiptap/styles/search.scss rename to packages/client/src/tiptap/core/styles/search.scss diff --git a/packages/client/src/tiptap/styles/selection.scss b/packages/client/src/tiptap/core/styles/selection.scss similarity index 100% rename from packages/client/src/tiptap/styles/selection.scss rename to packages/client/src/tiptap/core/styles/selection.scss diff --git a/packages/client/src/tiptap/styles/table.scss b/packages/client/src/tiptap/core/styles/table.scss similarity index 96% rename from packages/client/src/tiptap/styles/table.scss rename to packages/client/src/tiptap/core/styles/table.scss index fbb1b2a6..0b5fca3b 100644 --- a/packages/client/src/tiptap/styles/table.scss +++ b/packages/client/src/tiptap/core/styles/table.scss @@ -1,7 +1,9 @@ .ProseMirror { .tableWrapper { + max-width: 100%; padding: 0; margin: 0; + overflow: auto; } table { diff --git a/packages/client/src/tiptap/styles/title.scss b/packages/client/src/tiptap/core/styles/title.scss similarity index 100% rename from packages/client/src/tiptap/styles/title.scss rename to packages/client/src/tiptap/core/styles/title.scss diff --git a/packages/client/src/tiptap/styles/var.scss b/packages/client/src/tiptap/core/styles/var.scss similarity index 100% rename from packages/client/src/tiptap/styles/var.scss rename to packages/client/src/tiptap/core/styles/var.scss diff --git a/packages/client/src/tiptap/wrappers/attachment/file-icon.tsx b/packages/client/src/tiptap/core/wrappers/attachment/file-icon.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/attachment/file-icon.tsx rename to packages/client/src/tiptap/core/wrappers/attachment/file-icon.tsx diff --git a/packages/client/src/tiptap/wrappers/attachment/index.module.scss b/packages/client/src/tiptap/core/wrappers/attachment/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/attachment/index.module.scss rename to packages/client/src/tiptap/core/wrappers/attachment/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/attachment/index.tsx b/packages/client/src/tiptap/core/wrappers/attachment/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/attachment/index.tsx rename to packages/client/src/tiptap/core/wrappers/attachment/index.tsx diff --git a/packages/client/src/tiptap/wrappers/attachment/player/index.module.scss b/packages/client/src/tiptap/core/wrappers/attachment/player/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/attachment/player/index.module.scss rename to packages/client/src/tiptap/core/wrappers/attachment/player/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/attachment/player/index.tsx b/packages/client/src/tiptap/core/wrappers/attachment/player/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/attachment/player/index.tsx rename to packages/client/src/tiptap/core/wrappers/attachment/player/index.tsx diff --git a/packages/client/src/tiptap/wrappers/attachment/player/pdf-player/index.module.scss b/packages/client/src/tiptap/core/wrappers/attachment/player/pdf-player/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/attachment/player/pdf-player/index.module.scss rename to packages/client/src/tiptap/core/wrappers/attachment/player/pdf-player/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/attachment/player/pdf-player/index.tsx b/packages/client/src/tiptap/core/wrappers/attachment/player/pdf-player/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/attachment/player/pdf-player/index.tsx rename to packages/client/src/tiptap/core/wrappers/attachment/player/pdf-player/index.tsx diff --git a/packages/client/src/tiptap/wrappers/callout/index.module.scss b/packages/client/src/tiptap/core/wrappers/callout/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/callout/index.module.scss rename to packages/client/src/tiptap/core/wrappers/callout/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/callout/index.tsx b/packages/client/src/tiptap/core/wrappers/callout/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/callout/index.tsx rename to packages/client/src/tiptap/core/wrappers/callout/index.tsx diff --git a/packages/client/src/tiptap/wrappers/code-block/index.module.scss b/packages/client/src/tiptap/core/wrappers/code-block/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/code-block/index.module.scss rename to packages/client/src/tiptap/core/wrappers/code-block/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/code-block/index.tsx b/packages/client/src/tiptap/core/wrappers/code-block/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/code-block/index.tsx rename to packages/client/src/tiptap/core/wrappers/code-block/index.tsx diff --git a/packages/client/src/tiptap/wrappers/countdown/index.module.scss b/packages/client/src/tiptap/core/wrappers/countdown/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/countdown/index.module.scss rename to packages/client/src/tiptap/core/wrappers/countdown/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/countdown/index.tsx b/packages/client/src/tiptap/core/wrappers/countdown/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/countdown/index.tsx rename to packages/client/src/tiptap/core/wrappers/countdown/index.tsx diff --git a/packages/client/src/tiptap/wrappers/document-children/index.module.scss b/packages/client/src/tiptap/core/wrappers/document-children/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/document-children/index.module.scss rename to packages/client/src/tiptap/core/wrappers/document-children/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/document-children/index.tsx b/packages/client/src/tiptap/core/wrappers/document-children/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/document-children/index.tsx rename to packages/client/src/tiptap/core/wrappers/document-children/index.tsx diff --git a/packages/client/src/tiptap/wrappers/document-reference/index.module.scss b/packages/client/src/tiptap/core/wrappers/document-reference/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/document-reference/index.module.scss rename to packages/client/src/tiptap/core/wrappers/document-reference/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/document-reference/index.tsx b/packages/client/src/tiptap/core/wrappers/document-reference/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/document-reference/index.tsx rename to packages/client/src/tiptap/core/wrappers/document-reference/index.tsx diff --git a/packages/client/src/tiptap/wrappers/emoji-list/emojis.ts b/packages/client/src/tiptap/core/wrappers/emoji-list/emojis.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/emoji-list/emojis.ts rename to packages/client/src/tiptap/core/wrappers/emoji-list/emojis.ts diff --git a/packages/client/src/tiptap/wrappers/emoji-list/index.module.scss b/packages/client/src/tiptap/core/wrappers/emoji-list/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/emoji-list/index.module.scss rename to packages/client/src/tiptap/core/wrappers/emoji-list/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/emoji-list/index.tsx b/packages/client/src/tiptap/core/wrappers/emoji-list/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/emoji-list/index.tsx rename to packages/client/src/tiptap/core/wrappers/emoji-list/index.tsx diff --git a/packages/client/src/tiptap/wrappers/iframe/index.module.scss b/packages/client/src/tiptap/core/wrappers/iframe/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/iframe/index.module.scss rename to packages/client/src/tiptap/core/wrappers/iframe/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/iframe/index.tsx b/packages/client/src/tiptap/core/wrappers/iframe/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/iframe/index.tsx rename to packages/client/src/tiptap/core/wrappers/iframe/index.tsx diff --git a/packages/client/src/tiptap/wrappers/image/index.module.scss b/packages/client/src/tiptap/core/wrappers/image/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/image/index.module.scss rename to packages/client/src/tiptap/core/wrappers/image/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/image/index.tsx b/packages/client/src/tiptap/core/wrappers/image/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/image/index.tsx rename to packages/client/src/tiptap/core/wrappers/image/index.tsx diff --git a/packages/client/src/tiptap/wrappers/katex/index.module.scss b/packages/client/src/tiptap/core/wrappers/katex/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/katex/index.module.scss rename to packages/client/src/tiptap/core/wrappers/katex/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/katex/index.tsx b/packages/client/src/tiptap/core/wrappers/katex/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/katex/index.tsx rename to packages/client/src/tiptap/core/wrappers/katex/index.tsx diff --git a/packages/client/src/tiptap/wrappers/loading.tsx b/packages/client/src/tiptap/core/wrappers/loading.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/loading.tsx rename to packages/client/src/tiptap/core/wrappers/loading.tsx diff --git a/packages/client/src/tiptap/wrappers/mention-list/index.module.scss b/packages/client/src/tiptap/core/wrappers/mention-list/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/mention-list/index.module.scss rename to packages/client/src/tiptap/core/wrappers/mention-list/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/mention-list/index.tsx b/packages/client/src/tiptap/core/wrappers/mention-list/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/mention-list/index.tsx rename to packages/client/src/tiptap/core/wrappers/mention-list/index.tsx diff --git a/packages/client/src/tiptap/wrappers/menu-list/index.module.scss b/packages/client/src/tiptap/core/wrappers/menu-list/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/menu-list/index.module.scss rename to packages/client/src/tiptap/core/wrappers/menu-list/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/menu-list/index.tsx b/packages/client/src/tiptap/core/wrappers/menu-list/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/menu-list/index.tsx rename to packages/client/src/tiptap/core/wrappers/menu-list/index.tsx diff --git a/packages/client/src/tiptap/wrappers/mind/index.module.scss b/packages/client/src/tiptap/core/wrappers/mind/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/index.module.scss rename to packages/client/src/tiptap/core/wrappers/mind/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/mind/index.tsx b/packages/client/src/tiptap/core/wrappers/mind/index.tsx similarity index 98% rename from packages/client/src/tiptap/wrappers/mind/index.tsx rename to packages/client/src/tiptap/core/wrappers/mind/index.tsx index 1eebd3a6..7af48787 100644 --- a/packages/client/src/tiptap/wrappers/mind/index.tsx +++ b/packages/client/src/tiptap/core/wrappers/mind/index.tsx @@ -7,7 +7,7 @@ import { Spin, Typography } from '@douyinfe/semi-ui'; import { Resizeable } from 'components/resizeable'; import { useToggle } from 'hooks/use-toggle'; import { getEditorContainerDOMSize, uuid } from 'tiptap/prose-utils'; -import { Mind } from 'tiptap/extensions/mind'; +import { Mind } from 'tiptap/core/extensions/mind'; import styles from './index.module.scss'; const { Text } = Typography; diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/const.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/const.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/const.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/const.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/customLink.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/customLink.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/customLink.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/customLink.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/i18n.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/i18n.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/i18n.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/i18n.ts diff --git a/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/iconfont/iconfont.js b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/iconfont/iconfont.js new file mode 100644 index 00000000..3823ea6b --- /dev/null +++ b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/iconfont/iconfont.js @@ -0,0 +1,61 @@ +!(function (t) { + var c, + l, + a, + e, + o, + i, + n = + '', + h = (h = document.getElementsByTagName('script'))[h.length - 1].getAttribute('data-injectcss'); + if (h && !t.__iconfont__svg__cssinject__) { + t.__iconfont__svg__cssinject__ = !0; + try { + document.write( + '' + ); + } catch (t) { + console && console.log(t); + } + } + function d() { + o || ((o = !0), a()); + } + (c = function () { + var t, c, l, a; + ((a = document.createElement('div')).innerHTML = n), + (n = null), + (l = a.getElementsByTagName('svg')[0]) && + (l.setAttribute('aria-hidden', 'true'), + (l.style.position = 'absolute'), + (l.style.width = 0), + (l.style.height = 0), + (l.style.overflow = 'hidden'), + (t = l), + (c = document.body).firstChild + ? ((a = t), (l = c.firstChild).parentNode.insertBefore(a, l)) + : c.appendChild(t)); + }), + document.addEventListener + ? ~['complete', 'loaded', 'interactive'].indexOf(document.readyState) + ? setTimeout(c, 0) + : ((l = function () { + document.removeEventListener('DOMContentLoaded', l, !1), c(); + }), + document.addEventListener('DOMContentLoaded', l, !1)) + : document.attachEvent && + ((a = c), + (e = t.document), + (o = !1), + (i = function () { + try { + e.documentElement.doScroll('left'); + } catch (t) { + return void setTimeout(i, 50); + } + d(); + })(), + (e.onreadystatechange = function () { + 'complete' == e.readyState && ((e.onreadystatechange = null), d()); + })); +})(window); diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/index.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/index.ts similarity index 99% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/index.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/index.ts index b7c114a4..043096dc 100644 --- a/packages/client/src/tiptap/wrappers/mind/mind-elixir/index.ts +++ b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/index.ts @@ -198,6 +198,7 @@ function MindElixir( ) { const box = document.querySelector(el); if (!box) return; + // @ts-ignore this.mindElixirBox = box; this.before = before || {}; this.nodeData = data.nodeData; @@ -416,7 +417,6 @@ MindElixir.prototype = { destroy: function () { this.bus.destroy(); - this.mindElixirBox.removeChild(this.container); }, }; diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/interact.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/interact.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/interact.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/interact.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/linkDiv.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/linkDiv.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/linkDiv.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/linkDiv.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/mouse.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/mouse.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/mouse.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/mouse.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/nodeOperation.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/nodeOperation.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/nodeOperation.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/nodeOperation.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/contextMenu.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/contextMenu.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/contextMenu.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/contextMenu.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/keypress.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/keypress.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/keypress.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/keypress.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/mobileMenu.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/mobileMenu.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/mobileMenu.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/mobileMenu.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/nodeDraggable.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/nodeDraggable.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/nodeDraggable.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/nodeDraggable.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/nodeMenu.tsx b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/nodeMenu.tsx similarity index 99% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/nodeMenu.tsx rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/nodeMenu.tsx index b432519e..99b53db2 100644 --- a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/nodeMenu.tsx +++ b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/nodeMenu.tsx @@ -3,7 +3,7 @@ import ReactDOM from 'react-dom'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Button, Tooltip, Space, Dropdown, Form } from '@douyinfe/semi-ui'; import { IconBold, IconFont, IconMark, IconLink } from '@douyinfe/semi-icons'; -import { ColorPicker } from 'tiptap/menus/_components/color-picker'; +import { ColorPicker } from 'tiptap/components/color-picker'; import { findEle } from '../utils/dom'; import { FormApi } from '@douyinfe/semi-ui/lib/es/form'; diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/toolBar.tsx b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/toolBar.tsx similarity index 98% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/toolBar.tsx rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/toolBar.tsx index c92382f7..1f5739c5 100644 --- a/packages/client/src/tiptap/wrappers/mind/mind-elixir/plugin/toolBar.tsx +++ b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/plugin/toolBar.tsx @@ -11,7 +11,7 @@ import { IconZoomOut, IconZoomIn, } from 'components/icons'; -import { Divider } from 'tiptap/divider'; +import { Divider } from 'tiptap/components/divider'; import { useToggle } from 'hooks/use-toggle'; import { useMemo } from 'react'; diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/dom.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/dom.ts similarity index 99% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/dom.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/dom.ts index 7b474bd4..c0d5e7b9 100644 --- a/packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/dom.ts +++ b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/dom.ts @@ -1,6 +1,6 @@ import { LEFT, RIGHT, SIDE } from '../const'; import { NodeObj } from '../index'; -import { encodeHTML } from '../utils/index'; +import { encodeHTML } from './index'; export type Top = HTMLElement; export type Group = HTMLElement; diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/index.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/index.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/index.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/index.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/pubsub.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/pubsub.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/pubsub.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/pubsub.ts diff --git a/packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/svg.ts b/packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/svg.ts similarity index 100% rename from packages/client/src/tiptap/wrappers/mind/mind-elixir/utils/svg.ts rename to packages/client/src/tiptap/core/wrappers/mind/mind-elixir/utils/svg.ts diff --git a/packages/client/src/tiptap/wrappers/status/index.module.scss b/packages/client/src/tiptap/core/wrappers/status/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/status/index.module.scss rename to packages/client/src/tiptap/core/wrappers/status/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/status/index.tsx b/packages/client/src/tiptap/core/wrappers/status/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/status/index.tsx rename to packages/client/src/tiptap/core/wrappers/status/index.tsx diff --git a/packages/client/src/tiptap/wrappers/task-item/index.module.scss b/packages/client/src/tiptap/core/wrappers/task-item/index.module.scss similarity index 100% rename from packages/client/src/tiptap/wrappers/task-item/index.module.scss rename to packages/client/src/tiptap/core/wrappers/task-item/index.module.scss diff --git a/packages/client/src/tiptap/wrappers/task-item/index.tsx b/packages/client/src/tiptap/core/wrappers/task-item/index.tsx similarity index 100% rename from packages/client/src/tiptap/wrappers/task-item/index.tsx rename to packages/client/src/tiptap/core/wrappers/task-item/index.tsx diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx b/packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx new file mode 100644 index 00000000..5b3cfc27 --- /dev/null +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx @@ -0,0 +1,115 @@ +import React, { useEffect, forwardRef, useImperativeHandle, useRef, useMemo } from 'react'; +import { Toast, BackTop } from '@douyinfe/semi-ui'; +import { HocuspocusProvider } from '@hocuspocus/provider'; +import { debounce } from 'helpers/debounce'; +import { useNetwork } from 'hooks/use-network'; +import { useToggle } from 'hooks/use-toggle'; +import { LogoName } from 'components/logo'; +import { Banner } from 'components/banner'; +import { useEditor, EditorContent } from '../../react'; +import { Collaboration } from 'tiptap/core/extensions/collaboration'; +import { CollaborationCursor } from 'tiptap/core/extensions/collaboration-cursor'; +import { getRandomColor } from 'helpers/color'; +import { CollaborationKit } from '../kit'; +import { MenuBar } from './menubar'; +import { ICollaborationEditorProps, ProviderStatus } from './type'; + +type IProps = Pick< + ICollaborationEditorProps, + 'editable' | 'user' | 'onTitleUpdate' | 'menubar' | 'renderInEditorPortal' +> & { + hocuspocusProvider: HocuspocusProvider; + status: ProviderStatus; +}; + +export const EditorInstance = forwardRef((props: IProps, ref) => { + const { hocuspocusProvider, editable, user, onTitleUpdate, status, menubar, renderInEditorPortal } = props; + const $mainContainer = useRef(); + const { online } = useNetwork(); + const [created, toggleCreated] = useToggle(false); + const editor = useEditor( + { + editable, + extensions: [ + ...CollaborationKit, + Collaboration.configure({ + document: hocuspocusProvider.document, + }), + CollaborationCursor.configure({ + provider: hocuspocusProvider, + user: { + ...(user || { + name: '匿名用户正在阅读文章...', + }), + color: getRandomColor(), + }, + }), + ].filter(Boolean), + onTransaction: debounce(({ transaction }) => { + try { + const title = transaction.doc.content.firstChild.content.firstChild.textContent; + onTitleUpdate(title); + } catch (e) { + // + } + }, 50), + onCreate() { + toggleCreated(true); + }, + onDestroy() {}, + }, + [editable, user, onTitleUpdate, hocuspocusProvider] + ); + + useImperativeHandle(ref, () => editor); + + const protals = useMemo(() => { + if (!created || !renderInEditorPortal) return; + return renderInEditorPortal($mainContainer.current); + }, [created, renderInEditorPortal]); + + // 监听 ctrl+s + useEffect(() => { + const listener = (event: KeyboardEvent) => { + if ((event.ctrlKey || event.metaKey) && event.keyCode == 83) { + event.preventDefault(); + Toast.info(`${LogoName}会实时保存你的数据,无需手动保存。`); + return false; + } + }; + + window.document.addEventListener('keydown', listener); + + return () => { + window.document.removeEventListener('keydown', listener); + }; + }, []); + + return ( + <> + {(!online || status === 'disconnected') && ( + + )} + {/* FIXME:需要菜单栏但是无法编辑,则认为进入了编辑模式但是没有编辑权限 */} + {!editable && menubar && ( + + )} + {menubar && ( +
+ +
+ )} +
+ + {protals} +
+ + {editable && menubar && $mainContainer.current} visibilityHeight={200} />} + + ); +}); + +EditorInstance.displayName = 'EditorInstance'; diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss b/packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss new file mode 100644 index 00000000..92d2e0ab --- /dev/null +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss @@ -0,0 +1,26 @@ +.wrap { + display: flex; + width: 100%; + height: 100%; + overflow: hidden; + flex-direction: column; + + > header { + position: relative; + z-index: 110; + display: flex; + justify-content: center; + height: 50px; + padding: 0 24px; + overflow: hidden; + background-color: var(--semi-color-nav-bg); + align-items: center; + border-bottom: 1px solid var(--semi-color-border); + user-select: none; + } + + > main { + flex: 1; + overflow: auto; + } +} diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx b/packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx new file mode 100644 index 00000000..71463f1c --- /dev/null +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx @@ -0,0 +1,140 @@ +import React, { useMemo, useState, useEffect, forwardRef, useImperativeHandle, useRef } from 'react'; +import { Typography, Spin } from '@douyinfe/semi-ui'; +import { IndexeddbPersistence } from 'y-indexeddb'; +import { HocuspocusProvider } from '@hocuspocus/provider'; +import { useToggle } from 'hooks/use-toggle'; +import { SecureDocumentIllustration } from 'illustrations/secure-document'; +import { DataRender } from 'components/data-render'; +import { Editor } from '../../react'; +import { ICollaborationEditorProps, ProviderStatus } from './type'; +import { EditorInstance } from './editor'; +import styles from './index.module.scss'; + +const { Text } = Typography; + +export type ICollaborationRefProps = { + getEditor: () => Editor; +}; + +export const CollaborationEditor = forwardRef((props: ICollaborationEditorProps, ref) => { + const { + id: documentId, + type, + editable, + onTitleUpdate, + user, + menubar, + renderInEditorPortal, + onAwarenessUpdate, + } = props; + const $editor = useRef(); + const [loading, toggleLoading] = useToggle(true); + const [error, setError] = useState(null); + const [status, setStatus] = useState('connecting'); + + const hocuspocusProvider = useMemo(() => { + return new HocuspocusProvider({ + url: process.env.COLLABORATION_API_URL, + name: documentId, + token: (user && user.token) || 'read-public', + parameters: { + targetId: documentId, + userId: user && user.id, + docType: type, + }, + maxAttempts: 1, + onAwarenessUpdate({ states }) { + const users = states.map((state) => ({ clientId: state.clientId, user: state.user })); + onAwarenessUpdate && onAwarenessUpdate(users); + }, + onAuthenticationFailed() { + toggleLoading(false); + setError(new Error('鉴权失败!暂时无法提供服务')); + }, + onSynced() { + toggleLoading(false); + }, + onStatus({ status }) { + setStatus(status); + }, + } as any); + }, [documentId, user, type, onAwarenessUpdate, toggleLoading]); + + useImperativeHandle( + ref, + () => + ({ + getEditor: () => $editor.current, + } as ICollaborationRefProps) + ); + + // 离线缓存 + useEffect(() => { + if (!editable) return; + const indexdbProvider = new IndexeddbPersistence(documentId, hocuspocusProvider.document); + indexdbProvider.on('synced', () => { + setStatus('loadCacheSuccess'); + }); + + return () => { + if (indexdbProvider) { + indexdbProvider.destroy(); + } + }; + }, [editable, documentId, hocuspocusProvider]); + + useEffect(() => { + return () => { + if (hocuspocusProvider) { + hocuspocusProvider.destroy(); + } + }; + }, [hocuspocusProvider]); + + return ( +
+ + + {/* FIXME: semi-design 的问题,不加 div,文字会换行! */} +
+
+
+ } + error={error} + errorContent={(error) => ( +
+ + + {(error && error.message) || '未知错误'} + +
+ )} + normalContent={() => ( + + )} + /> +
+ ); +}); + +CollaborationEditor.displayName = 'CollaborationEditor'; diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/menubar.tsx b/packages/client/src/tiptap/editor/collaboration/collaboration/menubar.tsx new file mode 100644 index 00000000..81bf8727 --- /dev/null +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/menubar.tsx @@ -0,0 +1,119 @@ +import React, { useMemo } from 'react'; +import { Space } from '@douyinfe/semi-ui'; +import { Divider } from 'tiptap/components/divider'; +import { Editor } from 'tiptap/editor'; + +import { Insert } from 'tiptap/editor/menus/insert'; +import { Undo } from 'tiptap/editor/menus/undo'; +import { Redo } from 'tiptap/editor/menus/redo'; +import { CleadrNodeAndMarks } from 'tiptap/editor/menus/clear-node-and-marks'; + +import { Heading } from 'tiptap/editor/menus/heading'; +import { FontSize } from 'tiptap/editor/menus/fontsize'; +import { Bold } from 'tiptap/editor/menus/bold'; +import { Italic } from 'tiptap/editor/menus/italic'; +import { Underline } from 'tiptap/editor/menus/underline'; +import { Strike } from 'tiptap/editor/menus/strike'; +import { Code } from 'tiptap/editor/menus/code'; +import { Superscript } from 'tiptap/editor/menus/superscript'; +import { Subscript } from 'tiptap/editor/menus/subscript'; +import { TextColor } from 'tiptap/editor/menus/text-color'; +import { BackgroundColor } from 'tiptap/editor/menus/background-color'; + +import { Align } from 'tiptap/editor/menus/align'; + +import { BulletList } from 'tiptap/editor/menus/bullet-list'; +import { OrderedList } from 'tiptap/editor/menus/ordered-list'; +import { TaskList } from 'tiptap/editor/menus/task-list'; +import { Ident } from 'tiptap/editor/menus/ident'; + +import { Emoji } from 'tiptap/editor/menus/emoji'; +import { Link } from 'tiptap/editor/menus/link'; +import { Blockquote } from 'tiptap/editor/menus/blockquote'; +import { HorizontalRule } from 'tiptap/editor/menus/horizontal-rule'; +import { Search } from 'tiptap/editor/menus/search'; + +import { Attachment } from 'tiptap/editor/menus/attachment'; +import { Callout } from 'tiptap/editor/menus/callout'; +import { CodeBlock } from 'tiptap/editor/menus/code-block'; +import { Countdonw } from 'tiptap/editor/menus/countdown'; +import { DocumentChildren } from 'tiptap/editor/menus/document-children'; +import { DocumentReference } from 'tiptap/editor/menus/document-reference'; +import { Image } from 'tiptap/editor/menus/image'; +import { Iframe } from 'tiptap/editor/menus/iframe'; +import { Table } from 'tiptap/editor/menus/table'; +import { Mind } from 'tiptap/editor/menus/mind'; + +const _MenuBar: React.FC<{ editor: Editor }> = ({ editor }) => { + const isEditable = useMemo(() => editor && editor.isEditable, [editor]); + + if (!editor) return null; + + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +