mirror of https://github.com/lukechilds/node.git
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
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")
|
|
}
|
|
|