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 { ReactNodeViewRenderer } from '@tiptap/react';
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: [] };
@ -56,7 +56,7 @@ export const Excalidraw = Node.create({
addOptions() {
return {
HTMLAttributes: {
class: 'mind',
class: 'excalidraw',
},
};
},
@ -64,13 +64,13 @@ export const Excalidraw = Node.create({
parseHTML() {
return [
{
tag: 'div[class=mind]',
tag: 'div[class=excalidraw]',
},
];
},
renderHTML({ HTMLAttributes }) {
return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
renderHTML({ HTMLAttributes, node }) {
return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, nodeAttrsToDataset(node))];
},
addCommands() {

View File

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

View File

@ -23,6 +23,11 @@ interface IPasteOptions {
*/
htmlToProsemirror: (arg: { schema: Schema; html: string; needTitle: boolean; defaultTitle?: string }) => Node;
/**
* markdown html
*/
markdownToHTML: (arg: string) => string;
/**
* markdown prosemirror
*/
@ -41,6 +46,7 @@ export const Paste = Extension.create<IPasteOptions>({
addOptions() {
return {
htmlToProsemirror: (arg) => '',
markdownToHTML: (arg) => arg,
markdownToProsemirror: (arg) => 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';
// markdown 支持
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';
const DocumentWithTitle = Document.extend({
@ -137,6 +137,7 @@ export const CollaborationKit = [
Underline,
Paste.configure({
htmlToProsemirror,
markdownToHTML,
markdownToProsemirror,
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 { DocumentChildren } from './nodes/document-children';
import { DocumentReference } from './nodes/document-reference';
import { Excalidraw } from './nodes/excalidraw';
import { Flow } from './nodes/flow';
import { HardBreak } from './nodes/hard-break';
import { Heading } from './nodes/heading';
@ -57,6 +58,7 @@ export class Renderer {
Attachment,
Countdown,
Callout,
Excalidraw,
Iframe,
Status,
Mention,

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
import { safeJSONParse } from 'helpers/json';
import { Node } from 'prosemirror-state';
/**
* JSON
@ -89,3 +90,32 @@ export const getDatasetAttribute =
const toNumber = parseInt(value);
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));
};