punycode-esm 2.0.1 → 2.1.0

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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  <div style="text-align:center">
2
2
 
3
3
  # punycode-esm
4
+
4
5
  ESM and TypeScript port of the punycode.js library.
5
6
 
6
7
  [![npm package](https://badge.fury.io/js/punycode-esm.svg)](https://www.npmjs.com/package/punycode-esm)
@@ -9,6 +10,7 @@ ESM and TypeScript port of the punycode.js library.
9
10
  </div>
10
11
 
11
12
  ## Contents
13
+
12
14
  - [Install](#install)
13
15
  - [Example](#example)
14
16
  - [Usage](#usage)
@@ -45,6 +47,8 @@ toUnicode('xn----dqo34k.com'); // '☃-⌘.com'
45
47
 
46
48
  `punycode-esm` is an ESM module. It must be `import`ed. To load from a CJS module, use dynamic import: `const { encode } = await import('punycode-esm')`.
47
49
 
50
+ Functions throw `RangeError` for malformed Punycode: `decode` and `toUnicode` for input that is not ASCII (`Invalid input`), is not valid Punycode, or needs wider integers than JavaScript numbers hold (`Overflow: input needs wider integers to process`); `encode` and `toASCII` for the overflow case only. `toASCII` and `toUnicode` only convert labels, and do none of the other IDNA processing: no case folding, no Unicode normalization and no length checks. They split on `.` and the other full-stop characters `。`, `.` and `。` (all written as `.` in the result), and only recognize the lowercase `xn--` prefix.
51
+
48
52
  ## API
49
53
 
50
54
  ### `encode(string)`
@@ -53,9 +57,9 @@ Converts a string of Unicode symbols (a single domain label) to a Punycode strin
53
57
 
54
58
  **Parameters**
55
59
 
56
- | Parameter | Type | Default | Description |
57
- |-----------|------|---------|-------------|
58
- | `string` | `string` | — | Required. A Unicode domain label (no dots). |
60
+ | Parameter | Type | Default | Description |
61
+ | --------- | -------- | ------- | ------------------------------------------- |
62
+ | `string` | `string` | — | Required. A Unicode domain label (no dots). |
59
63
 
60
64
  **Returns** `string` — the Punycode-encoded ASCII label.
61
65
 
@@ -72,9 +76,9 @@ Converts a Punycode string of ASCII-only symbols (a single domain label) to a st
72
76
 
73
77
  **Parameters**
74
78
 
75
- | Parameter | Type | Default | Description |
76
- |-----------|------|---------|-------------|
77
- | `string` | `string` | — | Required. A Punycode-encoded ASCII label (no dots). |
79
+ | Parameter | Type | Default | Description |
80
+ | --------- | -------- | ------- | --------------------------------------------------- |
81
+ | `string` | `string` | — | Required. A Punycode-encoded ASCII label (no dots). |
78
82
 
79
83
  **Returns** `string` — the decoded Unicode label.
80
84
 
@@ -91,9 +95,9 @@ Converts a Unicode domain name or email address to its Punycode (ASCII) represen
91
95
 
92
96
  **Parameters**
93
97
 
94
- | Parameter | Type | Default | Description |
95
- |-----------|------|---------|-------------|
96
- | `string` | `string` | — | Required. A Unicode domain name or email address. |
98
+ | Parameter | Type | Default | Description |
99
+ | --------- | -------- | ------- | ------------------------------------------------- |
100
+ | `string` | `string` | — | Required. A Unicode domain name or email address. |
97
101
 
98
102
  **Returns** `string` — the ASCII-compatible encoding of the domain or email.
99
103
 
@@ -111,9 +115,9 @@ Converts a Punycode domain name or email address to Unicode. Only Punycode-encod
111
115
 
112
116
  **Parameters**
113
117
 
114
- | Parameter | Type | Default | Description |
115
- |-----------|------|---------|-------------|
116
- | `string` | `string` | — | Required. A Punycode domain name or email address. |
118
+ | Parameter | Type | Default | Description |
119
+ | --------- | -------- | ------- | -------------------------------------------------- |
120
+ | `string` | `string` | — | Required. A Punycode domain name or email address. |
117
121
 
118
122
  **Returns** `string` — the Unicode representation of the domain or email.
119
123
 
@@ -131,9 +135,9 @@ Creates an array of Unicode code point values from a string. Surrogate pairs (as
131
135
 
132
136
  **Parameters**
133
137
 
134
- | Parameter | Type | Default | Description |
135
- |-----------|------|---------|-------------|
136
- | `string` | `string` | — | Required. A UCS-2 encoded string. |
138
+ | Parameter | Type | Default | Description |
139
+ | --------- | -------- | ------- | --------------------------------- |
140
+ | `string` | `string` | — | Required. A UCS-2 encoded string. |
137
141
 
138
142
  **Returns** `number[]` — array of Unicode code point integers.
139
143
 
@@ -150,9 +154,9 @@ Creates a string from an array of Unicode code point values.
150
154
 
151
155
  **Parameters**
152
156
 
153
- | Parameter | Type | Default | Description |
154
- |-----------|------|---------|-------------|
155
- | `codePoints` | `readonly number[]` | — | Required. Array of Unicode code point integers. |
157
+ | Parameter | Type | Default | Description |
158
+ | ------------ | ------------------- | ------- | ----------------------------------------------- |
159
+ | `codePoints` | `readonly number[]` | — | Required. Array of Unicode code point integers. |
156
160
 
157
161
  **Returns** `string` — the UCS-2 encoded string.
158
162
 
@@ -6,7 +6,7 @@ declare const errors: {
6
6
  * A generic error utility function.
7
7
  *
8
8
  * @param type - The error type key.
9
- * @throws Throws a `RangeError` with the applicable error message.
9
+ * @throws {RangeError} with the applicable error message.
10
10
  */
11
11
  export declare const rangeError: (type: keyof typeof errors) => never;
12
12
  export declare const checkOverflow: (lower: number, upper: number, { gte, error, }?: {
package/dist/punycode.js CHANGED
@@ -9,22 +9,13 @@ const initialBias = 72;
9
9
  const initialN = 128;
10
10
  const delimiter = '-';
11
11
  const baseMinusTMin = base - tMin;
12
- const regexNonASCII = /[^\0-\u007F]/u;
13
- const regexSeparators = /[\u002E\u3002\uFF0E\uFF61]/gu;
12
+ const regexNonASCII = /[^\0-\u{7F}]/v;
13
+ const regexSeparators = /[\u{2E}\u{3002}\u{FF0E}\u{FF61}]/v;
14
14
  const mapDomain = (domain, callback)=>{
15
- const [first, ...rest] = domain.split('@');
16
- let result;
17
- let toEncode;
18
- if (rest.length > 0) {
19
- result = `${first}@`;
20
- toEncode = rest.join('@');
21
- } else {
22
- result = '';
23
- toEncode = first;
24
- }
25
- const labels = toEncode.split(regexSeparators);
15
+ const domainStart = domain.indexOf('@') + 1;
16
+ const labels = domain.slice(domainStart).split(regexSeparators);
26
17
  const encoded = labels.map((x)=>callback(x)).join('.');
27
- return result + encoded;
18
+ return domain.slice(0, domainStart) + encoded;
28
19
  };
29
20
  export const ucs2Decode = (string)=>{
30
21
  const output = [];
@@ -55,18 +46,15 @@ const basicToDigit = (codePoint)=>{
55
46
  if (codePoint >= 0x41 && codePoint < 0x5b) {
56
47
  return codePoint - 0x41;
57
48
  }
58
- if (codePoint >= 0x61 && codePoint < 0x7b) {
59
- return codePoint - 0x61;
60
- }
61
- return base;
49
+ return codePoint >= 0x61 && codePoint < 0x7b ? codePoint - 0x61 : base;
62
50
  };
63
51
  const digitToBasic = (digit)=>{
64
52
  const plus22 = digit + 22;
65
53
  return digit < 26 ? plus22 + 75 : plus22;
66
54
  };
67
- const adapt = (delta, numPoints, firstTime)=>{
55
+ const adapt = (delta, numPoints, isFirstTime)=>{
68
56
  let k = 0;
69
- let newDelta = firstTime ? Math.floor(delta / damp) : delta >> 1;
57
+ let newDelta = isFirstTime ? Math.floor(delta / damp) : delta >> 1;
70
58
  newDelta += Math.floor(newDelta / numPoints);
71
59
  const minCheck = baseMinusTMin * tMax >> 1;
72
60
  while(newDelta > minCheck){
@@ -75,6 +63,60 @@ const adapt = (delta, numPoints, firstTime)=>{
75
63
  }
76
64
  return Math.floor(k + (baseMinusTMin + 1) * newDelta / (newDelta + skew));
77
65
  };
66
+ const threshold = (k, bias)=>{
67
+ if (k <= bias) {
68
+ return tMin;
69
+ }
70
+ return k >= bias + tMax ? tMax : k - bias;
71
+ };
72
+ const decodeInteger = (input, start, i, bias)=>{
73
+ let index = start;
74
+ let sum = i;
75
+ let w = 1;
76
+ let k = base;
77
+ while(true){
78
+ checkOverflow(index, input.length, {
79
+ gte: true,
80
+ error: 'invalid-input'
81
+ });
82
+ const digit = basicToDigit(input.codePointAt(index));
83
+ ++index;
84
+ checkOverflow(digit, base, {
85
+ gte: true,
86
+ error: 'invalid-input'
87
+ });
88
+ checkOverflow(digit, Math.floor((maxInt - sum) / w));
89
+ sum += digit * w;
90
+ const t = threshold(k, bias);
91
+ if (digit < t) {
92
+ return {
93
+ index,
94
+ i: sum
95
+ };
96
+ }
97
+ const baseMinusT = base - t;
98
+ checkOverflow(w, Math.floor(maxInt / baseMinusT));
99
+ w *= baseMinusT;
100
+ k += base;
101
+ }
102
+ };
103
+ const encodeInteger = (delta, bias)=>{
104
+ const output = [];
105
+ let q = delta;
106
+ let k = base;
107
+ while(true){
108
+ const t = threshold(k, bias);
109
+ if (q < t) {
110
+ output.push(String.fromCodePoint(digitToBasic(q)));
111
+ return output;
112
+ }
113
+ const qMinusT = q - t;
114
+ const baseMinusT = base - t;
115
+ output.push(String.fromCodePoint(digitToBasic(t + qMinusT % baseMinusT)));
116
+ q = Math.floor(qMinusT / baseMinusT);
117
+ k += base;
118
+ }
119
+ };
78
120
  export const decode = (input)=>{
79
121
  const output = [];
80
122
  const inputLength = input.length;
@@ -95,30 +137,7 @@ export const decode = (input)=>{
95
137
  let index = basic > 0 ? basic + 1 : 0;
96
138
  while(index < inputLength){
97
139
  const oldi = i;
98
- let w = 1;
99
- let k = base;
100
- while(true){
101
- checkOverflow(index, inputLength, {
102
- gte: true,
103
- error: 'invalid-input'
104
- });
105
- const digit = basicToDigit(input.codePointAt(index));
106
- ++index;
107
- checkOverflow(digit, base, {
108
- gte: true,
109
- error: 'invalid-input'
110
- });
111
- checkOverflow(digit, Math.floor((maxInt - i) / w));
112
- i += digit * w;
113
- const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
114
- if (digit < t) {
115
- break;
116
- }
117
- const baseMinusT = base - t;
118
- checkOverflow(w, Math.floor(maxInt / baseMinusT));
119
- w *= baseMinusT;
120
- k += base;
121
- }
140
+ ({ index, i } = decodeInteger(input, index, i, bias));
122
141
  const out = output.length + 1;
123
142
  bias = adapt(i - oldi, out, oldi === 0);
124
143
  checkOverflow(Math.floor(i / out), maxInt - n);
@@ -162,25 +181,13 @@ export const encode = (input)=>{
162
181
  ++delta;
163
182
  checkOverflow(delta, maxInt);
164
183
  }
165
- if (currentValue === n) {
166
- let q = delta;
167
- let k = base;
168
- while(true){
169
- const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
170
- if (q < t) {
171
- break;
172
- }
173
- const qMinusT = q - t;
174
- const baseMinusT = base - t;
175
- output.push(String.fromCodePoint(digitToBasic(t + qMinusT % baseMinusT)));
176
- q = Math.floor(qMinusT / baseMinusT);
177
- k += base;
178
- }
179
- output.push(String.fromCodePoint(digitToBasic(q)));
180
- bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength);
181
- delta = 0;
182
- ++handledCPCount;
184
+ if (currentValue !== n) {
185
+ continue;
183
186
  }
187
+ output.push(...encodeInteger(delta, bias));
188
+ bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength);
189
+ delta = 0;
190
+ ++handledCPCount;
184
191
  }
185
192
  ++delta;
186
193
  ++n;
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "punycode-esm",
3
- "version": "2.0.1",
4
- "description": "Typescript + ESM version of punycode.js",
3
+ "version": "2.1.0",
4
+ "description": "ESM and TypeScript port of the punycode.js library.",
5
5
  "engines": {
6
- "node": ">=24"
6
+ "node": ">=22"
7
7
  },
8
8
  "type": "module",
9
9
  "author": "JacobLey",
@@ -25,6 +25,11 @@
25
25
  ],
26
26
  "sideEffects": false,
27
27
  "types": "./dist/punycode.js",
28
+ "files": [
29
+ "dist",
30
+ "!dist/**/*.map",
31
+ "!dist/tsconfig.tsbuildinfo"
32
+ ],
28
33
  "exports": {
29
34
  ".": "./dist/punycode.js"
30
35
  },
@@ -32,18 +37,18 @@
32
37
  "#errors": "./dist/lib/errors.js"
33
38
  },
34
39
  "devDependencies": {
35
- "@biomejs/biome": "^2.5.14",
40
+ "@biomejs/biome": "^2.6.4",
36
41
  "@leyman/eslint-config": "^0.0.1",
37
42
  "@leyman/expect": "^0.0.1",
38
43
  "@swc/cli": "^0.8.1",
39
- "@swc/core": "^1.16.2",
44
+ "@swc/core": "^1.16.20",
40
45
  "@types/mocha": "^10.0.10",
41
- "@types/node": "^24.19.0",
46
+ "@types/node": "^22.20.5",
42
47
  "@typescript/native": "npm:typescript@^7.0.2",
43
48
  "c8": "^12.0.0",
44
- "eslint": "^9.39.5",
45
- "mocha": "^12.0.2",
46
- "mocha-chain": "^1.0.1",
49
+ "eslint": "^10.13.0",
50
+ "mocha": "^12.0.3",
51
+ "mocha-chain": "^1.1.0",
47
52
  "typescript": "npm:@typescript/typescript6@^6.0.2"
48
53
  }
49
54
  }
package/.npmignore DELETED
@@ -1,13 +0,0 @@
1
- CHANGELOG.md
2
- project.json
3
- tsconfig.json
4
-
5
- coverage/**
6
- eslint.config.js
7
-
8
- dist/tsconfig.tsbuildinfo
9
- dist/**/*.map
10
- dist-test/**
11
- test/**
12
-
13
- src/**