zoukankan      html  css  js  c++  java
  • 百度编辑器(Ueditor)最新版(1.4.3.3)插入锚点失败原因分析及BUG修复

    用百度编辑器——Ueditor(版本1.4.3.3,2016-05-18日上线)插入锚点的时候,每次总是失败,百思不得其解。通过分析Ueditor的代码ueditor.all.js,可以看出Ueditor插入锚点的过程,实际上是一个img标签和a标签相互转换的过程,其代码如下: 

    'anchor':{
       //cmd:命令字符串,name:锚点名称
       execCommand:function (cmd, name) {
                      var range = this.selection.getRange(),img = range.getClosedNode();
                      if (img && img.getAttribute('anchorname')) {
                          if (name) {
                              img.setAttribute('anchorname', name);
                          } else {
                              range.setStartBefore(img).setCursor();
                              domUtils.remove(img);
                          }
                      } else {
                          if (name) {
                              //只在选区的开始插入
                              var anchor = this.document.createElement('img');
                              range.collapse(true);
                              domUtils.setAttributes(anchor,{
                                  'anchorname':name,
                                  'class':'anchorclass'
                              });
                              range.insertNode(anchor).setStartAfter(anchor).setCursor(false,true);
                          }
                      } 
                               ……

    分析上述代码,插入锚点的过程实际上在Ueditor中显示的时候其实是插入了一个图片(img元素),设置该img的anchorname属性为插入锚点的名字。生成的HTML代码形如”<img class='anchorclass' anchorname='title_01'>“其中“title_01”即为锚点的名字。代码看起来是没有问题的,笔者也多次使用alert调试,运行过程中是可以得到锚点的名称‘name’的值的,但是在编辑器中查看源代码的时候始终没有anchorname属性,于是笔者手动在得到的img标签中写入anchorname的属性值,结果切换到显示界面又切换回HTML界面后,该属性依然丢失,真可谓百思不得其解。接着查看针对插入锚节点时的输入规则(inputRule)和输出规则(outputRule)部分的代码,可以清晰的了解到输出时Ueditor会将拥有anchorname属性的img节点变成a(超级链接)节点,并将该img的anchorname属性值作为'a'的name属性值,这样就完成了一个图像锚像一个真正锚的变换,代码如下:

    outputRule: function(root){
              utils.each(root.getNodesByTagName('img'),function(a){
                  var val;
                  if(val = a.getAttr('anchorname')){
                      a.tagName = 'a';
                      a.setAttr({
                          anchorname : '',
                          name : val,
                          'class' : ''
                      })
                  }
              })
          },

    而输入的时候使用的输入规则(inputRule),是当用户直接在其HTML源码界面中输入锚节点的代码(比如:”<a name="title_01"></a>“)时,当用户切换到显示界面的时候,系统会自动将该锚点转换成图片锚,该图片节点(img节点)的class="anchorclass",anchorname="title_01"(上述锚节点的name属性值),代码如下:

    inputRule:function(root){
               utils.each(root.getNodesByTagName('a'),function(a){
                   var val;
                   if((val = a.getAttr('name')) && !a.getAttr('href')){
                       a.tagName = 'img';
                       a.setAttr({
                           anchorname :a.getAttr('name'),
                           'class' : 'anchorclass'
                       });
                       a.setAttr('name')
                   }
               })
           },

    这样用户看起来就有一个锚的图片在刚才插入锚的地方,而保存的时候仍然会使用outputRule,将该图片变成一个真正的锚。

    代码的实现看起来一点问题也没有,可是为什么就是插入不了锚呢(实质上是在img节点中,无论如何也插入不了anchorname属性,这点我在官网也尝试过,也不行,可以说结结实实是个BUG)。

    正当我以为该问题无解的时候,我突然发现原来在使用Ueditor的时候,除了引入了Ueditor.all.js外还引入了一个配置文件Ueditor.config.js,我觉得看看这个文件的代码,这一下,终于被我找到了原因所在。原来在这个配置文件中定义了每个HTML标签的过滤规则,也就是某个HTML标签只能有哪些属性,所以当我们加入其他属性的时候是会被编辑器过滤掉的,比如我给img添加的achorename属性(也就是上述程序在讲锚转换成图片的时候要插入的属性),因为在img的属性过滤的白名单中是没有该属性的,所以照成了插入的失败,也照成了编辑器插入锚节点时出现的BUG。同样,笔者还发现在‘a’标签的白名单中是没有‘name’属性的,也就是编辑器默认情况下是不能插入锚点的,将上述两个属性加入到配置文件中,问题得解,可以自由的插入任何锚节点了。下面附上修改后的img和a标签的白名单:

    // xss 过滤是否开启,inserthtml等操作

    ,xssFilterRules: true

    //input xss过滤

    ,inputXssFilter: true

    //output xss过滤

    ,outputXssFilter: true

    // xss过滤白名单 名单来源: https://raw.githubusercontent.com/leizongmin

    /js-xss/master/lib/default.js

    ,whitList: {

    a:      ['target', 'href', 'title', 'class', 'style','name'],

    ……

    img:    ['src', 'alt', 'title', 'width', 'height', 'id', '_src', 

              'loadingclass', 'class','anchorname']

    当然还有其他的一些白名单,由于和本主题无关就不再一一罗列。以上就是我解决Ueditor插入锚点BUG的过程,也许您有更好的方法,请给我留言,谢谢!

    本文首发于顶求网,转载请注明来源。

  • 相关阅读:
    jquery 序列化form表单
    nginx for windows 安装
    nodejs idea 创建项目 (一)
    spring 配置 shiro rememberMe
    idea 2018 解决 双击shift 弹出 search everywhere 搜索框的方法
    redis 在windows 集群
    spring IOC控制反转和DI依赖注入
    redis 的安装
    shiro 通过jdbc连接数据库
    handlebars的用法
  • 原文地址:https://www.cnblogs.com/nerd/p/5671793.html
Copyright © 2011-2022 走看看