mirror of https://github.com/fantasticit/think.git
tiptap: fix paste link
This commit is contained in:
parent
4340b3122d
commit
d309d538f5
|
@ -73,6 +73,7 @@
|
||||||
"markdown-it-sup": "^1.0.0",
|
"markdown-it-sup": "^1.0.0",
|
||||||
"next": "12.1.0",
|
"next": "12.1.0",
|
||||||
"next-pwa": "^5.5.2",
|
"next-pwa": "^5.5.2",
|
||||||
|
"prosemirror-commands": "^1.3.0",
|
||||||
"prosemirror-markdown": "^1.7.0",
|
"prosemirror-markdown": "^1.7.0",
|
||||||
"prosemirror-model": "^1.16.1",
|
"prosemirror-model": "^1.16.1",
|
||||||
"prosemirror-schema-list": "^1.1.6",
|
"prosemirror-schema-list": "^1.1.6",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Extension } from '@tiptap/core';
|
import { Extension } from '@tiptap/core';
|
||||||
import { safeJSONParse } from 'helpers/json';
|
import { safeJSONParse } from 'helpers/json';
|
||||||
|
import { toggleMark } from 'prosemirror-commands';
|
||||||
import { Fragment, Schema } from 'prosemirror-model';
|
import { Fragment, Schema } from 'prosemirror-model';
|
||||||
import { Plugin, PluginKey } from 'prosemirror-state';
|
import { Plugin, PluginKey } from 'prosemirror-state';
|
||||||
import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/core/constants';
|
import { EXTENSION_PRIORITY_HIGHEST } from 'tiptap/core/constants';
|
||||||
|
@ -9,6 +10,7 @@ import {
|
||||||
isInCode,
|
isInCode,
|
||||||
isMarkdown,
|
isMarkdown,
|
||||||
isTitleNode,
|
isTitleNode,
|
||||||
|
isValidURL,
|
||||||
LANGUAGES,
|
LANGUAGES,
|
||||||
normalizeMarkdown,
|
normalizeMarkdown,
|
||||||
} from 'tiptap/prose-utils';
|
} from 'tiptap/prose-utils';
|
||||||
|
@ -76,7 +78,9 @@ export const Paste = Extension.create<IPasteOptions>({
|
||||||
if (view.props.editable && !view.props.editable(view.state)) {
|
if (view.props.editable && !view.props.editable(view.state)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!event.clipboardData) return false;
|
if (!event.clipboardData) return false;
|
||||||
|
|
||||||
// 文件
|
// 文件
|
||||||
const files = Array.from(event.clipboardData.files);
|
const files = Array.from(event.clipboardData.files);
|
||||||
if (files.length) {
|
if (files.length) {
|
||||||
|
@ -87,19 +91,39 @@ export const Paste = Extension.create<IPasteOptions>({
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { markdownToProsemirror } = extensionThis.options;
|
|
||||||
const text = event.clipboardData.getData('text/plain');
|
const text = event.clipboardData.getData('text/plain');
|
||||||
const html = event.clipboardData.getData('text/html');
|
const html = event.clipboardData.getData('text/html');
|
||||||
const vscode = event.clipboardData.getData('vscode-editor-data');
|
const vscode = event.clipboardData.getData('vscode-editor-data');
|
||||||
const node = event.clipboardData.getData('text/node');
|
const node = event.clipboardData.getData('text/node');
|
||||||
const markdownText = event.clipboardData.getData('text/markdown');
|
const markdownText = event.clipboardData.getData('text/markdown');
|
||||||
|
const { state, dispatch } = view;
|
||||||
|
|
||||||
|
const { markdownToProsemirror } = extensionThis.options;
|
||||||
|
|
||||||
// 直接复制节点
|
// 直接复制节点
|
||||||
if (node) {
|
if (node) {
|
||||||
const doc = safeJSONParse(node);
|
const json = safeJSONParse(node);
|
||||||
const tr = view.state.tr;
|
const tr = view.state.tr;
|
||||||
const selection = tr.selection;
|
const selection = tr.selection;
|
||||||
view.dispatch(tr.insert(selection.from - 1, view.state.schema.nodeFromJSON(doc)).scrollIntoView());
|
view.dispatch(tr.insert(selection.from - 1, view.state.schema.nodeFromJSON(json)).scrollIntoView());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 链接
|
||||||
|
if (isValidURL(text)) {
|
||||||
|
if (!state.selection.empty) {
|
||||||
|
toggleMark(this.editor.schema.marks.link, { href: text })(state, dispatch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transaction = view.state.tr
|
||||||
|
.insertText(text, state.selection.from, state.selection.to)
|
||||||
|
.addMark(
|
||||||
|
state.selection.from,
|
||||||
|
state.selection.to + text.length,
|
||||||
|
state.schema.marks.link.create({ href: text })
|
||||||
|
);
|
||||||
|
view.dispatch(transaction);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,16 +140,21 @@ export const Paste = Extension.create<IPasteOptions>({
|
||||||
if (pasteCodeLanguage && pasteCodeLanguage !== 'markdown') {
|
if (pasteCodeLanguage && pasteCodeLanguage !== 'markdown') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
view.dispatch(
|
view.dispatch(
|
||||||
view.state.tr.replaceSelectionWith(
|
view.state.tr
|
||||||
view.state.schema.nodes.codeBlock.create({
|
.replaceSelectionWith(
|
||||||
language: Object.keys(LANGUAGES).includes(vscodeMeta.mode) ? vscodeMeta.mode : null,
|
view.state.schema.nodes.codeBlock.create({
|
||||||
})
|
language: Object.keys(LANGUAGES).includes(vscodeMeta.mode) ? vscodeMeta.mode : null,
|
||||||
)
|
})
|
||||||
|
)
|
||||||
|
.insertText(text)
|
||||||
);
|
);
|
||||||
view.dispatch(view.state.tr.insertText(text).scrollIntoView());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (html?.includes('data-pm-slice')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 处理 markdown
|
// 处理 markdown
|
||||||
if (markdownText || isMarkdown(text) || html.length === 0 || pasteCodeLanguage === 'markdown') {
|
if (markdownText || isMarkdown(text) || html.length === 0 || pasteCodeLanguage === 'markdown') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -147,11 +176,13 @@ export const Paste = Extension.create<IPasteOptions>({
|
||||||
view.dispatch(tr.scrollIntoView());
|
view.dispatch(tr.scrollIntoView());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text.length !== 0) {
|
if (text.length !== 0) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
view.dispatch(view.state.tr.insertText(text));
|
view.dispatch(view.state.tr.insertText(text));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
handleDrop: (view, event: any) => {
|
handleDrop: (view, event: any) => {
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
export function isValidURL(str: string) {
|
export function isValidURL(text: string) {
|
||||||
return str && str.startsWith('http');
|
if (text.match(/\n/)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = new URL(text);
|
||||||
|
return url.hostname !== '';
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ importers:
|
||||||
markdown-it-sup: ^1.0.0
|
markdown-it-sup: ^1.0.0
|
||||||
next: 12.1.0
|
next: 12.1.0
|
||||||
next-pwa: ^5.5.2
|
next-pwa: ^5.5.2
|
||||||
|
prosemirror-commands: ^1.3.0
|
||||||
prosemirror-markdown: ^1.7.0
|
prosemirror-markdown: ^1.7.0
|
||||||
prosemirror-model: ^1.16.1
|
prosemirror-model: ^1.16.1
|
||||||
prosemirror-schema-list: ^1.1.6
|
prosemirror-schema-list: ^1.1.6
|
||||||
|
@ -209,6 +210,7 @@ importers:
|
||||||
markdown-it-sup: 1.0.0
|
markdown-it-sup: 1.0.0
|
||||||
next: 12.1.0_react-dom@17.0.2+react@17.0.2
|
next: 12.1.0_react-dom@17.0.2+react@17.0.2
|
||||||
next-pwa: 5.5.2_next@12.1.0
|
next-pwa: 5.5.2_next@12.1.0
|
||||||
|
prosemirror-commands: 1.3.0
|
||||||
prosemirror-markdown: 1.7.0
|
prosemirror-markdown: 1.7.0
|
||||||
prosemirror-model: 1.16.1
|
prosemirror-model: 1.16.1
|
||||||
prosemirror-schema-list: 1.1.6
|
prosemirror-schema-list: 1.1.6
|
||||||
|
@ -2688,7 +2690,7 @@ packages:
|
||||||
'@types/prosemirror-state': 1.2.8
|
'@types/prosemirror-state': 1.2.8
|
||||||
'@types/prosemirror-transform': 1.1.5
|
'@types/prosemirror-transform': 1.1.5
|
||||||
'@types/prosemirror-view': 1.23.1
|
'@types/prosemirror-view': 1.23.1
|
||||||
prosemirror-commands: 1.2.1
|
prosemirror-commands: 1.3.0
|
||||||
prosemirror-keymap: 1.1.5
|
prosemirror-keymap: 1.1.5
|
||||||
prosemirror-model: 1.16.1
|
prosemirror-model: 1.16.1
|
||||||
prosemirror-schema-list: 1.1.6
|
prosemirror-schema-list: 1.1.6
|
||||||
|
@ -9143,8 +9145,8 @@ packages:
|
||||||
object-assign: 4.1.1
|
object-assign: 4.1.1
|
||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
|
|
||||||
/prosemirror-commands/1.2.1:
|
/prosemirror-commands/1.3.0:
|
||||||
resolution: {integrity: sha512-S/IkpXfpuLFsRynC2HQ5iYROUPiZskKS1+ClcWycGJvj4HMb/mVfeEkQrixYxgTl96EAh+RZQNWPC06GZXk5tQ==}
|
resolution: {integrity: sha512-BwBbZ5OAScPcm0x7H8SPbqjuEJnCU2RJT9LDyOiiIl/3NbL1nJZI4SFNHwU2e/tRr2Xe7JsptpzseqvZvToLBQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
prosemirror-model: 1.16.1
|
prosemirror-model: 1.16.1
|
||||||
prosemirror-state: 1.3.4
|
prosemirror-state: 1.3.4
|
||||||
|
|
Loading…
Reference in New Issue