Skip to content

Instantly share code, notes, and snippets.

@icholy
Created September 5, 2018 16:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save icholy/79d0da9ce2cf19e05bbfb4c872ff04ca to your computer and use it in GitHub Desktop.
Save icholy/79d0da9ce2cf19e05bbfb4c872ff04ca to your computer and use it in GitHub Desktop.
/**
* Same as joinPath, but preserves http(s):// schemes
*
* @param segments Url segments to join
* @return Joined url
*/
function joinUrl(...segments: string[]): string {
if (segments.length === 0) {
return "";
}
let first = segments[0],
rest = segments.slice(1),
schemes = /^(http|https):\/\//,
match = schemes.exec(first),
prefix = match ? match[0] : "";
first = first.slice(prefix.length);
return prefix + joinPath(first, ...rest);
}
/**
* Joins path segments. Preserves initial "/" and resolves ".." and "."
* Does not support using ".." to go above/outside the root.
* This means that join("foo", "../../bar") will not resolve to "../bar"
*
* @param segments Path segments to join
* @return Joined path
*/
function joinPath(...segments: string[]): string {
let parts: string[] = [];
for (let segment of segments) {
parts = parts.concat(segment.toString().split("/"));
}
let newParts: string[] = [];
for (let part of parts) {
if (!part || part === ".") {
continue;
}
if (part === "..") {
newParts.pop();
} else {
newParts.push(part);
}
}
// Preserve the initial slash if there was one.
if (parts[0] === "") newParts.unshift("");
// Turn back into a single string path.
return newParts.join("/") || (newParts.length ? "/" : ".");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment