thedesk/app/js/platform/punycode.js

510 lines
14 KiB
JavaScript
Raw Permalink Normal View History

2019-11-25 00:26:19 +11:00
'use strict'
2019-07-15 01:56:19 +10:00
/*! https://mths.be/punycode v1.4.1 by @mathias */
;(function(root) {
/** Detect free variables */
2019-11-09 00:52:54 +11:00
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports
var freeModule = typeof module == 'object' && module && !module.nodeType && module
var freeGlobal = typeof global == 'object' && global
2019-07-15 01:56:19 +10:00
if (
freeGlobal.global === freeGlobal ||
freeGlobal.window === freeGlobal ||
freeGlobal.self === freeGlobal
) {
2019-11-09 00:52:54 +11:00
root = freeGlobal
2019-07-15 01:56:19 +10:00
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
2019-11-09 00:52:54 +11:00
/** Highest positive signed 32-bit float value */
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128, // 0x80
delimiter = '-', // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
/** Error messages */
errors = {
overflow: 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key
2019-07-15 01:56:19 +10:00
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
2019-11-09 00:52:54 +11:00
throw new RangeError(errors[type])
2019-07-15 01:56:19 +10:00
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
2019-11-09 00:52:54 +11:00
var length = array.length
var result = []
2019-07-15 01:56:19 +10:00
while (length--) {
2019-11-09 00:52:54 +11:00
result[length] = fn(array[length])
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
return result
2019-07-15 01:56:19 +10:00
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings or email
* addresses.
* @private
* @param {String} domain The domain name or email address.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
2019-11-09 00:52:54 +11:00
var parts = string.split('@')
var result = ''
2019-07-15 01:56:19 +10:00
if (parts.length > 1) {
// In email addresses, only the domain name should be punycoded. Leave
// the local part (i.e. everything up to `@`) intact.
2019-11-09 00:52:54 +11:00
result = parts[0] + '@'
string = parts[1]
2019-07-15 01:56:19 +10:00
}
// Avoid `split(regex)` for IE8 compatibility. See #17.
2019-11-09 00:52:54 +11:00
string = string.replace(regexSeparators, '\x2E')
var labels = string.split('.')
var encoded = map(labels, fn).join('.')
return result + encoded
2019-07-15 01:56:19 +10:00
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
2019-11-09 00:52:54 +11:00
counter = 0,
length = string.length,
value,
extra
2019-07-15 01:56:19 +10:00
while (counter < length) {
2019-11-09 00:52:54 +11:00
value = string.charCodeAt(counter++)
if (value >= 0xd800 && value <= 0xdbff && counter < length) {
2019-07-15 01:56:19 +10:00
// high surrogate, and there is a next character
2019-11-09 00:52:54 +11:00
extra = string.charCodeAt(counter++)
if ((extra & 0xfc00) == 0xdc00) {
// low surrogate
output.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000)
2019-07-15 01:56:19 +10:00
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
2019-11-09 00:52:54 +11:00
output.push(value)
counter--
2019-07-15 01:56:19 +10:00
}
} else {
2019-11-09 00:52:54 +11:00
output.push(value)
2019-07-15 01:56:19 +10:00
}
}
2019-11-09 00:52:54 +11:00
return output
2019-07-15 01:56:19 +10:00
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function(value) {
2019-11-09 00:52:54 +11:00
var output = ''
if (value > 0xffff) {
value -= 0x10000
output += stringFromCharCode(((value >>> 10) & 0x3ff) | 0xd800)
value = 0xdc00 | (value & 0x3ff)
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
output += stringFromCharCode(value)
return output
}).join('')
2019-07-15 01:56:19 +10:00
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
2019-11-09 00:52:54 +11:00
return codePoint - 22
2019-07-15 01:56:19 +10:00
}
if (codePoint - 65 < 26) {
2019-11-09 00:52:54 +11:00
return codePoint - 65
2019-07-15 01:56:19 +10:00
}
if (codePoint - 97 < 26) {
2019-11-09 00:52:54 +11:00
return codePoint - 97
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
return base
2019-07-15 01:56:19 +10:00
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
2019-11-09 00:52:54 +11:00
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5)
2019-07-15 01:56:19 +10:00
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* https://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
2019-11-09 00:52:54 +11:00
var k = 0
delta = firstTime ? floor(delta / damp) : delta >> 1
delta += floor(delta / numPoints)
for (; /* no initialization */ delta > (baseMinusTMin * tMax) >> 1; k += base) {
delta = floor(delta / baseMinusTMin)
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
return floor(k + ((baseMinusTMin + 1) * delta) / (delta + skew))
2019-07-15 01:56:19 +10:00
}
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
2019-11-09 00:52:54 +11:00
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
/** Cached calculation results */
baseMinusT
2019-07-15 01:56:19 +10:00
// 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.
2019-11-09 00:52:54 +11:00
basic = input.lastIndexOf(delimiter)
2019-07-15 01:56:19 +10:00
if (basic < 0) {
2019-11-09 00:52:54 +11:00
basic = 0
2019-07-15 01:56:19 +10:00
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
2019-11-09 00:52:54 +11:00
error('not-basic')
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
output.push(input.charCodeAt(j))
2019-07-15 01:56:19 +10:00
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
2019-11-09 00:52:54 +11:00
for (index = basic > 0 ? basic + 1 : 0; index < inputLength /* no final expression */; ) {
2019-07-15 01:56:19 +10:00
// `index` 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`.
2019-11-09 00:52:54 +11:00
for (oldi = i, w = 1, k = base /* no condition */; ; k += base) {
2019-07-15 01:56:19 +10:00
if (index >= inputLength) {
2019-11-09 00:52:54 +11:00
error('invalid-input')
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
digit = basicToDigit(input.charCodeAt(index++))
2019-07-15 01:56:19 +10:00
if (digit >= base || digit > floor((maxInt - i) / w)) {
2019-11-09 00:52:54 +11:00
error('overflow')
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
i += digit * w
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias
2019-07-15 01:56:19 +10:00
if (digit < t) {
2019-11-09 00:52:54 +11:00
break
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
baseMinusT = base - t
2019-07-15 01:56:19 +10:00
if (w > floor(maxInt / baseMinusT)) {
2019-11-09 00:52:54 +11:00
error('overflow')
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
w *= baseMinusT
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
out = output.length + 1
bias = adapt(i - oldi, out, oldi == 0)
2019-07-15 01:56:19 +10:00
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
2019-11-09 00:52:54 +11:00
error('overflow')
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
n += floor(i / out)
i %= out
2019-07-15 01:56:19 +10:00
// Insert `n` at position `i` of the output
2019-11-09 00:52:54 +11:00
output.splice(i++, 0, n)
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
return ucs2encode(output)
2019-07-15 01:56:19 +10:00
}
/**
* Converts a string of Unicode symbols (e.g. a domain name label) to a
* Punycode string of ASCII-only symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
function encode(input) {
var n,
2019-11-09 00:52:54 +11:00
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT
2019-07-15 01:56:19 +10:00
// Convert the input in UCS-2 to Unicode
2019-11-09 00:52:54 +11:00
input = ucs2decode(input)
2019-07-15 01:56:19 +10:00
// Cache the length
2019-11-09 00:52:54 +11:00
inputLength = input.length
2019-07-15 01:56:19 +10:00
// Initialize the state
2019-11-09 00:52:54 +11:00
n = initialN
delta = 0
bias = initialBias
2019-07-15 01:56:19 +10:00
// Handle the basic code points
for (j = 0; j < inputLength; ++j) {
2019-11-09 00:52:54 +11:00
currentValue = input[j]
2019-07-15 01:56:19 +10:00
if (currentValue < 0x80) {
2019-11-09 00:52:54 +11:00
output.push(stringFromCharCode(currentValue))
2019-07-15 01:56:19 +10:00
}
}
2019-11-09 00:52:54 +11:00
handledCPCount = basicLength = output.length
2019-07-15 01:56:19 +10:00
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
2019-11-09 00:52:54 +11:00
output.push(delimiter)
2019-07-15 01:56:19 +10:00
}
// Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
2019-11-09 00:52:54 +11:00
currentValue = input[j]
2019-07-15 01:56:19 +10:00
if (currentValue >= n && currentValue < m) {
2019-11-09 00:52:54 +11:00
m = currentValue
2019-07-15 01:56:19 +10:00
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
2019-11-09 00:52:54 +11:00
handledCPCountPlusOne = handledCPCount + 1
2019-07-15 01:56:19 +10:00
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
2019-11-09 00:52:54 +11:00
error('overflow')
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
delta += (m - n) * handledCPCountPlusOne
n = m
2019-07-15 01:56:19 +10:00
for (j = 0; j < inputLength; ++j) {
2019-11-09 00:52:54 +11:00
currentValue = input[j]
2019-07-15 01:56:19 +10:00
if (currentValue < n && ++delta > maxInt) {
2019-11-09 00:52:54 +11:00
error('overflow')
2019-07-15 01:56:19 +10:00
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
2019-11-09 00:52:54 +11:00
for (q = delta, k = base /* no condition */; ; k += base) {
t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias
2019-07-15 01:56:19 +10:00
if (q < t) {
2019-11-09 00:52:54 +11:00
break
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
qMinusT = q - t
baseMinusT = base - t
output.push(stringFromCharCode(digitToBasic(t + (qMinusT % baseMinusT), 0)))
q = floor(qMinusT / baseMinusT)
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
output.push(stringFromCharCode(digitToBasic(q, 0)))
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength)
delta = 0
++handledCPCount
2019-07-15 01:56:19 +10:00
}
}
2019-11-09 00:52:54 +11:00
++delta
++n
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
return output.join('')
2019-07-15 01:56:19 +10:00
}
/**
* Converts a Punycode string representing a domain name or an email address
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
* it doesn't matter if you call it on a string that has already been
* converted to Unicode.
* @memberOf punycode
* @param {String} input The Punycoded domain name or email address to
* convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(input) {
return mapDomain(input, function(string) {
2019-11-09 00:52:54 +11:00
return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string
})
2019-07-15 01:56:19 +10:00
}
/**
* Converts a Unicode string representing a domain name or an email address to
* Punycode. Only the non-ASCII parts of the domain name will be converted,
* i.e. it doesn't matter if you call it with a domain that's already in
* ASCII.
* @memberOf punycode
* @param {String} input The domain name or email address to convert, as a
* Unicode string.
* @returns {String} The Punycode representation of the given domain name or
* email address.
*/
function toASCII(input) {
return mapDomain(input, function(string) {
2019-11-09 00:52:54 +11:00
return regexNonASCII.test(string) ? 'xn--' + encode(string) : string
})
2019-07-15 01:56:19 +10:00
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
2019-11-09 00:52:54 +11:00
version: '1.4.1',
2019-07-15 01:56:19 +10:00
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
2019-11-09 00:52:54 +11:00
ucs2: {
decode: ucs2decode,
encode: ucs2encode
2019-07-15 01:56:19 +10:00
},
2019-11-09 00:52:54 +11:00
decode: decode,
encode: encode,
toASCII: toASCII,
toUnicode: toUnicode
}
2019-07-15 01:56:19 +10:00
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
2019-11-09 00:52:54 +11:00
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
2019-07-15 01:56:19 +10:00
define('punycode', function() {
2019-11-09 00:52:54 +11:00
return punycode
})
2019-07-15 01:56:19 +10:00
} else if (freeExports && freeModule) {
if (module.exports == freeExports) {
// in Node.js, io.js, or RingoJS v0.8.0+
2019-11-09 00:52:54 +11:00
freeModule.exports = punycode
2019-07-15 01:56:19 +10:00
} else {
// in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
2019-11-09 00:52:54 +11:00
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key])
2019-07-15 01:56:19 +10:00
}
}
} else {
// in Rhino or a web browser
2019-11-09 00:52:54 +11:00
root.punycode = punycode
2019-07-15 01:56:19 +10:00
}
2019-11-09 00:52:54 +11:00
})(this)