|
2 | 2 | "use strict";
|
3 | 3 | import { RuleHelper } from "textlint-rule-helper";
|
4 | 4 | import { splitAST as splitSentences, Syntax as SentenceSyntax, SentenceNode } from "sentence-splitter";
|
5 |
| -import { getTokenizer, KuromojiToken } from "kuromojin"; |
| 5 | +import { tokenize, KuromojiToken } from "kuromojin"; |
6 | 6 | import {
|
7 | 7 | is助詞Token,
|
8 | 8 | create読点Matcher,
|
@@ -141,86 +141,84 @@ const report: TextlintRuleModule<Options> = function (context, options = {}) {
|
141 | 141 | },
|
142 | 142 | });
|
143 | 143 | const sentences = txtParentNode.children.filter(isSentenceNode);
|
144 |
| - return getTokenizer().then((tokenizer: any) => { |
145 |
| - const checkSentence = (sentence: SentenceNode) => { |
146 |
| - const sentenceSource = new StringSource(sentence); |
147 |
| - const text = sentenceSource.toString(); |
148 |
| - const tokens = tokenizer.tokenizeForSentence(text); |
149 |
| - // 助詞 + 助詞は 一つの助詞として扱う |
150 |
| - // https://github.com/textlint-ja/textlint-rule-no-doubled-joshi/issues/15 |
151 |
| - // 連語(助詞)の対応 |
152 |
| - // http://www.weblio.jp/parts-of-speech/%E9%80%A3%E8%AA%9E(%E5%8A%A9%E8%A9%9E)_1 |
153 |
| - const concatTokens = concatJoishiTokens(tokens); |
154 |
| - const countableTokens = concatTokens.filter((token) => { |
155 |
| - if (isStrict) { |
156 |
| - return is助詞Token(token); |
157 |
| - } |
158 |
| - // "("や")"などもトークンとしてカウントする |
159 |
| - // xxxx(xxx) xxx でカッコの中と外に距離を一つ増やす目的 |
160 |
| - // https://github.com/textlint-ja/textlint-rule-no-doubled-joshi/issues/31 |
161 |
| - if (is括弧Token(token)) { |
162 |
| - return true; |
163 |
| - } |
164 |
| - // "、" があると助詞同士の距離が開くようにすることで、並列的な"、"の使い方を許容する目的 |
165 |
| - // https://github.com/azu/textlint-rule-no-doubled-joshi/issues/2 |
166 |
| - if (is読点Token(token)) { |
167 |
| - return true; |
168 |
| - } |
169 |
| - // デフォルトでは、"、"を間隔値の距離としてカウントする |
| 144 | + const checkSentence = async (sentence: SentenceNode) => { |
| 145 | + const sentenceSource = new StringSource(sentence); |
| 146 | + const text = sentenceSource.toString(); |
| 147 | + const tokens = await tokenize(text); |
| 148 | + // 助詞 + 助詞は 一つの助詞として扱う |
| 149 | + // https://github.com/textlint-ja/textlint-rule-no-doubled-joshi/issues/15 |
| 150 | + // 連語(助詞)の対応 |
| 151 | + // http://www.weblio.jp/parts-of-speech/%E9%80%A3%E8%AA%9E(%E5%8A%A9%E8%A9%9E)_1 |
| 152 | + const concatTokens = concatJoishiTokens(tokens); |
| 153 | + const countableTokens = concatTokens.filter((token) => { |
| 154 | + if (isStrict) { |
170 | 155 | return is助詞Token(token);
|
171 |
| - }); |
172 |
| - const joshiTokenSurfaceKeyMap = createSurfaceKeyMap(countableTokens); |
173 |
| - /* |
174 |
| - # Data Structure |
| 156 | + } |
| 157 | + // "("や")"などもトークンとしてカウントする |
| 158 | + // xxxx(xxx) xxx でカッコの中と外に距離を一つ増やす目的 |
| 159 | + // https://github.com/textlint-ja/textlint-rule-no-doubled-joshi/issues/31 |
| 160 | + if (is括弧Token(token)) { |
| 161 | + return true; |
| 162 | + } |
| 163 | + // "、" があると助詞同士の距離が開くようにすることで、並列的な"、"の使い方を許容する目的 |
| 164 | + // https://github.com/azu/textlint-rule-no-doubled-joshi/issues/2 |
| 165 | + if (is読点Token(token)) { |
| 166 | + return true; |
| 167 | + } |
| 168 | + // デフォルトでは、"、"を間隔値の距離としてカウントする |
| 169 | + return is助詞Token(token); |
| 170 | + }); |
| 171 | + const joshiTokenSurfaceKeyMap = createSurfaceKeyMap(countableTokens); |
| 172 | + /* |
| 173 | + # Data Structure |
175 | 174 |
|
176 |
| - joshiTokens = [tokenA, tokenB, tokenC, tokenD, tokenE, tokenF] |
177 |
| - joshiTokenSurfaceKeyMap = { |
178 |
| - "は:助詞.係助詞": [tokenA, tokenC, tokenE], |
179 |
| - "で:助詞.係助詞": [tokenB, tokenD, tokenF] |
180 |
| - } |
181 |
| - */ |
182 |
| - Object.keys(joshiTokenSurfaceKeyMap).forEach((key) => { |
183 |
| - const tokens: KuromojiToken[] = joshiTokenSurfaceKeyMap[key]; |
184 |
| - const joshiName = restoreToSurfaceFromKey(key); |
185 |
| - // check allow |
186 |
| - if (allow.indexOf(joshiName) >= 0) { |
| 175 | + joshiTokens = [tokenA, tokenB, tokenC, tokenD, tokenE, tokenF] |
| 176 | + joshiTokenSurfaceKeyMap = { |
| 177 | + "は:助詞.係助詞": [tokenA, tokenC, tokenE], |
| 178 | + "で:助詞.係助詞": [tokenB, tokenD, tokenF] |
| 179 | + } |
| 180 | + */ |
| 181 | + Object.keys(joshiTokenSurfaceKeyMap).forEach((key) => { |
| 182 | + const tokens: KuromojiToken[] = joshiTokenSurfaceKeyMap[key]; |
| 183 | + const joshiName = restoreToSurfaceFromKey(key); |
| 184 | + // check allow |
| 185 | + if (allow.indexOf(joshiName) >= 0) { |
| 186 | + return; |
| 187 | + } |
| 188 | + // strict mode ではない時例外を除去する |
| 189 | + if (!isStrict) { |
| 190 | + if (matchExceptionRule(tokens)) { |
187 | 191 | return;
|
188 | 192 | }
|
189 |
| - // strict mode ではない時例外を除去する |
190 |
| - if (!isStrict) { |
191 |
| - if (matchExceptionRule(tokens)) { |
192 |
| - return; |
193 |
| - } |
| 193 | + } |
| 194 | + if (tokens.length <= 1) { |
| 195 | + return; // no duplicated token |
| 196 | + } |
| 197 | + // if found differenceIndex less than |
| 198 | + // tokes are sorted ascending order |
| 199 | + tokens.reduce((prev, current) => { |
| 200 | + const startPosition = countableTokens.indexOf(prev); |
| 201 | + const otherPosition = countableTokens.indexOf(current); |
| 202 | + // 助詞token同士の距離が設定値以下ならエラーを報告する |
| 203 | + const differenceIndex = otherPosition - startPosition; |
| 204 | + if (differenceIndex <= minInterval) { |
| 205 | + // padding positionを計算する |
| 206 | + const originalIndex = sentenceSource.originalIndexFromIndex(current.word_position - 1); |
| 207 | + report( |
| 208 | + sentence, |
| 209 | + new RuleError( |
| 210 | + `一文に二回以上利用されている助詞 "${joshiName}" がみつかりました。`, |
| 211 | + { |
| 212 | + index: originalIndex, |
| 213 | + } |
| 214 | + ) |
| 215 | + ); |
194 | 216 | }
|
195 |
| - if (tokens.length <= 1) { |
196 |
| - return; // no duplicated token |
197 |
| - } |
198 |
| - // if found differenceIndex less than |
199 |
| - // tokes are sorted ascending order |
200 |
| - tokens.reduce((prev, current) => { |
201 |
| - const startPosition = countableTokens.indexOf(prev); |
202 |
| - const otherPosition = countableTokens.indexOf(current); |
203 |
| - // 助詞token同士の距離が設定値以下ならエラーを報告する |
204 |
| - const differenceIndex = otherPosition - startPosition; |
205 |
| - if (differenceIndex <= minInterval) { |
206 |
| - // padding positionを計算する |
207 |
| - const originalIndex = sentenceSource.originalIndexFromIndex(current.word_position - 1); |
208 |
| - report( |
209 |
| - sentence, |
210 |
| - new RuleError( |
211 |
| - `一文に二回以上利用されている助詞 "${joshiName}" がみつかりました。`, |
212 |
| - { |
213 |
| - index: originalIndex, |
214 |
| - } |
215 |
| - ) |
216 |
| - ); |
217 |
| - } |
218 |
| - return current; |
219 |
| - }); |
| 217 | + return current; |
220 | 218 | });
|
221 |
| - }; |
222 |
| - sentences.forEach((node) => checkSentence(node)); |
223 |
| - }); |
| 219 | + }); |
| 220 | + }; |
| 221 | + return Promise.all(sentences.map(checkSentence)); |
224 | 222 | },
|
225 | 223 | };
|
226 | 224 | };
|
|
0 commit comments