import { insertTagToEditor } from "./utils"; // import { randomCode } from "../../utils/utils"; let _this = null; export function dataUrlToBlob(base64Buf) { console.log(base64Buf); const bufs = base64Buf.split("."); const mime = bufs[0].match(/:(.*?);/)[1]; const bstr = window.atob(bufs[1]); const len = bstr.length; const u8arr = new Uint8Array(len); for (let i = 0; i < len; i++) { u8arr[i] = bstr.charCodeAt(i); } return new Blob([u8arr], { type: mime }); } function fileToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result); reader.onerror = (error) => reject(error); }); } function getDataUrlFromImageUrl(url) { const img = new Image(); img.setAttribute("crossorigin", "anonymous"); img.src = url; return new Promise((resolve, reject) => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = img.width; canvas.height = img.height; // console.dir(img); img.onload = function () { ctx.drawImage(img, 0, 0); resolve(canvas.toDataURL("image/png")); }; img.onerror = function (err) { reject(err); }; }); } function dataItemGetAsString(dataTransferItem) { return new Promise((resolve, reject) => { try { dataTransferItem.getAsString((s) => { resolve(s); }); } catch (error) { reject(error); } }); } // function checkHtmlIsFromOffice(htmlDom) { // const meta = htmlDom.querySelector("meta[name='Originator']"); // return meta && meta.getAttribute("content").includes("Microsoft Word"); // } function checkDomIsBlock(dom) { if (dom.nodeType === Node.ELEMENT_NODE) { const disPlay = window.getComputedStyle(dom).display; if (disPlay) { return disPlay === "block"; } else { const blockDomNames = [ "div", "p", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "table", "tr", ]; return blockDomNames.includes(dom.tagName.toLowerCase()); } } } function checkDomHasTextContent(content) { let cont = content.replace(/\n/g, ""); return !!cont; } function checkDomIsUnvalid(dom) { const unvalidFunc = [ (node) => node.tagName && ["meta", "link", "script", "style", "title"].includes( node.tagName.toLowerCase() ), (node) => node.nodeType === Node.COMMENT_NODE, ]; return unvalidFunc.some((unfunc) => unfunc(dom)); } function getHtmlValidDom(htmlDom, checkBlock) { let doms = []; let curBlockDoms = []; const findDom = (nodeList) => { nodeList.forEach((node) => { if (checkDomIsUnvalid(node)) return; if (checkBlock && checkDomIsBlock(node) && curBlockDoms.length) { doms.push(curBlockDoms); curBlockDoms = []; } if (node.childNodes.length) { findDom(node.childNodes); return; } if ( (node.tagName && node.tagName.toLowerCase() === "img") || (node.nodeType === Node.TEXT_NODE && checkDomHasTextContent(node.textContent)) ) { curBlockDoms.push(node); } }); }; findDom(htmlDom.childNodes); if (curBlockDoms.length) { doms.push(curBlockDoms); curBlockDoms = []; } console.log(doms); return doms; } // function getOfficeHtmlValidDom(htmlDom) { // let doms = []; // htmlDom.querySelectorAll("p").forEach((pDom) => { // const elems = getHtmlValidDom(pDom, false); // if (elems.length) doms.push(...elems); // }); // return doms; // } async function pasteHtmlItem(htmlItem) { const cont = await dataItemGetAsString(htmlItem).catch((e) => { console.log(e); }); if (!cont) return; const divDom = document.createElement("div"); divDom.innerHTML = cont; console.log(divDom); const groups = getHtmlValidDom(divDom, true); for (let i = 0; i < groups.length; i++) { for (let j = 0; j < groups[i].length; j++) { const element = groups[i][j]; if (element.tagName && element.tagName.toLowerCase() === "img") { await pasteImageDom(element); } else { document.execCommand("insertText", false, element.textContent); } } document.execCommand("insertParagraph"); } } async function pasteImageDom(imgDom) { console.log(imgDom); const src = imgDom.getAttribute("src"); if (!src) return; let attributes = {}; if (imgDom.getAttribute("width")) attributes.width = imgDom.getAttribute("width"); if (imgDom.getAttribute("height")) attributes.height = imgDom.getAttribute("height"); if (src.includes("base64")) { insertTagToEditor(null, "IMG", src, attributes); } else if ( src.includes("http://") || src.includes("https://") || src.includes("file:///") ) { const dataUrl = await getDataUrlFromImageUrl(src).catch(() => {}); // console.log(dataUrl); if (!dataUrl) return; insertTagToEditor(null, "IMG", dataUrl, attributes); } else { console.log("unknown image url"); } } async function pasteImage(file, attributes) { if (file.size > _this.maxImageSize) { _this.$message(`单张图片超过限制,最大为 ${_this.maxImageSize / 1024} KB.`); return; } // 默认转base64; const srcBase64 = await fileToBase64(file); insertTagToEditor(null, "IMG", srcBase64, attributes); } async function pasteText(textItem) { const cont = await dataItemGetAsString(textItem).catch((e) => { console.log(e); }); if (!cont) return; document.execCommand("insertText", false, cont); } function filterItem(dataItems, filterFunc) { let data = []; for (let index = 0; index < dataItems.length; index++) { if (filterFunc(dataItems[index])) data.push(dataItems[index]); } return data; } export async function pasteHandle(event) { _this = this; // 禁止默认粘贴 event.preventDefault(); const clipboard = event.clipboardData; const htmlItems = filterItem( clipboard.items, (item) => item.kind == "string" && item.type.match("^text/html") ); if (htmlItems.length) { console.log("... paste: html "); for (let index = 0; index < htmlItems.length; index++) { await pasteHtmlItem(htmlItems[index]); } _this.$refs.editor.dispatchEvent(new Event("input")); return; } const fileItems = filterItem( clipboard.items, (item) => item.kind == "file" && item.type.match("^image/") ); if (fileItems.length) { console.log("... paste: file "); for (let index = 0; index < fileItems.length; index++) { const file = fileItems[index].getAsFile(); await pasteImage(file); } _this.$refs.editor.dispatchEvent(new Event("input")); return; } for (var i = 0; i < clipboard.items.length; i++) { const clipboardItem = clipboard.items[i]; if ( clipboardItem.kind == "string" && clipboardItem.type.match("^text/plain") ) { console.log("... paste: text "); await pasteText(clipboardItem); } else { console.log("... paste: other "); } } }