@@ -7183,37 +7183,20 @@ R.sliceTo = search => s => {
71837183classes like `[x-z]` or "\w" or even "ß" in a disjunctive manner. */
71847184
71857185
7186- R . preBound = flags => ( ...classes ) => {
7187- const bound = "(?<=^|" + classes . join ( "|" ) + ")" ;
7188- return R ( bound , flags ) ;
7189- } ;
7190-
7191-
7192- // default prefix bound
7186+ R . preBound = ( ...classes ) => `(?<=^|${ classes . join ( "|" ) } )` ;
71937187
7194- R . preBound_ = R . preBound ( "v" ) ( "[^\\p{L}]" ) ;
71957188
7189+ // default prefix bound (like "\b" but inlcuding special letters and excluding "_")
71967190
7197- R . sufBound = flags => ( ...classes ) => {
7198- const bound = "(?=$|" + classes . join ( "|" ) + ")" ;
7199- return R ( bound , flags ) ;
7200- } ;
7201-
7191+ R . preBound_ = R . preBound ( "[^\\p{L}\\d]" ) ;
72027192
7203- // default suffix bound
72047193
7205- R . sufBound_ = R . sufBound ( "v" ) ( "[^\\p{L}]" ) ;
7194+ R . sufBound = ( ... classes ) => `(?=$| ${ classes . join ( "|" ) } )` ;
72067195
72077196
7208- R . inBound = flags => ( ...classes ) => {
7209- const bound = "(?:" + classes . join ( "|" ) + ")" ;
7210- return R ( bound , flags ) ;
7211- } ;
7197+ // default suffix bound (like "\b" but inlcuding special letters and excluding "_")
72127198
7213-
7214- // default infix bound
7215-
7216- R . inBound_ = R . preBound ( "v" ) ( "[^\\p{L}]" ) ;
7199+ R . sufBound_ = R . sufBound ( "[^\\p{L}\\d]" ) ;
72177200
72187201
72197202//█████ Generalizing ██████████████████████████████████████████████████████████
@@ -9235,6 +9218,46 @@ S.countSubstr = t => s => {
92359218//█████ Replacing █████████████████████████████████████████████████████████████
92369219
92379220
9221+ S . replaceAt = ( { sub, is} ) => s => {
9222+ const xs = s . split ( "" ) ;
9223+ for ( let i = 0 ; i < is . length ; i ++ ) xs [ is [ i ] ] = sub ;
9224+ return xs . join ( "" ) ;
9225+ } ;
9226+
9227+
9228+ S . replaceAtAccum = ( { sub, is} ) => s => {
9229+ const xs = [ s ] ;
9230+
9231+ for ( let i = 0 ; i < is . length ; i ++ ) {
9232+ const ys = s . split ( "" ) ;
9233+ ys [ is [ i ] ] = sub ;
9234+ xs . push ( ys . join ( "" ) ) ;
9235+ }
9236+
9237+ return xs ;
9238+ } ;
9239+
9240+
9241+ S . updateAt = ( { f, is} ) => s => {
9242+ const xs = s . split ( "" ) ;
9243+ for ( let i = 0 ; i < is . length ; i ++ ) xs [ is [ i ] ] = f ( xs [ is [ i ] ] ) ;
9244+ return xs . join ( "" ) ;
9245+ } ;
9246+
9247+
9248+ S . updateAtAccum = ( { f, is} ) => s => {
9249+ const xs = [ s ] ;
9250+
9251+ for ( let i = 0 ; i < is . length ; i ++ ) {
9252+ const ys = s . split ( "" ) ;
9253+ ys [ is [ i ] ] = f ( ys [ is [ i ] ] ) ;
9254+ xs . push ( ys . join ( "" ) ) ;
9255+ }
9256+
9257+ return xs ;
9258+ } ;
9259+
9260+
92389261S . replaceChar = ( c , sub ) => s => {
92399262 let t = "" ;
92409263
@@ -9263,13 +9286,13 @@ S.replaceCharAccum = (c, sub) => s => {
92639286} ;
92649287
92659288
9266- S . replaceSub = ( c , sub ) => s => {
9289+ S . replaceSub = ( sub , sub2 ) => s => {
92679290 let r = "" , j = 0 ;
92689291
9269- for ( let i = s . indexOf ( c , j ) ; i !== - 1 ; i = s . indexOf ( c , j ) ) {
9292+ for ( let i = s . indexOf ( sub , j ) ; i !== - 1 ; i = s . indexOf ( sub , j ) ) {
92709293 r += s . substring ( j , i ) ;
9271- r += sub ;
9272- j = i + c . length ;
9294+ r += sub2 ;
9295+ j = i + sub . length ;
92739296 }
92749297
92759298 r += s . substring ( j ) ;
@@ -9361,12 +9384,12 @@ S.splitAscii = s => {
93619384} ;
93629385
93639386
9364- S . splitName = titles => s => {
9387+ S . splitName = ( ... titles ) => s => {
93659388 const titles2 = [ ] ;
93669389
93679390 for ( const title of titles ) {
93689391 const rx = R . giv (
9369- `${ R . preBound_ . source } ${ R . escape ( title ) } ( |${ R . sufBound_ . source } )`
9392+ `${ R . preBound_ } ${ R . escape ( title ) } ( |${ R . sufBound_ } )`
93709393 ) ;
93719394
93729395 if ( rx . test ( s ) ) {
@@ -9422,7 +9445,7 @@ S.splitMergedWord = (...exceptions) => s => {
94229445
94239446 for ( let i = 0 ; i < xs . length ; i ++ ) {
94249447 for ( const exception of exceptions ) {
9425- if ( R . v ( `\\b ${ R . escape ( exception ) } $` ) . test ( xs [ i ] ) ) {
9448+ if ( R . v ( `${ R . preBound_ } ${ R . escape ( exception ) } $` ) . test ( xs [ i ] ) ) {
94269449 if ( i < xs . length - 1 ) {
94279450 ys . push ( xs [ i ] + xs [ i + 1 ] ) ;
94289451 i ++ ;
@@ -11463,42 +11486,67 @@ S.Ctor.cmpWith = opt => (o, p) =>
1146311486//█████ Casing ████████████████████████████████████████████████████████████████
1146411487
1146511488
11466- // capitalize a word and its potential word components
11489+ // convert a word into title case form while considering word components
1146711490
11468- S . capitalize = nouns => {
11469- const lowercasedName = nouns . toLowerCase ( ) ;
11491+ S . capitalize = ( ... exceptions ) => word => {
11492+ const lcWord = word . toLowerCase ( ) ;
1147011493
11471- return lowercasedName . replace ( / ( ^ | [ \s ' -\. ] ) ( \w ) / g , ( match , separator , char ) => {
11494+ const word2 = lcWord . replace ( / ( ^ | [ ' -\. ] ) ( \w ) / gu , ( match , separator , char ) => {
1147211495 return separator + char . toUpperCase ( ) ;
1147311496 } ) ;
11497+
11498+ const is = exceptions . reduce ( ( acc , exception ) => {
11499+ const i = word2 . search ( R . v ( `${ R . preBound_ } ${ exception } (?=\\p{L})` ) )
11500+ if ( i === notFound ) return acc ;
11501+ else return A . push ( i + exception . length ) ( acc ) ;
11502+ } , [ ] ) ;
11503+
11504+ return is . reduce ( ( acc , i ) =>
11505+ S . updateAt ( { f : c => c . toUpperCase ( ) , is : [ i ] } ) ( acc ) , word2 ) ;
11506+ } ;
11507+
11508+
11509+ // convert allcaps into title case form while considering word components
11510+
11511+ S . capitalizeAcronym = ( ...exceptions ) => word => {
11512+ const casing = S . determineCasing ( ...exceptions ) ( word ) ;
11513+ if ( casing === "acronym" ) return S . capitalize ( ...exceptions ) ;
11514+ else return word ;
1147411515} ;
1147511516
1147611517
1147711518/* Possible casings:
1147811519
1147911520 • lower-case: foo
11480- • sentence -case: Foo
11521+ • title -case: Foo
1148111522 • camel-case: fooBar or FooBar
1148211523 • acronym: FOO
1148311524 • arbitrary-case: FOOBar */
1148411525
11485- S . determineCasing = word => {
11526+ S . determineCasing = ( ... exceptions ) => word => {
1148611527 const lc = word . toLowerCase ( ) ,
11487- uc = s . toUpperCase ( ) ;
11528+ uc = word . toUpperCase ( ) ;
1148811529
1148911530 if ( lc === word ) return "lower-case" ;
1149011531 else if ( uc === word ) return "acronym" ;
1149111532
1149211533 else {
11493- const guess = "" ;
11534+ let guess = "" ;
1149411535
1149511536 for ( let i = 0 ; i < word . length ; i ++ ) {
1149611537 if ( lc [ i ] !== word [ i ] ) {
11497- if ( i === 0 ) guess = "sentence-case" ;
11498- else if ( s [ i - 1 ] === "-" ) continue ;
11499- else if ( s [ i - 1 ] === "." ) continue ;
11500- else if ( s [ i - 1 ] === "'" ) continue ;
11501- else if ( s [ i - 1 ] === word [ i - 1 ] ) guess = "camel-case" ;
11538+ if ( i === 0 ) guess = "title-case" ;
11539+ else if ( word [ i - 1 ] === "-" ) continue ;
11540+ else if ( word [ i - 1 ] === "." ) continue ;
11541+ else if ( word [ i - 1 ] === "'" ) continue ;
11542+
11543+ else if ( lc [ i - 1 ] === word [ i - 1 ] ) {
11544+ const isException = exceptions . some ( exception =>
11545+ word . slice ( i - 2 ) . startsWith ( exception ) ) ;
11546+
11547+ if ( isException ) continue ;
11548+ else guess = "camel-case" ;
11549+ }
1150211550
1150311551 else {
1150411552 guess = "arbitrary-case" ;
0 commit comments