@liveblocks/react-ui
Version:
A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
167 lines (163 loc) • 5.06 kB
JavaScript
var slate = require('slate');
var slateHyperscript = require('slate-hyperscript');
var dataTransfer = require('../../utils/data-transfer.cjs');
const NEWLINE_REGEX = /[\r\n]/g;
const WHITESPACE_REGEX = /\s+/g;
function areUrlsEqual(a, b) {
try {
const urlA = new URL(a);
const urlB = new URL(b);
return urlA.origin === urlB.origin && urlA.pathname === urlB.pathname;
} catch {
return false;
}
}
const createParagraphElement = () => ({
type: "paragraph"
});
const ELEMENT_TAGS = {
A: (element) => {
const href = element.getAttribute("href");
const innerText = element.innerText;
return {
type: href && areUrlsEqual(href, innerText) ? "auto-link" : "custom-link",
url: href ?? ""
};
},
P: createParagraphElement,
BLOCKQUOTE: createParagraphElement,
H1: createParagraphElement,
H2: createParagraphElement,
H3: createParagraphElement,
H4: createParagraphElement,
H5: createParagraphElement,
H6: createParagraphElement,
LI: createParagraphElement
};
const TEXT_TAGS = {
CODE: () => ({ code: true }),
DEL: () => ({ strikethrough: true }),
EM: () => ({ italic: true }),
I: () => ({ italic: true }),
S: () => ({ strikethrough: true }),
STRONG: () => ({ bold: true }),
B: () => ({ bold: true })
};
function flattenListItems(node) {
const listItems = [];
if (node.nodeName === "LI") {
listItems.push(node);
}
node.childNodes.forEach((child) => {
if (child.nodeType === 1) {
listItems.push(...flattenListItems(child));
}
});
return listItems;
}
function jsxTextChildren(children, attrs) {
return children.map((child) => slateHyperscript.jsx("text", attrs, child));
}
function deserialize(node) {
if (node.nodeType === 3) {
let text = node.textContent;
const isMultiLine = text && NEWLINE_REGEX.test(text);
if (text && isMultiLine) {
text = text.replace(WHITESPACE_REGEX, " ").trim();
}
return text ? { text } : null;
} else if (node.nodeType !== 1) {
return null;
} else if (node.nodeName === "BR") {
return slateHyperscript.jsx("element", createParagraphElement(), []);
}
const childNodes = Array.from(node.childNodes);
let children = childNodes.map(deserialize).flat();
if (node.nodeName === "UL" || node.nodeName === "OL") {
const listItems = flattenListItems(node);
children = listItems.map((li) => deserialize(li)).flat();
}
if (children.length === 0) {
children = [{ text: "" }];
}
if (node.nodeName === "BODY") {
if (children.length > 0 && children.every((child) => typeof child === "string")) {
children = [
{ type: "paragraph", children: [{ text: children.join("") }] }
];
}
return slateHyperscript.jsx(
"fragment",
{},
children.filter((child) => typeof child !== "string")
);
}
if (ELEMENT_TAGS[node.nodeName]) {
const attrs = ELEMENT_TAGS[node.nodeName](node);
return slateHyperscript.jsx("element", attrs, children);
}
if (TEXT_TAGS[node.nodeName]) {
const attrs = TEXT_TAGS[node.nodeName](node);
if (children.some(
(child) => child && typeof child !== "string" && "type" in child
)) {
return slateHyperscript.jsx("fragment", {}, children);
}
return jsxTextChildren(children, attrs);
}
if (node.nodeName === "SPAN") {
const style = node.style;
const attrs = {};
if (style.fontWeight === "bold" || style.fontWeight === "700" || style.fontWeight === "800" || style.fontWeight === "900") {
attrs.bold = true;
}
if (style.fontStyle === "italic") {
attrs.italic = true;
}
if (style.textDecoration === "line-through") {
attrs.strikethrough = true;
}
return jsxTextChildren(children, attrs);
}
return children;
}
function withPaste(editor, {
createAttachments,
pasteFilesAsAttachments
}) {
const { insertData } = editor;
editor.insertData = (data) => {
if (data.types.includes("Files") && pasteFilesAsAttachments) {
const files = dataTransfer.getFiles(data);
if (files.length > 0) {
createAttachments(files);
return;
}
}
if (data.types.includes("text/html") && !data.types.includes("application/x-slate-fragment")) {
const html = data.getData("text/html");
try {
const { body } = new DOMParser().parseFromString(html, "text/html");
body.querySelector("br.Apple-interchange-newline")?.remove();
if (body.children.length === 1 && body.children[0]?.nodeName === "B") {
const wrapper = body.children[0];
while (wrapper.firstChild) {
body.insertBefore(wrapper.firstChild, wrapper);
}
body.removeChild(wrapper);
}
const fragment = deserialize(body);
if (fragment !== null && Array.isArray(fragment)) {
slate.Transforms.insertFragment(editor, fragment);
return;
}
} catch {
}
}
insertData(data);
};
return editor;
}
exports.withPaste = withPaste;
//# sourceMappingURL=paste.cjs.map
;