Skip to content

Commit 3d1418f

Browse files
authored
Merge pull request #16 from textlint-ja/joshi_joshi
feat(rule): "には" を 一つの助詞として認識するように
2 parents 4de3c24 + 071f27f commit 3d1418f

File tree

4 files changed

+76
-14
lines changed

4 files changed

+76
-14
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ textlint --rule no-doubled-joshi README.md
123123
124124
接続助詞 "て" の重なりは例外として許可する。
125125

126+
### 連語(助詞)
127+
128+
- [連語(助詞) - 修飾語 - 品詞の分類 - Weblio 辞書](http://www.weblio.jp/parts-of-speech/%E9%80%A3%E8%AA%9E(%E5%8A%A9%E8%A9%9E)_1 "連語(助詞) - 修飾語 - 品詞の分類 - Weblio 辞書")
129+
130+
連語は一つの助詞の塊として認識します。
131+
132+
```
133+
OK: 文字列の長さを正確**に**測る**には**ある程度の妥協が必要になります。
134+
NG: 文字列**には**そこ**には***問題がある。
135+
```
136+
126137
### その他の助詞
127138

128139
その他の助詞も例外として扱いたい場合は `allow` オプションを利用する。

src/no-doubled-joshi.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ import {split as splitSentences, Syntax as SentenceSyntax} from "sentence-splitt
66
import StringSource from "textlint-util-to-string";
77
import {
88
is助詞Token, is読点Token,
9-
createKeyFromKey, restoreToSurfaceFromKey
9+
concatJoishiTokens,
10+
createKeyFromKey,
11+
restoreToSurfaceFromKey
1012
} from "./token-utils";
1113
/**
1214
* Create token map object
1315
* {
14-
* "で": [token, token],
15-
* "の": [token, token]
16+
* "は:助詞.係助詞": [token, token]
1617
* }
1718
* @param tokens
1819
* @returns {*}
1920
*/
2021
function createSurfaceKeyMap(tokens) {
2122
// 助詞のみを対象とする
22-
return tokens.filter(is助詞Token).reduce((keyMap, token) => {
23+
return tokens.reduce((keyMap, token) => {
2324
// "は:助詞.係助詞" : [token]
2425
const tokenKey = createKeyFromKey(token);
2526
if (!keyMap[tokenKey]) {
@@ -70,7 +71,7 @@ export default function(context, options = {}) {
7071
const isStrict = options.strict || defaultOptions.strict;
7172
const allow = options.allow || defaultOptions.allow;
7273
const separatorChars = options.separatorChars || defaultOptions.separatorChars;
73-
const {Syntax, report, getSource, RuleError} = context;
74+
const {Syntax, report, RuleError} = context;
7475
return {
7576
[Syntax.Paragraph](node){
7677
if (helper.isChildNode(node, [Syntax.Link, Syntax.Image, Syntax.BlockQuote, Syntax.Emphasis])) {
@@ -81,13 +82,18 @@ export default function(context, options = {}) {
8182
const isSentenceNode = node => {
8283
return node.type === SentenceSyntax.Sentence;
8384
};
84-
let sentences = splitSentences(text, {
85+
const sentences = splitSentences(text, {
8586
separatorChars: separatorChars
8687
}).filter(isSentenceNode);
8788
return getTokenizer().then(tokenizer => {
8889
const checkSentence = (sentence) => {
89-
let tokens = tokenizer.tokenizeForSentence(sentence.raw);
90-
let countableTokens = tokens.filter(token => {
90+
const tokens = tokenizer.tokenizeForSentence(sentence.raw);
91+
// 助詞 + 助詞は 一つの助詞として扱う
92+
// https://github.com/textlint-ja/textlint-rule-no-doubled-joshi/issues/15
93+
// 連語(助詞)の対応
94+
// http://www.weblio.jp/parts-of-speech/%E9%80%A3%E8%AA%9E(%E5%8A%A9%E8%A9%9E)_1
95+
const concatTokens = concatJoishiTokens(tokens);
96+
const countableTokens = concatTokens.filter(token => {
9197
if (isStrict) {
9298
return is助詞Token(token);
9399
}
@@ -96,14 +102,14 @@ export default function(context, options = {}) {
96102
// https://github.com/azu/textlint-rule-no-doubled-joshi/issues/2
97103
return is助詞Token(token) || is読点Token(token);
98104
});
99-
let joshiTokenSurfaceKeyMap = createSurfaceKeyMap(countableTokens);
105+
const joshiTokenSurfaceKeyMap = createSurfaceKeyMap(countableTokens);
100106
/*
101107
# Data Structure
102108
103109
joshiTokens = [tokenA, tokenB, tokenC, tokenD, tokenE, tokenF]
104110
joshiTokenSurfaceKeyMap = {
105-
"は:助詞.係助詞": [tokenA, tokenC, tokenE],
106-
"で:助詞.係助詞": [tokenB, tokenD, tokenF]
111+
"は:助詞.係助詞": [tokenA, tokenC, tokenE],
112+
"で:助詞.係助詞": [tokenB, tokenD, tokenF]
107113
}
108114
*/
109115
Object.keys(joshiTokenSurfaceKeyMap).forEach(key => {

src/token-utils.js

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,48 @@
22
"use strict";
33
// 助詞どうか
44
export const is助詞Token = (token) => {
5-
return token.pos === "助詞";
5+
// 結合しているtokenは助詞助詞のようになってるため先頭一致で見る
6+
return token && /^/.test(token.pos);
67
};
78

89
export const is読点Token = (token) => {
910
return token.surface_form === "、" && token.pos === "名詞";
1011
};
11-
12+
/**
13+
* aTokenの_extraKeyに結合したkeyを追加する
14+
* @param {Object} aToken
15+
* @param {Object} bToken
16+
* @returns {Object}
17+
*/
18+
const concatToken = (aToken, bToken) => {
19+
aToken.surface_form += bToken.surface_form;
20+
aToken.pos += bToken.pos;
21+
aToken.pos_detail_1 += bToken.surface_form;
22+
return aToken;
23+
};
24+
/**
25+
* 助詞+助詞 というように連続しているtokenを結合し直したtokenの配列を返す
26+
* @param {Array} tokens
27+
* @returns {Array}
28+
*/
29+
export const concatJoishiTokens = (tokens) => {
30+
const newTokens = [];
31+
tokens.forEach((token) => {
32+
const prevToken = newTokens[newTokens.length - 1];
33+
if (is助詞Token(token) && is助詞Token(prevToken)) {
34+
newTokens[newTokens.length - 1] = concatToken(prevToken, token);
35+
} else {
36+
newTokens.push(token);
37+
}
38+
});
39+
return newTokens;
40+
};
1241
// 助詞tokenから品詞細分類1までを元にしたkeyを作る
1342
// http://www.unixuser.org/~euske/doc/postag/index.html#chasen
1443
// http://chasen.naist.jp/snapshot/ipadic/ipadic/doc/ipadic-ja.pdf
1544
export const createKeyFromKey = (token) => {
1645
// e.g.) "は:助詞.係助詞"
17-
return `${token.surface_form}:${token.pos}.${token.pos_detail_1}`
46+
return `${token.surface_form}:${token.pos}.${token.pos_detail_1}`;
1847
};
1948
// keyからsurfaceを取り出す
2049
export const restoreToSurfaceFromKey = (key) => {

test/no-doubled-joshi-test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ tester.run("no-double-joshi", rule, {
1717
"ナイフで切断した後、ハンマーで破砕した。",
1818
// 接続助詞のてが重複は許容
1919
"まずは試していただいて",
20+
// **に**と**には**は別の助動詞と認識
21+
"そのため、文字列の長さを正確に測るにはある程度の妥協が必要になります。",
22+
"そんな事で言うべきではない。",
23+
"言うのは簡単の法則。",
2024
// 1個目の「と」は格助詞、2個めの「と」は接続助詞
2125
"ターミナルで「test」**と**入力する**と**、画面に表示されます。",
2226
{
@@ -161,6 +165,18 @@ tester.run("no-double-joshi", rule, {
161165
column: 38
162166
}
163167
]
168+
},
169+
{
170+
// に + は と に + は
171+
// https://github.com/textlint-ja/textlint-rule-no-doubled-joshi/issues/15
172+
text: "文字列にはそこには問題がある。",
173+
errors: [
174+
{
175+
message: `一文に二回以上利用されている助詞 "には" がみつかりました。`,
176+
line: 1,
177+
column: 8
178+
}
179+
]
164180
}
165181
]
166182
});

0 commit comments

Comments
 (0)