cspell
Version:
A Spelling Checker for Code!
183 lines • 6.91 kB
JavaScript
import { promises as fsp } from 'node:fs';
import * as path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { toFileDirURL, toFilePathOrHref, toFileURL } from '@cspell/url';
import { readFileText as cioReadFile, toURL } from 'cspell-io';
import * as cspell from 'cspell-lib';
import { fileToDocument, isBinaryFile as isUriBinaryFile } from 'cspell-lib';
import getStdin from 'get-stdin';
import { asyncAwait, asyncFlatten, asyncMap, asyncPipe, mergeAsyncIterables } from './async.js';
import { FileUrlPrefix, STDIN, STDINProtocol, STDINUrlPrefix, UTF8 } from './constants.js';
import { IOError, toApplicationError, toError } from './errors.js';
import { globP } from './glob.js';
import { readStdin } from './stdin.js';
import { isStdinUrl, resolveStdinUrl } from './stdinUrl.js';
import { clean } from './util.js';
export async function readConfig(configFile, root) {
if (configFile) {
const cfgFile = typeof configFile === 'string' ? await readConfigHandleError(configFile) : configFile;
const config = await cspell.resolveConfigFileImports(cfgFile);
const source = toFilePathOrHref(cfgFile.url);
return { source, config };
}
const config = await cspell.searchForConfig(root);
return { source: config?.__importRef?.filename || 'None found', config: config || {} };
}
export function readConfigFile(filename) {
return cspell.readConfigFile(filename);
}
async function readConfigHandleError(filename) {
try {
return await readConfigFile(filename);
}
catch (e) {
const settings = {
__importRef: {
filename: filename.toString(),
error: e,
},
};
return { url: filenameToUrl(filename), settings };
}
}
export function fileInfoToDocument(fileInfo, languageId, locale) {
const { filename, text } = fileInfo;
languageId = languageId || undefined;
locale = locale || undefined;
const uri = filenameToUrl(filename);
if (uri.href.startsWith(STDINProtocol)) {
return clean({
uri: uri.href,
text,
languageId,
locale,
});
}
return fileToDocument(uri.href, text, languageId, locale);
}
export function filenameToUrl(filename, cwd = '.') {
if (filename instanceof URL)
return filename;
const cwdURL = toFileDirURL(cwd);
if (filename === STDIN)
return new URL('stdin:///');
if (isStdinUrl(filename)) {
return new URL(resolveStdinUrl(filename, cwd));
}
return toFileURL(filename, cwdURL);
}
export function filenameToUri(filename, cwd) {
return toURL(filenameToUrl(filename, cwd));
}
export function isBinaryFile(filename, cwd) {
const uri = filenameToUri(filename, cwd);
if (uri.protocol.startsWith('stdin'))
return false;
return isUriBinaryFile(uri);
}
export function resolveFilename(filename, cwd) {
cwd = cwd || process.cwd();
if (filename === STDIN)
return STDINUrlPrefix;
if (filename.startsWith(FileUrlPrefix)) {
const url = new URL(filename.slice(FileUrlPrefix.length), pathToFileURL(cwd + path.sep));
return fileURLToPath(url);
}
if (isStdinUrl(filename)) {
return resolveStdinUrl(filename, cwd);
}
return path.resolve(cwd, filename);
}
export function readFileInfo(filename, encoding = UTF8, handleNotFound = false) {
filename = resolveFilename(filename);
const pText = filename.startsWith(STDINProtocol) ? getStdin() : cioReadFile(filename, encoding);
return pText.then((text) => ({ text, filename }), (e) => {
const error = toError(e);
return handleNotFound && error.code === 'EISDIR'
? Promise.resolve({ text: '', filename, errorCode: error.code })
: handleNotFound && error.code === 'ENOENT'
? Promise.resolve({ text: '', filename, errorCode: error.code })
: Promise.reject(new IOError(`Error reading file: "${filename}"`, error));
});
}
export function readFile(filename, encoding = UTF8) {
return readFileInfo(filename, encoding).then((info) => info.text);
}
/**
* Looks for matching glob patterns or stdin
* @param globPatterns patterns or stdin
*/
export async function findFiles(globPatterns, options) {
const stdin = [];
const globPats = globPatterns.filter((filename) => !isStdin(filename) && !filename.startsWith(FileUrlPrefix) ? true : (stdin.push(filename), false));
const globResults = globPats.length ? await globP(globPats, options) : [];
const cwd = options.cwd || process.cwd();
return [...stdin, ...globResults].map((filename) => resolveFilename(filename, cwd));
}
const resolveFilenames = asyncMap(resolveFilename);
/**
* Read
* @param listFiles - array of file paths to read that will contain a list of files. Paths contained in each
* file will be resolved relative to the containing file.
* @returns - a list of files to be processed.
*/
export function readFileListFiles(listFiles) {
let useStdin = false;
const files = listFiles.filter((file) => {
const isStdin = file === 'stdin';
useStdin = useStdin || isStdin;
return !isStdin;
});
const found = asyncPipe(files, asyncMap((file) => readFileListFile(file)), asyncAwait(), asyncFlatten());
// Move `stdin` to the end.
const stdin = useStdin ? readStdin() : [];
return asyncPipe(mergeAsyncIterables(found, stdin), resolveFilenames);
}
/**
* Read a `listFile` and return the containing file paths resolved relative to the `listFile`.
* @param listFiles - array of file paths to read that will contain a list of files. Paths contained in each
* file will be resolved relative to the containing file.
* @returns - a list of files to be processed.
*/
export async function readFileListFile(listFile) {
try {
const relTo = path.resolve(path.dirname(listFile));
const content = await readFile(listFile);
const lines = content
.split('\n')
.map((a) => a.trim())
.filter((a) => !!a)
.map((file) => path.resolve(relTo, file));
return lines;
}
catch (err) {
throw toApplicationError(err, `Error reading file list from: "${listFile}"`);
}
}
function isStdin(filename) {
return filename === STDIN || isStdinUrl(filename);
}
export async function isFile(filename) {
if (isStdin(filename))
return true;
try {
const stat = await fsp.stat(filename);
return stat.isFile();
}
catch {
return false;
}
}
export async function isDir(filename) {
try {
const stat = await fsp.stat(filename);
return stat.isDirectory();
}
catch {
return false;
}
}
export function isNotDir(filename) {
return isDir(filename).then((a) => !a);
}
//# sourceMappingURL=fileHelper.js.map