#javascript #angularjs #angularjs-filter
#javascript #angularjs #angularjs-фильтр
Вопрос:
Я пытаюсь автоматически вставлять видео YouTube для пользовательского контента. Мой фильтр ищет ссылки в целом, а затем проверяет их, чтобы увидеть, являются ли они действительными видеороликами YouTube. Если это так, он должен встроить видео со стандартным кодом iframe. Если нет, то это просто ссылка. Однако фильтр вообще не выводит код iframe. Я предполагаю, что это как-то предотвращает атаки с использованием межсайтовых скриптов, но я понятия не имею, как я могу это обойти.
function ytVidId(url) {
var p = /^(?:https?://)?(?:www.)?(?:youtu.be/|youtube.com/(?:embed/|v/|watch?v=|watch?. amp;v=))((w|-){11})(?:S )?$/;
return (url.match(p)) ? RegExp.$1 : false;
}
myapp.filter('parseUrls', function() {
//with protocol
var urlPattern = /(http|ftp|https)://[w-] (.[w-] ) ([w.,@?^=%amp;amp;:/~ #-]*[w@?^=%amp;amp;/~ #-])?/gi;
return function(text, target, otherProp) {
if (text == null) {
return "";
}
angular.forEach(text.match(urlPattern), function(url) {
if(ytVidId(url)){
text = text.replace(url, '<div class="video-container"><iframe src="//www.youtube.com/embed/' ytVidId(url) '" frameborder="0" width="560" height="315"></iframe></div>');
}else{
text = text.replace(url, '<a target="' target '" href=' url '>' url '</a>');
}
});
return text;
};
})
Используется:
<span ng-bind-html="p.body | noHTML | newlines | parseUrls:'_blank'"></span>
Ответ №1:
Angular требует, чтобы вы передавали HTML через поставщика ‘sce’ (строгое контекстное экранирование).
Документация по поставщику SCE здесь
Так что это будет выглядеть примерно так (непроверено, но теоретически так и должно быть)
function ytVidId(url) {
var p = /^(?:https?://)?(?:www.)?(?:youtu.be/|youtube.com/(?:embed/|v/|watch?v=|watch?. amp;v=))((w|-){11})(?:S )?$/;
return (url.match(p)) ? RegExp.$1 : false;
}
myapp.filter('parseUrls', ['$sce', function() {
//with protocol
var urlPattern = /(http|ftp|https)://[w-] (.[w-] ) ([w.,@?^=%amp;amp;:/~ #-]*[w@?^=%amp;amp;/~ #-])?/gi;
return function(text, target, otherProp) {
if (text == null) {
return "";
}
angular.forEach(text.match(urlPattern), function(url) {
if(ytVidId(url)){
text = text.replace(url, $sce.trustAs('html', '<div class="video-container"><iframe src="//www.youtube.com/embed/' ytVidId(url) '" frameborder="0" width="560" height="315"></iframe></div>'));
}else{
text = text.replace(url, $sce.trustAs('html', '<a target="' target '" href=' url '>' url '</a>'));
}
});
return text;
};
}])`
Комментарии:
1. Это было довольно близко. Я действительно обнаружил, что конвейер в этом фильтре работал … .filter(‘unsafe’, function($sce) { return function(val) { return $sce.trustAsHtml(val); }; })