@@ -152,6 +152,7 @@ export async function generateCvb(filePaths: string[], workspacePath: string, us
152152
153153 return cvbFilePath ;
154154}
155+
155156/**
156157 * 解析 CVB 格式内容
157158 * @param cvbContent CVB 内容
@@ -162,23 +163,34 @@ export function parseCvb(cvbContent: string): {
162163 metadata : Record < string , string > ;
163164 files : Record < string , string > ;
164165} {
165- const cvbStartIndex = cvbContent . indexOf ( '## BEGIN_CVB' ) ;
166- const cvbEndIndex = cvbContent . indexOf ( '## END_CVB' ) ;
166+ // 匹配## BEGIN_CVB在行首的位置
167+ const cvbStartRegex = / ^ # # B E G I N _ C V B / m;
168+ const cvbStartMatch = cvbStartRegex . exec ( cvbContent ) ;
169+ if ( ! cvbStartMatch ) {
170+ throw new Error ( 'Invalid CVB format: missing BEGIN_CVB marker.' ) ;
171+ }
172+ const cvbStartIndex = cvbStartMatch . index ;
167173
168- if ( cvbStartIndex === - 1 || cvbEndIndex === - 1 ) {
169- throw new Error ( 'Invalid CVB format: missing BEGIN or END markers.' ) ;
174+ // 匹配## END_CVB在行首的位置
175+ const cvbEndRegex = / ^ # # E N D _ C V B / m;
176+ const cvbEndMatch = cvbEndRegex . exec ( cvbContent ) ;
177+ if ( ! cvbEndMatch ) {
178+ throw new Error ( 'Invalid CVB format: missing END_CVB marker.' ) ;
170179 }
180+ const cvbEndIndex = cvbEndMatch . index ;
171181
172- const content = cvbContent . slice ( cvbStartIndex , cvbEndIndex + '## END_CVB' . length ) ;
182+ // 提取CVB内容,包括## BEGIN_CVB和## END_CVB
183+ const cvbContentStr = cvbContent . slice ( cvbStartIndex , cvbEndIndex + cvbEndMatch [ 0 ] . length ) ;
173184
174185 // 提取元数据部分
175- const metaMatch = content . match ( / # # M E T A ( [ \s \S ] * ?) # # E N D _ M E T A / ) ;
186+ const metaRegex = / ^ # # M E T A \n ( [ \s \S ] * ?) ^ # # E N D _ M E T A / m;
187+ const metaMatch = metaRegex . exec ( cvbContentStr ) ;
176188 if ( ! metaMatch ) {
177189 throw new Error ( 'Invalid CVB format: missing META section.' ) ;
178190 }
179-
180191 const metadata : Record < string , string > = { } ;
181- metaMatch [ 1 ] . trim ( ) . split ( '\n' ) . forEach ( line => {
192+ const metaContent = metaMatch [ 1 ] . trim ( ) . split ( '\n' ) ;
193+ metaContent . forEach ( line => {
182194 const parts = line . split ( ':' ) ;
183195 if ( parts . length >= 2 ) {
184196 const key = parts . shift ( ) ?. trim ( ) ;
@@ -191,24 +203,23 @@ export function parseCvb(cvbContent: string): {
191203
192204 // 提取文件内容部分
193205 const files : Record < string , string > = { } ;
194- const fileRegex = / ^ # # F I L E : ( .* ?) \n ( [ \s \S ] * ?) (? = ^ # # F I L E : | # # E N D _ C V B ) / gm;
206+ const fileRegex = / ^ # # F I L E : ( .* ?) \n ( [ \s \S ] * ?) (? = ^ # # F I L E : | ^ # # E N D _ C V B ) / gm;
195207 let match : RegExpExecArray | null ;
196208
197- while ( ( match = fileRegex . exec ( content ) ) !== null ) {
209+ while ( ( match = fileRegex . exec ( cvbContentStr ) ) !== null ) {
198210 const filePath = match [ 1 ] ;
199- const fileContent = match [ 2 ] . trim ( ) ;
211+ let fileContent = match [ 2 ] . trim ( ) ;
200212 // 去除代码块标记
201- const codeBlockRegex = / ^ ` ` ` .* \n ( [ \s \S ] * ?) \n ` ` ` $ / ;
202- const codeBlockMatch = fileContent . match ( codeBlockRegex ) ;
213+ const codeBlockRegex = / ^ ` ` ` .* \n ( [ \s \S ] * ?) \n ` ` ` $ / m ;
214+ const codeBlockMatch = codeBlockRegex . exec ( fileContent ) ;
203215 if ( codeBlockMatch ) {
204- files [ filePath ] = codeBlockMatch [ 1 ] ;
205- } else {
206- files [ filePath ] = fileContent ;
216+ fileContent = codeBlockMatch [ 1 ] ;
207217 }
218+ files [ filePath ] = fileContent ;
208219 }
209220
210221 return {
211- cvbContent : content ,
222+ cvbContent : cvbContentStr ,
212223 metadata,
213224 files,
214225 } ;
0 commit comments