Merge pull request #115 from fantasticit/fix/markdown

close #107
This commit is contained in:
fantasticit 2022-07-02 10:29:53 +08:00 committed by GitHub
commit 121f089a30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 66 additions and 42 deletions

View File

@ -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() {

View File

@ -63,41 +63,41 @@ export const Clipboard = Extension.create<IClipboardOptions>({
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;
// },
},
}),
];

View File

@ -43,7 +43,7 @@ export const Countdown = Node.create({
parseHTML() {
return [
{
tag: 'div',
tag: 'div[class=countdown]',
},
];
},

View File

@ -60,7 +60,7 @@ export const Flow = Node.create({
parseHTML() {
return [
{
tag: 'div',
tag: 'div[class=flow]',
},
];
},

View File

@ -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,

View File

@ -71,7 +71,7 @@ export const Mind = Node.create({
parseHTML() {
return [
{
tag: 'div',
tag: 'div[class=mind]',
},
];
},

View File

@ -144,6 +144,13 @@ export const Paste = Extension.create<IPasteOptions>({
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();

View File

@ -68,7 +68,7 @@ export const TitleWrapper = ({ editor, node }) => {
<NodeViewWrapper className={cls(styles.wrap, 'title')}>
{cover ? (
<div className={styles.coverWrap} contentEditable={false}>
<LazyLoadImage src={cover} alt="cover" />
<LazyLoadImage src={cover} alt="请选择或移除封面" />
{isEditable ? (
<div className={styles.toolbar}>
<ImageUploader images={images} selectImage={setCover}>

View File

@ -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('&quot;', '"');
}
} catch (e) {
console.error('解析 element 失败!', e.message, element);
}
}
if (transformToJSON) {
try {