There's an npm module called relateurl
that works well but its dependency on url
(note lower-case) causes mild trouble in the latest Webpack and React. I published another called relativize-url
that uses URL
(shouty-caps), which is supported everywhere. It's pretty minimal so you can install it or just steal the code from index.js.
const components = [
{name: 'protocol', write: u => u.protocol },
{name: 'hostname', write: u => '//' + u.hostname },
{name: 'port', write: u => u.port === '' ? '' : (':' + u.port) },
{name: 'pathname', write: (u, frm, relativize) => {
if (!relativize) return u.pathname;
const f = frm.pathname.split('/').slice(1);
const t = u.pathname.split('/').slice(1);
const maxDepth = Math.max(f.length, t.length);
let start = 0;
while(start < maxDepth && f[start] === t[start]) ++start;
const rel = f.slice(start+1).map(c => '..')
.concat(t.slice(start)).join('/');
return rel.length <= u.pathname.length ? rel : u.pathname
}},
{name: 'search', write: u => u.search },
{name: 'hash', write: u => u.hash},
];
function relativize (rel, base, opts = {}) { // opts not yet used
const from = new URL(base);
const to = new URL(rel, from);
let ret = '';
for (let component of components) {
if (ret) { // force abs path if e.g. host was diffferent
ret += component.write(to, from, false);
} else if (from[component.name] !== to[component.name]) {
ret = component.write(to, from, true);
}
}
return ret;
}
The pathname
handler has extra code in it to give you nice minimal relative paths. Give it some exercise:
const base = 'http://a.example/b/e/f?g=h#i'
const target = 'http://a.example/b/c/d?j=k#l'
console.log(relativize(target, base))
// got '../c/d'; let's check it:
console.log(new URL('../c/d', base).href === target)
// true
console.log(relativize('http://a.example/b?a=b','http://a.example/b?c=d'))
// ?a=b
console.log(relativize('http://a.example/b#asdf', 'http://a.example/b'))
// #asdf
console.log(relativize('http://a.example/b', 'http://c.example/d'))
// //a.example/b
Please report bugs in https://github.com/ericprud/relativize-url/issues .