@@ -7,6 +7,7 @@ export type TIngridParseOpts = Partial<{
77export type TIngridParse = ( input : string ) => TIngridResponse
88
99const EOL = / \r ? \n | \r | \n /
10+ const EMPTY = '-'
1011
1112type TLineDigest = {
1213 spaces : number [ ] ,
@@ -61,7 +62,7 @@ export const parseLine = (line: string, sep = ' '): TLineDigest => {
6162}
6263
6364export const parseLines = ( input : string , sep ?: string ) : TLineDigest [ ] =>
64- input . split ( EOL ) . map ( l => parseLine ( l , sep ) )
65+ input . split ( EOL ) . filter ( Boolean ) . map ( l => parseLine ( l , sep ) )
6566
6667const countWordsByIndex = ( { words} : TLineDigest , index : number ) : number => words . filter ( ( { e} ) => e < index ) . length
6768
@@ -126,45 +127,74 @@ const gridToData = (grid: string[][][]): TIngridResponse => {
126127 return data
127128}
128129
129- const cut = ( line : string , points : number [ ] , pad = 2 ) : string [ ] => {
130- const chunks : string [ ] = [ ]
131- let s = 0
132- for ( const i in [ ...points , Number . POSITIVE_INFINITY ] ) {
133- const chunk = line . slice ( s , points [ i ] )
134- chunks . push ( chunk )
135- s = points [ i ] + pad
130+ // eslint-disable-next-line sonarjs/cognitive-complexity
131+ export const parseWinGrid = ( input : string ) : TIngridResponse => {
132+ const _lines = input . split ( / \r ? \n / )
133+ const lines = _lines . filter ( Boolean )
134+ const headline = lines . shift ( ) !
135+ const headers = headline . split ( / \s + / )
136+ const ll = lines [ 0 ] . length
137+ const hl = headers . length
138+
139+ if ( lines . every ( l => l . length === ll ) ) {
140+ const spaces = Array
141+ . from ( { length : ll } )
142+ . map ( ( _ , i ) =>
143+ lines . every ( l => l [ i ] === ' ' )
144+ )
145+ const borders = spaces
146+ . reduce < number [ ] > ( ( m , v , i , a ) => {
147+ if ( v && ! a [ i - 1 ] ) m . push ( i )
148+ return m
149+ } , [ 0 ] )
150+ const data : TIngridResponse = [ ]
151+
152+ for ( const line of lines ) {
153+ const props : [ string , [ string ] ] [ ] = [ ]
154+ for ( const i in headers ) {
155+ const k = headers [ i ]
156+ const s = borders [ i ]
157+ const e = borders [ + i + 1 ] || ll
158+ const v = line . slice ( s , e ) . trim ( )
159+ props . push ( [ k , [ v || EMPTY ] ] )
160+ }
161+ data . push ( Object . fromEntries ( props ) )
162+ }
163+ return data
136164 }
137165
138- return chunks
139- }
140-
141- export const parseWinGrid = ( input : string ) : TIngridResponse => {
142- const lines = input . split ( EOL )
143- const headers = lines [ 0 ] . trim ( ) . split ( / \s + / )
166+ let w = ''
167+ let p
168+ const body = input . slice ( headline . length )
169+ const vals : string [ ] = [ ]
144170 const data : TIngridResponse = [ ]
145171
146- let memo = null
147- for ( const line of lines . slice ( 1 ) ) {
148- if ( ! line ) continue
172+ const cap = ( v ?: string ) => {
173+ const _v = w . trim ( ) || ( vals . length === 0 ? v : w . trim ( ) )
174+ if ( ! _v ) return
149175
150- const { spaces} = parseLine ( line )
151- const borders = spaces . filter ( ( s , i ) => spaces [ i + 1 ] === s + 1 && spaces [ i + 2 ] !== s + 2 )
152-
153- let chunks = ( borders . length > 0 ? cut ( line , borders , 2 ) : [ line ] ) . map ( l => l . trim ( ) ) //.filter(Boolean)
154- if ( chunks . length < headers . length ) {
155- memo = chunks
156- continue
157- } else if ( chunks [ 0 ] ?. trim ( ) ) {
158- memo = null
159- } else {
160- chunks = [ ...( memo || [ '<unknown>' ] ) , ...chunks ] . filter ( Boolean )
176+ vals . push ( _v )
177+ if ( vals . length === hl ) {
178+ data . push ( Object . fromEntries ( headers . map ( ( h , i ) => [ h , [ vals [ i ] ] ] ) ) )
179+ vals . length = 0
161180 }
181+ w = ''
182+ }
162183
163- const entry : TIngridResponse [ number ] = Object . fromEntries ( headers . map ( ( header , i ) =>
164- [ header , parseLine ( chunks [ i ] || '' ) . words . map ( ( { w} ) => w ) ]
165- ) )
166- data . push ( entry )
184+ for ( const c of body ) {
185+ w += c
186+ if ( c === ' ' ) {
187+ if ( p === '\n' ) {
188+ cap ( EMPTY )
189+ } else if ( p === ' ' ) {
190+ cap ( )
191+ }
192+ } else if ( c === '\n' ) {
193+ cap ( )
194+ }
195+ p = c
167196 }
197+ cap ( )
168198
169199 return data
170200}
0 commit comments