diff --git a/purl.js b/purl.js index 509ca08..851a240 100644 --- a/purl.js +++ b/purl.js @@ -69,6 +69,103 @@ return uri; }; + + function constructUriFromAttr( attr, data ) { + var result; + switch(attr) + { + case 'source': + result = data.attr.source; + break; + case 'relative': case 'protocol': case 'userInfo': case 'port': case 'host': + result = buildUrl(data); + break; + case 'authority': + data = reassignForAuthority(data); + result = buildUrl(data); + break; + case 'user': case 'password': + data = reassignForUserOrPassword(data); + result = buildUrl(data); + break; + case 'path': + data = reassignPath(data); + data = reassignRelative(data); + result = buildUrl(data); + break; + case 'directory': case 'file': case 'query': case 'fragment': + data = reassignRelative(data); + result = buildUrl(data); + break; + } + return purl(result); + } + + function reassignPath( data ) { + path = data.attr.path; + path = path.split("/"); + last = path.slice(-1)[0] + if (last.indexOf('.') != -1) { + data.attr.file = last; + path.pop(); + } else { + data.attr.file = ''; + } + path = path.join("/"); + data.attr.directory = path; + return data; + } + + function reassignRelative( data ) { + path = data.attr.directory + data.attr.file + if (data.attr.query.length != 0) { + path = path + "?" + data.attr.query; + } + if (data.attr.fragment.length != 0) { + path = path + "#" + data.attr.fragment; + } + data.attr.relative = path; + return data; + } + + + function reassignForAuthority( data ) { + authority = data.attr.authority + authority = authority.split("@") + if (authority.length >= 2) { + data.attr.userInfo = authority.shift(); + } + data.attr.host = authority.join("@") + return data; + } + + function reassignForUserOrPassword( data ) { + if (data.attr.user.length > 0 || data.attr.password.length > 0) { + data.attr.userInfo = data.attr.user + ":" + data.attr.password; + } + return data; + } + + + function buildUrl( data ) { + return normalizeProtocol(data.attr.protocol) + + normalizeUserInfo(data.attr.userInfo) + + data.attr.host + + normalizePort(data.attr.port) + + data.attr.relative; + } + + function normalizePort( port ) { + return port.length == 0 ? "" : ":" + port; + } + + function normalizeProtocol( protocol ) { + return protocol.length == 0 ? "" : protocol + "://"; + } + + function normalizeUserInfo( userInfo ) { + return userInfo.length == 0 ? "" : userInfo + "@"; + } function getAttrName( elm ) { var tn = elm.tagName; @@ -210,12 +307,29 @@ return { data : parseUri(url, strictMode), - + // attempt function overloading + overload : function( attr, value, getFunction, setFunction, data ) { + if ( typeof value === 'undefined' ) { + return getFunction(attr, data) + } else { + return setFunction(attr, value, data) + } + }, + // get various attributes from the URI - attr : function( attr ) { + getAttr : function( attr, data ) { attr = aliases[attr] || attr; - return typeof attr !== 'undefined' ? this.data.attr[attr] : this.data.attr; + return typeof attr !== 'undefined' ? data.attr[attr] : data.attr; + }, + // set various attributes from the URI + setAttr : function( attr, value, data ) { + typeof attr !== 'undefined' ? (data.attr[attr] = value) : (data.attr = value); + return constructUriFromAttr(attr, data); }, + // attempt function overloading + attr : function( attr, setter ) { + return this.overload(attr, setter, this.getAttr, this.setAttr, this.data); + }, // return query string parameters param : function( param ) { diff --git a/test/purl-tests.js b/test/purl-tests.js index d6e266d..e9842fd 100644 --- a/test/purl-tests.js +++ b/test/purl-tests.js @@ -1,79 +1,146 @@ buster.spec.expose(); -testSuite = function(url) { +testSuite = function(wrapper, safe) { + safe = safe || false; + before(function() { + this.url = wrapper('http://allmarkedup.com/folder/dir/index.html?item=value#foo', safe) + }) + + it('should have a protocol of http', function() { - expect(url.attr('protocol')).toBe('http'); + expect(this.url.attr('protocol')).toBe('http'); }); it('should have a path of /folder/dir/index.html', function() { - expect(url.attr('path')).toBe('/folder/dir/index.html'); + expect(this.url.attr('path')).toBe('/folder/dir/index.html'); }); /* should it? */ it('should have an unset port', function() { - expect(url.attr('port')).toBe(''); + expect(this.url.attr('port')).toBe(''); }); - it('should have an host of allmarkedup.com', function() { - expect(url.attr('host')).toBe('allmarkedup.com'); + it('should have a host of allmarkedup.com', function() { + expect(this.url.attr('host')).toBe('allmarkedup.com'); }); it('should have a relative path of /folder/dir/index.html?item=value#foo', function() { - expect(url.attr('relative')).toBe('/folder/dir/index.html?item=value#foo'); + expect(this.url.attr('relative')).toBe('/folder/dir/index.html?item=value#foo'); }); it('should have a path of /folder/dir/index.html', function() { - expect(url.attr('path')).toBe('/folder/dir/index.html'); + expect(this.url.attr('path')).toBe('/folder/dir/index.html'); }); it('should have a directory of /folder/dir/', function() { - expect(url.attr('directory')).toBe('/folder/dir/'); + expect(this.url.attr('directory')).toBe('/folder/dir/'); }); it('should have a file of index.html', function() { - expect(url.attr('file')).toBe('index.html'); + expect(this.url.attr('file')).toBe('index.html'); }); it('should have a querystring of item=value', function() { - expect(url.attr('query')).toBe('item=value'); + expect(this.url.attr('query')).toBe('item=value'); }); it('should have an anchor of foo', function() { - expect(url.attr('anchor')).toBe('foo'); - expect(url.attr('fragment')).toBe('foo'); + expect(this.url.attr('anchor')).toBe('foo'); + expect(this.url.attr('fragment')).toBe('foo'); }); it('should have a param() of item: "value"', function() { - expect(url.param()).toBeObject({item: 'value'}) + expect(this.url.param()).toBeObject({item: 'value'}) }); it('should have a param("item") of "value"', function() { - expect(url.param('item')).toBe('value') + expect(this.url.param('item')).toBe('value') }); it('should have a segment() of ["folder","dir","index.html"]', function() { - expect(url.segment()).toEqual(["folder","dir","index.html"]) + expect(this.url.segment()).toEqual(["folder","dir","index.html"]) }); it('should have a segment(1) of "folder"', function() { - expect(url.segment(1)).toBe("folder"); + expect(this.url.segment(1)).toBe("folder"); }); it('should have a segment(-1) of "folder"', function() { - expect(url.segment(-1)).toBe("index.html"); + expect(this.url.segment(-1)).toBe("index.html"); }); + + it('should have a source which is the url provided', function() { + expect(this.url.attr('source')).toBe('http://allmarkedup.com/folder/dir/index.html?item=value#foo'); + }); + + it('should let you set the source and that will change everything', function() { + expect(this.url.attr('source', 'http://www.google.com').attr('host')).toBe('www.google.com'); + }) + + it('should let you set relative path and that will show changes in the querystring', function() { + expect(this.url.attr('relative', '/page.html?herp=derp').attr('query')).toBe('herp=derp'); + }) + + it('should let you set the protocol to https', function() { + expect(this.url.attr('protocol', 'https').attr('protocol')).toBe('https'); + }); + + it('should change user and password if userInfo changes', function() { + expect(this.url.attr('userInfo', 'someone:password').attr('user')).toBe('someone'); + expect(this.url.attr('userInfo', 'someone:password').attr('password')).toBe('password'); + }); + + it('should change hostname if authority changes and a username and password are supplied', function() { + expect(this.url.attr('authority', 'someone:password@www.google.com').attr('host')).toBe('www.google.com'); + }); + + it('should change hostname if authority changes and a username and password are not supplied', function() { + expect(this.url.attr('authority', 'www.google.com').attr('host')).toBe('www.google.com'); + }); + + it('should change userInfo if user is changed', function() { + expect(this.url.attr('user', 'foo').attr('userInfo')).toBe('foo:'); + }); + + it('should change userInfo if password is changed', function() { + expect(this.url.attr('password', 'foo').attr('userInfo')).toBe(':foo'); + }); + + it('should change host if host is changed', function() { + expect(this.url.attr('host', 'www.google.com').attr('host')).toBe('www.google.com'); + }); + + it('should change relative if path is changed', function() { + expect(this.url.attr('path', '/something/else').attr('relative')).toBe('/something/else?item=value#foo'); + }); + + it('should change relative if directory is changed', function() { + expect(this.url.attr('directory', '/something/else/').attr('relative')).toBe('/something/else/index.html?item=value#foo'); + }); + + it('should change relative if file is changed', function() { + expect(this.url.attr('file', 'help.html').attr('relative')).toBe('/folder/dir/help.html?item=value#foo'); + }); + + it('should change relative if querystring is changed', function() { + expect(this.url.attr('query', 'another=query').attr('relative')).toBe('/folder/dir/index.html?another=query#foo'); + }); + + it('should change relative if fragment is changed', function() { + expect(this.url.attr('fragment', 'bar').attr('relative')).toBe('/folder/dir/index.html?item=value#bar'); + }); + + } describe("purl in non-strict mode", function () { - testSuite(purl('http://allmarkedup.com/folder/dir/index.html?item=value#foo')); + testSuite(purl, false); }); - describe("purl in strict mode", function () { - testSuite(purl('http://allmarkedup.com/folder/dir/index.html?item=value#foo', - true)); + testSuite(purl, true); }); diff --git a/test/template.html b/test/template.html new file mode 100644 index 0000000..b55fecd --- /dev/null +++ b/test/template.html @@ -0,0 +1,8 @@ + + +
+ + + + +