UNPKG

textlint-rule-no-mix-dearu-desumasu

Version:
160 lines (151 loc) 5.41 kB
// LICENSE : MIT "use strict"; import { analyze, isDearu, isDesumasu } from "analyze-desumasu-dearu"; export default class MixedChecker { /** * @param context * @param {{preferDearu:boolean, preferDesumasu: boolean}} options */ constructor(context, options) { this.context = context; /** * 明示的な優先するタイプの指定 * @type {{preferDearu: boolean, preferDesumasu: boolean, isStrict: boolean}} */ this.options = options; this.dearuCount = 0; this.desumasuCount = 0; this.dearuHitList = []; this.desumasuHitList = []; this._queue = Promise.resolve(); } check(node, text) { this._queue = this._queue.then(() => { const analyzeOptions = { ignoreConjunction: !this.options.isStrict }; return analyze(text, analyzeOptions).then((results) => { const retDearu = results.filter(isDearu); const retDesumasu = results.filter(isDesumasu); const dearuCount = this.dearuCount + retDearu.length; const desumasuCount = this.desumasuCount + retDesumasu.length; if (this.dearuCount !== dearuCount) { this.dearuCount = dearuCount; this.dearuHitList.push({ node, matches: retDearu }); } if (this.desumasuCount !== desumasuCount) { this.desumasuCount = desumasuCount; this.desumasuHitList.push({ node, matches: retDesumasu }); } }); }); } /** * @param {IgnoreManger}ignoreManger * @returns {Promise.<TResult>} */ checkout(ignoreManger) { return this._queue.then(() => { if (!this.isOver()) { return; } const RuleError = this.context.RuleError; const report = this.context.report; const overType = this.getOverType(); const overHitList = this.overHitList(overType); // List overHitList.forEach(({ node, matches }) => { // Node const lastHitNode = node; // Tokens matches.forEach((token) => { const hitIndex = node.range[0] + token.index; if (ignoreManger.isIgnoredIndex(hitIndex)) { return; } const ruleError = new RuleError(this.outputMessage(token), { index: token.index }); report(lastHitNode, ruleError); }); }); }); } isOver() { if (this.options.preferDesumasu) { return this.dearuCount !== 0; } else if (this.options.preferDearu) { return this.desumasuCount !== 0; } return this.dearuCount !== 0 && this.desumasuCount !== 0; } /** * 優先するtypeを返します。 * @returns {*} */ getOverType() { if (this.options.preferDearu) { return "である"; } else if (this.options.preferDesumasu) { return "ですます"; } if (this.dearuCount > this.desumasuCount) { return "である"; } else { return "ですます"; } } /** * hist node list * @param overType * @returns {Array} */ overHitList(overType) { if (overType === "である") { return this.desumasuHitList; } else if (overType === "ですます") { return this.dearuHitList; } } /** * create message string * @param token * @returns {string} */ outputMessage(token) { const overType = this.getOverType(); let topMessage = ""; if (overType === "である") { // である優先 => 最後の"ですます"を表示 if (this.options.preferDearu) { // である優先が指定されている場合 topMessage = `"である"調 でなければなりません => "である"調 であるべき箇所に、次の "ですます"調 の箇所があります`; } else { topMessage = `"である"調 と "ですます"調 が混在 => "である"調 の文体に、次の "ですます"調 の箇所があります`; } } else if (overType === "ですます") { // ですます優先 => 最後の"である"を表示 if (this.options.preferDesumasu) { // ですます優先が指定されている場合 topMessage = `"ですます"調 でなければなりません => "ですます"調 であるべき箇所に、次の "である"調 の箇所があります`; } else { topMessage = `"である"調 と "ですます"調 が混在 => "ですます"調 の文体に、次の "である"調 の箇所があります`; } } return `${topMessage}: "${token.value}" Total: である : ${this.dearuCount} ですます: ${this.desumasuCount} `; } }