1+ class  Autocomplete  { 
2+ 
3+     constructor ( options )  { 
4+         this . options  =  options ; 
5+     } 
6+ 
7+     static  replace ( text ,  position ,  replaceValue ,  removeTrailing  =  false ,  afterSpace  =  false )  { 
8+         let  beginning  =  text . substring ( 0 ,  position ) ; 
9+         let  trailing  =  text . substring ( position ) ; 
10+ 
11+         let  lastIndexOf  =  this . lastWhitespaceIndex ( beginning ) ; 
12+         let  start  =  beginning . substr ( 0 ,  lastIndexOf  +  1 ) ; 
13+         let  end  =  trailing ; 
14+         if  ( removeTrailing )  { 
15+             let  indexOf  =  trailing . indexOf ( ' ' ) ; 
16+ 
17+             end  =  '' ; 
18+             if  ( indexOf  !==  - 1 ) 
19+                 end  =  trailing . substr ( indexOf ) ; 
20+         } 
21+ 
22+         if  ( afterSpace  &&  ! end . startsWith ( ' ' ) ) 
23+             end  =  ' '  +  end ; 
24+ 
25+         return  { 
26+             before : beginning . length  -  start . length , 
27+             after : trailing . length  -  end . length , 
28+             text : start  +  replaceValue  +  end , 
29+         } ; 
30+     } 
31+ 
32+     static  lastWhitespaceIndex ( beginning )  { 
33+         let  lastSpaceIndex  =  beginning . lastIndexOf ( ' ' ) ; 
34+         let  lastLineBreakIndex  =  beginning . lastIndexOf ( '\n' ) ; 
35+         return  lastSpaceIndex  >  lastLineBreakIndex  ? lastSpaceIndex  : lastLineBreakIndex ; 
36+     } 
37+ 
38+     suggest ( text ,  position )  { 
39+         let  beginning  =  text . substring ( 0 ,  position ) ; 
40+         // let trailing = text.substring(position); 
41+ 
42+         let  lastWord  =  beginning ; 
43+         let  lastIndexOf  =  Autocomplete . lastWhitespaceIndex ( beginning ) ; 
44+         if  ( lastIndexOf  !==  - 1 )  { 
45+             lastWord  =  beginning . substr ( lastIndexOf  +  1 ) ; 
46+         } 
47+ 
48+         let  suggests  =  [ ] ,  found  =  false ; 
49+ 
50+         for  ( let  option  of  this . options )  { 
51+             let  step  =  option ; 
52+             let  list  =  step . list ; 
53+             if  ( typeof  list  !==  'function' )  { 
54+                 const  data  =  list ; 
55+                 if  ( list  instanceof  Array )  { 
56+                     list  =  search  =>  { 
57+                         let  filtered  =  [ ] ; 
58+ 
59+                         let  filter  =  require ( 'lodash/fp/filter' ) ; 
60+                         if  ( search ) 
61+                             filtered  =  filter ( o  =>  o . startsWith ( search ) ) ( data ) ; 
62+                         else  if  ( search  ===  '' ) 
63+                             filtered  =  data ; 
64+ 
65+                         return  new  Promise ( resolve  =>  { 
66+                             resolve ( filtered ) ; 
67+                         } ) ; 
68+                     } ; 
69+                 }  else  { 
70+                     list  =  search  =>  { 
71+                         let  filtered  =  [ ] ; 
72+ 
73+                         let  cloneDeep  =  require ( 'lodash/fp/cloneDeep' ) ; 
74+                         let  keys  =  require ( 'lodash/fp/keys' ) ; 
75+                         let  filter  =  require ( 'lodash/fp/filter' ) ; 
76+                         let  start  =  '' ; 
77+                         step  =  cloneDeep ( option ) ; 
78+                         while  ( ! ( step . list  instanceof  Array ) )  { 
79+                             let  changed  =  false ; 
80+                             for  ( let  key  of  keys ( step . list ) )  { 
81+                                 if  ( search . startsWith ( start  +  key ) )  { 
82+                                     let  next_step  =  step . list [ key ] ; 
83+                                     if  ( typeof  next_step  ===  'object' )  { 
84+                                         if  ( next_step . hasOwnProperty ( 'list' ) )  { 
85+                                             if  ( ! next_step . hasOwnProperty ( 'trigger' )  ||  typeof  next_step . trigger  !==  'string' ) 
86+                                                 next_step . trigger  =  step . list . __trigger__ ; 
87+                                             if  ( ! next_step . hasOwnProperty ( 'color' )  ||  typeof  next_step . color  !==  'string' ) 
88+                                                 next_step . color  =  step . list . __color__ ; 
89+                                             changed  =  true ; 
90+                                             step  =  next_step ; 
91+                                             start  +=  key  +  step . trigger ; 
92+                                         } 
93+                                     } 
94+                                 } 
95+                             } 
96+                             if  ( ! changed ) 
97+                                 if  ( typeof  step  ===  'function' ) 
98+                                     return  new  Promise ( resolve  =>  { 
99+                                         filtered  =  step ( search ) ; 
100+                                         resolve ( filtered ) ; 
101+                                     } ) ; 
102+                                 else  if  ( ! ( step . list  instanceof  Array ) ) 
103+                                     step . list  =  keys ( step . list ) ; 
104+                         } 
105+                         if  ( option  !==  step )  { 
106+                             step . trigger  =  option . trigger  +  start ; 
107+                             if  ( search . startsWith ( start ) ) 
108+                                 search  =  search . substr ( start . length ) ; 
109+                         } 
110+                         if  ( search ) 
111+                             filtered  =  filter ( o  =>  o  !==  '__trigger__'  &&  o  !==  '__color__'  &&  o . startsWith ( search ) ) ( step . list ) ; 
112+                         else  if  ( search  ===  '' ) 
113+                             filtered  =  filter ( o  =>  o  !==  '__trigger__'  &&  o  !==  '__color__' ) ( step . list ) ; 
114+ 
115+                         return  new  Promise ( resolve  =>  { 
116+                             resolve ( filtered ) ; 
117+                         } ) ; 
118+                     } ; 
119+                 } 
120+             } 
121+ 
122+             let  result  =  undefined ; 
123+             if  ( ! step . pattern ) 
124+                 result  =  lastWord . startsWith ( step . trigger )  ? lastWord . substr ( step . trigger . length )  : false ; 
125+             else  { 
126+                 let  pattern  =  new  RegExp ( step . pattern ) ; 
127+                 pattern  =  new  RegExp ( step . trigger  +  pattern . source ,  pattern . flags ) ; 
128+                 result  =  pattern . exec ( lastWord ) ; 
129+             } 
130+ 
131+             if  ( result  ||  result  ===  '' )  { 
132+                 found  =  true ; 
133+                 list ( result ) . then ( filtered  =>  { 
134+                     suggests . push ( ...filtered . map ( d  =>  { 
135+                         return  { t : step . trigger ,  c : step . color ,  d} 
136+                     } ) ) ; 
137+                 } ) ; 
138+             } 
139+         } 
140+ 
141+         return  new  Promise ( ( resolve ,  reject )  =>  { 
142+             if  ( found ) 
143+                 resolve ( suggests ) ; 
144+             else 
145+                 reject ( new  Error ( 'not found!' ) ) ; 
146+         } ) ; 
147+     } 
148+ } 
149+ 
150+ module . exports  =  Autocomplete ; 
0 commit comments