UNPKG

textlint

Version:

The pluggable linting tool for natural language.

208 lines 9.24 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.cli = void 0; // LICENSE : MIT const debug_1 = __importDefault(require("debug")); const options_js_1 = require("./options.js"); const config_initializer_js_1 = require("./config/config-initializer.js"); const textlint_fixer_js_1 = require("./fixer/textlint-fixer.js"); const logger_js_1 = require("./util/logger.js"); const TextlintrcLoader_js_1 = require("./loader/TextlintrcLoader.js"); const CliLoader_js_1 = require("./loader/CliLoader.js"); const createLinter_js_1 = require("./createLinter.js"); const SeverityLevel_js_1 = require("./shared/type/SeverityLevel.js"); const cli_util_js_1 = require("./cli-util.js"); const formatter_js_1 = require("./formatter.js"); const server_js_1 = require("./mcp/server.js"); const debug = (0, debug_1.default)("textlint:cli"); const isStdinExecution = (executeOptions) => { return "text" in executeOptions; }; const loadDescriptor = async (cliOptions) => { const cliDescriptor = await (0, CliLoader_js_1.loadCliDescriptor)(cliOptions); debug("cliDescriptor: %j", cliDescriptor); const textlintrcDescriptor = cliOptions.textlintrc ? await (0, TextlintrcLoader_js_1.loadTextlintrc)({ configFilePath: cliOptions.config, node_modulesDir: cliOptions.rulesBaseDirectory }) : await (0, TextlintrcLoader_js_1.loadBuiltinPlugins)(); debug("textlintrcDescriptor: %j", textlintrcDescriptor); const mergedDescriptor = cliDescriptor.concat(textlintrcDescriptor); debug("mergedDescriptor: %j", mergedDescriptor); return mergedDescriptor; }; /** * Encapsulates all CLI behavior for eslint. Makes it easier to test as well as * for other Node.js programs to effectively run the CLI. */ exports.cli = { /** * Executes the CLI based on an array of arguments that is passed in. * @param {string|string[]} args The arguments to process. * @param {string} [text] The text to lint (used for TTY). * @returns {Promise<number>} The exit code for the operation. */ async execute(args, text) { var _a, _b; let currentOptions; // version from package.json 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"; try { currentOptions = options_js_1.options.parse(args); } catch (error) { logger_js_1.Logger.error(error); return Promise.resolve(1); } const files = currentOptions._; debug("cliOptions: %j", currentOptions); if (currentOptions.version) { logger_js_1.Logger.log(`v${version}`); } else if (currentOptions.init) { return (0, config_initializer_js_1.createConfigFile)({ dir: process.cwd(), verbose: !currentOptions.quiet }); } else if (currentOptions.printConfig) { const descriptor = await loadDescriptor(currentOptions); logger_js_1.Logger.log(JSON.stringify(descriptor, null, 4)); return Promise.resolve(0); } else if (currentOptions.mcp) { const mcpServer = await (0, server_js_1.connectStdioMcpServer)(); process.on("SIGINT", () => { mcpServer.close(); process.exitCode = 0; }); return 0; } else if (currentOptions.help || (!files.length && !text)) { logger_js_1.Logger.log(options_js_1.options.generateHelp()); } else { // specify file name of stdin content const stdinFilename = currentOptions.stdinFilename; debug(`textlint --version: ${version}`); debug(`Running on ${text ? "text" : "files"}, stdin-filename: ${stdinFilename}`); if (text) { if (!stdinFilename) { throw new Error("Please specify --stdin-filename option"); } return this.executeWithOptions({ cliOptions: currentOptions, text, stdinFilename }); } else { return this.executeWithOptions({ cliOptions: currentOptions, files }); } } return Promise.resolve(0); }, /** * execute with cli options * @returns {Promise<number>} exit status * - 0: Success (no lint errors, or files ignored/not found when mixed with existing files) * - 1: Lint errors found or unexpected errors * - 2: File search errors (no files found matching the specified patterns) or fatal errors */ async executeWithOptions(executeOptions) { const cliOptions = executeOptions.cliOptions; // cli > textlintrc // if cli and textlintrc have same option, cli option is prior. const descriptor = await loadDescriptor(cliOptions); const hasRuleAtLeastOne = descriptor.rule.lintableDescriptors.length > 0; if (!hasRuleAtLeastOne) { (0, cli_util_js_1.showEmptyRuleWarning)(); return Promise.resolve(1); } const linter = (0, createLinter_js_1.createLinter)({ cache: cliOptions.cache, cacheLocation: cliOptions.cacheLocation, quiet: cliOptions.quiet, ignoreFilePath: cliOptions.ignorePath, descriptor }); try { if (cliOptions.fix) { // --fix const results = isStdinExecution(executeOptions) ? [await linter.fixText(executeOptions.text, executeOptions.stdinFilename)] : await linter.fixFiles(executeOptions.files); debug("fix results: %j", results); const fixer = new textlint_fixer_js_1.TextLintFixer(); const formatter = await (0, formatter_js_1.loadFixerFormatter)({ formatterName: cliOptions.format, color: cliOptions.color }); const output = formatter.format(results); // --dry-run if (cliOptions.dryRun) { debug("Enable dry-run mode"); return (0, cli_util_js_1.printResults)(output, cliOptions) ? Promise.resolve(0) : Promise.resolve(2); } // modify file and return exit status await fixer.write(results); if ((0, cli_util_js_1.printResults)(output, cliOptions)) { if (cliOptions.outputFile) { return 0; // if --output-file option is specified, exit status is always 0 } // --fix result has remaining errors, return 1 const hasErrorMessage = results.some((result) => { return result.remainingMessages.some((message) => message.severity === SeverityLevel_js_1.SeverityLevel.error); }); return hasErrorMessage ? 1 : 0; } else { return 2; } } else { // lint as default const results = isStdinExecution(executeOptions) ? [await linter.lintText(executeOptions.text, executeOptions.stdinFilename)] : await linter.lintFiles(executeOptions.files); debug("lint results: %j", results); const formatter = await (0, formatter_js_1.loadLinterFormatter)({ formatterName: cliOptions.format, color: cliOptions.color }); const output = formatter.format(results); if ((0, cli_util_js_1.printResults)(output, cliOptions)) { if (cliOptions.outputFile) { return 0; // if --output-file option is specified, exit status is always 0 } const hasErrorMessage = results.some((result) => { return result.messages.some((message) => message.severity === SeverityLevel_js_1.SeverityLevel.error); }); return hasErrorMessage ? 1 : 0; } else { return 2; } } } catch (error) { // Handle file search errors with exit status 2 if (error instanceof createLinter_js_1.TextlintFileSearchError) { logger_js_1.Logger.error(error); return 2; } // Handle other unexpected errors logger_js_1.Logger.error("Unexpected error during file processing:", error); return 1; } } }; //# sourceMappingURL=cli.js.map