当前位置: 首页 > news >正文

百度编辑器(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的过程,也许您有更好的方法,请给我留言,谢谢!

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

转载于:https://www.cnblogs.com/nerd/p/5671793.html

相关文章:

  • Restore Volume 操作 - 每天5分钟玩转 OpenStack(60)
  • jsp页面实现局部刷新
  • k8s如何管理Pod
  • 全屏无标题栏解决方法
  • SQL Server 2008 中SQL查询语句中字段值不区分大小写问题处理
  • 初识JavaScript
  • iOS: 如何调节UITabbarItem的图片和文字位置
  • Python学习笔记——文件写入和读取
  • C/C++动态分配与释放内存的区别详细解析
  • I.MX6 简单电路模拟USB设备的插入
  • MySQL备份 博客---MYSQLDBA 黄杉
  • java-工具-Webservice wsdl解析
  • 重定向 管道
  • [ZigBee] 16、Zigbee协议栈应用(二)——基于OSAL的无线控制LED闪烁分析(下)
  • 微信公众号开发小记——5.python微信红包
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • ESLint简单操作
  • Java 内存分配及垃圾回收机制初探
  • Java精华积累:初学者都应该搞懂的问题
  • Java-详解HashMap
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • learning koa2.x
  • MySQL用户中的%到底包不包括localhost?
  • python大佬养成计划----difflib模块
  • SQLServer插入数据
  • Vue学习第二天
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 从零搭建Koa2 Server
  • 大数据与云计算学习:数据分析(二)
  • 分享一份非常强势的Android面试题
  • 欢迎参加第二届中国游戏开发者大会
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 在weex里面使用chart图表
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​Java并发新构件之Exchanger
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (c语言)strcpy函数用法
  • (ibm)Java 语言的 XPath API
  • (LeetCode) T14. Longest Common Prefix
  • (Python第六天)文件处理
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (ZT)薛涌:谈贫说富
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转) 深度模型优化性能 调参
  • ***监测系统的构建(chkrootkit )
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .NET精简框架的“无法找到资源程序集”异常释疑
  • .考试倒计时43天!来提分啦!