@@ -592,9 +592,6 @@ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof win
592592 let insertionPoint = oldParent . firstChild ;
593593 let newChild ;
594594
595- newParent . children ;
596- oldParent . children ;
597-
598595 // run through all the new content
599596 while ( nextNewChild ) {
600597
@@ -2729,6 +2726,127 @@ class ComponentRegistry {
27292726 }
27302727}
27312728
2729+ function isValueEmpty ( value ) {
2730+ if ( null === value || value === '' || undefined === value || ( Array . isArray ( value ) && value . length === 0 ) ) {
2731+ return true ;
2732+ }
2733+ if ( typeof value !== 'object' ) {
2734+ return false ;
2735+ }
2736+ for ( const key of Object . keys ( value ) ) {
2737+ if ( ! isValueEmpty ( value [ key ] ) ) {
2738+ return false ;
2739+ }
2740+ }
2741+ return true ;
2742+ }
2743+ function toQueryString ( data ) {
2744+ const buildQueryStringEntries = ( data , entries = { } , baseKey = '' ) => {
2745+ Object . entries ( data ) . forEach ( ( [ iKey , iValue ] ) => {
2746+ const key = baseKey === '' ? iKey : `${ baseKey } [${ iKey } ]` ;
2747+ if ( '' === baseKey && isValueEmpty ( iValue ) ) {
2748+ entries [ key ] = '' ;
2749+ }
2750+ else if ( null !== iValue ) {
2751+ if ( typeof iValue === 'object' ) {
2752+ entries = Object . assign ( Object . assign ( { } , entries ) , buildQueryStringEntries ( iValue , entries , key ) ) ;
2753+ }
2754+ else {
2755+ entries [ key ] = encodeURIComponent ( iValue )
2756+ . replace ( / % 2 0 / g, '+' )
2757+ . replace ( / % 2 C / g, ',' ) ;
2758+ }
2759+ }
2760+ } ) ;
2761+ return entries ;
2762+ } ;
2763+ const entries = buildQueryStringEntries ( data ) ;
2764+ return Object . entries ( entries )
2765+ . map ( ( [ key , value ] ) => `${ key } =${ value } ` )
2766+ . join ( '&' ) ;
2767+ }
2768+ function fromQueryString ( search ) {
2769+ search = search . replace ( '?' , '' ) ;
2770+ if ( search === '' )
2771+ return { } ;
2772+ const insertDotNotatedValueIntoData = ( key , value , data ) => {
2773+ const [ first , second , ...rest ] = key . split ( '.' ) ;
2774+ if ( ! second )
2775+ return ( data [ key ] = value ) ;
2776+ if ( data [ first ] === undefined ) {
2777+ data [ first ] = Number . isNaN ( Number . parseInt ( second ) ) ? { } : [ ] ;
2778+ }
2779+ insertDotNotatedValueIntoData ( [ second , ...rest ] . join ( '.' ) , value , data [ first ] ) ;
2780+ } ;
2781+ const entries = search . split ( '&' ) . map ( ( i ) => i . split ( '=' ) ) ;
2782+ const data = { } ;
2783+ entries . forEach ( ( [ key , value ] ) => {
2784+ value = decodeURIComponent ( value . replace ( / \+ / g, '%20' ) ) ;
2785+ if ( ! key . includes ( '[' ) ) {
2786+ data [ key ] = value ;
2787+ }
2788+ else {
2789+ if ( '' === value )
2790+ return ;
2791+ const dotNotatedKey = key . replace ( / \[ / g, '.' ) . replace ( / ] / g, '' ) ;
2792+ insertDotNotatedValueIntoData ( dotNotatedKey , value , data ) ;
2793+ }
2794+ } ) ;
2795+ return data ;
2796+ }
2797+ class UrlUtils extends URL {
2798+ has ( key ) {
2799+ const data = this . getData ( ) ;
2800+ return Object . keys ( data ) . includes ( key ) ;
2801+ }
2802+ set ( key , value ) {
2803+ const data = this . getData ( ) ;
2804+ data [ key ] = value ;
2805+ this . setData ( data ) ;
2806+ }
2807+ get ( key ) {
2808+ return this . getData ( ) [ key ] ;
2809+ }
2810+ remove ( key ) {
2811+ const data = this . getData ( ) ;
2812+ delete data [ key ] ;
2813+ this . setData ( data ) ;
2814+ }
2815+ getData ( ) {
2816+ if ( ! this . search ) {
2817+ return { } ;
2818+ }
2819+ return fromQueryString ( this . search ) ;
2820+ }
2821+ setData ( data ) {
2822+ this . search = toQueryString ( data ) ;
2823+ }
2824+ }
2825+ class HistoryStrategy {
2826+ static replace ( url ) {
2827+ history . replaceState ( history . state , '' , url ) ;
2828+ }
2829+ }
2830+
2831+ class QueryStringPlugin {
2832+ constructor ( mapping ) {
2833+ this . mapping = mapping ;
2834+ }
2835+ attachToComponent ( component ) {
2836+ component . on ( 'render:finished' , ( component ) => {
2837+ const urlUtils = new UrlUtils ( window . location . href ) ;
2838+ const currentUrl = urlUtils . toString ( ) ;
2839+ Object . entries ( this . mapping ) . forEach ( ( [ prop , mapping ] ) => {
2840+ const value = component . valueStore . get ( prop ) ;
2841+ urlUtils . set ( mapping . name , value ) ;
2842+ } ) ;
2843+ if ( currentUrl !== urlUtils . toString ( ) ) {
2844+ HistoryStrategy . replace ( urlUtils ) ;
2845+ }
2846+ } ) ;
2847+ }
2848+ }
2849+
27322850const getComponent = ( element ) => LiveControllerDefault . componentRegistry . getComponent ( element ) ;
27332851class LiveControllerDefault extends Controller {
27342852 constructor ( ) {
@@ -2756,6 +2874,7 @@ class LiveControllerDefault extends Controller {
27562874 new PageUnloadingPlugin ( ) ,
27572875 new PollingPlugin ( ) ,
27582876 new SetValueOntoModelFieldsPlugin ( ) ,
2877+ new QueryStringPlugin ( this . queryMappingValue ) ,
27592878 ] ;
27602879 plugins . forEach ( ( plugin ) => {
27612880 this . component . addPlugin ( plugin ) ;
@@ -2976,6 +3095,7 @@ LiveControllerDefault.values = {
29763095 debounce : { type : Number , default : 150 } ,
29773096 id : String ,
29783097 fingerprint : { type : String , default : '' } ,
3098+ queryMapping : { type : Object , default : { } } ,
29793099} ;
29803100LiveControllerDefault . componentRegistry = new ComponentRegistry ( ) ;
29813101
0 commit comments