Merge pull request #166 from fantasticit/fix/paste

This commit is contained in:
fantasticit 2022-08-16 10:25:28 +08:00 committed by GitHub
commit 058d0e6e48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 63 additions and 9 deletions

View File

@ -2,7 +2,7 @@ import { IUser } from '@think/domains';
import { mergeAttributes, Node, nodeInputRule } from '@tiptap/core'; import { mergeAttributes, Node, nodeInputRule } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react'; import { ReactNodeViewRenderer } from '@tiptap/react';
import { ExcalidrawWrapper } from 'tiptap/core/wrappers/excalidraw'; import { ExcalidrawWrapper } from 'tiptap/core/wrappers/excalidraw';
import { getDatasetAttribute } from 'tiptap/prose-utils'; import { getDatasetAttribute, nodeAttrsToDataset } from 'tiptap/prose-utils';
const DEFAULT_MIND_DATA = { elements: [] }; const DEFAULT_MIND_DATA = { elements: [] };
@ -56,7 +56,7 @@ export const Excalidraw = Node.create({
addOptions() { addOptions() {
return { return {
HTMLAttributes: { HTMLAttributes: {
class: 'mind', class: 'excalidraw',
}, },
}; };
}, },
@ -64,13 +64,13 @@ export const Excalidraw = Node.create({
parseHTML() { parseHTML() {
return [ return [
{ {
tag: 'div[class=mind]', tag: 'div[class=excalidraw]',
}, },
]; ];
}, },
renderHTML({ HTMLAttributes }) { renderHTML({ HTMLAttributes, node }) {
return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]; return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, nodeAttrsToDataset(node))];
}, },
addCommands() { addCommands() {

View File

@ -2,7 +2,7 @@ import { IUser } from '@think/domains';
import { mergeAttributes, Node, nodeInputRule } from '@tiptap/core'; import { mergeAttributes, Node, nodeInputRule } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react'; import { ReactNodeViewRenderer } from '@tiptap/react';
import { MindWrapper } from 'tiptap/core/wrappers/mind'; import { MindWrapper } from 'tiptap/core/wrappers/mind';
import { getDatasetAttribute } from 'tiptap/prose-utils'; import { getDatasetAttribute, nodeAttrsToDataset } from 'tiptap/prose-utils';
const DEFAULT_MIND_DATA = { const DEFAULT_MIND_DATA = {
root: { data: { text: '中心节点' }, children: [] }, root: { data: { text: '中心节点' }, children: [] },
@ -77,8 +77,8 @@ export const Mind = Node.create({
]; ];
}, },
renderHTML({ HTMLAttributes }) { renderHTML({ HTMLAttributes, node }) {
return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]; return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, nodeAttrsToDataset(node))];
}, },
addCommands() { addCommands() {

View File

@ -23,6 +23,11 @@ interface IPasteOptions {
*/ */
htmlToProsemirror: (arg: { schema: Schema; html: string; needTitle: boolean; defaultTitle?: string }) => Node; htmlToProsemirror: (arg: { schema: Schema; html: string; needTitle: boolean; defaultTitle?: string }) => Node;
/**
* markdown html
*/
markdownToHTML: (arg: string) => string;
/** /**
* markdown prosemirror * markdown prosemirror
*/ */
@ -41,6 +46,7 @@ export const Paste = Extension.create<IPasteOptions>({
addOptions() { addOptions() {
return { return {
htmlToProsemirror: (arg) => '', htmlToProsemirror: (arg) => '',
markdownToHTML: (arg) => arg,
markdownToProsemirror: (arg) => arg.content, markdownToProsemirror: (arg) => arg.content,
prosemirrorToMarkdown: (arg) => String(arg.content), prosemirrorToMarkdown: (arg) => String(arg.content),
}; };

View File

@ -66,7 +66,7 @@ import { TrailingNode } from 'tiptap/core/extensions/trailing-node';
import { Underline } from 'tiptap/core/extensions/underline'; import { Underline } from 'tiptap/core/extensions/underline';
// markdown 支持 // markdown 支持
import { htmlToProsemirror } from 'tiptap/markdown/html-to-prosemirror'; import { htmlToProsemirror } from 'tiptap/markdown/html-to-prosemirror';
import { markdownToProsemirror } from 'tiptap/markdown/markdown-to-prosemirror'; import { markdownToHTML, markdownToProsemirror } from 'tiptap/markdown/markdown-to-prosemirror';
import { prosemirrorToMarkdown } from 'tiptap/markdown/prosemirror-to-markdown'; import { prosemirrorToMarkdown } from 'tiptap/markdown/prosemirror-to-markdown';
const DocumentWithTitle = Document.extend({ const DocumentWithTitle = Document.extend({
@ -137,6 +137,7 @@ export const CollaborationKit = [
Underline, Underline,
Paste.configure({ Paste.configure({
htmlToProsemirror, htmlToProsemirror,
markdownToHTML,
markdownToProsemirror, markdownToProsemirror,
prosemirrorToMarkdown, prosemirrorToMarkdown,
}), }),

View File

@ -0,0 +1,9 @@
import { Node } from './node';
export class Excalidraw extends Node {
type = 'excalidraw';
matching() {
return this.DOMNode.nodeName === 'DIV' && this.DOMNode.classList.contains('excalidraw');
}
}

View File

@ -17,6 +17,7 @@ import { CodeBlockWrapper } from './nodes/code-block-wrapper';
import { Countdown } from './nodes/countdown'; import { Countdown } from './nodes/countdown';
import { DocumentChildren } from './nodes/document-children'; import { DocumentChildren } from './nodes/document-children';
import { DocumentReference } from './nodes/document-reference'; import { DocumentReference } from './nodes/document-reference';
import { Excalidraw } from './nodes/excalidraw';
import { Flow } from './nodes/flow'; import { Flow } from './nodes/flow';
import { HardBreak } from './nodes/hard-break'; import { HardBreak } from './nodes/hard-break';
import { Heading } from './nodes/heading'; import { Heading } from './nodes/heading';
@ -57,6 +58,7 @@ export class Renderer {
Attachment, Attachment,
Countdown, Countdown,
Callout, Callout,
Excalidraw,
Iframe, Iframe,
Status, Status,
Mention, Mention,

View File

@ -37,3 +37,5 @@ export const markdownToProsemirror = ({ schema, content, needTitle, defaultTitle
return node; return node;
}; };
export { markdownToHTML };

View File

@ -21,6 +21,7 @@ const markdownDocumentChildren = createMarkdownContainer('documentChildren');
const markdownIframe = createMarkdownContainer('iframe'); const markdownIframe = createMarkdownContainer('iframe');
const markdownMention = createMarkdownContainer('mention'); const markdownMention = createMarkdownContainer('mention');
const markdownMind = createMarkdownContainer('mind'); const markdownMind = createMarkdownContainer('mind');
const markdownExcalidraw = createMarkdownContainer('excalidraw');
const markdownFlow = createMarkdownContainer('flow'); const markdownFlow = createMarkdownContainer('flow');
const markdownTableOfContents = createMarkdownContainer('tableOfContents'); const markdownTableOfContents = createMarkdownContainer('tableOfContents');
const markdownTitle = createMarkdownContainer('title'); const markdownTitle = createMarkdownContainer('title');
@ -44,6 +45,7 @@ const markdown = markdownit('commonmark')
.use(markdownStatus) .use(markdownStatus)
.use(markdownMention) .use(markdownMention)
.use(markdownMind) .use(markdownMind)
.use(markdownExcalidraw)
.use(markdownDocumentReference) .use(markdownDocumentReference)
.use(markdownDocumentChildren) .use(markdownDocumentChildren)
.use(markdownFlow) .use(markdownFlow)

View File

@ -9,6 +9,7 @@ import { CodeBlock } from 'tiptap/core/extensions/code-block';
import { Countdown } from 'tiptap/core/extensions/countdown'; import { Countdown } from 'tiptap/core/extensions/countdown';
import { DocumentChildren } from 'tiptap/core/extensions/document-children'; import { DocumentChildren } from 'tiptap/core/extensions/document-children';
import { DocumentReference } from 'tiptap/core/extensions/document-reference'; import { DocumentReference } from 'tiptap/core/extensions/document-reference';
import { Excalidraw } from 'tiptap/core/extensions/excalidraw';
import { Flow } from 'tiptap/core/extensions/flow'; import { Flow } from 'tiptap/core/extensions/flow';
import { HardBreak } from 'tiptap/core/extensions/hard-break'; import { HardBreak } from 'tiptap/core/extensions/hard-break';
import { Heading } from 'tiptap/core/extensions/heading'; import { Heading } from 'tiptap/core/extensions/heading';
@ -127,6 +128,7 @@ const SerializerConfig = {
[Countdown.name]: renderCustomContainer('countdown'), [Countdown.name]: renderCustomContainer('countdown'),
[DocumentChildren.name]: renderCustomContainer('documentChildren'), [DocumentChildren.name]: renderCustomContainer('documentChildren'),
[DocumentReference.name]: renderCustomContainer('documentReference'), [DocumentReference.name]: renderCustomContainer('documentReference'),
[Excalidraw.name]: renderCustomContainer('excalidraw'),
[Flow.name]: renderCustomContainer('flow'), [Flow.name]: renderCustomContainer('flow'),
[HardBreak.name]: renderHardBreak, [HardBreak.name]: renderHardBreak,
[Heading.name]: defaultMarkdownSerializer.nodes.heading, [Heading.name]: defaultMarkdownSerializer.nodes.heading,

View File

@ -1,4 +1,5 @@
import { safeJSONParse } from 'helpers/json'; import { safeJSONParse } from 'helpers/json';
import { Node } from 'prosemirror-state';
/** /**
* JSON * JSON
@ -89,3 +90,32 @@ export const getDatasetAttribute =
const toNumber = parseInt(value); const toNumber = parseInt(value);
return toNumber !== toNumber ? value : toNumber; // 避免 NaN return toNumber !== toNumber ? value : toNumber; // 避免 NaN
}; };
/**
* dataset
* @param node
* @returns
*/
export const nodeAttrsToDataset = (node: Node) => {
const { attrs } = node;
return Object.keys(attrs).reduce((accu, key) => {
const value = attrs[key];
if (value == null) {
return accu;
}
let encodeValue = '';
if (typeof value === 'object') {
encodeValue = jsonToStr(value);
} else {
encodeValue = value;
}
accu[key] = encodeValue;
return accu;
}, Object.create(null));
};