Skip to content

Commit 2e35940

Browse files
committed
feat(rule): RegExp-like Stringをサポート
1 parent 754497f commit 2e35940

File tree

5 files changed

+2716
-34
lines changed

5 files changed

+2716
-34
lines changed

README.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
IMEの入力ミスによるtypoを見つけるルールです。
66

7+
`{日本語}{アルファベット}{日本語}`のように不自然な形でアルファベットが登場した場合をチェックしていないかをチェックしています。
8+
79
## Example
810

911
**OK**:
@@ -51,7 +53,7 @@ textlint --rule ja-unnatural-alphabet README.md
5153
- 無視するアルファベットや単語の配列
5254
- デフォルト: `["a", "i", "u", "e", "o", "n", 典型例 ]`
5355
- デフォルトでは母音とnを除外している
54-
- `"/正規表現/"` のような文字列もサポート
56+
- `"/正規表現/"` のような[RegExp-like String](https://github.com/textlint/regexp-string-matcher#regexp-like-string)もサポートしています
5557

5658
```json5
5759
{
@@ -67,6 +69,36 @@ textlint --rule ja-unnatural-alphabet README.md
6769
}
6870
```
6971

72+
### `allow`: `string[]`
73+
74+
`allow`オプションには、エラーとしたくない文字列または[RegExp-like String](https://github.com/textlint/regexp-string-matcher#regexp-like-string)を指定できます。
75+
[RegExp-like String](https://github.com/textlint/regexp-string-matcher#regexp-like-string)についての詳細は次を参照してください。
76+
77+
- [textlint/regexp-string-matcher: Regexp-like string matcher.](https://github.com/textlint/regexp-string-matcher#regexp-like-string)
78+
79+
たとえば、`アンドロイドNを購入する`という文章は`{日本語}{アルファベット}{日本語}`のルールに該当するためエラーとなりますが、`allow`オプションでは問題として無視できます。
80+
81+
```json5
82+
{
83+
// 無視する設定を追加
84+
"allow": [
85+
"アンドロイドN"
86+
]
87+
}
88+
```
89+
90+
同様に[RegExp-like String](https://github.com/textlint/regexp-string-matcher#regexp-like-string)を使うことで、`allow`オプションに正規表現での指定が可能です。
91+
次の設定は`アンドロイド{アルファベット}`は問題ないとしてエラーにしません。
92+
93+
```json5
94+
{
95+
"allow": [
96+
// RegExp-like String は `/` と `/` で囲む
97+
"/アンドロイド[a-zA-Z]/"
98+
]
99+
}
100+
```
101+
70102
## 参考文献
71103

72104
> (3) 不自然なアルファベット

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"textlint-scripts": "^1.2.2"
3535
},
3636
"dependencies": {
37-
"escape-string-regexp": "^1.0.5",
37+
"@textlint/regexp-string-matcher": "^1.0.2",
3838
"match-index": "^1.0.1",
3939
"regx": "^1.0.4"
4040
}

src/textlint-rule-ja-unnatural-alphabet.js

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MIT © 2017 azu
22
"use strict";
3-
const escapeStringRegexp = require('escape-string-regexp');
3+
const { matchPatterns } = require("@textlint/regexp-string-matcher");
44
const matchCaptureGroupAll = require("match-index").matchCaptureGroupAll;
55
const regx = require("regx").default;
66
// IME的に入力されそうな文字列
@@ -23,40 +23,16 @@ const matchUnnaturalAlphabet = (text) => {
2323
};
2424

2525
/**
26-
* if actual is in the `exceptGroups`, return true
27-
* @param {MatchCaptureGroup[]} exceptGroups
26+
* if actual is in the `matchPatternResults`, return true
27+
* @param {matchPatternResult[]} matchPatternResults
2828
* @param {MatchCaptureGroup} actual
2929
* @returns {boolean}
3030
*/
31-
const isIgnoredRange = (exceptGroups, actual) => {
32-
return exceptGroups.some(({ text, index }) => {
33-
const endIndex = index + text.length;
34-
return index <= actual.index && actual.index <= endIndex;
31+
const isIgnoredRange = (matchPatternResults, actual) => {
32+
return matchPatternResults.some(result => {
33+
return result.startIndex <= actual.index && actual.index <= result.endIndex;
3534
});
3635
};
37-
/***
38-
*
39-
* @param {string} input
40-
* @param {string[]} allowAlphabets
41-
* @returns {MatchCaptureGroup[]}
42-
*/
43-
const createIgnoreRanges = (input, allowAlphabets) => {
44-
// str -> RegExp
45-
const patterns = allowAlphabets.map(allowWord => {
46-
if (!allowWord) {
47-
return /^$/;
48-
}
49-
if (allowWord[0] === "/" && allowWord[allowWord.length - 1] === "/") {
50-
const regExpString = allowWord.slice(1, allowWord.length - 1);
51-
return new RegExp(`(${regExpString})`, "g");
52-
}
53-
const escapeString = escapeStringRegexp(allowWord);
54-
return new RegExp(`(${escapeString})`, "g");
55-
});
56-
return patterns.reduce((total, pattern) => {
57-
return total.concat(matchCaptureGroupAll(input, pattern));
58-
}, []);
59-
};
6036

6137
/**
6238
* ビルトインの無視するリスト
@@ -89,7 +65,7 @@ const report = (context, options = {}) => {
8965
return {
9066
[Syntax.Str](node){
9167
const text = getSource(node);
92-
const ignoreMatch = createIgnoreRanges(text, allow);
68+
const ignoreMatch = matchPatterns(text, allow);
9369
matchUnnaturalAlphabet(text).forEach((actual) => {
9470
const { text, index } = actual;
9571
// 無視する単語を含んでいるなら無視

test/textlint-rule-ja-unnatural-alphabet-test.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ tester.run("textlint-rule-ja-unnatural-alphabet", rule, {
2020
options: {
2121
allow: ["N"]
2222
}
23+
}, {
24+
text: "アンドロイドNは良し",
25+
options: {
26+
allow: ["アンドロイドN"]
27+
}
28+
}, {
29+
text: "アンドロイドNは良し",
30+
options: {
31+
allow: ["/アンドロイド[a-zA-Z]/"]
32+
}
2333
}
2434
],
2535
invalid: [
@@ -48,4 +58,4 @@ tester.run("textlint-rule-ja-unnatural-alphabet", rule, {
4858
]
4959
}
5060
]
51-
});
61+
});

0 commit comments

Comments
 (0)