Моя проблема
Я хочу очистить HTML, вставленный в текстовый редактор (сейчас FCK 1.6). Очистка должна проводиться на основе белого списка тегов (и, возможно, другого списка с атрибутами). Это в первую очередь не для предотвращения XSS, а для удаления уродливого HTML.
В настоящее время я не вижу возможности сделать это на сервере, поэтому полагаю, что это нужно делать на JavaScript.
Текущие идеи
Я нашел плагин jquery-clean, но, насколько я понимаю, он использует регулярные выражения для выполнения своей работы, и мы знаю, что это небезопасно.
Поскольку я не нашел другого решения на основе JS, я сам начал его использовать, используя jQuery. Он будет работать, создав jQuery-версию вставленного HTML ($(pastedHtml)
), а затем пройдя по результирующему дереву, удалив каждый элемент, не соответствующий белому списку, просмотрев атрибут 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"?
- Это рекомендуемый способ создания нового узла?