You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/* MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra */
"use strict";
const path = require("path");
const CHAR_HASH = "#".charCodeAt(0); const CHAR_SLASH = "/".charCodeAt(0); const CHAR_BACKSLASH = "\\".charCodeAt(0); const CHAR_A = "A".charCodeAt(0); const CHAR_Z = "Z".charCodeAt(0); const CHAR_LOWER_A = "a".charCodeAt(0); const CHAR_LOWER_Z = "z".charCodeAt(0); const CHAR_DOT = ".".charCodeAt(0); const CHAR_COLON = ":".charCodeAt(0);
const posixNormalize = path.posix.normalize; const winNormalize = path.win32.normalize;
/** * @enum {number} */ const PathType = Object.freeze({ Empty: 0, Normal: 1, Relative: 2, AbsoluteWin: 3, AbsolutePosix: 4, Internal: 5 }); exports.PathType = PathType;
const invalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))?(\\|\/|$)/i; exports.invalidSegmentRegEx = invalidSegmentRegEx;
const deprecatedInvalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i; exports.deprecatedInvalidSegmentRegEx = deprecatedInvalidSegmentRegEx;
/** * @param {string} p a path * @returns {PathType} type of path */ const getType = p => { switch (p.length) { case 0: return PathType.Empty; case 1: { const c0 = p.charCodeAt(0); switch (c0) { case CHAR_DOT: return PathType.Relative; case CHAR_SLASH: return PathType.AbsolutePosix; case CHAR_HASH: return PathType.Internal; } return PathType.Normal; } case 2: { const c0 = p.charCodeAt(0); switch (c0) { case CHAR_DOT: { const c1 = p.charCodeAt(1); switch (c1) { case CHAR_DOT: case CHAR_SLASH: return PathType.Relative; } return PathType.Normal; } case CHAR_SLASH: return PathType.AbsolutePosix; case CHAR_HASH: return PathType.Internal; } const c1 = p.charCodeAt(1); if (c1 === CHAR_COLON) { if ( (c0 >= CHAR_A && c0 <= CHAR_Z) || (c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z) ) { return PathType.AbsoluteWin; } } return PathType.Normal; } } const c0 = p.charCodeAt(0); switch (c0) { case CHAR_DOT: { const c1 = p.charCodeAt(1); switch (c1) { case CHAR_SLASH: return PathType.Relative; case CHAR_DOT: { const c2 = p.charCodeAt(2); if (c2 === CHAR_SLASH) return PathType.Relative; return PathType.Normal; } } return PathType.Normal; } case CHAR_SLASH: return PathType.AbsolutePosix; case CHAR_HASH: return PathType.Internal; } const c1 = p.charCodeAt(1); if (c1 === CHAR_COLON) { const c2 = p.charCodeAt(2); if ( (c2 === CHAR_BACKSLASH || c2 === CHAR_SLASH) && ((c0 >= CHAR_A && c0 <= CHAR_Z) || (c0 >= CHAR_LOWER_A && c0 <= CHAR_LOWER_Z)) ) { return PathType.AbsoluteWin; } } return PathType.Normal; }; exports.getType = getType;
/** * @param {string} p a path * @returns {string} the normalized path */ const normalize = p => { switch (getType(p)) { case PathType.Empty: return p; case PathType.AbsoluteWin: return winNormalize(p); case PathType.Relative: { const r = posixNormalize(p); return getType(r) === PathType.Relative ? r : `./${r}`; } } return posixNormalize(p); }; exports.normalize = normalize;
/** * @param {string} rootPath the root path * @param {string | undefined} request the request path * @returns {string} the joined path */ const join = (rootPath, request) => { if (!request) return normalize(rootPath); const requestType = getType(request); switch (requestType) { case PathType.AbsolutePosix: return posixNormalize(request); case PathType.AbsoluteWin: return winNormalize(request); } switch (getType(rootPath)) { case PathType.Normal: case PathType.Relative: case PathType.AbsolutePosix: return posixNormalize(`${rootPath}/${request}`); case PathType.AbsoluteWin: return winNormalize(`${rootPath}\\${request}`); } switch (requestType) { case PathType.Empty: return rootPath; case PathType.Relative: { const r = posixNormalize(rootPath); return getType(r) === PathType.Relative ? r : `./${r}`; } } return posixNormalize(rootPath); }; exports.join = join;
/** @type {Map<string, Map<string, string | undefined>>} */ const joinCache = new Map();
/** * @param {string} rootPath the root path * @param {string} request the request path * @returns {string} the joined path */ const cachedJoin = (rootPath, request) => { /** @type {string | undefined} */ let cacheEntry; let cache = joinCache.get(rootPath); if (cache === undefined) { joinCache.set(rootPath, (cache = new Map())); } else { cacheEntry = cache.get(request); if (cacheEntry !== undefined) return cacheEntry; } cacheEntry = join(rootPath, request); cache.set(request, cacheEntry); return cacheEntry; }; exports.cachedJoin = cachedJoin;
|