├── .editorconfig
├── .gitignore
├── README.md
├── UNLICENSE
├── index.js
├── package.json
└── test
└── IRI.test.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://EditorConfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = tab
7 | indent_size = 3
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | # stryker temp files
4 | .stryker-tmp
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IRI: A utility for converting and parsing URIs and IRIs
2 |
3 | Utilities for using RFC 3987 and
4 | RFC 3986
5 |
6 | IRIs are unicode URIs, URIs by definition being 7-bit characters.
7 |
8 | ## Construction of the URI
9 |
10 | From RFC 3986:
11 |
12 | foo://example.com:8042/over/there?name=ferret#nose
13 | \_/ \______________/\_________/ \_________/ \__/
14 | | | | | |
15 | scheme authority path query fragment
16 | | _____________________|__
17 | / \ / \
18 | urn:example:animal:ferret:nose
19 |
20 | The authority exists in a URI/IRI and is marked by a leading `//`. It can be broken down into a number of other components:
21 |
22 | root:hunter2@[::1]:8080
23 | \__________/ \___/ \__/
24 | | | |
25 | userinfo host port
26 |
27 | ## Usage of `IRI`
28 |
29 | The constructor takes a single argument, a URI or IRI string:
30 |
31 | var iri = require('iri');
32 | var path = new iri.IRI(str).resolveReference('/');
33 |
34 | ### toString()
35 |
36 | Returns UTF-16 IRI
37 |
38 | ### defrag()
39 |
40 | Returns the IRI without the fragment component. Useful for dereferencing URLs on a network.
41 |
42 | new IRI().defrag() === 'http://example.com/resource'
43 |
44 | ### isAbsolute()
45 |
46 | IRIs with a fragment are not absolute.
47 |
48 | ### toAbsolute()
49 |
50 | Resolves the IRI against itself, having the effect of stripping the fragment and checking that the supplied IRI is valid (absolute).
51 |
52 | ### authority()
53 |
54 | Returns the authority component of the IRI, such as "user:password@example.com:8080"
55 |
56 | ### fragment()
57 |
58 | Returns the fragment component of the IRI.
59 |
60 | ### hierpart()
61 |
62 | Returns the hier-part of the IRI, the hierarchial component: Everything between the scheme and query, including leading `//` for the host, if it exists.
63 |
64 | ### host()
65 |
66 | Returns the host component of the URI, either a domain name or string-formatted IP address. Excludes port number and username/password.
67 |
68 | ### path()
69 |
70 | Returns the path component of the hier-part. Does not include the authority/host, query, or fragment.
71 |
72 | ### port()
73 |
74 | Returns the port component of the authority as a string, or null if there is no port.
75 |
76 | ### query()
77 |
78 | Returns the query component of the IRI including leading "?", or `null` if there is no query component.
79 |
80 | ### resolveReference(ref)
81 |
82 | Resolve the provided URI/IRI reference against this IRI.
83 |
84 | ### scheme()
85 |
86 | Returns the scheme of the IRI, e.g. "https", "file", or "urn".
87 |
88 | ### userinfo()
89 |
90 | Returns the username/password component of the IRI.
91 |
92 | ### toURIString()
93 |
94 | Returns a URI formatted string with only 7-bit characters.
95 |
96 | ### toIRIString()
97 |
98 | Decodes URI-encoded UTF-8 characters and returns a unicode string (Strings in ECMAScript/JavaScript are UTF-16).
99 |
100 | ### toIRI()
101 |
102 | Returns a new IRI object with URI-encoded UTF-8 characters decoded.
103 |
104 |
105 | ## Function Usage
106 |
107 | ### iri.fromURI(uri)
108 |
109 | Returns an iri.IRI object with UTF-8 escaped characterd decoded.
110 |
111 | ### iri.toIRIString(uri)
112 |
113 | Returns an IRI string decoded from the given URI.
114 |
115 |
116 | ## Tests
117 |
118 | Tests are available as a Vows test suite. Run `vows` in the package directory to execute.
119 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var api = exports;
4 |
5 | api.encodeString = function encodeString(s) {
6 | var out = "";
7 | var skip = false;
8 | var _g1 = 0, _g = s.length;
9 | while(_g1 < _g) {
10 | var i = _g1++;
11 | if(!skip) {
12 | var code = s.charCodeAt(i);
13 | if(55296 <= code && code <= 56319) {
14 | var low = s.charCodeAt(i + 1);
15 | code = (code - 55296) * 1024 + (low - 56320) + 65536;
16 | skip = true;
17 | }
18 | if(code > 1114111) { throw new Error("Char out of range"); }
19 | var hex = "00000000".concat((new Number(code)).toString(16).toUpperCase());
20 | if(code >= 65536) {
21 | out += "\\U" + hex.slice(-8);
22 | } else {
23 | if(code >= 127 || code <= 31) {
24 | switch(code) {
25 | case 9: out += "\\t"; break;
26 | case 10: out += "\\n"; break;
27 | case 13: out += "\\r"; break;
28 | default: out += "\\u" + hex.slice(-4); break;
29 | }
30 | } else {
31 | switch(code) {
32 | case 34: out += '\\"'; break;
33 | case 92: out += "\\\\"; break;
34 | default: out += s.charAt(i); break;
35 | }
36 | }
37 | }
38 | } else {
39 | skip = !skip;
40 | }
41 | }
42 | return out;
43 | };
44 |
45 | /**
46 | * IRI
47 | */
48 | api.IRI = IRI;
49 | function IRI(iri) { this.value = iri; }
50 | IRI.SCHEME_MATCH = new RegExp("^[a-z0-9-.+]+:", "i");
51 | //IRI.prototype = new api.RDFNode;
52 | IRI.prototype.toString = function toString() { return this.value; };
53 | IRI.prototype.nodeType = function nodeType() { return "IRI"; };
54 | IRI.prototype.toNT = function toNT() { return "<" + api.encodeString(this.value) + ">"; };
55 | IRI.prototype.n3 = function n3() { return this.toNT(); };
56 | IRI.prototype.defrag = function defrag() {
57 | var i = this.value.indexOf("#");
58 | return (i < 0) ? this : new IRI(this.value.slice(0, i));
59 | };
60 | IRI.prototype.isAbsolute = function isAbsolute() {
61 | return this.scheme()!=null && this.hierpart()!=null && this.fragment()==null;
62 | };
63 | IRI.prototype.toAbsolute = function toAbsolute() {
64 | if(this.scheme() == null || this.hierpart() == null) { throw new Error("IRI must have a scheme and a hierpart!"); }
65 | return this.resolveReference(this.value).defrag();
66 | };
67 | IRI.prototype.getAuthority = function authority() {
68 | var hierpart = this.hierpart();
69 | if(hierpart.substring(0, 2) != "//") return null;
70 | var authority = hierpart.slice(2);
71 | var q = authority.indexOf("/");
72 | return q>=0 ? authority.substring(0, q) : authority;
73 | };
74 | IRI.prototype.getFragment = function fragment() {
75 | var i = this.value.indexOf("#");
76 | return (i<0) ? null : this.value.slice(i);
77 | };
78 | IRI.prototype.getHierpart = function hierpart() {
79 | var hierpart = this.value;
80 | var q = hierpart.indexOf("?");
81 | if(q >= 0) {
82 | hierpart = hierpart.substring(0, q);
83 | } else {
84 | q = hierpart.indexOf("#");
85 | if(q >= 0) hierpart = hierpart.substring(0, q);
86 | }
87 | var q2 = this.scheme();
88 | if(q2 != null) hierpart = hierpart.slice(1 + q2.length);
89 | return hierpart;
90 | };
91 | IRI.prototype.getHost = function host() {
92 | var host = this.authority();
93 | var q = host.indexOf("@");
94 | if(q >= 0) host = host.slice(++q);
95 | if(host.indexOf("[") == 0) {
96 | q = host.indexOf("]");
97 | if(q > 0) return host.substring(0, q);
98 | }
99 | q = host.lastIndexOf(":");
100 | return q >= 0 ? host.substring(0, q) : host;
101 | };
102 | IRI.prototype.getPath = function path() {
103 | var q = this.authority();
104 | if(q == null) return this.hierpart();
105 | return this.hierpart().slice(q.length + 2);
106 | };
107 | IRI.prototype.getPort = function port() {
108 | var host = this.authority();
109 | var q = host.indexOf("@");
110 | if(q >= 0) host = host.slice(++q);
111 | if(host.indexOf("[") == 0) {
112 | q = host.indexOf("]");
113 | if(q > 0) return host.substring(0, q);
114 | }
115 | q = host.lastIndexOf(":");
116 | if(q < 0) return null;
117 | host = host.slice(++q);
118 | return host.length == 0 ? null : host;
119 | };
120 | IRI.prototype.getQuery = function query() {
121 | var q = this.value.indexOf("?");
122 | if(q < 0) return null;
123 | var f = this.value.indexOf("#");
124 | if(f < 0) return this.value.slice(q);
125 | return this.value.substring(q, f);
126 | };
127 | api.removeDotSegments = function removeDotSegments(input) {
128 | var output = "";
129 | var q = 0;
130 | while(input.length > 0) {
131 | if(input.substr(0, 3) == "../" || input.substr(0, 2) == "./") {
132 | input = input.slice(input.indexOf("/"));
133 | }else if(input == "/.") {
134 | input = "/";
135 | }else if(input.substr(0, 3) == "/./") {
136 | input = input.slice(2);
137 | }else if(input.substr(0, 4) == "/../" || input == "/..") {
138 | input = (input=="/..") ? "/" : input.slice(3);
139 | q = output.lastIndexOf("/");
140 | output = (q>=0) ? output.substring(0, q) : "";
141 | }else if(input.substr(0, 2) == ".." || input.substr(0, 1) == ".") {
142 | input = input.slice(input.indexOf("."));
143 | q = input.indexOf(".");
144 | if(q >= 0) input = input.slice(q);
145 | }else {
146 | if(input.substr(0, 1) == "/") {
147 | output += "/";
148 | input = input.slice(1);
149 | }
150 | q = input.indexOf("/");
151 | if(q < 0) {
152 | output += input;
153 | input = "";
154 | }else {
155 | output += input.substring(0, q);
156 | input = input.slice(q);
157 | }
158 | }
159 | }
160 | return output;
161 | };
162 | IRI.prototype.resolveReference = function resolveReference(ref) {
163 | var reference;
164 | if(typeof ref == "string") {
165 | reference = new IRI(ref);
166 | }else if(ref.nodeType && ref.nodeType() == "IRI") {
167 | reference = ref;
168 | }else {
169 | throw new Error("Expected IRI or String");
170 | }
171 | var T = {scheme:"", authority:"", path:"", query:"", fragment:""};
172 | var q = "";
173 | if(reference.scheme() != null) {
174 | T.scheme = reference.scheme();
175 | q = reference.authority();
176 | T.authority += q!=null ? "//"+q : "";
177 | T.path = api.removeDotSegments(reference.path());
178 | T.query += reference.query()||'';
179 | }else {
180 | q = reference.authority();
181 | if(q != null) {
182 | T.authority = q!=null ? "//"+q : "";
183 | T.path = api.removeDotSegments(reference.path());
184 | T.query += reference.query()||'';
185 | }else {
186 | q = reference.path();
187 | if(q == "" || q == null) {
188 | T.path = this.path();
189 | q = reference.query();
190 | if(q != null) {
191 | T.query += q;
192 | }else {
193 | q = this.query();
194 | T.query += q!=null ? q : "";
195 | }
196 | }else {
197 | if(q.substring(0, 1) == "/") {
198 | T.path = api.removeDotSegments(q);
199 | }else {
200 | if(this.path() != null) {
201 | var q2 = this.path().lastIndexOf("/");
202 | if(q2 >= 0) {
203 | T.path = this.path().substring(0, ++q2);
204 | }
205 | T.path += reference.path();
206 | }else {
207 | T.path = "/" + q;
208 | }
209 | T.path = api.removeDotSegments(T.path);
210 | }
211 | T.query += reference.query()||'';
212 | }
213 | q = this.authority();
214 | T.authority = q!=null ? "//" + q : "";
215 | }
216 | T.scheme = this.scheme();
217 | }
218 | T.fragment = reference.fragment()||'';
219 | return new IRI(T.scheme + ":" + T.authority + T.path + T.query + T.fragment);
220 | };
221 | IRI.prototype.getScheme = function scheme() {
222 | var scheme = this.value.match(IRI.SCHEME_MATCH);
223 | return (scheme == null) ? null : scheme.shift().slice(0, -1);
224 | };
225 | IRI.prototype.getUserinfo = function userinfo() {
226 | var authority = this.authority();
227 | var q = authority.indexOf("@");
228 | return (q < 0) ? null : authority.substring(0, q);
229 | };
230 | IRI.prototype.toURIString = function toURIString(){
231 | return this.value.replace(/([\uA0-\uD7FF\uE000-\uFDCF\uFDF0-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF])/g, function(a){return encodeURI(a);});
232 | };
233 | IRI.prototype.toIRIString = function toIRIString(){
234 | // HEXDIG requires capital characters
235 | // 80-BF is following bytes, (%[89AB][0-9A-F])
236 | // 00-7F no bytes follow (%[0-7][0-9A-F])(%[89AB][0-9A-F]){0}
237 | // C0-DF one byte follows (%[CD][0-9A-F])(%[89AB][0-9A-F]){1}
238 | // E0-EF two bytes follow (%[E][0-9A-F])(%[89AB][0-9A-F]){2}
239 | // F0-F7 three bytes follow (%[F][0-7])(%[89AB][0-9A-F]){3}
240 | // F8-FB four bytes follow (%[F][89AB])(%[89AB][0-9A-F]){4}
241 | // FC-FD five bytes follow (%[F][CD])(%[89AB][0-9A-F]){5}
242 | var utf8regexp = /%([2-7][0-9A-F])|%[CD][0-9A-F](%[89AB][0-9A-F])|%[E][0-9A-F](%[89AB][0-9A-F]){2}|%[F][0-7](%[89AB][0-9A-F]){3}|%[F][89AB](%[89AB][0-9A-F]){4}|%[F][CD](%[89AB][0-9A-F]){5}/g;
243 | // reserved characters := gen-delims, space, and sub-delims
244 | // : / ? # [ ] @ ! $ & ' ( ) * + , ; =
245 | var reserved = [ '3A', '2F', '3F', '23', '5B', '5D', '40', '20', '21', '24', '26', '27', '28', '29', '2A', '2B', '2C', '3B', '3D'];
246 | var iri = this.toString().replace(utf8regexp, function(a, b){
247 | if(reserved.indexOf(b)>=0) return a;
248 | return decodeURIComponent(a);
249 | });
250 | return iri;
251 | };
252 |
253 | IRI.prototype.toIRI = function toIRI(){
254 | return new IRI(this.toIRIString());
255 | };
256 |
257 | // Alias old names to new ones
258 | IRI.prototype.authority = IRI.prototype.getAuthority;
259 | IRI.prototype.hierpart = IRI.prototype.getHierpart;
260 | IRI.prototype.scheme = IRI.prototype.getScheme;
261 | IRI.prototype.path = IRI.prototype.getPath;
262 | IRI.prototype.query = IRI.prototype.getQuery;
263 | IRI.prototype.fragment = IRI.prototype.getFragment;
264 | IRI.prototype.userinfo = IRI.prototype.getUserinfo;
265 | IRI.prototype.host = IRI.prototype.getHost;
266 | IRI.prototype.port = IRI.prototype.getPort;
267 |
268 | // Create a new IRI object and decode UTF-8 escaped characters
269 | api.fromURI = function fromURI(uri){
270 | return new IRI(uri).toIRI();
271 | };
272 |
273 | api.toIRIString = function toIRIString(uri){
274 | return new IRI(uri).toIRIString();
275 | };
276 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iri",
3 | "description": "IRI parsing and IRI-URI conversion utilities",
4 | "homepage": "https://github.com/awwright/node-iri",
5 | "author": "Austin Wright",
6 | "keywords": [
7 | "IRI"
8 | ],
9 | "repository": {
10 | "type": "git",
11 | "url": "git://github.com/awwright/node-iri.git",
12 | "web": "https://github.com/awwright/node-iri"
13 | },
14 | "main": "index.js",
15 | "scripts": {
16 | "coverage": "stryker run",
17 | "test": "mocha"
18 | },
19 | "license": "Unlicense",
20 | "devDependencies": {
21 | "@stryker-mutator/core": "^6.1.2",
22 | "@stryker-mutator/mocha-runner": "^6.1.2",
23 | "eslint": "^8.21.0",
24 | "mocha": "^10.0.0"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test/IRI.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var assert = require('assert').strict;
4 | var iri = require('../');
5 | var IRI = iri.IRI;
6 |
7 | function testConversion(irival, urival){
8 | it(irival, function(){
9 | assert.equal(new IRI(irival).toURIString(), urival);
10 | assert.equal(new IRI(urival).toIRIString(), irival);
11 | });
12 | }
13 |
14 | describe('Interface', function(){
15 | describe("new IRI()", function(){
16 | var t = new IRI('http://example.com/');
17 | it(".nodeType() === 'IRI'", function(){ assert.equal(t.scheme(), 'http'); });
18 | it(".toNT()", function(){ assert.equal(t.toNT(), ''); });
19 | it(".n3()", function(){ assert.equal(t.n3(), ''); });
20 | it(".defrag() is self", function(){ assert.equal(t.defrag().value, 'http://example.com/'); });
21 | it(".isAbsolute() is true", function(){ assert.equal(t.isAbsolute(), true); });
22 | it(".toAbsolute() is self", function(){ assert.equal(t.toAbsolute().value, 'http://example.com/'); });
23 | it(".authority() === 'example.com'", function(){ assert.equal(t.authority(), 'example.com'); });
24 | it(".fragment() is null", function(){ assert.equal(t.fragment(), null); });
25 | it(".hierpart() === '//example.com/'", function(){ assert.equal(t.hierpart(), '//example.com/'); });
26 | it(".host() === 'example.com'", function(){ assert.equal(t.host(), 'example.com'); });
27 | it(".path() === '/'", function(){ assert.equal(t.path(), '/'); });
28 | it(".port() is null", function(){ assert.equal(t.port(), null); });
29 | it(".query() is null", function(){ assert.equal(t.query(), null); });
30 | it(".resolveReference(absoluteURI)", function(){ assert.equal(t.resolveReference('http://xyz.example.org/123').value, 'http://xyz.example.org/123'); });
31 | it(".resolveReference(path)", function(){ assert.equal(t.resolveReference('/a/b/c').value, 'http://example.com/a/b/c'); });
32 | it(".resolveReference(authority)", function(){ assert.equal(t.resolveReference('//example.org/1?x').value, 'http://example.org/1?x'); });
33 | it(".resolveReference(relative)", function(){ assert.equal(t.resolveReference('b/c.js').value, 'http://example.com/b/c.js'); });
34 | it(".resolveReference(decend)", function(){ assert.equal(t.resolveReference('../..').value, 'http://example.com/'); });
35 | it(".resolveReference(query)", function(){ assert.equal(t.resolveReference('?query').value, 'http://example.com/?query'); });
36 | it(".scheme() === 'http'", function(){ assert.equal(t.scheme(), 'http'); });
37 | it(".userinfo() is null", function(){ assert.equal(t.userinfo(), null); });
38 | });
39 | describe("(new iri.IRI())", function(){
40 | var t = new iri.IRI('https://user:pass@a.example.com:8080/b/c/d/?123&aa=1&aa=2#455');
41 | it(".nodeType() === 'IRI'", function(){ assert.equal(t.nodeType(), 'IRI'); });
42 | it(".toNT()", function(){ assert.equal(t.toNT(), ''); });
43 | it(".n3()", function(){ assert.equal(t.n3(), ''); });
44 | it(".defrag() strips fragment", function(){ assert.equal(t.defrag().value, 'https://user:pass@a.example.com:8080/b/c/d/?123&aa=1&aa=2'); });
45 | it(".isAbsolute() is false", function(){ assert.equal(t.isAbsolute(), false); });
46 | it(".toAbsolute() strips fragment", function(){ assert.equal(t.toAbsolute().value, 'https://user:pass@a.example.com:8080/b/c/d/?123&aa=1&aa=2'); });
47 | it(".authority() === 'user:pass@a.example.com:8080'", function(){ assert.equal(t.authority(), 'user:pass@a.example.com:8080'); });
48 | it(".fragment()", function(){ assert.equal(t.fragment(), '#455'); });
49 | it(".hierpart()", function(){ assert.equal(t.hierpart(), '//user:pass@a.example.com:8080/b/c/d/'); });
50 | it(".host() === 'a.example.com'", function(){ assert.equal(t.host(), 'a.example.com'); });
51 | it(".path() === '/b/c/d/?123&aa=1&aa=2'", function(){ assert.equal(t.path(), '/b/c/d/'); });
52 | it(".port() is '8080'", function(){ assert.equal(t.port(), '8080'); });
53 | it(".query()", function(){ assert.equal(t.query(), '?123&aa=1&aa=2'); });
54 | it(".resolveReference(absoluteURI)", function(){ assert.equal(t.resolveReference('http://xyz.example.org/123').value, 'http://xyz.example.org/123'); });
55 | it(".resolveReference(path)", function(){ assert.equal(t.resolveReference('/a/b/c').value, 'https://user:pass@a.example.com:8080/a/b/c'); });
56 | it(".resolveReference(authority)", function(){ assert.equal(t.resolveReference('//example.org/1?x').value, 'https://example.org/1?x'); });
57 | it(".resolveReference(relative)", function(){ assert.equal(t.resolveReference('b/c.js').value, 'https://user:pass@a.example.com:8080/b/c/d/b/c.js'); });
58 | it(".resolveReference(cwd)", function(){ assert.equal(t.resolveReference('.').value, 'https://user:pass@a.example.com:8080/b/c/d/'); });
59 | it(".resolveReference(decend)", function(){ assert.equal(t.resolveReference('../..').value, 'https://user:pass@a.example.com:8080/b/'); });
60 | it(".resolveReference(query)", function(){ assert.equal(t.resolveReference('?query').value, 'https://user:pass@a.example.com:8080/b/c/d/?query'); });
61 | it(".scheme() === 'https'", function(){ assert.equal(t.scheme(), 'https'); });
62 | it(".userinfo()", function(){ assert.equal(t.userinfo(), 'user:pass'); });
63 | });
64 | describe("(new iri.IRI())", function(){
65 | // The examples from RFC 3986
66 | var t = new iri.IRI('http://a/b/c/d;p?q');
67 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g:h").value, "g:h"); });
68 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g").value, "http://a/b/c/g"); });
69 | it(".resolveReference(<./g>)", function(){ assert.equal(t.resolveReference("./g").value, "http://a/b/c/g"); });
70 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g/").value, "http://a/b/c/g/"); });
71 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("/g").value, "http://a/g"); });
72 | it(".resolveReference(/g>)", function(){ assert.equal(t.resolveReference("//g").value, "http://g"); });
73 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("?y").value, "http://a/b/c/d;p?y"); });
74 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g?y").value, "http://a/b/c/g?y"); });
75 | it(".resolveReference(<#s>)", function(){ assert.equal(t.resolveReference("#s").value, "http://a/b/c/d;p?q#s"); });
76 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g#s").value, "http://a/b/c/g#s"); });
77 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g?y#s").value, "http://a/b/c/g?y#s"); });
78 | it(".resolveReference(<;x>)", function(){ assert.equal(t.resolveReference(";x").value, "http://a/b/c/;x"); });
79 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g;x").value, "http://a/b/c/g;x"); });
80 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g;x?y#s").value, "http://a/b/c/g;x?y#s"); });
81 | it(".resolveReference(<>)", function(){ assert.equal(t.resolveReference("").value, "http://a/b/c/d;p?q"); });
82 | it(".resolveReference(<.>)", function(){ assert.equal(t.resolveReference(".").value, "http://a/b/c/"); });
83 | it(".resolveReference(<./>)", function(){ assert.equal(t.resolveReference("./").value, "http://a/b/c/"); });
84 | it(".resolveReference(<..>)", function(){ assert.equal(t.resolveReference("..").value, "http://a/b/"); });
85 | it(".resolveReference(<../>)", function(){ assert.equal(t.resolveReference("../").value, "http://a/b/"); });
86 | it(".resolveReference(<../g>)", function(){ assert.equal(t.resolveReference("../g").value, "http://a/b/g"); });
87 | it(".resolveReference(<../..>)", function(){ assert.equal(t.resolveReference("../..").value, "http://a/"); });
88 | it(".resolveReference(<../../>)", function(){ assert.equal(t.resolveReference("../../").value, "http://a/"); });
89 | it(".resolveReference(<../../g>)", function(){ assert.equal(t.resolveReference("../../g").value, "http://a/g"); });
90 | it(".resolveReference(<../../../g>)", function(){ assert.equal(t.resolveReference("../../../g").value, "http://a/g"); });
91 | it(".resolveReference(<../../../../g>)", function(){ assert.equal(t.resolveReference("../../../../g").value, "http://a/g"); });
92 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("/./g").value, "http://a/g"); });
93 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("/../g").value, "http://a/g"); });
94 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g.").value, "http://a/b/c/g."); });
95 | it(".resolveReference(<.g>)", function(){ assert.equal(t.resolveReference(".g").value, "http://a/b/c/.g"); });
96 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g..").value, "http://a/b/c/g.."); });
97 | it(".resolveReference(<..g>)", function(){ assert.equal(t.resolveReference("..g").value, "http://a/b/c/..g"); });
98 | it(".resolveReference(<./../g>)", function(){ assert.equal(t.resolveReference("./../g").value, "http://a/b/g"); });
99 | it(".resolveReference(<./g/.>)", function(){ assert.equal(t.resolveReference("./g/.").value, "http://a/b/c/g/"); });
100 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g/./h").value, "http://a/b/c/g/h"); });
101 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g/../h").value, "http://a/b/c/h"); });
102 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g;x=1/./y").value, "http://a/b/c/g;x=1/y"); });
103 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g;x=1/../y").value, "http://a/b/c/y"); });
104 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g?y/./x").value, "http://a/b/c/g?y/./x"); });
105 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g?y/../x").value, "http://a/b/c/g?y/../x"); });
106 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g#s/./x").value, "http://a/b/c/g#s/./x"); });
107 | it(".resolveReference()", function(){ assert.equal(t.resolveReference("g#s/../x").value, "http://a/b/c/g#s/../x"); });
108 | });
109 | describe("IRI to URI conversion", function(){
110 | var t = new IRI('http://www.example.org/red%09ros\xE9#red');
111 | it(".toURIString()", function(){ assert.equal(t.toURIString(), "http://www.example.org/red%09ros%C3%A9#red"); });
112 | });
113 | describe("IRI to URI conversion with surrogate pairs", function(){
114 | var t = new IRI('http://example.com/\uD800\uDF00\uD800\uDF01\uD800\uDF02');
115 | it(".toURIString()", function(){ assert.equal(t.toURIString(), "http://example.com/%F0%90%8C%80%F0%90%8C%81%F0%90%8C%82"); });
116 | });
117 | describe("IRI<->URI conversion", function(){
118 | describe("Standard examples", function(){
119 | testConversion('http://www.example.org/red%09ros\xE9#red', 'http://www.example.org/red%09ros%C3%A9#red');
120 | testConversion('http://example.com/\uD800\uDF00\uD800\uDF01\uD800\uDF02', 'http://example.com/%F0%90%8C%80%F0%90%8C%81%F0%90%8C%82');
121 | testConversion('http://www.example.org/r\xE9sum\xE9.html', 'http://www.example.org/r%C3%A9sum%C3%A9.html');
122 | testConversion('http://www.example.org/%2F', 'http://www.example.org/%2F');
123 | });
124 | describe("Reserved characters are not encoded", function(){
125 | testConversion('http://www.example.org/%3A', 'http://www.example.org/%3A');
126 | testConversion('http://www.example.org/%2F', 'http://www.example.org/%2F');
127 | testConversion('http://www.example.org/%3F', 'http://www.example.org/%3F');
128 | testConversion('http://www.example.org/%23', 'http://www.example.org/%23');
129 | testConversion('http://www.example.org/%5B', 'http://www.example.org/%5B');
130 | testConversion('http://www.example.org/%5D', 'http://www.example.org/%5D');
131 | testConversion('http://www.example.org/%40', 'http://www.example.org/%40');
132 | testConversion('http://www.example.org/%20', 'http://www.example.org/%20');
133 | testConversion('http://www.example.org/%21', 'http://www.example.org/%21');
134 | testConversion('http://www.example.org/%24', 'http://www.example.org/%24');
135 | testConversion('http://www.example.org/%26', 'http://www.example.org/%26');
136 | testConversion('http://www.example.org/%27', 'http://www.example.org/%27');
137 | testConversion('http://www.example.org/%28', 'http://www.example.org/%28');
138 | testConversion('http://www.example.org/%29', 'http://www.example.org/%29');
139 | testConversion('http://www.example.org/%2A', 'http://www.example.org/%2A');
140 | testConversion('http://www.example.org/%2B', 'http://www.example.org/%2B');
141 | testConversion('http://www.example.org/%2C', 'http://www.example.org/%2C');
142 | testConversion('http://www.example.org/%3B', 'http://www.example.org/%3B');
143 | testConversion('http://www.example.org/%3D', 'http://www.example.org/%3D');
144 | });
145 | });
146 | });
147 |
--------------------------------------------------------------------------------