You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

81 lines
2.7 KiB

module.exports = relativize
// return the shortest path between two folders.
// if the original path is shorter, then use that,
// unless forceRelative is set to true.
var path = require("path")
function relativize (dest, src, forceRelative) {
var orig = dest
if (!isAbsolute(src)) forceRelative = true
else if (!isAbsolute(dest)) return false
src = path.resolve(src)
dest = path.resolve(dest)
if (src === dest) return "."
src = src.split(split)
dest = dest.split(split)
var i = 0
while (src[i] === dest[i]) i++
if (!forceRelative && i === 1) return orig // nothing in common
src.splice(0, i + 1)
var dots = [0, i, "."]
for (var i = 0, l = src.length; i < l; i ++) dots.push("..")
dest.splice.apply(dest, dots)
if (dest[0] === "." && dest[1] === "..") dest.shift()
dest = dest.join("/")
return !forceRelative && orig.length < dest.length ? orig : dest
}
var split = process.platform === "win32" ? /[\/\\]/ : "/"
function isAbsolute (p) {
if (process.platform !== "win32") return p.charAt(0) === "/"
// yanked from node/lib/path.js
var splitDeviceRe =
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/
var result = p.match(splitDeviceRe)
, device = result[1] || ""
, isUnc = device && device.charAt(1) !== ":"
, isAbs = !!result[2] || isUnc // UNC always absolute
return isAbs
}
if (module === require.main) {
// from, to, result, relativeForced
var assert = require("assert")
; [ ["/bar" ,"/foo" ,"/bar" ,"./bar" ]
, ["/foo/baz" ,"/foo/bar/baz" ,"../baz" ,"../baz" ]
, ["/a/d" ,"/a/b/c/d/e/f" ,"/a/d" ,"../../../../d" ]
// trailing slashes are ignored.
, ["/a/d" ,"/a/b/c/d/e/" ,"/a/d" ,"../../../d" ]
, ["./foo/bar" ,"./foo/baz" ,"./bar" ,"./bar" ]
// force relative when the src is relative.
, ["./d" ,"./a/b/c/d/e" ,"../../../../d" ,"../../../../d" ]
// if src is abs and dest is relative, then fail
, ["./d" ,"/a/b" ,false ,false ]
].forEach(function (test) {
var d = test[0]
, s = test[1]
, r = test[2]
, rr = test[3]
, ra = relativize(d, s)
, rra = relativize(d, s, true)
console.log([d, s, r, rr], [ra, rra], [r === ra, rr === rra])
assert.equal(r, ra)
assert.equal(rr, rra)
if (!r) return
// contract: this is the relative path from absolute A to absolute B
var ad = path.resolve(d)
, as = path.resolve(s)
, dir = path.dirname(as)
assert.equal(path.resolve(dir, rr), ad)
assert.equal(path.resolve(dir, r), ad)
})
console.log("ok")
}