我的问题
我想清理粘贴在富文本编辑器中的 HTML(目前为 FCK 1.6)。清理应该基于标签的白名单(可能还有另一个带有属性的)。这主要不是为了防止 XSS,而是为了移除丑陋的 HTML。
目前我看不到在服务器上做这件事,所以我想它必须在 JavaScript 中完成。
当前的想法
我找到了jquery-clean 插件,但据我所知,它使用正则表达式来完成这项工作,我们知道这是不安全的。
由于我没有找到任何其他基于 JS 的解决方案,因此我开始使用 jQuery 自己实现一个。它可以通过创建粘贴的 html ( $(pastedHtml)
) 的 jQuery 版本来工作,然后遍历生成的树,通过查看属性删除每个与白名单不匹配的元素tagName
。
我的问题
- 这更好吗?
- 我可以相信 jQuery 能够很好地表示粘贴的内容(可能有不匹配的结束标签和你有什么)?
- 有没有我找不到的更好的解决方案?
更新
这是我当前的基于 jQuery 的解决方案(详细且未经过广泛测试):
function clean(element, whitelist, replacerTagName) {
// Use div if no replace tag was specified
replacerTagName = replacerTagName || "div";
// Accept anything that jQuery accepts
var jq = $(element);
// Create a a copy of the current element, but without its children
var clone = jq.clone();
clone.children().remove();
// Wrap the copy in a dummy parent to be able to search with jQuery selectors
// 1)
var wrapper = $('<div/>').append(clone);
// Check if the element is not on the whitelist by searching with the 'not' selector
var invalidElement = wrapper.find(':not(' + whitelist + ')');
// If the element wasn't on the whitelist, replace it.
if (invalidElement.length > 0) {
var el = $('<' + replacerTagName + '/>');
el.text(invalidElement.text());
invalidElement.replaceWith(el);
}
// Extract the (maybe replaced) element
var cleanElement = $(wrapper.children().first());
// Recursively clean the children of the original element and
// append them to the cleaned element
var children = jq.children();
if (children.length > 0) {
children.each(function(_index, thechild) {
var cleaned = clean(thechild, whitelist, replacerTagName);
cleanElement.append(cleaned);
});
}
return cleanElement;
}
我想知道一些要点(请参阅代码中的注释);
- 我真的需要将我的元素包装在一个虚拟父级中以便能够将它与 jQuery 的 ":not" 匹配吗?
- 这是创建新节点的推荐方法吗?