Skip to content

Commit 58f604c

Browse files
committed
fix: StringSourceを使用してコードブロックを除外し、エラー件数の一致を改善
- textlint-util-to-stringのStringSourceを使用してコードブロック(Code, InlineCode)を除外 - analyzeDocumentQuality関数を修正して全体とカテゴリのエラー件数を一致させる - originalIndexFromIndexを使用して正確な位置マッピングを実装 - README.mdの例文がコードブロック内で正しく除外されることを確認
1 parent 0e1ed81 commit 58f604c

File tree

5 files changed

+66
-44
lines changed

5 files changed

+66
-44
lines changed

.textlintrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"rules": {
3+
"preset-ai-writing": {
4+
"ai-tech-writing-guideline": {
5+
"severity": "info"
6+
}
7+
}
8+
}
9+
}

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,17 @@ AIが機械的に生成しがちな強調パターンを検出します。
4040
テクニカルライティングのベストプラクティスに基づいて、文書品質の改善提案を行います。
4141
詳細なガイドラインについては [docs/tech-writing-guidelines.md](./docs/tech-writing-guidelines.md) を参照してください。
4242

43+
#### 推奨する組み合わせ
44+
このルールは [textlint-rule-preset-ja-technical-writing](https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing) との組み合わせを推奨します。
45+
`ja-technical-writing` はfalse positiveが少ない確実なルールセットで、基本的な日本語技術文書の品質を担保します。
46+
本ルール(`ai-tech-writing-guideline`)は、より高度な文書品質向上のためのサジェストとして使用することを想定しています。
47+
4348
#### 検出される内容
44-
- 簡潔性: 冗長表現の排除(「まず」→「まず」など)
49+
- 簡潔性: 冗長表現の排除
50+
```
51+
まず最初に → まず
52+
〜することができます → 〜します
53+
```
4554
- 明確性: 能動態の使用推奨(受動態から能動態への変更提案)
4655
- 具体性: 抽象的表現の具体化(「高速な」→「50ms未満の」など)
4756
- 一貫性: 用語と表現の統一(同一対象への異なる用語使用の検出)
@@ -190,6 +199,25 @@ Via `.textlintrc`(Recommended)
190199
}
191200
```
192201

202+
### 推奨構成: ja-technical-writing との組み合わせ
203+
204+
基本的な日本語技術文書の品質担保と、より高度な文書品質向上の組み合わせ:
205+
206+
```json
207+
{
208+
"rules": {
209+
"preset-ja-technical-writing": true,
210+
"preset-ai-writing": {
211+
"ai-tech-writing-guideline": {
212+
"severity": "info"
213+
}
214+
}
215+
}
216+
}
217+
```
218+
219+
この構成では、`ja-technical-writing` で確実な問題を修正し、`ai-tech-writing-guideline` でさらなる改善提案を受け取ることができます。
220+
193221
## Options
194222

195223
各ルールに対して個別にオプションを設定できます。

package-lock.json

Lines changed: 2 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@
6868
"access": "public"
6969
},
7070
"dependencies": {
71-
"@textlint/regexp-string-matcher": "^2.0.2"
71+
"@textlint/regexp-string-matcher": "^2.0.2",
72+
"textlint-util-to-string": "^3.3.4"
7273
},
7374
"packageManager": "npm@10.9.2+sha512.8ab88f10f224a0c614cb717a7f7c30499014f77134120e9c1f0211ea3cf3397592cbe483feb38e0c4b3be1c54e347292c76a1b5edb94a3289d5448484ab8ac81"
7475
}

src/rules/ai-tech-writing-guideline.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { TextlintRuleModule } from "@textlint/types";
22
import { matchPatterns } from "@textlint/regexp-string-matcher";
3+
import { StringSource } from "textlint-util-to-string";
34

45
/**
56
* テクニカルライティングガイドラインに基づく文書品質改善ルール
@@ -23,7 +24,7 @@ export interface Options {
2324
}
2425

2526
const rule: TextlintRuleModule<Options> = (context, options = {}) => {
26-
const { Syntax, report, getSource, locator } = context;
27+
const { Syntax, report, locator } = context;
2728
const allows = options.allows ?? [];
2829
const disableRedundancyGuidance = options.disableRedundancyGuidance ?? false;
2930
const disableVoiceGuidance = options.disableVoiceGuidance ?? false;
@@ -188,8 +189,8 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
188189
[Syntax.Document](node) {
189190
// 文書全体の分析を実行(enableDocumentAnalysisがtrueの場合)
190191
if (enableDocumentAnalysis) {
191-
const documentText = getSource(node);
192-
const totalIssues = analyzeDocumentQuality(documentText);
192+
const source = new StringSource(node);
193+
const totalIssues = analyzeDocumentQuality(source.toString());
193194

194195
if (totalIssues > 0) {
195196
report(node, {
@@ -199,7 +200,8 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
199200
}
200201
},
201202
[Syntax.Paragraph](node) {
202-
const text = getSource(node);
203+
const source = new StringSource(node);
204+
const text = source.toString();
203205

204206
// 許可パターンのチェック
205207
if (allows.length > 0) {
@@ -222,15 +224,19 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
222224
const matches = text.matchAll(pattern);
223225
for (const match of matches) {
224226
const index = match.index ?? 0;
225-
const matchRange = [index, index + match[0].length] as const;
227+
const originalPosition = source.originalIndexFromIndex(index);
228+
const originalEndPosition = source.originalIndexFromIndex(index + match[0].length);
226229

227230
// カテゴリ別のメトリクスを更新
228231
documentQualityMetrics[category as keyof typeof documentQualityMetrics]++;
229232

230-
report(node, {
231-
message: message,
232-
padding: locator.range(matchRange)
233-
});
233+
if (originalPosition !== undefined && originalEndPosition !== undefined) {
234+
const matchRange = [originalPosition, originalEndPosition] as const;
235+
report(node, {
236+
message: message,
237+
padding: locator.range(matchRange)
238+
});
239+
}
234240
}
235241
}
236242
}
@@ -239,15 +245,17 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
239245
// 文書全体の品質分析関数
240246
function analyzeDocumentQuality(text: string): number {
241247
let totalIssues = 0;
242-
const allPatterns = [
243-
...redundancyGuidance,
244-
...voiceGuidance,
245-
...clarityGuidance,
246-
...consistencyGuidance,
247-
...structureGuidance
248+
249+
// コードブロックを除外して分析するためのパターンリスト
250+
const guidancePatterns = [
251+
...(disableRedundancyGuidance ? [] : redundancyGuidance),
252+
...(disableVoiceGuidance ? [] : voiceGuidance),
253+
...(disableClarityGuidance ? [] : clarityGuidance),
254+
...(disableConsistencyGuidance ? [] : consistencyGuidance),
255+
...(disableStructureGuidance ? [] : structureGuidance)
248256
];
249257

250-
for (const { pattern } of allPatterns) {
258+
for (const { pattern } of guidancePatterns) {
251259
const matches = text.matchAll(pattern);
252260
totalIssues += Array.from(matches).length;
253261
}

0 commit comments

Comments
 (0)