src/ub.strings.escape.js   F
last analyzed

Complexity

Total Complexity 68
Complexity/F 4.53

Size

Lines of Code 284
Function Count 15

Duplication

Duplicated Lines 66
Ratio 23.24 %

Importance

Changes 0
Metric Value
cc 0
eloc 180
nc 1
dl 66
loc 284
rs 2.96
c 0
b 0
f 0
wmc 68
mnd 4
bc 49
fnc 15
bpm 3.2666
cpm 4.5333
noi 0

15 Functions

Rating   Name   Duplication   Size   Complexity  
A stringFuncs.flattenAccents 0 4 2
A arrayFuncs.escapeURLEncodedVars 0 17 3
A stringFuncs.flattenSymbols 0 4 1
F stringFuncs.escapeURLStrict 0 25 14
A stringFuncs.unescapeURLEncoded 0 5 2
C stringFuncs.escapeJS 33 33 11
A stringFuncs.escapeURLEncoded 0 5 2
A stringFuncs.unescapeDouble 0 15 4
A stringFuncs.escapeXML 0 9 1
B stringFuncs.escapeHTMLSimple 0 11 6
C stringFuncs.escapeHTML 0 45 10
A stringFuncs.escapeJSSimple 0 11 1
C stringFuncs.unescapeJS 33 33 9
A stringFuncs.unescapeHTMLSimple 0 12 1
A stringFuncs.escapeString 0 9 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like src/ub.strings.escape.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/** global: UB */
2
3
UB.accentChars = ["Â", "Ã", "Ä", "À", "Á", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß", "ẞ", "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", "ø", "ù", "ú", "û", "ü", "ý", "þ", "ÿ"];
4
UB.accentEngChars = ["A", "A", "Ae", "A", "A", "A", "A", "C", "E", "E", "E", "E", "I", "I", "I", "I", "D", "N", "O", "O", "O", "O", "Oe", "O", "U", "U", "U", "Ue", "Y", "T", "ss", "ss", "a", "a", "a", "a", "ae", "a", "a", "c", "e", "e", "e", "e", "i", "i", "i", "i", "o", "n", "o", "o", "o", "o", "oe", "o", "u", "u", "u", "ue", "y", "t", "y"];
5
UB.accentEngChars2 = ["A", "A", "A", "A", "A", "A", "A", "C", "E", "E", "E", "E", "I", "I", "I", "I", "D", "N", "O", "O", "O", "O", "O", "O", "U", "U", "U", "U", "Y", "T", "s", "s", "a", "a", "a", "a", "a", "a", "a", "c", "e", "e", "e", "e", "i", "i", "i", "i", "o", "n", "o", "o", "o", "o", "o", "o", "u", "u", "u", "u", "y", "t", "y"];
6
7
UB.htmlCharNames = ["hellip", "deg", "prime", "lsaquo", "rsaquo", "frasl", "ndash", "mdash", "iexcl", "iquest", "ldquo", "rdquo", "lsquo", "rsquo", "laquo", "raquo", "cent", "copy", "divide", "micro", "middot", "para", "plusmn", "euro", "pound", "reg", "sect", "trade", "yen", "aacute", "Aacute", "agrave", "Agrave", "acirc", "Acirc", "aring", "Aring", "atilde", "Atilde", "auml", "Auml", "aelig", "AElig", "ccedil", "Ccedil", "eacute", "Eacute", "egrave", "Egrave", "ecirc", "Ecirc", "euml", "Euml", "iacute", "Iacute", "igrave", "Igrave", "icirc", "Icirc", "iuml", "ntilde", "Ntilde", "oacute", "Oacute", "ograve", "Ograve", "ocirc", "Ocirc", "oslash", "Oslash", "otilde", "Otilde", "ouml", "Ouml", "szlig", "uacute", "Uacute", "ugrave", "Ugrave", "ucirc", "Ucirc", "uuml", "Uuml", "yuml", "loz", "diams", "spades", "clubs", "hearts", "crarr", "larr", "rarr", "harr", "uarr", "darr", "lArr", "rArr", "hArr", "dArr", "uArr", "Delta", "nabla", "fnof", "pi", "plusmn", "divide", "times", "sup1", "sup2", "sup3", "frac12", "frac14", "frac34", "le", "ge", "middot", "prod", "sum", "minus", "radic", "infin", "ang", "sim", "isin", "prop", "asymp", "int", "forall", "exist", "part", "empty", "notin", "cap", "cup", "permil", "there4", "perp", "mu", "Theta", "curren"];
8
UB.htmlCharUTF = ['…', '°', '`', '‹', '›', '⁄', '–', '—', '¡', '¿', '“', '”', '‘', '’', '«', '»', '¢', '©', '÷', 'µ', '·', '¶', '±', '€', '£', '®', '§', '™', '¥', 'á', 'Á', 'à', 'À', 'â', 'Â', 'å', 'Å', 'ã', 'Ã', 'ä', 'Ä', 'æ', 'Æ', 'ç', 'Ç', 'é', 'É', 'è', 'È', 'ê', 'Ê', 'ë', 'Ë', 'í', 'Í', 'ì', 'Ì', 'î', 'Î', 'Ï', 'ñ', 'Ñ', 'ó', 'Ó', 'ò', 'Ò', 'ô', 'Ô', 'ø', 'Ø', 'õ', 'Õ', 'ö', 'Ö', 'ß', 'ú', 'Ú', 'ù', 'Ù', 'û', 'Û', 'ü', 'Ü', 'ÿ', '◊', '♦', '♠', '♣', '♥', '↵', '←', '→', '↔', '↑', '↓', '⇐', '⇒', '⇔', '⇓', '⇑', 'Δ', '∇', 'ƒ', 'π', '±', '÷', '×', '¹', '²', '³', '½', '¼', '¾', '≤', '≥', '·', '∏', '∑', '−', '√', '∞', '∠', '∼', '∈', '∝', '≈', '∫', '∀', '∃', '∂', '∅', '∉', '∩', '∪', '‰', '∴', '⊥', 'μ', 'Θ', '¤'];
9
10
UB.htmlCharNames2 = ["apos", "amp", "quot", "lt", "gt"];
11
UB.htmlCharUTF2 = ['\'', '&', '\'', '<', '>'];
12
13
UB.htmlCharNames3 = ["nbsp"];
14
UB.htmlCharUTF3 = [' '];
15
16
17
UB.escapedDict = {'n':'\n', 'r':'\r', 't':'\t', 'f':'\f', 'b':'\b', '"':'\"', "'":'\'', '\\':''};
18
19
var arrayFuncs = {
20
21
	escapeURLEncodedVars: function(varVals, forPopups = false){
22
		var varNames = this;
23
		
24
		// combine name and values
25
		var pairs = [];
26
		for (var v = 0, vl = varNames.length;v<vl;v++){
27
			var arg = varVals[v].escapeURLEncoded();
28
			
29
			// FIX: protects from window.open() in JS
30
			if (forPopups) {
31
				arg = escape(arg);
32
			}
33
			
34
			pairs.push(varNames[v] + "=" + arg);
35
		}
36
		return pairs.join("&");
37
	},
38
39
	none:null
40
};
41
42
// register funcs
43
UB.registerFuncs(Array.prototype, arrayFuncs);
44
45
46
var stringFuncs = {
47
	
48
	flattenSymbols: function(){
49
		var text = this;
50
		return text.split("#").join("Hash").split("@").join("At").split("%").join("Percent").split("$").join("Dollar").split("/").join("Slash").split("\\").join("Slash");
51
	},
52
	
53
	
54
	/**
55
	 * Convert "Café" to "Cafe"
56
	 * 
57
	 * @param	str
58
	 * @param	preservePronunciation	If true, converts "döppl" to "doeppl", else "doppl"
59
	 */
60
	flattenAccents: function(preservePronunciation = true){
61
		var str = this;
62
		return str.replaceManyMany(UB.accentChars, preservePronunciation ? UB.accentEngChars : UB.accentEngChars2);
63
	},
64
	
65
	
66
	
67
	// escaping strings
68
	escapeString: function(){
69
		var str = this;
70
		str = str.split("\\").join("\\\\"); // replace \ with \\
71
		str = str.split('"').join('\"'); // replace " with \"
72
		str = str.split("\t").join("\\"+"t"); // replace (tab) with \t
73
		str = str.split("\n").join("\\"+"n"); // replace (newline) with \n
74
		str = str.split("\r").join("\\"+"r"); // replace (newline) with \r
75
		return str;
76
	},
77
	escapeURLEncoded: function(isFullURL = false){
78
		var txt = this;
79
		// do not use escape() -- OUTDATED
80
		return isFullURL ? encodeURI(txt.trim()) : encodeURIComponent(txt.trim());
81
	},
82
	unescapeURLEncoded: function(isFullURL = false){
83
		var txt = this;
84
		// do not use unescape() -- OUTDATED
85
		return isFullURL ? decodeURI(txt.trim()) : decodeURIComponent(txt.trim());
86
	},
87 View Code Duplication
	escapeJS: function(singleQuotes = true, doubleQuotes = true){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
88
		var txt = this;
89
		
90
		/// C escape sequences 	 		\ ' " ? a b f n r t v
91
		/// JS escape sequences	 		\ ' " b f n r t
92
		
93
		// process string
94
		if (txt.indexOf("\\") > -1) {
95
			txt = txt.split("\\").join("\\\\");
96
		}
97
		if (singleQuotes && txt.indexOf("\'") > -1) {
98
			txt = txt.split("\'").join("\\'");
99
		}
100
		if (doubleQuotes && txt.indexOf('\"') > -1) {
101
			txt = txt.split("\"").join('\\"');
102
		}
103
		if (txt.indexOf("\b") > -1) {
104
			txt = txt.split("\b").join("\\b");
105
		}
106
		if (txt.indexOf("\f") > -1) {
107
			txt = txt.split("\f").join("\\f");
108
		}
109
		if (txt.indexOf("\n") > -1) {
110
			txt = txt.split("\n").join("\\n");
111
		}
112
		if (txt.indexOf("\r") > -1) {
113
			txt = txt.split("\r").join("\\r");
114
		}
115
		if (txt.indexOf("\t") > -1) {
116
			txt = txt.split("\t").join("\\t");
117
		}
118
		return txt;
119
	},
120 View Code Duplication
	unescapeJS: function(){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
121
		var txt = this;
122
		
123
		/// C escape sequences 	 		\ ' " ? a b f n r t v
124
		/// JS escape sequences	 		\ ' " b f n r t
125
		
126
		// process string
127
		if (txt.indexOf("\\\\") > -1) {
128
			txt = txt.split("\\\\").join("\\");
129
		}
130
		if (txt.indexOf("\\'") > -1) {
131
			txt = txt.split("\\'").join("\'");
132
		}
133
		if (txt.indexOf('\\"') > -1) {
134
			txt = txt.split('\\"').join("\"");
135
		}
136
		if (txt.indexOf("\\b") > -1) {
137
			txt = txt.split("\\b").join("\b");
138
		}
139
		if (txt.indexOf("\\f") > -1) {
140
			txt = txt.split("\\f").join("\f");
141
		}
142
		if (txt.indexOf("\\n") > -1) {
143
			txt = txt.split("\\n").join("\n");
144
		}
145
		if (txt.indexOf("\\r") > -1) {
146
			txt = txt.split("\\r").join("\r");
147
		}
148
		if (txt.indexOf("\\t") > -1) {
149
			txt = txt.split("\\t").join("\t");
150
		}
151
		return txt;
152
	},
153
	escapeJSSimple: function(){
154
		var input = this;
155
		input = input.split("\\").join("\\\\");
156
		input = input.split("\n").join("\\n");
157
		input = input.split("\r").join("\\r");
158
		input = input.split("\t").join("\\t");
159
		input = input.split("\f").join("\\f");
160
		input = input.split("\b").join("\\b");
161
		input = input.split("\"").join("\\\"");
162
		return input;
163
	},
164
	escapeURLStrict: function(doTrim = true){
165
		var input = this;
166
		if (input != null && input.length > 0) {
167
			if (doTrim) {
168
				input = input.trim();
169
			}
170
			input = encodeURIComponent(input);
171
			var a = input.split("");
172
			for (var i = 0;i<a.length;i++){
173
				switch(a[i]) {
174
					case "!": a[i] = "%21"; break;
175
					case "'": a[i] = "%27"; break;
176
					case "(": a[i] = "%28"; break;
177
					case ")": a[i] = "%29"; break;
178
					case "*": a[i] = "%2A"; break;
179
					case "-": a[i] = "%2D"; break;
180
					case ".": a[i] = "%2E"; break;
181
					case "_": a[i] = "%5F"; break;
182
					case "~": a[i] = "%7E"; break;
183
				}
184
			}
185
			return a.join("");
186
		}
187
		return "";
188
	},
189
	unescapeHTMLSimple: function(){
190
		var s = this;
191
		s = s.split("&amp;").join("&");
192
		s = s.split("&nbsp;").join("  ");
193
		s = s.split("&eq;").join("=");
194
		s = s.split("&lt;").join("<");
195
		s = s.split("&gt;").join(">");
196
		s = s.split("&quot;").join('"');
197
		s = s.split("&apos;").join("'");
198
		s = s.split("&#39;").join("'");
199
		return s;
200
	},
201
	escapeHTMLSimple: function(names = true){
202
		var s = this;
203
		s = s.split("&").join(names ? "&amp;" : "&#38;");
204
		//s = s.split("  ").join("&nbsp;");
205
		s = s.split("=").join(names ? "&eq;" : "&#61;");
206
		s = s.split("<").join(names ? "&lt;" : "&#60;");
207
		s = s.split(">").join(names ? "&gt;" : "&#62;");
208
		s = s.split('"').join(names ? '&quot;' : "&#34;");
209
		s = s.split("'").join("&#39;"); /// &apos; is not in the HTML spec, not supported in IE7
210
		return s;
211
	},
212
	escapeXML: function(){
213
		var s = this;
214
		s = s.split("&").join("&amp;");
215
		s = s.split("<").join("&lt;")
216
		s = s.split(">").join("&gt;")
217
		s = s.split('"').join("&quot;");
218
		s = s.split("'").join("&apos;");
219
		return s;
220
	},
221
	escapeHTML: function(encodeEntities = true, encodeHighUnicodeChars = true, encodeAll = false){
222
		var text = this;
223
		if (text == null) {
224
			return "";
225
		}
226
		var sb = [];
227
		var len = text.length;
228
		for (var i = 0;i<len;i++){
229
			
230
			var charIndex;
231
			if (encodeEntities) {
232
				var charName = null;
233
				charIndex = UB.htmlCharUTF.indexOf(text.charAt(i));
234
				if (charIndex === -1) {
235
					charIndex = UB.htmlCharUTF2.indexOf(text.charAt(i));
236
					if (charIndex > -1) {
237
						charName = UB.htmlCharNames2[charIndex];
238
					}
239
				}else {
240
					charName = UB.htmlCharNames[charIndex];
241
				}
242
				if (charName){
243
					
244
					// add entity name if known entity
245
					sb.push('&');
246
					sb.push(charName);
247
					sb.push(';');
248
					continue;
249
					
250
				}
251
				
252
			}
253
			
254
			if (encodeHighUnicodeChars) {
255
				var charUnicode = text.charCodeAt(i);
256
				if (encodeAll || charUnicode > 127) {
257
					sb.push("&#" + charUnicode + ";");
258
				} else {
259
					sb.push(text.charAt(i));
260
				}
261
				continue;
262
			}
263
		}
264
		return sb.join("");
265
	},
266
	
267
	unescapeDouble: function(){
268
		var src = this;
269
	
270
		// try with --- 'quelques \\ncaract\\u00e8res \\r ololo\\t\\" ' + " \\'" + 'lol\\/lol\\blol\\f\\tsp\\u00e9ciaux'
271
	
272
		var arr = src.split('\\');
273
		for (var i = 1;i<arr.length;i++){
274
			if (arr[i].charAt(0) != 'u') {
275
				arr[i] = UB.escapedDict[arr[i].charAt(0)] ? UB.escapedDict[arr[i].charAt(0)] + arr[i].substr(1) : arr[i];
276
			}else {
277
				arr[i] = String.fromCharCode('0x' + arr[i].slice(1, 5)) + arr[i].substr(5);
278
			}                
279
		}
280
		return arr.join('');
281
	},
282
	none:null
283
};
284
285
// register funcs
286
UB.registerFuncs(String.prototype, stringFuncs);
287