Spaces:
Paused
Paused
| const HEX: Record<string, number> = { | |
| '0': 0, | |
| '1': 1, | |
| '2': 2, | |
| '3': 3, | |
| '4': 4, | |
| '5': 5, | |
| '6': 6, | |
| '7': 7, | |
| '8': 8, | |
| '9': 9, | |
| a: 10, | |
| A: 10, | |
| b: 11, | |
| B: 11, | |
| c: 12, | |
| C: 12, | |
| d: 13, | |
| D: 13, | |
| e: 14, | |
| E: 14, | |
| f: 15, | |
| F: 15 | |
| }; | |
| const UTF8 = { | |
| accept: 12, | |
| reject: 0, | |
| data: [ | |
| // Maps bytes to character to a transition | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, | |
| 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | |
| 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, | |
| 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 7, 10, 9, 9, 9, 11, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, | |
| // Maps a state to a new state when adding a transition | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 24, 36, 48, 60, 72, 84, 96, 0, 12, 12, 12, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, | |
| // Maps the current transition to a mask that needs to apply to the byte | |
| 0x7f, 0x3f, 0x3f, 0x3f, 0x00, 0x1f, 0x0f, 0x0f, 0x0f, 0x07, 0x07, 0x07 | |
| ] | |
| }; | |
| /** | |
| * Faster version of decodeURIComponent() that does not throw. | |
| * | |
| * @param string - the URL string to decode. | |
| * | |
| * @returns the decoded string or null if invalid. | |
| */ | |
| export function uriDecode(string: string) { | |
| let percentPos = string.indexOf('%'); | |
| if (percentPos === -1) { | |
| return string; | |
| } | |
| let decoded = ''; | |
| let last = 0; | |
| let codepoint = 0; | |
| let startOfOctets = percentPos; | |
| let state = UTF8.accept; | |
| while (percentPos > -1 && percentPos < string.length) { | |
| const high = resolveHex(string[percentPos + 1], 4); | |
| const low = resolveHex(string[percentPos + 2], 0); | |
| const byte = high | low; | |
| const type = UTF8.data[byte]; | |
| state = UTF8.data[256 + state + type]; | |
| codepoint = (codepoint << 6) | (byte & UTF8.data[364 + type]); | |
| if (state === UTF8.accept) { | |
| decoded += string.slice(last, startOfOctets); | |
| decoded += | |
| codepoint <= 0xffff | |
| ? String.fromCharCode(codepoint) | |
| : String.fromCharCode(0xd7c0 + (codepoint >> 10), 0xdc00 + (codepoint & 0x3ff)); | |
| codepoint = 0; | |
| last = percentPos + 3; | |
| percentPos = string.indexOf('%', last); | |
| startOfOctets = percentPos; | |
| continue; | |
| } | |
| if (state === UTF8.reject) { | |
| return null; | |
| } | |
| percentPos += 3; | |
| if (percentPos >= string.length || string[percentPos] !== '%') { | |
| return null; | |
| } | |
| } | |
| return decoded + string.slice(last); | |
| } | |
| function resolveHex(char: string, shift: number) { | |
| const i = HEX[char]; | |
| return i === undefined ? 255 : i << shift; | |
| } | |
| // Adapted from: | |
| // Copyright (c) 2017-2019 Justin Ridgewell, MIT Licensed, https://github.com/jridgewell/safe-decode-string-component | |
| // Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>, MIT Licensed, http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ | |