cspell
Version:
A Spelling Checker for Code!
161 lines • 6.32 kB
JavaScript
import { readFileText as cioReadFile } from 'cspell-io';
import * as cspell from 'cspell-lib';
import { fileToDocument, isBinaryFile as isUriBinaryFile } from 'cspell-lib';
import { promises as fsp } from 'fs';
import getStdin from 'get-stdin';
import * as path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
import { URI } from 'vscode-uri';
import { asyncAwait, asyncFlatten, asyncMap, asyncPipe, mergeAsyncIterables } from './async.mjs';
import { FileProtocol, STDIN, STDINProtocol, UTF8 } from './constants.mjs';
import { IOError, toApplicationError, toError } from './errors.mjs';
import { globP } from './glob.mjs';
import { readStdin } from './stdin.mjs';
import { clean } from './util.mjs';
const doesMatchUrl = /^(file|stdin|https?):\/\//;
export async function readConfig(configFile, root) {
if (configFile) {
const config = (await cspell.loadConfig(configFile)) || {};
return { source: configFile, config };
}
const config = await cspell.searchForConfig(root);
return { source: config?.__importRef?.filename || 'None found', config: config || {} };
}
export function fileInfoToDocument(fileInfo, languageId, locale) {
const { filename, text } = fileInfo;
languageId = languageId || undefined;
locale = locale || undefined;
const uri = filenameToUrlString(filename);
if (uri.startsWith(STDINProtocol)) {
return clean({
uri,
text,
languageId,
locale,
});
}
return fileToDocument(uri, text, languageId, locale);
}
export function filenameToUrlString(filename, cwd = '.') {
if (filename === STDIN)
return 'stdin:///';
if (filename.startsWith(STDINProtocol)) {
const filePath = filename.slice(STDINProtocol.length);
const fullPath = path.resolve(cwd, filePath);
return pathToFileURL(fullPath).toString();
}
if (doesMatchUrl.test(filename))
return filename;
return pathToFileURL(path.resolve(cwd, filename)).toString();
}
export function filenameToUri(filename, cwd) {
return URI.parse(filenameToUrlString(filename, cwd));
}
export function isBinaryFile(filename, cwd) {
const uri = filenameToUri(filename, cwd);
if (uri.scheme.startsWith('stdin'))
return false;
return isUriBinaryFile(uri);
}
export function resolveFilename(filename, cwd) {
cwd = cwd || process.cwd();
if (filename === STDIN)
return STDINProtocol;
if (filename.startsWith(FileProtocol)) {
const url = new URL(filename.slice(FileProtocol.length), pathToFileURL(cwd + path.sep));
return fileURLToPath(url);
}
const scheme = filename.startsWith(STDINProtocol) ? STDINProtocol : '';
const pathname = filename.slice(scheme.length);
return scheme + path.resolve(cwd, pathname);
}
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) => filename !== STDIN && !filename.startsWith(STDINProtocol) && !filename.startsWith(FileProtocol)
? 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}"`);
}
}
export async function isFile(filename) {
try {
const stat = await fsp.stat(filename);
return stat.isFile();
}
catch (e) {
return false;
}
}
export async function isDir(filename) {
try {
const stat = await fsp.stat(filename);
return stat.isDirectory();
}
catch (e) {
return false;
}
}
export function isNotDir(filename) {
return isDir(filename).then((a) => !a);
}
//# sourceMappingURL=fileHelper.mjs.map