Skip to content

Commit 7d5d37c

Browse files
committed
Enhancement(factories): Better removal of style junk which Chome inserts. Also one bug fix in the old existing code (a missing /").
1 parent b432e74 commit 7d5d37c

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

src/factories.js

+29-13
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,32 @@ angular.module('textAngular.factories', [])
3636
var taFixChrome = function(html){
3737
if(!html || !angular.isString(html) || html.length <= 0) return html;
3838
// grab all elements with a style attibute
39-
var spanMatch = /<([^>\/]+?)style=("([^"]+)"|'([^']+)')([^>]*)>/ig;
40-
var match, styleVal, newTag, finalHtml = '', lastIndex = 0;
39+
var spanMatch = /<([^>\/]+?)style=("([^\"]+)"|'([^']+)')([^>]*)>/ig;
40+
var appleConvertedSpaceMatch = /<span class="Apple-converted-space">([^<]+)<\/span>/ig;
41+
var match, styleVal, appleSpaceVal, newTag, finalHtml = '', lastIndex = 0;
42+
// remove all the Apple-converted-space spans and replace with the content of the span
43+
/* istanbul ignore next: apple-contereted-space span match */
44+
while(match = appleConvertedSpaceMatch.exec(html)){
45+
appleSpaceVal = match[1];
46+
appleSpaceVal = appleSpaceVal.replace(/&nbsp;/ig, ' ');
47+
finalHtml += html.substring(lastIndex, match.index) + appleSpaceVal;
48+
lastIndex = match.index + match[0].length;
49+
}
50+
/* istanbul ignore next: apple-contereted-space span has matched */
51+
if (lastIndex) {
52+
// modified....
53+
html=finalHtml;
54+
finalHtml='';
55+
lastIndex=0;
56+
}
4157
while(match = spanMatch.exec(html)){
4258
// one of the quoted values ' or "
4359
/* istanbul ignore next: quotations match */
4460
styleVal = match[3] || match[4];
4561
// test for chrome inserted junk
46-
if(styleVal && styleVal.match(/line-height: 1.[0-9]{3,12};|color: inherit; line-height: 1.1;/i)){
62+
if(styleVal && styleVal.match(/line-height: 1.[0-9]{3,12};|color: inherit; line-height: 1.1;|color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);|background-color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);/i)){
4763
// replace original tag with new tag
48-
styleVal = styleVal.replace(/( |)font-family: inherit;|( |)line-height: 1.[0-9]{3,12};|( |)color: inherit;/ig, '');
64+
styleVal = styleVal.replace(/( |)font-family: inherit;|( |)line-height: 1.[0-9]{3,12};|( |)color: inherit;|( |)color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);|( |)background-color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);/ig, '');
4965
newTag = '<' + match[1].trim();
5066
if(styleVal.trim().length > 0) newTag += ' style=' + match[2].substring(0,1) + styleVal + match[2].substring(0,1);
5167
newTag += match[5].trim() + ">";
@@ -75,7 +91,7 @@ angular.module('textAngular.factories', [])
7591
tag: 'i'
7692
}
7793
];
78-
94+
7995
var styleMatch = [];
8096
for(var i = 0; i < convert_infos.length; i++){
8197
var _partialStyle = '(' + convert_infos[i].property + ':\\s*(';
@@ -88,7 +104,7 @@ angular.module('textAngular.factories', [])
88104
styleMatch.push(_partialStyle);
89105
}
90106
var styleRegexString = '(' + styleMatch.join('|') + ')';
91-
107+
92108
function wrapNested(html, wrapTag) {
93109
var depth = 0;
94110
var lastIndex = 0;
@@ -107,7 +123,7 @@ angular.module('textAngular.factories', [])
107123
angular.element(wrapTag)[0].outerHTML.substring(wrapTag.length) +
108124
html.substring(lastIndex);
109125
}
110-
126+
111127
function transformLegacyStyles(html){
112128
if(!html || !angular.isString(html) || html.length <= 0) return html;
113129
var i;
@@ -155,7 +171,7 @@ angular.module('textAngular.factories', [])
155171
else finalHtml += html.substring(lastIndex);
156172
return finalHtml;
157173
}
158-
174+
159175
function transformLegacyAttributes(html){
160176
if(!html || !angular.isString(html) || html.length <= 0) return html;
161177
// replace all align='...' tags with text-align attributes
@@ -184,7 +200,7 @@ angular.module('textAngular.factories', [])
184200
// return with remaining html
185201
return finalHtml + html.substring(lastIndex);
186202
}
187-
203+
188204
return function taSanitize(unsafe, oldsafe, ignore){
189205
// unsafe html should NEVER built into a DOM object via angular.element. This allows XSS to be inserted and run.
190206
if ( !ignore ) {
@@ -198,7 +214,7 @@ angular.module('textAngular.factories', [])
198214
// any exceptions (lets say, color for example) should be made here but with great care
199215
// setup unsafe element for modification
200216
unsafe = transformLegacyAttributes(unsafe);
201-
217+
202218
var safe;
203219
try {
204220
safe = $sanitize(unsafe);
@@ -207,9 +223,9 @@ angular.module('textAngular.factories', [])
207223
} catch (e){
208224
safe = oldsafe || '';
209225
}
210-
226+
211227
// Do processing for <pre> tags, removing tabs and return carriages outside of them
212-
228+
213229
var _preTags = safe.match(/(<pre[^>]*>.*?<\/pre[^>]*>)/ig);
214230
var processedSafe = safe.replace(/(&#(9|10);)*/ig, '');
215231
var re = /<pre[^>]*>.*?<\/pre[^>]*>/ig;
@@ -247,4 +263,4 @@ angular.module('textAngular.factories', [])
247263
deferred.resolve();
248264
}
249265
};
250-
}]);
266+
}]);

0 commit comments

Comments
 (0)