@@ -22,7 +22,8 @@ const REQUIREMENT_HEADER_REGEX = /^###\s*Requirement:\s*(.+)\s*$/;
2222 * Extracts the Requirements section from a spec file and parses requirement blocks.
2323 */
2424export function extractRequirementsSection ( content : string ) : RequirementsSectionParts {
25- const lines = content . split ( '\n' ) ;
25+ const normalized = normalizeLineEndings ( content ) ;
26+ const lines = normalized . split ( '\n' ) ;
2627 const reqHeaderIndex = lines . findIndex ( l => / ^ # # \s + R e q u i r e m e n t s \s * $ / i. test ( l ) ) ;
2728
2829 if ( reqHeaderIndex === - 1 ) {
@@ -102,11 +103,16 @@ export interface DeltaPlan {
102103 renamed : Array < { from : string ; to : string } > ;
103104}
104105
106+ function normalizeLineEndings ( content : string ) : string {
107+ return content . replace ( / \r \n ? / g, '\n' ) ;
108+ }
109+
105110/**
106111 * Parse a delta-formatted spec change file content into a DeltaPlan with raw blocks.
107112 */
108113export function parseDeltaSpec ( content : string ) : DeltaPlan {
109- const sections = splitTopLevelSections ( content ) ;
114+ const normalized = normalizeLineEndings ( content ) ;
115+ const sections = splitTopLevelSections ( normalized ) ;
110116 const added = parseRequirementBlocksFromSection ( sections [ 'ADDED Requirements' ] || '' ) ;
111117 const modified = parseRequirementBlocksFromSection ( sections [ 'MODIFIED Requirements' ] || '' ) ;
112118 const removedNames = parseRemovedNames ( sections [ 'REMOVED Requirements' ] || '' ) ;
@@ -136,7 +142,7 @@ function splitTopLevelSections(content: string): Record<string, string> {
136142
137143function parseRequirementBlocksFromSection ( sectionBody : string ) : RequirementBlock [ ] {
138144 if ( ! sectionBody ) return [ ] ;
139- const lines = sectionBody . split ( '\n' ) ;
145+ const lines = normalizeLineEndings ( sectionBody ) . split ( '\n' ) ;
140146 const blocks : RequirementBlock [ ] = [ ] ;
141147 let i = 0 ;
142148 while ( i < lines . length ) {
@@ -161,7 +167,7 @@ function parseRequirementBlocksFromSection(sectionBody: string): RequirementBloc
161167function parseRemovedNames ( sectionBody : string ) : string [ ] {
162168 if ( ! sectionBody ) return [ ] ;
163169 const names : string [ ] = [ ] ;
164- const lines = sectionBody . split ( '\n' ) ;
170+ const lines = normalizeLineEndings ( sectionBody ) . split ( '\n' ) ;
165171 for ( const line of lines ) {
166172 const m = line . match ( REQUIREMENT_HEADER_REGEX ) ;
167173 if ( m ) {
@@ -180,7 +186,7 @@ function parseRemovedNames(sectionBody: string): string[] {
180186function parseRenamedPairs ( sectionBody : string ) : Array < { from : string ; to : string } > {
181187 if ( ! sectionBody ) return [ ] ;
182188 const pairs : Array < { from : string ; to : string } > = [ ] ;
183- const lines = sectionBody . split ( '\n' ) ;
189+ const lines = normalizeLineEndings ( sectionBody ) . split ( '\n' ) ;
184190 let current : { from ?: string ; to ?: string } = { } ;
185191 for ( const line of lines ) {
186192 const fromMatch = line . match ( / ^ \s * - ? \s * F R O M : \s * ` ? # # # \s * R e q u i r e m e n t : \s * ( .+ ?) ` ? \s * $ / ) ;
0 commit comments