@nxext/stencil
Version:
Nx plugin for stenciljs
149 lines • 6.25 kB
JavaScript
"use strict";
/**
* Originally from the StencilJS codebase (packages\stencil\src\utils\normalize-path.ts) copied, to create the same
* kind of path strings like the originally config
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizePath = void 0;
/**
* Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar
* Forward-slash paths can be used in Windows as long as they're not
* extended-length paths and don't contain any non-ascii characters.
* This was created since the path methods in Node.js outputs \\ paths on Windows.
*/
const normalizePath = (path) => {
if (typeof path !== 'string') {
throw new Error(`invalid path to normalize`);
}
path = normalizeSlashes(path.trim());
const components = pathComponents(path, getRootLength(path));
const reducedComponents = reducePathComponents(components);
const rootPart = reducedComponents[0];
const secondPart = reducedComponents[1];
const normalized = rootPart + reducedComponents.slice(1).join('/');
if (normalized === '') {
return '.';
}
if (rootPart === '' &&
secondPart &&
path.includes('/') &&
!secondPart.startsWith('.') &&
!secondPart.startsWith('@')) {
return './' + normalized;
}
return normalized;
};
exports.normalizePath = normalizePath;
const normalizeSlashes = (path) => path.replace(backslashRegExp, '/');
const altDirectorySeparator = '\\';
const urlSchemeSeparator = '://';
const backslashRegExp = /\\/g;
const reducePathComponents = (components) => {
if (!Array.isArray(components) || components.length === 0) {
return [];
}
const reduced = [components[0]];
for (let i = 1; i < components.length; i++) {
const component = components[i];
if (!component)
continue;
if (component === '.')
continue;
if (component === '..') {
if (reduced.length > 1) {
if (reduced[reduced.length - 1] !== '..') {
reduced.pop();
continue;
}
}
else if (reduced[0])
continue;
}
reduced.push(component);
}
return reduced;
};
const getRootLength = (path) => {
const rootLength = getEncodedRootLength(path);
return rootLength < 0 ? ~rootLength : rootLength;
};
const getEncodedRootLength = (path) => {
if (!path)
return 0;
const ch0 = path.charCodeAt(0);
// POSIX or UNC
if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
if (path.charCodeAt(1) !== ch0)
return 1; // POSIX: "/" (or non-normalized "\")
const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? '/' : altDirectorySeparator, 2);
if (p1 < 0)
return path.length; // UNC: "//server" or "\\server"
return p1 + 1; // UNC: "//server/" or "\\server\"
}
// DOS
if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* CharacterCodes.colon */) {
const ch2 = path.charCodeAt(2);
if (ch2 === 47 /* CharacterCodes.slash */ || ch2 === 92 /* CharacterCodes.backslash */)
return 3; // DOS: "c:/" or "c:\"
if (path.length === 2)
return 2; // DOS: "c:" (but not "c:d")
}
// URL
const schemeEnd = path.indexOf(urlSchemeSeparator);
if (schemeEnd !== -1) {
const authorityStart = schemeEnd + urlSchemeSeparator.length;
const authorityEnd = path.indexOf('/', authorityStart);
if (authorityEnd !== -1) {
// URL: "file:///", "file://server/", "file://server/path"
// For local "file" URLs, include the leading DOS volume (if present).
// Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a
// special case interpreted as "the machine from which the URL is being interpreted".
const scheme = path.slice(0, schemeEnd);
const authority = path.slice(authorityStart, authorityEnd);
if (scheme === 'file' &&
(authority === '' || authority === 'localhost') &&
isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) {
const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2);
if (volumeSeparatorEnd !== -1) {
if (path.charCodeAt(volumeSeparatorEnd) === 47 /* CharacterCodes.slash */) {
// URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/"
return ~(volumeSeparatorEnd + 1);
}
if (volumeSeparatorEnd === path.length) {
// URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a"
// but not "file:///c:d" or "file:///c%3ad"
return ~volumeSeparatorEnd;
}
}
}
return ~(authorityEnd + 1); // URL: "file://server/", "http://server/"
}
return ~path.length; // URL: "file://server", "http://server"
}
// relative
return 0;
};
const isVolumeCharacter = (charCode) => (charCode >= 97 /* CharacterCodes.a */ && charCode <= 122 /* CharacterCodes.z */) ||
(charCode >= 65 /* CharacterCodes.A */ && charCode <= 90 /* CharacterCodes.Z */);
const getFileUrlVolumeSeparatorEnd = (url, start) => {
const ch0 = url.charCodeAt(start);
if (ch0 === 58 /* CharacterCodes.colon */)
return start + 1;
if (ch0 === 37 /* CharacterCodes.percent */ &&
url.charCodeAt(start + 1) === 51 /* CharacterCodes._3 */) {
const ch2 = url.charCodeAt(start + 2);
if (ch2 === 97 /* CharacterCodes.a */ || ch2 === 65 /* CharacterCodes.A */)
return start + 3;
}
return -1;
};
const pathComponents = (path, rootLength) => {
const root = path.substring(0, rootLength);
const rest = path.substring(rootLength).split('/');
const restLen = rest.length;
if (restLen > 0 && !rest[restLen - 1]) {
rest.pop();
}
return [root, ...rest];
};
//# sourceMappingURL=normalize-path.js.map