UNPKG

@textlint/kernel

Version:
233 lines (227 loc) 9.82 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TextlintKernel = void 0; // MIT © 2017- azu // sequence const fixer_processor_1 = __importDefault(require("./fixer/fixer-processor")); // parallel const linter_processor_1 = __importDefault(require("./linter/linter-processor")); // message process manager const MessageProcessManager_1 = __importDefault(require("./messages/MessageProcessManager")); const filter_ignored_process_1 = __importDefault(require("./messages/filter-ignored-process")); const filter_duplicated_process_1 = __importDefault(require("./messages/filter-duplicated-process")); const filter_severity_process_1 = __importDefault(require("./messages/filter-severity-process")); const sort_messages_process_1 = __importDefault(require("./messages/sort-messages-process")); const descriptor_1 = require("./descriptor"); const TextlintSourceCodeImpl_1 = require("./context/TextlintSourceCodeImpl"); const isPluginParsedObject_1 = require("./util/isPluginParsedObject"); const invariant_1 = require("./util/invariant"); const feature_flag_1 = require("@textlint/feature-flag"); const ast_tester_1 = require("@textlint/ast-tester"); const debug_1 = __importDefault(require("debug")); const parse_by_plugin_1 = require("./util/parse-by-plugin"); const createDummyTextLintResult_1 = require("./util/createDummyTextLintResult"); const debug = (0, debug_1.default)("textlint:kernel"); /** * add fileName to trailing of error message * @param {string|undefined} fileName * @param {string} message * @returns {string} */ function addingAtFileNameToError(fileName, message) { if (!fileName) { return message; } return `${message} at ${fileName}`; } /** * TextlintKernel is core logic written by pure JavaScript. * * Pass * * - config * - plugins * - rules * - filterRules * - messageProcessor * */ class TextlintKernel { /** * @param config */ constructor(config = {}) { // this.config often is undefined. this.config = config; // Initialize Message Processor // Now, It is built-in process only // filter `shouldIgnore()` results this.messageProcessManager = new MessageProcessManager_1.default([filter_ignored_process_1.default]); // filter duplicated messages this.messageProcessManager.add(filter_duplicated_process_1.default); // filter by severity this.messageProcessManager.add((0, filter_severity_process_1.default)(this.config)); this.messageProcessManager.add(sort_messages_process_1.default); } /** * lint text by registered rules. * The result contains target filePath and error messages. * @param {string} text * @param {Object} options linting options * @returns {Promise.<TextlintResult>} */ lintText(text, options) { return Promise.resolve().then(() => { const descriptor = new descriptor_1.TextlintKernelDescriptor({ rules: options.rules || [], filterRules: options.filterRules || [], plugins: options.plugins || [] }); return this._parallelProcess({ descriptor, text, options }); }); } /** * fix texts and return fix result object * @param {string} text * @param {Object} options lint options * @returns {Promise.<TextlintFixResult>} */ fixText(text, options) { return Promise.resolve().then(() => { const descriptor = new descriptor_1.TextlintKernelDescriptor({ rules: options.rules || [], filterRules: options.filterRules || [], plugins: options.plugins || [] }); return this._sequenceProcess({ descriptor, options, text }); }); } /** * process text in parallel for Rules and return {Promise.<TextLintResult>} * In other word, parallel flow process. * @param {*} processor * @param {string} text * @param {Object} options * @returns {Promise.<TextlintResult>} * @private */ async _parallelProcess({ descriptor, text, options }) { const { ext, filePath, configBaseDir } = options; const plugin = descriptor.findPluginDescriptorWithExt(ext); if (plugin === undefined) { throw new Error(`Not found available plugin for ${ext}`); } debug("used plugin %j", plugin.id); const processor = plugin.processor; const { preProcess, postProcess } = processor.processor(ext); (0, invariant_1.invariant)(typeof preProcess === "function" && typeof postProcess === "function", `${plugin.id} processor should implements {preProcess, postProcess}`); const preProcessResult = await (0, parse_by_plugin_1.parseByPlugin)({ preProcess, sourceText: text, filePath }); if (preProcessResult instanceof Error) { return (0, createDummyTextLintResult_1.createDummyTextLintResult)(`Failed to parse text by plugin: ${plugin.id} Please report this error with the content to plugin author. ${preProcessResult.stack} `, filePath); } // { text, ast } or ast const isParsedObject = (0, isPluginParsedObject_1.isPluginParsedObject)(preProcessResult); const textForAST = isParsedObject ? preProcessResult.text : text; const ast = isParsedObject ? preProcessResult.ast : preProcessResult; (0, invariant_1.invariant)(typeof textForAST === "string", `${plugin.id} processor should return correct text`); (0, invariant_1.invariant)(typeof ast === "object", `${plugin.id} processor should return correct AST object`); if (feature_flag_1.coreFlags.runningTester) { (0, invariant_1.invariant)((0, ast_tester_1.isTxtAST)(ast), `${plugin.id} processor return invalid AST object. Please check out @textlint/ast-tester. You can check the validation result with "DEBUG=textlint*" env See https://textlint.github.io/docs/plugin.html`); } const sourceCode = new TextlintSourceCodeImpl_1.TextlintSourceCodeImpl({ text: textForAST, ast, ext, filePath }); debug("process file %s", filePath); const linterProcessor = new linter_processor_1.default(processor, this.messageProcessManager); return await linterProcessor .process({ config: this.config, ruleDescriptors: descriptor.rule, filterRuleDescriptors: descriptor.filterRule, sourceCode, configBaseDir }) .catch((error) => { error.message = addingAtFileNameToError(filePath, error.message); return Promise.reject(error); }); } /** * process text in series for Rules and return {Promise.<TextlintFixResult>} * In other word, sequence flow process. * @param {*} processor * @param {string} text * @param {TextlintKernelOptions} options * @returns {Promise.<TextlintFixResult>} * @private */ async _sequenceProcess({ descriptor, text, options }) { const { ext, filePath, configBaseDir } = options; const plugin = descriptor.findPluginDescriptorWithExt(ext); if (plugin === undefined) { throw new Error(`Not found available plugin for ${ext}`); } debug("used plugin %j", plugin.id); const processor = plugin.processor; const { preProcess, postProcess } = processor.processor(ext); (0, invariant_1.invariant)(typeof preProcess === "function" && typeof postProcess === "function", `${plugin.id} processor should implements {preProcess, postProcess}`); const preProcessResult = await Promise.resolve(preProcess(text, filePath)); // { text, ast } or ast const isParsedObject = (0, isPluginParsedObject_1.isPluginParsedObject)(preProcessResult); const textForAST = isParsedObject ? preProcessResult.text : text; const ast = isParsedObject ? preProcessResult.ast : preProcessResult; (0, invariant_1.invariant)(typeof textForAST === "string", `${plugin.id} processor should return correct text`); (0, invariant_1.invariant)(typeof ast === "object", `${plugin.id} processor should return correct AST object`); if (feature_flag_1.coreFlags.runningTester) { (0, invariant_1.invariant)((0, ast_tester_1.isTxtAST)(ast), `${plugin.id} processor return invalid AST object. Please check out @textlint/ast-tester. You can check the validation result with "DEBUG=textlint*" env See https://textlint.github.io/docs/plugin.html`); } const sourceCode = new TextlintSourceCodeImpl_1.TextlintSourceCodeImpl({ text: textForAST, ast, ext, filePath }); debug("process file %s", filePath); const fixerProcessor = new fixer_processor_1.default(processor, this.messageProcessManager); return await fixerProcessor .process({ config: this.config, ruleDescriptors: descriptor.rule, filterRules: descriptor.filterRule, sourceCode, configBaseDir }) .catch((error) => { error.message = addingAtFileNameToError(filePath, error.message); return Promise.reject(error); }); } } exports.TextlintKernel = TextlintKernel; //# sourceMappingURL=textlint-kernel.js.map