disallow nested links in DOMfilter (fixes #680)
This commit is contained in:
parent
8e43758c2e
commit
d1176a5b2b
2 changed files with 33 additions and 1 deletions
|
@ -61,10 +61,15 @@ weechat.filter('inlinecolour', function() {
|
||||||
|
|
||||||
// apply a filter to an HTML string's text nodes, and do so with not exceedingly terrible performance
|
// apply a filter to an HTML string's text nodes, and do so with not exceedingly terrible performance
|
||||||
weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) {
|
weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) {
|
||||||
|
// To prevent nested anchors, we need to know if a filter is going to create them.
|
||||||
|
// Here's a list of names. See #681 for more information.
|
||||||
|
var filtersThatCreateAnchors = ['irclinky'];
|
||||||
|
|
||||||
return function(text, filter) {
|
return function(text, filter) {
|
||||||
if (!text || !filter) {
|
if (!text || !filter) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
var createsAnchor = filtersThatCreateAnchors.indexOf(filter) > -1;
|
||||||
|
|
||||||
var escape_html = function(text) {
|
var escape_html = function(text) {
|
||||||
// First, escape entities to prevent escaping issues because it's a bad idea
|
// First, escape entities to prevent escaping issues because it's a bad idea
|
||||||
|
@ -92,6 +97,7 @@ weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) {
|
||||||
// as innerHTML causes it to be unescaped.
|
// as innerHTML causes it to be unescaped.
|
||||||
var input = escape_html(node.nodeValue);
|
var input = escape_html(node.nodeValue);
|
||||||
var value = filterFunction(input, extraArgument, thirdArgument);
|
var value = filterFunction(input, extraArgument, thirdArgument);
|
||||||
|
|
||||||
if (value !== input) {
|
if (value !== input) {
|
||||||
// we changed something. create a new node to replace the current one
|
// we changed something. create a new node to replace the current one
|
||||||
// we could also only add its children but that would probably incur
|
// we could also only add its children but that would probably incur
|
||||||
|
@ -114,7 +120,11 @@ weechat.filter('DOMfilter', ['$filter', '$sce', function($filter, $sce) {
|
||||||
if (node === undefined || node === null) return;
|
if (node === undefined || node === null) return;
|
||||||
node = node.firstChild;
|
node = node.firstChild;
|
||||||
while (node) {
|
while (node) {
|
||||||
var nextNode = process(node);
|
var nextNode;
|
||||||
|
// do not recurse inside links if the filter would create a nested link
|
||||||
|
if (!(createsAnchor && node.tagName === 'A')) {
|
||||||
|
nextNode = process(node);
|
||||||
|
}
|
||||||
node = (nextNode ? nextNode : node).nextSibling;
|
node = (nextNode ? nextNode : node).nextSibling;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,13 @@ describe('Filters', function() {
|
||||||
it('should not mess up IRC channels surrounded by HTML entities', inject(function(irclinkyFilter) {
|
it('should not mess up IRC channels surrounded by HTML entities', inject(function(irclinkyFilter) {
|
||||||
expect(irclinkyFilter('<"#foo">')).toEqual('<"<a href="#" onclick="openBuffer(\'#foo">\');">#foo"></a>');
|
expect(irclinkyFilter('<"#foo">')).toEqual('<"<a href="#" onclick="openBuffer(\'#foo">\');">#foo"></a>');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should not touch links created by `linky`', inject(function(linkyFilter, DOMfilterFilter) {
|
||||||
|
var url = 'http://foo.bar/#baz',
|
||||||
|
link = linkyFilter(url, '_blank'),
|
||||||
|
result = DOMfilterFilter(link, 'irclinky').$$unwrapTrustedValue();
|
||||||
|
expect(result).toEqual(link);
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('inlinecolour', function() {
|
describe('inlinecolour', function() {
|
||||||
|
@ -62,4 +69,19 @@ describe('Filters', function() {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('DOMfilter', function() {
|
||||||
|
it('should run a filter on all text nodes', inject(function(DOMfilterFilter) {
|
||||||
|
var dom = 'a<p>b<i>c<b>d</b>e<b>f</b>g</i>h</p>i',
|
||||||
|
expected = '<span>A</span><p><span>B</span><i><span>C</span><b><span>D</span></b><span>E</span><b><span>F</span></b><span>G</span></i><span>H</span></p><span>I</span>',
|
||||||
|
result = DOMfilterFilter(dom, 'uppercase').$$unwrapTrustedValue();
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should pass additional arguments to the filter', inject(function(DOMfilterFilter) {
|
||||||
|
var dom = '1<p>2</p>3.14159265',
|
||||||
|
expected = '<span>1.00</span><p><span>2.00</span></p><span>3.14</span>',
|
||||||
|
result = DOMfilterFilter(dom, 'number', 2).$$unwrapTrustedValue();
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue