* Given two URLs that are assumed to be on the same * protocol/host/user/password build a relative URL from the * path, params, and hash values. * * @param rootURL The root URL that the target will be relative to. * @param targetURL The target that the relative URL points to. * @return A rootU
(rootURL, targetURL)
| 2617 | * @return A rootURL-relative, normalized URL value. |
| 2618 | */ |
| 2619 | function computeRelativeURL(rootURL, targetURL) { |
| 2620 | if (typeof rootURL === "string") rootURL = new URL(rootURL); |
| 2621 | if (typeof targetURL === "string") targetURL = new URL(targetURL); |
| 2622 | |
| 2623 | const targetParts = targetURL.pathname.split("/"); |
| 2624 | const rootParts = rootURL.pathname.split("/"); |
| 2625 | |
| 2626 | // If we've got a URL path ending with a "/", we remove it since we'd |
| 2627 | // otherwise be relative to the wrong location. |
| 2628 | if (rootParts.length > 0 && !rootParts[rootParts.length - 1]) { |
| 2629 | rootParts.pop(); |
| 2630 | } |
| 2631 | |
| 2632 | while ( |
| 2633 | targetParts.length > 0 && |
| 2634 | rootParts.length > 0 && |
| 2635 | targetParts[0] === rootParts[0] |
| 2636 | ) { |
| 2637 | targetParts.shift(); |
| 2638 | rootParts.shift(); |
| 2639 | } |
| 2640 | |
| 2641 | const relativePath = rootParts |
| 2642 | .map(() => "..") |
| 2643 | .concat(targetParts) |
| 2644 | .join("/"); |
| 2645 | |
| 2646 | return relativePath + targetURL.search + targetURL.hash; |
| 2647 | } |
| 2648 | |
| 2649 | /** |
| 2650 | * Given a URL, ensure that it is treated as a directory URL. |