@@ -106,57 +106,70 @@ RED.search = (function() {
106106 return val ;
107107 }
108108
109- function search ( val ) {
110- var results = [ ] ;
111- var typeFilter ;
112- var m = / (?: ^ | ) t y p e : ( [ ^ ] + ) / . exec ( val ) ;
113- if ( m ) {
114- val = val . replace ( / (?: ^ | ) t y p e : [ ^ ] + / , "" ) ;
115- typeFilter = m [ 1 ] ;
109+ function extractType ( val , flags ) {
110+ // extracts: type:XYZ & type:"X Y Z"
111+ const regEx = / (?: t y p e ) : \s * (?: " ( [ ^ " ] + ) " | ( [ ^ " ] + ) ) / ;
112+ let m
113+ while ( ( m = regEx . exec ( val ) ) !== null ) {
114+ // avoid infinite loops with zero-width matches
115+ if ( m . index === regEx . lastIndex ) {
116+ regEx . lastIndex ++ ;
117+ }
118+ val = val . replace ( m [ 0 ] , " " ) . trim ( )
119+ const flag = m [ 2 ] || m [ 1 ] // quoted entries in capture group 1, unquoted in capture group 2
120+ flags . type = flags . type || [ ] ;
121+ flags . type . push ( flag ) ;
116122 }
117- var flags = { } ;
123+ return val ;
124+ }
125+
126+ function search ( val ) {
127+ const results = [ ] ;
128+ const flags = { } ;
118129 val = extractFlag ( val , "invalid" , flags ) ;
119130 val = extractFlag ( val , "unused" , flags ) ;
120131 val = extractFlag ( val , "config" , flags ) ;
121132 val = extractFlag ( val , "subflow" , flags ) ;
122133 val = extractFlag ( val , "hidden" , flags ) ;
123134 val = extractFlag ( val , "modified" , flags ) ;
124- val = extractValue ( val , "flow" , flags ) ; // flow:active or flow:<flow-id>
135+ val = extractValue ( val , "flow" , flags ) ; // flow:current or flow:<flow-id>
125136 val = extractValue ( val , "uses" , flags ) ; // uses:<node-id>
137+ val = extractType ( val , flags ) ; // type:<node-type>
126138 val = val . trim ( ) ;
127- var hasFlags = Object . keys ( flags ) . length > 0 ;
139+ const hasFlags = Object . keys ( flags ) . length > 0 ;
140+ const hasTypeFilter = flags . type && flags . type . length > 0
128141 if ( flags . flow && flags . flow . indexOf ( "current" ) >= 0 ) {
129142 let idx = flags . flow . indexOf ( "current" ) ;
130- flags . flow [ idx ] = RED . workspaces . active ( ) ; //convert active to flow ID
143+ flags . flow [ idx ] = RED . workspaces . active ( ) ; //convert 'current' to active flow ID
131144 }
132145 if ( flags . flow && flags . flow . length ) {
133146 flags . flow = [ ...new Set ( flags . flow ) ] ; //deduplicate
134147 }
135- if ( val . length > 0 || typeFilter || hasFlags ) {
148+ if ( val . length > 0 || hasFlags ) {
136149 val = val . toLowerCase ( ) ;
137- var i ;
138- var j ;
139- var list = [ ] ;
140- var nodes = { } ;
150+ let i ;
151+ let j ;
152+ let list = [ ] ;
153+ const nodes = { } ;
141154 let keys = [ ] ;
142155 if ( flags . uses ) {
143156 keys = flags . uses ;
144157 } else {
145158 keys = Object . keys ( index ) ;
146159 }
147160 for ( i = 0 ; i < keys . length ; i ++ ) {
148- var key = keys [ i ] ;
149- var kpos = keys [ i ] . indexOf ( val ) ;
150- if ( kpos > - 1 ) {
151- var ids = Object . keys ( index [ key ] || { } ) ;
161+ const key = keys [ i ] ;
162+ const kpos = val ? keys [ i ] . indexOf ( val ) : - 1 ;
163+ if ( kpos > - 1 || ( val === "" && hasFlags ) ) {
164+ const ids = Object . keys ( index [ key ] || { } ) ;
152165 for ( j = 0 ; j < ids . length ; j ++ ) {
153166 var node = index [ key ] [ ids [ j ] ] ;
154167 var isConfigNode = node . node . _def . category === "config" && node . node . type !== 'group' ;
155168 if ( flags . uses && key === node . node . id ) {
156169 continue ;
157170 }
158171 if ( flags . hasOwnProperty ( "invalid" ) ) {
159- var nodeIsValid = ! node . node . hasOwnProperty ( "valid" ) || node . node . valid ;
172+ const nodeIsValid = ! node . node . hasOwnProperty ( "valid" ) || node . node . valid ;
160173 if ( flags . invalid === nodeIsValid ) {
161174 continue ;
162175 }
@@ -186,7 +199,7 @@ RED.search = (function() {
186199 }
187200 }
188201 if ( flags . hasOwnProperty ( "unused" ) ) {
189- var isUnused = ( node . node . type === 'subflow' && node . node . instances . length === 0 ) ||
202+ const isUnused = ( node . node . type === 'subflow' && node . node . instances . length === 0 ) ||
190203 ( isConfigNode && node . node . users . length === 0 && node . node . _def . hasUsers !== false )
191204 if ( flags . unused !== isUnused ) {
192205 continue ;
@@ -197,12 +210,16 @@ RED.search = (function() {
197210 continue ;
198211 }
199212 }
200- if ( ! typeFilter || node . node . type === typeFilter ) {
201- nodes [ node . node . id ] = nodes [ node . node . id ] = {
213+ let typeIndex = - 1
214+ if ( hasTypeFilter ) {
215+ typeIndex = flags . type . indexOf ( node . node . type )
216+ }
217+ if ( ! hasTypeFilter || typeIndex > - 1 ) {
218+ nodes [ node . node . id ] = nodes [ node . node . id ] || {
202219 node : node . node ,
203220 label : node . label
204221 } ;
205- nodes [ node . node . id ] . index = Math . min ( nodes [ node . node . id ] . index || Infinity , kpos ) ;
222+ nodes [ node . node . id ] . index = Math . min ( nodes [ node . node . id ] . index || Infinity , typeIndex > - 1 ? typeIndex : kpos ) ;
206223 }
207224 }
208225 }
0 commit comments