Fix inline colour filter by applying to text nodes only

this requires traversing the line's DOM and manipulating things there
This commit is contained in:
Lorenz Hübschle-Schneider 2014-10-27 21:50:01 +01:00
parent dbdd0523f9
commit d95abdd0df
2 changed files with 49 additions and 3 deletions

View File

@ -269,7 +269,7 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
<td class="prefix"><a ng-click="addMention(bufferline.prefix)"><span ng-repeat="part in ::bufferline.prefix" ng-class="::part.classes" ng-bind="::part.text"></span></a></td><!-- <td class="prefix"><a ng-click="addMention(bufferline.prefix)"><span ng-repeat="part in ::bufferline.prefix" ng-class="::part.classes" ng-bind="::part.text"></span></a></td><!--
--><td class="message"><!-- --><td class="message"><!--
--><div ng-repeat="metadata in ::bufferline.metadata" plugin data="::metadata"></div><!-- --><div ng-repeat="metadata in ::bufferline.metadata" plugin data="::metadata"></div><!--
--><span ng-repeat="part in ::bufferline.content" class="text" ng-class="::part.classes" ng-bind-html="::part.text | irclinky:'_blank' | inlinecolour"></span> --><span ng-repeat="part in ::bufferline.content" class="text" ng-class="::part.classes" ng-bind-html="::part.text | irclinky:'_blank' | DOMfilter:'inlinecolour'"></span>
</td> </td>
</tr> </tr>
<tr class="readmarker" ng-if="activeBuffer().lastSeen==$index"> <tr class="readmarker" ng-if="activeBuffer().lastSeen==$index">

View File

@ -36,7 +36,7 @@ weechat.filter('irclinky', ['$filter', function($filter) {
}; };
}]); }]);
weechat.filter('inlinecolour', ['$sce', function($sce) { weechat.filter('inlinecolour', function() {
return function(text) { return function(text) {
if (!text) { if (!text) {
return text; return text;
@ -46,7 +46,53 @@ weechat.filter('inlinecolour', ['$sce', function($sce) {
var hexColourRegex = /(^|[^&])\#([0-9a-f]{6})($|[^\w'"])/gmi; var hexColourRegex = /(^|[^&])\#([0-9a-f]{6})($|[^\w'"])/gmi;
var substitute = '$1#$2 <div class="colourbox" style="background-color:#$2"></div> $3'; var substitute = '$1#$2 <div class="colourbox" style="background-color:#$2"></div> $3';
return $sce.trustAsHtml(text.replace(hexColourRegex, substitute)); return text.replace(hexColourRegex, substitute);
};
});
// 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) {
return function(text, filter) {
if (!text || !filter) {
return text;
}
var filterFunction = $filter(filter);
var el = document.createElement('div');
el.innerHTML = text;
// Recursive DOM-walking function applying the filter to the text nodes
var process = function(node) {
if (node.nodeType === 3) { // text node
var value = filterFunction(node.nodeValue);
if (value !== node.nodeValue) {
// we changed something. create a new node to replace the current one
// we could also only add its children but that would probably incur
// more overhead than it would gain us
var newNode = document.createElement('span');
newNode.innerHTML = value;
var parent = node.parentNode;
var sibling = node.nextSibling;
parent.removeChild(node);
if (sibling) {
parent.insertBefore(newNode, sibling);
} else {
parent.appendChild(newNode);
}
}
}
// recurse
node = node.firstChild;
while (node) {
process(node);
node = node.nextSibling;
}
};
process(el);
return $sce.trustAsHtml(el.innerHTML);
}; };
}]); }]);
})(); })();