]+>/gi, ""));
            body.html(body.html().replace(/<\/span>/gi, ""));
            body.html(body.html().replace(//g, ""));
            body.html(body.html().replace(/<\/P>/g, ""));
            body.html(body.html().replace(/
<\/p>/g, ""));//移除空p
            //clean word end
            //清除影响版面的css属性
            //body.find('*[style]').each(function () {
            //    var textAlign = this.style.textAlign;
            //    this.removeAttribute('style');
            //    $(this).css({
            //        'text-align': textAlign || ''
            //    })
            //});
            // 移除不安全的标签
            //    body.find('script,link').remove();
            ////修饰表格
            //body.find('table').addClass('layui-table');
        }
        //Range对象兼容性处理
        , Range = function (iframeDOM) {
            const selection = iframeDOM.getSelection()
            return iframeDOM.selection
                ? iframeDOM.selection.createRange()
                : selection.rangeCount && selection.getRangeAt(0);
        }
        //当前Range对象的endContainer兼容性处理
        , getContainer = function (range) {
            if (!range) return
            return range.endContainer || range.parentElement().childNodes[0]
        }
        //在选区插入内联元素
        , insertInline = function (tagName, attr, range) {
            var iframeDOM = this.document
                , elem = document.createElement(tagName);
            for (var key in attr) {
                elem.setAttribute(key, attr[key]);
            }
            elem.removeAttribute('text');
            // be fix by knifeZ
            if (device.ie) { //IE
                var text = range.text || attr.text;
                if (tagName === 'a' && !text) return;
                if (text) {
                    elem.innerHTML = text;
                }
                layer.msg("暂不支持IE浏览器");
                range.selectNode(this.document.body.childNodes.item(0));
                range.insertNode(elem);
            } else { //非IE
                var text = range.toString() || attr.text;
                if (tagName === 'a' && !text) return;
                if (text) {
                    elem.innerHTML = text;
                }
                var container = getContainer(range)
                    , parentNode = container.parentNode;
                //var elep = document.createElement('p');
                //if (tagName != "pre" && tagName != "span" && tagName != "p" && tagName != "a" && tagName != "hr" && tagName != "div" && parentNode.tagName != "P" && container.innerHTML != "
');
                    iframeDOM.execCommand('justifyCenter');
                    setTimeout(function () {
                        body.focus();
                    }, 10);
                }
            }
        }
        // 批量在选区插入内联元素 - 此处服务于图片
        ,insertInlineAll = function (data, range) {
            var iframeDOM = this.document;
            var elems = [];
            for(var i = 0; i < data.length;i++){
                elems[i] = document.createElement(data[i].tagName);
                for (var key in data[i].attr) {
                    elems[i].setAttribute(key, data[i].attr[key]);
                }
                elems[i].removeAttribute('text');
            }
            if (iframeDOM.selection) { //IE
                var text = range.text || attr.text;
                if (tagName === 'a' && !text) return;
                if (text) {
                    elem.innerHTML = text;
                }
                range.pasteHTML($(elems).prop('outerHTML'));
                range.select();
            } else { //非IE
                /*
                var text = range.toString() || attr.text;
                if (tagName === 'a' && !text) return;
                if (text) {
                    elem.innerHTML = text;
                }
                */
                range.deleteContents();
                for(var j = 0; j < elems.length;j++){
                    var text = range.toString() || data[j].attr.text;
                    // if (data[j].tagName === 'a' && !text) return;
                    if (text) {
                        elem.innerHTML = text;
                    }
                    range.insertNode(elems[j]);
                }
            }
        }
        //工具选中
        , toolCheck = function (tools, othis) {
            var iframeDOM = this.document
                , CHECK = 'layedit-tool-active'
                , container = getContainer(Range(iframeDOM))
                , item = function (type) {
                    return tools.find('.layedit-tool-' + type)
                }
            if (othis) {
                othis[othis.hasClass(CHECK) ? 'removeClass' : 'addClass'](CHECK);
            }
            tools.find('>i').removeClass(CHECK);
            item('unlink').addClass(ABLED);
            $(container).parents().each(function () {
                var tagName = this.tagName.toLowerCase()
                    , textAlign = this.style.textAlign;
                //be fix by kinfeZ
                //文字
                //if (tagName === 'b' || tagName === 'strong') {
                //    item('b').addClass(CHECK)
                //}
                //if (tagName === 'i' || tagName === 'em') {
                //    item('i').addClass(CHECK)
                //}
                //if (tagName === 'u') {
                //    item('u').addClass(CHECK)
                //}
                //if (tagName === 'strike') {
                //    item('d').addClass(CHECK)
                //}
                //对齐
                if (tagName === 'p') {
                    if (textAlign === 'center') {
                        item('center').addClass(CHECK);
                    } else if (textAlign === 'right') {
                        item('right').addClass(CHECK);
                    } else {
                        item('left').addClass(CHECK);
                    }
                }
                //超链接
                if (tagName === 'a') {
                    item('link').addClass(CHECK);
                    item('unlink').removeClass(ABLED);
                }
            });
        }
        //触发工具
        , toolActive = function (iframeWin, editor, set) {
            var iframeDOM = iframeWin.document
                , body = $(iframeDOM.body)
                , toolEvent = {
                    //超链接
                    link: function (range) {
                        var container = getContainer(range)
                            , parentNode = $(container).parent();
                        link.call(body, {
                            href: parentNode.attr('href')
                            , target: parentNode.attr('target')
                            , rel: parentNode.attr('rel')
                            , text: parentNode.attr('text') || range.toString()
                            , dmode: set.devmode
                        }, function (field) {
                            var parent = parentNode[0];
                            if (parent.tagName === 'A') {
                                parent.href = field.url;
                                parent.rel = field.rel;
                                if (field.rel == "") {
                                    parent.removeAttr("rel");
                                }
                                parent.target = field.target;
                                if (field.target == "_self" || field.target == undefined) {
                                    parent.removeAttr("target");
                                }
                                if (field.text != "") {
                                    parent.text = field.text;
                                }
                            } else {
                                var data = {
                                    target: field.target
                                    , href: field.url
                                    , rel: field.rel
                                    , text: field.text
                                };
                                if (field.rel == "" || field.rel == undefined) {
                                    delete data["rel"];
                                }
                                if (field.target == "_self" || field.target == undefined) {
                                    delete data["target"];
                                }
                                if (field.text == "") {
                                    data["text"] = data["href"]
                                }
                                insertInline.call(iframeWin, 'a', data, range);
                            }
                        });
                    }
                    //清除超链接
                    , unlink: function (range) {
                        iframeDOM.execCommand('unlink');
                    }
                    //表情
                    , face: function (range) {
                        face.call(this, { facePath: set.facePath }, function (img) {
                            insertInline.call(iframeWin, 'img', {
                                src: img.src
                                , alt: img.alt
                            }, range);
                            setTimeout(function () {
                                body.focus();
                            }, 10);
                        });
                    }
                    //图片
                    , image: function (range) {
                        var that = this;
                        layui.use('upload', function (upload) {
                            var uploadImage = set.uploadImage || {};
                            if (uploadImage.url == "") {
                                layer.msg("上传接口配置错误!");
                            }
                            upload.render({
                                url: uploadImage.url
                                , method: uploadImage.method
                                , field: uploadImage.field
                                , data: uploadImage.data
                                , headers: uploadImage.headers
                                , accept: uploadImage.accept || 'image'
                                , acceptMime: uploadImage.acceptMime || 'image/*'
                                , exts: uploadImage.exts || 'jpg|png|gif|bmp|jpeg'
                                , size: uploadImage.size || 1024 * 10
                                , elem: $(that).find('input')[0]
                                , done: function (res) {
                                    if (res.code == 0) {
                                        res.data = res.data || {};
                                        insertInline.call(iframeWin, 'img', {
                                            src: res.data.src
                                            , alt: res.data.title
                                        }, range);
                                        uploadImage.done(res);
                                        setTimeout(function () {
                                            body.focus();
                                        }, 10);
                                    } else {
                                        layer.msg(res.msg || '上传失败');
                                    }
                                }
                            });
                        });
                    }
                    //插入代码
                    , code: function (range) {
                        var codeConfig = set.codeConfig || { hide: false, encode: true, class: "layui-code" };
                        code.call(body, { hide: codeConfig.hide, default: codeConfig.default }, function (pre) {
                            if (codeConfig.encode || true) {
                                pre.code = pre.code.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&')
                                    .replace(//g, '>').replace(/'/g, ''').replace(/"/g, '"');
                            }
                            insertInline.call(iframeWin, 'pre', {
                                text: pre.code
                                , 'lay-lang': pre.lang
                                , 'lay-encode': codeConfig.encode
                                , class: codeConfig.class || 'layui-code'
                            }, range);
                            setTimeout(function () {
                                layui.code();
                                body.focus();
                            }, 10);
                        });
                    }
                    /*#Extens#*/
                    //多图上传
                    , images: function (range) {
                        var that = this;
                        layer.open({
                            type: 1
                            , id: 'fly-jie-image-upload'
                            , title: '图片管理'
                            , shade: 0.05
                            , shadeClose: true
                            , area: function () {
                                if (/mobile/i.test(navigator.userAgent) || $(window).width() <= 485) {
                                    return ['90%']
                                } else {
                                    return ['485px']
                                }
                            }()
                            , offset: function () {
                                if (/mobile/i.test(navigator.userAgent)) {
                                    return 'auto'
                                } else {
                                    return '100px'
                                }
                            }()
                            , skin: 'layui-layer-border'
                            , content: ['
'].join('')
                            , btn: ['确定', '取消']
                            , btnAlign: 'c'
                            , yes: function (index, layero) {
                                var styleStr = "";
                                if (layero.find('input[name="imgWidth"]').val() != "") {
                                    var w = layero.find('input[name="imgWidth"]').val();
                                    styleStr += w.indexOf('%') > 0 ? "width:" + w + ";" : "width:" + w + "px;";
                                }
                                if (layero.find('input[name="imgHeight"]').val() != "") {
                                    var h = layero.find('input[name="imgHeight"]').val();
                                    styleStr += h.indexOf('%') > 0 ? "height:" + h + ";" : "height:" + h + "px;";
                                }
                                if (layero.find('#imgsPrev').find('img').length === 0) {
                                    layer.msg('请选择要插入的图片');
                                } else {
                                    /*
                                    if (styleStr != "") styleStr = "style='" + styleStr + "'";
                                    insertInline.call(iframeWin, 'p', {
                                        text: layero.find('#imgsPrev').html().replace(new RegExp(/(style="max-width:70px;margin:2px")/g), styleStr)
                                    }, range);
                                    */
                                    var list = document.getElementById('imgsPrev').children;
                                    var objs = [];
                                    for(var i = 0; i < list.length;i++){
                                        objs.push({
                                            tagName: 'img',
                                            attr: {
                                                src: list[i].src,
                                                alt: list[i].alt,
                                                style: styleStr
                                            }
                                        })
                                    }
                                    insertInlineAll.call(iframeWin, objs, range);
                                    layer.close(index);
                                }
                            }
                            , btn2: function (index, layero) {
                                if (layero.find("#imgsPrev img").length > 0) {
                                    var imgPaths = "";
                                    for (var i = 0; i < layero.find("#imgsPrev img").length; i++) {
                                        imgPaths += layero.find("#imgsPrev img")[i].src;
                                    }
                                    var callDel = set.calldel;
                                    if (callDel.url != "") {
                                        $.post(callDel.url, { "imgpath": imgPaths }, function (res) {
                                            callDel.done(res);
                                        })
                                    }
                                }
                            }
                            , cancel: function (index, layero) {
                                if (layero.find("#imgsPrev img").length > 0) {
                                    var imgPaths = "";
                                    for (var i = 0; i < layero.find("#imgsPrev img").length; i++) {
                                        imgPaths += layero.find("#imgsPrev img")[i].src;
                                    }
                                    var callDel = set.calldel;
                                    if (callDel.url != "") {
                                        $.post(callDel.url, { "imgpath": imgPaths }, function (res) {
                                            callDel.done(res);
                                        })
                                    }
                                }
                            }
                            , success: function (layero, index) {
                                layui.use('upload', function () {
                                    var upload = layui.upload;
                                    var uploadImage = set.uploadImage || {};
                                    if (uploadImage.url == "") {
                                        layer.msg("上传接口配置错误!");
                                    }
                                    var loding;
                                    var errorIndex = [];//上传接口出错的文件索引
                                    //执行实例
                                    upload.render({
                                        elem: '#LayEdit_InsertImages'
                                        , url: uploadImage.url
                                        , method: uploadImage.method
                                        , data: uploadImage.data
                                        , headers: uploadImage.headers
                                        , accept: uploadImage.accept || 'image'
                                        , acceptMime: uploadImage.acceptMime || 'image/*'
                                        , exts: uploadImage.exts || 'jpg|png|gif|bmp|jpeg'
                                        , size: uploadImage.size || 1024 * 10
                                        , field: uploadImage.field
                                        , multiple: true
                                        , before: function (obj) {
                                            loding = layer.msg('文件上传中,请稍等', { icon: 16, shade: 0.3, time: 0 });
                                            obj.preview(function (index, file, result) {
                                                //由于有时预览会在allDone之后回调,此时所有单个文件的error已经执行,即已经出错的文件id以有,因此需要判断此预览文件id是否是上传出错文件的id,不是才预览
                                                if (errorIndex.indexOf(index) === -1)
                                                    $('#imgsPrev').append('您的浏览器不支持video播放  ';
                                    var custclass = '';
                                    if (customTheme.video.title.length > 0 && theme.length > 0) {
                                        //追加样式
                                        custclass = theme[0].options[theme[0].selectedIndex].value;
                                    }
                                    insertInline.call(iframeWin, 'div', {
                                        text: txt
                                        , class: custclass
                                    }, range);
                                    layer.close(index);
                                }
                            }
                            , btn2: function (index, layero) {
                                var callDel = set.calldel;
                                if (callDel.url != "") {
                                    $.post(callDel.url, {
                                        "imgpath": layero.find('input[name="cover"]').val()
                                        , "filepath": layero.find('input[name="video"]').val()
                                    }, function (res) {
                                        callDel.done(res);
                                    })
                                }
                            }
                            , cancel: function (index, layero) {
                                var callDel = set.calldel;
                                if (callDel.url != "") {
                                    $.post(callDel.url, {
                                        "imgpath": layero.find('input[name="cover"]').val()
                                        , "filepath": layero.find('input[name="video"]').val()
                                    }, function (res) {
                                        callDel.done(res);
                                    })
                                }
                            }
                            , success: function (layero, index) {
                                layui.use('upload', function (upload) {
                                    var loding
                                        , video = layero.find('input[name="video"]')
                                        , cover = layero.find('input[name="cover"]')
                                        , upload = layui.upload
                                        , uploadImage = set.uploadImage || {};
                                    if (uploadImage.url == "") {
                                        layer.msg("图片上传接口配置错误!");
                                    }
                                    var uploadfile = set.uploadVideo || {};
                                    if (uploadfile.url == "") {
                                        layer.msg("视频上传接口配置错误!");
                                    }
                                    //执行实例
                                    upload.render({
                                        elem: '#LayEdit_InsertImage'
                                        , url: uploadImage.url
                                        , method: uploadImage.method
                                        , data: uploadImage.data
                                        , headers: uploadImage.headers
                                        , accept: uploadImage.accept || 'image'
                                        , acceptMime: uploadImage.acceptMime || 'image/*'
                                        , exts: uploadImage.exts || 'jpg|png|gif|bmp|jpeg'
                                        , size: uploadImage.size || 1024 * 10
                                        , field: uploadImage.field
                                        , before: function (obj) {
                                            loding = layer.msg('文件上传中,请稍等哦', { icon: 16, shade: 0.3, time: 0 });
                                        }
                                        , done: function (res, input, upload) {
                                            layer.close(loding);
                                            if (res.code == 0) {
                                                res.data = res.data || {};
                                                cover.val(res.data.src);
                                                uploadImage.done(res);
                                            } else if (res.code == 2) {
                                                var curIndex = layer.open({
                                                    type: 1
                                                    , anim: 2
                                                    , icon: 5
                                                    , title: '提示'
                                                    , area: ['390px', '260px']
                                                    , offset: 't'
                                                    , content: res.msg + "确定使用该文件吗?
"
                                                    , btn: ['确定', '取消']
                                                    , yes: function () {
                                                        res.data = res.data || {};
                                                        cover.val(res.data.src);
                                                        layer.close(curIndex);
                                                    }
                                                });
                                            } else {
                                                layer.msg(res.msg || "上传失败");
                                            }
                                        }
                                    });
                                    upload.render({
                                        elem: '#LayEdit_InsertVideo'
                                        , url: uploadfile.url
                                        , method: uploadfile.method
                                        , data: uploadfile.data
                                        , headers: uploadfile.headers
                                        , field: uploadfile.field
                                        , accept: uploadfile.accept || 'video'
                                        , acceptMime: uploadfile.acceptMime || 'video/*'
                                        , exts: uploadfile.exts || 'mp4|flv|avi|rm|rmvb'
                                        , size: uploadfile.size || 1024 * 20
                                        , before: function (obj) {
                                            loding = layer.msg('文件上传中,请稍等哦', { icon: 16, shade: 0.3, time: 0 });
                                        }
                                        , done: function (res, input, upload) {
                                            layer.close(loding);
                                            if (res.code == 0) {
                                                res.data = res.data || {};
                                                video.val(res.data.src);
                                                uploadfile.done(res);
                                            } else if (res.code == 2) {
                                                var curIndex = layer.open({
                                                    type: 1
                                                    , anim: 2
                                                    , icon: 5
                                                    , title: '提示'
                                                    , area: ['390px', '260px']
                                                    , offset: 't'
                                                    , content: res.msg + "
确定使用该文件吗?
"
                                                    , btn: ['确定', '取消']
                                                    , yes: function () {
                                                        res.data = res.data || {};
                                                        video.val(res.data.src);
                                                        layer.close(curIndex);
                                                    }
                                                });
                                            } else {
                                                layer.msg(res.msg || "上传失败");
                                            }
                                        }
                                    });
                                    var theme = layero.find('select[name="theme"]');
                                    if (customTheme.video.title.length > 0 && theme.length > 0) {
                                        layero.find('select[name="theme"]').on('change mouseover', function () {
                                            layer.tips("' + file.name + '  ')
                                            });
                                        }
                                        , allDone: function () {
                                            //所有上传操作完成后,删除出错的文件
                                            for (var i = 0; i < errorIndex.length; i++) {
                                                $('#filesPrev').find('a[data-index="' + errorIndex[i] + '"]').remove();
                                            }
                                            //触发自动插入编辑器功能
                                            if (uploadFiles.autoInsert) {
                                                insertInline.call(iframeWin, 'p', {
                                                    text: layero.find('#filesPrev').html()
                                                }, range);
                                                layer.close(index);
                                            }
                                        }
                                        , error: function (index, upload) {
                                            //某文件上传接口返回错误时,将其错误index记录下来
                                            errorIndex.push(index);
                                        }
                                        , done: function (res, index, upload) {
                                            if (res.code == 0) {
                                                res.data = res.data || {};
                                                $('#filesPrev a[data-index="' + index + '"]').attr('href', res.data.src);
                                                uploadFiles.done(res);
                                            } else if (res.code == 2) {
                                                layer.msg(res.msg || '上传失败');
                                                res.data = res.data || {};
                                                $('#filesPrev a[data-index="' + index + '"]').attr('href', res.data.src);
                                                uploadFiles.done(res);
                                            } else {
                                                layer.msg(res.msg || '上传失败');
                                            }
                                            layero.find('#filesPrev a').on('click', function () {
                                                var dataIndex = this.getAttribute("data-index");
                                                layer.confirm('是否删除该附件?', { icon: 3, title: '提示' }, function (index) {
                                                    var callDel = set.calldel;
                                                    if (callDel.url != "") {
                                                        $.post(callDel.url, { "filepath": this.href }, function (res) {
                                                            $('#filesPrev').find('a[data-index="' + dataIndex + '"]').remove();
                                                            callDel.done(res);
                                                        })
                                                    } else {
                                                        layer.msg("没有配置回调参数");
                                                        $('#filesPrev').find('a[data-index="' + dataIndex + '"]').remove();
                                                    }
                                                    layer.close(index);
                                                });
                                            });
                                        }
                                    });
                                })
                            }
                        });
                    }
                    //源码模式
                    , html: function (range) {
                        var that = this;
                        if (that.parentElement.nextElementSibling.lastElementChild.id.indexOf('aceHtmleditor') == -1) {
                            var docs = that.parentElement.nextElementSibling.firstElementChild.contentDocument.body.innerHTML;
                            if (docs.indexOf("") > -1) {
                                docs = docs
                                    .replace(/</g, '<').replace(/>/g, '>').replace(/'/g, "'").replace(/"/g, '"');
                            }
                            docs = style_html(docs, 4, ' ', 80);
                            that.parentElement.nextElementSibling.setAttribute("style", "z-index: 999; overflow: hidden;height:" + that.parentElement.nextElementSibling.clientHeight + "px");
                            if (this.parentElement.parentElement.getAttribute("style") !== null) this.parentElement.nextElementSibling.setAttribute("style", "z-index: 999; overflow: hidden;height: " + (this.parentElement.parentElement.offsetHeight - this.parentElement.offsetHeight - 14) + "px");
                            that.parentElement.nextElementSibling.firstElementChild.style = "position: absolute;left: -32768px;top: -32768px;";
                            var htmlPanel = document.createElement("div");
                            htmlPanel.setAttribute("id", that.parentElement.nextElementSibling.firstElementChild.id + "aceHtmleditor");
                            htmlPanel.setAttribute("style", "left: 0px;top: 0px;width: 100%;height: 100%");
                            that.parentElement.nextElementSibling.appendChild(htmlPanel);
                            var editor = ace.edit(that.parentElement.nextElementSibling.firstElementChild.id + 'aceHtmleditor');
                            editor.setFontSize(14);
                            editor.session.setMode("ace/mode/html");
                            editor.setTheme("ace/theme/tomorrow");
                            editor.setValue(docs);
                            editor.setOption("wrap", "free");
                            editor.gotoLine(0);
                            //工具栏屏蔽
                            $(that).siblings('i').addClass("layui-disabled");
                            $(that).siblings('.layedit-tool-fullScreen').removeClass("layui-disabled");
                            $(that).removeClass("layui-disabled");
                        } else {
                            var editor = ace.edit(that.parentElement.nextElementSibling.firstElementChild.id + 'aceHtmleditor');
                            var doc = editor.getValue();
                            iframeWin.document.body.innerHTML = doc;
                            iframeWin.document.body.childNodes.forEach(function (item, index, arr) {
                                if (item.tagName == "PRE") {
                                    item.innerHTML = item.innerHTML.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&').replace(//g, '>').replace(/'/g, ''').replace(/"/g, '"');
                                }
                            });
                            var height = that.parentElement.nextElementSibling.clientHeight;
                            that.parentElement.nextElementSibling.removeAttribute("style");
                            this.parentElement.nextElementSibling.firstElementChild.style = "height:" + height + "px";
                            this.parentElement.nextElementSibling.lastElementChild.remove();
                            $(that).siblings('i').removeClass("layui-disabled");
                        }
                    }
                    //全屏
                    , fullScreen: function (range) {
                        if (this.parentElement.parentElement.getAttribute("style") == null) {
                            this.parentElement.parentElement.setAttribute("style", "position: fixed;top: 0;left: 0;height: 100%;width: 100%;background-color: #fff;z-index: 9999;");
                            this.parentElement.nextElementSibling.style = "height:" + (this.parentElement.parentElement.offsetHeight - this.parentElement.offsetHeight - 8) + "px";
                            this.parentElement.nextElementSibling.firstElementChild.style = "height:100%";
                            //是否源码模式
                            if (this.parentElement.nextElementSibling.lastElementChild.id.indexOf('aceHtmleditor') > -1) {
                                this.parentElement.nextElementSibling.firstElementChild.style = "position: absolute;left: -32768px;top: -32768px;";
                                this.parentElement.nextElementSibling.setAttribute("style", "z-index: 999; overflow: hidden;height: " + (this.parentElement.parentElement.offsetHeight - this.parentElement.offsetHeight) + "px");
                            }
                        } else {
                            this.parentElement.parentElement.removeAttribute("style");
                            this.parentElement.nextElementSibling.removeAttribute("style");
                            this.parentElement.nextElementSibling.firstElementChild.style = "height:" + set.height;
                            if (this.parentElement.nextElementSibling.lastElementChild.id.indexOf('aceHtmleditor') > -1) {
                                this.parentElement.nextElementSibling.setAttribute("style", "z-index: 999; overflow: hidden;height:" + this.parentElement.nextElementSibling.firstElementChild.clientHeight + "px");
                                this.parentElement.nextElementSibling.firstElementChild.style = "position: absolute;left: -32768px;top: -32768px;";
                            }
                        }
                    }
                    , preview: function (range) {
                        var currStyle = [];
                        layui.each(set.quote.style, function (index, item) {
                            currStyle.push(' 0){
                                fontText = alt.text[fontText];
                            }else {
                                fontText = value;
                            }
                            // 获取到对应的节点id
                            var list = getRangeNodes(range);
                            // window.iframeDOM = iframeDOM;
                            layer.msg('已成功设置行间距为:'+fontText,{icon:6})
                            // iframeDOM.execCommand('FontSize', false, value);
                            window.list = list;
                            // 修改字体样式
                            for(var i = 0;i");
                            setTimeout(function () {
                                body.focus();
                            }, 10);
                        });
                    }
                    , customlink: function (range) {
                        var container = getContainer(range)
                            , parentNode = $(container).parent();
                        customlink.call(body, { title: set.customlink.title }, function (field) {
                            var parent = parentNode[0];
                            if (parent.tagName === 'A') {
                                parent.href = field.url;
                                parent.rel = field.rel;
                            } else {
                                insertInline.call(iframeWin, 'a', {
                                    target: "_blank"
                                    , href: set.customlink.href
                                    , rel: "nofollow"
                                    , text: field.text
                                    , onmouseup: set.customlink.onmouseup
                                }, range);
                            }
                        });
                    }
                    , anchors: function (range) {
                        anchors.call(body, {}, function (field) {
                            insertInline.call(iframeWin, 'a', {
                                name: field.text
                                , text: " "
                            }, range);
                        });
                    }
                    , table: function (range) {
                        table.call(this, {}, function (opts) {
                            var tbody = "";
                            for (var i = 0; i < opts.cells; i++) {
                                tbody += " ";
                            var tmptr = tbody;
                            for (var i = 0; i < opts.rows; i++) {
                                tbody += tmptr;
                            }
                            insertInline.call(iframeWin, 'table', {
                                text: tbody
                            }, range);
                        });
                    }
                    , addhr: function (range) {
                        insertInline.call(iframeWin, 'hr', {}, range);
                    }
                    /*End*/
                    //帮助
                    , help: function () {
                        layer.open({
                            type: 2
                            , title: '帮助'
                            , area: ['600px', '380px']
                            , shadeClose: true
                            , shade: 0.1
                            , offset: '100px'
                            , skin: 'layui-layer-msg'
                            , content: ['http://www.layui.com/about/layedit/help.html', 'no']
                        });
                    }
                }
                , tools = editor.find('.layui-layedit-tool')
                , click = function () {
                    var othis = $(this)
                        , events = othis.attr('layedit-event')
                        , command = othis.attr('lay-command');
                    if (othis.hasClass(ABLED)) return;
                    body.focus();
                    var range = Range(iframeDOM)
                        , container = range.commonAncestorContainer;
                    if (command) {
                        if (/justifyLeft|justifyCenter|justifyRight/.test(command)) {
                            if (container.parentNode.tagName === 'BODY') {
                                iframeDOM.execCommand('formatBlock', false, '');
                            }
                        }
                        iframeDOM.execCommand(command);
                        setTimeout(function () {
                            if (/Bold/.test(command)) {
                                var elem = document.createElement("strong");
                                body.find("b").each(function () {
                                    elem.innerText = this.innerText;
                                    this.outerHTML = elem.outerHTML;
                                });
                            }
                            body.focus();
                        }, 10);
                    } else {
                        toolEvent[events] && toolEvent[events].call(this, range, iframeDOM);
                    }
                    toolCheck.call(iframeWin, tools, othis);
                }
                , isClick = /image/;
            tools.find('>i').on('mousedown', function () {
                var othis = $(this)
                    , events = othis.attr('layedit-event');
                if (isClick.test(events)) return;
                click.call(this)
            }).on('click', function () {
                var othis = $(this)
                    , events = othis.attr('layedit-event');
                if (!isClick.test(events)) return;
                click.call(this)
            });
            //触发内容区域
            body.on('click', function () {
                toolCheck.call(iframeWin, tools);
                layer.close(face.index);
                layer.close(fontFomatt.index);
                layer.close(fontfamily.index);
                layer.close(fontSize.index);
                layer.close(table.index);
            });
            //右键菜单自定义
            var rbtnIndex = null;
            var contextmenu = function (event) {
                var rbtn = set.rightBtn || {
                    type: "layBtn", customEvent: function (tagName, event) { }
                };
                if (event != null && rbtn.type != "default") {
                    layer.close(rbtnIndex);
                    var currenNode, parentNode;
                    currenNode = event.target;
                    parentNode = currenNode.parentNode;
                    if (rbtn.type == "custom") {
                        rbtn.customEvent(currenNode.tagName, event);
                        return false;
                    }
                    switch (currenNode.tagName) {
                        case "IMG":
                            imageEditor({
                                context: {
                                    set: set
                                }
                                , data: {
                                    src: event.target.src
                                    , alt: event.target.alt
                                    , width: event.target.style.width || event.target.getAttribute('width')
                                    , height: event.target.style.height || event.target.getAttribute('height')
                                }//打开图片编辑器之前
                                , beforeOpen: function (options, context) {
                                    //增加图片删除按钮
                                    options.btn.push('删除 ');
                                    options.btn3 = function (index, layero) {
                                        context.deleteImage(context.getImageData(), { src: 'must-delete' });
                                        event.toElement.remove();
                                        layer.close(index);
                                    }
                                }//上传前,用于删除之前的图片
                                , beforeUpload: function (imageData, context) {
                                    context.deleteImage(imageData);
                                }//点击确定后
                                , success: function (imageData, context) {
                                    event.target.src = imageData.src;
                                    event.target.alt = imageData.alt;
                                    event.target.style.width = imageData.width;
                                    event.target.style.height = imageData.height;
                                }
                            });
                            break;
                        case "VIDEO":
                            var customTheme = set.customTheme || { video: [] }
                                , customContent = "";
                            if (customTheme.video.title.length > 0) {
                                customContent = AddCustomThemes(customTheme.video.title, customTheme.video.content, customTheme.video.preview);
                            }
                            rbtnIndex = layer.open({
                                type: 1
                                , id: 'fly-jie-video-upload'
                                , title: '视频管理'
                                , shade: 0.05
                                , shadeClose: true
                                , area: function () {
                                    if (/mobile/i.test(navigator.userAgent) || $(window).width() <= 485) {
                                        return ['90%']
                                    } else {
                                        return ['485px']
                                    }
                                }()
                                , offset: function () {
                                    if (/mobile/i.test(navigator.userAgent)) {
                                        return 'auto'
                                    } else {
                                        return '100px'
                                    }
                                }()
                                , skin: 'layui-layer-border'
                                , content: ['
'].join('')
                                , btn: ['确定', '取消', '删除 ']
                                , btnAlign: 'c'
                                , yes: function (index, layero) {
                                    var video = layero.find('input[name="video"]')
                                        , cover = layero.find('input[name="cover"]');
                                    if (video.val() == '') {
                                        layer.msg('请选择一个视频或输入视频地址')
                                    } else {
                                        event.target.src = video.val();
                                        event.target.poster = cover.val();
                                        layer.close(index);
                                    }
                                }
                                , btn2: function (index, layero) {
                                }
                                , btn3: function (index, layero) {
                                    var callDel = set.calldel;
                                    if (callDel.url != "") {
                                        $.post(callDel.url, {
                                            "filepath": event.target.src
                                            , "imgpath": event.target.poster
                                        }, function (res) {
                                            parentNode.remove();
                                            callDel.done(res);
                                        })
                                    } else {
                                        event.toElement.remove();
                                    }
                                    layer.close(index);
                                }
                                , success: function (layero, index) {
                                    layui.use('upload', function (upload) {
                                        var loding
                                            , video = layero.find('input[name="video"]')
                                            , cover = layero.find('input[name="cover"]')
                                            , upload = layui.upload
                                            , uploadImage = set.uploadImage || {}
                                            , uploadfile = set.uploadVideo || {};
                                        if (uploadImage.url == "") {
                                            layer.msg("图片上传接口配置错误!");
                                        }
                                        if (uploadfile.url == "") {
                                            layer.msg("视频上传接口配置错误!");
                                        }
                                        //执行实例
                                        upload.render({
                                            elem: '#LayEdit_InsertImage'
                                            , url: uploadImage.url
                                            , method: uploadImage.method
                                            , data: uploadImage.data
                                            , headers: uploadImage.headers
                                            , accept: uploadImage.accept || 'image'
                                            , acceptMime: uploadImage.acceptMime || 'image/*'
                                            , exts: uploadImage.exts || 'jpg|png|gif|bmp|jpeg'
                                            , size: uploadImage.size || 1024 * 10
                                            , field: uploadImage.field
                                            , before: function (obj) {
                                                loding = layer.msg('文件上传中,请稍等哦', { icon: 16, shade: 0.3, time: 0 });
                                            }
                                            , done: function (res, input, upload) {
                                                layer.close(loding);
                                                if (res.code == 0) {
                                                    res.data = res.data || {};
                                                    cover.val(res.data.src);
                                                    uploadImage.done(res);
                                                } else if (res.code == 2) {
                                                    var curIndex = layer.open({
                                                        type: 1
                                                        , anim: 2
                                                        , icon: 5
                                                        , title: '提示'
                                                        , area: ['390px', '260px']
                                                        , offset: 't'
                                                        , content: res.msg + "确定使用该文件吗?
"
                                                        , btn: ['确定', '取消']
                                                        , yes: function () {
                                                            res.data = res.data || {};
                                                            cover.val(res.data.src);
                                                            layer.close(curIndex);
                                                        }
                                                    });
                                                } else {
                                                    layer.msg(res.msg || "上传失败");
                                                }
                                            }
                                        });
                                        upload.render({
                                            elem: '#LayEdit_InsertVideo'
                                            , url: uploadfile.url
                                            , method: uploadfile.method
                                            , data: uploadfile.data
                                            , headers: uploadfile.headers
                                            , field: uploadfile.field
                                            , accept: uploadfile.accept || 'video'
                                            , acceptMime: uploadfile.acceptMime || 'video/*'
                                            , exts: uploadfile.exts || 'mp4|flv|avi|rm|rmvb'
                                            , size: uploadfile.size || 1024 * 20
                                            , before: function (obj) {
                                                loding = layer.msg('文件上传中,请稍等哦', { icon: 16, shade: 0.3, time: 0 });
                                            }
                                            , done: function (res, input, upload) {
                                                layer.close(loding);
                                                if (res.code == 0) {
                                                    res.data = res.data || {};
                                                    video.val(res.data.src);
                                                    uploadfile.done(res);
                                                } else if (res.code == 2) {
                                                    var curIndex = layer.open({
                                                        type: 1
                                                        , anim: 2
                                                        , icon: 5
                                                        , title: '提示'
                                                        , area: ['390px', '260px']
                                                        , offset: 't'
                                                        , content: res.msg + "
确定使用该文件吗?
"
                                                        , btn: ['确定', '取消']
                                                        , yes: function () {
                                                            res.data = res.data || {};
                                                            video.val(res.data.src);
                                                            layer.close(curIndex);
                                                        }
                                                    });
                                                } else {
                                                    layer.msg(res.msg || "上传失败");
                                                }
                                            }
                                        });
                                        var theme = layero.find('select[name="theme"]');
                                        if (customTheme.video.title.length > 0 && theme.length > 0) {
                                            layero.find('select[name="theme"]').on('change mouseover', function () {
                                                layer.tips(" 新增行  '
                                        , ' 删除行  '].join('');
                                    return '';
                                }()
                                , success: function (layero, index) {
                                    layero.find('li').on('click', function () {
                                        var othis = $(this)
                                            , command = othis.attr('lay-command');
                                        if (command) {
                                            switch (command) {
                                                case 'deltr':
                                                    parentNode.remove();
                                                    break;
                                                case 'addnewtr':
                                                    var html = "";
                                                    for (var i = 0; i < parentNode.children.length; i++) {
                                                        html += " ";
                                                    $(parentNode).after(html)
                                                    break;
                                            }
                                        }
                                        layer.close(index);
                                    });
                                }
                            });
                            break;
                        default:
                            rbtnIndex = layer.open({
                                type: 1
                                , title: false
                                , closeBtn: false
                                , offset: function () {
                                    if (/mobile/i.test(navigator.userAgent)) {
                                        return 'auto'
                                    } else {
                                        var frame = set._elem.next().find('iframe').get(0);
                                        return [
                                            frame.offsetTop + event.clientY + parentNode.getBoundingClientRect().y + "px", frame.offsetLeft + event.clientX + parentNode.getBoundingClientRect().x + 'px'
                                        ];
                                    }
                                }()
                                , shade: function () {
                                    if (/mobile/i.test(navigator.userAgent)) {
                                        return 0.1
                                    }
                                    return 0;
                                }
                                , shadeClose: true
                                , content: [''
                                    , ''].join('')
                                , success: function (layero, index) {
                                    var callDel = set.calldel;
                                    layero.find('.layui-btn-primary').on('click', function () {
                                        var othis = $(this)
                                            , command = othis.attr('lay-command');
                                        if (command) {
                                            if (currenNode.tagName == "VIDEO") {
                                                parentNode.style = "text-align:" + command;
                                            } else {
                                                currenNode.style = "text-align:" + command;
                                            }
                                        }
                                        layer.close(index);
                                    });
                                    layero.find('.context-menu-delete').on('click', function () {
                                        if (currenNode.tagName == "BODY") {
                                            layer.msg("不能再删除了")
                                        } else if (currenNode.tagName == "VIDEO") {
                                            if (callDel.url != "") {
                                                $.post(callDel.url, {
                                                    "filepath": event.target.src, "imgpath": event.target.poster
                                                }, function (res) {
                                                    parentNode.remove();
                                                    callDel.done(res);
                                                })
                                            } else {
                                                parentNode.remove();
                                            }
                                        } else if (currenNode.tagName == "IMG") {
                                            if (callDel.url != "") {
                                                $.post(callDel.url, { para: event.target.src }, function (res) {
                                                    currenNode.remove();
                                                    callDel.done(res);
                                                })
                                            } else {
                                                currenNode.remove();
                                            }
                                        } else {
                                            currenNode.remove();
                                        }
                                        layer.close(index);
                                    });
                                }
                            });
                            break;
                        //return true;
                    }
                    return false;
                }
            };
            if (/mobile/i.test(navigator.userAgent)) {
                var timeOutEvent;
                body.on({
                    touchstart: function (e) {
                        // 长按事件触发
                        timeOutEvent = setTimeout(function () {
                            contextmenu(e);
                            clearTimeout(timeOutEvent);
                        }, 300);
                        //长按300毫秒
                        e.preventDefault();
                    }, touchmove: function () {
                        clearTimeout(timeOutEvent);
                    }, touchend: function () {
                        clearTimeout(timeOutEvent);
                    }
                });
            } else {
                body.on('contextmenu', function (event) {
                    return contextmenu(event);
                })
            }
        }
        //超链接面板
        , link = function (options, callback) {
            var dMode = options.dmode;
            var body = this
                , index = layer.open({
                    type: 1
                    , id: 'LAY_layedit_link'
                    , area: function () {
                        if (/mobile/i.test(navigator.userAgent) || $(window).width() <= 460) {
                            return ['90%']
                        } else {
                            return ['460px']
                        }
                    }()
                    , offset: function () {
                        if (/mobile/i.test(navigator.userAgent)) {
                            return 'auto'
                        } else {
                            return '100px'
                        }
                    }()
                    , shade: 0.05
                    , shadeClose: true
                    , moveType: 1
                    , title: '超链接'
                    , skin: 'layui-layer-msg'
                    , content: [''].join('')
                    , btn: ['确定', '取消']
                    , btnAlign: 'c'
                    , yes: function (index, layero) {
                        $('#layedit-link-yes').click();
                    }
                    , btn1: function (index, layero) {
                        layer.close(index);
                        setTimeout(function () {
                            body.focus();
                        }, 10);
                    }
                    , success: function (layero, index) {
                        var eventFilter = 'submit(layedit-link-yes)';
                        form.render('radio');
                        form.on(eventFilter, function (data) {
                            layer.close(link.index);
                            callback && callback(data.field);
                        });
                    }
                });
            link.index = index;
        }
        , customlink = function (options, callback) {
            var body = this
                , index = layer.open({
                    type: 1
                    , id: 'LAY_layedit_customlink'
                    , area: function () {
                        if (/mobile/i.test(navigator.userAgent) || $(window).width() <= 350) {
                            return ['90%']
                        } else {
                            return ['350px']
                        }
                    }()
                    , offset: function () {
                        if (/mobile/i.test(navigator.userAgent)) {
                            return 'auto'
                        } else {
                            return '100px'
                        }
                    }()
                    , shade: 0.05
                    , shadeClose: true
                    , moveType: 1
                    , title: options.title
                    , skin: 'layui-layer-msg'
                    , content: [''].join('')
                    , btn: ['确定', '取消']
                    , btnAlign: 'c'
                    , yes: function (index, layero) {
                        $('#layedit-link-yes').click();
                    }
                    , success: function (layero, index) {
                        var eventFilter = 'submit(layedit-link-yes)';
                        form.render('radio');
                        form.on(eventFilter, function (data) {
                            callback && callback(data.field);
                            layer.close(customlink.index);
                        });
                    }
                });
            customlink.index = index;
        }
        , anchors = function (options, callback) {
            var body = this
                , index = layer.open({
                    type: 1
                    , id: 'LAY_layedit_addmd'
                    , area: function () {
                        if (/mobile/i.test(navigator.userAgent) || $(window).width() <= 350) {
                            return ['90%']
                        } else {
                            return ['350px']
                        }
                    }()
                    , offset: function () {
                        if (/mobile/i.test(navigator.userAgent)) {
                            return 'auto'
                        } else {
                            return '100px'
                        }
                    }()
                    , shade: 0.05
                    , shadeClose: true
                    , moveType: 1
                    , title: '添加锚点'
                    , skin: 'layui-layer-msg'
                    , content: [''].join('')
                    , btn: ['确定', '取消']
                    , btnAlign: 'c'
                    , yes: function (index, layero) {
                        $('#layedit-link-yes').click();
                    }
                    , success: function (layero, index) {
                        var eventFilter = 'submit(layedit-link-yes)';
                        form.render('radio');
                        form.on(eventFilter, function (data) {
                            layer.close(anchors.index);
                            callback && callback(data.field);
                        });
                    }
                });
            anchors.index = index;
        }
        , table = function (options, callback) {
            table.hide = table.hide || function (e) {
                if ($(e.target).attr('layedit-event') !== 'table') {
                    layer.close(table.index);
                }
            };
            if (!/mobile/i.test(navigator.userAgent)) {
                table.index = layer.tips(
                    function () {
                        return '0列 x 0行 '
                            + '
'
                            + ''
                            + ' '
                            + '
0列 x 0行 '
                            + '
'
                            + '
<' + options.fonts[index] + '>' + options.texts[index] + '' + options.fonts[index] + '> ');
                });
                return '';
            }(), this, {
                tips: 1
                , time: 0
                , skin: 'layui-box layui-util-face'
                , success: function (layero, index) {
                    layero.css({ marginTop: -4, marginLeft: -10 }).find('.layui-clear>li').on('click', function () {
                        callback && callback(this.title, options.fonts);
                        layer.close(index);
                    });
                    $(document).off('click', fontFomatt.hide).on('click', fontFomatt.hide);
                }
            });
        }
        , fontfamily = function (options, callback) {
            fontfamily.hide = fontfamily.hide || function (e) {
                if ($(e.target).attr('layedit-event') != 'fontfamily') {
                    layer.close(fontfamily.index);
                }
            }
            fontfamily.index = layer.tips(function () {
                var content = [];
                layui.each(options.fonts, function (index, item) {
                    content.push('<' + options.fonts[index] + '>' + options.texts[index] + '' + options.fonts[index] + '> ');
                });
                return '';
            }(), this, {
                tips: 1
                , time: 0
                , skin: 'layui-box layui-util-face'
                , success: function (layero, index) {
                    layero.css({ marginTop: -4, marginLeft: -10 }).find('.layui-clear>li').on('click', function () {
                        callback && callback(this.title, options.fonts);
                        layer.close(index);
                    });
                    $(document).off('click', fontfamily.hide).on('click', fontfamily.hide);
                }
            });
        }
        // 字体大小 显示操作
        ,fontSize = function (options, callback) {
            fontSize.hide = fontSize.hide || function (e) {
                if ($(e.target).attr('layedit-event') !== 'fontSize') {
                    layer.close(fontSize.index);
                }
            }
            if(!options.last_value){
                options.last_value = 2;
            }
            fontSize.index = layer.tips(function () {
                var content = [];
                layui.each(options.fonts, function (index, item) {
                    var iHtml = '';
                    if(options.last_value == options.fonts[index]){
                        iHtml = '   '
                    }
                    content.push('' + options.fonts[index] + ':' + options.texts[index] + iHtml +'' + options.fonts[index] +'> ');
                });
                return '';
            }(), this, {
                    tips: 1
                    , time: 0
                    , skin: 'layui-box layui-util-font'
                    , success: function (layero, index) {
                        layero.css({ marginTop: -4, marginLeft: -10 }).find('.layui-clear>li').on('click', function () {
                            callback && callback(this.title, options.fonts,options.texts);
                            layer.close(index);
                        });
                        $(document).off('click', fontSize.hide).on('click', fontSize.hide);
                    }
                });
        }
         // 间距
         ,lineHeight = function (options, callback) {
            lineHeight.hide = lineHeight.hide || function (e) {
                if ($(e.target).attr('layedit-event') !== 'lineHeight') {
                    layer.close(lineHeight.index);
                }
            }
            if(!options.last_value){
                options.last_value = 1;
            }
            lineHeight.index = layer.tips(function () {
                var content = [];
                layui.each(options.fonts, function (index, item) {
                    var iHtml = '';
                    if(options.last_value == options.fonts[index]){
                        iHtml = '     '
                    }
                    content.push('' + options.texts[index] + iHtml + '' + options.fonts[index]  + '> ');
                });
                return '';
            }(), this, {
                    tips: 1
                    , time: 0
                    , skin: 'layui-box layui-util-font'
                    , success: function (layero, index) {
                        layero.css({ marginTop: -4, marginLeft: -10 }).find('.layui-clear>li').on('click', function () {
                            callback && callback(this.title, options.fonts);
                            layer.close(index);
                        });
                        $(document).off('click', lineHeight.hide).on('click', lineHeight.hide);
                    }
                });
        }
        //插入代码面板
        , code = function (options, callback) {
            var objSel = [''
                , '请选择语言 '
                , ''
                , ''
                , ''
                , 'JavaScript '
                , 'HTML '
                , 'CSS '
                , 'Java '
                , 'PHP '
                , 'C# '
                , 'Python '
                , 'Ruby '
                , 'Go '
                , ' '
                , '
'
                , ' '].join('');
            if (options.hide) {
                objSel = [''
                    , '请选择语言 '
                    , ''
                    , ''
                    , ''
                    , options.default
                    , ' '
                    , ' '
                    , '
'
                    , ' '].join('');
            }
            var body = this
                , index = layer.open({
                    type: 1
                    , id: 'LAY_layedit_code'
                    , area: function () {
                        if (/mobile/i.test(navigator.userAgent) || $(window).width() <= 650) {
                            return ['90%']
                        } else {
                            return ['650px']
                        }
                    }()
                    , offset: function () {
                        if (/mobile/i.test(navigator.userAgent)) {
                            return 'auto'
                        } else {
                            return '100px'
                        }
                    }()
                    , shade: 0.05
                    , shadeClose: true
                    , moveType: 1
                    , title: '插入代码'
                    , skin: 'layui-layer-msg'
                    , content: [''].join('')
                    , btn: ['确定', '取消']
                    , btnAlign: 'c'
                    , yes: function (index, layero) {
                        $('#layedit-code-yes').click();
                    }
                    , btn1: function (index, layero) {
                        layer.close(index);
                        body.focus();
                    }
                    , success: function (layero, index) {
                        var eventFilter = 'submit(layedit-code-yes)';
                        form.render('select');
                        form.on(eventFilter, function (data) {
                            layer.close(code.index);
                            callback && callback(data.field, options.hide, options.default);
                        });
                    }
                });
            code.index = index;
        }
        //全部工具
        , tools = {
            html: '  '
            , redo: ' '
            , strong: ' '
            , italic: ' '
            , underline: ' '
            , del: ' '
            , '|': ' '
            , center: ' '
            , right: ' '
            , link: ' '
            , unlink: ' '
            , face: ' '
            , image: ' '
            , code: ' '
            , images: ' '
            , image_alt: ' '
            , video: ' '
            , fullScreen: ' '
            , colorpicker: ' '
            , fontBackColor: ' '
            , fontfamily: ' '
            , fontSize: ' '
            , lineHeight: ' '
            , addhr: ' '
            , customlink: ' '
            , table: ' '
            , attachment: ' '
            , preview: ' '
            , removeformat: ' '
            , help: ' '
        }
        // 打开图片编辑框
        , imageEditor = function (options) {
            var context = options.context || {}
                , successCallback = options.success
                , beforeUploadCallback = options.beforeUpload
                , initialData = context.initialData = options.data
                , formId = context.formId = 'image-upload-' + parseInt(Math.random() * 1000000)
                , formatWidthHeight = function (val) {
                    var isNum = val.toString().indexOf('%') == -1;
                    return {
                        value: isNum ? parseInt(val) : val, string: isNum ? parseInt(val) + 'px' : val
                    };
                }
                , getImageData = context.getImageData = function () {
                    var imageData = layui.form.val(formId) || (function () {
                        //老版本layui.form.val无法取值
                        var itemForm = $('[lay-filter="' + formId + '"]').eq(0)
                            , field = {};
                        layui.each(itemForm.find('input,select,textarea'), function (_, item) {
                            field[item.name] = item.value;
                        });
                        return field;
                    })();
                    imageData.style = '';
                    if (imageData.width) {
                        imageData.width = formatWidthHeight(imageData.width).string;
                        imageData.style += "width:" + imageData.width + ";";
                    }
                    if (imageData.height) {
                        imageData.height = formatWidthHeight(imageData.height).string;
                        imageData.style += "height:" + imageData.height + ";";
                    }
                    context.logger && context.logger('getImageData', imageData);
                    return imageData;
                }
                , setImageData = context.setImageData = function (imageData) {
                    imageData = imageData || {};
                    if (!!imageData.width) {
                        imageData.width = formatWidthHeight(imageData.width).value;
                    }
                    if (!!imageData.height) {
                        imageData.height = formatWidthHeight(imageData.height).value;
                    }
                    form.val(formId, imageData);
                    //如果没有指定图片尺寸,尝试获取
                    if (imageData.src && !imageData.isInitialData && !imageData.loaded && !imageData.width && !imageData.height) {
                        var image = new Image();
                        image.src = imageData.src;
                        image.onload = function () {
                            imageData.loaded = true;
                            imageData.width = image.naturalWidth.toString();
                            imageData.height = image.naturalHeight.toString();
                            setImageData(imageData);
                        };
                    }
                }
                , checkImageSrc = context.checkImageSrc = function (imageData) {
                    if (!imageData.src) {
                        layer.msg('请先上传图片', { icon: 2, shade: 0.3, time: 1000 })
                    }
                    return !!imageData.src;
                }
                , imagePreview = context.imagePreview = function (imageData, title, callback) {
                    var image = new Image()
                        , maxWidth = /mobile/i.test(navigator.userAgent) ? 300 : 640
                        , maxHeight = /mobile/i.test(navigator.userAgent) ? 600 : 480;
                    image.src = imageData.src;
                    image.onload = function () {
                        //获取图片实际尺寸,并根据图片原始尺寸调整预览框大小
                        var width = image.naturalWidth
                            , height = image.naturalHeight;
                        if (width > maxWidth) {
                            height = height * maxWidth / width
                            width = maxWidth
                        }
                        if (height > maxHeight) {
                            width = width * maxHeight / height
                            height = maxHeight
                        }
                        layer.open({
                            type: 1
                            , anim: 2
                            , icon: 5
                            , title: title || null
                            , offset: '100px'
                            , area: [(width + 20) + 'px', (height + 77) + 'px']
                            , content: [''
                                , ' 
'
                                , '
' + item + ' ');
    });
    return [''
        , '主题选择 '
        , ''
        , '' + content.join('') + ' '
        , '
'
        , ' '].join('');
}
// 找出当前选中范围的节点
function getRangeNodes(range){
    var cls = range.commonAncestorContainer.nodeName == 'BODY' ? range.commonAncestorContainer.children : [range.commonAncestorContainer.parentElement];
    var list = [];
    var bool = false;
    for(var i = 0; i< cls.length;i++){
        var start = range.startContainer.parentElement;
        if(start.nodeName == "FONT"){
            start = start.parentElement;
        }
        var end = range.endContainer.parentElement
        if(end.nodeName == "FONT"){
            end = end.parentElement;
        }
        if(!bool && cls[i] == start){
            bool = true;
        } else if(bool && cls[i] == end){
            list.push(cls[i])
            break;
        }
        if(bool){
            list.push(cls[i])
        }
    }
    return list;
}
//HTML 格式化
function style_html (html_source, indent_size, indent_character, max_char) {
    var Parser, multi_parser;
    function Parser () {
        this.pos = 0;
        this.token = '';
        this.current_mode = 'CONTENT';
        this.tags = {
            parent: 'parent1'
            , parentcount: 1
            , parent1: ''
        };
        this.tag_type = '';
        this.token_text = this.last_token = this.last_text = this.token_type = '';
        this.Utils = {
            whitespace: "\n\r\t ".split('')
            , single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed'.split(',')
            , extra_liners: 'head,body,/html'.split(',')
            , in_array: function (what, arr) {
                for (var i = 0; i < arr.length; i++) {
                    if (what === arr[i]) {
                        return true;
                    }
                }
                return false;
            }
        }
        this.get_content = function () {
            var char = '';
            var content = [];
            var space = false;
            while (this.input.charAt(this.pos) !== '<') {
                if (this.pos >= this.input.length) {
                    return content.length ? content.join('') : ['', 'TK_EOF'];
                }
                char = this.input.charAt(this.pos);
                this.pos++;
                this.line_char_count++;
                if (this.Utils.in_array(char, this.Utils.whitespace)) {
                    if (content.length) {
                        space = true;
                    }
                    this.line_char_count--;
                    continue;
                } else if (space) {
                    if (this.line_char_count >= this.max_char) {
                        content.push('\n');
                        for (var i = 0; i < this.indent_level; i++) {
                            content.push(this.indent_string);
                        }
                        this.line_char_count = 0;
                    } else {
                        content.push(' ');
                        this.line_char_count++;
                    }
                    space = false;
                }
                content.push(char);
            }
            return content.length ? content.join('') : '';
        }
        this.get_script = function () {
            var char = '';
            var content = [];
            var reg_match = new RegExp('', 'igm'); //使用RegExp,无需转义
            reg_match.lastIndex = this.pos;
            var reg_array = reg_match.exec(this.input);
            var end_script = reg_array ? reg_array.index : this.input.length;
            while (this.pos < end_script) {
                if (this.pos >= this.input.length) {
                    return content.length ? content.join('') : ['', 'TK_EOF'];
                }
                char = this.input.charAt(this.pos);
                this.pos++;
                content.push(char);
            }
            return content.length ? content.join('') : '';
        }
        this.record_tag = function (tag) {
            if (this.tags[tag + 'count']) {
                this.tags[tag + 'count']++;
                this.tags[tag + this.tags[tag + 'count']] = this.indent_level;
            } else {
                this.tags[tag + 'count'] = 1;
                this.tags[tag + this.tags[tag + 'count']] = this.indent_level;
            }
            this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent;
            this.tags.parent = tag + this.tags[tag + 'count'];
        }
        this.retrieve_tag = function (tag) {
            if (this.tags[tag + 'count']) {
                var temp_parent = this.tags.parent;
                while (temp_parent) {
                    if (tag + this.tags[tag + 'count'] === temp_parent) {
                        break;
                    }
                    temp_parent = this.tags[temp_parent + 'parent'];
                }
                if (temp_parent) {
                    this.indent_level = this.tags[tag + this.tags[tag + 'count']];
                    this.tags.parent = this.tags[temp_parent + 'parent'];
                }
                delete this.tags[tag + this.tags[tag + 'count'] + 'parent'];
                delete this.tags[tag + this.tags[tag + 'count']];
                if (this.tags[tag + 'count'] == 1) {
                    delete this.tags[tag + 'count'];
                } else {
                    this.tags[tag + 'count']--;
                }
            }
        }
        this.get_tag = function () {
            var char = '';
            var content = [];
            var space = false;
            do {
                if (this.pos >= this.input.length) {
                    return content.length ? content.join('') : ['', 'TK_EOF'];
                }
                char = this.input.charAt(this.pos);
                this.pos++;
                this.line_char_count++;
                if (this.Utils.in_array(char, this.Utils.whitespace)) {
                    space = true;
                    this.line_char_count--;
                    continue;
                }
                if (char === "'" || char === '"') {
                    if (!content[1] || content[1] !== '!') {
                        char += this.get_unformatted(char);
                        space = true;
                    }
                }
                if (char === '=') {
                    space = false;
                }
                if (content.length && content[content.length - 1] !== '=' && char !== '>'
                    && space) {
                    if (this.line_char_count >= this.max_char) {
                        this.print_newline(false, content);
                        this.line_char_count = 0;
                    } else {
                        content.push(' ');
                        this.line_char_count++;
                    }
                    space = false;
                }
                content.push(char);
            } while (char !== '>');
            var tag_complete = content.join('');
            var tag_index;
            if (tag_complete.indexOf(' ') !== -1) {
                tag_index = tag_complete.indexOf(' ');
            } else {
                tag_index = tag_complete.indexOf('>');
            }
            var tag_check = tag_complete.substring(1, tag_index).toLowerCase();
            if (tag_complete.charAt(tag_complete.length - 2) === '/' ||
                this.Utils.in_array(tag_check, this.Utils.single_token)) {
                this.tag_type = 'SINGLE';
            } else if (tag_check === 'script') {
                this.record_tag(tag_check);
                this.tag_type = 'SCRIPT';
            } else if (tag_check === 'style') {
                this.record_tag(tag_check);
                this.tag_type = 'STYLE';
            } else if (tag_check.charAt(0) === '!') {
                if (tag_check.indexOf('[if') !== -1) {
                    if (tag_complete.indexOf('!IE') != -1) {
                        var comment = this.get_unformatted('-->', tag_complete);
                        content.push(comment);
                    }
                    this.tag_type = 'START';
                } else if (tag_check.indexOf('[endif') !== -1) {
                    this.tag_type = 'END';
                    this.unindent();
                } else if (tag_check.indexOf('[cdata[') != -1) {
                    var comment = this.get_unformatted(']]>', tag_complete);
                    content.push(comment);
                    this.tag_type = 'SINGLE';
                } else {
                    var comment = this.get_unformatted('-->', tag_complete);
                    content.push(comment);
                    this.tag_type = 'SINGLE';
                }
            } else {
                if (tag_check.charAt(0) === '/') {
                    this.retrieve_tag(tag_check.substring(1));
                    this.tag_type = 'END';
                } else {
                    this.record_tag(tag_check);
                    this.tag_type = 'START';
                }
                if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) {
                    this.print_newline(true, this.output);
                }
            }
            return content.join('');
        }
        this.get_unformatted = function (delimiter, orig_tag) {
            if (orig_tag && orig_tag.indexOf(delimiter) != -1) {
                return '';
            }
            var char = '';
            var content = '';
            var space = true;
            do {
                char = this.input.charAt(this.pos);
                this.pos++
                if (this.Utils.in_array(char, this.Utils.whitespace)) {
                    if (!space) {
                        this.line_char_count--;
                        continue;
                    }
                    if (char === '\n' || char === '\r') {
                        content += '\n';
                        for (var i = 0; i < this.indent_level; i++) {
                            content += this.indent_string;
                        }
                        space = false;
                        this.line_char_count = 0;
                        continue;
                    }
                }
                content += char;
                this.line_char_count++;
                space = true;
            } while (content.indexOf(delimiter) == -1);
            return content;
        }
        this.get_token = function () {
            var token;
            if (this.last_token === 'TK_TAG_SCRIPT') {
                var temp_token = this.get_script();
                if (typeof temp_token !== 'string') {
                    return temp_token;
                }
                token = js_beautify(temp_token, this.indent_size, this.indent_character, this.indent_level);
                return [token, 'TK_CONTENT'];
            }
            if (this.current_mode === 'CONTENT') {
                token = this.get_content();
                if (typeof token !== 'string') {
                    return token;
                } else {
                    return [token, 'TK_CONTENT'];
                }
            }
            if (this.current_mode === 'TAG') {
                token = this.get_tag();
                if (typeof token !== 'string') {
                    return token;
                } else {
                    var tag_name_type = 'TK_TAG_' + this.tag_type;
                    return [token, tag_name_type];
                }
            }
        }
        this.printer = function (js_source, indent_character, indent_size, max_char) {
            this.input = js_source || '';
            this.output = [];
            this.indent_character = indent_character || ' ';
            this.indent_string = '';
            this.indent_size = indent_size || 2;
            this.indent_level = 0;
            this.max_char = max_char || 7000;
            this.line_char_count = 0;
            for (var i = 0; i < this.indent_size; i++) {
                this.indent_string += this.indent_character;
            }
            this.print_newline = function (ignore, arr) {
                this.line_char_count = 0;
                if (!arr || !arr.length) {
                    return;
                }
                if (!ignore) {
                    while (this.Utils.in_array(arr[arr.length - 1], this.Utils.whitespace)) {
                        arr.pop();
                    }
                }
                arr.push('\n');
                for (var i = 0; i < this.indent_level; i++) {
                    arr.push(this.indent_string);
                }
            }
            this.print_token = function (text) {
                this.output.push(text);
            }
            this.indent = function () {
                this.indent_level++;
            }
            this.unindent = function () {
                if (this.indent_level > 0) {
                    this.indent_level--;
                }
            }
        }
        return this;
    }
    multi_parser = new Parser();
    multi_parser.printer(html_source, indent_character, indent_size);
    var f = true;
    while (true) {
        var t = multi_parser.get_token();
        multi_parser.token_text = t[0];
        multi_parser.token_type = t[1];
        if (multi_parser.token_type === 'TK_EOF') {
            break;
        }
        switch (multi_parser.token_type) {
            case 'TK_TAG_START':
            case 'TK_TAG_SCRIPT':
            case 'TK_TAG_STYLE':
                multi_parser.print_newline(false, multi_parser.output);
                multi_parser.print_token(multi_parser.token_text);
                multi_parser.indent();
                multi_parser.current_mode = 'CONTENT';
                break;
            case 'TK_TAG_END':
                if (f)
                    multi_parser.print_newline(true, multi_parser.output);
                multi_parser.print_token(multi_parser.token_text);
                multi_parser.current_mode = 'CONTENT';
                f = true;
                break;
            case 'TK_TAG_SINGLE':
                multi_parser.print_newline(false, multi_parser.output);
                multi_parser.print_token(multi_parser.token_text);
                multi_parser.current_mode = 'CONTENT';
                break;
            case 'TK_CONTENT':
                if (multi_parser.token_text !== '') {
                    f = false;
                    multi_parser.print_token(multi_parser.token_text);
                }
                multi_parser.current_mode = 'TAG';
                break;
        }
        multi_parser.last_token = multi_parser.token_type;
        multi_parser.last_text = multi_parser.token_text;
    }
    return multi_parser.output.join('');
}
//JS 格式化
function js_beautify (js_source_text, indent_size, indent_character, indent_level) {
    var input, output, token_text, last_type, last_text, last_word, current_mode, modes, indent_string;
    var whitespace, wordchar, punct, parser_pos, line_starters, in_case;
    var prefix, token_type, do_block_just_closed, var_line, var_line_tainted;
    function trim_output () {
        while (output.length && (output[output.length - 1] === ' ' || output[output.length - 1] === indent_string)) {
            output.pop();
        }
    }
    function print_newline (ignore_repeated) {
        ignore_repeated = typeof ignore_repeated === 'undefined' ? true : ignore_repeated;
        trim_output();
        if (!output.length) {
            return; // no newline on start of file
        }
        if (output[output.length - 1] !== "\n" || !ignore_repeated) {
            output.push("\n");
        }
        for (var i = 0; i < indent_level; i++) {
            output.push(indent_string);
        }
    }
    function print_space () {
        var last_output = output.length ? output[output.length - 1] : ' ';
        if (last_output !== ' ' && last_output !== '\n' && last_output !== indent_string) { // prevent occassional duplicate space
            output.push(' ');
        }
    }
    function print_token () {
        output.push(token_text);
    }
    function indent () {
        indent_level++;
    }
    function unindent () {
        if (indent_level) {
            indent_level--;
        }
    }
    function remove_indent () {
        if (output.length && output[output.length - 1] === indent_string) {
            output.pop();
        }
    }
    function set_mode (mode) {
        modes.push(current_mode);
        current_mode = mode;
    }
    function restore_mode () {
        do_block_just_closed = current_mode === 'DO_BLOCK';
        current_mode = modes.pop();
    }
    function in_array (what, arr) {
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] === what) {
                return true;
            }
        }
        return false;
    }
    function get_next_token () {
        var n_newlines = 0;
        var c = '';
        do {
            if (parser_pos >= input.length) {
                return ['', 'TK_EOF'];
            }
            c = input.charAt(parser_pos);
            parser_pos += 1;
            if (c === "\n") {
                n_newlines += 1;
            }
        }
        while (in_array(c, whitespace));
        if (n_newlines > 1) {
            for (var i = 0; i < 2; i++) {
                print_newline(i === 0);
            }
        }
        var wanted_newline = (n_newlines === 1);
        if (in_array(c, wordchar)) {
            if (parser_pos < input.length) {
                while (in_array(input.charAt(parser_pos), wordchar)) {
                    c += input.charAt(parser_pos);
                    parser_pos += 1;
                    if (parser_pos === input.length) {
                        break;
                    }
                }
            }
            // small and surprisingly unugly hack for 1E-10 representation
            if (parser_pos !== input.length && c.match(/^[0-9]+[Ee]$/) && input.charAt(parser_pos) === '-') {
                parser_pos += 1;
                var t = get_next_token(parser_pos);
                c += '-' + t[0];
                return [c, 'TK_WORD'];
            }
            if (c === 'in') { // hack for 'in' operator
                return [c, 'TK_OPERATOR'];
            }
            return [c, 'TK_WORD'];
        }
        if (c === '(' || c === '[') {
            return [c, 'TK_START_EXPR'];
        }
        if (c === ')' || c === ']') {
            return [c, 'TK_END_EXPR'];
        }
        if (c === '{') {
            return [c, 'TK_START_BLOCK'];
        }
        if (c === '}') {
            return [c, 'TK_END_BLOCK'];
        }
        if (c === ';') {
            return [c, 'TK_END_COMMAND'];
        }
        if (c === '/') {
            var comment = '';
            // peek for comment /* ... */
            if (input.charAt(parser_pos) === '*') {
                parser_pos += 1;
                if (parser_pos < input.length) {
                    while (!(input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/') && parser_pos < input.length) {
                        comment += input.charAt(parser_pos);
                        parser_pos += 1;
                        if (parser_pos >= input.length) {
                            break;
                        }
                    }
                }
                parser_pos += 2;
                return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
            }
            // peek for comment // ...
            if (input.charAt(parser_pos) === '/') {
                comment = c;
                while (input.charAt(parser_pos) !== "\x0d" && input.charAt(parser_pos) !== "\x0a") {
                    comment += input.charAt(parser_pos);
                    parser_pos += 1;
                    if (parser_pos >= input.length) {
                        break;
                    }
                }
                parser_pos += 1;
                if (wanted_newline) {
                    print_newline();
                }
                return [comment, 'TK_COMMENT'];
            }
        }
        if (c === "'" || // string
            c === '"' || // string
            (c === '/' &&
                ((last_type === 'TK_WORD' && last_text === 'return') || (last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || last_type === 'TK_OPERATOR' || last_type === 'TK_EOF' || last_type === 'TK_END_COMMAND')))) { // regexp
            var sep = c;
            var esc = false;
            c = '';
            if (parser_pos < input.length) {
                while (esc || input.charAt(parser_pos) !== sep) {
                    c += input.charAt(parser_pos);
                    if (!esc) {
                        esc = input.charAt(parser_pos) === '\\';
                    } else {
                        esc = false;
                    }
                    parser_pos += 1;
                    if (parser_pos >= input.length) {
                        break;
                    }
                }
            }
            parser_pos += 1;
            if (last_type === 'TK_END_COMMAND') {
                print_newline();
            }
            return [sep + c + sep, 'TK_STRING'];
        }
        if (in_array(c, punct)) {
            while (parser_pos < input.length && in_array(c + input.charAt(parser_pos), punct)) {
                c += input.charAt(parser_pos);
                parser_pos += 1;
                if (parser_pos >= input.length) {
                    break;
                }
            }
            return [c, 'TK_OPERATOR'];
        }
        return [c, 'TK_UNKNOWN'];
    }
    //----------------------------------
    indent_character = indent_character || ' ';
    indent_size = indent_size || 4;
    indent_string = '';
    while (indent_size--) {
        indent_string += indent_character;
    }
    input = js_source_text;
    last_word = ''; // last 'TK_WORD' passed
    last_type = 'TK_START_EXPR'; // last token type
    last_text = ''; // last token text
    output = [];
    do_block_just_closed = false;
    var_line = false;
    var_line_tainted = false;
    whitespace = "\n\r\t ".split('');
    wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');
    punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |='.split(' ');
    // words which should always start on new line.
    line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');
    // states showing if we are currently in expression (i.e. "if" case) - 'EXPRESSION', or in usual block (like, procedure), 'BLOCK'.
    // some formatting depends on that.
    current_mode = 'BLOCK';
    modes = [current_mode];
    indent_level = indent_level || 0;
    parser_pos = 0; // parser position
    in_case = false; // flag for parser that case/default has been processed, and next colon needs special attention
    while (true) {
        var t = get_next_token(parser_pos);
        token_text = t[0];
        token_type = t[1];
        if (token_type === 'TK_EOF') {
            break;
        }
        switch (token_type) {
            case 'TK_START_EXPR':
                var_line = false;
                set_mode('EXPRESSION');
                if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR') {
                    // do nothing on (( and )( and ][ and ]( ..
                } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
                    print_space();
                } else if (in_array(last_word, line_starters) && last_word !== 'function') {
                    print_space();
                }
                print_token();
                break;
            case 'TK_END_EXPR':
                print_token();
                restore_mode();
                break;
            case 'TK_START_BLOCK':
                if (last_word === 'do') {
                    set_mode('DO_BLOCK');
                } else {
                    set_mode('BLOCK');
                }
                if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
                    if (last_type === 'TK_START_BLOCK') {
                        print_newline();
                    } else {
                        print_space();
                    }
                }
                print_token();
                indent();
                break;
            case 'TK_END_BLOCK':
                if (last_type === 'TK_START_BLOCK') {
                    // nothing
                    trim_output();
                    unindent();
                } else {
                    unindent();
                    print_newline();
                }
                print_token();
                restore_mode();
                break;
            case 'TK_WORD':
                if (do_block_just_closed) {
                    print_space();
                    print_token();
                    print_space();
                    break;
                }
                if (token_text === 'case' || token_text === 'default') {
                    if (last_text === ':') {
                        // switch cases following one another
                        remove_indent();
                    } else {
                        // case statement starts in the same line where switch
                        unindent();
                        print_newline();
                        indent();
                    }
                    print_token();
                    in_case = true;
                    break;
                }
                prefix = 'NONE';
                if (last_type === 'TK_END_BLOCK') {
                    if (!in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {
                        prefix = 'NEWLINE';
                    } else {
                        prefix = 'SPACE';
                        print_space();
                    }
                } else if (last_type === 'TK_END_COMMAND' && (current_mode === 'BLOCK' || current_mode === 'DO_BLOCK')) {
                    prefix = 'NEWLINE';
                } else if (last_type === 'TK_END_COMMAND' && current_mode === 'EXPRESSION') {
                    prefix = 'SPACE';
                } else if (last_type === 'TK_WORD') {
                    prefix = 'SPACE';
                } else if (last_type === 'TK_START_BLOCK') {
                    prefix = 'NEWLINE';
                } else if (last_type === 'TK_END_EXPR') {
                    print_space();
                    prefix = 'NEWLINE';
                }
                if (last_type !== 'TK_END_BLOCK' && in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {
                    print_newline();
                } else if (in_array(token_text, line_starters) || prefix === 'NEWLINE') {
                    if (last_text === 'else') {
                        // no need to force newline on else break
                        print_space();
                    } else if ((last_type === 'TK_START_EXPR' || last_text === '=') && token_text === 'function') {
                        // no need to force newline on 'function': (function
                        // DONOTHING
                    } else if (last_type === 'TK_WORD' && (last_text === 'return' || last_text === 'throw')) {
                        // no newline between 'return nnn'
                        print_space();
                    } else if (last_type !== 'TK_END_EXPR') {
                        if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && last_text !== ':') {
                            // no need to force newline on 'var': for (var x = 0...)
                            if (token_text === 'if' && last_type === 'TK_WORD' && last_word === 'else') {
                                // no newline for } else if {
                                print_space();
                            } else {
                                print_newline();
                            }
                        }
                    } else {
                        if (in_array(token_text, line_starters) && last_text !== ')') {
                            print_newline();
                        }
                    }
                } else if (prefix === 'SPACE') {
                    print_space();
                }
                print_token();
                last_word = token_text;
                if (token_text === 'var') {
                    var_line = true;
                    var_line_tainted = false;
                }
                break;
            case 'TK_END_COMMAND':
                print_token();
                var_line = false;
                break;
            case 'TK_STRING':
                if (last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK') {
                    print_newline();
                } else if (last_type === 'TK_WORD') {
                    print_space();
                }
                print_token();
                break;
            case 'TK_OPERATOR':
                var start_delim = true;
                var end_delim = true;
                if (var_line && token_text !== ',') {
                    var_line_tainted = true;
                    if (token_text === ':') {
                        var_line = false;
                    }
                }
                if (token_text === ':' && in_case) {
                    print_token(); // colon really asks for separate treatment
                    print_newline();
                    break;
                }
                in_case = false;
                if (token_text === ',') {
                    if (var_line) {
                        if (var_line_tainted) {
                            print_token();
                            print_newline();
                            var_line_tainted = false;
                        } else {
                            print_token();
                            print_space();
                        }
                    } else if (last_type === 'TK_END_BLOCK') {
                        print_token();
                        print_newline();
                    } else {
                        if (current_mode === 'BLOCK') {
                            print_token();
                            print_newline();
                        } else {
                            // EXPR od DO_BLOCK
                            print_token();
                            print_space();
                        }
                    }
                    break;
                } else if (token_text === '--' || token_text === '++') { // unary operators special case
                    if (last_text === ';') {
                        // space for (;; ++i)
                        start_delim = true;
                        end_delim = false;
                    } else {
                        start_delim = false;
                        end_delim = false;
                    }
                } else if (token_text === '!' && last_type === 'TK_START_EXPR') {
                    // special case handling: if (!a)
                    start_delim = false;
                    end_delim = false;
                } else if (last_type === 'TK_OPERATOR') {
                    start_delim = false;
                    end_delim = false;
                } else if (last_type === 'TK_END_EXPR') {
                    start_delim = true;
                    end_delim = true;
                } else if (token_text === '.') {
                    // decimal digits or object.property
                    start_delim = false;
                    end_delim = false;
                } else if (token_text === ':') {
                    // zz: xx
                    // can't differentiate ternary op, so for now it's a ? b: c; without space before colon
                    if (last_text.match(/^\d+$/)) {
                        // a little help for ternary a ? 1 : 0;
                        start_delim = true;
                    } else {
                        start_delim = false;
                    }
                }
                if (start_delim) {
                    print_space();
                }
                print_token();
                if (end_delim) {
                    print_space();
                }
                break;
            case 'TK_BLOCK_COMMENT':
                print_newline();
                print_token();
                print_newline();
                break;
            case 'TK_COMMENT':
                // print_newline();
                print_space();
                print_token();
                print_newline();
                break;
            case 'TK_UNKNOWN':
                print_token();
                break;
            default:
                break;
        }
        last_type = token_type;
        last_text = token_text;
    }
    return output.join('');
}