contenteditable去除html标签

2021-01-18 13:52:18

有时候我们实现了div的contenteditable属性,但是粘贴的时候有时候会携带html语句。我们需要去掉。

最近把Reader项目的评论框从textarea换成div了, 实现元素的自增高确实方便了, 但随之而来的却是更多的麻烦.

比如, div[contenteditable=true]元素的内容可以是HTML代码, 虽然直接输入不行, 但从网页上复制内容到编辑框却是可以的, 这带来了2个问题:

  1. 评论框的内容不统一, 排版混乱, 影响用户体验, 并且评论框本身期望的内容就是纯文字.

  2. 允许HTML代码提交会存在安全方面的问题.

原先的textarea在这方面就完全不用顾虑, 因为它可输入的内容就只有纯文字, 而且还支持input等表单元素特有的事件.

对于div[contenteditable=true], 我们需要用很多的代码将其实现成一个编辑器, 这对于快速开发的项目而言, 太不合适了, 那怎么办? 退回textarea吗? 若是退回textarea, 就无法轻松实现一些高级的功能, 而且这两种元素差别挺大, 并不方便切换.

所以有这样一种方法, 移除div[contenteditable=true]中的不安全HTML标签:


text = text.replace(/<[\/\s]*(?:(?!div|br)[^>]*)>/g,'')


这段代码会移除除了div和br以外的所有HTML标签, 但我们需要在用户输入时执行它, 所以免不了额外的计算消耗.

需要执行这段代码的事件有blur, paste, keyup, 而且在触发之前可能还需要设置一个timeout, 不然就无法获取到内容. 这些都不是实现功能的最大障碍, 最要命的是我们使用到了正则表达式, 这种东西极难维护, 后患无穷.

实际上, 上面代码给出的正则表达式还留有一个问题, 即无法去除div标签的属性.

所以我不得不再加上另外两行代码:

text = text.replace(/<[\/\s]*(?:(?!div|br)[^>]*)>/g, '')text = text.replace(/<\s*div[^>]*>/g, '<div>')text = text.replace(/<[\/\s]*div[^>]*>/g, '</div>')


也许这里还存在着一些其他的漏洞, 我只想告诉你, 这真的不是一个好的解决方案.

 

另一个解决方案是获取剪切板的纯文本内容, 然后将内容插入到编辑框中, 这样就避免了HTML代码的输入. 该代码只在现代浏览器中可以执行, 对于旧版本的浏览器, 可能需要另设兼容方案:

var clipboard = e.clipboardData,text = clipboard.getData('text/plain'),sel = window.getSelection();if(sel.getRangeAt && sel.rangeCount){var range = sel.getRangeAt(0),frag = document.createDocumentFragment(),node,lastNode;range.deleteContents();var ele = document.createElement("div");ele.innerHTML = text;while(node = el.firstChild){lastNode = frag.appendChild(node);}range.insertNode(frag);if(lastNode){range = range.cloneRange();range.setStartAfter(lastNode);range.collapse(true);sel.removeAllRanges();sel.addRange(range);}}


这段代码需要放在未调用settimeout的paste事件中(beforepaste), 否则将无法获得剪切板内容, 执行完毕后别忘了取消浏览器的默认事件.

这里用到了clipboardData, Selection, Range等W3C标准的对象, 虽然实现起来相比第一种方法要复杂一些, 但这换来了更轻松的代码维护工作.


  • 2017-09-11 11:30:09

    linux 获取经过N层Nginx转发的访问来源真实IP

    通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了nginx作为反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址。如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下:

  • 2017-09-11 16:15:11

    Nginx日志管理

    通过访问日志,你可以得到用户地域来源、跳转来源、使用终端、某个URL访问量等相关信息;通过错误日志,你可以得到系统某个服务或server的性能瓶颈等。因此,将日志好好利用,你可以得到很多有价值的信息。

  • 2017-09-11 16:34:14

    Nginx如何保留真实IP和获取前端IP

    squid,varnish以及nginx等,在做反向代理的时候,因为要代替客户端去访问服务器,所以,当请求包经过反向代理后,在代理服务器这里这个IP数据包的IP包头做了修改,最终后端web服务器得到的数据包的头部的源IP地址是代理服务器的IP地址,这样一来,后端服务器的程序给予IP的统计功能就没有任何意义,所以在做代理或集群的时候必须解决这个问题,这里,我以nginx做集群或代理的时候如何给后端web服务器保留(确切的说是传递)客户端的真实IP地址。

  • 2017-09-11 16:35:22

    ngx_http_realip_module使用详解

    网络上关于ngx_http_realip_module的文章千篇一律,全是在说怎么安装,最多贴一个示例配置,却没有说怎么用,为什么这么用,官网文档写得也十分简略,于是就自己探索了一下。

  • 2017-09-11 16:39:43

    基于Nginx dyups模块的站点动态上下线

    在分布式服务下,我们会用nginx做负载均衡, 业务站点访问某服务站点的时候, 统一走nginx, 然后nginx根据一定的轮询策略,将请求路由到后端一台指定的服务器上。

  • 2017-09-13 13:49:21

    Web性能测试:工具之Siege详解

    Siege是一款开源的压力测试工具,设计用于评估WEB应用在压力下的承受能力。可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。siege可以从您选择的预置列表中请求随机的URL。所以siege可用于仿真用户请求负载,而ab则不能。但不要使用siege来执行最高性能基准调校测试,这方面ab就准确很多

  • 2017-09-14 10:18:25

    15分钟成为Git专家

    不管是以前使用过 Git 还是刚开始使用这个神奇的版本控制工具的开发者,阅读了本文以后都会收获颇丰。如果你是应一名有经验的 GIT 使用者,你会更好的理解 checkout -> modify -> commit 这个过程。如果你刚开始使用 Git,本文将给你一个很好的开端。