UNPKG

textlint

Version:

The pluggable linting tool for natural language.

211 lines (208 loc) 8.92 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.TextLintModuleLoader = void 0; const events_1 = require("events"); const module_interop_1 = require("@textlint/module-interop"); const debug_1 = __importDefault(require("debug")); const config_util_1 = require("../config/config-util"); const rule_loader_1 = require("../../engine/rule-loader"); const logger_1 = require("../../util/logger"); const textlint_module_resolver_1 = require("./textlint-module-resolver"); const textlint_module_mapper_1 = require("./textlint-module-mapper"); const utils_1 = require("@textlint/utils"); const fs_1 = __importDefault(require("fs")); const debug = (0, debug_1.default)("textlint:module-loader"); const isFile = (filePath) => { try { return fs_1.default.statSync(filePath).isFile(); } catch (error) { return false; } }; class TextLintModuleLoader extends events_1.EventEmitter { static get Event() { return { rule: "rule", filterRule: "filterRule", plugin: "plugin", error: "error" }; } constructor(config) { super(); this.moduleResolver = new textlint_module_resolver_1.TextLintModuleResolver(config); } /** * set up lint rules using {@lint Config} object. * The {@lint Config} object was created with initialized {@link TextLintEngine} (as-known Constructor). * @param {Config} config the config is parsed object */ loadFromConfig(config) { debug("config %O", config); // --ruledir if (config.rulePaths && this.listenerCount(TextLintModuleLoader.Event.rule) > 0) { // load in additional rules config.rulePaths.forEach((rulesDir) => { debug("Loading rules from %o", rulesDir); const rules = (0, rule_loader_1.loadFromDir)(rulesDir); Object.keys(rules).forEach((ruleName) => { const entry = [ruleName, rules[ruleName]]; this.emit(TextLintModuleLoader.Event.rule, entry); }); }); } // --rule if (config.rules && this.listenerCount(TextLintModuleLoader.Event.rule) > 0) { // load in additional rules config.rules.forEach((ruleName) => { this.loadRule(ruleName); }); } // TODO: --filter if (config.filterRules && this.listenerCount(TextLintModuleLoader.Event.filterRule) > 0) { // load in additional filterRules config.filterRules.forEach((ruleName) => { this.loadFilterRule(ruleName); }); } // --preset if (config.presets && this.listenerCount(TextLintModuleLoader.Event.rule) > 0) { config.presets.forEach((presetName) => { this.loadPreset(presetName); }); } // --plugin if (config.plugins && this.listenerCount(TextLintModuleLoader.Event.plugin) > 0) { // load in additional rules from plugin config.plugins.forEach((pluginName) => { this.loadPlugin(pluginName); }); } } /** * load rule from plugin name. * plugin module has `rules` object and define rule with plugin prefix. * @param {string} pluginName */ loadPlugin(pluginName) { const pkgPath = this.moduleResolver.resolvePluginPackageName(pluginName); debug("Loading rules from plugin: %s", pkgPath); const plugin = (0, module_interop_1.moduleInterop)(require(pkgPath)); const pluginNameWithoutPrefix = (0, utils_1.normalizeTextlintPluginKey)(pluginName); // Notes: plugins not support "rules" and "rulesConfig" // https://github.com/textlint/textlint/issues/291 if (plugin.hasOwnProperty("rules")) { throw new Error(`textlint plugins not support "rules" and "rulesConfig". But ${pluginName} has these filed. For more details, See https://github.com/textlint/textlint/issues/291`); } // register plugin.Processor if (!plugin.hasOwnProperty("Processor")) { throw new Error(`textlint plugin should have "Processor". For more details. See https://github.com/textlint/textlint/blob/master/docs/plugin.md`); } const pluginEntry = [pluginNameWithoutPrefix, plugin]; this.emit(TextLintModuleLoader.Event.plugin, pluginEntry); } loadPreset(presetName) { /* Caution: Rules of preset are defined as following. { "rules": { "preset-gizmo": { "ruleA": false } } It mean that "ruleA" is defined as "preset-gizmo/ruleA" */ const presetRuleNameWithoutPrefix = (0, utils_1.normalizeTextlintRulePresetKey)(presetName); // ignore plugin's rule if ((0, config_util_1.isPluginRuleKey)(presetRuleNameWithoutPrefix)) { logger_1.Logger.warn(`${presetRuleNameWithoutPrefix} is Plugin's rule. This is unknown case, please report issue.`); return; } const pkgPath = this.moduleResolver.resolvePresetPackageName(presetName); debug("Loading rules from preset: %s", pkgPath); const preset = (0, module_interop_1.moduleInterop)(require(pkgPath)); const entities = textlint_module_mapper_1.TextLintModuleMapper.createEntities(preset.rules, presetRuleNameWithoutPrefix); entities.forEach((entry) => { this.emit(TextLintModuleLoader.Event.rule, entry); }); } /** * load rule file with `ruleName` and define rule. * if rule is not found, then throw ReferenceError. * if already rule is loaded, do not anything. * @param {string} ruleName */ loadRule(ruleName) { /* Task - check already define - resolve package name - load package - emit rule */ // ruleName is filePath if (isFile(ruleName)) { const ruleCreator = (0, module_interop_1.moduleInterop)(require(ruleName)); const ruleEntry = [ruleName, ruleCreator]; this.emit(TextLintModuleLoader.Event.rule, ruleEntry); return; } // ignore already defined rule // ignore rules from rulePaths because avoid ReferenceError is that try to require. const definedRuleName = (0, utils_1.normalizeTextlintRuleKey)(ruleName); // ignore plugin's rule if ((0, config_util_1.isPluginRuleKey)(definedRuleName)) { logger_1.Logger.warn(`${definedRuleName} is Plugin's rule. This is unknown case, please report issue.`); return; } const pkgPath = this.moduleResolver.resolveRulePackageName(ruleName); debug("Loading rules from %s", pkgPath); const ruleCreator = (0, module_interop_1.moduleInterop)(require(pkgPath)); const ruleEntry = [definedRuleName, ruleCreator]; this.emit(TextLintModuleLoader.Event.rule, ruleEntry); } /** * load filter rule file with `ruleName` and define rule. * if rule is not found, then throw ReferenceError. * if already rule is loaded, do not anything. * @param {string} ruleName */ loadFilterRule(ruleName) { /* Task - check already define - resolve package name - load package - emit rule */ // ignore already defined rule // ignore rules from rulePaths because avoid ReferenceError is that try to require. if (isFile(ruleName)) { const ruleCreator = (0, module_interop_1.moduleInterop)(require(ruleName)); const ruleEntry = [ruleName, ruleCreator]; this.emit(TextLintModuleLoader.Event.filterRule, ruleEntry); return; } const definedRuleName = (0, utils_1.normalizeTextlintFilterRuleKey)(ruleName); // ignore plugin's rule if ((0, config_util_1.isPluginRuleKey)(definedRuleName)) { logger_1.Logger.warn(`${definedRuleName} is Plugin's rule. This is unknown case, please report issue.`); return; } const pkgPath = this.moduleResolver.resolveFilterRulePackageName(ruleName); debug("Loading filter rules from %s", pkgPath); const ruleCreator = (0, module_interop_1.moduleInterop)(require(pkgPath)); const ruleEntry = [definedRuleName, ruleCreator]; this.emit(TextLintModuleLoader.Event.filterRule, ruleEntry); } } exports.TextLintModuleLoader = TextLintModuleLoader; //# sourceMappingURL=textlint-module-loader.js.map