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 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
- /** Resolve with generic RFC 3986 semantics; this does not invoke a URN resolution service.
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
- /** Derive a generic URI reference without scheme-specific relative-URN semantics.
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
- fragment?: string;
99
+ fComponent?: string;
105
100
  };
106
101
 
107
- type AbsoluteUrnIdentifierComponents = Omit<UrnIdentifierComponents, 'fragment'>;
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]|[uU][rR][nN])';
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: implemented_schemes,
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
- const addNames = (key) => (groupNames[key] ? `(?<${groupNames[key]}>${rules(profile)[key]})` : rules(profile)[key]);
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.fragment === undefined ? undefined : normalizePercentEncoding(parts.fragment, false) });
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 `fragment` properties.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "identifier-js",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "A fast RFC 3986/3987 URI/IRI parser, validator, normalizer, resolver, and composer with RFC 8141 URN syntax support.",
5
5
  "keywords": [
6
6
  "IRI",
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.fragment); // part
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`, and `qComponent`, while the RFC-defined f-component is exposed as `fragment`. They do not expose generic `path` or `query` aliases. To require a URN after parsing a value accepted as a general URI, check `parsed.scheme.toLowerCase() === 'urn'`.
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
- This function performs generic RFC 3986 reference resolution only. It does not invoke a URN resolution service or implement scheme-specific URN resolution semantics.
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
- These conversion functions retain their generic URI-reference behavior. They do not construct, resolve, or interpret scheme-specific relative URNs.
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 NID, NSS, r-component, q-component, and fragment fields through the URI and IRI parsers.
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
- - RFC 3986 reference resolution and relative-reference generation receive no URN-specific semantics; RFC 8141 URN resolution services and URN-equivalence APIs are not implemented.
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