/* eslint-disable no-nested-ternary */ /* eslint-disable no-bitwise */ const utf16 = { // The utf16-class is necessary to convert from javascripts internal character representation to unicode and back. decode: (input) => { const output = []; let i = 0; const len = input.length; let value; let extra; while (i < len) { value = input.charCodeAt(i++); if ((value & 0xf800) === 0xd800) { extra = input.charCodeAt(i++); if ((value & 0xfc00) !== 0xd800 || (extra & 0xfc00) !== 0xdc00) { throw new RangeError('UTF-16(decode): Illegal UTF-16 sequence'); } value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; } output.push(value); } return output; }, encode: (input) => { const output = []; let i = 0; const len = input.length; let value; while (i < len) { value = input[i++]; if ((value & 0xf800) === 0xd800) { throw new RangeError('UTF-16(encode): Illegal UTF-16 value'); } if (value > 0xffff) { value -= 0x10000; output.push(String.fromCharCode(((value >>> 10) & 0x3ff) | 0xd800)); value = 0xdc00 | (value & 0x3ff); } output.push(String.fromCharCode(value)); } return output.join(''); }, }; // Default parameters const initial_n = 0x80; const initial_bias = 72; const delimiter = '\x2D'; const base = 36; const damp = 700; const tmin = 1; const tmax = 26; const skew = 38; const maxint = 0x7fffffff; // decode_digit(cp) returns the numeric value of a basic code // point (for use in representing integers) in the range 0 to // base-1, or base if cp is does not represent a value. function decode_digit(cp) { return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : cp - 97 < 26 ? cp - 97 : base; } // ** Bias adaptation function ** function adapt(delta, numpoints, firsttime) { let k; delta = firsttime ? Math.floor(delta / damp) : delta >> 1; delta += Math.floor(delta / numpoints); for (k = 0; delta > ((base - tmin) * tmax) >> 1; k += base) { delta = Math.floor(delta / (base - tmin)); } return Math.floor(k + ((base - tmin + 1) * delta) / (delta + skew)); } // Main decode function decode(input, preserveCase) { // Dont use utf16 const output = []; const case_flags = []; const input_length = input.length; let n; let out; let i; let bias; let basic; let j; let ic; let oldi; let w; let k; let digit; let t; let len; // Initialize the state: n = initial_n; i = 0; bias = initial_bias; // Handle the basic code points: Let basic be the number of input code // points before the last delimiter, or 0 if there is none, then // copy the first basic code points to the output. basic = input.lastIndexOf(delimiter); if (basic < 0) basic = 0; for (j = 0; j < basic; ++j) { if (preserveCase) case_flags[output.length] = input.charCodeAt(j) - 65 < 26; if (input.charCodeAt(j) >= 0x80) { throw new RangeError('Illegal input >= 0x80'); } output.push(input.charCodeAt(j)); } // Main decoding loop: Start just after the last delimiter if any // basic code points were copied; start at the beginning otherwise. for (ic = basic > 0 ? basic + 1 : 0; ic < input_length;) { // ic is the index of the next character to be consumed, // Decode a generalized variable-length integer into delta, // which gets added to i. The overflow checking is easier // if we increase i as we go, then subtract off its starting // value at the end to obtain delta. for (oldi = i, w = 1, k = base; ; k += base) { if (ic >= input_length) { throw RangeError('punycode_bad_input(1)'); } digit = decode_digit(input.charCodeAt(ic++)); if (digit >= base) { throw RangeError('punycode_bad_input(2)'); } if (digit > Math.floor((maxint - i) / w)) { throw RangeError('punycode_overflow(1)'); } i += digit * w; t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias; if (digit < t) { break; } if (w > Math.floor(maxint / (base - t))) { throw RangeError('punycode_overflow(2)'); } w *= base - t; } out = output.length + 1; bias = adapt(i - oldi, out, oldi === 0); // i was supposed to wrap around from out to 0, // incrementing n each time, so we'll fix that now: if (Math.floor(i / out) > maxint - n) { throw RangeError('punycode_overflow(3)'); } n += Math.floor(i / out); i %= out; // Insert n at position i of the output: // Case of last character determines uppercase flag: if (preserveCase) { case_flags.splice(i, 0, input.charCodeAt(ic - 1) - 65 < 26); } output.splice(i, 0, n); i++; } if (preserveCase) { for (i = 0, len = output.length; i < len; i++) { if (case_flags[i]) { output[i] = String.fromCharCode(output[i]) .toUpperCase() .charCodeAt(0); } } } return utf16.encode(output); } function toUnicode(domain) { const domain_array = domain.split('.'); const out = []; for (let i = 0; i < domain_array.length; ++i) { const s = domain_array[i]; out.push(s.match(/^xn--/) ? decode(s.slice(4)) : s); } return out.join('.'); } export default toUnicode;