+ process([\r
+ // Word comments like conditional comments etc\r
+ /<!--[\s\S]+?-->/gi,\r
+\r
+ // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags\r
+ /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,\r
+\r
+ // Convert <s> into <strike> for line-though\r
+ [/<(\/?)s>/gi, "<$1strike>"],\r
+\r
+ // Replace nsbp entites to char since it's easier to handle\r
+ [/ /gi, "\u00a0"]\r
+ ]);\r
+\r
+ // Remove bad attributes, with or without quotes, ensuring that attribute text is really inside a tag.\r
+ // If JavaScript had a RegExp look-behind, we could have integrated this with the last process() array and got rid of the loop. But alas, it does not, so we cannot.\r
+ do {\r
+ len = h.length;\r
+ h = h.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi, "$1");\r
+ } while (len != h.length);\r
+\r
+ // Remove all spans if no styles is to be retained\r
+ if (getParam(ed, "paste_retain_style_properties").replace(/^none$/i, "").length == 0) {\r
+ h = h.replace(/<\/?span[^>]*>/gi, "");\r
+ } else {\r
+ // We're keeping styles, so at least clean them up.\r
+ // CSS Reference: http://msdn.microsoft.com/en-us/library/aa155477.aspx\r
+\r
+ process([\r
+ // Convert <span style="mso-spacerun:yes">___</span> to string of alternating breaking/non-breaking spaces of same length\r
+ [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,\r
+ function(str, spaces) {\r
+ return (spaces.length > 0)? spaces.replace(/./, " ").slice(Math.floor(spaces.length/2)).split("").join("\u00a0") : "";\r
+ }\r
+ ],\r
+\r
+ // Examine all styles: delete junk, transform some, and keep the rest\r
+ [/(<[a-z][^>]*)\sstyle="([^"]*)"/gi,\r
+ function(str, tag, style) {\r
+ var n = [],\r
+ i = 0,\r
+ s = explode(trim(style).replace(/"/gi, "'"), ";");\r
+\r
+ // Examine each style definition within the tag's style attribute\r
+ each(s, function(v) {\r
+ var name, value,\r
+ parts = explode(v, ":");\r
+\r
+ function ensureUnits(v) {\r
+ return v + ((v !== "0") && (/\d$/.test(v)))? "px" : "";\r
+ }\r
+\r
+ if (parts.length == 2) {\r
+ name = parts[0].toLowerCase();\r
+ value = parts[1].toLowerCase();\r
+\r
+ // Translate certain MS Office styles into their CSS equivalents\r
+ switch (name) {\r
+ case "mso-padding-alt":\r
+ case "mso-padding-top-alt":\r
+ case "mso-padding-right-alt":\r
+ case "mso-padding-bottom-alt":\r
+ case "mso-padding-left-alt":\r
+ case "mso-margin-alt":\r
+ case "mso-margin-top-alt":\r
+ case "mso-margin-right-alt":\r
+ case "mso-margin-bottom-alt":\r
+ case "mso-margin-left-alt":\r
+ case "mso-table-layout-alt":\r
+ case "mso-height":\r
+ case "mso-width":\r
+ case "mso-vertical-align-alt":\r
+ n[i++] = name.replace(/^mso-|-alt$/g, "") + ":" + ensureUnits(value);\r
+ return;\r
+\r
+ case "horiz-align":\r
+ n[i++] = "text-align:" + value;\r
+ return;\r
+\r
+ case "vert-align":\r
+ n[i++] = "vertical-align:" + value;\r
+ return;\r
+\r
+ case "font-color":\r
+ case "mso-foreground":\r
+ n[i++] = "color:" + value;\r
+ return;\r
+\r
+ case "mso-background":\r
+ case "mso-highlight":\r
+ n[i++] = "background:" + value;\r
+ return;\r
+\r
+ case "mso-default-height":\r
+ n[i++] = "min-height:" + ensureUnits(value);\r
+ return;\r
+\r
+ case "mso-default-width":\r
+ n[i++] = "min-width:" + ensureUnits(value);\r
+ return;\r
+\r
+ case "mso-padding-between-alt":\r
+ n[i++] = "border-collapse:separate;border-spacing:" + ensureUnits(value);\r
+ return;\r
+\r
+ case "text-line-through":\r
+ if ((value == "single") || (value == "double")) {\r
+ n[i++] = "text-decoration:line-through";\r
+ }\r
+ return;\r
+\r
+ case "mso-zero-height":\r
+ if (value == "yes") {\r
+ n[i++] = "display:none";\r
+ }\r
+ return;\r
+ }\r