Compare commits

...

8 Commits

Author SHA1 Message Date
Chakib Benziane c4bc6b70ac Update bower.json 9 years ago
Matteo Suppo bdb7c3fece Minor fix: don't pollute the global namespace 10 years ago
Matteo Suppo 0c1b23464f Minor edits to README 10 years ago
Matteo Suppo 7124b00ce2 Minor edits to README 10 years ago
Matteo Suppo 9b4762640e Minor edits to README 10 years ago
Matteo Suppo 4d0c27d247 Add plunkr to Readme 10 years ago
Matteo Suppo ee01566ca4 New version 10 years ago
Matteo Suppo 5a4846e7a0 Make it return safe html 10 years ago

@ -30,9 +30,16 @@ USAGE
It's a filter, you use it in your html like this:
```{{text|diff:otherText}}```
<div ng-bind-html="oldText|diff:newText"></div>
This will show the diff between ```text``` and ```otherText```
This will show the diff between ```oldText``` and ```newText```
Note that the filter returns html with ```<ins>``` and ```<del>``` tags, so in order to
display it you have to use ng-bind-html.
Here's a demo, that's worth more than a thousand words:
[http://plnkr.co/edit/nfhA5g?p=preview](http://plnkr.co/edit/nfhA5g?p=preview)
DEVELOPMENT

165
angular-diff.js vendored

@ -1,7 +1,7 @@
'use strict';
angular.module('diff', [])
.filter('diff', function () {
.filter('diff', function ($sce) {
/*
* Javascript Diff Algorithm
@ -173,167 +173,6 @@ angular.module('diff', [])
// Actual filter
return function(input, match) {
return diffString(input, match);
return $sce.trustAsHtml(diffString(input, match));
};
});
/*
* Javascript Diff Algorithm
* By John Resig (http://ejohn.org/)
* Modified by Chu Alan "sprite"
*
* Released under the MIT license.
*
* More Info:
* http://ejohn.org/projects/javascript-diff-algorithm/
*/
function escape(s) {
var n = s;
n = n.replace(/&/g, "&amp;");
n = n.replace(/</g, "&lt;");
n = n.replace(/>/g, "&gt;");
n = n.replace(/"/g, "&quot;");
return n;
}
function diffString( o, n ) {
o = o.replace(/\s+$/, '');
n = n.replace(/\s+$/, '');
var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
var str = "";
var oSpace = o.match(/\s+/g);
if (oSpace == null) {
oSpace = ["\n"];
} else {
oSpace.push("\n");
}
var nSpace = n.match(/\s+/g);
if (nSpace == null) {
nSpace = ["\n"];
} else {
nSpace.push("\n");
}
if (out.n.length == 0) {
for (var i = 0; i < out.o.length; i++) {
str += '<del>' + escape(out.o[i]) + oSpace[i] + "</del>";
}
} else {
if (out.n[0].text == null) {
for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
str += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
}
}
for ( var i = 0; i < out.n.length; i++ ) {
if (out.n[i].text == null) {
str += '<ins>' + escape(out.n[i]) + nSpace[i] + "</ins>";
} else {
var pre = "";
for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
pre += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
}
str += " " + out.n[i].text + nSpace[i] + pre;
}
}
}
return str;
}
function randomColor() {
return "rgb(" + (Math.random() * 100) + "%, " +
(Math.random() * 100) + "%, " +
(Math.random() * 100) + "%)";
}
function diffString2( o, n ) {
o = o.replace(/\s+$/, '');
n = n.replace(/\s+$/, '');
var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
var oSpace = o.match(/\s+/g);
if (oSpace == null) {
oSpace = ["\n"];
} else {
oSpace.push("\n");
}
var nSpace = n.match(/\s+/g);
if (nSpace == null) {
nSpace = ["\n"];
} else {
nSpace.push("\n");
}
var os = "";
var colors = new Array();
for (var i = 0; i < out.o.length; i++) {
colors[i] = randomColor();
if (out.o[i].text != null) {
os += '<span style="background-color: ' +colors[i]+ '">' +
escape(out.o[i].text) + oSpace[i] + "</span>";
} else {
os += "<del>" + escape(out.o[i]) + oSpace[i] + "</del>";
}
}
var ns = "";
for (var i = 0; i < out.n.length; i++) {
if (out.n[i].text != null) {
ns += '<span style="background-color: ' +colors[out.n[i].row]+ '">' +
escape(out.n[i].text) + nSpace[i] + "</span>";
} else {
ns += "<ins>" + escape(out.n[i]) + nSpace[i] + "</ins>";
}
}
return { o : os , n : ns };
}
function diff( o, n ) {
var ns = new Object();
var os = new Object();
for ( var i = 0; i < n.length; i++ ) {
if ( ns[ n[i] ] == null )
ns[ n[i] ] = { rows: new Array(), o: null };
ns[ n[i] ].rows.push( i );
}
for ( var i = 0; i < o.length; i++ ) {
if ( os[ o[i] ] == null )
os[ o[i] ] = { rows: new Array(), n: null };
os[ o[i] ].rows.push( i );
}
for ( var i in ns ) {
if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
}
}
for ( var i = 0; i < n.length - 1; i++ ) {
if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
n[i+1] == o[ n[i].row + 1 ] ) {
n[i+1] = { text: n[i+1], row: n[i].row + 1 };
o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
}
}
for ( var i = n.length - 1; i > 0; i-- ) {
if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
n[i-1] == o[ n[i].row - 1 ] ) {
n[i-1] = { text: n[i-1], row: n[i].row - 1 };
o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
}
}
return { o: o, n: n };
}

@ -1,2 +1 @@
"use strict";angular.module("diff",[]).filter("diff",function(){function t(t){var r=t;return r=r.replace(/&/g,"&amp;"),r=r.replace(/</g,"&lt;"),r=r.replace(/>/g,"&gt;"),r=r.replace(/'/g,"&quot;")}function r(r,o){r=r.replace(/\s+$/,""),o=o.replace(/\s+$/,"");var n,l=e(""===r?[]:r.split(/\s+/),""===o?[]:o.split(/\s+/)),w="",s=r.match(/\s+/g);null===s?s=["\n"]:s.push("\n");var u=o.match(/\s+/g);if(null===u?u=["\n"]:u.push("\n"),0===l.n.length)for(n=0;n<l.o.length;n++)w+="<del>"+t(l.o[n])+s[n]+"</del>";else{if(null===l.n[0].text)for(o=0;o<l.o.length&&null===l.o[o].text;o++)w+="<del>"+t(l.o[o])+s[o]+"</del>";for(n=0;n<l.n.length;n++)if(l.n[n].text){var f="";for(o=l.n[n].row+1;o<l.o.length&&!l.o[o].text;o++)f+="<del>"+t(l.o[o])+s[o]+"</del>";w+=" "+l.n[n].text+u[n]+f}else w+="<ins>"+t(l.n[n])+u[n]+"</ins>"}return w}function e(t,r){var e,o={},n={};for(e=0;e<r.length;e++)o[r[e]]||(o[r[e]]={rows:[],o:null}),o[r[e]].rows.push(e);for(e=0;e<t.length;e++)n[t[e]]||(n[t[e]]={rows:[],n:null}),n[t[e]].rows.push(e);for(e in o)1===o[e].rows.length&&"undefined"!=typeof n[e]&&1===n[e].rows.length&&(r[o[e].rows[0]]={text:r[o[e].rows[0]],row:n[e].rows[0]},t[n[e].rows[0]]={text:t[n[e].rows[0]],row:o[e].rows[0]});for(e=0;e<r.length-1;e++)null!==r[e].text&&null===r[e+1].text&&r[e].row+1<t.length&&!t[r[e].row+1].text&&r[e+1]===t[r[e].row+1]&&(r[e+1]={text:r[e+1],row:r[e].row+1},t[r[e].row+1]={text:t[r[e].row+1],row:e+1});for(e=r.length-1;e>0;e--)r[e].text&&!r[e-1].text&&r[e].row>0&&!t[r[e].row-1].text&&r[e-1]===t[r[e].row-1]&&(r[e-1]={text:r[e-1],row:r[e].row-1},t[r[e].row-1]={text:t[r[e].row-1],row:e-1});return{o:t,n:r}}return function(t,e){return r(t,e)}});
function escape(e){var n=e;return n=n.replace(/&/g,"&amp;"),n=n.replace(/</g,"&lt;"),n=n.replace(/>/g,"&gt;"),n=n.replace(/"/g,"&quot;")}function diffString(e,n){e=e.replace(/\s+$/,""),n=n.replace(/\s+$/,"");var r=diff(""==e?[]:e.split(/\s+/),""==n?[]:n.split(/\s+/)),t="",l=e.match(/\s+/g);null==l?l=["\n"]:l.push("\n");var o=n.match(/\s+/g);if(null==o?o=["\n"]:o.push("\n"),0==r.n.length)for(var s=0;s<r.o.length;s++)t+="<del>"+escape(r.o[s])+l[s]+"</del>";else{if(null==r.n[0].text)for(n=0;n<r.o.length&&null==r.o[n].text;n++)t+="<del>"+escape(r.o[n])+l[n]+"</del>";for(var s=0;s<r.n.length;s++)if(null==r.n[s].text)t+="<ins>"+escape(r.n[s])+o[s]+"</ins>";else{var a="";for(n=r.n[s].row+1;n<r.o.length&&null==r.o[n].text;n++)a+="<del>"+escape(r.o[n])+l[n]+"</del>";t+=" "+r.n[s].text+o[s]+a}}return t}function randomColor(){return"rgb("+100*Math.random()+"%, "+100*Math.random()+"%, "+100*Math.random()+"%)"}function diffString2(e,n){e=e.replace(/\s+$/,""),n=n.replace(/\s+$/,"");var r=diff(""==e?[]:e.split(/\s+/),""==n?[]:n.split(/\s+/)),t=e.match(/\s+/g);null==t?t=["\n"]:t.push("\n");var l=n.match(/\s+/g);null==l?l=["\n"]:l.push("\n");for(var o="",s=new Array,a=0;a<r.o.length;a++)s[a]=randomColor(),o+=null!=r.o[a].text?'<span style="background-color: '+s[a]+'">'+escape(r.o[a].text)+t[a]+"</span>":"<del>"+escape(r.o[a])+t[a]+"</del>";for(var u="",a=0;a<r.n.length;a++)u+=null!=r.n[a].text?'<span style="background-color: '+s[r.n[a].row]+'">'+escape(r.n[a].text)+l[a]+"</span>":"<ins>"+escape(r.n[a])+l[a]+"</ins>";return{o:o,n:u}}function diff(e,n){for(var r=new Object,t=new Object,l=0;l<n.length;l++)null==r[n[l]]&&(r[n[l]]={rows:new Array,o:null}),r[n[l]].rows.push(l);for(var l=0;l<e.length;l++)null==t[e[l]]&&(t[e[l]]={rows:new Array,n:null}),t[e[l]].rows.push(l);for(var l in r)1==r[l].rows.length&&"undefined"!=typeof t[l]&&1==t[l].rows.length&&(n[r[l].rows[0]]={text:n[r[l].rows[0]],row:t[l].rows[0]},e[t[l].rows[0]]={text:e[t[l].rows[0]],row:r[l].rows[0]});for(var l=0;l<n.length-1;l++)null!=n[l].text&&null==n[l+1].text&&n[l].row+1<e.length&&null==e[n[l].row+1].text&&n[l+1]==e[n[l].row+1]&&(n[l+1]={text:n[l+1],row:n[l].row+1},e[n[l].row+1]={text:e[n[l].row+1],row:l+1});for(var l=n.length-1;l>0;l--)null!=n[l].text&&null==n[l-1].text&&n[l].row>0&&null==e[n[l].row-1].text&&n[l-1]==e[n[l].row-1]&&(n[l-1]={text:n[l-1],row:n[l].row-1},e[n[l].row-1]={text:e[n[l].row-1],row:l-1});return{o:e,n:n}}
"use strict";angular.module("diff",[]).filter("diff",["$sce",function(t){function r(t){var r=t;return r=r.replace(/&/g,"&amp;"),r=r.replace(/</g,"&lt;"),r=r.replace(/>/g,"&gt;"),r=r.replace(/'/g,"&quot;")}function e(t,e){t=t.replace(/\s+$/,""),e=e.replace(/\s+$/,"");var n,l=o(""===t?[]:t.split(/\s+/),""===e?[]:e.split(/\s+/)),s="",w=t.match(/\s+/g);null===w?w=["\n"]:w.push("\n");var u=e.match(/\s+/g);if(null===u?u=["\n"]:u.push("\n"),0===l.n.length)for(n=0;n<l.o.length;n++)s+="<del>"+r(l.o[n])+w[n]+"</del>";else{if(null===l.n[0].text)for(e=0;e<l.o.length&&null===l.o[e].text;e++)s+="<del>"+r(l.o[e])+w[e]+"</del>";for(n=0;n<l.n.length;n++)if(l.n[n].text){var f="";for(e=l.n[n].row+1;e<l.o.length&&!l.o[e].text;e++)f+="<del>"+r(l.o[e])+w[e]+"</del>";s+=" "+l.n[n].text+u[n]+f}else s+="<ins>"+r(l.n[n])+u[n]+"</ins>"}return s}function o(t,r){var e,o={},n={};for(e=0;e<r.length;e++)o[r[e]]||(o[r[e]]={rows:[],o:null}),o[r[e]].rows.push(e);for(e=0;e<t.length;e++)n[t[e]]||(n[t[e]]={rows:[],n:null}),n[t[e]].rows.push(e);for(e in o)1===o[e].rows.length&&"undefined"!=typeof n[e]&&1===n[e].rows.length&&(r[o[e].rows[0]]={text:r[o[e].rows[0]],row:n[e].rows[0]},t[n[e].rows[0]]={text:t[n[e].rows[0]],row:o[e].rows[0]});for(e=0;e<r.length-1;e++)null!==r[e].text&&null===r[e+1].text&&r[e].row+1<t.length&&!t[r[e].row+1].text&&r[e+1]===t[r[e].row+1]&&(r[e+1]={text:r[e+1],row:r[e].row+1},t[r[e].row+1]={text:t[r[e].row+1],row:e+1});for(e=r.length-1;e>0;e--)r[e].text&&!r[e-1].text&&r[e].row>0&&!t[r[e].row-1].text&&r[e-1]===t[r[e].row-1]&&(r[e-1]={text:r[e-1],row:r[e].row-1},t[r[e].row-1]={text:t[r[e].row-1],row:e-1});return{o:t,n:r}}return function(r,o){return t.trustAsHtml(e(r,o))}}]);

@ -1,6 +1,6 @@
{
"name": "angular-diff",
"version": "v1.0.0",
"version": "v1.0.1",
"description": "Diff filter for angular.js. Show inline text diff in your page",
"homepage": "https://github.com/matteosuppo/angular-diff",
"authors": [
@ -19,7 +19,7 @@
"tests"
],
"dependencies": {
"angular": "~1.2.18",
"angular-mocks": "~1.2.18"
"angular": "~1.3.10",
"angular-mocks": "~1.3.10"
}
}

@ -1,6 +1,6 @@
{
"name": "angular-diff",
"version": "v1.0.0",
"version": "v1.0.1",
"description": "Diff filter for angular.js. Show inline text diff in your page",
"repository": {
"type": "git",

@ -1,7 +1,7 @@
'use strict';
angular.module('diff', [])
.filter('diff', function () {
.filter('diff', function ($sce) {
/*
* Javascript Diff Algorithm
@ -173,6 +173,6 @@ angular.module('diff', [])
// Actual filter
return function(input, match) {
return diffString(input, match);
return $sce.trustAsHtml(diffString(input, match));
};
});

@ -1,160 +0,0 @@
/*
* Javascript Diff Algorithm
* By John Resig (http://ejohn.org/)
* Modified by Chu Alan "sprite"
*
* Released under the MIT license.
*
* More Info:
* http://ejohn.org/projects/javascript-diff-algorithm/
*/
function escape(s) {
var n = s;
n = n.replace(/&/g, "&amp;");
n = n.replace(/</g, "&lt;");
n = n.replace(/>/g, "&gt;");
n = n.replace(/"/g, "&quot;");
return n;
}
function diffString( o, n ) {
o = o.replace(/\s+$/, '');
n = n.replace(/\s+$/, '');
var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
var str = "";
var oSpace = o.match(/\s+/g);
if (oSpace == null) {
oSpace = ["\n"];
} else {
oSpace.push("\n");
}
var nSpace = n.match(/\s+/g);
if (nSpace == null) {
nSpace = ["\n"];
} else {
nSpace.push("\n");
}
if (out.n.length == 0) {
for (var i = 0; i < out.o.length; i++) {
str += '<del>' + escape(out.o[i]) + oSpace[i] + "</del>";
}
} else {
if (out.n[0].text == null) {
for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
str += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
}
}
for ( var i = 0; i < out.n.length; i++ ) {
if (out.n[i].text == null) {
str += '<ins>' + escape(out.n[i]) + nSpace[i] + "</ins>";
} else {
var pre = "";
for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
pre += '<del>' + escape(out.o[n]) + oSpace[n] + "</del>";
}
str += " " + out.n[i].text + nSpace[i] + pre;
}
}
}
return str;
}
function randomColor() {
return "rgb(" + (Math.random() * 100) + "%, " +
(Math.random() * 100) + "%, " +
(Math.random() * 100) + "%)";
}
function diffString2( o, n ) {
o = o.replace(/\s+$/, '');
n = n.replace(/\s+$/, '');
var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
var oSpace = o.match(/\s+/g);
if (oSpace == null) {
oSpace = ["\n"];
} else {
oSpace.push("\n");
}
var nSpace = n.match(/\s+/g);
if (nSpace == null) {
nSpace = ["\n"];
} else {
nSpace.push("\n");
}
var os = "";
var colors = new Array();
for (var i = 0; i < out.o.length; i++) {
colors[i] = randomColor();
if (out.o[i].text != null) {
os += '<span style="background-color: ' +colors[i]+ '">' +
escape(out.o[i].text) + oSpace[i] + "</span>";
} else {
os += "<del>" + escape(out.o[i]) + oSpace[i] + "</del>";
}
}
var ns = "";
for (var i = 0; i < out.n.length; i++) {
if (out.n[i].text != null) {
ns += '<span style="background-color: ' +colors[out.n[i].row]+ '">' +
escape(out.n[i].text) + nSpace[i] + "</span>";
} else {
ns += "<ins>" + escape(out.n[i]) + nSpace[i] + "</ins>";
}
}
return { o : os , n : ns };
}
function diff( o, n ) {
var ns = new Object();
var os = new Object();
for ( var i = 0; i < n.length; i++ ) {
if ( ns[ n[i] ] == null )
ns[ n[i] ] = { rows: new Array(), o: null };
ns[ n[i] ].rows.push( i );
}
for ( var i = 0; i < o.length; i++ ) {
if ( os[ o[i] ] == null )
os[ o[i] ] = { rows: new Array(), n: null };
os[ o[i] ].rows.push( i );
}
for ( var i in ns ) {
if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
}
}
for ( var i = 0; i < n.length - 1; i++ ) {
if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
n[i+1] == o[ n[i].row + 1 ] ) {
n[i+1] = { text: n[i+1], row: n[i].row + 1 };
o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
}
}
for ( var i = n.length - 1; i > 0; i-- ) {
if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
n[i-1] == o[ n[i].row - 1 ] ) {
n[i-1] = { text: n[i-1], row: n[i].row - 1 };
o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
}
}
return { o: o, n: n };
}

@ -9,7 +9,8 @@ describe('filter', function() {
it('should convert a string to the diff value with another string', inject(function(diffFilter) {
expect(diffFilter(
'The red brown fox jumped over the rolling log.',
'The brown spotted fox leaped over the rolling log')).toBe(
'The brown spotted fox leaped over the rolling log')
.$$unwrapTrustedValue()).toBe(
' The <del>red </del> brown <ins>spotted </ins> fox <del>jumped </del><ins>leaped </ins> over the rolling <del>log.\n</del><ins>log\n</ins>');
}));
});