UNPKG

pretty-parallel

Version:
175 lines 6.4 kB
"use strict"; /** * This file has been copied from https://github.com/prettier/prettier/blob/2bbbe1a8d17961101d076ac530309fd2c6b06cbe/src/cli/expand-patterns.js * and has been adapted to typescript */ Object.defineProperty(exports, "__esModule", { value: true }); exports.fixWindowsSlashes = exports.expandPatterns = void 0; const tslib_1 = require("tslib"); const promises_1 = tslib_1.__importDefault(require("node:fs/promises")); const node_path_1 = tslib_1.__importDefault(require("node:path")); const fast_glob_1 = tslib_1.__importDefault(require("fast-glob")); async function statSafe(filePath) { try { return await promises_1.default.stat(filePath); } catch (error) { /* istanbul ignore next */ if (error.code !== 'ENOENT') { throw error; } return null; } } async function* expandPatterns(context) { const cwd = process.cwd(); const seen = new Set(); for await (const pathOrError of expandPatternsInternal(context)) { if (typeof pathOrError !== 'string') { yield pathOrError; continue; } const relativePath = node_path_1.default.relative(cwd, pathOrError); // filter out duplicates if (seen.has(relativePath)) { continue; } seen.add(relativePath); yield relativePath; } } exports.expandPatterns = expandPatterns; async function* expandPatternsInternal(context) { // Ignores files in version control systems directories and `node_modules` const silentlyIgnoredDirs = ['.git', '.svn', '.hg', 'node_modules']; const globOptions = { dot: true, ignore: silentlyIgnoredDirs.map((dir) => '**/' + dir), }; let supportedFilesGlob; const cwd = process.cwd(); const entries = []; for (const pattern of context.filePatterns) { const stringPattern = pattern.toString(); const absolutePath = node_path_1.default.resolve(cwd, stringPattern); if (containsIgnoredPathSegment(absolutePath, cwd, silentlyIgnoredDirs)) { continue; } const stat = await statSafe(absolutePath); if (stat) { if (stat.isFile()) { entries.push({ type: 'file', glob: escapePathForGlob(fixWindowsSlashes(stringPattern)), input: stringPattern, }); } else if (stat.isDirectory()) { /* 1. Remove trailing `/`, `fast-glob` can't find files for `src//*.js` pattern 2. Cleanup dirname, when glob `src/../*.js` pattern with `fast-glob`, it returns files like 'src/../index.js' */ const relativePath = node_path_1.default.relative(cwd, absolutePath) || '.'; entries.push({ type: 'dir', glob: escapePathForGlob(fixWindowsSlashes(relativePath)) + '/' + getSupportedFilesGlob(), input: stringPattern, }); } } else if (stringPattern[0] === '!') { // convert negative patterns to `ignore` entries globOptions.ignore.push(fixWindowsSlashes(stringPattern.slice(1))); } else { entries.push({ type: 'glob', glob: fixWindowsSlashes(stringPattern), input: stringPattern, }); } } for (const { type, glob, input } of entries) { let result; try { result = await (0, fast_glob_1.default)(glob, globOptions); } catch (err) { /* istanbul ignore next */ yield { error: `${errorMessages.globError[type]}: ${input}\n${err.message}`, }; /* istanbul ignore next */ continue; } if (result.length > 0) { yield* sortPaths(result); } } function getSupportedFilesGlob() { if (!supportedFilesGlob) { const extensions = context.languages.flatMap((lang) => lang.extensions || []); const filenames = context.languages.flatMap((lang) => lang.filenames || []); supportedFilesGlob = `**/{${[ ...extensions.map((ext) => '*' + (ext[0] === '.' ? ext : '.' + ext)), ...filenames, ]}}`; } return supportedFilesGlob; } } const errorMessages = { globError: { file: 'Unable to resolve file', dir: 'Unable to expand directory', glob: 'Unable to expand glob pattern', }, emptyResults: { file: 'Explicitly specified file was ignored due to negative glob patterns', dir: 'No supported files were found in the directory', glob: 'No files matching the pattern were found', }, }; /** * @param {string} absolutePath * @param {string} cwd * @param {string[]} ignoredDirectories */ function containsIgnoredPathSegment(absolutePath, cwd, ignoredDirectories) { return node_path_1.default .relative(cwd, absolutePath) .split(node_path_1.default.sep) .some((dir) => ignoredDirectories.includes(dir)); } /** * @param {string[]} paths */ function sortPaths(paths) { return paths.sort((a, b) => a.localeCompare(b)); } /** * This function should be replaced with `fastGlob.escapePath` when these issues are fixed: * - https://github.com/mrmlnc/fast-glob/issues/261 * - https://github.com/mrmlnc/fast-glob/issues/262 * @param {string} path */ function escapePathForGlob(path) { return fast_glob_1.default .escapePath(path.replace(/\\/g, '\0')) .replace(/\\!/g, '@(!)') // Workaround for fast-glob#261 .replace(/\0/g, '@(\\\\)'); // Workaround for fast-glob#262 (part 2) } const isWindows = node_path_1.default.sep === '\\'; /** * Using backslashes in globs is probably not okay, but not accepting * backslashes as path separators on Windows is even more not okay. * https://github.com/prettier/prettier/pull/6776#discussion_r380723717 * https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows * @param {string} pattern */ function fixWindowsSlashes(pattern) { return isWindows ? pattern.replace(/\\/g, '/') : pattern; } exports.fixWindowsSlashes = fixWindowsSlashes; //# sourceMappingURL=expand-patterns.js.map