Passed
Push — master ( 09858a...f82812 )
by Night
01:11
created

stringFuncs.uppercaseFirst   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
/** global: UB */
2
3
// CASING
4
5
// PROVIDES THE TABLES USED FOR FAST CASE-INSENSITIVE STRING COMPARISON
6
// FOR THESE TABLES SEE "unicode uppercase lowercase tables.xlsx"
7
8
// meta tables
9
UB.UTF_casingRangedLowerS = [97, 224, 1072, 1121, 1169, 1377, 4304, 7681, 7841, 9424];
10
UB.UTF_casingRangedLowerE = [122, 246, 1103, 1153, 1215, 1414, 4341, 7829, 7929, 9449];
11
UB.UTF_casingRangedIncrement = [1, 1, 1, 2, 2, 1, 1, 2, 2, 1];
12
UB.UTF_casingRangedUpper = [65, 192, 1040, 1120, 1168, 1329, 4256, 7680, 7840, 9398];
13
14
// raw tables
15
UB.UTF_casingRawLower = [248, 249, 250, 251, 252, 253, 254, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, 295, 297, 299, 301, 303, 305, 307, 309, 311, 314, 316, 318, 320, 322, 324, 326, 328, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 378, 380, 382, 387, 389, 392, 396, 402, 409, 417, 419, 421, 424, 429, 432, 436, 438, 441, 445, 454, 457, 460, 462, 464, 466, 468, 470, 472, 474, 476, 479, 481, 483, 485, 487, 489, 491, 493, 495, 499, 501, 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535, 595, 596, 599, 600, 601, 603, 608, 611, 616, 617, 623, 626, 629, 643, 648, 650, 651, 658, 940, 941, 942, 943, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 995, 997, 999, 1001, 1003, 1005, 1007, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1118, 1119, 1218, 1220, 1224, 1228, 1233, 1235, 1237, 1239, 1241, 1243, 1245, 1247, 1249, 1251, 1253, 1255, 1257, 1259, 1263, 1265, 1267, 1269, 1273, 7936, 7937, 7938, 7939, 7940, 7941, 7942, 7943, 7952, 7953, 7954, 7955, 7956, 7957, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7984, 7985, 7986, 7987, 7988, 7989, 7990, 7991, 8000, 8001, 8002, 8003, 8004, 8005, 8017, 8019, 8021, 8023, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8096, 8097, 8098, 8099, 8100, 8101, 8102, 8103, 8112, 8113, 8144, 8145, 8160, 8161];
16
UB.UTF_casingRawUpper = [216, 217, 218, 219, 220, 221, 222, 376, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 73, 306, 308, 310, 313, 315, 317, 319, 321, 323, 325, 327, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 377, 379, 381, 386, 388, 391, 395, 401, 408, 416, 418, 420, 423, 428, 431, 435, 437, 440, 444, 452, 455, 458, 461, 463, 465, 467, 469, 471, 473, 475, 478, 480, 482, 484, 486, 488, 490, 492, 494, 497, 500, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 385, 390, 394, 398, 399, 400, 403, 404, 407, 406, 412, 413, 415, 425, 430, 433, 434, 439, 902, 904, 905, 906, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 908, 910, 911, 994, 996, 998, 1000, 1002, 1004, 1006, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1038, 1039, 1217, 1219, 1223, 1227, 1232, 1234, 1236, 1238, 1240, 1242, 1244, 1246, 1248, 1250, 1252, 1254, 1256, 1258, 1262, 1264, 1266, 1268, 1272, 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7951, 7960, 7961, 7962, 7963, 7964, 7965, 7976, 7977, 7978, 7979, 7980, 7981, 7982, 7983, 7992, 7993, 7994, 7995, 7996, 7997, 7998, 7999, 8008, 8009, 8010, 8011, 8012, 8013, 8025, 8027, 8029, 8031, 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 8072, 8073, 8074, 8075, 8076, 8077, 8078, 8079, 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8120, 8121, 8152, 8153, 8168, 8169];
17
18
19
// final tables (= ranged + raw)
20
UB.UTF_casingTablesMax = 9450;
21
22
UB.initCasing = function(){
23
	
24
	// exit if already initialized
25
	if (UB.UTF_lowerToUpper != null){
26
		return;
27
	}
28
	
29
	// CALC CASING CONVERSION TABLES
30
	UB.UTF_lowerToUpper = [];
31
	UB.UTF_upperToLower = [];
32
	
33
	// init by mapping to self (most chars dont have an uppercase/lowercase version)
34
	for (var n = 0, nlast = UB.UTF_casingTablesMax;n <= nlast;n++){
35
		UB.UTF_lowerToUpper[n] = n;
36
		UB.UTF_upperToLower[n] = n;
37
	}
38
	
39
	// per range
40
	for (var r = 0, rl = UB.UTF_casingRangedLowerS.length;r<rl;r++){
41
		
42
		// per value in range
43
		var inc = UB.UTF_casingRangedIncrement[r];
44
		var offset = UB.UTF_casingRangedUpper[r] - UB.UTF_casingRangedLowerS[r];
45
		for (var lower = UB.UTF_casingRangedLowerS[r], lowerlast = UB.UTF_casingRangedLowerE[r];lower <= lowerlast;lower += inc){
46
			
47
			// calc uppercase
48
			var upper = lower + offset;
49
			
50
			// store in table
51
			UB.UTF_lowerToUpper[lower] = upper;
52
			UB.UTF_upperToLower[upper] = lower;
53
			
54
		}
55
		
56
	}
57
	
58
	// per raw value
59
	for (var n = 0, nl = UB.UTF_casingRawLower.length;n<nl;n++){
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable n already seems to be declared on line 34. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
60
		
61
		lower = UB.UTF_casingRawLower[n];
62
		upper = UB.UTF_casingRawUpper[n];
63
		
64
		// store in table
65
		UB.UTF_lowerToUpper[lower] = upper;
66
		UB.UTF_upperToLower[upper] = lower;
67
		
68
	}
69
	
70
	// fix bug in unicode table .. "I" >> "i"
71
	UB.UTF_upperToLower[73] = 105;
72
	
73
	
74
}
75
76
77
var arrayFuncs = {
78
79
	camelCaseMergeWords: function(firstCharCaps = false){
80
		var words = this;
81
		
82
		// lowercase first letter
83
		words[0] = firstCharCaps ? words[0].uppercaseFirst() : words[0].lowercaseFirst();
84
		
85
		// loop thru all words
86
		var newWords = "";
87
		for (var w = 0, wl = words.length;w<wl;w++){
88
			var word = words[w].replace(UB.regex.Trim, '');
89
			
90
			// cap first letter if not 1st word
91
			newWords += w === 0 ? word : word.uppercaseFirst();
92
		}
93
		return newWords;
94
	},
95
	
96
	none:null
97
};
98
99
// register funcs
100
UB.registerFuncs(Array.prototype, arrayFuncs);
101
102
103
var stringFuncs = {
104
	
105
	// casing
106
	camelCaseSeperate: function(){
107
		var camelCase = this;
108
		
109
		// loop thru all chars
110
		var lastUp = false;
111
		var lastSpace = false;
112
		var newName = [];
113
		var len = 0;
114
		for (var c = 0, cl = camelCase.length - 1;c <= cl;c++){
115
			var char = camelCase.charAt(c);
116
			var charNext = c < cl ? camelCase.charAt(c + 1) : "_";
117
			
118
			// if its a Capital ... and if prev is not also a capital ... or if the next is small
119
			var up = (char.toUpperCase() == char);
120
			var nextUp = (charNext.toUpperCase() == charNext);
121
			if ((up && (!lastUp || !nextUp) && !lastSpace) || char == "_") {
122
				
123
				// add a space
124
				if (len > 0 && newName[len - 1] != " "){
125
					newName.push(" ");
126
					len++;
127
				}
128
			}
129
			lastUp = up;
130
			
131
			// add the char
132
			if (char != "_"){
133
				newName.push(char);
134
				len++;
135
			}
136
			lastSpace = char == " ";
137
		}
138
		
139
		// caps first letter
140
		return newName.join("").uppercaseFirst();
141
	},
142
	camelCaseSeperateWords: function(){
143
		var camelCase = this;
144
		return camelCase.camelCaseSeperate().split(" ");
145
	},
146
	camelCaseMerge: function(firstCharCaps = false){
147
		var sentence = this;
148
		
149
		// exit quickly if no spaces .. no words to merge
150
		if (sentence.indexOf(" ") === -1) {
151
			if (firstCharCaps) {
152
				return sentence.uppercaseFirst();
153
			}
154
			return sentence;
155
		}
156
		
157
		// merge words using camel case
158
		return sentence.split(" ").camelCaseMergeWords(firstCharCaps);
159
	},
160
	uppercaseFirst: function(){
161
		var str = this;
162
		str = str.trim();
163
		return str.charAt(0).toUpperCase() + str.substr(1);
164
	},
165
	lowercaseFirst: function(){
166
		var str = this;
167
		str = str.trim();
168
		return str.charAt(0).toLowerCase() + str.substr(1);
169
	},
170
	toSmartCase: function(){
171
		var word = this;
172
		// home loan > Home Loan
173
		// PRNQ loan > PRNQ Loan
174
		return word.toCustomCase(";,. -_" + "\t" + "\n", true);
175
	},
176
	toSentenceCase: function(){
177
		var word = this;
178
		return word.toCustomCase(".", false);
179
	},
180
	toCustomCase: function(capsAfterChars, preserveCaps = false){
181
		var word = this;
182
		var nextCaps = true;// first char caps
183
		
184
		// per char
185
		var chars = word.splitChars();
186
		var chars2 = [];
187
		for (var c = 0, cl = chars.length;c<cl;c++){
188
			var ch = chars[c];
189
			var added = false;
190
			
191
			// add as CAPS if wanted
192
			if (nextCaps) {
193
				nextCaps = false;
194
				chars2.push(ch.toUpperCase());
195
				added = true;
196
			}
197
			
198
			// next char should have caps
199
			if (capsAfterChars.indexOf(ch) > -1) {
200
				nextCaps = true;
201
			}
202
			
203
			// add normally
204
			if (!added) {
205
				
206
				// preserve caps if wanted
207
				if (preserveCaps && ch.toUpperCase() == ch) {
208
					chars2.push(ch);
209
				}else {
210
					
211
					// add as lower case
212
					chars2.push(ch.toLowerCase());
213
				}
214
			}
215
		}
216
		return chars2.join("");
217
	},
218
	toTitleCase: function(){
219
		var word = this;
220
		// home loan > Home Loan
221
		// PRNQ loan > Prnq Loan
222
		return word.toCustomCase(";,. -_" + "\t" + "\n", false);
223
	},
224
	toSentenceTitleCase: function(){
225
		var title = this;
226
		var parts = [];
227
		var index = 0;
228
		
229
		// create regexps
230
		var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)";
231
		var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)";
