import { svgElementAttributes , htmlElementAttributes } from 'all-html-attributes' ; export const isEvent = ( optionName ) => optionName ?. length > 2 && optionName . slice ( 0 , 2 ) === 'on' ; async function parseFnType ( item ) { if ( typeof item . type === 'function' ) { const rendered = await item . type ( item . props ) ; return parseFnType ( rendered ) ; } return item ; } export const render = async ( raw , childRenderer = null , renderedArr = [ ] , events = { } , parent = '' ) => { async function traverse ( arr , renderedArr = [ ] , parent = null ) { for ( let item of ( Array . isArray ( arr ) ? arr : [ arr ] ) ) { if ( item ?. type === '$$fragment' ) { await traverse ( item . props ?. children , renderedArr , parent ) ; } else if ( item ?. type ) { item = { ... await parseFnType ( item ) } ; const result = await childRenderer ?. ( item . type , item . key ? `${ parent }/${ item . key }/${ item . type }` : `${ parent }/${ renderedArr . length }/${ item . type }` , item . props ) ; if ( result ) { await render ( result , childRenderer , renderedArr , events , `${ parent }` ) ; } else { const type = ( item . type === 'container' || item . type === 'html' ) ? 'div' : item . type ; const { children , style , ... options } = item . props || { } ; const itemName = `${ parent }/${ renderedArr . length }/${ type }` ; const on = { } ; const props = { } ; const attrs = { } ; for ( const optionKey of Object . keys ( options ) ) { if ( isEvent ( optionKey ) ) { let eventOptions ; let eventFn ; if ( typeof options [ optionKey ] === 'function' ) { eventFn = options [ optionKey ] ; eventOptions = true ; } else { [ eventFn , eventOptions ] = options [ optionKey ] ; } if ( ( type as string ) . includes ( '-' ) ) { events [ `${ itemName }/${ optionKey }` ] = eventFn ; props [ optionKey ] = eventOptions ; } else { const eventName = optionKey . slice ( 2 ) . toLowerCase ( ) ; events [ `${ itemName }/${ eventName }` ] = eventFn ; on [ eventName ] = eventOptions ; } } else if ( optionKey === 'ref' || ( svgElementAttributes [ type ] && ( svgElementAttributes [ type ] . includes ( optionKey ) || svgElementAttributes [ '*' ] . includes ( optionKey ) ) ) ) { attrs [ optionKey ] = options [ optionKey ] ; } else { if ( htmlElementAttributes [ type ] && ( htmlElementAttributes [ type ] . includes ( optionKey ) || htmlElementAttributes [ '*' ] . includes ( optionKey ) ) ) { attrs [ optionKey ] = options [ optionKey ] ; } props [ optionKey ] = options [ optionKey ] ; } } const newItem = { children : [ ] , sel : type , key : itemName , data : { } , } ; if ( style && Object . keys ( style ) . length ) { newItem . data . style = formatStyle ( style ) ; } if ( Object . keys ( props ) . length ) { newItem . data . props = props ; } if ( Object . keys ( attrs ) . length ) { newItem . data . attrs = attrs ; } if ( Object . keys ( on ) . length ) { newItem . data . on = on ; } if ( options . is ) { newItem . data . is = options . is ; } renderedArr . push ( newItem ) ; await traverse ( children , newItem . children , itemName ) ; } } else if ( Array . isArray ( item ) ) { await traverse ( item , renderedArr , `${ parent }` ) ; } else if ( item && typeof item === 'string' || typeof item === 'number' ) { const lastItem = renderedArr [ renderedArr . length - 1 ] ; if ( lastItem && ! lastItem . sel ) { lastItem . text += item ; } else { renderedArr . push ( { children : [ ] , text : item , key : `${ parent }/${ renderedArr . length }/text` , } ) ; } } } } await traverse ( raw , renderedArr , parent ) ; return { tree : renderedArr , events } ; } ; const formatStyle = ( style ) => { if ( ! style ) { return null ; } const newStyle = { } ; for ( const prop of Object . keys ( style || { } ) ) { if ( typeof style [ prop ] === 'number' && ! isUnitlessNumber [ prop ] ) { style [ prop ] = `${ style [ prop ] }px` ; } newStyle [ prop ] = style [ prop ] ; } return newStyle ; } ; const isUnitlessNumber = { animationIterationCount : true , borderImageOutset : true , borderImageSlice : true , borderImageWidth : true , boxFlex : true , boxFlexGroup : true , boxOrdinalGroup : true , columnCount : true , columns : true , flex : true , flexGrow : true , flexPositive : true , flexShrink : true , flexNegative : true , flexOrder : true , gridRow : true , gridRowEnd : true , gridRowSpan : true , gridRowStart : true , gridColumn : true , gridColumnEnd : true , gridColumnSpan : true , gridColumnStart : true , fontWeight : true , lineClamp : true , lineHeight : true , opacity : true , order : true , orphans : true , tabSize : true , widows : true , zIndex : true , zoom : true , fillOpacity : true , floodOpacity : true , stopOpacity : true , strokeDasharray : true , strokeDashoffset : true , strokeMiterlimit : true , strokeOpacity : true , strokeWidth : true , } ; const toKebabCase = ( string ) => { return string . replace ( /\B(?:([A-Z])(?=[a-z]))|(?:(?<=[a-z0-9])([A-Z]))/g , '-$1$2' ) . toLowerCase ( ) ; } ;