123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /*
- 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;
|