UNPKG

textlint

Version:

The pluggable linting tool for text and markdown.

277 lines 10.1 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.AbstractTextLintEngine = void 0; const textlint_core_1 = require("../textlint-core"); const rule_map_1 = require("../../engine/rule-map"); const processor_map_1 = require("../../engine/processor-map"); const config_1 = require("../config"); const old_find_util_1 = require("../../util/old-find-util"); const textlint_module_loader_1 = require("./textlint-module-loader"); const execute_file_backer_manager_1 = require("../../engine/execute-file-backer-manager"); const cache_backer_1 = require("../../engine/execute-file-backers/cache-backer"); const SeverityLevel_1 = require("../../shared/type/SeverityLevel"); const debug_1 = __importDefault(require("debug")); const path_1 = __importDefault(require("path")); const separate_by_availability_1 = require("../../util/separate-by-availability"); const debug = (0, debug_1.default)("textlint:engine-core"); /** * Core of TextLintEngine. * It is internal user. * * Hackable adaptor * * - executeOnFiles * - executeOnText * - formatResults * * There are hackable by `executor` option. */ class AbstractTextLintEngine { /** * Process files are wanted to lint. * TextLintEngine is a wrapper of textlint.js. * Aim to be called from cli with cli options. * @param {Config|Object} [options] the options is command line options or Config object. * @constructor */ constructor(options) { /** * @type {Config} */ if (options instanceof config_1.Config) { // Almost internal use-case this.config = options; } else { this.config = config_1.Config.initWithAutoLoading(options); } /** * @type {TextLintCore} * @private */ this.textlint = new textlint_core_1.TextLintCore(this.config); /** * @type {ExecuteFileBackerManager} * @private */ this.executeFileBackerManger = new execute_file_backer_manager_1.ExecuteFileBackerManager(); const cacheBaker = new cache_backer_1.CacheBacker(this.config); if (this.config.cache) { this.executeFileBackerManger.add(cacheBaker); } else { cacheBaker.destroyCache(); } /** * @type {RuleMap} ruleMap is used for linting/fixer * @private */ this.ruleMap = new rule_map_1.RuleMap(); /** * @type {RuleMap} filerRuleMap is used for filtering * @private */ this.filterRuleMap = new rule_map_1.RuleMap(); /** * @type {PluginMap} * @private */ this.pluginMap = new processor_map_1.PluginMap(); /** * @type {TextLintModuleLoader} * @private */ this.moduleLoader = new textlint_module_loader_1.TextLintModuleLoader(this.config); this.moduleLoader.on(textlint_module_loader_1.TextLintModuleLoader.Event.rule, ([ruleName, ruleCreator]) => { this.ruleMap.defineRule(ruleName, ruleCreator); }); this.moduleLoader.on(textlint_module_loader_1.TextLintModuleLoader.Event.filterRule, ([ruleName, ruleCreator]) => { this.filterRuleMap.defineRule(ruleName, ruleCreator); }); this.moduleLoader.on(textlint_module_loader_1.TextLintModuleLoader.Event.plugin, ([pluginName, plugin]) => { this.pluginMap.set(pluginName, plugin); }); // load rule/plugin/processor this.moduleLoader.loadFromConfig(this.config); // set settings to textlint core this._setupRules(); } /** * @deprecated remove this method */ setRulesBaseDirectory() { throw new Error(`Should not use setRulesBaseDirectory(), insteadof use new TextLintEngine({ rulesBaseDirectory: directory }) `); } /** * load plugin manually * Note: it high cost, please use config * @param {string} pluginName * @deprecated use Constructor(config) insteadof it */ loadPlugin(pluginName) { this.moduleLoader.loadPlugin(pluginName); this._setupRules(); } /** * load plugin manually * Note: it high cost, please use config * @param {string} presetName * @deprecated use Constructor(config) insteadof it */ loadPreset(presetName) { this.moduleLoader.loadPreset(presetName); this._setupRules(); } /** * load rule manually * Note: it high cost, please use config * @param {string} ruleName * @deprecated use Constructor(config) insteadof it */ loadRule(ruleName) { this.moduleLoader.loadRule(ruleName); this._setupRules(); } /** * load filter rule manually * Note: it high cost, please use config * @param {string} ruleName * @deprecated use Constructor(config) insteadof it */ loadFilerRule(ruleName) { this.moduleLoader.loadFilterRule(ruleName); this._setupRules(); } /** * Update rules from current config * @private */ _setupRules() { // set Rules const textlintConfig = this.config ? this.config.toJSON() : {}; this.textlint.setupRules(this.ruleMap.getAllRules(), textlintConfig.rulesConfig); this.textlint.setupFilterRules(this.filterRuleMap.getAllRules(), textlintConfig.filterRulesConfig); // set Processor this.textlint.setupPlugins(this.pluginMap.toJSON(), textlintConfig.pluginsConfig); } /** * Remove all registered rule and clear messages. * @private */ resetRules() { this.textlint.resetRules(); this.ruleMap.resetRules(); this.filterRuleMap.resetRules(); } /** * Return available extensions of plugins that include built-in plugins * @example * ``` * engine.availableExtensions; // => [".txt", ".md"] * ``` */ get availableExtensions() { return this.textlint.textlintKernelDescriptor.availableExtensions; } /** * Return meta descriptor object for this engine * * WARNING: This is experimental getter method. * It will be renamed. */ get textlintrcDescriptor() { return this.textlint.textlintKernelDescriptor; } /** * Executes the current configuration on an array of file and directory names. * @param {String[]} files An array of file and directory names. * @returns {Promise<TextlintResult[]>} The results for all files that were linted. */ executeOnFiles(files) { const execFile = this.onFile(this.textlint); const patterns = (0, old_find_util_1.pathsToGlobPatterns)(files, { extensions: this.textlintrcDescriptor.availableExtensions }); const targetFiles = (0, old_find_util_1.findFiles)(patterns, { ignoreFilePath: this.config.ignoreFile }); // Maybe, unAvailableFilePath should be warning. // But, The user can use glob pattern like `src/**/*` as arguments. // pathsToGlobPatterns not modified that pattern. // So, unAvailableFilePath should be ignored silently. const { availableFiles, unAvailableFiles } = (0, separate_by_availability_1.separateByAvailability)(targetFiles, { extensions: this.textlintrcDescriptor.availableExtensions }); debug("Process files", availableFiles); debug("No Process files that are un-support extensions:", unAvailableFiles); // FIXME: remove cast return this.executeFileBackerManger.process(availableFiles, execFile); } /** * If want to lint a text, use it. * But, if you have a target file, use {@link executeOnFiles} instead of it. * @param {string} text linting text content * @param {string} ext ext is a type for linting. default: ".txt" * @returns {Promise<TextlintResult[]>} */ executeOnText(text, ext = ".txt") { const textlint = this.textlint; const execText = this.onText(textlint); // filePath or ext const actualExt = ext[0] === "." ? ext : path_1.default.extname(ext); if (actualExt.length === 0) { throw new Error("should specify the extension.\nex) .md"); } return execText(text, actualExt).then((result) => { return [result]; }); } /** * format {@link results} and return output text. * @param {TextlintResult[]} results the collection of result * @returns {string} formatted output text * @example * console.log(formatResults(results)); */ formatResults(results) { // default formatter: "stylish" const formatter = this.onFormat({ formatterName: this.config.formatterName || "stylish", color: this.config.color }); return formatter(results); } /** * Checks if the given message is an error message. * @param {TextlintMessage} message The message to check. * @returns {boolean} Whether or not the message is an error message. */ isErrorMessage(message) { return message.severity === SeverityLevel_1.SeverityLevel.error; } /** * Checks if the given results contain error message. * If there is even one error then return true. * @param {TextlintResult[]} results Linting result collection * @returns {Boolean} Whether or not the results contain error message. */ isErrorResults(results) { return results.some((result) => { return result.messages.some(this.isErrorMessage); }); } /** * @returns {boolean} */ hasRuleAtLeastOne() { return this.ruleMap.hasRuleAtLeastOne(); } } exports.AbstractTextLintEngine = AbstractTextLintEngine; //# sourceMappingURL=textlint-engine-core.js.map