textlint-rule-no-mix-dearu-desumasu
Version:
textlint rule that no mixed である and ですます.
165 lines (160 loc) • 4.89 kB
JavaScript
// LICENSE : MIT
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _analyzeDesumasuDearu = require("analyze-desumasu-dearu");
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 (0, _analyzeDesumasuDearu.analyze)(text, analyzeOptions).then(results => {
const retDearu = results.filter(_analyzeDesumasuDearu.isDearu);
const retDesumasu = results.filter(_analyzeDesumasuDearu.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}
`;
}
}
exports.default = MixedChecker;
//# sourceMappingURL=MixedChecker.js.map