Spaces:
Running
Running
| // Forked from https://github.com/jsdom/jsdom/blob/main/lib/jsdom/living/helpers/strings.js | |
| ; | |
| // https://infra.spec.whatwg.org/#ascii-whitespace | |
| const asciiWhitespaceRe = /^[\t\n\f\r ]$/; | |
| exports.asciiWhitespaceRe = asciiWhitespaceRe; | |
| // https://infra.spec.whatwg.org/#ascii-lowercase | |
| exports.asciiLowercase = (s) => { | |
| const len = s.length; | |
| const out = new Array(len); | |
| for (let i = 0; i < len; i++) { | |
| const code = s.charCodeAt(i); | |
| // If the character is between 'A' (65) and 'Z' (90), convert using bitwise OR with 32 | |
| out[i] = code >= 65 && code <= 90 ? String.fromCharCode(code | 32) : s[i]; | |
| } | |
| return out.join(""); | |
| }; | |
| // https://infra.spec.whatwg.org/#ascii-uppercase | |
| exports.asciiUppercase = (s) => { | |
| const len = s.length; | |
| const out = new Array(len); | |
| for (let i = 0; i < len; i++) { | |
| const code = s.charCodeAt(i); | |
| // If the character is between 'a' (97) and 'z' (122), convert using bitwise AND with ~32 | |
| out[i] = code >= 97 && code <= 122 ? String.fromCharCode(code & ~32) : s[i]; | |
| } | |
| return out.join(""); | |
| }; | |
| // https://infra.spec.whatwg.org/#strip-newlines | |
| exports.stripNewlines = (s) => { | |
| return s.replace(/[\n\r]+/g, ""); | |
| }; | |
| // https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace | |
| exports.stripLeadingAndTrailingASCIIWhitespace = (s) => { | |
| return s.replace(/^[ \t\n\f\r]+/, "").replace(/[ \t\n\f\r]+$/, ""); | |
| }; | |
| // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace | |
| exports.stripAndCollapseASCIIWhitespace = (s) => { | |
| return s | |
| .replace(/[ \t\n\f\r]+/g, " ") | |
| .replace(/^[ \t\n\f\r]+/, "") | |
| .replace(/[ \t\n\f\r]+$/, ""); | |
| }; | |
| // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-simple-colour | |
| exports.isValidSimpleColor = (s) => { | |
| return /^#[a-fA-F\d]{6}$/.test(s); | |
| }; | |
| // https://infra.spec.whatwg.org/#ascii-case-insensitive | |
| exports.asciiCaseInsensitiveMatch = (a, b) => { | |
| if (a.length !== b.length) { | |
| return false; | |
| } | |
| for (let i = 0; i < a.length; ++i) { | |
| if ((a.charCodeAt(i) | 32) !== (b.charCodeAt(i) | 32)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }; | |
| // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-integers | |
| // Error is represented as null. | |
| const parseInteger = (exports.parseInteger = (input) => { | |
| // The implementation here is slightly different from the spec's. We want to use parseInt(), but parseInt() trims | |
| // Unicode whitespace in addition to just ASCII ones, so we make sure that the trimmed prefix contains only ASCII | |
| // whitespace ourselves. | |
| const numWhitespace = input.length - input.trimStart().length; | |
| if (/[^\t\n\f\r ]/.test(input.slice(0, numWhitespace))) { | |
| return null; | |
| } | |
| // We don't allow hexadecimal numbers here. | |
| // eslint-disable-next-line radix | |
| const value = parseInt(input, 10); | |
| if (Number.isNaN(value)) { | |
| return null; | |
| } | |
| // parseInt() returns -0 for "-0". Normalize that here. | |
| return value === 0 ? 0 : value; | |
| }); | |
| // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-non-negative-integers | |
| // Error is represented as null. | |
| exports.parseNonNegativeInteger = (input) => { | |
| const value = parseInteger(input); | |
| if (value === null) { | |
| return null; | |
| } | |
| if (value < 0) { | |
| return null; | |
| } | |
| return value; | |
| }; | |
| // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number | |
| const floatingPointNumRe = /^-?(?:\d+|\d*\.\d+)(?:[eE][-+]?\d+)?$/; | |
| exports.isValidFloatingPointNumber = (str) => floatingPointNumRe.test(str); | |
| // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values | |
| // Error is represented as null. | |
| exports.parseFloatingPointNumber = (str) => { | |
| // The implementation here is slightly different from the spec's. We need to use parseFloat() in order to retain | |
| // accuracy, but parseFloat() trims Unicode whitespace in addition to just ASCII ones, so we make sure that the | |
| // trimmed prefix contains only ASCII whitespace ourselves. | |
| const numWhitespace = str.length - str.trimStart().length; | |
| if (/[^\t\n\f\r ]/.test(str.slice(0, numWhitespace))) { | |
| return null; | |
| } | |
| const parsed = parseFloat(str); | |
| return isFinite(parsed) ? parsed : null; | |
| }; | |
| // https://infra.spec.whatwg.org/#split-on-ascii-whitespace | |
| exports.splitOnASCIIWhitespace = (str) => { | |
| let position = 0; | |
| const tokens = []; | |
| while (position < str.length && asciiWhitespaceRe.test(str[position])) { | |
| position++; | |
| } | |
| if (position === str.length) { | |
| return tokens; | |
| } | |
| while (position < str.length) { | |
| const start = position; | |
| while (position < str.length && !asciiWhitespaceRe.test(str[position])) { | |
| position++; | |
| } | |
| tokens.push(str.slice(start, position)); | |
| while (position < str.length && asciiWhitespaceRe.test(str[position])) { | |
| position++; | |
| } | |
| } | |
| return tokens; | |
| }; | |
| // https://infra.spec.whatwg.org/#split-on-commas | |
| exports.splitOnCommas = (str) => { | |
| let position = 0; | |
| const tokens = []; | |
| while (position < str.length) { | |
| let start = position; | |
| while (position < str.length && str[position] !== ",") { | |
| position++; | |
| } | |
| let end = position; | |
| while (start < str.length && asciiWhitespaceRe.test(str[start])) { | |
| start++; | |
| } | |
| while (end > start && asciiWhitespaceRe.test(str[end - 1])) { | |
| end--; | |
| } | |
| tokens.push(str.slice(start, end)); | |
| if (position < str.length) { | |
| position++; | |
| } | |
| } | |
| return tokens; | |
| }; | |