9
9
10
10
var extend = require ( 'extend-shallow' ) ;
11
11
12
- module . exports = function ( str , options , fn ) {
13
- if ( typeof str !== 'string' ) {
12
+ module . exports = function ( input , options , fn ) {
13
+ if ( typeof input !== 'string' ) {
14
14
throw new TypeError ( 'expected a string' ) ;
15
15
}
16
16
@@ -21,23 +21,26 @@ module.exports = function(str, options, fn) {
21
21
22
22
// allow separator to be defined as a string
23
23
if ( typeof options === 'string' ) {
24
- options = { sep : options } ;
24
+ options = { separator : options } ;
25
25
}
26
26
27
- var opts = extend ( { sep : '.' } , options ) ;
28
- var quotes = opts . quotes || {
29
- '"' : '"' ,
30
- "'" : "'" ,
31
- '`' : '`' ,
32
- '“' : '”'
27
+ var defaults = {
28
+ separator : '.' ,
29
+ doubleQuoteRegex : / ^ [ " “ ” ] / ,
30
+ singleQuoteRegex : / ^ [ ' ‘ ’ ] / ,
31
+ quoteRegex : / ^ [ ' ‘ ’ " “ ” ` ] / ,
32
+ quotes : {
33
+ '"' : '"' ,
34
+ "'" : "'" ,
35
+ '`' : '`' ,
36
+ '‘' : '’' ,
37
+ '“' : '”'
38
+ }
33
39
} ;
34
40
35
- if ( Array . isArray ( quotes ) ) {
36
- quotes = quotes . reduce ( function ( acc , ele ) {
37
- acc [ ele ] = ele ;
38
- return acc ;
39
- } , { } ) ;
40
- }
41
+ var opts = extend ( { } , defaults , options ) ;
42
+ var sep = opts . sep || opts . separator ;
43
+ var quotes = opts . quotes ;
41
44
42
45
var brackets ;
43
46
if ( opts . brackets === true ) {
@@ -51,57 +54,56 @@ module.exports = function(str, options, fn) {
51
54
brackets = opts . brackets ;
52
55
}
53
56
54
- var tokens = [ ] ;
55
- var stack = [ ] ;
56
- var arr = [ '' ] ;
57
- var sep = opts . sep ;
58
- var len = str . length ;
59
- var idx = - 1 ;
57
+ var len = input . length ;
58
+ var index = - 1 ;
60
59
var closeIdx ;
60
+ var stack = [ ] ;
61
+ var tokens = [ '' ] ;
62
+ var arr = [ ] ;
61
63
62
64
function expected ( ) {
63
65
if ( brackets && stack . length ) {
64
66
return brackets [ stack [ stack . length - 1 ] ] ;
65
67
}
66
68
}
67
69
68
- while ( ++ idx < len ) {
69
- var ch = str [ idx ] ;
70
- var next = str [ idx + 1 ] ;
71
- var tok = { val : ch , idx : idx , arr : arr , str : str } ;
72
- tokens . push ( tok ) ;
70
+ while ( ++ index < len ) {
71
+ var ch = input [ index ] ;
72
+ var next = input [ index + 1 ] ;
73
+ var tok = { val : ch , index : index , tokens : tokens , input : input } ;
74
+ arr . push ( tok ) ;
73
75
74
76
if ( ch === '\\' ) {
75
- tok . val = keepEscaping ( opts , str , idx ) === true ? ( ch + next ) : next ;
77
+ tok . val = keepEscaping ( opts , input , index ) === true ? ( ch + next ) : next ;
76
78
tok . escaped = true ;
77
79
if ( typeof fn === 'function' ) {
78
80
fn ( tok ) ;
79
81
}
80
- arr [ arr . length - 1 ] += tok . val ;
81
- idx ++ ;
82
+ tokens [ tokens . length - 1 ] += tok . val ;
83
+ index ++ ;
82
84
continue ;
83
85
}
84
86
85
87
if ( brackets && brackets [ ch ] ) {
86
88
stack . push ( ch ) ;
87
89
var e = expected ( ) ;
88
- var i = idx + 1 ;
90
+ var i = index + 1 ;
89
91
90
- if ( str . indexOf ( e , i + 1 ) !== - 1 ) {
92
+ if ( input . indexOf ( e , i + 1 ) !== - 1 ) {
91
93
while ( stack . length && i < len ) {
92
- var s = str [ ++ i ] ;
94
+ var s = input [ ++ i ] ;
93
95
if ( s === '\\' ) {
94
96
s ++ ;
95
97
continue ;
96
98
}
97
99
98
100
if ( quotes [ s ] ) {
99
- i = getClosingQuote ( str , quotes [ s ] , i + 1 ) ;
101
+ i = getClosingQuote ( input , quotes [ s ] , i + 1 ) ;
100
102
continue ;
101
103
}
102
104
103
105
e = expected ( ) ;
104
- if ( stack . length && str . indexOf ( e , i + 1 ) === - 1 ) {
106
+ if ( stack . length && input . indexOf ( e , i + 1 ) === - 1 ) {
105
107
break ;
106
108
}
107
109
@@ -118,66 +120,74 @@ module.exports = function(str, options, fn) {
118
120
119
121
closeIdx = i ;
120
122
if ( closeIdx === - 1 ) {
121
- arr [ arr . length - 1 ] += ch ;
123
+ tokens [ tokens . length - 1 ] += ch ;
122
124
continue ;
123
125
}
124
126
125
- ch = str . slice ( idx , closeIdx + 1 ) ;
127
+ ch = input . slice ( index , closeIdx + 1 ) ;
126
128
tok . val = ch ;
127
- tok . idx = idx = closeIdx ;
129
+ tok . index = index = closeIdx ;
128
130
}
129
131
130
132
if ( quotes [ ch ] ) {
131
- closeIdx = getClosingQuote ( str , quotes [ ch ] , idx + 1 ) ;
133
+ closeIdx = getClosingQuote ( input , quotes [ ch ] , index + 1 ) ;
132
134
if ( closeIdx === - 1 ) {
133
- arr [ arr . length - 1 ] += ch ;
135
+ tokens [ tokens . length - 1 ] += ch ;
134
136
continue ;
135
137
}
136
138
137
139
if ( keepQuotes ( ch , opts ) === true ) {
138
- ch = str . slice ( idx , closeIdx + 1 ) ;
140
+ ch = input . slice ( index , closeIdx + 1 ) ;
139
141
} else {
140
- ch = str . slice ( idx + 1 , closeIdx ) ;
142
+ ch = input . slice ( index + 1 , closeIdx ) ;
141
143
}
142
144
143
145
tok . val = ch ;
144
- tok . idx = idx = closeIdx ;
146
+ tok . index = index = closeIdx ;
145
147
}
146
148
147
149
if ( typeof fn === 'function' ) {
148
- fn ( tok , tokens ) ;
150
+ fn ( tok , arr ) ;
149
151
ch = tok . val ;
150
- idx = tok . idx ;
152
+ index = tok . index ;
151
153
}
152
154
153
155
if ( tok . val === sep && tok . split !== false ) {
154
- arr . push ( '' ) ;
156
+ tokens . push ( '' ) ;
155
157
continue ;
156
158
}
157
159
158
- arr [ arr . length - 1 ] += tok . val ;
160
+ tokens [ tokens . length - 1 ] += tok . val ;
159
161
}
160
162
161
- return arr ;
163
+ return tokens ;
162
164
} ;
163
165
164
166
function getClosingQuote ( str , ch , i , brackets ) {
165
- var idx = str . indexOf ( ch , i ) ;
166
- if ( str . charAt ( idx - 1 ) === '\\' ) {
167
- return getClosingQuote ( str , ch , idx + 1 ) ;
167
+ var index = str . indexOf ( ch , i ) ;
168
+ if ( str . charAt ( index - 1 ) === '\\' ) {
169
+ return getClosingQuote ( str , ch , index + 1 ) ;
168
170
}
169
- return idx ;
171
+ return index ;
170
172
}
171
173
172
- function keepQuotes ( ch , opts ) {
173
- if ( opts . keepDoubleQuotes === true && ( ch === '"' || ch === '“' || ch === '”' ) ) return true ;
174
- if ( opts . keepSingleQuotes === true && ch === "'" ) return true ;
175
- return opts . keepQuotes ;
174
+ function keepQuotes ( ch , options ) {
175
+ if ( options . keepDoubleQuotes === true && isDoubleQuote ( ch , options ) ) return true ;
176
+ if ( options . keepSingleQuotes === true && isSingleQuote ( ch , options ) ) return true ;
177
+ return options . keepQuotes ;
176
178
}
177
179
178
- function keepEscaping ( opts , str , idx ) {
179
- if ( typeof opts . keepEscaping === 'function' ) {
180
- return opts . keepEscaping ( str , idx ) ;
180
+ function keepEscaping ( options , str , index ) {
181
+ if ( typeof options . keepEscaping === 'function' ) {
182
+ return options . keepEscaping ( str , index ) ;
181
183
}
182
- return opts . keepEscaping === true || str [ idx + 1 ] === '\\' ;
184
+ return options . keepEscaping === true || str [ index + 1 ] === '\\' ;
185
+ }
186
+
187
+ function isDoubleQuote ( ch , options ) {
188
+ return options . doubleQuoteRegex . test ( ch ) ;
189
+ }
190
+
191
+ function isSingleQuote ( ch , options ) {
192
+ return options . singleQuoteRegex . test ( ch ) ;
183
193
}
0 commit comments