作者:Tony Qu

本章我们将来说一说filterPasteData函数的实现。

上篇中提到我们采用的粘贴方式是浏览器自己提供的,只是使用了不少技巧,使得粘贴的东西不直接进入Html编辑器的iframe,所以从某种意义上讲,我们获得的粘贴数据内容都是html。根据我们之前所说的三种需求,文本、html以及Word内容,我们可以把过滤的内容分为两大类:

a. html

b. Word xml

之所以纯文本可以当做html就是因为贴进来就是当html处理了,只不过是不带标签的html。

说到过滤,自然要做匹配和替换,于是我们很自然的想到了正则表达式,先来处理比较简单的html过滤。我定义了以下一些规则:

* 移除html, body, form, doctype, head, script,style, textarea, button,select, option, input,span标签

* 移除id, name, class, language,type属性

* 移除on开头的属性,如onclick

* 移除a, table, tr,td,tbody, thead, th, img,input,iframe, div标签(我们的系统中不支持table)

* 移除换行符(\n, \r)

以上这些标签都是要移除的对象,因为它们并没有给系统带来任何好处,还会降低安全性。当然根据实际需要,你可以适当保留一些标签,比如select, button, input, img, table等 function FilterPasteText(str)

{

str = str.replace(/\r\n|\n|\r/ig, "");

//remove html body form

str = str.replace(/])[^>]*>/ig, "");

//remove doctype

str = str.replace(//ig, "");

//remove xml tags

str = str.replace(/]))[^>]*>/gi,"");

//remove head

str = str.replace(/

]*>(\n|.)*?/ig, "");

//remove

str = str.replace(//ig, "");

//remove empty span

str = str.replace(/]*?>/ig, "");

//remove ...

str = str.replace(/]*>(\n|.)*?/ig, "");

//remove table and tag, tag, tag (this can help filter unclosed tag)

str = str.replace(/]*>/ig, "");

//remove bad attributes

do {

len = str.length;

str = str.replace(/(]*\s)(?:id|name|language|type|class|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi, "$1");

} while (len != str.length);

return str;

}

这里str.replace(/]*>([\s\S]+)/ig, “$2”)的意思是保留里面的内容,但是移除标签本身。

