Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editable attributes #34

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 117 additions & 3 deletions purl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 ) {
Expand Down
111 changes: 89 additions & 22 deletions test/purl-tests.js
Original file line number Diff line number Diff line change
@@ -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:[email protected]').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);

});
8 changes: 8 additions & 0 deletions test/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<!doctype html>
<html>
<head>
<script src="../purl.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>