@jarenjs/core 0.9.2 → 0.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +229 -26
- package/README.md +64 -10
- package/dist/types/array.d.ts +13 -0
- package/dist/types/cache.d.ts +166 -0
- package/dist/types/chunk.d.ts +102 -0
- package/dist/types/color.d.ts +64 -0
- package/dist/types/convert/convert.d.ts +33 -0
- package/dist/types/convert/currency.d.ts +47 -0
- package/dist/types/convert/index.d.ts +9 -0
- package/dist/types/convert/registry.d.ts +55 -0
- package/dist/types/dates/civil.d.ts +146 -0
- package/dist/types/dates/duration.d.ts +83 -0
- package/dist/types/dates/format.d.ts +59 -0
- package/dist/types/dates/index.d.ts +4 -0
- package/dist/types/{dates.d.ts → dates/rfc3339.d.ts} +57 -3
- package/dist/types/errors.d.ts +77 -0
- package/dist/types/finance/amortization.d.ts +51 -0
- package/dist/types/finance/bond.d.ts +45 -0
- package/dist/types/finance/cashflow.d.ts +44 -0
- package/dist/types/finance/depreciation.d.ts +26 -0
- package/dist/types/finance/index.d.ts +16 -0
- package/dist/types/finance/indicators.d.ts +76 -0
- package/dist/types/finance/interest.d.ts +44 -0
- package/dist/types/finance/returns.d.ts +43 -0
- package/dist/types/finance/tvm.d.ts +50 -0
- package/dist/types/geo/angle.d.ts +4 -0
- package/dist/types/geo/bbox.d.ts +32 -0
- package/dist/types/geo/distance.d.ts +67 -0
- package/dist/types/geo/geohash.d.ts +63 -0
- package/dist/types/geo/geojson.d.ts +108 -0
- package/dist/types/geo/index-tree.d.ts +52 -0
- package/dist/types/geo/index.d.ts +11 -0
- package/dist/types/geo/mercator.d.ts +57 -0
- package/dist/types/geo/predicates.d.ts +44 -0
- package/dist/types/geo/ring.d.ts +80 -0
- package/dist/types/geo/simplify.d.ts +31 -0
- package/dist/types/geo/valid.d.ts +24 -0
- package/dist/types/geo/wkt.d.ts +16 -0
- package/dist/types/math/float64.d.ts +126 -3
- package/dist/types/math/format.d.ts +58 -0
- package/dist/types/math/index.d.ts +5 -0
- package/dist/types/math/mat4.d.ts +60 -0
- package/dist/types/math/project.d.ts +54 -0
- package/dist/types/math/solve.d.ts +67 -0
- package/dist/types/math/word.d.ts +82 -0
- package/dist/types/message.d.ts +52 -0
- package/dist/types/object.d.ts +151 -0
- package/dist/types/scan.d.ts +30 -0
- package/dist/types/schema.d.ts +24 -0
- package/dist/types/string.d.ts +96 -0
- package/dist/types/text/base64.d.ts +6 -4
- package/dist/types/text/email.d.ts +0 -1
- package/dist/types/text/host.d.ts +39 -8
- package/dist/types/text/i18n.d.ts +13 -1
- package/dist/types/text/index.d.ts +1 -0
- package/dist/types/text/misc.d.ts +15 -1
- package/dist/types/text/punycode.d.ts +45 -85
- package/docs/CONVERT.md +45 -0
- package/docs/DATES.md +78 -0
- package/docs/FINANCE.md +59 -0
- package/docs/GEO.md +114 -0
- package/docs/MATH.md +75 -0
- package/package.json +57 -4
- package/src/array.js +16 -0
- package/src/cache.js +206 -0
- package/src/chunk.js +159 -0
- package/src/color.js +125 -0
- package/src/convert/convert.js +59 -0
- package/src/convert/currency.js +74 -0
- package/src/convert/index.js +11 -0
- package/src/convert/registry.js +213 -0
- package/src/dates/civil.js +360 -0
- package/src/dates/duration.js +225 -0
- package/src/dates/format.js +238 -0
- package/src/dates/index.js +30 -0
- package/src/dates/rfc3339.js +621 -0
- package/src/errors.js +102 -0
- package/src/finance/amortization.js +50 -0
- package/src/finance/bond.js +100 -0
- package/src/finance/cashflow.js +122 -0
- package/src/finance/depreciation.js +54 -0
- package/src/finance/index.js +27 -0
- package/src/finance/indicators.js +207 -0
- package/src/finance/interest.js +63 -0
- package/src/finance/returns.js +90 -0
- package/src/finance/tvm.js +94 -0
- package/src/function.js +0 -2
- package/src/geo/angle.js +12 -0
- package/src/geo/bbox.js +80 -0
- package/src/geo/distance.js +155 -0
- package/src/geo/geohash.js +224 -0
- package/src/geo/geojson.js +361 -0
- package/src/geo/index-tree.js +294 -0
- package/src/geo/index.js +52 -0
- package/src/geo/mercator.js +124 -0
- package/src/geo/predicates.js +313 -0
- package/src/geo/ring.js +182 -0
- package/src/geo/simplify.js +130 -0
- package/src/geo/valid.js +142 -0
- package/src/geo/wkt.js +262 -0
- package/src/math/float64.js +228 -11
- package/src/math/format.js +157 -0
- package/src/math/index.js +5 -0
- package/src/math/mat4.js +131 -0
- package/src/math/project.js +49 -0
- package/src/math/solve.js +112 -0
- package/src/math/word.js +177 -0
- package/src/message.js +119 -0
- package/src/object.js +329 -0
- package/src/scan.js +42 -0
- package/src/schema.js +37 -0
- package/src/string.js +189 -0
- package/src/text/base64.js +15 -52
- package/src/text/email.js +0 -5
- package/src/text/host.js +515 -140
- package/src/text/i18n.js +13 -6
- package/src/text/identifiers.js +1 -1
- package/src/text/index.js +1 -0
- package/src/text/misc.js +81 -5
- package/src/text/punycode.js +235 -323
- package/src/dates.js +0 -371
package/src/text/punycode.js
CHANGED
|
@@ -1,407 +1,319 @@
|
|
|
1
|
-
|
|
2
|
-
// Copyright Mathias Bynens <https://mathiasbynens.be/>
|
|
3
|
-
// https://github.com/bestiejs/punycode.js/blob/master/punycode.js
|
|
4
|
-
|
|
5
|
-
export const punycodeVersion = '2.1.0';
|
|
6
|
-
|
|
7
|
-
/** Highest positive signed 32-bit float value */
|
|
8
|
-
const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1
|
|
9
|
-
|
|
10
|
-
/** Bootstring parameters */
|
|
11
|
-
const base = 36;
|
|
12
|
-
const tMin = 1;
|
|
13
|
-
const tMax = 26;
|
|
14
|
-
const skew = 38;
|
|
15
|
-
const damp = 700;
|
|
16
|
-
const initialBias = 72;
|
|
17
|
-
const initialN = 128; // 0x80
|
|
18
|
-
const delimiter = '-'; // '\x2D'
|
|
19
|
-
|
|
20
|
-
/** Regular expressions */
|
|
21
|
-
const regexPunycode = /^xn--/;
|
|
22
|
-
const regexNonASCII = /[^\0-\x7E]/; // non-ASCII chars
|
|
23
|
-
const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators
|
|
24
|
-
|
|
25
|
-
/** Error messages */
|
|
26
|
-
const errors = {
|
|
27
|
-
'overflow': 'Overflow: input needs wider integers to process',
|
|
28
|
-
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
|
|
29
|
-
'invalid-input': 'Invalid input',
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/** Convenience shortcuts */
|
|
33
|
-
const baseMinusTMin = base - tMin;
|
|
34
|
-
const floor = Math.floor;
|
|
35
|
-
const stringFromCharCode = String.fromCharCode;
|
|
36
|
-
|
|
37
|
-
/*--------------------------------------------------------------------------*/
|
|
1
|
+
//@ts-check
|
|
38
2
|
|
|
39
3
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
4
|
+
* Punycode - the Bootstring encoding of Unicode for IDNA (RFC 3492) -
|
|
5
|
+
* and the domain-level conversions built on it.
|
|
6
|
+
*
|
|
7
|
+
* Two layers, because they are used at different granularities:
|
|
8
|
+
* `punycodeEncode`/`punycodeDecode` are the codec for ONE label and know
|
|
9
|
+
* nothing about domains, while `domainToASCII`/`domainToUnicode` walk a
|
|
10
|
+
* domain name (or the domain half of an email address) label by label
|
|
11
|
+
* and apply the `xn--` prefix convention. `isValidIdnHostname` in
|
|
12
|
+
* `host.js` splits labels itself and so calls the codec directly; the
|
|
13
|
+
* domain pair is for callers holding a whole name.
|
|
14
|
+
*
|
|
15
|
+
* The `flag` parameter of RFC 3492's digit encoder is omitted: it
|
|
16
|
+
* selects uppercase output, and IDNA A-labels are lowercase.
|
|
44
17
|
*/
|
|
45
|
-
function error(type) {
|
|
46
|
-
throw new RangeError(errors[type]);
|
|
47
|
-
}
|
|
48
18
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
* @param {Function} fn The function that gets called for every array
|
|
54
|
-
* item.
|
|
55
|
-
* @returns {Array} A new array of values returned by the callback function.
|
|
56
|
-
*/
|
|
57
|
-
function map(array, fn) {
|
|
58
|
-
const result = [];
|
|
59
|
-
let length = array.length;
|
|
60
|
-
while (length--) {
|
|
61
|
-
result[length] = fn(array[length]);
|
|
62
|
-
}
|
|
63
|
-
return result;
|
|
64
|
-
}
|
|
19
|
+
import {
|
|
20
|
+
toCodePoints,
|
|
21
|
+
fromCodePoints,
|
|
22
|
+
} from '../string.js';
|
|
65
23
|
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
function mapDomain(domain, fn) {
|
|
77
|
-
const parts = domain.split('@');
|
|
78
|
-
let result = '';
|
|
79
|
-
if (parts.length > 1) {
|
|
80
|
-
// In email addresses, only the domain name should be punycoded. Leave
|
|
81
|
-
// the local part (i.e. everything up to `@`) intact.
|
|
82
|
-
result = parts[0] + '@';
|
|
83
|
-
domain = parts[1];
|
|
84
|
-
}
|
|
85
|
-
// Avoid `split(regex)` for IE8 compatibility. See #17.
|
|
86
|
-
domain = domain.replace(regexSeparators, '\x2E');
|
|
87
|
-
const labels = domain.split('.');
|
|
88
|
-
const encoded = map(labels, fn).join('.');
|
|
89
|
-
return result + encoded;
|
|
90
|
-
}
|
|
24
|
+
/** Bootstring parameters (RFC 3492 section 5). */
|
|
25
|
+
const BASE = 36;
|
|
26
|
+
const T_MIN = 1;
|
|
27
|
+
const T_MAX = 26;
|
|
28
|
+
const SKEW = 38;
|
|
29
|
+
const DAMP = 700;
|
|
30
|
+
const INITIAL_BIAS = 72;
|
|
31
|
+
const INITIAL_N = 128; // the first non-basic code point
|
|
32
|
+
const DELIMITER = '-';
|
|
33
|
+
const MAX_INT = 0x7FFFFFFF; // the largest positive signed 32-bit value
|
|
91
34
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* UCS-2 exposes as separate characters) into a single code point,
|
|
97
|
-
* matching UTF-16.
|
|
98
|
-
* @see `punycode.ucs2.encode`
|
|
99
|
-
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
|
100
|
-
* @memberOf punycode.ucs2
|
|
101
|
-
* @name decode
|
|
102
|
-
* @param {String} string The Unicode input string (UCS-2).
|
|
103
|
-
* @returns {Array} The new array of code points.
|
|
104
|
-
*/
|
|
105
|
-
export function ucs2decode(string) {
|
|
106
|
-
const output = [];
|
|
107
|
-
let counter = 0;
|
|
108
|
-
const length = string.length;
|
|
109
|
-
while (counter < length) {
|
|
110
|
-
const value = string.charCodeAt(counter++);
|
|
111
|
-
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
|
112
|
-
// It's a high surrogate, and there is a next character.
|
|
113
|
-
const extra = string.charCodeAt(counter++);
|
|
114
|
-
if ((extra & 0xFC00) === 0xDC00) { // Low surrogate.
|
|
115
|
-
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
|
116
|
-
} else {
|
|
117
|
-
// It's an unmatched surrogate; only append this code unit, in case the
|
|
118
|
-
// next code unit is the high surrogate of a surrogate pair.
|
|
119
|
-
output.push(value);
|
|
120
|
-
counter--;
|
|
121
|
-
}
|
|
122
|
-
} else {
|
|
123
|
-
output.push(value);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return output;
|
|
127
|
-
}
|
|
35
|
+
const BASE_MINUS_T_MIN = BASE - T_MIN;
|
|
36
|
+
|
|
37
|
+
/** The ACE prefix that marks an encoded label. */
|
|
38
|
+
const ACE_PREFIX = 'xn--';
|
|
128
39
|
|
|
129
40
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* @
|
|
133
|
-
* @
|
|
134
|
-
* @param {Array} codePoints The array of numeric code points.
|
|
135
|
-
* @returns {String} The new Unicode string (UCS-2).
|
|
41
|
+
* Whether the code point separates labels. IDNA (RFC 3490 section 3.1)
|
|
42
|
+
* accepts three full-stop variants besides the ASCII one.
|
|
43
|
+
* @param {number} code - A UTF-16 code unit
|
|
44
|
+
* @returns {boolean} True for a label separator
|
|
136
45
|
*/
|
|
137
|
-
|
|
46
|
+
function isLabelSeparator(code) {
|
|
47
|
+
return code === 0x2E // '.'
|
|
48
|
+
|| code === 0x3002 // ideographic full stop
|
|
49
|
+
|| code === 0xFF0E // fullwidth full stop
|
|
50
|
+
|| code === 0xFF61; // halfwidth ideographic full stop
|
|
51
|
+
}
|
|
138
52
|
|
|
139
53
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* @
|
|
143
|
-
* @
|
|
144
|
-
* @returns {Number} The numeric value of a basic code point (for use in
|
|
145
|
-
* representing integers) in the range `0` to `base - 1`, or `base` if
|
|
146
|
-
* the code point does not represent a value.
|
|
54
|
+
* The numeric value of a basic code point used as a Bootstring digit, or
|
|
55
|
+
* `BASE` when the code point is not a digit at all.
|
|
56
|
+
* @param {number} code - A basic (ASCII) code point
|
|
57
|
+
* @returns {number} The digit value 0..35, or BASE
|
|
147
58
|
*/
|
|
148
|
-
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return codePoint - 0x41;
|
|
154
|
-
}
|
|
155
|
-
if (codePoint - 0x61 < 0x1A) {
|
|
156
|
-
return codePoint - 0x61;
|
|
157
|
-
}
|
|
158
|
-
return base;
|
|
59
|
+
function basicToDigit(code) {
|
|
60
|
+
if (code - 0x30 < 0x0A) return code - 0x16; // '0'-'9' -> 26..35
|
|
61
|
+
if (code - 0x41 < 0x1A) return code - 0x41; // 'A'-'Z' -> 0..25
|
|
62
|
+
if (code - 0x61 < 0x1A) return code - 0x61; // 'a'-'z' -> 0..25
|
|
63
|
+
return BASE;
|
|
159
64
|
}
|
|
160
65
|
|
|
161
66
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* @
|
|
165
|
-
* @
|
|
166
|
-
* @returns {Number} The basic code point whose value (when used for
|
|
167
|
-
* representing integers) is `digit`, which needs to be in the range
|
|
168
|
-
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
|
|
169
|
-
* used; else, the lowercase form is used. The behavior is undefined
|
|
170
|
-
* if `flag` is non-zero and `digit` has no uppercase form.
|
|
67
|
+
* The basic code point representing a Bootstring digit: 0..25 map to
|
|
68
|
+
* 'a'-'z', 26..35 to '0'-'9'.
|
|
69
|
+
* @param {number} digit - A digit value 0..35
|
|
70
|
+
* @returns {number} The code point
|
|
171
71
|
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// 26..35 map to ASCII 0..9
|
|
175
|
-
return digit + 22 + 75 * (digit < 26) - ((flag !== 0) << 5);
|
|
72
|
+
function digitToBasic(digit) {
|
|
73
|
+
return digit + 22 + 75 * (digit < 26 ? 1 : 0);
|
|
176
74
|
}
|
|
177
75
|
|
|
178
76
|
/**
|
|
179
|
-
* Bias adaptation
|
|
180
|
-
*
|
|
181
|
-
* @
|
|
77
|
+
* Bias adaptation (RFC 3492 section 6.1).
|
|
78
|
+
* @param {number} delta - The delta just encoded or decoded
|
|
79
|
+
* @param {number} numPoints - Code points handled so far, plus one
|
|
80
|
+
* @param {boolean} firstTime - Whether this is the first adaptation
|
|
81
|
+
* @returns {number} The new bias
|
|
182
82
|
*/
|
|
183
83
|
function adapt(delta, numPoints, firstTime) {
|
|
84
|
+
delta = firstTime ? Math.floor(delta / DAMP) : delta >> 1;
|
|
85
|
+
delta += Math.floor(delta / numPoints);
|
|
184
86
|
let k = 0;
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
delta = floor(delta / baseMinusTMin);
|
|
189
|
-
}
|
|
190
|
-
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
|
|
87
|
+
for (; delta > ((BASE_MINUS_T_MIN * T_MAX) >> 1); k += BASE)
|
|
88
|
+
delta = Math.floor(delta / BASE_MINUS_T_MIN);
|
|
89
|
+
return Math.floor(k + (BASE_MINUS_T_MIN + 1) * delta / (delta + SKEW));
|
|
191
90
|
}
|
|
192
91
|
|
|
193
92
|
/**
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* @param {
|
|
198
|
-
* @returns {
|
|
93
|
+
* Decode a Punycode string to Unicode. The input is a bare encoded
|
|
94
|
+
* label - the `xn--` prefix, if any, belongs to the caller.
|
|
95
|
+
*
|
|
96
|
+
* @param {string} input - The Punycode-encoded text
|
|
97
|
+
* @returns {string} The decoded Unicode text
|
|
98
|
+
* @throws {RangeError} On a non-basic input character, a truncated digit
|
|
99
|
+
* sequence, or an integer overflow
|
|
100
|
+
* @example
|
|
101
|
+
* punycodeDecode('bcher-kva'); // 'bücher'
|
|
199
102
|
*/
|
|
200
|
-
export function
|
|
201
|
-
// Don't use UCS-2.
|
|
202
|
-
const output = [];
|
|
103
|
+
export function punycodeDecode(input) {
|
|
203
104
|
const inputLength = input.length;
|
|
105
|
+
const output = [];
|
|
204
106
|
let i = 0;
|
|
205
|
-
let n =
|
|
206
|
-
let bias =
|
|
107
|
+
let n = INITIAL_N;
|
|
108
|
+
let bias = INITIAL_BIAS;
|
|
207
109
|
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
let basic = input.lastIndexOf(delimiter);
|
|
213
|
-
if (basic < 0) {
|
|
214
|
-
basic = 0;
|
|
215
|
-
}
|
|
110
|
+
// Everything before the last delimiter is literal basic code points.
|
|
111
|
+
let basic = input.lastIndexOf(DELIMITER);
|
|
112
|
+
if (basic < 0) basic = 0;
|
|
216
113
|
|
|
217
114
|
for (let j = 0; j < basic; ++j) {
|
|
218
|
-
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
output.push(input.charCodeAt(j));
|
|
115
|
+
const code = input.charCodeAt(j);
|
|
116
|
+
if (code >= 0x80)
|
|
117
|
+
throw new RangeError('Illegal input >= 0x80 (not a basic code point)');
|
|
118
|
+
output.push(code);
|
|
223
119
|
}
|
|
224
120
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
// `index` is the index of the next character to be consumed.
|
|
230
|
-
// Decode a generalized variable-length integer into `delta`,
|
|
231
|
-
// which gets added to `i`. The overflow checking is easier
|
|
232
|
-
// if we increase `i` as we go, then subtract off its starting
|
|
233
|
-
// value at the end to obtain `delta`.
|
|
121
|
+
for (let index = basic > 0 ? basic + 1 : 0; index < inputLength;) {
|
|
122
|
+
// Decode a generalized variable-length integer into `i`. Overflow is
|
|
123
|
+
// easier to check by growing `i` as we go and taking the difference
|
|
124
|
+
// at the end than by tracking the delta separately.
|
|
234
125
|
const oldi = i;
|
|
235
|
-
for (let w = 1, k =
|
|
236
|
-
if (index >= inputLength)
|
|
237
|
-
error('invalid-input');
|
|
238
|
-
}
|
|
126
|
+
for (let w = 1, k = BASE; ; k += BASE) {
|
|
127
|
+
if (index >= inputLength) throw new RangeError('Invalid input');
|
|
239
128
|
|
|
240
129
|
const digit = basicToDigit(input.charCodeAt(index++));
|
|
241
|
-
if (digit >=
|
|
242
|
-
|
|
243
|
-
}
|
|
130
|
+
if (digit >= BASE || digit > Math.floor((MAX_INT - i) / w))
|
|
131
|
+
throw new RangeError('Overflow: input needs wider integers to process');
|
|
244
132
|
|
|
245
133
|
i += digit * w;
|
|
246
|
-
const t = k <= bias ?
|
|
247
|
-
if (digit < t)
|
|
248
|
-
break;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const baseMinusT = base - t;
|
|
252
|
-
if (w > floor(maxInt / baseMinusT)) {
|
|
253
|
-
error('overflow');
|
|
254
|
-
}
|
|
134
|
+
const t = k <= bias ? T_MIN : (k >= bias + T_MAX ? T_MAX : k - bias);
|
|
135
|
+
if (digit < t) break;
|
|
255
136
|
|
|
137
|
+
const baseMinusT = BASE - t;
|
|
138
|
+
if (w > Math.floor(MAX_INT / baseMinusT))
|
|
139
|
+
throw new RangeError('Overflow: input needs wider integers to process');
|
|
256
140
|
w *= baseMinusT;
|
|
257
141
|
}
|
|
258
142
|
|
|
259
143
|
const out = output.length + 1;
|
|
260
144
|
bias = adapt(i - oldi, out, oldi === 0);
|
|
261
145
|
|
|
262
|
-
// `i` was
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
error('overflow');
|
|
266
|
-
}
|
|
146
|
+
// `i` was meant to wrap from `out` to 0, carrying into `n` each time.
|
|
147
|
+
if (Math.floor(i / out) > MAX_INT - n)
|
|
148
|
+
throw new RangeError('Overflow: input needs wider integers to process');
|
|
267
149
|
|
|
268
|
-
n += floor(i / out);
|
|
150
|
+
n += Math.floor(i / out);
|
|
269
151
|
i %= out;
|
|
270
152
|
|
|
271
|
-
// Insert `n` at position `i` of the output.
|
|
272
153
|
output.splice(i++, 0, n);
|
|
273
154
|
}
|
|
274
155
|
|
|
275
|
-
return
|
|
156
|
+
return fromCodePoints(output);
|
|
276
157
|
}
|
|
277
158
|
|
|
278
159
|
/**
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
* @param {
|
|
283
|
-
* @returns {
|
|
160
|
+
* Encode Unicode text as Punycode. The result is a bare encoded label -
|
|
161
|
+
* prefixing it with `xn--` is the caller's job.
|
|
162
|
+
*
|
|
163
|
+
* @param {string} str - The Unicode text
|
|
164
|
+
* @returns {string} The Punycode-encoded text
|
|
165
|
+
* @throws {RangeError} On an integer overflow
|
|
166
|
+
* @example
|
|
167
|
+
* punycodeEncode('bücher'); // 'bcher-kva'
|
|
284
168
|
*/
|
|
285
|
-
export function
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
// Convert the input in UCS-2 to an array of Unicode code points.
|
|
289
|
-
const input = ucs2decode(str);
|
|
290
|
-
|
|
291
|
-
// Cache the length.
|
|
169
|
+
export function punycodeEncode(str) {
|
|
170
|
+
const input = toCodePoints(str);
|
|
292
171
|
const inputLength = input.length;
|
|
293
172
|
|
|
294
|
-
//
|
|
295
|
-
|
|
173
|
+
// Appended to directly rather than collected in an array and joined:
|
|
174
|
+
// every character is written once and never revisited.
|
|
175
|
+
let output = '';
|
|
176
|
+
let n = INITIAL_N;
|
|
296
177
|
let delta = 0;
|
|
297
|
-
let bias =
|
|
298
|
-
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
178
|
+
let bias = INITIAL_BIAS;
|
|
179
|
+
|
|
180
|
+
// The basic code points are copied out in order, then separated from
|
|
181
|
+
// the encoded remainder by the delimiter.
|
|
182
|
+
let basicLength = 0;
|
|
183
|
+
for (let j = 0; j < inputLength; j++) {
|
|
184
|
+
if (input[j] < 0x80) {
|
|
185
|
+
output += String.fromCharCode(input[j]);
|
|
186
|
+
basicLength++;
|
|
303
187
|
}
|
|
304
188
|
}
|
|
189
|
+
if (basicLength) output += DELIMITER;
|
|
305
190
|
|
|
306
|
-
const basicLength = output.length;
|
|
307
191
|
let handledCPCount = basicLength;
|
|
308
|
-
|
|
309
|
-
// `handledCPCount` is the number of code points that have been handled;
|
|
310
|
-
// `basicLength` is the number of basic code points.
|
|
311
|
-
|
|
312
|
-
// Finish the basic string with a delimiter unless it's empty.
|
|
313
|
-
if (basicLength) {
|
|
314
|
-
output.push(delimiter);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Main encoding loop:
|
|
318
192
|
while (handledCPCount < inputLength) {
|
|
319
|
-
//
|
|
320
|
-
//
|
|
321
|
-
let m =
|
|
322
|
-
for (
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
193
|
+
// Every non-basic code point below `n` is already encoded; find the
|
|
194
|
+
// next one up.
|
|
195
|
+
let m = MAX_INT;
|
|
196
|
+
for (let j = 0; j < inputLength; j++) {
|
|
197
|
+
const value = input[j];
|
|
198
|
+
if (value >= n && value < m) m = value;
|
|
326
199
|
}
|
|
327
200
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
|
|
332
|
-
error('overflow');
|
|
333
|
-
}
|
|
201
|
+
const handledPlusOne = handledCPCount + 1;
|
|
202
|
+
if (m - n > Math.floor((MAX_INT - delta) / handledPlusOne))
|
|
203
|
+
throw new RangeError('Overflow: input needs wider integers to process');
|
|
334
204
|
|
|
335
|
-
delta += (m - n) *
|
|
205
|
+
delta += (m - n) * handledPlusOne;
|
|
336
206
|
n = m;
|
|
337
207
|
|
|
338
|
-
for (
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if (
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)),
|
|
354
|
-
);
|
|
355
|
-
q = floor(qMinusT / baseMinusT);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
output.push(stringFromCharCode(digitToBasic(q, 0)));
|
|
359
|
-
bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength);
|
|
360
|
-
delta = 0;
|
|
361
|
-
++handledCPCount;
|
|
208
|
+
for (let j = 0; j < inputLength; j++) {
|
|
209
|
+
const value = input[j];
|
|
210
|
+
if (value < n && ++delta > MAX_INT)
|
|
211
|
+
throw new RangeError('Overflow: input needs wider integers to process');
|
|
212
|
+
if (value !== n) continue;
|
|
213
|
+
|
|
214
|
+
// Write `delta` as a generalized variable-length integer.
|
|
215
|
+
let q = delta;
|
|
216
|
+
for (let k = BASE; ; k += BASE) {
|
|
217
|
+
const t = k <= bias ? T_MIN : (k >= bias + T_MAX ? T_MAX : k - bias);
|
|
218
|
+
if (q < t) break;
|
|
219
|
+
const qMinusT = q - t;
|
|
220
|
+
const baseMinusT = BASE - t;
|
|
221
|
+
output += String.fromCharCode(digitToBasic(t + qMinusT % baseMinusT));
|
|
222
|
+
q = Math.floor(qMinusT / baseMinusT);
|
|
362
223
|
}
|
|
224
|
+
|
|
225
|
+
output += String.fromCharCode(digitToBasic(q));
|
|
226
|
+
bias = adapt(delta, handledPlusOne, handledCPCount === basicLength);
|
|
227
|
+
delta = 0;
|
|
228
|
+
++handledCPCount;
|
|
363
229
|
}
|
|
364
230
|
|
|
365
231
|
++delta;
|
|
366
232
|
++n;
|
|
367
233
|
}
|
|
368
|
-
return output
|
|
234
|
+
return output;
|
|
369
235
|
}
|
|
370
236
|
|
|
371
237
|
/**
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
* converted
|
|
376
|
-
* @
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
238
|
+
* Walk a domain name label by label, converting each with `convert` and
|
|
239
|
+
* rejoining on ASCII full stops.
|
|
240
|
+
*
|
|
241
|
+
* In an email address only the domain is converted; the local part is
|
|
242
|
+
* left exactly as written. Splitting on the FIRST "@" and converting
|
|
243
|
+
* only what follows the second segment matches RFC 3490's assumption of
|
|
244
|
+
* a single "@" - a malformed address with more is not a case this
|
|
245
|
+
* conversion is defined for.
|
|
246
|
+
*
|
|
247
|
+
* @param {string} domain - A domain name or email address
|
|
248
|
+
* @param {(label: string) => string} convert - The per-label conversion
|
|
249
|
+
* @returns {string} The converted domain
|
|
381
250
|
*/
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
251
|
+
function mapLabels(domain, convert) {
|
|
252
|
+
let prefix = '';
|
|
253
|
+
const parts = domain.split('@');
|
|
254
|
+
if (parts.length > 1) {
|
|
255
|
+
prefix = parts[0] + '@';
|
|
256
|
+
domain = parts[1];
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
let out = prefix;
|
|
260
|
+
let start = 0;
|
|
261
|
+
const end = domain.length;
|
|
262
|
+
for (let i = 0; i <= end; i++) {
|
|
263
|
+
if (i < end && !isLabelSeparator(domain.charCodeAt(i))) continue;
|
|
264
|
+
out += convert(domain.slice(start, i));
|
|
265
|
+
if (i < end) out += '.';
|
|
266
|
+
start = i + 1;
|
|
267
|
+
}
|
|
268
|
+
return out;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Whether the label carries the ACE prefix, in any case.
|
|
273
|
+
* @param {string} label - A domain label
|
|
274
|
+
* @returns {boolean} True when the label starts with `xn--`
|
|
275
|
+
*/
|
|
276
|
+
function hasAcePrefix(label) {
|
|
277
|
+
return label.length >= 4
|
|
278
|
+
&& (label.charCodeAt(0) | 0x20) === 0x78 // 'x'
|
|
279
|
+
&& (label.charCodeAt(1) | 0x20) === 0x6E // 'n'
|
|
280
|
+
&& label.charCodeAt(2) === 0x2D // '-'
|
|
281
|
+
&& label.charCodeAt(3) === 0x2D;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Convert a domain name or email address to its Unicode form, decoding
|
|
286
|
+
* every `xn--` label. Labels that are not encoded are left alone, so
|
|
287
|
+
* calling this on an already-Unicode name is harmless.
|
|
288
|
+
*
|
|
289
|
+
* @param {string} input - The domain name or email address
|
|
290
|
+
* @returns {string} The Unicode form
|
|
291
|
+
* @example
|
|
292
|
+
* domainToUnicode('xn--bcher-kva.example'); // 'bücher.example'
|
|
293
|
+
*/
|
|
294
|
+
export function domainToUnicode(input) {
|
|
295
|
+
return mapLabels(input, (label) => hasAcePrefix(label)
|
|
296
|
+
? punycodeDecode(label.slice(4).toLowerCase())
|
|
297
|
+
: label);
|
|
388
298
|
}
|
|
389
299
|
|
|
390
300
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
* @param {
|
|
397
|
-
*
|
|
398
|
-
* @
|
|
399
|
-
*
|
|
301
|
+
* Convert a domain name or email address to its ASCII (ACE) form,
|
|
302
|
+
* encoding every label that carries non-ASCII characters. Labels that
|
|
303
|
+
* are already ASCII are left alone, so calling this on an ASCII name is
|
|
304
|
+
* harmless.
|
|
305
|
+
*
|
|
306
|
+
* @param {string} input - The domain name or email address
|
|
307
|
+
* @returns {string} The ACE form
|
|
308
|
+
* @example
|
|
309
|
+
* domainToASCII('bücher.example'); // 'xn--bcher-kva.example'
|
|
400
310
|
*/
|
|
401
|
-
export function
|
|
402
|
-
return
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
311
|
+
export function domainToASCII(input) {
|
|
312
|
+
return mapLabels(input, (label) => {
|
|
313
|
+
for (let i = 0; i < label.length; i++) {
|
|
314
|
+
if (label.charCodeAt(i) > 0x7E)
|
|
315
|
+
return ACE_PREFIX + punycodeEncode(label);
|
|
316
|
+
}
|
|
317
|
+
return label;
|
|
406
318
|
});
|
|
407
319
|
}
|