本文共 9629 字,大约阅读时间需要 32 分钟。
-----------------------------------------------------------
作为一个平台,用户在发布文章也好,产品也好,都需要清除掉他们粘贴过来时的样式,以适应自己平台的需求,总不能让用户任意编辑,然后同一个网站,同一个页面类型呈现的格式五花八门,风格各异吧,所以,让我们强制清除我们不支持的格式吧!
百度编辑器内部其实自带了一个htmlParse,但在使用过程中,有些内容我们需要保留的,他也给弄掉了,但要是完全修正自带的代码,感觉好麻烦啊,算了,自己重新写一个,并接管过来吧
第一步:粘贴触发排版
先打开src\adapter\editor.js,找到editor.addListener("afterpaste", function() {这一行,在这行下边追加我们之前添加的按钮事件
editor.addListener("afterpaste", function () { editor.execCommand('formatcontent'); // 触发我们自己定义的格式化
第二步:接管粘贴事件
打开\src\plugins\paste.js,这里百度编辑器自己定义了格式化方法的调用。。。。看起来有点眼晕,算了,不管他了
找到filter(div)的定义,在html = div.innerHTML;之后的代码全部注释掉,换成我们自己的代码
//ie下使用innerHTML会产生多余的\r\n字符,也会产生 这里过滤掉 html = div.innerHTML;//.replace(/>(?:(\s| )*?)<'); //接管粘贴事件 if (me.queryCommandState('pasteplain') === 1) { me.execCommand('insertHtml', div.innerTEXT, true); } else { address = me.selection.getRange().createAddress(true); me.execCommand('insertHtml', html, true); } me.fireEvent("afterpaste", html); //之后代码全部注释掉
Hmmmmm,没有专门研究百度编辑器怎么实现的代码解析,所以这里我丢失了一个beforepaste事件得触发,反正我用不到 ^v^
我在这里直接触发afterpaste事件,用来调用自己定义的格式化方法
第三步:实现粘贴内容格式化
UE.plugins['formatcontent'] = function () { var me = this; me.commands['formatcontent'] = { execCommand: function () { var me = this; var body = me.window.document.body; var attrs = { a: ['href'], img: ['width', 'height', 'src'] } var keeps = ['text-align', 'font-weight', 'font-style', 'display', 'align-item', 'justify-content']; formatElement(body); me.execCommand('adwordfilter', 'highlight'); function formatElement(el) { var name = el.nodeName.toLowerCase(); if (name == '#comment') { console.log(el) return; } if (name == '#text') { el.nodeValue = el.nodeValue.replace(/^( | | |[\s\r\n\t]| )+/gi, ''); return; } if (name == 'img' && el.style.margin == '0px auto') { return; } if (name != 'body') { var tar = el; // 获取当前标签所有样式 var style = { length: el.style.length }; for (var i = 0; i < el.style.length; i++) { style[i] = el.style[i]; style[el.style[i]] = el.style[el.style[i]]; } // 获取当前标签所有属性 var attr = { length: el.attributes.length }; for (var i = 0; i < el.attributes.length; i++) { attr[i] = el.attributes[i].localName; attr[el.attributes[i].localName] = el.attributes[i].value; } // 如果是特定标签,更换成P标签 if ($.inArray(name, ['div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7']) > -1) { tar = me.window.document.createElement('p'); tar.innerHTML = el.innerHTML; el.parentNode.insertBefore(tar, el); el.parentNode.removeChild(el) el = tar; name = el.nodeName.toLowerCase(); } // 清空当前标签所有属性 while (el.attributes.length > 0) { el.removeAttribute(el.attributes[0].localName); } // 如果属性不为空,则将符合条件的属性附加回来 for (var i = 0; i < attr.length; i++) { switch (attr[i].toLowerCase()) { case 'align': el.style.textAlign = attr[attr[i]]; break; default: if (attrs[name]) { if ($.inArray(attr[i].toLowerCase(), attrs[name]) > -1) { if (attr[i] == 'href') { var href = (function (url) { if (!/^https?:\/\//gi.test(url)) { return url; } if (/^https?:\/\/([a-z0-9]+\.)?xxxx\.com\.cn(?=$|[\\\/])/gi.test(url)) { return url; } })(attr[attr[i]]); if (href) { el.setAttribute('href', href.trim()); } } else { el.setAttribute(attr[i], attr[attr[i]]); } } } break; } } // 将符合条件的样式附加回来 for (var i = 0; i < style.length; i++) { if ($.inArray(style[i], keeps) < 0) { console.log(style[i], style[style[i]]); } else { el.style[style[i]] = style[style[i]]; } } // 图片前追加p节点后居中 if (name == 'img') { var tar = me.window.document.createElement('p'); tar.style.textAlign = 'center'; el.parentNode.insertBefore(tar, el); el.style.margin = '0px auto'; tar.appendChild(el); el = tar; } // br换成p if (name == 'br') { if (el.nextSibling && el.nextSibling.nodeName.toLowerCase() == '#text') { var tar = me.window.document.createElement('p'); for (var i = 0; i < el.parentNode.style.length; i++) { tar.style[el.parentNode.style[i]] = el.parentNode.style[el.parentNode.style[i]]; } tar.innerHTML = el.nextSibling.nodeValue; el.parentNode.insertBefore(tar, el); el.parentNode.insertBefore(el, tar); el.parentNode.removeChild(el.nextSibling.nextSibling) el = tar; } } // 单列表格替换为p,否则宽95% if (name == 'table') { var single = true; for (var i = 0; i < el.rows.length; i++) { if (el.rows[i].cells.length > 1) { single = false; break; } if (el.rows[i].cells[0].rowSpan > 1 && i < el.rows.length - 1) { single = false; break; } } if (single) { var div = me.window.document.createElement('div'); for (var i = 0; i < el.rows.length; i++) { var p = me.window.document.createElement('p'); div.appendChild(p); p.innerHTML = el.rows[i].cells[0].innerHTML; } el.parentNode.insertBefore(div, el); el.parentNode.removeChild(el) el = div; } else { el.style.width = '95%'; } } } for (var i = 0 ; i < el.childNodes.length; i++) { formatElement(el.childNodes[i]); } if (name == 'body') { me.setContent(el.innerHTML); // 去空行空标签 var els = me.window.document.querySelector('body').querySelectorAll('*'); for (var i = 0; i < els.length; i++) { if (!els[i].innerText.trim()) { if (els[i].querySelectorAll('img').length == 0 && els[i].nodeName.toLowerCase() != 'img') { els[i].parentNode.removeChild(els[i]); } } } els = me.window.document.querySelector('body').children; // 非居中段落加缩进 for (var i = 0; i < els.length; i++) { if (els[i].nodeName.toLowerCase() == 'p' && els[i].style.textAlign != 'center' && els[i].style.justifyContent != 'center') { els[i].innerHTML = ' ' + els[i].innerHTML; } } } } } }}
老顾的做法是,定义一些样式和属性,是否允许保留,如果允许保留,则格式化后重新赋予,否则则删除掉
主要就是样式保留粗体、斜体、居中等,而百度编辑器自身不支持flex布局的内容粘贴过来,所以在样式里保留display和justify-content,就可以保留flex布局了
当然,float布局一般来说应该是删除掉了,为了保证网站正文风格一致,很少有平台允许float布局和positioin定义
最后,老顾调用了setContent,用这个方法触发了百度编辑器本身的htmlParse,用来自动进行p标签排版。。。。老顾懒得自己弄了,反正百度编辑器里有了,嘿嘿
以上实现就是文盲所在单位网站平台的需求了,至于各自需要怎样的排版方式,可以自己进行修改
转载地址:http://cxvxi.baihongyu.com/