UNPKG

@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
'use strict' 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