这里str.replace(//ig, "");的意思是移除input标签。

以下是一些测试数据

替换前

替换后

abc

...

...

abc

abc

abccde

好了,接下来就来讲word xml的过滤。要想过滤word xml就必须知道当前贴进来的是word的数据,而非普通html,tinymce使用了一个技巧,如下:

function IsWordDocument(strValue)

{

var re=new RegExp(/(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/ig);

return re.test(strValue);

}

只要是从Word贴过来的都会有这样的标记:class=”MsoNormal”或或style=”mso-font-charset:0”

一旦检测到这样的标签,就可以认为这是从Word粘贴过来的,当然如果有人特别无聊,故意做了这样的标签或样式贴进来也没关系,因为过滤器会把没有用的东西过滤掉,那些不在规则里面的不管你是Word数据还是html数据,都尽量保留。

Word的过滤会比普通的html复杂很多,主要原因还是浏览器自动贴进来的word xml保留了很多东西,通常一段十分简单的文本数据,通过word xml表示可能字符长度要达到上万。

举个例子:这里有一段很简单的Word文本,如下

它对应的粘贴结果却是下面这么一大段,是不是很恐怖?

Abcde

l你好

lAaaaaaaaaaaaaa

lBbbbbbbbbbb

lCcccccccccccc

如果你原来只允许用户输入1000个字符,你在数据库里面只给了nvarchar(1000),这就意味着这东西保存进去必然会被截断,而且可能连正文部分都没保存进去,这肯定是不允许的。这也解释了为什么主流html编辑器提供了专门的Word粘贴功能。

上面那段东西其实真正有用的东西也就是下面这么点:

Abcde

l你好

lAaaaaaaaaaaaaa

lBbbbbbbbbbb

lCcccccccccccc

所以这就是我们需要的过滤结果,接下来就看你JavaScript正则表达式有多牛了!

我主要设置了以下这些规则:

1. 去除\r\n, \n, \r

2. 去除文本开头的 和文本结尾的

3. 去除Word的条件注释(如)

4. 去除script, xml:*, img, meta,link, style, *:*标签

5. 将Word的抬头转换成标签

6. 去除lang属性

7. 去除或替换所有没有意义的样式标签,如mso-padding-alt, mso-margin-top-alt,horiz-align, mso-default-width, mso-zero-height等

对应代码如下:

function FilterPasteWord(str)

{

//remove link break

str = str.replace(/\r\n|\n|\r/ig, "");

//remove   entities at the start of contents

str = str.replace(/^\s*( )+/ig,"");

//remove   entities at the end of contents

str = str.replace(/( |
]*>)+\s*$/ig,"");

// Word comments like conditional comments etc

str = str.replace(//ig, "");

// Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags

str = str.replace(/]*>.*?\s])|\/?(\?xml(:\w+)?|xml|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,"");

//convert word headers to strong

str = str.replace(/

]*class="?MsoHeading"?[^>]*>(.*?)/gi, "

$1");

//remove lang attribute

str = str.replace(/(lang)\s*=\s*([\'\"]?)[\w-]+\2/ig, "");

// Examine all styles: delete junk, transform some, and keep the rest

str = str.replace(/(]*)\sstyle="([^"]*)"/gi,function(str, tag, style) {

var n = [],

i = 0,

s = style.trim().replace(/"/gi, "'").split(";");

// Examine each style definition within the tag's style attribute

for(var i=0;i

{

v=s[i];

var name, value,

parts = v.split(":");

if (parts.length == 2) {

name = parts[0].toLowerCase();

value = parts[1].toLowerCase();

// Translate certain MS Office styles into their CSS equivalents

switch (name) {

case "mso-padding-alt":

case "mso-padding-top-alt":

case "mso-padding-right-alt":

case "mso-padding-bottom-alt":

case "mso-padding-left-alt":

case "mso-margin-alt":

case "mso-margin-top-alt":

case "mso-margin-right-alt":

case "mso-margin-bottom-alt":

case "mso-margin-left-alt":

case "mso-table-layout-alt":

case "mso-height":

case "mso-width":

case "mso-vertical-align-alt":

n[i++] = name.replace(/^mso-|-alt$/g, "") + ":" + ensureUnits(value);

continue;

case "horiz-align":

n[i++] = "text-align:" + value;

continue;

case "vert-align":

n[i++] = "vertical-align:" + value;

continue;

case "font-color":

case "mso-foreground":

n[i++] = "color:" + value;

continue;

case "mso-background":

case "mso-highlight":

n[i++] = "background:" + value;

continue;

case "mso-default-height":

n[i++] = "min-height:" + ensureUnits(value);

continue;

case "mso-default-width":

n[i++] = "min-; + ensureUnits(value);

continue;

case "mso-padding-between-alt":

n[i++] = "border-collapse:separate;border-spacing:" + ensureUnits(value);

continue;

case "text-line-through":

if ((value == "single") || (value == "double")) {

n[i++] = "text-decoration:line-through";

}

continue;

case "mso-zero-height":

if (value == "yes") {

n[i++] = "display:none";

}

continue;

}

// Eliminate all MS Office style definitions that have no CSS equivalent by examining the first characters in the name

if (/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?:align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(name)) {

continue;

}

// If it reached this point, it must be a valid CSS style

n[i++] = name + ":" + parts[1]; // Lower-case name, but keep value case

}

}

// If style attribute contained any valid styles the re-write it; otherwise delete style attribute.

if (i > 0) {

return tag + ' style="' + n.join(';') + '"';

} else {

return tag;

}

});

return str;

}

到此,你应该对这项技术有了很详细的了解了。当然具体过滤哪些东西,你还是要多实践多测试,比如前两天客户一不小心把youtube视频贴近系统里面了,于是我又过滤了object, embed, param标签。当然有了这样一个模型之后,规则的维护变得很方便,无形中降低了代码的维护成本。

在线html过滤,在线Html编辑器粘贴过滤技术详解(二)相关推荐

  1. for根据ID去重_汽车ECU参数标定之配置Overlay RAM实现Qorivva MPC57xx系列MCU参数在线标定和代码重映射原理和方法详解...

    内容提要 引言 1. MPC5744P的Overlay RAM工作原理介绍 2 MPC5744P的Flash Overlay配置详解 2.1 平台Flash标定区域描述字寄存器配置字0--PFLASH ...

  2. 【Linux练习生】Linux编辑器-vim使用(详解)

    vim使用 1. vim的基本概念 2. vim的基本操作 2.vim正常模式命令集 4. vim末行模式命令集 5.vim多行操作 常用命令选项: – the End – vi/vim区别: vi/ ...

  3. asp.net文本编辑器FCKeditor使用方法详解 - 橙色大地 - 博客园

    asp.net文本编辑器FCKeditor使用方法详解 效果图: 那么为什么说是FCKeditor的冰冷之心呢?这不是哗众取宠,主要是说它使用起来有点麻烦,下文就详细说明如何搞定这玩意儿. 1.FCK ...

  4. Linux——文本编辑器(Vi)详解介绍

    Linux--文本编辑器(Vi)详解介绍 1.Vi的简介 Vi是Visual interface的简称,可以执行输出.删除.查找.替换.块操作等众多文本操作,而且用户根据自己的需要对其进行制定,这是v ...

  5. 在线公开课 | 从理论走向实践,多角度详解Cloud Native

    戳蓝字"CSDN云计算"关注我们哦! 本次直播课程是由京东云产品研发部中间件负责人李道兵从Cloud Native概念入手到实践出发,深度解析了Cloud Native年度热词背后 ...

  6. Python中过滤序列内置函数filter()的详解(常用)

    目录 一.功能 二.语法 三.举例 3.1代码 3.2运行结果 一.功能   用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换. https: ...

  7. python3 在线加密_Python3对称加密算法AES、DES3实例详解

    本文实例讲述了Python3对称加密算法AES.DES3.分享给大家供大家参考,具体如下: python3.6此库安装方式,需要pip3 install pycryptodome. 如有site-pa ...

  8. php 密码过滤,PHP实践教程之过滤、验证、转义与密码详解

    本文主要给大家介绍的是关于PHP实践之过滤.验证.转义与密码等相关的内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 一.过滤.验证和转义 1).不要相信任何来自不受自己直接控制的 ...

  9. python读取html文件正则替换_Python使用正则表达式过滤或替换HTML标签的方法详解...

    本文实例讲述了Python使用正则表达式过滤或替换HTML标签的方法.分享给大家供大家参考,具体如下: python正则表达式关键内容: python正则表达式转义符: . 匹配除换行符以外的任意字符 ...

