param { string } content returns { [ string [ ] , string [ ] [ ] , string [ ] ] | null } function parseCsv ( content , csvReadOptions ) { if ( content === '' ) { content = defaultCsvContentIfEmpty ; } const parseResult = csv . parse ( content , { ... csvReadOptions , comments : false , rowInsertCommentLines_commentsString : typeof csvReadOptions . comments === 'string' && csvReadOptions . comments !== '' ? csvReadOptions . comments : null , /**
         * normally when parsing quotes are discarded as they don't change the retrieved data
         * true: quote information are returned as part of the parse result, for each column:
         * 	 true: column was quoted
         * 	 false: column was not quoted
         * false: quote information is returned as null or undefined (falsy)
         *
         * to determine if a column is quoted we use the first cell only (if a column has no cells then it's not quoted)
         * so if the first line has only 3 columns and all other more than 3 (e.g. 4) then all columns starting from 4 are treated as not quoted!!
         * not that there is no difference if we have column headers (first row is used)
         * comment rows are ignored for this
         */ retainQuoteInformation : true , } as any ) ; if ( parseResult . errors . length === 1 && parseResult . errors [ 0 ] . type === 'Delimiter' && parseResult . errors [ 0 ] . code === 'UndetectableDelimiter' ) { } else { if ( parseResult . errors . length > 0 ) { for ( let i = 0 ; i < parseResult . errors . length ; i ++ ) { const error = parseResult . errors [ i ] ; if ( error . type === 'Delimiter' && error . code === 'UndetectableDelimiter' ) { continue ; } if ( typeof error . row === 'number' ) { statusInfo . innerText = `Error` ; const errorMsg = `${ error . message } on line ${ error . row + 1 }` ; csvEditorDiv . innerText = errorMsg ; _error ( errorMsg ) ; continue ; } statusInfo . innerText = `Error` ; const errorMsg = `${ error . message }` ; csvEditorDiv . innerText = errorMsg ; _error ( errorMsg ) ; } return null ; } } defaultCsvWriteOptions . delimiter = parseResult . meta . delimiter ; newLineFromInput = parseResult . meta . linebreak ; updateNewLineSelect ( ) ; readDelimiterTooltip . setAttribute ( 'data-tooltip' , `${ readDelimiterTooltipText } (detected: ${ defaultCsvWriteOptions . delimiter . replace ( "\t" , "⇥" ) })` ) ; return { data : parseResult . data , columnIsQuoted : ( parseResult as any ) . columnIsQuoted } ; } function updateNewLineSelect ( ) { newlineSameSsInputOption . innerText = `${ newlineSameSsInputOptionText } (${ newLineFromInput === `\n` ? 'LF' : 'CRLF' })` ; } returns { string [ ] [ ] } function getData ( ) { if ( ! hot ) throw new Error ( 'table was null' ) ; return hot . getData ( ) ; } /**
 * if we have an header row already it is ignored here!!
 */ function getFirstRowWithIndex ( skipCommentLines = true ) { if ( ! hot ) return null ; const rowCount = hot . countRows ( ) ; if ( rowCount === 0 ) return null ; let firstDataRow = [ ] ; let rowIndex = - 1 ; for ( let i = 0 ; i < rowCount ; i ++ ) { const row = hot . getDataAtRow ( i ) ; if ( row . length === 0 ) continue ; if ( skipCommentLines && isCommentCell ( row [ 0 ] , defaultCsvReadOptions ) ) continue ; firstDataRow = [ ... row ] ; rowIndex = i ; break ; } if ( rowIndex === - 1 ) { return null ; } return { physicalIndex : rowIndex , row : firstDataRow } ; } function getFirstRowWithIndexByData ( data , skipCommentLines = true ) { const rowCount = data . length ; if ( rowCount === 0 ) return null ; let firstDataRow = [ ] ; let rowIndex = - 1 ; for ( let i = 0 ; i < rowCount ; i ++ ) { const row = data [ i ] ; if ( row . length === 0 ) continue ; if ( skipCommentLines && isCommentCell ( row [ 0 ] , defaultCsvReadOptions ) ) continue ; firstDataRow = [ ... row ] ; rowIndex = i ; break ; } if ( rowIndex === - 1 ) { return null ; } return { physicalIndex : rowIndex , row : firstDataRow } ; } param { any } csvReadOptions param { any } csvWriteOptions returns { string } function getDataAsCsv ( csvReadOptions , csvWriteOptions ) { const data = getData ( ) ; if ( csvWriteOptions . newline === '' ) { csvWriteOptions . newline = newLineFromInput ; } const _conf = { ... csvWriteOptions , quotes : csvWriteOptions . quoteAllFields , quoteEmptyOrNullFields : csvWriteOptions . quoteEmptyOrNullFields , } ; if ( csvWriteOptions . header ) { if ( ! hot ) throw new Error ( 'table was null' ) ; if ( headerRowWithIndex === null ) { const colHeaderCells = hot . getColHeader ( ) as string [ ] ; data . unshift ( colHeaderCells . map ( ( p , index ) => getSpreadsheetColumnLabel ( index ) ) ) ; } else { if ( headerRowWithIndex === null ) { throw new Error ( 'header row was null' ) ; } data . unshift ( headerRowWithIndex . row . map < string > ( ( val ) => val !== null ? val : '' ) ) ; } } for ( let i = 0 ; i < data . length ; i ++ ) { const row = data [ i ] ; if ( row [ 0 ] === null ) continue ; if ( typeof csvReadOptions . comments === 'string' && typeof csvWriteOptions . comments === 'string' && isCommentCell ( row [ 0 ] , csvReadOptions ) ) { const index = row [ 0 ] . indexOf ( csvReadOptions . comments ) ; row [ 0 ] = `${ row [ 0 ] . substring ( 0 , index ) }${ csvWriteOptions . comments }${ row [ 0 ] . substring ( index + csvReadOptions . comments . length ) }` . trimLeft ( ) . replace ( /\n/mg , "" ) ; } } _conf [ 'skipEmptyLines' ] = false ; _conf [ 'rowInsertCommentLines_commentsString' ] = typeof csvWriteOptions . comments === 'string' ? csvWriteOptions . comments : null ; _conf [ 'columnIsQuoted' ] = csvWriteOptions . retainQuoteInformation ? columnIsQuoted : null ; let dataAsString = csv . unparse ( data , _conf ) ; return dataAsString ; } param text function postReloadFile ( ) { if ( ! vscode ) { console . log ( `postReloadFile (but in browser)` ) ; return ; } _postReadyMessage ( ) ; } param text var postVsInformation = ( text ) => { if ( ! vscode ) { console . log ( `postVsInformation (but in browser)` ) ; return ; } vscode . postMessage ( { command : 'msgBox' , type : 'info' , content : text } ) ; } ; param text var postVsWarning = ( text ) => { if ( ! vscode ) { console . log ( `postVsWarning (but in browser)` ) ; return ; } vscode . postMessage ( { command : 'msgBox' , type : 'warn' , content : text } ) ; } ; param text var postVsError = ( text ) => { if ( ! vscode ) { console . log ( `postVsError (but in browser)` ) ; return ; } vscode . postMessage ( { command : 'msgBox' , type : 'error' , content : text } ) ; } ; param text function postCopyToClipboard ( text ) { if ( ! vscode ) { console . log ( `postCopyToClipboard (but in browser)` ) ; navigator . clipboard . writeText ( text ) ; return ; } vscode . postMessage ( { command : 'copyToClipboard' , text } ) ; } param text function postSetEditorHasChanges ( hasChanges ) { _setHasUnsavedChangesUiIndicator ( hasChanges ) ; if ( ! vscode ) { console . log ( `postSetEditorHasChanges (but in browser)` ) ; return ; } vscode . postMessage ( { command : 'setHasChanges' , hasChanges } ) ; } param csvContent param saveSourceFile function _postApplyContent ( csvContent , saveSourceFile ) { _setHasUnsavedChangesUiIndicator ( false ) ; if ( ! vscode ) { console . log ( `_postApplyContent (but in browser)` ) ; return ; } vscode . postMessage ( { command : 'apply' , csvContent , saveSourceFile } ) ; } function _postReadyMessage ( ) { if ( ! vscode ) { console . log ( `_postReadyMessage (but in browser)` ) ; return ; } startReceiveCsvProgBar ( ) ; vscode . postMessage ( { command : 'ready' } ) ; } function handleVsCodeMessage ( event ) { const message = event . data ; switch ( message . command ) { case 'csvUpdate' : { if ( typeof message . csvContent === 'string' ) { onReceiveCsvContentSlice ( { text : message . csvContent , sliceNr : 1 , totalSlices : 1 } ) ; } else { onReceiveCsvContentSlice ( message . csvContent ) ; } break ; } case "applyPress" : { postApplyContent ( false ) ; break ; } case 'applyAndSavePress' : { postApplyContent ( true ) ; break ; } case 'changeFontSizeInPx' : { changeFontSizeInPx ( message . fontSizeInPx ) ; break ; } case 'sourceFileChanged' : { const hasAnyChanges = getHasAnyChangesUi ( ) ; if ( ! hasAnyChanges && ! isReadonlyMode ) { reloadFileFromDisk ( ) ; return ; } toggleSourceFileChangedModalDiv ( true ) ; break ; } default : { _error ( 'received unknown message from vs code' ) ; notExhaustiveSwitch ( message ) ; break ; } } } function onReceiveCsvContentSlice ( slice ) { if ( slice . sliceNr === 1 ) { initialContent = '' ; statusInfo . innerText = `Receiving csv...` ; csvEditorDiv . innerText = `` ; } initialContent += slice . text ; receivedCsvProgBar . value = slice . sliceNr * 100 / slice . totalSlices ; if ( slice . sliceNr === slice . totalSlices ) { stopReceiveCsvProgBar ( ) ; startRenderData ( ) ; } } /**
 * performs the last steps to actually show the data (set status, render table, ...)
 * also called on reset data
 */ function startRenderData ( ) { statusInfo . innerText = `Rendering table...` ; if ( hasHeaderReadOptionInput . checked ) { isFirstHasHeaderChangedEvent = true ; defaultCsvReadOptions . _hasHeader = true ; } else { isFirstHasHeaderChangedEvent = false ; defaultCsvReadOptions . _hasHeader = false ; } call_after_DOM_updated ( ( ) => { resetData ( initialContent , defaultCsvReadOptions ) ; statusInfo . innerText = `Performing last steps...` ; if ( ! defaultCsvReadOptions . _hasHeader ) { setTimeout ( ( ) => { statusInfo . innerText = '' ; } , 0 ) ; } } ) ; } function call_after_DOM_updated ( fn ) { var intermediate = function ( ) { window . requestAnimationFrame ( fn ) ; } ; window . requestAnimationFrame ( intermediate ) ; } function notExhaustiveSwitch ( x ) { throw new Error ( 'not exhaustive switch' ) ; }