identifier-js 0.4.2 → 0.4.3
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/normalization.md +52 -6
- package/package.json +1 -1
- package/readme.md +1 -1
package/normalization.md
CHANGED
|
@@ -110,10 +110,22 @@ A parsed value under the case-insensitive `urn` scheme takes the separate RFC 81
|
|
|
110
110
|
```js
|
|
111
111
|
const { parseUri } = require('identifier-js');
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
const input = 'URN:EXAMPLE:a%62/./b/../C?+r%2f?=q%2f#f%2f';
|
|
114
|
+
const output = parseUri(input).normalize();
|
|
115
|
+
|
|
116
|
+
output;
|
|
114
117
|
// urn:example:a%62/./b/../C?+r%2F?=q%2F#f%2F
|
|
115
118
|
```
|
|
116
119
|
|
|
120
|
+
This example demonstrates each URN normalization rule:
|
|
121
|
+
|
|
122
|
+
- `URN` becomes `urn` because the scheme is case-insensitive and normalized to lowercase.
|
|
123
|
+
- `EXAMPLE` becomes `example` because ASCII letters in the NID are normalized to lowercase.
|
|
124
|
+
- `%62` remains encoded in the NSS rather than becoming `b`; URN normalization does not decode percent-encoded NSS octets.
|
|
125
|
+
- `/./b/../C` remains unchanged because the NSS is opaque to generic path processing: dot segments are not removed, and literal NSS case is preserved.
|
|
126
|
+
- The r-, q-, and f-components and their `?+`, `?=`, and `#` delimiters are retained.
|
|
127
|
+
- `%2f` becomes `%2F` in each optional component because retained percent triplets use uppercase hexadecimal letters without decoding the represented `/`.
|
|
128
|
+
|
|
117
129
|
RFC 8141 URNs remain ASCII, including when parsed through an IRI operation. Consequently, `transform: 'URI'` and `transform: 'IRI'` produce the same URN representation, and `mapRegName` is not called because a URN has no authority or registered-name host.
|
|
118
130
|
|
|
119
131
|
For a parsed URN, the current URN-specific fields are the normalization input. The NSS and optional-component values stay opaque except for percent-triplet letter case. The method leaves every property unchanged.
|
|
@@ -137,20 +149,54 @@ mapped;
|
|
|
137
149
|
|
|
138
150
|
The example deliberately produces text that is not a valid URI or IRI; validating or selecting mapper output belongs to the application.
|
|
139
151
|
|
|
152
|
+
### IRI-to-URI transformation
|
|
153
|
+
|
|
140
154
|
With `transform: 'URI'`, retained reserved and non-ASCII percent triplets remain encoded, and literal non-ASCII userinfo, mapper output, path, query, and fragment text becomes uppercase UTF-8 percent triplets. A mapper can supply an ASCII hostname when its consuming scheme requires one; this package does not validate mapper output against that scheme.
|
|
141
155
|
|
|
142
156
|
```js
|
|
143
|
-
const { parseIri
|
|
157
|
+
const { parseIri } = require('identifier-js');
|
|
144
158
|
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
const input = 'x://usér@exämple/latin-é/emoji-😀?native=資料&private=\uE000&reserved=/&encoded=%c3%a9#résultat';
|
|
160
|
+
const output = parseIri(input).normalize({ transform: 'URI' });
|
|
147
161
|
|
|
148
|
-
|
|
149
|
-
// x
|
|
162
|
+
output;
|
|
163
|
+
// x://us%C3%A9r@ex%C3%A4mple/latin-%C3%A9/emoji-%F0%9F%98%80?native=%E8%B3%87%E6%96%99&private=%EE%80%80&reserved=/&encoded=%C3%A9#r%C3%A9sultat
|
|
150
164
|
```
|
|
151
165
|
|
|
166
|
+
This example demonstrates each relevant output rule:
|
|
167
|
+
|
|
168
|
+
- `usér`, `exämple`, `latin-é`, and `résultat` become UTF-8 percent triplets in userinfo, host, path, and fragment text.
|
|
169
|
+
- `😀` is processed as one Unicode scalar and becomes its four UTF-8 octets `%F0%9F%98%80`.
|
|
170
|
+
- `資料` becomes `%E8%B3%87%E6%96%99` in the query.
|
|
171
|
+
- The query's private-use character `\uE000` becomes `%EE%80%80`.
|
|
172
|
+
- The literal reserved `/` remains literal because it is already valid URI query syntax.
|
|
173
|
+
- The existing encoded sequence `%c3%a9` remains encoded while its hexadecimal letters become uppercase as `%C3%A9`.
|
|
174
|
+
|
|
175
|
+
### URI-to-IRI transformation
|
|
176
|
+
|
|
152
177
|
With `transform: 'IRI'`, conversion uses UTF-8 exclusively and decodes as many eligible percent-encoded characters as possible. Encoded reserved characters, `%25`, malformed or incomplete UTF-8, legacy character encodings, Unicode outside the RFC 3987 component repertoire, and forbidden bidirectional formatting characters remain percent encoded. Private-use characters are decoded only in the query component. The hexadecimal letters of retained triplets are uppercase.
|
|
153
178
|
|
|
179
|
+
```js
|
|
180
|
+
const { parseUri } = require('identifier-js');
|
|
181
|
+
|
|
182
|
+
const input = 'x:/ok-%C3%A9/reserved-%2F/percent-%25/malformed-%C3%28/incomplete-%E2%82/latin1-%E9/outside-%EF%B7%90/bidi-%E2%80%8E';
|
|
183
|
+
const output = parseUri(input).normalize({ transform: 'IRI' });
|
|
184
|
+
|
|
185
|
+
output;
|
|
186
|
+
// x:/ok-é/reserved-%2F/percent-%25/malformed-%C3%28/incomplete-%E2%82/latin1-%E9/outside-%EF%B7%90/bidi-%E2%80%8E
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
This example shows why transformation is not equivalent to applying `decodeURIComponent()` to every triplet:
|
|
190
|
+
|
|
191
|
+
- `%C3%A9` becomes `é` because it is valid UTF-8 for a character permitted in an IRI path.
|
|
192
|
+
- `%2F` remains encoded because `/` is reserved and decoding it could change path structure.
|
|
193
|
+
- `%25` remains encoded because decoding it would introduce a literal percent sign.
|
|
194
|
+
- `%C3%28` remains encoded because it is malformed UTF-8.
|
|
195
|
+
- `%E2%82` remains encoded because it is an incomplete UTF-8 sequence.
|
|
196
|
+
- `%E9` remains encoded because a Latin-1 or Windows-1252 byte is not valid UTF-8 by itself.
|
|
197
|
+
- `%EF%B7%90` remains encoded because it represents U+FDD0, which is outside the RFC 3987 character repertoire.
|
|
198
|
+
- `%E2%80%8E` remains encoded because it represents U+200E, a forbidden bidirectional formatting character.
|
|
199
|
+
|
|
154
200
|
The IRI transformation decodes percent-encoded ASCII unreserved characters even when this changes a registered name into IPv4-looking text. Without an explicit transformation, normalization preserves that registered-name host classification.
|
|
155
201
|
|
|
156
202
|
ACE-to-Unicode and Unicode-to-ACE registered-name conversion remain application policy. `mapRegName` runs before the selected representation transformation, so applications can provide the appropriate mapping in either direction.
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -212,7 +212,7 @@ When no safe rootless relative form can round-trip to the target, `toRelativeRef
|
|
|
212
212
|
Every URI and IRI parse result provides an optional, non-enumerable `normalize()` method. Parsing remains usable by itself; normalization runs only when the method is called and returns a string without modifying the parsed components.
|
|
213
213
|
|
|
214
214
|
<details>
|
|
215
|
-
<summary><strong>API
|
|
215
|
+
<summary><strong>API and examples</strong></summary>
|
|
216
216
|
|
|
217
217
|
```ts
|
|
218
218
|
type RegNameMapper = (regName: string) => string
|