diff options
Diffstat (limited to 'vanilla/node_modules/whatwg-url/lib/percent-encoding.js')
| -rw-r--r-- | vanilla/node_modules/whatwg-url/lib/percent-encoding.js | 147 |
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 +}; |
