identifier-js 0.4.0 → 0.4.1
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/index.d.ts +4 -9
- package/index.js +11 -6
- package/normalization.md +1 -1
- package/package.json +1 -1
- package/readme.md +6 -6
package/index.d.ts
CHANGED
|
@@ -31,17 +31,13 @@ export const parseIri: (iri: string) => ParsedIdentifierComponents;
|
|
|
31
31
|
export const parseIriReference: (iriReference: string) => ParsedRelativeIdentifierComponents;
|
|
32
32
|
/** @throws {Error} If the absolute-IRI is invalid. */
|
|
33
33
|
export const parseAbsoluteIri: (iri: string) => ParsedAbsoluteIdentifierComponents;
|
|
34
|
-
/**
|
|
35
|
-
* @throws {Error} If the base or the reference is invalid.
|
|
36
|
-
*/
|
|
34
|
+
/** @throws {Error} If the base or the reference is invalid. */
|
|
37
35
|
export function resolveReference(reference: string, base: string, strict?: boolean, returnParts?: false): string;
|
|
38
36
|
export function resolveReference(reference: string, base: string, strict: boolean | undefined, returnParts: true): IdentifierComponents;
|
|
39
37
|
export function resolveReference(reference: string, base: string, strict: boolean | undefined, returnParts: boolean | undefined): string | IdentifierComponents;
|
|
40
38
|
/** @throws {Error} If the reference is invalid. */
|
|
41
39
|
export const toAbsoluteReference: (reference: string) => string;
|
|
42
|
-
/**
|
|
43
|
-
* @throws {Error} If the base or the reference is invalid.
|
|
44
|
-
*/
|
|
40
|
+
/** @throws {Error} If the base or the reference is invalid. */
|
|
45
41
|
export const toRelativeReference: (target: string, base: string) => string;
|
|
46
42
|
|
|
47
43
|
/** Map a parsed non-empty registered-name host to caller-owned text. */
|
|
@@ -94,17 +90,16 @@ export type AbsoluteIdentifierComponents = {
|
|
|
94
90
|
query?: string;
|
|
95
91
|
};
|
|
96
92
|
|
|
97
|
-
// Describe the scheme-specific captures returned by each complete or fragment-free URN grammar.
|
|
98
93
|
type UrnIdentifierComponents = {
|
|
99
94
|
scheme: string;
|
|
100
95
|
nid: string;
|
|
101
96
|
nss: string;
|
|
102
97
|
rComponent?: string;
|
|
103
98
|
qComponent?: string;
|
|
104
|
-
|
|
99
|
+
fComponent?: string;
|
|
105
100
|
};
|
|
106
101
|
|
|
107
|
-
type AbsoluteUrnIdentifierComponents = Omit<UrnIdentifierComponents, '
|
|
102
|
+
type AbsoluteUrnIdentifierComponents = Omit<UrnIdentifierComponents, 'fComponent'>;
|
|
108
103
|
|
|
109
104
|
export type ParsedIdentifierComponents = (IdentifierComponents | UrnIdentifierComponents) & NormalizableReference;
|
|
110
105
|
export type ParsedRelativeIdentifierComponents = (RelativeIdentifierComponents | UrnIdentifierComponents) & NormalizableReference;
|
package/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// A valid URI is always a valid IRI, subject to every implemented scheme's more specific grammar.
|
|
4
4
|
const { recursiveCompile } = require('url-templates');
|
|
5
5
|
const patterns = new Map();
|
|
6
|
-
const implemented_schemes = '(?:[hH][tT][tT][pP][sS]?|[wW][sS][sS]?|[fF][iI][lL][eE]
|
|
6
|
+
const implemented_schemes = '(?:[hH][tT][tT][pP][sS]?|[wW][sS][sS]?|[fF][iI][lL][eE])';
|
|
7
7
|
// RFC3986/RFC3987 common rules + https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2:~:text=DNS%29%2E-,A,of%20%5BRFC1123%5D%2E
|
|
8
8
|
const commonRules = {
|
|
9
9
|
implemented_schemes,
|
|
@@ -81,11 +81,9 @@ const iriRules = {
|
|
|
81
81
|
};
|
|
82
82
|
// Define RFC 8141 productions and URI/IRI root overrides for the conditional URN profile.
|
|
83
83
|
const urnRules = {
|
|
84
|
-
scheme:
|
|
85
|
-
URI_reference: '{URI}',
|
|
84
|
+
scheme: '[uU][rR][nN]',
|
|
86
85
|
URI: '{namestring}',
|
|
87
86
|
absolute_URI: '{assigned_name}(?:{rq_components})?',
|
|
88
|
-
IRI_reference: '{IRI}',
|
|
89
87
|
IRI: '{URI}',
|
|
90
88
|
absolute_IRI: '{absolute_URI}',
|
|
91
89
|
namestring: '{assigned_name}(?:{rq_components})?(?:#{f_component})?',
|
|
@@ -148,7 +146,10 @@ const groupNames = {
|
|
|
148
146
|
NSS: 'nss',
|
|
149
147
|
r_component: 'rComponent',
|
|
150
148
|
q_component: 'qComponent',
|
|
149
|
+
f_component: 'fComponent',
|
|
151
150
|
};
|
|
151
|
+
// Keep URN parse results limited to their RFC 8141 component names.
|
|
152
|
+
const genericUrnGroupNames = new Set(['authority', 'userinfo', 'host', 'port', 'path', 'query', 'fragment']);
|
|
152
153
|
// Detect schemes for which the package implements grammar beyond generic URI/IRI syntax.
|
|
153
154
|
const isSpecificScheme = (string) => new RegExp('^' + implemented_schemes + ':').test(string);
|
|
154
155
|
// Select and merge generic, DNS-host, empty-file-host, or URN grammar profiles.
|
|
@@ -158,7 +159,11 @@ const rules = (profile) => Object.assign({}, commonRules, uriRules, iriRules, pr
|
|
|
158
159
|
const parse = (string, rule) => {
|
|
159
160
|
if (typeof string !== 'string') throw new TypeError(`Invalid ${rule.replace('_', '-')} type: must be a string.`);
|
|
160
161
|
const profile = schemeProfile(string);
|
|
161
|
-
|
|
162
|
+
// Select only the component captures exposed by the active grammar.
|
|
163
|
+
const addNames = (key) => {
|
|
164
|
+
const groupName = groupNames[key];
|
|
165
|
+
return groupName && !(profile === 'u' && genericUrnGroupNames.has(groupName)) ? `(?<${groupName}>${rules(profile)[key]})` : rules(profile)[key];
|
|
166
|
+
};
|
|
162
167
|
const ruleId = '_' + profile + rule;
|
|
163
168
|
if (!patterns.has(ruleId)) patterns.set(ruleId, new RegExp(`^${recursiveCompile(rules(profile), rule, addNames)}$`, 'u'));
|
|
164
169
|
const match = patterns.get(ruleId).exec(string);
|
|
@@ -562,7 +567,7 @@ function normalizeParsedReference(parts, options = {}) {
|
|
|
562
567
|
const rComponent = parts.rComponent === undefined ? undefined : normalizePercentEncoding(parts.rComponent, false);
|
|
563
568
|
const qComponent = parts.qComponent === undefined ? undefined : normalizePercentEncoding(parts.qComponent, false);
|
|
564
569
|
const query = rComponent !== undefined ? `+${rComponent}${qComponent === undefined ? '' : `?=${qComponent}`}` : qComponent === undefined ? undefined : `=${qComponent}`;
|
|
565
|
-
return compose({ scheme: parts.scheme.toLowerCase(), path: `${parts.nid.toLowerCase()}:${normalizePercentEncoding(parts.nss, false)}`, query, fragment: parts.
|
|
570
|
+
return compose({ scheme: parts.scheme.toLowerCase(), path: `${parts.nid.toLowerCase()}:${normalizePercentEncoding(parts.nss, false)}`, query, fragment: parts.fComponent === undefined ? undefined : normalizePercentEncoding(parts.fComponent, false) });
|
|
566
571
|
}
|
|
567
572
|
// Normalize each component independently so encoded delimiters cannot become structure.
|
|
568
573
|
const scheme = parts.scheme === undefined ? undefined : parts.scheme.toLowerCase();
|
package/normalization.md
CHANGED
|
@@ -60,7 +60,7 @@ Without a mapper, normalization retains the parser's host classification as an I
|
|
|
60
60
|
|
|
61
61
|
## URNs
|
|
62
62
|
|
|
63
|
-
A parsed value under the case-insensitive `urn` scheme takes a separate RFC 8141 normalization path using its captured `scheme`, `nid`, `nss`, `rComponent`, `qComponent`, and `
|
|
63
|
+
A parsed value under the case-insensitive `urn` scheme takes a separate RFC 8141 normalization path using its captured `scheme`, `nid`, `nss`, `rComponent`, `qComponent`, and `fComponent` properties.
|
|
64
64
|
|
|
65
65
|
| Input component | Output | Source |
|
|
66
66
|
| --- | --- | --- |
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -169,12 +169,12 @@ console.log(parsed.nid); // Example
|
|
|
169
169
|
console.log(parsed.nss); // a%2f/../B
|
|
170
170
|
console.log(parsed.rComponent); // service?x
|
|
171
171
|
console.log(parsed.qComponent); // key=value
|
|
172
|
-
console.log(parsed.
|
|
172
|
+
console.log(parsed.fComponent); // part
|
|
173
173
|
console.log(parsed.normalize());
|
|
174
174
|
// urn:example:a%2F/../B?+service?x?=key=value#part
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
URN parse results expose `nid`, `nss`, `rComponent`,
|
|
177
|
+
URN parse results expose `nid`, `nss`, `rComponent`, `qComponent`, and `fComponent`. They do not expose generic `path`, `query`, or `fragment` aliases. To require a URN after parsing a value accepted as a general URI, check `parsed.scheme.toLowerCase() === 'urn'`.
|
|
178
178
|
|
|
179
179
|
URNs remain ASCII even through the IRI operations. Callers representing non-ASCII names must first encode them as UTF-8 and then percent-encode the resulting octets; lexical validation does not decode or verify those octet sequences.
|
|
180
180
|
|
|
@@ -212,7 +212,7 @@ console.log(resolveReference('?page=2', 'https://example.com/items?page=1#curren
|
|
|
212
212
|
|
|
213
213
|
Empty authorities, queries, and fragments are preserved during recomposition.
|
|
214
214
|
|
|
215
|
-
|
|
215
|
+
`resolveReference` does not apply when either input uses the `urn` scheme. URN resolution services are outside this package's scope.
|
|
216
216
|
|
|
217
217
|
</details>
|
|
218
218
|
|
|
@@ -242,7 +242,7 @@ console.log(relative); // ../images/logo.svg
|
|
|
242
242
|
|
|
243
243
|
When no safe rootless relative form can round-trip to the target, `toRelativeReference` returns the absolute target. Different schemes or authorities also return the target unchanged. Complete dot segments in either path also trigger this fallback because RFC resolution removes them. For those inputs, resolving the result produces the same identifier as resolving the target directly; lexical dot-segment spelling is not preserved.
|
|
244
244
|
|
|
245
|
-
|
|
245
|
+
`toAbsoluteReference` and `toRelativeReference` do not apply when an input uses the `urn` scheme. Relative-URN semantics are outside this package's scope.
|
|
246
246
|
|
|
247
247
|
</details>
|
|
248
248
|
|
|
@@ -465,7 +465,7 @@ RFC 9562 lists database keys, filenames, system identifiers, and transaction ide
|
|
|
465
465
|
|
|
466
466
|
- Generic URI syntax follows RFC 3986 character and component grammar; HTTP, WebSocket, and `file` schemes apply the documented hostname restrictions.
|
|
467
467
|
- Generic IRI syntax follows the RFC 3987 Unicode extensions to URI grammar; HTTP, WebSocket, and `file` schemes apply the documented hostname restrictions.
|
|
468
|
-
- Values with the case-insensitive `urn` scheme follow RFC 8141 namestring syntax and expose
|
|
468
|
+
- Values with the case-insensitive `urn` scheme follow RFC 8141 namestring syntax and expose `nid`, `nss`, `rComponent`, `qComponent`, and `fComponent` fields through the URI and IRI parsers.
|
|
469
469
|
- URN validation establishes generic lexical syntax only, not namespace registration, namespace-specific syntax, assignment, resolution, or equivalence.
|
|
470
470
|
- Validators return `true` or throw at the first grammar violation.
|
|
471
471
|
- `absolute-URI` and `absolute-IRI` use the fragment-free grammar defined by their RFCs; complete URI and IRI operations accept fragments.
|
|
@@ -483,7 +483,7 @@ RFC 9562 lists database keys, filenames, system identifiers, and transaction ide
|
|
|
483
483
|
- `toAbsoluteReference` removes the fragment from an identifier containing a scheme.
|
|
484
484
|
- `toRelativeReference` generates a reference whose RFC resolution equals the target resolution for supported forms.
|
|
485
485
|
- `normalize()` implements the applicable case, percent-encoding, and path-segment rules from RFC 3986 §§6.2.2.1–6.2.2.3 and RFC 3987 §§5.3.2.1, 5.3.2.3–5.3.2.4, RFC 3987 §§3.1–3.2 URI/IRI representation transformation, RFC 5952 IPv6 text, RFC 9110 HTTP(S) port/path forms, RFC 6455 WS(S) port/resource-name forms, and RFC 8141 scheme/NID/percent-triplet normalization without NSS decoding or path reduction.
|
|
486
|
-
-
|
|
486
|
+
- Reference resolution and absolute/relative reference conversion do not apply to `urn` inputs; RFC 8141 URN resolution services and URN-equivalence APIs are not implemented.
|
|
487
487
|
|
|
488
488
|
</details>
|
|
489
489
|
|