232
		var r1 =  new RegExp("\\b([A-Za-z][a-z.'Õ]*)\\b", "g");
233
		var r2 =  new RegExp("[A-Za-z]\\.[A-Za-z]", "");
234
		var r3 =  new RegExp("\\b" + small + "\\b", "ig");
235
		var r4 =  new RegExp("^" + punct + small + "\\b", "ig");
236
		var r5 =  new RegExp("\\b" + small + punct + "$", "ig");
237
		var r6 =  new RegExp(" V(s?)\\. ", "ig");
238
		var r7 =  new RegExp("(['Õ])S\\b", "ig");
239
		var split =  new RegExp("[:.;?!] |(?: |^)[\"Ò]", "g");
240
		
241
		// per word in string
242
		while (true) {
243
			var m = split.exec(title);
244
			
245
			var ToLowerCase = function(x){
246
				return x.toLowerCase();
247
			}
248
			var ToUpperCaseFirst = function(x){
249
				return x.uppercaseFirst();
250
			}
251
252
			// smart capatalize
253
			parts.push( title.substring(index, m ? m.index : title.length).replace(r1, function(all) {
254
				return r2.test(all) ? all : all.uppercaseFirst();
255
			}).replace(r3, ToLowerCase).replace(r4, function (all, punct, word){
256
				return punct + word.uppercaseFirst();
257
			}).replace(r5, ToUpperCaseFirst));
258
			
259
			index = split.lastIndex;
260
			
261
			if ( m ) parts.push( m[0] );
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
262
			else break;
263
		}
