11const chute = ( ( ) => {
2- /* https://gregabbott.github.io/chute By + (C) Greg Abbott
3- [V1=2024-11-27][V=2024-12-07.3]*/
2+ // https://gregabbott.github.io/chute By + Copyright Greg Abbott
3+ // [V1=2024-11-27][V=2024-12-08.1]
44const stringy = x => JSON . stringify ( x ) ,
55error = ( ...x ) => { throw new Error ( x ) } ,
66is_fn = x => x instanceof Function ,
@@ -10,21 +10,18 @@ is_object=v=>v&& typeof v=='object'&&!Array.isArray(v),
1010is_js_method = ( o , k ) => is_fn ( Object . getPrototypeOf ( o ) [ k ] ) ,
1111is_global_fn = name => is_fn ( globalThis [ name ] ) ,
1212loop_o = f => o => { for ( let k in o ) if ( f ( k , o [ k ] , o ) === ! 1 ) break } ,
13- lift_a_library = ( k , v ) => {
14- if ( ! is_object ( v ) ) return
15- CHUTE . library [ k ] = v
16- CHUTE . lifted_libraries . push ( v )
17- } ,
1813lift_libraries = o => { // hoist
1914 if ( ! is_object ( o ) ) error ( `give .lift 1 object` )
20- loop_o ( lift_a_library ) ( o )
21- } ,
22- load_a_feed_item = ( k , v ) => {
23- if ( is_fn ( v ) || is_object ( v ) ) CHUTE . library [ k ] = v
15+ loop_o ( ( k , v ) => {
16+ if ( ! is_object ( v ) ) return
17+ CHUTE . library [ k ] = v
18+ CHUTE . lifted_libraries . push ( v )
19+ } ) ( o )
2420} ,
2521load_feed_items = o => {
2622 if ( ! is_object ( o ) ) error ( `give .feed 1 object` )
27- loop_o ( load_a_feed_item ) ( o )
23+ loop_o ( ( k , v ) => { if ( is_fn ( v ) || is_object ( v ) ) CHUTE . library [ k ] = v } )
24+ ( o )
2825} ,
2926chute_lib = { } , //Holds chute's own functions: log, tap, do, if
3027PLACEHOLDER = { } , //Sets data argument position in .fn calls.
@@ -117,7 +114,7 @@ const process_condition_block=(c,data,a_chute)=>{
117114 }
118115 return data //No matches
119116}
120- chute_lib . if = ( { args, data, a_chute} ) => {
117+ chute_lib . pick = ( { args, data, a_chute} ) => {
121118 if ( args . length == 0 ) error ( '.if needs 1-2 arguments' )
122119 let conditions_block =
123120 args . length === 2 ?{ if :args } //reshape as if-else object
@@ -129,8 +126,7 @@ chute_lib.if=({args,data,a_chute})=>{
129126 data ,
130127 a_chute
131128 )
132- let unchanged = data === rv
133- if ( unchanged ) return data
129+ if ( data === rv ) return data //unchanged
134130 if ( is_fn ( rv ) ) return call_a_function ( { fn :rv , data, args :[ ] } )
135131 //^If above true, memoized the FN in process_condition_block
136132 return rv
@@ -154,7 +150,7 @@ chute_lib.with=({args,data,a_chute})=>{//configure a chute
154150 if ( ! valid_config ) error ( '.with accepts 1 object for settings' )
155151 config = config [ 0 ] //settings object
156152 if ( config . sync ) load_sync_fn ( config . sync , a_chute )
157- if ( config . skip_void ) a_chute . skip_void = ! ! config . skip_void
153+ if ( 'skip' in config ) a_chute . skip_void = ! ! config . skip
158154 if ( config . feed ) load_feed_items ( config . feed )
159155 if ( config . lift ) lift_libraries ( config . lift )
160156 if ( config . path ) a_chute . treat_dots_as_paths = ! ! config . path
@@ -221,7 +217,7 @@ function handle_nested_access(a_chute,args){
221217 // next key starts a new path:
222218 a . path = null //reset
223219 }
224- a . context = a . path //the current item holds the next item
220+ else a . context = a . path //the current item holds the next item
225221 return a
226222 } , { path :null , data, context :null , root :null } )
227223 function try_do ( { fn, key, a, args= [ ] } ) {
@@ -244,7 +240,7 @@ function handle_nested_access(a_chute,args){
244240 rv = fn . call ( a . context , ...swap_placeholders ( args , a . data ) )
245241 rv = chain_stopping_methods . has ( key ) ?a . data :rv
246242 }
247- return skip_void && rv === undefined ? a . data :rv
243+ return rv === undefined && skip_void ? /*old*/ a . data :/*new*/ rv
248244 }
249245}
250246const blank_chute = ( ) => ( {
@@ -256,44 +252,46 @@ const blank_chute=()=>({
256252 skip_void :true , //Default
257253 dot_list :[ ] , //^.a.b.c collected until '()'
258254} )
255+ function _get ( a_chute , key ) {
256+ a_chute . dot_list . push ( key ) //store all keys pre '()' apply
257+ }
258+ function _apply ( a_chute , args ) {
259+ let named_end_chute = [ '_end' , '_$' ]
260+ . includes ( a_chute . dot_list . at ( - 1 ) )
261+ if ( named_end_chute ) a_chute . dot_list . pop ( )
262+ let is_nameless_call = a_chute . dot_list . length == 0 ,
263+ is_nameless_do_call = is_nameless_call && args . length > 0 ,
264+ is_nameless_end_chute = is_nameless_call && args . length === 0 ,
265+ is_named_call = ! is_nameless_call ,
266+ should_end_chute = is_nameless_end_chute || named_end_chute
267+ let update_value = is_nameless_do_call || is_named_call
268+ let rv
269+ if ( is_nameless_do_call ) {
270+ rv = chute_lib . do ( { args, data :a_chute . get_data ( ) , a_chute} )
271+ }
272+ else if ( is_named_call ) rv = handle_nested_access ( a_chute , args )
273+ if ( update_value ) a_chute . set_data ( rv )
274+ a_chute . dot_list . length = 0 //Reset : processed all call keys
275+ return should_end_chute ?a_chute . get_data ( ) :a_chute . proxy
276+ }
259277function new_chute ( { seed, args} ) {
260278 let a_chute = blank_chute ( )
261279 a_chute . keep = make_memoizer ( a_chute )
262280 a_chute . set_data = x => {
263- //console.log(`result of "${keys[0]||'nameless'}"`,x,typeof x)
264- if ( a_chute . skip_void && x === undefined ) return /*move on*/
281+ if ( x === undefined && a_chute . skip_void ) return /*move on*/
265282 if ( a_chute . sync_data /*provided*/ ) { a_chute . sync_data ( x ) }
266283 a_chute . data = x
267284 }
268285 a_chute . get_data = ( ) => a_chute . data
269- a_chute . set_data ( seed ) //initial chute call may give seed value
286+ if ( seed ) a_chute . set_data ( seed )
270287 if ( args . length > 0 ) {
271288 a_chute . set_data ( chute_lib . do ( { args, data :seed , a_chute} ) )
272289 }
273- function get ( target , key ) {
274- a_chute . dot_list . push ( key ) //store all keys pre '()' apply
275- return proxy
276- }
277- function apply ( target , this_arg , args ) {
278- let named_end_chute = [ '_end' , '_$' ]
279- . includes ( a_chute . dot_list . at ( - 1 ) )
280- if ( named_end_chute ) a_chute . dot_list . pop ( )
281- let is_nameless_call = a_chute . dot_list . length == 0 ,
282- is_nameless_do_call = is_nameless_call && args . length > 0 ,
283- is_nameless_end_chute = is_nameless_call && args . length === 0 ,
284- is_named_call = a_chute . dot_list . length > 0 ,
285- should_end_chute = is_nameless_end_chute || named_end_chute ,
286- rv
287- if ( is_nameless_do_call ) {
288- rv = chute_lib . do ( { args, data :a_chute . get_data ( ) , a_chute} )
289- }
290- else if ( is_named_call ) rv = handle_nested_access ( a_chute , args )
291- if ( rv ) a_chute . set_data ( rv )
292- a_chute . dot_list . length = 0 //Reset : processed all call keys
293- return should_end_chute ?a_chute . get_data ( ) :proxy
294- }
295- let proxy = new Proxy ( ( ) => { } /*target*/ , { get, apply} )
296- return proxy
290+ a_chute . proxy = new Proxy ( ( ) => { } , {
291+ get :( _ , k ) => { _get ( a_chute , k ) ; return a_chute . proxy } ,
292+ apply :( _ , __ , args ) => _apply ( a_chute , args )
293+ } )
294+ return a_chute . proxy
297295}
298296return CHUTE
299297} ) ( )
0 commit comments