|
|
@ -548,3 +548,191 @@ function isFullwidthCodePoint(cp: number) { |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// Below adapted from https://github.com/pieroxy/lz-string
|
|
|
|
|
|
|
|
const keyStrBase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; |
|
|
|
const baseReverseDic: Record<string, Record<string, number>> = {}; |
|
|
|
function getBaseValue(alphabet: string, character: string | number) { |
|
|
|
if (!baseReverseDic[alphabet]) { |
|
|
|
baseReverseDic[alphabet] = {}; |
|
|
|
for (let i = 0; i < alphabet.length; i++) { |
|
|
|
baseReverseDic[alphabet][alphabet.charAt(i)] = i; |
|
|
|
} |
|
|
|
} |
|
|
|
return baseReverseDic[alphabet][character]; |
|
|
|
} |
|
|
|
|
|
|
|
export function decompressFromBase64LZString(input: string | undefined) { |
|
|
|
if (input == null || input === '') return ''; |
|
|
|
return ( |
|
|
|
_decompressLZString(input.length, 32, (index: number) => getBaseValue(keyStrBase64, input.charAt(index))) ?? '' |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
function _decompressLZString(length: number, resetValue: any, getNextValue: (index: number) => number) { |
|
|
|
const dictionary = []; |
|
|
|
let next; |
|
|
|
let enlargeIn = 4; |
|
|
|
let dictSize = 4; |
|
|
|
let numBits = 3; |
|
|
|
let entry: any = ''; |
|
|
|
const result = []; |
|
|
|
let i; |
|
|
|
let w: any; |
|
|
|
let bits; |
|
|
|
let resb; |
|
|
|
let maxpower; |
|
|
|
let power; |
|
|
|
let c; |
|
|
|
const data = { val: getNextValue(0), position: resetValue, index: 1 }; |
|
|
|
|
|
|
|
for (i = 0; i < 3; i += 1) { |
|
|
|
dictionary[i] = i; |
|
|
|
} |
|
|
|
|
|
|
|
bits = 0; |
|
|
|
maxpower = Math.pow(2, 2); |
|
|
|
power = 1; |
|
|
|
while (power != maxpower) { |
|
|
|
resb = data.val & data.position; |
|
|
|
data.position >>= 1; |
|
|
|
if (data.position == 0) { |
|
|
|
data.position = resetValue; |
|
|
|
data.val = getNextValue(data.index++); |
|
|
|
} |
|
|
|
bits |= (resb > 0 ? 1 : 0) * power; |
|
|
|
power <<= 1; |
|
|
|
} |
|
|
|
|
|
|
|
const fromCharCode = String.fromCharCode; |
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
switch ((next = bits)) { |
|
|
|
case 0: |
|
|
|
bits = 0; |
|
|
|
maxpower = Math.pow(2, 8); |
|
|
|
power = 1; |
|
|
|
while (power != maxpower) { |
|
|
|
resb = data.val & data.position; |
|
|
|
data.position >>= 1; |
|
|
|
if (data.position == 0) { |
|
|
|
data.position = resetValue; |
|
|
|
data.val = getNextValue(data.index++); |
|
|
|
} |
|
|
|
bits |= (resb > 0 ? 1 : 0) * power; |
|
|
|
power <<= 1; |
|
|
|
} |
|
|
|
c = fromCharCode(bits); |
|
|
|
break; |
|
|
|
case 1: |
|
|
|
bits = 0; |
|
|
|
maxpower = Math.pow(2, 16); |
|
|
|
power = 1; |
|
|
|
while (power != maxpower) { |
|
|
|
resb = data.val & data.position; |
|
|
|
data.position >>= 1; |
|
|
|
if (data.position == 0) { |
|
|
|
data.position = resetValue; |
|
|
|
data.val = getNextValue(data.index++); |
|
|
|
} |
|
|
|
bits |= (resb > 0 ? 1 : 0) * power; |
|
|
|
power <<= 1; |
|
|
|
} |
|
|
|
c = fromCharCode(bits); |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
return ''; |
|
|
|
} |
|
|
|
dictionary[3] = c; |
|
|
|
w = c; |
|
|
|
result.push(c); |
|
|
|
while (true) { |
|
|
|
if (data.index > length) { |
|
|
|
return ''; |
|
|
|
} |
|
|
|
|
|
|
|
bits = 0; |
|
|
|
maxpower = Math.pow(2, numBits); |
|
|
|
power = 1; |
|
|
|
while (power != maxpower) { |
|
|
|
resb = data.val & data.position; |
|
|
|
data.position >>= 1; |
|
|
|
if (data.position == 0) { |
|
|
|
data.position = resetValue; |
|
|
|
data.val = getNextValue(data.index++); |
|
|
|
} |
|
|
|
bits |= (resb > 0 ? 1 : 0) * power; |
|
|
|
power <<= 1; |
|
|
|
} |
|
|
|
|
|
|
|
switch ((c = bits)) { |
|
|
|
case 0: |
|
|
|
bits = 0; |
|
|
|
maxpower = Math.pow(2, 8); |
|
|
|
power = 1; |
|
|
|
while (power != maxpower) { |
|
|
|
resb = data.val & data.position; |
|
|
|
data.position >>= 1; |
|
|
|
if (data.position == 0) { |
|
|
|
data.position = resetValue; |
|
|
|
data.val = getNextValue(data.index++); |
|
|
|
} |
|
|
|
bits |= (resb > 0 ? 1 : 0) * power; |
|
|
|
power <<= 1; |
|
|
|
} |
|
|
|
|
|
|
|
dictionary[dictSize++] = fromCharCode(bits); |
|
|
|
c = dictSize - 1; |
|
|
|
enlargeIn--; |
|
|
|
break; |
|
|
|
case 1: |
|
|
|
bits = 0; |
|
|
|
maxpower = Math.pow(2, 16); |
|
|
|
power = 1; |
|
|
|
while (power != maxpower) { |
|
|
|
resb = data.val & data.position; |
|
|
|
data.position >>= 1; |
|
|
|
if (data.position == 0) { |
|
|
|
data.position = resetValue; |
|
|
|
data.val = getNextValue(data.index++); |
|
|
|
} |
|
|
|
bits |= (resb > 0 ? 1 : 0) * power; |
|
|
|
power <<= 1; |
|
|
|
} |
|
|
|
dictionary[dictSize++] = fromCharCode(bits); |
|
|
|
c = dictSize - 1; |
|
|
|
enlargeIn--; |
|
|
|
break; |
|
|
|
case 2: |
|
|
|
return result.join(''); |
|
|
|
} |
|
|
|
|
|
|
|
if (enlargeIn == 0) { |
|
|
|
enlargeIn = Math.pow(2, numBits); |
|
|
|
numBits++; |
|
|
|
} |
|
|
|
|
|
|
|
if (dictionary[c]) { |
|
|
|
entry = dictionary[c]!; |
|
|
|
} else if (c === dictSize) { |
|
|
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
|
|
entry = w + w.charAt(0); |
|
|
|
} else { |
|
|
|
return undefined; |
|
|
|
} |
|
|
|
result.push(entry); |
|
|
|
|
|
|
|
// Add w+entry[0] to the dictionary.
|
|
|
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
|
|
dictionary[dictSize++] = w + entry.charAt(0); |
|
|
|
enlargeIn--; |
|
|
|
|
|
|
|
w = entry; |
|
|
|
|
|
|
|
if (enlargeIn == 0) { |
|
|
|
enlargeIn = Math.pow(2, numBits); |
|
|
|
numBits++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |