From 27d4261c1db5837a57123cbcf319d0b983f85a84 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Sat, 2 Jul 2022 10:26:41 +0800 Subject: [PATCH] close #107 --- .../src/tiptap/core/extensions/callout.ts | 8 +-- .../src/tiptap/core/extensions/clipboard.ts | 56 +++++++++---------- .../src/tiptap/core/extensions/countdown.ts | 2 +- .../client/src/tiptap/core/extensions/flow.ts | 2 +- .../src/tiptap/core/extensions/katex.ts | 5 +- .../client/src/tiptap/core/extensions/mind.ts | 2 +- .../src/tiptap/core/extensions/paste.ts | 7 +++ .../src/tiptap/core/wrappers/title/index.tsx | 2 +- .../src/tiptap/prose-utils/dom-dataset.ts | 24 +++++++- 9 files changed, 66 insertions(+), 42 deletions(-) diff --git a/packages/client/src/tiptap/core/extensions/callout.ts b/packages/client/src/tiptap/core/extensions/callout.ts index d0f6f0df..468710b5 100644 --- a/packages/client/src/tiptap/core/extensions/callout.ts +++ b/packages/client/src/tiptap/core/extensions/callout.ts @@ -43,15 +43,11 @@ export const Callout = Node.create({ }, parseHTML() { - return [ - { - tag: 'div', - }, - ]; + return [{ tag: 'div[class=callout]' }]; }, renderHTML({ HTMLAttributes }) { - return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]; + return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0]; }, addCommands() { diff --git a/packages/client/src/tiptap/core/extensions/clipboard.ts b/packages/client/src/tiptap/core/extensions/clipboard.ts index 259a0a1e..158d8453 100644 --- a/packages/client/src/tiptap/core/extensions/clipboard.ts +++ b/packages/client/src/tiptap/core/extensions/clipboard.ts @@ -63,41 +63,41 @@ export const Clipboard = Extension.create({ return false; }, - clipboardTextSerializer: (slice) => { - const json = slice.content.toJSON(); - const isSelectAll = slice.openStart === slice.openEnd && slice.openEnd === 0; + // clipboardTextSerializer: (slice) => { + // const json = slice.content.toJSON(); + // const isSelectAll = slice.openStart === slice.openEnd && slice.openEnd === 0; - if (Array.isArray(json) && !isSelectAll) { - const type = json[0].type; + // if (Array.isArray(json) && !isSelectAll) { + // const type = json[0].type; - // 列表项返回文字内容 - if (['bulletList', 'orderedList', 'taskList'].includes(type)) { - return slice.content.textBetween(0, slice.content.size, '\n\n'); - } - } + // // 列表项返回文字内容 + // if (['bulletList', 'orderedList', 'taskList'].includes(type)) { + // return slice.content.textBetween(0, slice.content.size, '\n\n'); + // } + // } - if (typeof json === 'object' || isSelectAll) { - return extensionThis.options.prosemirrorToMarkdown({ - content: slice.content, - }); - } + // if (typeof json === 'object' || isSelectAll) { + // return extensionThis.options.prosemirrorToMarkdown({ + // content: slice.content, + // }); + // } - const isText = isPureText(json) && !isSelectAll; + // const isText = isPureText(json) && !isSelectAll; - if (isText) { - return slice.content.textBetween(0, slice.content.size, '\n\n'); - } - const doc = slice.content; + // if (isText) { + // return slice.content.textBetween(0, slice.content.size, '\n\n'); + // } + // const doc = slice.content; - if (!doc) { - return ''; - } + // if (!doc) { + // return ''; + // } - const content = extensionThis.options.prosemirrorToMarkdown({ - content: doc, - }); - return content; - }, + // const content = extensionThis.options.prosemirrorToMarkdown({ + // content: doc, + // }); + // return content; + // }, }, }), ]; diff --git a/packages/client/src/tiptap/core/extensions/countdown.ts b/packages/client/src/tiptap/core/extensions/countdown.ts index 016d187c..48f8e6fb 100644 --- a/packages/client/src/tiptap/core/extensions/countdown.ts +++ b/packages/client/src/tiptap/core/extensions/countdown.ts @@ -43,7 +43,7 @@ export const Countdown = Node.create({ parseHTML() { return [ { - tag: 'div', + tag: 'div[class=countdown]', }, ]; }, diff --git a/packages/client/src/tiptap/core/extensions/flow.ts b/packages/client/src/tiptap/core/extensions/flow.ts index bd2f63fd..ac64c0a6 100644 --- a/packages/client/src/tiptap/core/extensions/flow.ts +++ b/packages/client/src/tiptap/core/extensions/flow.ts @@ -60,7 +60,7 @@ export const Flow = Node.create({ parseHTML() { return [ { - tag: 'div', + tag: 'div[class=flow]', }, ]; }, diff --git a/packages/client/src/tiptap/core/extensions/katex.ts b/packages/client/src/tiptap/core/extensions/katex.ts index 75127c7d..afb1f71e 100644 --- a/packages/client/src/tiptap/core/extensions/katex.ts +++ b/packages/client/src/tiptap/core/extensions/katex.ts @@ -2,6 +2,7 @@ import { IUser } from '@think/domains'; import { mergeAttributes, Node, nodeInputRule } from '@tiptap/core'; import { ReactNodeViewRenderer } from '@tiptap/react'; import { KatexWrapper } from 'tiptap/core/wrappers/katex'; +import { getDatasetAttribute } from 'tiptap/prose-utils'; export type IKatexAttrs = { text?: string; @@ -35,9 +36,7 @@ export const Katex = Node.create({ return { text: { default: '', - parseHTML: (element) => { - return element.getAttribute('data-text'); - }, + parseHTML: getDatasetAttribute('text'), }, defaultShowPicker: { default: false, diff --git a/packages/client/src/tiptap/core/extensions/mind.ts b/packages/client/src/tiptap/core/extensions/mind.ts index 5ada9c47..1607f99c 100644 --- a/packages/client/src/tiptap/core/extensions/mind.ts +++ b/packages/client/src/tiptap/core/extensions/mind.ts @@ -71,7 +71,7 @@ export const Mind = Node.create({ parseHTML() { return [ { - tag: 'div', + tag: 'div[class=mind]', }, ]; }, diff --git a/packages/client/src/tiptap/core/extensions/paste.ts b/packages/client/src/tiptap/core/extensions/paste.ts index da2d8bdd..a7ac714d 100644 --- a/packages/client/src/tiptap/core/extensions/paste.ts +++ b/packages/client/src/tiptap/core/extensions/paste.ts @@ -144,6 +144,13 @@ export const Paste = Extension.create({ return true; } + // If the HTML on the clipboard is from Prosemirror then the best + // compatability is to just use the HTML parser, regardless of + // whether it "looks" like Markdown, see: outline/outline#2416 + if (html?.includes('data-pm-slice')) { + return false; + } + // 处理 markdown if (markdownText || isMarkdown(text) || html.length === 0 || pasteCodeLanguage === 'markdown') { event.preventDefault(); diff --git a/packages/client/src/tiptap/core/wrappers/title/index.tsx b/packages/client/src/tiptap/core/wrappers/title/index.tsx index 8c3f152a..820cd9f7 100644 --- a/packages/client/src/tiptap/core/wrappers/title/index.tsx +++ b/packages/client/src/tiptap/core/wrappers/title/index.tsx @@ -68,7 +68,7 @@ export const TitleWrapper = ({ editor, node }) => { {cover ? (
- + {isEditable ? (
diff --git a/packages/client/src/tiptap/prose-utils/dom-dataset.ts b/packages/client/src/tiptap/prose-utils/dom-dataset.ts index 22de6d0e..18b73016 100644 --- a/packages/client/src/tiptap/prose-utils/dom-dataset.ts +++ b/packages/client/src/tiptap/prose-utils/dom-dataset.ts @@ -50,7 +50,29 @@ export const getDatasetAttribute = (attribute: string, transformToJSON = false) => (element: HTMLElement) => { const dataKey = attribute.startsWith('data-') ? attribute : `data-${attribute}`; - const value = decodeURIComponent(element.getAttribute(dataKey)); + let value = decodeURIComponent(element.getAttribute(dataKey)); + + if (value == null || (typeof value === 'string' && value === 'null')) { + try { + const html = element.outerHTML; + // eslint-disable-next-line no-useless-escape + const texts = html.match(/(.|\s)+?\="(.|\s)+?"/gi); + if (texts && texts.length) { + const params = texts + .map((str) => str.trim()) + .reduce((accu, item) => { + const i = item.indexOf('='); + const arr = [item.slice(0, i), item.slice(i + 1).slice(1, -1)]; + accu[arr[0]] = arr[1]; + return accu; + }, {}); + + value = (params[attribute.toLowerCase()] || '').replaceAll('"', '"'); + } + } catch (e) { + console.error('解析 element 失败!', e.message, element); + } + } if (transformToJSON) { try {