feat: Handle pasting iframe for supported embed
This commit is contained in:
@@ -9,9 +9,13 @@ import isInCode from "../queries/isInCode";
|
||||
import isInList from "../queries/isInList";
|
||||
import { LANGUAGES } from "./Prism";
|
||||
|
||||
/**
|
||||
* Checks if the HTML string is likely coming from Dropbox Paper.
|
||||
*
|
||||
* @param html The HTML string to check.
|
||||
* @returns True if the HTML string is likely coming from Dropbox Paper.
|
||||
*/
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -23,6 +27,34 @@ function sliceSingleNode(slice: Slice) {
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the text contents of an HTML string and returns the src of the first
|
||||
* iframe if it exists.
|
||||
*
|
||||
* @param text The HTML string to parse.
|
||||
* @returns The src of the first iframe if it exists, or undefined.
|
||||
*/
|
||||
function parseSingleIframeSrc(html: string) {
|
||||
try {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, "text/html");
|
||||
|
||||
if (
|
||||
doc.body.children.length === 1 &&
|
||||
doc.body.firstElementChild?.tagName === "IFRAME"
|
||||
) {
|
||||
const iframe = doc.body.firstElementChild;
|
||||
const src = iframe.getAttribute("src");
|
||||
if (src) {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore the million ways parsing could fail.
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export default class PasteHandler extends Extension {
|
||||
get name() {
|
||||
return "paste-handler";
|
||||
@@ -65,10 +97,16 @@ export default class PasteHandler extends Extension {
|
||||
return false;
|
||||
}
|
||||
|
||||
const text = event.clipboardData.getData("text/plain");
|
||||
const { state, dispatch } = view;
|
||||
const iframeSrc = parseSingleIframeSrc(
|
||||
event.clipboardData.getData("text/plain")
|
||||
);
|
||||
const text =
|
||||
iframeSrc && !isInCode(state)
|
||||
? iframeSrc
|
||||
: event.clipboardData.getData("text/plain");
|
||||
const html = event.clipboardData.getData("text/html");
|
||||
const vscode = event.clipboardData.getData("vscode-editor-data");
|
||||
const { state, dispatch } = view;
|
||||
|
||||
// first check if the clipboard contents can be parsed as a single
|
||||
// url, this is mainly for allowing pasted urls to become embeds
|
||||
|
||||
@@ -27,7 +27,7 @@ export default class Embed extends Node {
|
||||
},
|
||||
parseDOM: [
|
||||
{
|
||||
tag: "iframe.embed",
|
||||
tag: "iframe",
|
||||
getAttrs: (dom: HTMLIFrameElement) => {
|
||||
const { embeds } = this.editor.props;
|
||||
const href = dom.getAttribute("src") || "";
|
||||
@@ -43,7 +43,7 @@ export default class Embed extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
return false;
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user