最新文章

  1. 微软官方工具MediaCreationTool制作U盘Windows10启动盘教程
  2. 动态ram依靠什么存储信息_处理器内存系统1(ROM,RAM,数据存储顺序)
  3. getresourceasstream方法_【设计模式】第三篇:一篇搞定工厂模式【简单工厂、工厂方法模式、抽象工厂模式】...
  4. if( 1 == x ) 比 if( x == 1 ) 哪个好
  5. bzoj 4563 [Haoi2016]放棋子 错位排列+高精度
  6. KVM halt-polling机制分析
  7. 每一次结束只是一次新的起点,深有体会。
  8. wifi小程序源码流量主源码
  9. IP地址是如何分配的
  10. 外卖系统源码,如何搭建一套同城o2o外卖商城平台
  11. TP-LINK路由器手动设置网关、DNS、开启DHCP并指定地址池IP范围
  12. [转载]中国书法:中华文化的代表性符号
  13. 聊聊新西兰的工作和生活
  14. Android 仿微信实现语音聊天功能
  15. Pycharm提示“typo:in word“的意思
  16. 整合dubbo报错严重 Exception sending context initialized event to listener instance of class 解决
  17. Epub文件解析库-- Epublib
  18. pip离线安装第三方包
  19. 【公平锁和非公平锁有什么区别?】
  20. 《纽约时报》发文评选掀起区块链革命的10位代表性人物,吴忌寒上榜

热门文章

  1. 北向资金能预示大盘涨跌?【附Python源码】
  2. [C语言简明教程] 指针的进阶(上)
  3. 32位 和 64位系统区别
  4. Cache-Control浏览器缓存
  5. 数理基础(高等代数)------sympy三角、指数、对数、幂函数、极限、求导、微分、积分等基础知识
  6. 张玉成科学院计算机所,石晶林-中国科学院大学-UCAS
  7. 一线城市运营成本虚高,中小城市成餐饮版图扩展新动向
  8. qzwxecasd测试1234
  9. apple pencil必须要买吗?性价比平替电容笔排行榜
  10. java 加单引号_【沫沫金】Java逗号拼接字符串增加单引号