Skip to content

Commit 7ba481a

Browse files
authored
feat: add preferWords option (#9)
1 parent ac82f19 commit 7ba481a

File tree

4 files changed

+84
-5
lines changed

4 files changed

+84
-5
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ textlint --rule @textlint-ja/no-synonyms README.md
5656
* 例) ["ウェブアプリ", "ウェブアプリケーション"]
5757
*/
5858
allows?: string[];
59+
/**
60+
* 使用を許可する見出し語の配列
61+
* 定義された見出し語以外の同義語をエラーにします
62+
* 例) ["ユーザー"] // => 「ユーザー」だけ許可し「ユーザ」などはエラーにする
63+
*/
64+
preferWords?: string[];
5965
/**
6066
* 同じ語形の語の中でのアルファベットの表記揺れを許可するかどうか
6167
* trueの場合はカタカナとアルファベットの表記ゆれを許可します
@@ -80,6 +86,7 @@ textlint --rule @textlint-ja/no-synonyms README.md
8086
"rules": {
8187
"@textlint-ja/no-synonyms": {
8288
"allows": ["ウェブアプリ", "ウェブアプリケーション"],
89+
"preferWords": ["ユーザー"],
8390
"allowAlphabet": false,
8491
"allowNumber": false
8592
}

src/create-index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export class ItemGroup {
1919

2020
}
2121

22+
getItem(midashi: string): SudachiSynonyms | null {
23+
return this.items.find(item => item.midashi === midashi) ?? null
24+
}
25+
2226
usedItems(usedItemSet: Set<SudachiSynonyms>, { allowAlphabet, allowNumber, allows }: { allowAlphabet: boolean; allowNumber: boolean; allows: string[] }): SudachiSynonyms[] {
2327
// sort by used
2428
return Array.from(usedItemSet.values()).filter(item => {

src/textlint-rule-no-synonyms.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export interface Options {
1313
* 例) ["ウェブアプリ", "ウェブアプリケーション"]
1414
*/
1515
allows?: string[];
16+
/**
17+
* 使用を許可する見出し語の配列
18+
* 定義された見出し語以外の同義語をエラーにします
19+
* 例) ["ユーザー"] // => 「ユーザー」だけ許可し「ユーザ」などはエラーにする
20+
*/
21+
preferWords?: string[];
1622
/**
1723
* 同じ語形の語の中でのアルファベットの表記揺れを許可するかどうか
1824
* trueの場合はカタカナとアルファベットの表記ゆれを許可します
@@ -32,6 +38,7 @@ export interface Options {
3238

3339
export const DefaultOptions: Required<Options> = {
3440
allows: [],
41+
preferWords: [],
3542
allowAlphabet: true,
3643
allowNumber: true
3744
};
@@ -40,7 +47,8 @@ const report: TextlintRuleReporter<Options> = (context, options = {}) => {
4047
const allowAlphabet = options.allowAlphabet ?? DefaultOptions.allowAlphabet;
4148
const allowNumber = options.allowNumber ?? DefaultOptions.allowNumber;
4249
const allows = options.allows !== undefined ? options.allows : DefaultOptions.allows;
43-
const { Syntax, getSource, RuleError } = context;
50+
const preferWords = options.preferWords !== undefined ? options.preferWords : DefaultOptions.preferWords;
51+
const { Syntax, getSource, RuleError, fixer } = context;
4452
const usedSudachiSynonyms: Set<SudachiSynonyms> = new Set();
4553
const locationMap: Map<SudachiSynonyms, { index: number }> = new Map();
4654
const usedItemGroup: Set<ItemGroup> = new Set();
@@ -87,7 +95,19 @@ const report: TextlintRuleReporter<Options> = (context, options = {}) => {
8795
allowAlphabet,
8896
allowNumber
8997
});
90-
if (items.length >= 2) {
98+
const preferWord = preferWords.find(midashi => itemGroup.getItem(midashi))
99+
if (preferWord) {
100+
const deniedItems = items.filter(item => item.midashi !== preferWord)
101+
for (const item of deniedItems) {
102+
const index = locationMap.get(item)?.index ?? 0;
103+
const deniedWord = item.midashi
104+
const message = `「${preferWord}」の同義語である「${deniedWord}」が利用されています`;
105+
report(node, new RuleError(message, {
106+
index,
107+
fix: fixer.replaceTextRange([index, index + deniedWord.length], preferWord),
108+
}));
109+
}
110+
} else if (items.length >= 2) {
91111
const 同義の見出しList = items.map(item => item.midashi);
92112
// select last used
93113
const matchSegment = locationMap.get(items[items.length - 1]);
@@ -104,4 +124,7 @@ const report: TextlintRuleReporter<Options> = (context, options = {}) => {
104124
);
105125
};
106126

107-
export default report;
127+
export default {
128+
linter: report,
129+
fixer: report,
130+
};

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

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ tester.run("textlint-rule-no-synonyms", rule, {
2424
options: {
2525
allows: ["ウェブアプリ"] // <= 片方が許可されていればOK
2626
}
27-
}
27+
},
28+
// preferWords
29+
{
30+
text: `ユーザーだけに統一されていればユーザーは許容する`,
31+
options: {
32+
preferWords: ["ユーザー"]
33+
}
34+
},
2835
],
2936
invalid: [{
3037
text: "サーバとサーバーの表記揺れがある",
@@ -58,5 +65,43 @@ tester.run("textlint-rule-no-synonyms", rule, {
5865
message: "同義語である「1」と「一」が利用されています",
5966
index: 5
6067
}]
61-
}]
68+
},
69+
{
70+
text: "ユーザーは許可しユーザはエラー。allowAlphabetがtrueならuserはエラーにならない",
71+
output: "ユーザーは許可しユーザーはエラー。allowAlphabetがtrueならuserはエラーにならない",
72+
options: {
73+
preferWords: ["ユーザー"]
74+
},
75+
errors: [{
76+
message: "「ユーザー」の同義語である「ユーザ」が利用されています",
77+
index: 8
78+
}]
79+
},
80+
{
81+
text: "ユーザーは許可しallowAlphabetがfalseならユーザもuserもエラー",
82+
output: "ユーザーは許可しallowAlphabetがfalseならユーザーもユーザーもエラー",
83+
options: {
84+
preferWords: ["ユーザー"],
85+
allowAlphabet: false
86+
},
87+
errors: [{
88+
message: "「ユーザー」の同義語である「ユーザ」が利用されています",
89+
index: 29
90+
}, {
91+
message: "「ユーザー」の同義語である「user」が利用されています",
92+
index: 33
93+
}]
94+
},
95+
{
96+
text: "ユーザはエラー",
97+
output: "ユーザーはエラー",
98+
options: {
99+
preferWords: ["ユーザー"]
100+
},
101+
errors: [{
102+
message: "「ユーザー」の同義語である「ユーザ」が利用されています",
103+
index: 0
104+
}]
105+
},
106+
]
62107
});

0 commit comments

Comments
 (0)