identifier-js 0.0.1 → 0.0.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.
@@ -0,0 +1,472 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import id from '../index.js';
3
+
4
+ describe('parseUri', () => {
5
+ test('Full', () => {
6
+ expect(id.parseUri('https://jason@example.com:80/foo?bar#baz')).to.eql({
7
+ scheme: 'https',
8
+ authority: 'jason@example.com:80',
9
+ userinfo: 'jason',
10
+ host: 'example.com',
11
+ port: '80',
12
+ path: '/foo',
13
+ query: 'bar',
14
+ fragment: 'baz',
15
+ });
16
+ });
17
+
18
+ test('No path with query', () => {
19
+ expect(id.parseUri('https://example.org?bar')).to.eql({
20
+ scheme: 'https',
21
+ authority: 'example.org',
22
+ userinfo: undefined,
23
+ host: 'example.org',
24
+ port: undefined,
25
+ path: '',
26
+ query: 'bar',
27
+ fragment: undefined,
28
+ });
29
+ });
30
+
31
+ test('No path with fragment', () => {
32
+ expect(id.parseUri('https://example.org#baz')).to.eql({
33
+ scheme: 'https',
34
+ authority: 'example.org',
35
+ userinfo: undefined,
36
+ host: 'example.org',
37
+ port: undefined,
38
+ path: '',
39
+ query: undefined,
40
+ fragment: 'baz',
41
+ });
42
+ });
43
+
44
+ test('Scheme is required', () => {
45
+ expect(() => id.parseUri('//example.com/foo?bar#baz')).to.throw(Error, 'Invalid URI: //example.com/foo?bar#baz');
46
+ });
47
+
48
+ test('No authority', () => {
49
+ expect(id.parseUri('uri:/foo?bar#baz')).to.eql({
50
+ scheme: 'uri',
51
+ authority: undefined,
52
+ userinfo: undefined,
53
+ host: undefined,
54
+ port: undefined,
55
+ path: '/foo',
56
+ query: 'bar',
57
+ fragment: 'baz',
58
+ });
59
+ });
60
+
61
+ test('Rootless path', () => {
62
+ expect(id.parseUri('uri:foo?bar#baz')).to.eql({
63
+ scheme: 'uri',
64
+ authority: undefined,
65
+ userinfo: undefined,
66
+ host: undefined,
67
+ port: undefined,
68
+ path: 'foo',
69
+ query: 'bar',
70
+ fragment: 'baz',
71
+ });
72
+ });
73
+
74
+ test('Unicode is not allowed', () => {
75
+ expect(() => id.parseUri('http://examplé.org/rosé#')).to.throw(Error, 'Invalid URI: http://examplé.org/rosé#');
76
+ });
77
+ });
78
+
79
+ describe('isUriReference', () => {
80
+ test('Full', () => {
81
+ expect(id.parseUriReference('https://jason@example.com:80/foo?bar#baz')).to.eql({
82
+ scheme: 'https',
83
+ authority: 'jason@example.com:80',
84
+ userinfo: 'jason',
85
+ host: 'example.com',
86
+ port: '80',
87
+ path: '/foo',
88
+ query: 'bar',
89
+ fragment: 'baz',
90
+ });
91
+ });
92
+
93
+ test('No path with query', () => {
94
+ expect(id.parseUriReference('https://example.org?bar')).to.eql({
95
+ scheme: 'https',
96
+ authority: 'example.org',
97
+ userinfo: undefined,
98
+ host: 'example.org',
99
+ port: undefined,
100
+ path: '',
101
+ query: 'bar',
102
+ fragment: undefined,
103
+ });
104
+ });
105
+
106
+ test('No path with fragment', () => {
107
+ expect(id.parseUriReference('https://example.org#baz')).to.eql({
108
+ scheme: 'https',
109
+ authority: 'example.org',
110
+ userinfo: undefined,
111
+ host: 'example.org',
112
+ port: undefined,
113
+ path: '',
114
+ query: undefined,
115
+ fragment: 'baz',
116
+ });
117
+ });
118
+
119
+ test('No scheme with authority', () => {
120
+ expect(id.parseUriReference('//example.com/foo?bar#baz')).to.eql({
121
+ scheme: undefined,
122
+ authority: 'example.com',
123
+ userinfo: undefined,
124
+ host: 'example.com',
125
+ port: undefined,
126
+ path: '/foo',
127
+ query: 'bar',
128
+ fragment: 'baz',
129
+ });
130
+ });
131
+
132
+ test('No double slash', () => {
133
+ expect(id.parseUriReference('example.com/foo?bar#baz')).to.eql({
134
+ scheme: undefined,
135
+ authority: undefined,
136
+ userinfo: undefined,
137
+ host: undefined,
138
+ port: undefined,
139
+ path: 'example.com/foo',
140
+ query: 'bar',
141
+ fragment: 'baz',
142
+ });
143
+ });
144
+
145
+ test('No authority', () => {
146
+ expect(id.parseUriReference('/foo?bar#baz')).to.eql({
147
+ scheme: undefined,
148
+ authority: undefined,
149
+ userinfo: undefined,
150
+ host: undefined,
151
+ port: undefined,
152
+ path: '/foo',
153
+ query: 'bar',
154
+ fragment: 'baz',
155
+ });
156
+ });
157
+
158
+ test('No path', () => {
159
+ expect(id.parseUriReference('?bar#baz')).to.eql({
160
+ scheme: undefined,
161
+ authority: undefined,
162
+ userinfo: undefined,
163
+ host: undefined,
164
+ port: undefined,
165
+ path: '',
166
+ query: 'bar',
167
+ fragment: 'baz',
168
+ });
169
+ });
170
+
171
+ test('No query', () => {
172
+ expect(id.parseUriReference('#baz')).to.eql({
173
+ scheme: undefined,
174
+ authority: undefined,
175
+ userinfo: undefined,
176
+ host: undefined,
177
+ port: undefined,
178
+ path: '',
179
+ query: undefined,
180
+ fragment: 'baz',
181
+ });
182
+ });
183
+
184
+ test('Empty', () => {
185
+ expect(id.parseUriReference('')).to.eql({
186
+ scheme: undefined,
187
+ authority: undefined,
188
+ userinfo: undefined,
189
+ host: undefined,
190
+ port: undefined,
191
+ path: '',
192
+ query: undefined,
193
+ fragment: undefined,
194
+ });
195
+ });
196
+
197
+ test('Unicode is not allowed', () => {
198
+ expect(() => id.parseUriReference('/rosé#')).to.throw(Error, 'Invalid URI-reference: /rosé#');
199
+ });
200
+ });
201
+
202
+ describe('isAbsoluteUri', () => {
203
+ test('Full', () => {
204
+ expect(id.parseAbsoluteUri('https://jason@example.com:80/foo?bar')).to.eql({
205
+ scheme: 'https',
206
+ authority: 'jason@example.com:80',
207
+ userinfo: 'jason',
208
+ host: 'example.com',
209
+ port: '80',
210
+ path: '/foo',
211
+ query: 'bar',
212
+ });
213
+ });
214
+
215
+ test('Scheme is required', () => {
216
+ expect(() => id.parseAbsoluteUri('//example.com/foo?bar')).to.throw(Error, 'Invalid absolute-URI: //example.com/foo?bar');
217
+ });
218
+
219
+ test('Fragment is not allowed', () => {
220
+ expect(() => id.parseAbsoluteUri('https://example.com/foo?bar#baz')).to.throw(Error, 'Invalid absolute-URI: https://example.com/foo?bar#baz');
221
+ });
222
+
223
+ test('Unicode is not allowed', () => {
224
+ expect(() =>id. parseAbsoluteUri('http://examplé.org/rosé')).to.throw(Error, 'Invalid absolute-URI: http://examplé.org/rosé');
225
+ });
226
+ });
227
+
228
+ describe('parseIri', () => {
229
+ test('Full', () => {
230
+ expect(id.parseIri('http://jásón@examplé.org:80/rosé?fóo#bár')).to.eql({
231
+ scheme: 'http',
232
+ authority: 'jásón@examplé.org:80',
233
+ userinfo: 'jásón',
234
+ host: 'examplé.org',
235
+ port: '80',
236
+ path: '/rosé',
237
+ query: 'fóo',
238
+ fragment: 'bár',
239
+ });
240
+ });
241
+
242
+ test('No path with query', () => {
243
+ expect(id.parseIri('http://examplé.org?fóo')).to.eql({
244
+ scheme: 'http',
245
+ authority: 'examplé.org',
246
+ userinfo: undefined,
247
+ host: 'examplé.org',
248
+ port: undefined,
249
+ path: '',
250
+ query: 'fóo',
251
+ fragment: undefined,
252
+ });
253
+ });
254
+
255
+ test('No path with fragment', () => {
256
+ expect(id.parseIri('http://examplé.org#bár')).to.eql({
257
+ scheme: 'http',
258
+ authority: 'examplé.org',
259
+ userinfo: undefined,
260
+ host: 'examplé.org',
261
+ port: undefined,
262
+ path: '',
263
+ query: undefined,
264
+ fragment: 'bár',
265
+ });
266
+ });
267
+
268
+ test('Scheme is required', () => {
269
+ expect(() => id.parseIri('//examplé.com/rosé?fóo#bár')).to.throw(Error, 'Invalid IRI: //examplé.com/rosé?fóo#bár');
270
+ });
271
+
272
+ test('No authority', () => {
273
+ expect(id.parseIri('uri:/rosé?fóo#bár')).to.eql({
274
+ scheme: 'uri',
275
+ authority: undefined,
276
+ userinfo: undefined,
277
+ host: undefined,
278
+ port: undefined,
279
+ path: '/rosé',
280
+ query: 'fóo',
281
+ fragment: 'bár',
282
+ });
283
+ });
284
+
285
+ test('Rootless path', () => {
286
+ expect(id.parseIri('uri:rosé?fóo#bár')).to.eql({
287
+ scheme: 'uri',
288
+ authority: undefined,
289
+ userinfo: undefined,
290
+ host: undefined,
291
+ port: undefined,
292
+ path: 'rosé',
293
+ query: 'fóo',
294
+ fragment: 'bár',
295
+ });
296
+ });
297
+
298
+ test('Unicode is not allowed in scheme', () => {
299
+ expect(() => id.parseIri('examplé://examplé.org/rosé')).to.throw(Error, 'Invalid IRI: examplé://examplé.org/rosé');
300
+ });
301
+ });
302
+
303
+ describe('parseIriReference', () => {
304
+ test('Full', () => {
305
+ expect(id.parseIriReference('http://jásón@examplé.org:80/rosé?fóo#bár')).to.eql({
306
+ scheme: 'http',
307
+ authority: 'jásón@examplé.org:80',
308
+ userinfo: 'jásón',
309
+ host: 'examplé.org',
310
+ port: '80',
311
+ path: '/rosé',
312
+ query: 'fóo',
313
+ fragment: 'bár',
314
+ });
315
+ });
316
+
317
+ test('No path with query', () => {
318
+ expect(id.parseIriReference('http://examplé.org?fóo')).to.eql({
319
+ scheme: 'http',
320
+ authority: 'examplé.org',
321
+ userinfo: undefined,
322
+ host: 'examplé.org',
323
+ port: undefined,
324
+ path: '',
325
+ query: 'fóo',
326
+ fragment: undefined,
327
+ });
328
+ });
329
+
330
+ test('No path with fragment', () => {
331
+ expect(id.parseIriReference('http://examplé.org#bár')).to.eql({
332
+ scheme: 'http',
333
+ authority: 'examplé.org',
334
+ userinfo: undefined,
335
+ host: 'examplé.org',
336
+ port: undefined,
337
+ path: '',
338
+ query: undefined,
339
+ fragment: 'bár',
340
+ });
341
+ });
342
+
343
+ test('No scheme with authority', () => {
344
+ expect(id.parseIriReference('//examplé.org/rosé?fóo#bár')).to.eql({
345
+ scheme: undefined,
346
+ authority: 'examplé.org',
347
+ userinfo: undefined,
348
+ host: 'examplé.org',
349
+ port: undefined,
350
+ path: '/rosé',
351
+ query: 'fóo',
352
+ fragment: 'bár',
353
+ });
354
+ });
355
+
356
+ test('No double slash', () => {
357
+ expect(id.parseIriReference('examplé.org/rosé?fóo#bár')).to.eql({
358
+ scheme: undefined,
359
+ authority: undefined,
360
+ userinfo: undefined,
361
+ host: undefined,
362
+ port: undefined,
363
+ path: 'examplé.org/rosé',
364
+ query: 'fóo',
365
+ fragment: 'bár',
366
+ });
367
+ });
368
+
369
+ test('No authority', () => {
370
+ expect(id.parseIriReference('/rosé?fóo#bár')).to.eql({
371
+ scheme: undefined,
372
+ authority: undefined,
373
+ userinfo: undefined,
374
+ host: undefined,
375
+ port: undefined,
376
+ path: '/rosé',
377
+ query: 'fóo',
378
+ fragment: 'bár',
379
+ });
380
+ });
381
+
382
+ test('Rootless path', () => {
383
+ expect(id.parseIriReference('rosé?fóo#bár')).to.eql({
384
+ scheme: undefined,
385
+ authority: undefined,
386
+ userinfo: undefined,
387
+ host: undefined,
388
+ port: undefined,
389
+ path: 'rosé',
390
+ query: 'fóo',
391
+ fragment: 'bár',
392
+ });
393
+ });
394
+
395
+ test('Query and fragment', () => {
396
+ expect(id.parseIriReference('?fóo#bár')).to.eql({
397
+ scheme: undefined,
398
+ authority: undefined,
399
+ userinfo: undefined,
400
+ host: undefined,
401
+ port: undefined,
402
+ path: '',
403
+ query: 'fóo',
404
+ fragment: 'bár',
405
+ });
406
+ });
407
+
408
+ test('Query only', () => {
409
+ expect(id.parseIriReference('?fóo')).to.eql({
410
+ scheme: undefined,
411
+ authority: undefined,
412
+ userinfo: undefined,
413
+ host: undefined,
414
+ port: undefined,
415
+ path: '',
416
+ query: 'fóo',
417
+ fragment: undefined,
418
+ });
419
+ });
420
+
421
+ test('Fragment only', () => {
422
+ expect(id.parseIriReference('#bár')).to.eql({
423
+ scheme: undefined,
424
+ authority: undefined,
425
+ userinfo: undefined,
426
+ host: undefined,
427
+ port: undefined,
428
+ path: '',
429
+ query: undefined,
430
+ fragment: 'bár',
431
+ });
432
+ });
433
+
434
+ test('Empty', () => {
435
+ expect(id.parseIriReference('')).to.eql({
436
+ scheme: undefined,
437
+ authority: undefined,
438
+ userinfo: undefined,
439
+ host: undefined,
440
+ port: undefined,
441
+ path: '',
442
+ query: undefined,
443
+ fragment: undefined,
444
+ });
445
+ });
446
+ });
447
+
448
+ describe('parseAbsoluteIri', () => {
449
+ test('Full', () => {
450
+ expect(id.parseAbsoluteIri('http://jásón:jásón@examplé.org:80/rosé?fóo')).to.eql({
451
+ scheme: 'http',
452
+ authority: 'jásón:jásón@examplé.org:80',
453
+ userinfo: 'jásón:jásón',
454
+ host: 'examplé.org',
455
+ port: '80',
456
+ path: '/rosé',
457
+ query: 'fóo',
458
+ });
459
+ });
460
+
461
+ test('Scheme is required', () => {
462
+ expect(() => id.parseAbsoluteIri('//examplé.org/rosé?fóo')).to.throw(Error, 'Invalid absolute-IRI: //examplé.org/rosé?fóo');
463
+ });
464
+
465
+ test('Fragment is not allowed', () => {
466
+ expect(() => id.parseAbsoluteIri('http://examplé.org/rosé?fóo#bár')).to.throw(Error, 'Invalid absolute-IRI: http://examplé.org/rosé?fóo#bár');
467
+ });
468
+
469
+ test('Unicode is not allowed in scheme', () => {
470
+ expect(() => id.parseAbsoluteIri('examplé://examplé.org/rosé')).to.throw(Error, 'Invalid absolute-IRI: examplé://examplé.org/rosé');
471
+ });
472
+ });
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+ //
3
+ const { isAbsoluteIri, isAbsoluteUri, isIPv4, isIPv6, isIri, isIriReference, isUUID, isUUIDv4, isUri, isUriReference, parseAbsoluteIri, parseAbsoluteUri, parseIri, parseIriReference, parseUri, parseUriReference } = require('..');
4
+ //
5
+ const uri = 'https://user:pass@munich-und-uberacht.de:15/path.to/the/ccc.txt?ddd=ddd#/eee/fff/ggg';
6
+ const iri = 'https://user:pass@münich-und-uberacht.de:15/path.to/the/ccc.txt?ddd=ddd#/eee/fff/ggg';
7
+
8
+ const iterations = 1000000;
9
+
10
+ console.log(` Number of iterations: ${iterations}`);
11
+
12
+ // URI_reference
13
+ console.time(' parse URI_reference');
14
+ for (let i = 0; i < iterations; i++) parseUriReference(uri);
15
+ console.timeEnd(' parse URI_reference');
16
+
17
+ console.time('validate URI_reference');
18
+ for (let i = 0; i < iterations; i++) isUriReference(uri);
19
+ console.timeEnd('validate URI_reference');
20
+
21
+ // URI
22
+ console.time(' parse URI');
23
+ for (let i = 0; i < iterations; i++) parseUri(uri);
24
+ console.timeEnd(' parse URI');
25
+
26
+ console.time(' validate URI');
27
+ for (let i = 0; i < iterations; i++) isUri(uri);
28
+ console.timeEnd(' validate URI');
29
+
30
+ // IRI_reference
31
+ console.time(' parse IRI_reference');
32
+ for (let i = 0; i < iterations; i++) parseIriReference(iri);
33
+ console.timeEnd(' parse IRI_reference');
34
+
35
+ console.time('validate IRI_reference');
36
+ for (let i = 0; i < iterations; i++) isIriReference(iri);
37
+ console.timeEnd('validate IRI_reference');
38
+
39
+ // IRI
40
+ console.time(' parse IRI');
41
+ for (let i = 0; i < iterations; i++) parseIri(iri);
42
+ console.timeEnd(' parse IRI');
43
+
44
+ console.time(' validate IRI');
45
+ for (let i = 0; i < iterations; i++) isIri(iri);
46
+ console.timeEnd(' validate IRI');
@@ -0,0 +1,62 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import id from '../index.js';
3
+ //
4
+ const base = 'http://a/b/c/d;p?q';
5
+ const refs = {
6
+ "g:h" : "g:h",
7
+ "g" : "http://a/b/c/g",
8
+ "./g" : "http://a/b/c/g",
9
+ "g/" : "http://a/b/c/g/",
10
+ "/g" : "http://a/g",
11
+ "//g" : "http://g",
12
+ "?y" : "http://a/b/c/d;p?y",
13
+ "g?y" : "http://a/b/c/g?y",
14
+ "#s" : "http://a/b/c/d;p?q#s",
15
+ "g#s" : "http://a/b/c/g#s",
16
+ "g?y#s" : "http://a/b/c/g?y#s",
17
+ ";x" : "http://a/b/c/;x",
18
+ "g;x" : "http://a/b/c/g;x",
19
+ "g;x?y#s" : "http://a/b/c/g;x?y#s",
20
+ "" : "http://a/b/c/d;p?q",
21
+ "." : "http://a/b/c/",
22
+ "./" : "http://a/b/c/",
23
+ ".." : "http://a/b/",
24
+ "../" : "http://a/b/",
25
+ "../g" : "http://a/b/g",
26
+ "../.." : "http://a/",
27
+ "../../" : "http://a/",
28
+ "../../g" : "http://a/g",
29
+ "../../../g" : "http://a/g",
30
+ "../../../../g" : "http://a/g",
31
+ "/./g" : "http://a/g",
32
+ "/../g" : "http://a/g",
33
+ "g." : "http://a/b/c/g.",
34
+ ".g" : "http://a/b/c/.g",
35
+ "g.." : "http://a/b/c/g..",
36
+ "..g" : "http://a/b/c/..g",
37
+ "./../g" : "http://a/b/g",
38
+ "./g/." : "http://a/b/c/g/",
39
+ "g/./h" : "http://a/b/c/g/h",
40
+ "g/../h" : "http://a/b/c/h",
41
+ "g;x=1/./y" : "http://a/b/c/g;x=1/y",
42
+ "g;x=1/../y" : "http://a/b/c/y",
43
+ "g?y/./x" : "http://a/b/c/g?y/./x",
44
+ "g?y/../x" : "http://a/b/c/g?y/../x",
45
+ "g#s/./x" : "http://a/b/c/g#s/./x",
46
+ "g#s/../x" : "http://a/b/c/g#s/../x",
47
+ }
48
+
49
+ describe('resolveReference', () => {
50
+ Object.keys(refs).forEach((reference) => {
51
+ const expected = refs[reference];
52
+ test(`resolveReference('${reference}', '${base}') === '${expected}'`, () => {
53
+ const subject = id.resolveReference(reference, base);
54
+ expect(subject).to.equal(expected);
55
+ });
56
+ });
57
+ });
58
+
59
+ // WHATWG is adding the / if no path after authority and scheme is one of their handled: http, https, ftp, ws, wss, etc
60
+ // Object.keys(refs).forEach((key) => {
61
+ // if (new URL(key, base).href !== refs[key]) console.log('[whatwg url]: Error! expected vs result:', refs[key], '=>', new URL(key, base).href);
62
+ // });
@@ -0,0 +1,25 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import id from '../index.js';
3
+
4
+ const resolveTests = [
5
+ // ['', 'urn:some:ip:prop', 'urn:some:ip:prop'], // invalid base (resolveReference throw)
6
+ // ['#', 'urn:some:ip:prop', 'urn:some:ip:prop'], // invalid base (resolveReference throw)
7
+ ['urn:some:ip:prop', 'urn:some:ip:prop', 'urn:some:ip:prop'],
8
+ ['urn:some:other:prop', 'urn:some:ip:prop', 'urn:some:ip:prop'],
9
+ ['hTTp://example.com/b/c/d/e', '', 'http://example.com/b/c/d/e'], // scheme to lowercase
10
+ ['http://eXaMpLe.com/b/c/d/e', '', 'http://example.com/b/c/d/e'], // authority to lowercase
11
+ ['http://example.com/b%2Ec/d/e', '', 'http://example.com/b.c/d/e'], // Unnecessary encoding segment
12
+ ['http://example.com/b%2Fc/d/e', '', 'http://example.com/b%2Fc/d/e'], // Necessary encoding segment
13
+ ['http://example.com/b%2fc/d/e', '', 'http://example.com/b%2Fc/d/e'], // Case normalization of encoding segment
14
+ ['http://example.com/b?c%2Fd%3Fe', '', 'http://example.com/b?c/d?e'], // Unnecessary encoding query
15
+ ['http://example.com/b', '#c%2Fd%3Fe', 'http://example.com/b#c/d?e'], // Unnecessary encoding fragment
16
+ ];
17
+
18
+ describe('resolveReference', () => {
19
+ resolveTests.forEach(([baseIri, iriReference, expected]) => {
20
+ test(`resolveReference('${iriReference}', '${baseIri}') === '${expected}'`, () => {
21
+ const subject = id.resolveReference(iriReference, baseIri);
22
+ expect(subject).to.equal(expected);
23
+ });
24
+ });
25
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import id from '../index.js';
3
+
4
+ describe('toAbsoluteReference', () => {
5
+ test('Base with a fragment', () => {
6
+ expect(id.toAbsoluteReference('http://examplé://examplé.org/rosé#dasd')).to.equal('http://examplé://examplé.org/rosé');
7
+ });
8
+
9
+ test('Scheme is required', () => {
10
+ expect(() => id.toAbsoluteReference('//example.com/foo?bar#baz')).to.throw(Error, 'Invalid IRI: //example.com/foo?bar#baz');
11
+ });
12
+ });
@@ -0,0 +1,50 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import id from '../index.js';
3
+
4
+ describe('toRelativeReference IRI', () => {
5
+ test.each([
6
+ ['https://examplé.com/var/lib', 'https://examplé.com', '/var/lib'],
7
+ ['https://examplé.com/var/lib', 'https://examplé.com/z', 'var/lib'],
8
+ ['https://examplé.com/a/var/lib', 'https://examplé.com/a', 'a/var/lib'],
9
+ ['https://examplé.com/a/var/lib', 'https://examplé.com/a/', 'var/lib'],
10
+ ['https://examplé.com/foo/test/bar/package.json', 'https://examplé.com/foo/test', 'test/bar/package.json'],
11
+ ['https://examplé.com/var', 'https://examplé.com/var/lib', '../var'],
12
+ ['https://examplé.com/bin', 'https://examplé.com/var/lib', '../bin'],
13
+ ['https://examplé.com/var/lib', 'https://examplé.com/var/lib', ''],
14
+ ['https://examplé.com/var/apache', 'https://examplé.com/var/lib', 'apache'],
15
+ ['https://examplé.com/Users/a/web/b', 'https://examplé.com/Users/a/web/b/test/mails', '../../b'],
16
+ ['https://examplé.com/foo/bar/baz', 'https://examplé.com/foo/bar/baz-quux', 'baz'],
17
+ ['https://examplé.com/foo/bar/baz-quux', 'https://examplé.com/foo/bar/baz', 'baz-quux'],
18
+ ['https://examplé.com/baz', 'https://examplé.com/baz-quux', 'baz'],
19
+ ['https://examplé.com/baz-quux', 'https://examplé.com/baz', 'baz-quux'],
20
+ ['https://examplé.com/', 'https://examplé.com/page1/page2/foo', '../../'],
21
+ ])('toRelativeIri(%s, %s) => %s', (target, base, expected) => {
22
+ const relative = id.toRelativeReference(target, base);
23
+ expect(relative).to.equal(expected);
24
+ expect(id.resolveReference(relative, base)).to.equal(target); // sanity check
25
+ });
26
+ });
27
+
28
+ describe('toRelativeReference URI', () => {
29
+ test.each([
30
+ ['https://example.com/var/lib', 'https://example.com', '/var/lib'],
31
+ ['https://example.com/var/lib', 'https://example.com/z', 'var/lib'],
32
+ ['https://example.com/a/var/lib', 'https://example.com/a', 'a/var/lib'],
33
+ ['https://example.com/a/var/lib', 'https://example.com/a/', 'var/lib'],
34
+ ['https://example.com/foo/test/bar/package.json', 'https://example.com/foo/test', 'test/bar/package.json'],
35
+ ['https://example.com/var', 'https://example.com/var/lib', '../var'],
36
+ ['https://example.com/bin', 'https://example.com/var/lib', '../bin'],
37
+ ['https://example.com/var/lib', 'https://example.com/var/lib', ''],
38
+ ['https://example.com/var/apache', 'https://example.com/var/lib', 'apache'],
39
+ ['https://example.com/Users/a/web/b', 'https://example.com/Users/a/web/b/test/mails', '../../b'],
40
+ ['https://example.com/foo/bar/baz', 'https://example.com/foo/bar/baz-quux', 'baz'],
41
+ ['https://example.com/foo/bar/baz-quux', 'https://example.com/foo/bar/baz', 'baz-quux'],
42
+ ['https://example.com/baz', 'https://example.com/baz-quux', 'baz'],
43
+ ['https://example.com/baz-quux', 'https://example.com/baz', 'baz-quux'],
44
+ ['https://example.com/', 'https://example.com/page1/page2/foo', '../../'],
45
+ ])('toRelativeIri(%s, %s) => %s', (target, base, expected) => {
46
+ const relative = id.toRelativeReference(target, base);
47
+ expect(relative).to.equal(expected);
48
+ expect(id.resolveReference(relative, base)).to.equal(target); // sanity check
49
+ });
50
+ });