UNPKG

textlint

Version:

The pluggable linting tool for natural language.

194 lines (193 loc) 9.34 kB
// LICENSE : MIT "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createLinter = exports.TextlintFileSearchError = void 0; const kernel_1 = require("@textlint/kernel"); const find_util_js_1 = require("./util/find-util.js"); const execute_file_backer_manager_js_1 = require("./engine/execute-file-backer-manager.js"); const cache_backer_js_1 = require("./engine/execute-file-backers/cache-backer.js"); const node_path_1 = __importDefault(require("node:path")); const node_crypto_1 = __importDefault(require("node:crypto")); const promises_1 = __importDefault(require("node:fs/promises")); const logger_js_1 = require("./util/logger.js"); const debug_1 = __importDefault(require("debug")); const separate_by_availability_js_1 = require("./util/separate-by-availability.js"); const debug = (0, debug_1.default)("textlint:createTextlint"); // File Search Custom Error class TextlintFileSearchError extends Error { constructor({ errors, patterns }) { super(`Not found target files. Patterns: ${patterns.join(", ")} Reason: ${errors.map((e) => e.type).join(", ") || "Unknown error"}`); this.name = "TextlintFileSearchError"; this.errors = errors; this.patterns = patterns; } } exports.TextlintFileSearchError = TextlintFileSearchError; const createHashForDescriptor = async (descriptor) => { var _a, _b; try { const { readPackageUpSync } = await import("read-package-up"); const version = (_b = (_a = readPackageUpSync({ cwd: __dirname })) === null || _a === void 0 ? void 0 : _a.packageJson.version) !== null && _b !== void 0 ? _b : "unknown"; const toString = JSON.stringify(descriptor.toJSON()); const md5 = node_crypto_1.default.createHash("md5"); return md5.update(`${version}-${toString}`, "utf8").digest("hex"); } catch (error) { // Fallback for some env // https://github.com/textlint/textlint/issues/597 logger_js_1.Logger.warn("Use random value as hash because calculating hash value throw error", error); return node_crypto_1.default.randomBytes(20).toString("hex"); } }; const createExecutor = async (options) => { var _a, _b; const executeFileBackerManager = new execute_file_backer_manager_js_1.ExecuteFileBackerManager(); if (options.cache) { const cacheBaker = new cache_backer_js_1.CacheBacker({ cache: (_a = options.cache) !== null && _a !== void 0 ? _a : false, cacheLocation: (_b = options.cacheLocation) !== null && _b !== void 0 ? _b : node_path_1.default.resolve(process.cwd(), ".textlintcache"), hash: await createHashForDescriptor(options.descriptor) }); executeFileBackerManager.add(cacheBaker); } return executeFileBackerManager; }; const createLinter = (options) => { var _a; const cwd = (_a = options.cwd) !== null && _a !== void 0 ? _a : process.cwd(); const kernel = new kernel_1.TextlintKernel({ quiet: options.quiet }); const baseOptions = options.descriptor.toKernelOptions(); return { /** * Lint files * Note: lintFiles respect ignore file * @param {String[]} filesOrGlobs An array of file path and directory names, or glob. * @returns {Promise<TextlintResult[]>} The results for all files that were linted. */ async lintFiles(filesOrGlobs) { const executeFileBackerManager = await createExecutor(options); const patterns = (0, find_util_js_1.pathsToGlobPatterns)(filesOrGlobs, { extensions: options.descriptor.availableExtensions }); const searchResult = await (0, find_util_js_1.searchFiles)(patterns, { cwd, ignoreFilePath: options.ignoreFilePath }); if (!searchResult.ok) { debug("Failed to search files with patterns: %j. Reason: %s", patterns, searchResult.errors.map((e) => e.type).join(", ") || "Unknown error"); throw new TextlintFileSearchError({ errors: searchResult.errors, patterns }); } const targetFiles = searchResult.items; const { availableFiles, unAvailableFiles } = (0, separate_by_availability_js_1.separateByAvailability)(targetFiles, { extensions: options.descriptor.availableExtensions }); debug("Available extensions: %j", options.descriptor.availableExtensions); debug("Process files: %j", availableFiles); debug("No Process files that are un-support extensions: %j", unAvailableFiles); const results = await executeFileBackerManager.process(availableFiles, async (filePath) => { const absoluteFilePath = node_path_1.default.resolve(process.cwd(), filePath); const fileContent = await promises_1.default.readFile(filePath, "utf-8"); const kernelOptions = { ext: node_path_1.default.extname(filePath), filePath: absoluteFilePath, ...baseOptions }; return kernel.lintText(fileContent, kernelOptions); }); return results; }, /** * Lint text * Note: lintText does not respect ignore file * You can detect the file path is ignored or not by `scanFilePath()` * @param text * @param filePath */ async lintText(text, filePath) { const kernelOptions = { ext: node_path_1.default.extname(filePath), filePath, ...baseOptions }; return kernel.lintText(text, kernelOptions); }, /** * Lint files and fix them * Note: fixFiles respect ignore file * @param fileOrGlobs An array of file path and directory names, or glob. * @returns {Promise<TextlintFixResult[]>} The results for all files that were linted and fixed. */ async fixFiles(fileOrGlobs) { const executeFileBackerManager = await createExecutor(options); const patterns = (0, find_util_js_1.pathsToGlobPatterns)(fileOrGlobs, { extensions: options.descriptor.availableExtensions }); const searchResult = await (0, find_util_js_1.searchFiles)(patterns, { cwd, ignoreFilePath: options.ignoreFilePath }); if (!searchResult.ok) { debug("Failed to search files with patterns: %j. Reason: %s", patterns, searchResult.errors.map((e) => e.type).join(", ") || "Unknown error"); throw new TextlintFileSearchError({ errors: searchResult.errors, patterns }); } const targetFiles = searchResult.items; const { availableFiles, unAvailableFiles } = (0, separate_by_availability_js_1.separateByAvailability)(targetFiles, { extensions: options.descriptor.availableExtensions }); debug("Available extensions: %j", options.descriptor.availableExtensions); debug("Process files: %j", availableFiles); debug("No Process files that are un-support extensions: %j", unAvailableFiles); const results = await executeFileBackerManager.process(availableFiles, async (filePath) => { const absoluteFilePath = node_path_1.default.resolve(process.cwd(), filePath); const fileContent = await promises_1.default.readFile(filePath, "utf-8"); const kernelOptions = { ext: node_path_1.default.extname(filePath), filePath: absoluteFilePath, ...baseOptions }; return kernel.fixText(fileContent, kernelOptions); }); return results; }, /** * Lint text and fix it * Note: fixText does not respect ignore file * You can detect the file path is ignored or not by `scanFilePath()` * @param text * @param filePath */ async fixText(text, filePath) { const kernelOptions = { ext: node_path_1.default.extname(filePath), filePath, ...baseOptions }; return kernel.fixText(text, kernelOptions); }, /** * Scan file path and return scan result * If you want to know the file is ignored by ignore file, use this function * Return { status "ok" | "ignored" | "error" } object: * - ok: found file and allow to lint/fix * - ignored: found file, and it is ignored by ignore file * - error: not found file * @param filePath * @returns {Promise<ScanFilePathResult>} */ async scanFilePath(filePath) { return (0, find_util_js_1.scanFilePath)(filePath, { cwd, ignoreFilePath: options.ignoreFilePath }); } }; }; exports.createLinter = createLinter; //# sourceMappingURL=createLinter.js.map