UNPKG

@govbr-ds/webcomponents

Version:

Biblioteca de Web Components baseado no GovBR-DS

208 lines (207 loc) 8.63 kB
/*! * 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