-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Make the path of external sources relative
- Loading branch information
Showing
2 changed files
with
97 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Modified https://deno.land/std@0.114.0/path/posix.ts in order to use web browsers | ||
// | ||
const CHAR_FORWARD_SLASH = 47; | ||
|
||
/** | ||
* Return the relative path from `from` to `to` based on current working directory. | ||
* @param from path in current working directory | ||
* @param to path in current working directory | ||
*/ | ||
export function relative(from: string, to: string): string { | ||
if (from === to) return ""; | ||
|
||
// Trim any leading backslashes | ||
let fromStart = 1; | ||
const fromEnd = from.length; | ||
for (; fromStart < fromEnd; ++fromStart) { | ||
if (from.charCodeAt(fromStart) !== CHAR_FORWARD_SLASH) break; | ||
} | ||
const fromLen = fromEnd - fromStart; | ||
|
||
// Trim any leading backslashes | ||
let toStart = 1; | ||
const toEnd = to.length; | ||
for (; toStart < toEnd; ++toStart) { | ||
if (to.charCodeAt(toStart) !== CHAR_FORWARD_SLASH) break; | ||
} | ||
const toLen = toEnd - toStart; | ||
|
||
// Compare paths to find the longest common path from root | ||
const length = fromLen < toLen ? fromLen : toLen; | ||
let lastCommonSep = -1; | ||
let i = 0; | ||
for (; i <= length; ++i) { | ||
if (i === length) { | ||
if (toLen > length) { | ||
if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) { | ||
// We get here if `from` is the exact base path for `to`. | ||
// For example: from='/foo/bar'; to='/foo/bar/baz' | ||
return to.slice(toStart + i + 1); | ||
} else if (i === 0) { | ||
// We get here if `from` is the root | ||
// For example: from='/'; to='/foo' | ||
return to.slice(toStart + i); | ||
} | ||
} else if (fromLen > length) { | ||
if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) { | ||
// We get here if `to` is the exact base path for `from`. | ||
// For example: from='/foo/bar/baz'; to='/foo/bar' | ||
lastCommonSep = i; | ||
} else if (i === 0) { | ||
// We get here if `to` is the root. | ||
// For example: from='/foo'; to='/' | ||
lastCommonSep = 0; | ||
} | ||
} | ||
break; | ||
} | ||
const fromCode = from.charCodeAt(fromStart + i); | ||
const toCode = to.charCodeAt(toStart + i); | ||
if (fromCode !== toCode) break; | ||
else if (fromCode === CHAR_FORWARD_SLASH) lastCommonSep = i; | ||
} | ||
|
||
let out = ""; | ||
// Generate the relative path based on the path difference between `to` | ||
// and `from` | ||
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { | ||
if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) { | ||
if (out.length === 0) out += ".."; | ||
else out += "/.."; | ||
} | ||
} | ||
|
||
// Lastly, append the rest of the destination (`to`) path that comes after | ||
// the common path parts | ||
if (out.length > 0) return out + to.slice(toStart + lastCommonSep); | ||
else { | ||
toStart += lastCommonSep; | ||
if (to.charCodeAt(toStart) === CHAR_FORWARD_SLASH) ++toStart; | ||
return to.slice(toStart); | ||
} | ||
} |