1+ import type { AnyTxtNode } from "@textlint/ast-node-types" ;
12import { matchPatterns } from "@textlint/regexp-string-matcher" ;
2- import type { TextlintRuleModule } from "@textlint/types" ;
3+ import type { TextlintRuleContext , TextlintRuleModule } from "@textlint/types" ;
34import { StringSource } from "textlint-util-to-string" ;
45
56/**
@@ -9,7 +10,7 @@ import { StringSource } from "textlint-util-to-string";
910 * https://github.com/textlint-ja/textlint-rule-preset-ai-writing/blob/main/docs/tech-writing-guidelines.md
1011 */
1112
12- export interface Options {
13+ type Options = {
1314 // If node's text includes allowed patterns, does not report.
1415 // Can be string or RegExp-like string ("/pattern/flags")
1516 allows ?: string [ ] ;
@@ -21,9 +22,9 @@ export interface Options {
2122 disableStructureGuidance ?: boolean ;
2223 // Enable document-level analysis
2324 enableDocumentAnalysis ?: boolean ;
24- }
25+ } ;
2526
26- const rule : TextlintRuleModule < Options > = ( context , options = { } ) => {
27+ const rule : TextlintRuleModule < Options > = ( context : TextlintRuleContext , options = { } ) => {
2728 const { Syntax, report, locator } = context ;
2829 const allows = options . allows ?? [ ] ;
2930 const disableRedundancyGuidance = options . disableRedundancyGuidance ?? false ;
@@ -190,8 +191,9 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
190191 * 機械的な段落と箇条書きの組み合わせパターンを検出
191192 * 注意: コロン関連のパターンは no-ai-colon-continuation ルールで処理されます
192193 */
193- const detectMechanicalListIntroPattern = ( node : any ) => {
194- const children = node . children || [ ] ;
194+ const detectMechanicalListIntroPattern = ( node : AnyTxtNode ) => {
195+ const nodeObj = node as AnyTxtNode & { children ?: AnyTxtNode [ ] } ;
196+ const children = nodeObj . children || [ ] ;
195197
196198 for ( let i = 0 ; i < children . length - 1 ; i ++ ) {
197199 const currentNode = children [ i ] ;
@@ -200,7 +202,7 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
200202 // Paragraph → List のパターンを検出
201203 if ( currentNode . type === "Paragraph" && nextNode . type === "List" ) {
202204 // Paragraphの最後の文字列ノードを取得
203- const paragraphSource = new StringSource ( currentNode , {
205+ const paragraphSource = new StringSource ( currentNode as never , {
204206 replacer ( { node, emptyValue } ) {
205207 if ( node . type === "Code" || node . type === "InlineCode" ) {
206208 return emptyValue ( ) ;
@@ -217,7 +219,9 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
217219 // 注意: コロンパターンは no-ai-colon-continuation で処理されるため削除
218220
219221 // パターン: 「例えば。」「具体的には。」など、接続表現+句点で終わる段落
220- if ( / (?: 例 え ば | 具 体 的 に は | 詳 細 に は | 以 下 | 次 に | ま た ) 。 [ \s ] * $ / . test ( paragraphText . trim ( ) ) ) {
222+ const connectivePattern = / (?: 例 え ば | 具 体 的 に は | 詳 細 に は | 以 下 | 次 に | ま た ) 。 [ \s ] * $ / ;
223+ const connectiveMatch = paragraphText . trim ( ) . match ( connectivePattern ) ;
224+ if ( connectiveMatch ) {
221225 isDetected = true ;
222226 message =
223227 "【構造化】接続表現と句点で終わる文の直後の箇条書きは機械的な印象を与える可能性があります。「たとえば、次のような点があります。」のような自然な導入文を検討してください。" ;
@@ -246,7 +250,7 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
246250 /**
247251 * 構造化ガイダンスに関する文書レベルの検出処理
248252 */
249- const processDocumentStructureGuidance = ( node : any ) => {
253+ const processDocumentStructureGuidance = ( node : AnyTxtNode ) => {
250254 if ( disableStructureGuidance ) {
251255 return ;
252256 }
@@ -265,9 +269,9 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
265269 /**
266270 * 段落内のガイダンスパターンを検出・報告
267271 */
268- const processParagraphGuidance = ( node : any ) => {
272+ const processParagraphGuidance = ( node : AnyTxtNode ) => {
269273 // StringSourceを使用してコードブロックを除外したテキストを取得
270- const source = new StringSource ( node , {
274+ const source = new StringSource ( node as never , {
271275 replacer ( { node, emptyValue } ) {
272276 // コードブロック、インラインコードを除外
273277 if ( node . type === "Code" || node . type === "InlineCode" ) {
@@ -298,13 +302,13 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
298302 for ( const { pattern, message, category } of allGuidancePatterns ) {
299303 const matches = text . matchAll ( pattern ) ;
300304 for ( const match of matches ) {
301- const index = match . index ?? 0 ;
305+ const index : number = match . index ?? 0 ;
302306
303307 // プレーンテキストの位置を元のノード内の位置に変換
304308 const originalIndex = source . originalIndexFromIndex ( index ) ;
305309 const originalEndIndex = source . originalIndexFromIndex ( index + match [ 0 ] . length ) ;
306310
307- if ( originalIndex !== undefined && originalEndIndex !== undefined ) {
311+ if ( typeof originalIndex === "number" && typeof originalEndIndex === "number" ) {
308312 const originalRange = [ originalIndex , originalEndIndex ] as const ;
309313
310314 // カテゴリ別のメトリクスを更新
@@ -323,7 +327,7 @@ const rule: TextlintRuleModule<Options> = (context, options = {}) => {
323327 /**
324328 * 文書全体の品質分析結果を報告
325329 */
326- const processDocumentAnalysis = ( node : any ) => {
330+ const processDocumentAnalysis = ( node : AnyTxtNode ) => {
327331 // 文書全体の分析を実行(enableDocumentAnalysisがtrueの場合)
328332 if ( enableDocumentAnalysis && hasDocumentIssues ) {
329333 const totalIssues = Object . values ( documentQualityMetrics ) . reduce ( ( sum , count ) => sum + count , 0 ) ;
0 commit comments