aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/whatwg-url/lib/percent-encoding.js
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
commit76cb9c2a39d477a64824a985ade40507e3bbade1 (patch)
tree41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/whatwg-url/lib/percent-encoding.js
parent819a39a21ac992b1393244a4c283bbb125208c69 (diff)
downloadneko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/whatwg-url/lib/percent-encoding.js')
-rw-r--r--vanilla/node_modules/whatwg-url/lib/percent-encoding.js147
1 files changed, 147 insertions, 0 deletions
diff --git a/vanilla/node_modules/whatwg-url/lib/percent-encoding.js b/vanilla/node_modules/whatwg-url/lib/percent-encoding.js
new file mode 100644
index 0000000..c4c86ec
--- /dev/null
+++ b/vanilla/node_modules/whatwg-url/lib/percent-encoding.js
@@ -0,0 +1,147 @@
+"use strict";
+const { isASCIIHex } = require("./infra");
+const { utf8Encode } = require("./encoding");
+
+function p(char) {
+ return char.codePointAt(0);
+}
+
+// https://url.spec.whatwg.org/#percent-encode
+function percentEncode(c) {
+ let hex = c.toString(16).toUpperCase();
+ if (hex.length === 1) {
+ hex = `0${hex}`;
+ }
+
+ return `%${hex}`;
+}
+
+// https://url.spec.whatwg.org/#percent-decode
+function percentDecodeBytes(input) {
+ const output = new Uint8Array(input.byteLength);
+ let outputIndex = 0;
+ for (let i = 0; i < input.byteLength; ++i) {
+ const byte = input[i];
+ if (byte !== 0x25) {
+ output[outputIndex++] = byte;
+ } else if (byte === 0x25 && (!isASCIIHex(input[i + 1]) || !isASCIIHex(input[i + 2]))) {
+ output[outputIndex++] = byte;
+ } else {
+ const bytePoint = parseInt(String.fromCodePoint(input[i + 1], input[i + 2]), 16);
+ output[outputIndex++] = bytePoint;
+ i += 2;
+ }
+ }
+
+ return output.slice(0, outputIndex);
+}
+
+// https://url.spec.whatwg.org/#string-percent-decode
+function percentDecodeString(input) {
+ const bytes = utf8Encode(input);
+ return percentDecodeBytes(bytes);
+}
+
+// https://url.spec.whatwg.org/#c0-control-percent-encode-set
+function isC0ControlPercentEncode(c) {
+ return c <= 0x1F || c > 0x7E;
+}
+
+// https://url.spec.whatwg.org/#fragment-percent-encode-set
+const extraFragmentPercentEncodeSet = new Set([p(" "), p("\""), p("<"), p(">"), p("`")]);
+function isFragmentPercentEncode(c) {
+ return isC0ControlPercentEncode(c) || extraFragmentPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#query-percent-encode-set
+const extraQueryPercentEncodeSet = new Set([p(" "), p("\""), p("#"), p("<"), p(">")]);
+const extraQueryPercentEncodeChars = String.fromCodePoint(...[...extraQueryPercentEncodeSet].sort());
+function isQueryPercentEncode(c) {
+ return isC0ControlPercentEncode(c) || extraQueryPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#special-query-percent-encode-set
+const extraSpecialQueryPercentEncodeSet = new Set([...extraQueryPercentEncodeSet, p("'")]);
+const extraSpecialQueryPercentEncodeChars = String.fromCodePoint(...[...extraSpecialQueryPercentEncodeSet].sort());
+function isSpecialQueryPercentEncode(c) {
+ return isC0ControlPercentEncode(c) || extraSpecialQueryPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#path-percent-encode-set
+const extraPathPercentEncodeSet = new Set([p("?"), p("`"), p("{"), p("}"), p("^")]);
+function isPathPercentEncode(c) {
+ return isQueryPercentEncode(c) || extraPathPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#userinfo-percent-encode-set
+const extraUserinfoPercentEncodeSet =
+ new Set([p("/"), p(":"), p(";"), p("="), p("@"), p("["), p("\\"), p("]"), p("|")]);
+function isUserinfoPercentEncode(c) {
+ return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#component-percent-encode-set
+const extraComponentPercentEncodeSet = new Set([p("$"), p("%"), p("&"), p("+"), p(",")]);
+function isComponentPercentEncode(c) {
+ return isUserinfoPercentEncode(c) || extraComponentPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#application-x-www-form-urlencoded-percent-encode-set
+const extraURLEncodedPercentEncodeSet = new Set([p("!"), p("'"), p("("), p(")"), p("~")]);
+function isURLEncodedPercentEncode(c) {
+ return isComponentPercentEncode(c) || extraURLEncodedPercentEncodeSet.has(c);
+}
+
+// https://url.spec.whatwg.org/#code-point-percent-encode-after-encoding
+// https://url.spec.whatwg.org/#utf-8-percent-encode
+// Assuming encoding is always utf-8 allows us to trim one of the logic branches. TODO: support encoding.
+// The "-Internal" variant here has code points as JS strings. The external version used by other files has code points
+// as JS numbers, like the rest of the codebase.
+function utf8PercentEncodeCodePointInternal(codePoint, percentEncodePredicate) {
+ const bytes = utf8Encode(codePoint);
+ let output = "";
+ for (const byte of bytes) {
+ // Our percentEncodePredicate operates on bytes, not code points, so this is slightly different from the spec.
+ if (!percentEncodePredicate(byte)) {
+ output += String.fromCharCode(byte);
+ } else {
+ output += percentEncode(byte);
+ }
+ }
+
+ return output;
+}
+
+function utf8PercentEncodeCodePoint(codePoint, percentEncodePredicate) {
+ return utf8PercentEncodeCodePointInternal(String.fromCodePoint(codePoint), percentEncodePredicate);
+}
+
+// https://url.spec.whatwg.org/#string-percent-encode-after-encoding
+// https://url.spec.whatwg.org/#string-utf-8-percent-encode
+function utf8PercentEncodeString(input, percentEncodePredicate, spaceAsPlus = false) {
+ let output = "";
+ for (const codePoint of input) {
+ if (spaceAsPlus && codePoint === " ") {
+ output += "+";
+ } else {
+ output += utf8PercentEncodeCodePointInternal(codePoint, percentEncodePredicate);
+ }
+ }
+ return output;
+}
+
+module.exports = {
+ isC0ControlPercentEncode,
+ isFragmentPercentEncode,
+ isQueryPercentEncode,
+ isSpecialQueryPercentEncode,
+ isPathPercentEncode,
+ isUserinfoPercentEncode,
+ isURLEncodedPercentEncode,
+ extraQueryPercentEncodeChars,
+ extraSpecialQueryPercentEncodeChars,
+ percentDecodeString,
+ percentDecodeBytes,
+ utf8PercentEncodeString,
+ utf8PercentEncodeCodePoint
+};