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标准的对象, 虽然实现起来相比第一种方法要复杂一些, 但这换来了更轻松的代码维护工作.


  • 2018-12-16 18:14:23

    Android在代码中设置状态栏半透明/全透明

    顶部是有文字,小图标等,如果直接用透明半透明 状态栏上的东西会与内容重叠(你觉得无所谓也可以直接用上面2部分代码),这样我们就想做成类似支付宝这样的效果:

  • 2018-12-18 15:33:01

    <![CDATA[]]>和转义字符

      此标记用于xml文档中,我们先来看看使用转义符的情况。我们知道,在xml中,”<”、”>”、”&”等字符是不能直接存入的,否则xml语法检查时会报错,如果想在xml中使用这些符号,必须将其转义为实体,如”&lt;”、”&gt;”、”&amp;”,这样才能保存进xml文档。

  • 2018-12-26 15:06:00

    PHP-FPM运行状态的实时查看及监控详解

    php-fpm和nginx一样内建了一个状态页,对于想了解php-fpm的状态以及监控php-fpm非常有帮助。这篇文章就给大家详细介绍了PHP-FPM运行状态的实时查看及监控,有需要的朋友们可以参考学习,感兴趣的朋友们下面来一起看看吧。

  • 2018-12-26 16:12:56

    nginx+php-fpm模式php内存泄漏探究

    这里要重点说一下第三步骤。第三步涉及到php-fpm进程生命周期的东西。一个php-fpm的生命周期大致是这样的:模块初始化(MINIT)-> 模块激活(RINIT)-> 请求处理 -> 模块停用(RSHUTDOWN) -> 模块激活(RINIT)-> 请求处理 -> 模块停用(RSHUTDOWN)……. 模块激活(RINIT)-> 请求处理 -> 模块停用(RSHUTDOWN)-> 模块关闭(MSHUTDOWN)。在一个php-fpm进程的生命周期里,会有多次的模块激活(RINIT)-> 请求处理 -> 模块停用(RSHUTDOWN)的过程。这个“请求处理”的大致过程是这样的:php读取相应的php文件,对其进行词法分析,生成opcode,zend虚拟机执行opcode。

  • 2019-01-01 21:38:51

    php使用curl设置超时的重要性

    网站登录不了,原因是没有可用的 PHP 子进程来响应新的请求了。这可能是是由于PHP-curl 没有设置超时时间引起的。