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 { get schema(): MarkSpec {
return { return {
excludes: "_", excludes: "_",
parseDOM: [{ tag: "code", preserveWhitespace: true }], parseDOM: [{ tag: "code.inline", preserveWhitespace: true }],
toDOM: () => ["code", { spellCheck: "false" }], toDOM: () => ["code", { class: "inline", spellCheck: "false" }],
}; };
} }

View File

@@ -16,7 +16,11 @@ export default class Blockquote extends Node {
content: "block+", content: "block+",
group: "block", group: "block",
defining: true, 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], toDOM: () => ["blockquote", 0],
}; };
} }

View File

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

View File

@@ -7,6 +7,12 @@ import isUrl from "../lib/isUrl";
import selectionIsInCode from "../queries/isInCode"; import selectionIsInCode from "../queries/isInCode";
import { LANGUAGES } from "./Prism"; 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 * Add support for additional syntax that users paste even though it isn't
* supported by the markdown parser directly by massaging the text content. * 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 * @param text The incoming pasted plain text
*/ */
function normalizePastedMarkdown(text: string): string { 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; 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)) { while (text.match(CHECKBOX_REGEX)) {
text = text.replace(CHECKBOX_REGEX, (match) => `- ${match.trim()}`); 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; return text;
} }
@@ -33,6 +42,13 @@ export default class PasteHandler extends Extension {
return [ return [
new Plugin({ new Plugin({
props: { 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) => { handlePaste: (view, event: ClipboardEvent) => {
if (view.props.editable && !view.props.editable(view.state)) { if (view.props.editable && !view.props.editable(view.state)) {
return false; 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 // If the text on the clipboard looks like Markdown OR there is no
// html on the clipboard then try to parse content as Markdown // html on the clipboard then try to parse content as Markdown
if ( if (
isMarkdown(text) || (isMarkdown(text) && !isDropboxPaper(html)) ||
html.length === 0 || html.length === 0 ||
pasteCodeLanguage === "markdown" pasteCodeLanguage === "markdown"
) { ) {