Browse Source

add path.relative

v0.7.4-release
Tony Huang 14 years ago
committed by Ryan Dahl
parent
commit
502900c0bc
  1. 103
      lib/path.js
  2. 36
      test/simple/test-path.js

103
lib/path.js

@ -165,6 +165,64 @@ if (isWindows) {
return exports.normalize(joined);
};
// path.relative(from, to)
// it will solve the relative path from 'from' to 'to', for instance:
// from = 'C:\\orandea\\test\\aaa'
// to = 'C:\\orandea\\impl\\bbb'
// The output of the function should be: '..\\..\\impl\\bbb'
// windows version
exports.relative = function(from, to) {
from = exports.resolve(from);
to = exports.resolve(to);
// windows is not case sensitive
var lowerFrom = from.toLowerCase();
var lowerTo = to.toLowerCase();
function trim(arr) {
var start = 0;
for(;start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for(;end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('\\'));
var toParts = trim(to.split('\\'));
var lowerFromParts = trim(lowerFrom.split('\\'));
var lowerToParts = trim(lowerTo.split('\\'));
var length = Math.min(lowerFromParts.length, lowerToParts.length);
var samePartsLength = length;
for(var i = 0; i < length; i++) {
if (lowerFromParts[i] !== lowerToParts[i]) {
samePartsLength = i;
break;
}
}
if (samePartsLength == 0) {
return to;
}
var outputParts = [];
for(var i = samePartsLength; i < lowerFromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('\\');
};
} else /* posix */ {
@ -232,6 +290,51 @@ if (isWindows) {
return p && typeof p === 'string';
}).join('/'));
};
// path.relative(from, to)
// posix version
exports.relative = function(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for(;start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for(;end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for(var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for(var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
}

36
test/simple/test-path.js

@ -147,3 +147,39 @@ resolveTests.forEach(function(test) {
// assert.equal(actual, expected, message);
});
assert.equal(failures.length, 0, failures.join(''));
// path.relative tests
if (isWindows) {
// windows
var relativeTests =
// arguments result
[['c:/blah\\blah', 'd:/games', 'd:\\games'],
['c:/aaaa/bbbb', 'c:/aaaa', '..'],
['c:/aaaa/bbbb', 'c:/cccc', '..\\..\\cccc'],
['c:/aaaa/bbbb', 'c:/aaaa/bbbb',''],
['c:/aaaa/bbbb', 'c:/aaaa/cccc','..\\cccc'],
['c:/aaaa/', 'c:/aaaa/cccc', 'cccc'],
['c:/', 'c:\\aaaa\\bbbb', 'aaaa\\bbbb'],
['c:/aaaa/bbbb', 'd:\\', 'd:\\']];
} else {
// posix
var relativeTests =
// arguments result
[['/var/lib', '/var', '..'],
['/var/lib', '/bin', '../../bin'],
['/var/lib', '/var/lib', ''],
['/var/lib', '/var/apache', '../apache'],
['/var/', '/var/lib', 'lib'],
['/', '/var/lib', 'var/lib']];
}
var failures = [];
relativeTests.forEach(function(test) {
var actual = path.relative(test[0], test[1]);
var expected = test[2];
var message = 'path.relative(' + test.slice(0, 2).map(JSON.stringify).join(',') + ')' +
'\n expect=' + JSON.stringify(expected) +
'\n actual=' + JSON.stringify(actual);
if (actual !== expected) failures.push('\n' + message);
});
assert.equal(failures.length, 0, failures.join(''));

Loading…
Cancel
Save