fix: Improved pasting behavior from Dropbox Paper

This commit is contained in:
Tom Moor
2022-01-25 22:01:51 -08:00
parent bc40a0074a
commit 13b8ed58fd
4 changed files with 26 additions and 5 deletions

View File

@@ -40,8 +40,8 @@ export default class Code extends Mark {
get schema(): MarkSpec {
return {
excludes: "_",
parseDOM: [{ tag: "code", preserveWhitespace: true }],
toDOM: () => ["code", { spellCheck: "false" }],
parseDOM: [{ tag: "code.inline", preserveWhitespace: true }],
toDOM: () => ["code", { class: "inline", spellCheck: "false" }],
};
}

View File

@@ -16,7 +16,11 @@ export default class Blockquote extends Node {
content: "block+",
group: "block",
defining: true,
parseDOM: [{ tag: "blockquote" }],
parseDOM: [
{ tag: "blockquote" },
// Dropbox Paper parsing, yes their quotes are actually lists
{ tag: "ul.listtype-quote", contentElement: "li" },
],
toDOM: () => ["blockquote", 0],
};
}

View File

@@ -89,6 +89,7 @@ export default class CodeFence extends Node {
defining: true,
draggable: false,
parseDOM: [
{ tag: "code" },
{ tag: "pre", preserveWhitespace: "full" },
{
tag: ".code-block",

View File

@@ -7,6 +7,12 @@ import isUrl from "../lib/isUrl";
import selectionIsInCode from "../queries/isInCode";
import { LANGUAGES } from "./Prism";
function isDropboxPaper(html: string): boolean {
// The best we have to detect if a paste is likely coming from Paper
// In this case it's actually better to use the text version
return html?.includes("usually-unique-id");
}
/**
* Add support for additional syntax that users paste even though it isn't
* supported by the markdown parser directly by massaging the text content.
@@ -14,13 +20,16 @@ import { LANGUAGES } from "./Prism";
* @param text The incoming pasted plain text
*/
function normalizePastedMarkdown(text: string): string {
// find checkboxes not contained in a list and wrap them in list items
const CHECKBOX_REGEX = /^\s?(\[(X|\s|_|-)\]\s(.*)?)/gim;
// find checkboxes not contained in a list and wrap them in list items
while (text.match(CHECKBOX_REGEX)) {
text = text.replace(CHECKBOX_REGEX, (match) => `- ${match.trim()}`);
}
// find multiple newlines and insert a hard break to ensure they are respected
text = text.replace(/\n{2,}/g, "\n\n\\\n");
return text;
}
@@ -33,6 +42,13 @@ export default class PasteHandler extends Extension {
return [
new Plugin({
props: {
transformPastedHTML(html: string) {
if (isDropboxPaper(html)) {
// Fixes double paragraphs when pasting from Dropbox Paper
html = html.replace(/<div><br><\/div>/gi, "<p></p>");
}
return html;
},
handlePaste: (view, event: ClipboardEvent) => {
if (view.props.editable && !view.props.editable(view.state)) {
return false;
@@ -125,7 +141,7 @@ export default class PasteHandler extends Extension {
// If the text on the clipboard looks like Markdown OR there is no
// html on the clipboard then try to parse content as Markdown
if (
isMarkdown(text) ||
(isMarkdown(text) && !isDropboxPaper(html)) ||
html.length === 0 ||
pasteCodeLanguage === "markdown"
) {