From 90c49826fd1b7ac9bd2e77c149762499d8145bfe Mon Sep 17 00:00:00 2001 From: Omar Qureshi Date: Tue, 4 Sep 2012 23:15:00 +0100 Subject: [PATCH 1/4] Implement function overloading for attr() Begin the implementation of attr('source', 'setter') and attr('relative', 'setter'). Since these are probably the easiest to implement for now. --- purl.js | 53 +++++++++++++++++++++++++++++++++++++++++++--- test/purl-tests.js | 31 +++++++++++++++++++++++---- test/template.html | 8 +++++++ 3 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 test/template.html diff --git a/purl.js b/purl.js index 509ca08..8fc6dd6 100644 --- a/purl.js +++ b/purl.js @@ -69,6 +69,36 @@ return uri; }; + + function constructUriFromAttr( attr, data ) { + var result; + switch(attr) + { + case 'source': + result = data.attr.source; + break; + case 'relative': + result = expandRelativeUrl(data); + break; + } + return purl(result); + } + + function expandRelativeUrl( data ) { + normalizeProtocol(data.attr.protocol) + normalizeUserInfo(data.attr.userInfo) + data.attr.relative + } + + function normalizeProtocol( protocol ) { + protocol.length == 0 ? "" : protocol + "://"; + } + + function normalizeUserInfo( userInfo ) { + userInfo.length == 0 ? "" : userInfo + "@"; + } + + function updateSource( data ) { + + } function getAttrName( elm ) { var tn = elm.tagName; @@ -210,12 +240,29 @@ return { data : parseUri(url, strictMode), - + // attempt function overloading + overload : function( attr, setter, getFunction, setFunction, data ) { + if ( typeof setter === 'undefined' ) { + return getFunction(attr, data) + } else { + return setFunction(attr, setter, 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, setter, data ) { + typeof attr !== 'undefined' ? (data.attr[attr] = setter) : (data.attr = setter); + 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..110fa01 100644 --- a/test/purl-tests.js +++ b/test/purl-tests.js @@ -1,6 +1,9 @@ buster.spec.expose(); -testSuite = function(url) { +testSuite = function(wrapper, safe) { + safe = safe || false; + 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'); }); @@ -14,7 +17,7 @@ testSuite = function(url) { expect(url.attr('port')).toBe(''); }); - it('should have an host of allmarkedup.com', function() { + it('should have a host of allmarkedup.com', function() { expect(url.attr('host')).toBe('allmarkedup.com'); }); @@ -62,18 +65,38 @@ testSuite = function(url) { it('should have a segment(-1) of "folder"', function() { expect(url.segment(-1)).toBe("index.html"); }); + + it('should have a source which is the url provided', function() { + expect(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(url.attr('source', 'http://www.google.com').attr('host')).toBe('www.google.com'); + }) + +/* + it('should let you set the protocol to https', function() { + expect(url.attr('protocol', 'https').attr('protocol').toBe('https')); + }); + +*/ +} + +testSuiteNoProtocol = function() { + } 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 () { +/* describe("purl in strict mode", function () { testSuite(purl('http://allmarkedup.com/folder/dir/index.html?item=value#foo', 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 @@ + + + + + + + + From 294dc46be6ab6c53a453e0b2fa509b3d245322cc Mon Sep 17 00:00:00 2001 From: Omar Qureshi Date: Tue, 4 Sep 2012 23:19:52 +0100 Subject: [PATCH 2/4] value is better than setter setter implies some sort of function --- purl.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/purl.js b/purl.js index 8fc6dd6..1a10784 100644 --- a/purl.js +++ b/purl.js @@ -241,11 +241,11 @@ data : parseUri(url, strictMode), // attempt function overloading - overload : function( attr, setter, getFunction, setFunction, data ) { - if ( typeof setter === 'undefined' ) { + overload : function( attr, value, getFunction, setFunction, data ) { + if ( typeof value === 'undefined' ) { return getFunction(attr, data) } else { - return setFunction(attr, setter, data) + return setFunction(attr, value, data) } }, @@ -255,8 +255,8 @@ return typeof attr !== 'undefined' ? data.attr[attr] : data.attr; }, // set various attributes from the URI - setAttr : function( attr, setter, data ) { - typeof attr !== 'undefined' ? (data.attr[attr] = setter) : (data.attr = setter); + setAttr : function( attr, value, data ) { + typeof attr !== 'undefined' ? (data.attr[attr] = value) : (data.attr = value); return constructUriFromAttr(attr, data); }, // attempt function overloading From 165e8b25183a13354d005d344b0674698d10717a Mon Sep 17 00:00:00 2001 From: Omar Qureshi Date: Wed, 5 Sep 2012 10:44:05 +0100 Subject: [PATCH 3/4] Implementation of basic setting of attr - along with test suite --- purl.js | 105 ++++++++++++++++++++++++++++++++++++++++----- test/purl-tests.js | 102 ++++++++++++++++++++++++++++++------------- 2 files changed, 167 insertions(+), 40 deletions(-) diff --git a/purl.js b/purl.js index 1a10784..961f04f 100644 --- a/purl.js +++ b/purl.js @@ -74,30 +74,113 @@ var result; switch(attr) { - case 'source': + case 'source': result = data.attr.source; break; - case 'relative': - result = expandRelativeUrl(data); + 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': + data = reassignForUserOrPassword(data); + result = buildUrl(data); + break; + case 'password': + data = reassignForUserOrPassword(data); + result = buildUrl(data); + break; + case 'path': + data = reassignPath(data); + data = reassignRelative(data); + result = buildUrl(data); + break; + case 'directory': + data = reassignRelative(data); + result = buildUrl(data); + break; + case 'file': + data = reassignRelative(data); + result = buildUrl(data); + break; + case 'query': + data = reassignRelative(data); + result = buildUrl(data); + break; + case 'fragment': + data = reassignRelative(data); + result = buildUrl(data); + break; } return purl(result); } - function expandRelativeUrl( data ) { - normalizeProtocol(data.attr.protocol) + normalizeUserInfo(data.attr.userInfo) + data.attr.relative + 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 normalizeProtocol( protocol ) { - protocol.length == 0 ? "" : protocol + "://"; + 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 normalizeUserInfo( userInfo ) { - userInfo.length == 0 ? "" : userInfo + "@"; + + 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 updateSource( 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 ) { diff --git a/test/purl-tests.js b/test/purl-tests.js index 110fa01..e9842fd 100644 --- a/test/purl-tests.js +++ b/test/purl-tests.js @@ -2,87 +2,134 @@ buster.spec.expose(); testSuite = function(wrapper, safe) { safe = safe || false; - url = wrapper('http://allmarkedup.com/folder/dir/index.html?item=value#foo', safe) + 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 a host of allmarkedup.com', function() { - expect(url.attr('host')).toBe('allmarkedup.com'); + 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(url.attr('source')).toBe('http://allmarkedup.com/folder/dir/index.html?item=value#foo'); + 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(url.attr('source', 'http://www.google.com').attr('host')).toBe('www.google.com'); + 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(url.attr('protocol', 'https').attr('protocol').toBe('https')); + 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'); + }); -testSuiteNoProtocol = function() { } @@ -92,11 +139,8 @@ describe("purl in non-strict mode", function () { }); +describe("purl in strict mode", function () { -/* describe("purl in strict mode", function () { - - testSuite(purl('http://allmarkedup.com/folder/dir/index.html?item=value#foo', - true)); + testSuite(purl, true); }); -*/ From acc9d793d257c772b073ea12881505393e6973c7 Mon Sep 17 00:00:00 2001 From: Omar Qureshi Date: Wed, 5 Sep 2012 10:49:45 +0100 Subject: [PATCH 4/4] Tidy up case statement --- purl.js | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/purl.js b/purl.js index 961f04f..851a240 100644 --- a/purl.js +++ b/purl.js @@ -84,11 +84,7 @@ data = reassignForAuthority(data); result = buildUrl(data); break; - case 'user': - data = reassignForUserOrPassword(data); - result = buildUrl(data); - break; - case 'password': + case 'user': case 'password': data = reassignForUserOrPassword(data); result = buildUrl(data); break; @@ -97,19 +93,7 @@ data = reassignRelative(data); result = buildUrl(data); break; - case 'directory': - data = reassignRelative(data); - result = buildUrl(data); - break; - case 'file': - data = reassignRelative(data); - result = buildUrl(data); - break; - case 'query': - data = reassignRelative(data); - result = buildUrl(data); - break; - case 'fragment': + case 'directory': case 'file': case 'query': case 'fragment': data = reassignRelative(data); result = buildUrl(data); break;