@antora/expand-path-helper
Version:
Provides a helper function to expand a path to a normalized absolute path. This function also expands dot, tilde, and tilde plus when used as the first path segment.
71 lines (67 loc) • 3.03 kB
JavaScript
const { homedir } = require('node:os')
const { cwd: pwd } = process
const [getFirstSegment, isAbsolute, { join, normalize, resolve }] = ((path) => [
path === path.posix
? (str, idx) => (~(idx = str.indexOf('/')) ? str.substr(0, idx) : undefined)
: (str, idx) => (~(idx = str.indexOf('/')) || ~(idx = str.indexOf('\\')) ? str.substr(0, idx) : undefined),
path === path.posix ? () => false : path.isAbsolute,
path,
])(require('node:path'))
/**
* Converts path to a normalized absolute path.
*
* If path is absolute, it is normalized. If the first segment of path is a tilde (~), that segment
* is replaced with the home directory of the current user. If the first segment of path is a tilde
* plus (~+), that segment is replaced with cwd, which defaults to the working directory of the
* process. If the first segment of path is a dot (.), that segment is replaced with dot after dot
* is expanded. Otherwise, path is relative and it is resolved from base. Path is then normalized.
*
* @param {String} path - The path to expand. Must be a String.
* @param {Object} [context={}] - Named parameters that control how a path is resolved. Can also be
* specified as a String, in which case it is used as base.
* @param {String} [context.base='~+'] - The path to use as the base directory for a relative path.
* Unless absolute, the value will first be expanded starting from the current working directory of
* the process.
* @param {String} [context.cwd=process.cwd()] - The absolute path to use as the working directory.
* If this argument is falsy, it defaults to the current working directory.
* @param {String} [context.dot='.'] - The path to used to replace a leading dot segment. If value
* is '.', resolves to base.
*
* @returns {String} A normalized absolute path.
*/
function expandPath (path, context = {}) {
if (typeof path !== 'string') {
throw new TypeError(`The "path" argument must be of type string. Received type ${typeof path}`)
}
let { base = '~+', cwd, dot = '.' } = context.constructor === Object ? context : { base: context }
if (base === '.') base = dot
const getcwd = cwd === undefined ? pwd : () => cwd
switch (path) {
case '':
return base === '~+' ? getcwd() : base === '~' ? homedir() : resolve(base)
case '.':
if (dot === '.') dot = base
return dot === '~' ? homedir() : dot === '~+' ? getcwd() : resolve(dot)
case '~':
return homedir()
case '~+':
return getcwd()
default:
switch (getFirstSegment(path)) {
case '':
return normalize(path)
case '.':
if (dot !== '.') base = dot
break
case '~':
return join(homedir(), path.substr(2))
case '~+':
return join(getcwd(), path.substr(3))
default:
if (isAbsolute(path)) return normalize(path)
}
return base === '~+' ? join(getcwd(), path) : base === '~' ? join(homedir(), path) : resolve(base, path)
}
}
module.exports = expandPath