@@ -5171,6 +5171,16 @@ class ResizeableBuffer{
51715171 }
51725172}
51735173
5174+ // white space characters
5175+ // https://en.wikipedia.org/wiki/Whitespace_character
5176+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes#Types
5177+ // \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff
5178+ const np = 12 ;
5179+ const cr$1 = 13 ; // `\r`, carriage return, 0x0D in hexadécimal, 13 in decimal
5180+ const nl$1 = 10 ; // `\n`, newline, 0x0A in hexadecimal, 10 in decimal
5181+ const space = 32 ;
5182+ const tab = 9 ;
5183+
51745184const init_state = function ( options ) {
51755185 return {
51765186 bomSkipped : false ,
@@ -5204,7 +5214,14 @@ const init_state = function(options){
52045214 recordDelimiterMaxLength : options . record_delimiter . length === 0 ? 2 : Math . max ( ...options . record_delimiter . map ( ( v ) => v . length ) ) ,
52055215 trimChars : [ Buffer . from ( ' ' , options . encoding ) [ 0 ] , Buffer . from ( '\t' , options . encoding ) [ 0 ] ] ,
52065216 wasQuoting : false ,
5207- wasRowDelimiter : false
5217+ wasRowDelimiter : false ,
5218+ timchars : [
5219+ Buffer . from ( Buffer . from ( [ cr$1 ] , 'utf8' ) . toString ( ) , options . encoding ) ,
5220+ Buffer . from ( Buffer . from ( [ nl$1 ] , 'utf8' ) . toString ( ) , options . encoding ) ,
5221+ Buffer . from ( Buffer . from ( [ np ] , 'utf8' ) . toString ( ) , options . encoding ) ,
5222+ Buffer . from ( Buffer . from ( [ space ] , 'utf8' ) . toString ( ) , options . encoding ) ,
5223+ Buffer . from ( Buffer . from ( [ tab ] , 'utf8' ) . toString ( ) , options . encoding ) ,
5224+ ]
52085225 } ;
52095226} ;
52105227
@@ -5627,15 +5644,9 @@ const isRecordEmpty = function(record){
56275644 return record . every ( ( field ) => field == null || field . toString && field . toString ( ) . trim ( ) === '' ) ;
56285645} ;
56295646
5630- // white space characters
5631- // https://en.wikipedia.org/wiki/Whitespace_character
5632- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes#Types
5633- // \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff
5634- const tab = 9 ;
5635- const nl = 10 ; // \n, 0x0A in hexadecimal, 10 in decimal
5636- const np = 12 ;
5637- const cr = 13 ; // \r, 0x0D in hexadécimal, 13 in decimal
5638- const space = 32 ;
5647+ const cr = 13 ; // `\r`, carriage return, 0x0D in hexadécimal, 13 in decimal
5648+ const nl = 10 ; // `\n`, newline, 0x0A in hexadecimal, 10 in decimal
5649+
56395650const boms = {
56405651 // Note, the following are equals:
56415652 // Buffer.from("\ufeff")
@@ -5780,7 +5791,7 @@ const transform = function(original_options = {}) {
57805791 if ( this . state . commenting === false && this . __isQuote ( buf , pos ) ) {
57815792 if ( this . state . quoting === true ) {
57825793 const nextChr = buf [ pos + quote . length ] ;
5783- const isNextChrTrimable = rtrim && this . __isCharTrimable ( nextChr ) ;
5794+ const isNextChrTrimable = rtrim && this . __isCharTrimable ( buf , pos + quote . length ) ;
57845795 const isNextChrComment = comment !== null && this . __compareBytes ( comment , buf , pos + quote . length , nextChr ) ;
57855796 const isNextChrDelimiter = this . __isDelimiter ( buf , pos + quote . length , nextChr ) ;
57865797 const isNextChrRecordDelimiter = record_delimiter . length === 0 ? this . __autoDiscoverRecordDelimiter ( buf , pos + quote . length ) : this . __isRecordDelimiter ( nextChr , buf , pos + quote . length ) ;
@@ -5890,30 +5901,34 @@ const transform = function(original_options = {}) {
58905901 }
58915902 if ( this . state . commenting === false ) {
58925903 if ( max_record_size !== 0 && this . state . record_length + this . state . field . length > max_record_size ) {
5893- const err = this . __error (
5904+ return this . __error (
58945905 new CsvError ( 'CSV_MAX_RECORD_SIZE' , [
58955906 'Max Record Size:' ,
58965907 'record exceed the maximum number of tolerated bytes' ,
58975908 `of ${ max_record_size } ` ,
58985909 `at line ${ this . info . lines } ` ,
58995910 ] , this . options , this . __infoField ( ) )
59005911 ) ;
5901- if ( err !== undefined ) return err ;
59025912 }
59035913 }
5904- const lappend = ltrim === false || this . state . quoting === true || this . state . field . length !== 0 || ! this . __isCharTrimable ( chr ) ;
5914+ const lappend = ltrim === false || this . state . quoting === true || this . state . field . length !== 0 || ! this . __isCharTrimable ( buf , pos ) ;
59055915 // rtrim in non quoting is handle in __onField
59065916 const rappend = rtrim === false || this . state . wasQuoting === false ;
59075917 if ( lappend === true && rappend === true ) {
59085918 this . state . field . append ( chr ) ;
5909- } else if ( rtrim === true && ! this . __isCharTrimable ( chr ) ) {
5919+ } else if ( rtrim === true && ! this . __isCharTrimable ( buf , pos ) ) {
59105920 return this . __error (
59115921 new CsvError ( 'CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE' , [
59125922 'Invalid Closing Quote:' ,
59135923 'found non trimable byte after quote' ,
59145924 `at line ${ this . info . lines } ` ,
59155925 ] , this . options , this . __infoField ( ) )
59165926 ) ;
5927+ } else {
5928+ if ( lappend === false ) {
5929+ pos += this . __isCharTrimable ( buf , pos ) - 1 ;
5930+ }
5931+ continue ;
59175932 }
59185933 }
59195934 if ( end === true ) {
@@ -6170,8 +6185,19 @@ const transform = function(original_options = {}) {
61706185 return [ undefined , field ] ;
61716186 } ,
61726187 // Helper to test if a character is a space or a line delimiter
6173- __isCharTrimable : function ( chr ) {
6174- return chr === space || chr === tab || chr === cr || chr === nl || chr === np ;
6188+ __isCharTrimable : function ( buf , pos ) {
6189+ const isTrim = ( buf , pos ) => {
6190+ const { timchars} = this . state ;
6191+ loop1: for ( let i = 0 ; i < timchars . length ; i ++ ) {
6192+ const timchar = timchars [ i ] ;
6193+ for ( let j = 0 ; j < timchar . length ; j ++ ) {
6194+ if ( timchar [ j ] !== buf [ pos + j ] ) continue loop1;
6195+ }
6196+ return timchar . length ;
6197+ }
6198+ return 0 ;
6199+ } ;
6200+ return isTrim ( buf , pos ) ;
61756201 } ,
61766202 // Keep it in case we implement the `cast_int` option
61776203 // __isInt(value){
0 commit comments