Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ textlint --rule @textlint-ja/no-synonyms README.md
* 例) ["ウェブアプリ", "ウェブアプリケーション"]
*/
allows?: string[];
/**
* 使用を許可する見出し語の配列
* 定義された見出し語以外の同義語をエラーにします
* 例) ["ユーザー"] // => 「ユーザー」だけ許可し「ユーザ」などはエラーにする
*/
preferWords?: string[];
/**
* 同じ語形の語の中でのアルファベットの表記揺れを許可するかどうか
* trueの場合はカタカナとアルファベットの表記ゆれを許可します
Expand All @@ -80,6 +86,7 @@ textlint --rule @textlint-ja/no-synonyms README.md
"rules": {
"@textlint-ja/no-synonyms": {
"allows": ["ウェブアプリ", "ウェブアプリケーション"],
"preferWords": ["ユーザー"],
"allowAlphabet": false,
"allowNumber": false
}
Expand Down
4 changes: 4 additions & 0 deletions src/create-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export class ItemGroup {

}

getItem(midashi: string): SudachiSynonyms | null {
return this.items.find(item => item.midashi === midashi) ?? null
}

usedItems(usedItemSet: Set<SudachiSynonyms>, { allowAlphabet, allowNumber, allows }: { allowAlphabet: boolean; allowNumber: boolean; allows: string[] }): SudachiSynonyms[] {
// sort by used
return Array.from(usedItemSet.values()).filter(item => {
Expand Down
29 changes: 26 additions & 3 deletions src/textlint-rule-no-synonyms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export interface Options {
* 例) ["ウェブアプリ", "ウェブアプリケーション"]
*/
allows?: string[];
/**
* 使用を許可する見出し語の配列
* 定義された見出し語以外の同義語をエラーにします
* 例) ["ユーザー"] // => 「ユーザー」だけ許可し「ユーザ」などはエラーにする
*/
preferWords?: string[];
/**
* 同じ語形の語の中でのアルファベットの表記揺れを許可するかどうか
* trueの場合はカタカナとアルファベットの表記ゆれを許可します
Expand All @@ -32,6 +38,7 @@ export interface Options {

export const DefaultOptions: Required<Options> = {
allows: [],
preferWords: [],
allowAlphabet: true,
allowNumber: true
};
Expand All @@ -40,7 +47,8 @@ const report: TextlintRuleReporter<Options> = (context, options = {}) => {
const allowAlphabet = options.allowAlphabet ?? DefaultOptions.allowAlphabet;
const allowNumber = options.allowNumber ?? DefaultOptions.allowNumber;
const allows = options.allows !== undefined ? options.allows : DefaultOptions.allows;
const { Syntax, getSource, RuleError } = context;
const preferWords = options.preferWords !== undefined ? options.preferWords : DefaultOptions.preferWords;
const { Syntax, getSource, RuleError, fixer } = context;
const usedSudachiSynonyms: Set<SudachiSynonyms> = new Set();
const locationMap: Map<SudachiSynonyms, { index: number }> = new Map();
const usedItemGroup: Set<ItemGroup> = new Set();
Expand Down Expand Up @@ -87,7 +95,19 @@ const report: TextlintRuleReporter<Options> = (context, options = {}) => {
allowAlphabet,
allowNumber
});
if (items.length >= 2) {
const preferWord = preferWords.find(midashi => itemGroup.getItem(midashi))
if (preferWord) {
const deniedItems = items.filter(item => item.midashi !== preferWord)
for (const item of deniedItems) {
const index = locationMap.get(item)?.index ?? 0;
const deniedWord = item.midashi
const message = `「${preferWord}」の同義語である「${deniedWord}」が利用されています`;
report(node, new RuleError(message, {
index,
fix: fixer.replaceTextRange([index, index + deniedWord.length], preferWord),
}));
}
} else if (items.length >= 2) {
const 同義の見出しList = items.map(item => item.midashi);
// select last used
const matchSegment = locationMap.get(items[items.length - 1]);
Expand All @@ -104,4 +124,7 @@ const report: TextlintRuleReporter<Options> = (context, options = {}) => {
);
};

export default report;
export default {
linter: report,
fixer: report,
};
49 changes: 47 additions & 2 deletions test/textlint-rule-no-synonyms.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ tester.run("textlint-rule-no-synonyms", rule, {
options: {
allows: ["ウェブアプリ"] // <= 片方が許可されていればOK
}
}
},
// preferWords
{
text: `ユーザーだけに統一されていればユーザーは許容する`,
options: {
preferWords: ["ユーザー"]
}
},
],
invalid: [{
text: "サーバとサーバーの表記揺れがある",
Expand Down Expand Up @@ -58,5 +65,43 @@ tester.run("textlint-rule-no-synonyms", rule, {
message: "同義語である「1」と「一」が利用されています",
index: 5
}]
}]
},
{
text: "ユーザーは許可しユーザはエラー。allowAlphabetがtrueならuserはエラーにならない",
output: "ユーザーは許可しユーザーはエラー。allowAlphabetがtrueならuserはエラーにならない",
options: {
preferWords: ["ユーザー"]
},
errors: [{
message: "「ユーザー」の同義語である「ユーザ」が利用されています",
index: 8
}]
},
{
text: "ユーザーは許可しallowAlphabetがfalseならユーザもuserもエラー",
output: "ユーザーは許可しallowAlphabetがfalseならユーザーもユーザーもエラー",
options: {
preferWords: ["ユーザー"],
allowAlphabet: false
},
errors: [{
message: "「ユーザー」の同義語である「ユーザ」が利用されています",
index: 29
}, {
message: "「ユーザー」の同義語である「user」が利用されています",
index: 33
}]
},
{
text: "ユーザはエラー",
output: "ユーザーはエラー",
options: {
preferWords: ["ユーザー"]
},
errors: [{
message: "「ユーザー」の同義語である「ユーザ」が利用されています",
index: 0
}]
},
]
});