Skip to content

Commit

Permalink
fixing .relativeTo() for descendant paths - Issue #57
Browse files Browse the repository at this point in the history
  • Loading branch information
rodneyrehm committed Dec 27, 2012
1 parent 0159b2b commit 83c0d36
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 19 deletions.
57 changes: 38 additions & 19 deletions src/URI.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ generateAccessor = function(_part){
};
};

for (_part in _parts) {
for (_part in _parts) {
p[_part] = generateAccessor(_parts[_part]);
}

Expand Down Expand Up @@ -1507,7 +1507,7 @@ p.absoluteTo = function(base) {
p.relativeTo = function(base) {
var relative = this.clone();
var properties = ['protocol', 'username', 'password', 'hostname', 'port'];
var common, _base;
var common, _base, _this, _base_diff, _this_diff;

if (this._parts.urn) {
throw new Error('URNs do not have any generally defined hierachical components');
Expand All @@ -1521,33 +1521,52 @@ p.relativeTo = function(base) {
throw new Error('Cannot calculate common path from non-relative URLs');
}

// determine common sub path
common = URI.commonPath(relative.path(), base.path());
_base = base.directory();


// no relation if there's nothing in common
if (!common || common === '/') {
return relative;
}

// relative paths don't have authority
for (var i = 0, p; p = properties[i]; i++) {
relative._parts[p] = null;
}

if (!common || common === '/') {
return relative;

_base = base.directory();
_this = this.directory();

// base and this are on the same level
if (_base === _this) {
relative._parts.path = './' + relative.filename();
return relative.build();
}


_base_diff = _base.substring(common.length);
_this_diff = _this.substring(common.length);

// this is a descendant of base
if (_base + '/' === common) {
relative._parts.path = './' + relative.filename();
} else {
var parents = '../';
var _common = new RegExp('^' + escapeRegEx(common));
var _parents = _base.replace(_common, '/').match(/\//g).length -1;

while (_parents--) {
parents += '../';
if (_this_diff) {
_this_diff += '/';
}

relative._parts.path = './' + _this_diff + relative.filename();
return relative.build();
}

// this is a descendant of base
var parents = '../';
var _common = new RegExp('^' + escapeRegEx(common));
var _parents = _base.replace(_common, '/').match(/\//g).length -1;

relative._parts.path = relative._parts.path.replace(_common, parents);
while (_parents--) {
parents += '../';
}

relative.build();
return relative;
relative._parts.path = relative._parts.path.replace(_common, parents);
return relative.build();
};

// comparing URIs
Expand Down
5 changes: 5 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,11 @@ test("relativeTo", function() {
url: '/relative/path?blubber=1#hash1',
base: '/relative/sub/foo/sub/file?some=query#hash',
result: '../../../path?blubber=1#hash1'
}, {
name: 'descendant',
url: '/base/path/with/subdir/inner.html',
base: '/base/path/top.html',
result: './with/subdir/inner.html'
}
];

Expand Down

0 comments on commit 83c0d36

Please sign in to comment.