264
		
265
		return parts.join("").replace(r6, " v$1. ").replace(r7, "$1s");
266
	},
267
	toCamelCase: function(){
268
		var word = this;
269
		return word.camelCaseMerge(false);
270
	},
271
	toPascalCase: function(){
272
		var word = this;
273
		return word.camelCaseMerge(true);
274
	},
275
	toURLCase: function(){
276
		var path = this;
277
		path = path.removeAll("&");
278
		path = path.removeAll("\"");
279
		path = path.removeAll("'");
280
		path = path.removeAll(",");
281
		path = path.removeAll("?");
282
		path = path.setSlash("/").replaceAll(" ", "-");	
283
		path = path.replaceAll("----", "-");
284
		path = path.replaceAll("---", "-");
285
		path = path.replaceAll("--", "-");
286
		return path.toLowerCase();
287
	},
288
	pascalToCamelCase: function(){
289
		var word = this;
290
		
291
		// no change if already begins with lowercase letter
292
		if (word.substr(0, 1).isLowercase()) {
293
			return word;
294
		}
295
		
296
		// make the first word lowercase
297
		
298
		// if >2 chars are uppercase
299
		var num = word.countStartingUppercase();
300
		if (num > 2) {	
301
			
302
			// lowercase all uppercase chars (except the last)
303
			return word.lowercaseFirstX(num - 1);
304
		}
305
		
306
		// lowercase first char only
307
		return word.lowercaseFirst();
308
	},
309
	uppercaseFirstX: function(numOfChars){
310
		var text = this;
311
		return text.setRange(0, numOfChars - 1, text.getRange(0, numOfChars - 1).toUpperCase());
312
	},
313
	lowercaseFirstX: function(numOfChars){
314
		var text = this;
315
		return text.setRange(0, numOfChars - 1, text.getRange(0, numOfChars - 1).toLowerCase());
316
	},
317
	none:null
318
};
319
320
// register funcs
321
UB.registerFuncs(String.prototype, stringFuncs);