123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- 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 ");
- }
- }
- }
|