I was toying with a completely different thing and specifically a Yahoo service that gives you the ability to use HTML as data and then lets you use xpath to query this data. I came up with a somewhat interesting idea (will post tomorrow, too late now), but all of a sudden I realized I need to convert relative links to absolute ones. I thought it's just a trivial thing (I mean how hard could it be) but then it turns out there are these little edge cases...
Anyway, I came up with something and posting here in case someone else might need it (or even me, for example two years from now. Hmm, will there be URLs in the future, in the distant 2011, or we'll all be just pure non-material consciousness ?)
So, the test page is here
And the actual code (also on github) is as follows:
function toAbs(link, host) { var lparts = link.split('/'); if (/http:|https:|ftp:/.test(lparts[0])) { // already abs, return return link; } var i, hparts = host.split('/'); if (hparts.length > 3) { hparts.pop(); // strip trailing thingie, either scriptname or blank } if (lparts[0] === '') { // like "/here/dude.png" host = hparts[0] + '//' + hparts[2]; hparts = host.split('/'); // re-split host parts from scheme and domain only delete lparts[0]; } for(i = 0; i < lparts.length; i++) { if (lparts[i] === '..') { // remove the previous dir level, if exists if (typeof lparts[i - 1] !== 'undefined') { delete lparts[i - 1]; } else if (hparts.length > 3) { // at least leave scheme and domain hparts.pop(); // stip one dir off the host for each /../ } delete lparts[i]; } if(lparts[i] === '.') { delete lparts[i]; } } // remove deleted var newlinkparts = []; for (i = 0; i < lparts.length; i++) { if (typeof lparts[i] !== 'undefined') { newlinkparts[newlinkparts.length] = lparts[i]; } } return hparts.join('/') + '/' + newlinkparts.join('/'); }
Update: added a check for ./ in the URLs thanks to QA from Boštjan