如何将绝对网址转换为相对网址?
相对绝对转换很简单
const rel = "../images/doggy.jpg"
const base = "https://example.com/pages/page.html?foo=bar#baz";
function relToAbs(baseHref, relHref) {
const url = new URL(rel, base);
return `${url.origin}${url.pathname}`;
}
console.log(base, rel);
朝相反的方向似乎需要一堆代码。
这就是我尝试过的。
const pageURL1 = 'https://example.com/bar/baz.html?bla=blap#hash';
const pageURL2 = 'https://example.com/bar/?bla=blap#hash';
const absURL1 = 'https://example.com/bar/image/doggy.jpg';
const absURL2 = 'https://example.com/image/kitty.jpg';
const absURL3 = 'https://example.com/bar/birdy.jpg';
const tests = [
{ pageHref: pageURL1, absHref: absURL1, expected: 'image/doggy.jpg', },
{ pageHref: pageURL1, absHref: absURL2, expected: '../image/kitty.jpg', },
{ pageHref: pageURL1, absHref: absURL3, expected: 'birdy.jpg', },
{ pageHref: pageURL2, absHref: absURL1, expected: 'image/doggy.jpg', },
{ pageHref: pageURL2, absHref: absURL2, expected: '../image/kitty.jpg', },
{ pageHref: pageURL2, absHref: absURL3, expected: 'birdy.jpg', },
];
for (const {pageHref, absHref, expected} of tests) {
const actual = absToRel(pageHref, absHref);
console.log(absHref, actual, actual === expected ? 'pass' : 'FAIL');
}
function absToRel(pageHref, absHref) {
const pagePaths = dirPaths(pageHref).slice(0, -1);
const absPaths = dirPaths(absHref);
if (pagePaths[0] !== absPaths[0]) {
return absHref; // not same domain
}
// remove same paths
const firstDiffNdx = firstNonMatchingNdx(pagePaths, absPaths);
pagePaths.splice(0, firstDiffNdx);
absPaths.splice(0, firstDiffNdx);
// for each path still on page add a ..
return [
...(new Array(pagePaths.length).fill('..')),
...absPaths,
].join('/');
}
function firstNonMatchingNdx(a, b) {
let ndx = 0;
while (ndx < a.length && a[ndx] === b[ndx]) {
++ndx;
}
return ndx;
}
function dirPaths(href) {
const url = new URL(href);
return [url.origin, ...url.pathname.split('/')];
}
答案 0 :(得分:0)
您可以使用内置的URL类来帮助解析URL。这样,您的代码就可以只关注单个路径元素,而忽略搜索参数,域,模式等...
这就是我想出的。
我不保证这是完美的或万无一失的,但希望它能使您接近所寻找的东西。
function pathParts(path) {
let parts = path.split('/');
let start = 0;
let end = parts.length;
// Remove initial blank part from root /
if( !parts[0] ) {
start = 1;
}
// Remove trailing / part
if( !parts[parts.length - 1] ) {
end -= 1;
}
return parts.slice(start, end);
}
function absToRel(pageHref, absHref) {
var pageUrl = new URL(pageHref);
var absUrl = new URL(absHref);
// If the urls have different schemas or domain, relative is not possible
if( pageUrl.origin !== absUrl.origin ) {
return absHref;
}
var pagePath = pathParts(pageUrl.pathname)
var absPath = pathParts(absUrl.pathname)
// Remove common root paths
while( absPath.length && pagePath[0] === absPath[0] ) {
absPath.shift();
pagePath.shift();
}
// For each path segment left on pagePath, we'll need a relative ..
pagePath.fill('..');
let relPath = [
...pagePath,
...absPath
].join('/');
// If the paths do not require traversal up, use current directory relative path
if( relPath[0] !== '.' ) {
relPath = './' + relPath;
}
return relPath;
}