@govbr-ds/webcomponents
Version:
Biblioteca de Web Components baseado no GovBR-DS
208 lines (207 loc) • 8.63 kB
JavaScript
/*!
* Construído por SERPRO
* © https://serpro.gov.br/ - MIT License.
*/
import path from "path";
/**
* Converte caminhos com barras invertidas do Windows para caminhos com barras normais: foo\\bar ➔ foo/bar
* Caminhos com barras normais podem ser usados no Windows, desde que não sejam
* caminhos de comprimento estendido e não contenham caracteres não ASCII.
* Isso foi criado porque os métodos de caminho no Node.js geram caminhos com \\ no Windows.
* @param path o caminho baseado em Windows a ser convertido
* @param relativize se um caminho relativo deve ou não ter `./` adicionado
* @returns o caminho convertido
*/
export const normalizePath = (path, relativize = true) => {
if (typeof path !== 'string') {
throw new Error(`caminho inválido para normalizar`);
}
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('@') &&
relativize) {
return './' + normalized;
}
return normalized;
};
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 || component === '.') {
continue;
}
if (component === '..') {
if (reduced.length > 1 && reduced[reduced.length - 1] !== '..') {
reduced.pop();
continue;
}
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);
const posixOrUNCResult = checkPosixOrUNC(path, ch0);
if (posixOrUNCResult !== undefined) {
return posixOrUNCResult;
}
const dosResult = checkDOS(path, ch0);
if (dosResult !== undefined) {
return dosResult;
}
const urlResult = checkURL(path);
if (urlResult !== undefined) {
return urlResult;
}
// relativo
return 0;
};
function checkPosixOrUNC(path, ch0) {
// POSIX ou UNC
if (ch0 === 47 /* CharacterCodes.slash */ || ch0 === 92 /* CharacterCodes.backslash */) {
if (path.charCodeAt(1) !== ch0)
return 1; // POSIX: "/" (ou não normalizado "\")
const p1 = path.indexOf(ch0 === 47 /* CharacterCodes.slash */ ? '/' : altDirectorySeparator, 2);
if (p1 < 0)
return path.length; // UNC: "//servidor" ou "\\servidor"
return p1 + 1; // UNC: "//servidor/" ou "\\servidor\"
}
return undefined;
}
function checkDOS(path, ch0) {
// 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:/" ou "c:\"
if (path.length === 2)
return 2; // DOS: "c:" (mas não "c:d")
}
return undefined;
}
function checkURL(path) {
// URL
const schemeEnd = path.indexOf(urlSchemeSeparator);
if (schemeEnd === -1)
return undefined;
const authorityStart = schemeEnd + urlSchemeSeparator.length;
const authorityEnd = path.indexOf('/', authorityStart);
if (authorityEnd !== -1) {
// URL: "file:///", "file://servidor/", "file://servidor/caminho"
// Para URLs "file" locais, incluir o volume do DOS à frente (se presente).
// De acordo com https://www.ietf.org/rfc/rfc1738.txt, um host de "" ou "localhost" é um
// caso especial interpretado como "a máquina a partir da qual a URL está sendo interpretada".
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"
// mas não "file:///c:d" ou "file:///c%3ad"
return ~volumeSeparatorEnd;
}
}
}
return ~(authorityEnd + 1); // URL: "file://servidor/", "http://servidor/"
}
return ~path.length; // URL: "file://servidor", "http://servidor"
}
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];
};
/**
* Igual a normalizePath(), exceto que também removerá quaisquer strings de consulta
* do nome do caminho. Assim, /dir/file.css?tag=cmp-a se torna /dir/file.css
* @param p o caminho a ser normalizado
* @returns o caminho normalizado, sem quaisquer strings de consulta
*/
export const normalizeFsPath = (p) => normalizePath(p.split('?')[0].replace(/\0/g, ''));
export const normalizeFsPathQuery = (importPath) => {
var _a;
const pathParts = importPath.split('?');
const filePath = normalizePath(pathParts[0]);
const filePathParts = filePath.split('.');
const ext = filePathParts.length > 1 ? (_a = filePathParts.pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase() : null;
const params = pathParts.length > 1 ? new URLSearchParams(pathParts[1]) : null;
const format = params !== null ? params.get('format') : null;
return {
filePath,
ext,
format,
};
};
/**
* Uma versão embrulhada da função {@link path.relative} do node.js que adiciona nossa lógica de
* normalização personalizada. Isso resolve o caminho relativo entre `from` e `to`!
*
* O cálculo do caminho retornado segue a lógica do Node, com uma exceção - se o caminho calculado
* resultar em uma string vazia, uma string de comprimento um com um ponto (`'.'`) é retornada.
*
* @throws a função subjacente do node.js pode lançar uma exceção se qualquer caminho não for um
* string
* @param from o caminho onde a resolução relativa começa
* @param to o caminho de destino
* @returns o caminho relativo resolvido
*/
export function relative(from, to) {
/**
* Ao normalizar, não devemos _tentar_ relativizar o caminho retornado pelo método nativo `relative` do Node.
* Ao encontrar os caminhos, qualquer caminho que possa acabar em uma string vazia deve ser retornado como '.'
*/
return normalizePath(path.relative(from, to));
}
//# sourceMappingURL=path.js.map