Procházet zdrojové kódy

use String#codePointAt

Gildas před 7 roky
rodič
revize
32efa45910
1 změnil soubory, kde provedl 40 přidání a 60 odebrání
  1. 40 60
      lib/single-file/css-declarations-parser.js

+ 40 - 60
lib/single-file/css-declarations-parser.js

@@ -44,16 +44,11 @@ this.parseCss = this.parseCss || (() => {
 	const DECLARATION_TYPE = "DECLARATION";
 	const FUNCTION_TYPE = "FUNCTION";
 
-	function between(num, first, last) { return num >= first && num <= last; }
-	function digit(code) { return between(code, 0x30, 0x39); }
-	function hexdigit(code) { return digit(code) || between(code, 0x41, 0x46) || between(code, 0x61, 0x66); }
-	function uppercaseletter(code) { return between(code, 0x41, 0x5a); }
-	function lowercaseletter(code) { return between(code, 0x61, 0x7a); }
-	function letter(code) { return uppercaseletter(code) || lowercaseletter(code); }
-	function nonascii(code) { return code >= 0x80; }
-	function namestartchar(code) { return letter(code) || nonascii(code) || code == 0x5f; }
+	function digit(code) { return code >= 0x30 && code <= 0x39; }
+	function hexdigit(code) { return digit(code) || code >= 0x41 && code <= 0x46 || code >= 0x61 && code <= 0x66; }
+	function namestartchar(code) { return code >= 0x41 && code <= 0x5a || code >= 0x61 && code <= 0x7a || code >= 0x80 || code == 0x5f; }
 	function namechar(code) { return namestartchar(code) || digit(code) || code == 0x2d; }
-	function nonprintable(code) { return between(code, 0, 8) || code == 0xb || between(code, 0xe, 0x1f) || code == 0x7f; }
+	function nonprintable(code) { return code >= 0 && code <= 8 || code == 0xb || code >= 0xe && code <= 0x1f || code == 0x7f; }
 	function newline(code) { return code == 0xa; }
 	function whitespace(code) { return newline(code) || code == 9 || code == 0x20; }
 
@@ -64,33 +59,17 @@ this.parseCss = this.parseCss || (() => {
 		// following the preprocessing cleanup rules.
 		const codepoints = [];
 		for (let i = 0; i < str.length; i++) {
-			let code = str.charCodeAt(i);
-			if (code == 0xd && str.charCodeAt(i + 1) == 0xa) {
+			let code = str.codePointAt(i);
+			if (code == 0xd && str.codePointAt(i + 1) == 0xa) {
 				code = 0xa; i++;
 			}
 			if (code == 0xd || code == 0xc) code = 0xa;
 			if (code == 0x0) code = 0xfffd;
-			if (between(code, 0xd800, 0xdbff) && between(str.charCodeAt(i + 1), 0xdc00, 0xdfff)) {
-				// Decode a surrogate pair into an astral codepoint.
-				const lead = code - 0xd800;
-				const trail = str.charCodeAt(i + 1) - 0xdc00;
-				code = Math.pow(2, 20) + lead * Math.pow(2, 10) + trail;
-				i++;
-			}
 			codepoints.push(code);
 		}
 		return codepoints;
 	}
 
-	function stringFromCode(code) {
-		if (code <= 0xffff) return String.fromCharCode(code);
-		// Otherwise, encode astral char as surrogate pair.
-		code -= Math.pow(2, 20);
-		const lead = Math.floor(code / Math.pow(2, 10)) + 0xd800;
-		const trail = code % Math.pow(2, 10) + 0xdc00;
-		return String.fromCharCode(lead) + String.fromCharCode(trail);
-	}
-
 	function consumeAToken(consume, next, eof, reconsume, parseerror, donothing) {
 		consumeComments(consume, next, eof, parseerror);
 		let code = consume();
@@ -108,14 +87,14 @@ this.parseCss = this.parseCss || (() => {
 						token.value = consumeAName(consume, next, eof, reconsume);
 						return token;
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x24:
 					if (next() == 0x3d) {
 						code = consume();
 						return new Token(SUFFIX_MATCH_TOKEN_TYPE);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x27:
 					return consumeAStringToken(consume, next, eof, reconsume, parseerror, donothing, code);
@@ -128,14 +107,14 @@ this.parseCss = this.parseCss || (() => {
 						code = consume();
 						return new Token(SUBSTRING_MATCH_TOKEN_TYPE);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x2b:
 					if (startsWithANumber(next, code)) {
 						reconsume();
 						return consumeANumericToken(consume, next, eof, reconsume);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x2c:
 					return new Token(COMMA_TOKEN_TYPE);
@@ -150,14 +129,14 @@ this.parseCss = this.parseCss || (() => {
 						reconsume();
 						return consumeAnIdentlikeToken(consume, next, eof, reconsume, parseerror, donothing);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x2e:
 					if (startsWithANumber(next, code)) {
 						reconsume();
 						return consumeANumericToken(consume, next, eof, reconsume);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x3a:
 					return new Token(COLON_TOKEN_TYPE);
@@ -168,10 +147,10 @@ this.parseCss = this.parseCss || (() => {
 						consume(3);
 						return new Token(CDO_TOKEN_TYPE);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x40:
-					return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+					return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 				case 0x5b:
 					return new Token(OPEN_SQUARE_TOKEN_TYPE);
 				case 0x5c:
@@ -180,7 +159,7 @@ this.parseCss = this.parseCss || (() => {
 						return consumeAnIdentlikeToken(consume, next, eof, reconsume, parseerror, donothing);
 					} else {
 						parseerror();
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x5d:
 					return new Token(CLOSE_SQUARE_TOKEN_TYPE);
@@ -189,7 +168,7 @@ this.parseCss = this.parseCss || (() => {
 						code = consume();
 						return new Token(PREFIX_MATCH_TOKEN_TYPE);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x7b:
 					return new Token(OPEN_CURLY_TOKEN_TYPE);
@@ -201,7 +180,7 @@ this.parseCss = this.parseCss || (() => {
 						code = consume();
 						return new Token(COLUMN_TOKEN_TYPE);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				case 0x7d:
 					return new Token(CLOSE_CURLY_TOKEN_TYPE);
@@ -210,7 +189,7 @@ this.parseCss = this.parseCss || (() => {
 						code = consume();
 						return new Token(INCLUDE_MATCH_TOKEN_TYPE);
 					} else {
-						return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+						return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 					}
 				default:
 					if (digit(code)) {
@@ -222,7 +201,7 @@ this.parseCss = this.parseCss || (() => {
 						return consumeAnIdentlikeToken(consume, next, eof, reconsume, parseerror, donothing);
 					}
 					else if (eof()) return new Token(EOF_TOKEN_TYPE);
-					else return new Token(DELIM_TOKEN_TYPE, stringFromCode(code));
+					else return new Token(DELIM_TOKEN_TYPE, String.fromCodePoint(code));
 			}
 		}
 	}
@@ -302,10 +281,10 @@ this.parseCss = this.parseCss || (() => {
 				} else if (newline(next())) {
 					code = consume();
 				} else {
-					string += stringFromCode(consumeEscape(consume, next, eof));
+					string += String.fromCodePoint(consumeEscape(consume, next, eof));
 				}
 			} else {
-				string += stringFromCode(code);
+				string += String.fromCodePoint(code);
 			}
 		}
 	}
@@ -333,14 +312,14 @@ this.parseCss = this.parseCss || (() => {
 				return new Token(BAD_URL_TOKEN_TYPE);
 			} else if (code == 0x5c) {
 				if (startsWithAValidEscape(next, code)) {
-					token.value += stringFromCode(consumeEscape(consume, next, eof));
+					token.value += String.fromCodePoint(consumeEscape(consume, next, eof));
 				} else {
 					parseerror();
 					consumeTheRemnantsOfABadURL(consume, next, eof, donothing);
 					return new Token(BAD_URL_TOKEN_TYPE);
 				}
 			} else {
-				token.value += stringFromCode(code);
+				token.value += String.fromCodePoint(code);
 			}
 		}
 	}
@@ -417,9 +396,9 @@ this.parseCss = this.parseCss || (() => {
 		let code;
 		while (code = consume()) { // eslint-disable-line no-cond-assign
 			if (namechar(code)) {
-				result += stringFromCode(code);
+				result += String.fromCodePoint(code);
 			} else if (startsWithAValidEscape(next, code)) {
-				result += stringFromCode(consumeEscape(consume, next, eof));
+				result += String.fromCodePoint(consumeEscape(consume, next, eof));
 			} else {
 				reconsume();
 				return result;
@@ -433,45 +412,45 @@ this.parseCss = this.parseCss || (() => {
 		let code;
 		if (next() == 0x2b || next() == 0x2d) {
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 		}
 		while (digit(next())) {
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 		}
 		if (next(1) == 0x2e && digit(next(2))) {
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 			type = "number";
 			while (digit(next())) {
 				code = consume();
-				repr += stringFromCode(code);
+				repr += String.fromCodePoint(code);
 			}
 		}
 		const c1 = next(1), c2 = next(2), c3 = next(3);
 		if ((c1 == 0x45 || c1 == 0x65) && digit(c2)) {
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 			type = "number";
 			while (digit(next())) {
 				code = consume();
-				repr += stringFromCode(code);
+				repr += String.fromCodePoint(code);
 			}
 		} else if ((c1 == 0x45 || c1 == 0x65) && (c2 == 0x2b || c2 == 0x2d) && digit(c3)) {
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 			code = consume();
-			repr += stringFromCode(code);
+			repr += String.fromCodePoint(code);
 			type = "number";
 			while (digit(next())) {
 				code = consume();
-				repr += stringFromCode(code);
+				repr += String.fromCodePoint(code);
 			}
 		}
 		const value = convertAStringToANumber(repr);
@@ -501,6 +480,7 @@ this.parseCss = this.parseCss || (() => {
 		str = preprocess(str);
 		let i = -1;
 		const tokens = [];
+		const strLength = str.length;
 		let code;
 
 		// Line number information.
@@ -517,7 +497,7 @@ this.parseCss = this.parseCss || (() => {
 		const locStart = { line, column };
 
 		const codepoint = function (i) {
-			if (i >= str.length) {
+			if (i >= strLength) {
 				return -1;
 			}
 			return str[i];
@@ -562,7 +542,7 @@ this.parseCss = this.parseCss || (() => {
 		while (!eof(next())) {
 			tokens.push(consumeAToken(consume, next, eof, reconsume, parseerror, donothing));
 			iterationCount++;
-			if (iterationCount > str.length * 2) return "I'm infinite-looping!";
+			if (iterationCount > strLength * 2) return "I'm infinite-looping!";
 		}
 		return tokens;
 	}