I don't think you can do this with a filter, try a directive.
Below is an example, fairly straightforward. I first changed the filter to a service (though you can use the filter similarly with $filter if you want but I don't see why). Then I use $interpolate to create an interpolation function, described here:
Compiles a string with markup into an interpolation function. This service is used by the HTML $compile service for data binding. See $interpolateProvider for configuring the interpolation markup.
You can see in the example that the strings '1', '2' and '3' are highlighted because I added style="color:red", and they have the class as well.
Edit: edited solution with usage of ngModelController to make changes to the textarea appear in the element below with angular's data binding. Note the change to the snippet element: <snippet ng-model="txt">
var app = angular.module('plunker', ['syntax']);
app.controller('MainCtrl', function($scope) {
$scope.txt = "1 2 3 \n #This is a mysql syntax highlighter\n-- This is a comment/*\nAnd this is a multi line comment\nSELECT things FROM table;*/\nSELECT \nag.name AS agent, `d.date`, d.first_payment_date, d.account_number, ";
});
angular.module('syntax', [])
.service('formatter', function () {
return function (input) {
if (input) {
return input.replace(/(\d+)/g, "<span class=\"string\" style=\"color:red\">$1</span>");
}
}
})
.directive('snippet', function($timeout, $interpolate, formatter) {
return {
restrict: 'E',
template:'<pre><code></code></pre>',
replace:true,
require: '?ngModel',
link:function(scope, elm, attrs, ngModel){
ngModel.$render = function(){
var tmp = $interpolate(scope.txt)(scope);
elm.find('code').html(formatter(tmp));
}
}
};
});
http://plnkr.co/edit/783ML4Y2qH8oMLarf0kg?p=preview