Skip to content

Commit 7a2deb7

Browse files
authored
feat: add allowLexeme option (#12)
1 parent 8b76cb5 commit 7a2deb7

File tree

4 files changed

+92
-10
lines changed

4 files changed

+92
-10
lines changed

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ textlint --rule @textlint-ja/no-synonyms README.md
7676
* Default: true
7777
*/
7878
allowNumber?: boolean;
79+
/**
80+
* 語彙素の異なる同義語を許可するかどうか
81+
* trueの場合は語彙素の異なる同義語を許可します
82+
* 例) 「ルーム」と「部屋」
83+
* Default: true
84+
*/
85+
allowLexeme?: boolean;
7986
}
8087
```
8188

@@ -88,7 +95,8 @@ textlint --rule @textlint-ja/no-synonyms README.md
8895
"allows": ["ウェブアプリ", "ウェブアプリケーション"],
8996
"preferWords": ["ユーザー"],
9097
"allowAlphabet": false,
91-
"allowNumber": false
98+
"allowNumber": false,
99+
"allowLexeme": false
92100
}
93101
}
94102
}

src/create-index.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,20 @@ export type IndexType = {
6969
keyItemGroupMap: Map<Midashi, ItemGroup[]>;
7070
SudachiSynonymsItemGroup: Map<SudachiSynonyms, ItemGroup>;
7171
};
72-
let _ret: IndexType | null = null;
73-
export const createIndex = async (): Promise<IndexType> => {
74-
if (_ret) {
75-
return Promise.resolve(_ret);
72+
const _cache = new Map<boolean, IndexType>();
73+
const firstVocabularyNumber = 1;
74+
export const createIndex = async ({ allowLexeme }: { allowLexeme: boolean }): Promise<IndexType> => {
75+
if (_cache.has(allowLexeme)) {
76+
return Promise.resolve(_cache.get(allowLexeme)!);
7677
}
7778
assertInstallationSudachiSynonymsDictionary();
7879
const keyItemGroupMap: Map<Midashi, ItemGroup[]> = new Map();
7980
const SudachiSynonymsItemGroup: Map<SudachiSynonyms, ItemGroup> = new Map();
8081
const SynonymsDictionary = await fetchDictionary();
8182
SynonymsDictionary.forEach((group) => {
8283
const groupByVocabularyNumber = group.items.reduce((res, item) => {
83-
res[item.vocabularyNumber!] = (res[item.vocabularyNumber!] || []).concat(item);
84+
const vocabularyNumber = allowLexeme ? item.vocabularyNumber! : firstVocabularyNumber;
85+
res[vocabularyNumber] = (res[vocabularyNumber] || []).concat(item);
8486
return res;
8587
}, {} as { [index: string]: SudachiSynonyms[] });
8688
const itemGroups = Object.values(groupByVocabularyNumber)
@@ -99,9 +101,10 @@ export const createIndex = async (): Promise<IndexType> => {
99101
});
100102
});
101103
});
102-
_ret = {
104+
const _ret = {
103105
keyItemGroupMap,
104106
SudachiSynonymsItemGroup
105107
};
108+
_cache.set(allowLexeme, _ret);
106109
return Promise.resolve(_ret);
107110
};

src/textlint-rule-no-synonyms.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,34 @@ export interface Options {
3333
* Default: true
3434
*/
3535
allowNumber?: boolean;
36+
/**
37+
* 語彙素の異なる同義語を許可するかどうか
38+
* trueの場合は語彙素の異なる同義語を許可します
39+
* 例) 「ルーム」と「部屋」
40+
* Default: true
41+
*/
42+
allowLexeme?: boolean;
3643
}
3744

3845
export const DefaultOptions: Required<Options> = {
3946
allows: [],
4047
preferWords: [],
4148
allowAlphabet: true,
42-
allowNumber: true
49+
allowNumber: true,
50+
allowLexeme: true
4351
};
4452

4553
const report: TextlintRuleReporter<Options> = (context, options = {}) => {
4654
const allowAlphabet = options.allowAlphabet ?? DefaultOptions.allowAlphabet;
4755
const allowNumber = options.allowNumber ?? DefaultOptions.allowNumber;
56+
const allowLexeme = options.allowLexeme ?? DefaultOptions.allowLexeme;
4857
const allows = options.allows !== undefined ? options.allows : DefaultOptions.allows;
4958
const preferWords = options.preferWords !== undefined ? options.preferWords : DefaultOptions.preferWords;
5059
const { Syntax, getSource, RuleError, fixer } = context;
5160
const usedSudachiSynonyms: Set<SudachiSynonyms> = new Set();
5261
const locationMap: Map<SudachiSynonyms, { index: number }> = new Map();
5362
const usedItemGroup: Set<ItemGroup> = new Set();
54-
const indexPromise = createIndex();
63+
const indexPromise = createIndex({ allowLexeme });
5564
const matchSegment = (segment: string, absoluteIndex: number, keyItemGroupMap: Map<Midashi, ItemGroup[]>) => {
5665
const itemGroups = keyItemGroupMap.get(segment);
5766
if (!itemGroups) {
@@ -104,7 +113,8 @@ const report: TextlintRuleReporter<Options> = (context, options = {}) => {
104113
allowNumber
105114
});
106115
const preferWord = preferWords.find((midashi) => itemGroup.getItem(midashi));
107-
if (preferWord) {
116+
const allowed = allows.find((midashi) => itemGroup.getItem(midashi));
117+
if (preferWord && !allowed) {
108118
const deniedItems = items.filter((item) => item.midashi !== preferWord);
109119
for (const item of deniedItems) {
110120
const index = locationMap.get(item)?.index ?? 0;

test/textlint-rule-no-synonyms.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,28 @@ tester.run("textlint-rule-no-synonyms", rule, {
3131
options: {
3232
preferWords: ["ユーザー"]
3333
}
34+
},
35+
// allowLexeme
36+
{
37+
text: "部屋の同義語はルームです",
38+
options: {
39+
allowLexeme: true
40+
}
41+
},
42+
{
43+
text: "部屋の英語はroomです",
44+
options: {
45+
allowLexeme: false,
46+
allowAlphabet: true
47+
}
48+
},
49+
{
50+
text: "部屋の英語はroomです",
51+
options: {
52+
allowLexeme: false,
53+
allowAlphabet: false,
54+
allows: ["部屋"] // <= 片方が許可されていればOK
55+
}
3456
}
3557
],
3658
invalid: [
@@ -76,6 +98,31 @@ tester.run("textlint-rule-no-synonyms", rule, {
7698
}
7799
]
78100
},
101+
{
102+
text: "部屋のカタカナ英語はルームです",
103+
options: {
104+
allowLexeme: false
105+
},
106+
errors: [
107+
{
108+
message: "同義語である「部屋」と「ルーム」が利用されています",
109+
index: 10
110+
}
111+
]
112+
},
113+
{
114+
text: "部屋の英語はroomです",
115+
options: {
116+
allowAlphabet: false,
117+
allowLexeme: false
118+
},
119+
errors: [
120+
{
121+
message: "同義語である「部屋」と「room」が利用されています",
122+
index: 6
123+
}
124+
]
125+
},
79126
{
80127
text: "ユーザーは許可しユーザはエラー。allowAlphabetがtrueならuserはエラーにならない",
81128
output: "ユーザーは許可しユーザーはエラー。allowAlphabetがtrueならuserはエラーにならない",
@@ -119,6 +166,20 @@ tester.run("textlint-rule-no-synonyms", rule, {
119166
index: 0
120167
}
121168
]
169+
},
170+
{
171+
text: "ルームは許可しallowLexemeがfalseなら部屋もエラー",
172+
output: "ルームは許可しallowLexemeがfalseならルームもエラー",
173+
options: {
174+
preferWords: ["ルーム"],
175+
allowLexeme: false
176+
},
177+
errors: [
178+
{
179+
message: "「ルーム」の同義語である「部屋」が利用されています",
180+
index: 26
181+
}
182+
]
122183
}
123184
]
124185
});

0 commit comments

Comments
 (0)