百度编辑器(ueditor)魔改:5、自定义一键排版(按照需求保留标签和样式)

1、增加自定义按钮

2、彻底接管文件上传

3、高亮提示

4、滚动条管理

5、自定义排版

-----------------------------------------------------------

作为一个平台,用户在发布文章也好,产品也好,都需要清除掉他们粘贴过来时的样式,以适应自己平台的需求,总不能让用户任意编辑,然后同一个网站,同一个页面类型呈现的格式五花八门,风格各异吧,所以,让我们强制清除我们不支持的格式吧!

百度编辑器内部其实自带了一个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标签排版。。。。老顾懒得自己弄了,反正百度编辑器里有了,嘿嘿

以上实现就是文盲所在单位网站平台的需求了,至于各自需要怎样的排版方式,可以自己进行修改

你可能感兴趣的:(javascript)