1
1
import defaultOptions , { Options } from './options'
2
- import { Input , cloneDeep } from './core'
2
+ import { Input , cloneDeep , MINUS } from './core'
3
3
4
4
export interface Config {
5
5
prefix : string
@@ -34,7 +34,12 @@ export default class NumberFormat {
34
34
number : Input
35
35
isClean : boolean
36
36
isCustomDecimal : boolean
37
- preSurRegExp : RegExp
37
+ noPreSuffix : boolean
38
+ hasPreOrSuffix : boolean
39
+ prefix : string
40
+ preSufRegExp ?: RegExp
41
+ prefixRegExp ?: RegExp
42
+ suffixRegExp ?: RegExp
38
43
numberRegExp : RegExp
39
44
cleanRegExp : RegExp
40
45
negativeRegExp : RegExp
@@ -47,14 +52,28 @@ export default class NumberFormat {
47
52
this . number = ''
48
53
this . isClean = ! reverseFill
49
54
50
- const escapedPrefix = prefix . replace ( / [ - / \\ ^ $ * + ? . ( ) | [ \] { } ] / g, '\\$&' )
51
- const escapedSuffix = suffix . replace ( / [ - / \\ ^ $ * + ? . ( ) | [ \] { } ] / g, '\\$&' )
55
+ // Use Negative Medium Space Unicode as default prefix if none provided
56
+ const safePrefix = prefix
57
+ const safeSuffix = suffix
58
+
59
+ const escapedPrefix = safePrefix . replace ( / [ - / \\ ^ $ * + ? . ( ) | [ \] { } ] / g, '\\$&' )
60
+ const escapedSuffix = safeSuffix . replace ( / [ - / \\ ^ $ * + ? . ( ) | [ \] { } ] / g, '\\$&' )
61
+
62
+ if ( escapedPrefix ) {
63
+ this . prefixRegExp = new RegExp ( `^${ escapedPrefix } ` )
64
+ }
65
+
66
+ if ( escapedSuffix ) {
67
+ this . suffixRegExp = new RegExp ( `${ escapedSuffix } $` )
68
+ }
52
69
53
- this . preSurRegExp = new RegExp ( ` ${ escapedPrefix } | ${ escapedSuffix } ` , 'g' )
70
+ this . prefix = prefix
54
71
this . numberRegExp = new RegExp ( `[^0-9\\${ decimal } ]+` , 'gi' )
55
72
this . cleanRegExp = new RegExp ( '[^0-9]+' , 'gi' )
56
73
this . negativeRegExp = new RegExp ( '[^0-9\\-]+' , 'gi' )
57
74
this . isCustomDecimal = decimal !== '.'
75
+ this . noPreSuffix = ! safePrefix && ! safeSuffix
76
+ this . hasPreOrSuffix = ! this . noPreSuffix
58
77
}
59
78
60
79
isNull ( ) {
@@ -70,11 +89,11 @@ export default class NumberFormat {
70
89
if ( this . input === null || this . input === undefined ) {
71
90
return ''
72
91
}
73
- const hasMinus = this . input . toString ( ) . indexOf ( '-' ) >= 0
92
+ const hasMinus = this . input . toString ( ) . indexOf ( MINUS ) >= 0
74
93
if ( this . isClean ) {
75
- return hasMinus && this . realNumber ( ) > 0 ? '-' : ''
94
+ return hasMinus && this . realNumber ( ) > 0 ? MINUS : ''
76
95
}
77
- return hasMinus ? '-' : ''
96
+ return hasMinus ? MINUS : ''
78
97
}
79
98
80
99
toFixed ( ) {
@@ -88,29 +107,65 @@ export default class NumberFormat {
88
107
}
89
108
90
109
numberOnly ( regExp ?: RegExp ) {
91
- return this . input
92
- ?. toString ( )
93
- . replace ( this . preSurRegExp , '' )
94
- . replace ( regExp || this . numberRegExp , '' )
110
+ let number = this . input ?. toString ( )
111
+
112
+ if ( this . prefixRegExp ) {
113
+ number = number . replace ( this . prefixRegExp , '' )
114
+ }
115
+
116
+ if ( this . suffixRegExp ) {
117
+ number = number . replace ( this . suffixRegExp , '' )
118
+ }
119
+
120
+ return number . replace ( regExp || this . numberRegExp , '' )
121
+ }
122
+
123
+ inputWithPreOrSuffix ( ) {
124
+ if ( this . input && this . prefixRegExp ) {
125
+ return this . prefixRegExp . test ( this . input . toString ( ) )
126
+ }
127
+
128
+ if ( this . input && this . suffixRegExp ) {
129
+ return this . suffixRegExp . test ( this . input . toString ( ) )
130
+ }
131
+
132
+ return true
95
133
}
96
134
97
135
isNegative ( ) {
98
- return this . sign ( ) === '-'
136
+ return this . sign ( ) === MINUS
137
+ }
138
+
139
+ isNumber ( val ?: any ) {
140
+ return ! isNaN ( this . toNumber ( val || this . input ) )
99
141
}
100
142
101
143
numbers ( ) {
102
- const { reverseFill, decimal } = this . options
103
- const hasDeciaml = this . input . toString ( ) . indexOf ( decimal ) >= 0
104
- const input = ! hasDeciaml && this . isCustomDecimal ? this . input + decimal : this . input
144
+ const { reverseFill, decimal, separator } = this . options
105
145
106
146
if ( reverseFill ) {
107
147
this . number = this . toFixed ( ) . replace ( '.' , decimal )
108
- } else if ( typeof this . input === 'number' ) {
109
- this . number = this . parts ( this . input . toString ( ) . replace ( '-' , '' ) , '.' ) . join ( decimal )
110
- } else if ( ! isNaN ( this . toNumber ( input ) ) ) {
111
- this . number = this . parts ( this . input . replace ( '-' , '' ) , '.' ) . join ( decimal )
112
148
} else {
113
- this . number = this . parts ( this . numberOnly ( ) ) . join ( decimal )
149
+ const number = this . input
150
+ ?. toString ( )
151
+ . replace ( this . prefixRegExp ?? '' , '' )
152
+ . replace ( this . suffixRegExp ?? '' , '' )
153
+ . replace ( new RegExp ( MINUS , 'g' ) , '' )
154
+
155
+ const hasCustomDecimal = this . input . toString ( ) . indexOf ( decimal ) >= 0 && this . isCustomDecimal
156
+ const realNumber = number . replace ( new RegExp ( `\\${ separator } ` , 'g' ) , '' ) . replace ( decimal , '.' )
157
+
158
+ if ( typeof this . input === 'number' ) {
159
+ this . number = this . parts ( number , '.' ) . join ( decimal )
160
+ } else if ( this . isNumber ( ) && ! hasCustomDecimal && ! this . inputWithPreOrSuffix ( ) && this . hasPreOrSuffix ) {
161
+ // Only process separator-to-decimal conversion when necessary
162
+ this . number = this . parts ( number , '.' ) . join ( decimal )
163
+ } else if ( this . isNumber ( realNumber ) && ! hasCustomDecimal && this . inputWithPreOrSuffix ( ) && this . hasPreOrSuffix ) {
164
+ this . number = this . parts ( realNumber , '.' ) . join ( decimal )
165
+ } else {
166
+ // If no custom decimal is detected, do not convert the separator
167
+ this . number = this . parts ( this . numberOnly ( ) ) . join ( decimal )
168
+ }
114
169
}
115
170
116
171
return this . number
0 commit comments