1- // ================ 类型定义 ================
1+ // ================ 类型定义 ================
22interface MatchPosition {
33 start : number ;
44 end : number ;
@@ -9,7 +9,7 @@ interface NormalizedContent {
99 mapping : number [ ] ;
1010}
1111
12- // ================ 核心实现 ================
12+ // ================ 核心实现 ================
1313const MAX_EDIT_DISTANCE = 5 ;
1414const SEGMENT_COUNT = MAX_EDIT_DISTANCE + 1 ;
1515
@@ -18,42 +18,42 @@ export function applyFuzzyGlobalReplace(
1818 strOldContent : string ,
1919 strNewContent : string
2020) : string {
21- // 第二阶段:模糊匹配流程
21+ // 第二阶段:模糊匹配流程
2222 const { content : normContent , mapping } = normalizeContent ( strContent ) ;
2323 const pattern = normalizePattern ( strOldContent ) ;
2424
25- // 分片查找候选位置
25+ // 分片查找候选位置
2626 const candidates = findCandidatePositions ( normContent , pattern ) ;
2727
28- // 验证并获取有效匹配
28+ // 验证并获取有效匹配
2929 const matches = verifyMatches ( normContent , pattern , candidates , mapping ) ;
3030
3131 if ( matches . length === 0 ) {
32- throw new Error ( `GLOBAL-REPLACE失败:未找到允许${ MAX_EDIT_DISTANCE } 个字符差异的匹配` ) ;
32+ throw new Error ( `GLOBAL-REPLACE失败:未找到允许${ MAX_EDIT_DISTANCE } 个字符差异的匹配` ) ;
3333 }
3434
35- // 应用替换
35+ // 应用替换
3636 return applyReplacements ( strContent , matches , strNewContent ) ;
3737}
3838
39- // ================ 算法核心模块 ================
39+ // ================ 算法核心模块 ================
4040export function normalizeContent ( original : string ) : { content : string ; mapping : number [ ] } {
41- // 第一步:去除注释
41+ // 第一步:去除注释
4242 const { content : noComments , mapping : mapping1 } = removeComments ( original ) ;
4343
44- // 第二步:去除符号前后的空格
44+ // 第二步:去除符号前后的空格
4545 const { content : noSymbolSpaces , mapping : mapping2 } = removeSymbolSpaces ( noComments ) ;
4646
47- // 第三步:将换行符改为空格,并合并连续的空格
47+ // 第三步:将换行符改为空格,并合并连续的空格
4848 const { content : finalContent , mapping : mapping3 } = normalizeWhitespace ( noSymbolSpaces ) ;
4949
50- // 合并 mapping
50+ // 合并 mapping
5151 const finalMapping = mapping3 . map ( idx => mapping2 [ idx ] ) . map ( idx => mapping1 [ idx ] ) ;
5252
5353 return { content : finalContent , mapping : finalMapping } ;
5454}
5555
56- // 辅助函数1:去除注释,并确保 mapping 数组严格对应每个输出字符(包括换行符)
56+ // 辅助函数1:去除注释,并确保 mapping 数组严格对应每个输出字符(包括换行符)
5757export function removeComments ( original : string ) : { content : string ; mapping : number [ ] } {
5858 const astrLines : string [ ] = original . split ( '\n' ) ;
5959 let strContent : string = "" ;
@@ -65,27 +65,27 @@ export function removeComments(original: string): { content: string; mapping: nu
6565 const nCommentIndex : number = strLine . indexOf ( '//' ) ;
6666 const strCleanLine : string = nCommentIndex !== - 1 ? strLine . slice ( 0 , nCommentIndex ) : strLine ;
6767
68- // 添加清理后的行内容,并记录映射
68+ // 添加清理后的行内容,并记录映射
6969 strContent += strCleanLine ;
7070 for ( let nI : number = 0 ; nI < strCleanLine . length ; nI ++ ) {
7171 arrMapping . push ( nCurrentPos + nI ) ;
7272 }
7373
74- // 只有在不是最后一行时添加换行符
74+ // 只有在不是最后一行时添加换行符
7575 if ( i < astrLines . length - 1 ) {
7676 strContent += "\n" ;
7777 arrMapping . push ( nCurrentPos + strLine . length ) ;
78- nCurrentPos += strLine . length + 1 ; // +1 表示换行符
78+ nCurrentPos += strLine . length + 1 ; // +1 表示换行符
7979 } else {
80- nCurrentPos += strLine . length ; // 最后一行没有换行符
80+ nCurrentPos += strLine . length ; // 最后一行没有换行符
8181 }
8282 }
8383 return { content : strContent , mapping : arrMapping } ;
8484}
8585
86- // 辅助函数2:去除符号前后的空格
86+ // 辅助函数2:去除符号前后的空格
8787export function removeSymbolSpaces ( strContentIn : string ) : { content : string ; mapping : number [ ] } {
88- // 更新正则表达式,匹配常见符号
88+ // 更新正则表达式,匹配常见符号
8989 const regSymbols : RegExp = / [ + \- / * ( ) \[ \] { } ; = , ' " ` ! & | ] / ;
9090 let strNewContent : string = "" ;
9191 const arrMapping : number [ ] = [ ] ;
@@ -94,59 +94,59 @@ export function removeSymbolSpaces(strContentIn: string): { content: string; map
9494 for ( let nI : number = 0 ; nI < nLen ; nI ++ ) {
9595 const strCurrentChar : string = strContentIn [ nI ] ;
9696
97- // 使用正则表达式匹配所有空白字符(空格、制表符、换行符等)
97+ // 使用正则表达式匹配所有空白字符(空格、制表符、换行符等)
9898 if ( / \s / . test ( strCurrentChar ) && strCurrentChar !== '\n' ) {
99- // 查找向左第一个非空白字符
99+ // 查找向左第一个非空白字符
100100 let nPrev : number = nI - 1 ;
101101 while ( nPrev >= 0 && / \s / . test ( strContentIn [ nPrev ] ) ) {
102102 nPrev -- ;
103103 }
104- // 查找向右第一个非空白字符
104+ // 查找向右第一个非空白字符
105105 let nNext : number = nI + 1 ;
106106 while ( nNext < nLen && / \s / . test ( strContentIn [ nNext ] ) ) {
107107 nNext ++ ;
108108 }
109109
110110 let bSkipSpace : boolean = false ;
111- // 如果前一个字符是符号,跳过当前空白字符
111+ // 如果前一个字符是符号,跳过当前空白字符
112112 if ( nPrev >= 0 && regSymbols . test ( strContentIn [ nPrev ] ) ) {
113113 bSkipSpace = true ;
114114 }
115- // 如果后一个字符是符号,跳过当前空白字符
115+ // 如果后一个字符是符号,跳过当前空白字符
116116 if ( nNext < nLen && regSymbols . test ( strContentIn [ nNext ] ) ) {
117117 bSkipSpace = true ;
118118 }
119119
120120 if ( bSkipSpace ) {
121- continue ; // 跳过符号附近的空白字符
121+ continue ; // 跳过符号附近的空白字符
122122 }
123123 }
124124
125- // 保留非空白字符或未跳过的空白字符
125+ // 保留非空白字符或未跳过的空白字符
126126 strNewContent += strCurrentChar ;
127127 arrMapping . push ( nI ) ;
128128 }
129129
130130 return { content : strNewContent , mapping : arrMapping } ;
131131}
132132
133- // 辅助函数3:将换行符改为空格,并合并连续的空格
133+ // 辅助函数3:将换行符改为空格,并合并连续的空格
134134export function normalizeWhitespace ( content : string ) : { content : string ; mapping : number [ ] }
135135{
136136 let strNewContent : string = "" ;
137137 let arrMapping : number [ ] = [ ] ;
138- let bAtLineStart : boolean = true ; // 标记当前是否处于行首
139- let nPendingSpaceIndex : number | null = null ; // 待添加空格的原始索引
138+ let bAtLineStart : boolean = true ; // 标记当前是否处于行首
139+ let nPendingSpaceIndex : number | null = null ; // 待添加空格的原始索引
140140
141141 for ( let nIdx = 0 ; nIdx < content . length ; nIdx ++ )
142142 {
143143 const chChar : string = content [ nIdx ] ;
144144
145145 if ( chChar === '\n' )
146146 {
147- // 遇到换行符时,丢弃待添加的空格(避免行尾空格)
147+ // 遇到换行符时,丢弃待添加的空格(避免行尾空格)
148148 nPendingSpaceIndex = null ;
149- // 如果输出为空或上一个字符不是换行符,则添加换行符
149+ // 如果输出为空或上一个字符不是换行符,则添加换行符
150150 if ( strNewContent . length === 0 || strNewContent [ strNewContent . length - 1 ] !== '\n' )
151151 {
152152 strNewContent += '\n' ;
@@ -156,7 +156,7 @@ export function normalizeWhitespace(content: string): { content: string; mapping
156156 }
157157 else if ( / \s / . test ( chChar ) )
158158 {
159- // 遇到非换行空白字符:如果在行首,则忽略;否则,记录第一个空白字符索引
159+ // 遇到非换行空白字符:如果在行首,则忽略;否则,记录第一个空白字符索引
160160 if ( ! bAtLineStart )
161161 {
162162 if ( nPendingSpaceIndex === null )
@@ -167,7 +167,7 @@ export function normalizeWhitespace(content: string): { content: string; mapping
167167 }
168168 else
169169 {
170- // 遇到非空白字符时,如果有待添加的空格则先输出一个空格
170+ // 遇到非空白字符时,如果有待添加的空格则先输出一个空格
171171 if ( nPendingSpaceIndex !== null )
172172 {
173173 strNewContent += ' ' ;
@@ -235,13 +235,13 @@ export function verifyMatches(
235235 }
236236 } ) ;
237237
238- // 如果找到了最佳候选,则用贪心方式扩展匹配范围
238+ // 如果找到了最佳候选,则用贪心方式扩展匹配范围
239239 if ( bestMatch && bestCandidate !== - 1 )
240240 {
241241 let candidateIdx : number = bestCandidate ;
242242 let patternIdx : number = 0 ;
243243 let startIndex : number = - 1 ;
244- // 从最佳候选起点开始,贪心扫描候选区域,遇到匹配的字符则同步推进模式串下标
244+ // 从最佳候选起点开始,贪心扫描候选区域,遇到匹配的字符则同步推进模式串下标
245245 while ( candidateIdx < content . length && patternIdx < pattern . length )
246246 {
247247 if ( content . charAt ( candidateIdx ) === pattern . charAt ( patternIdx ) )
@@ -256,7 +256,7 @@ export function verifyMatches(
256256 }
257257
258258 let tmpMatch : MatchPosition = bestMatch ;
259- // nCandidateIdx 作为最终匹配结束位置(注意这里是最后一次匹配后加1的位置)
259+ // nCandidateIdx 作为最终匹配结束位置(注意这里是最后一次匹配后加1的位置)
260260 tmpMatch . start = mapping [ startIndex ] ;
261261 tmpMatch . end = mapping [ Math . min ( candidateIdx , content . length - 1 ) ] ;
262262 bestMatch = tmpMatch ;
@@ -265,7 +265,7 @@ export function verifyMatches(
265265 return bestMatch ? [ bestMatch ] : [ ] ;
266266}
267267
268- // ================ 工具函数 ================
268+ // ================ 工具函数 ================
269269function splitPatternWithStart ( pattern : string , count : number ) : { segment : string , start : number } [ ] {
270270 const segments : { segment : string , start : number } [ ] = [ ] ;
271271 const minSegmentLength = 3 ;
@@ -289,7 +289,7 @@ function calculateEditDistance(a: string, b: string, maxDistance: number): numbe
289289 return Infinity ;
290290 }
291291
292- // 使用滚动数组优化
292+ // 使用滚动数组优化
293293 let prevRow = Array ( b . length + 1 ) . fill ( 0 ) . map ( ( _ , i ) => i ) ;
294294 let currentRow = new Array ( b . length + 1 ) ;
295295
0 commit comments