import { BlockAttributes } from "./types" ; type NodeType = "stringInQuotes" | "stringWithBrackets" | "word" | "array" ; type Node = [ any , number , NodeType ] ; const normalizeValue = ( value ) : boolean | number | string => { if ( value . toLowerCase ( ) === "true" ) { return true ; } else if ( value . toLowerCase ( ) === "false" ) { return false ; } else if ( ! isNaN ( value as any ) ) { return parseFloat ( value as any ) ; } return value ; } ; const extractStringWithBrackets = ( text , start ) : Node | void => { if ( text [ start ] !== "(" ) { return ; } let bracketDepth = 1 ; let end = start + 1 ; while ( end < text . length ) { if ( text [ end ] === "(" ) { bracketDepth += 1 ; } else if ( text [ end ] === ")" ) { bracketDepth -= 1 ; } end += 1 ; if ( bracketDepth === 0 ) { break ; } } return [ text . substring ( start , end ) , end , "stringWithBrackets" ] ; } ; const extractStringInQuotes = ( text , start ) : Node | void => { const quote = text [ start ] ; if ( ! "'\"`" . includes ( quote ) ) { return ; } let end = start + 1 ; const chars = [ ] ; while ( end < text . length ) { if ( text [ end ] === "\\" ) { if ( end + 1 < text . length ) { chars . push ( text [ end + 1 ] ) ; } end += 2 ; continue ; } if ( text [ end ] === quote ) { end += 1 ; break ; } chars . push ( text [ end ] ) ; end += 1 ; } return [ chars . join ( "" ) , end , "stringInQuotes" ] ; } ; const wordCharRegExp = /^[^,;=\s]$/ ; const extractWord = ( text , start ) : Node | void => { let i = start ; let bracketDepth = 0 ; while ( i < text . length ) { const char = text [ i ] ; if ( ! wordCharRegExp . test ( char ) ) { break ; } if ( char === "[" ) { bracketDepth += 1 ; } else if ( char === "]" ) { bracketDepth -= 1 ; } if ( bracketDepth < 0 ) { break ; } i += 1 ; } if ( i === start ) { return ; } return [ text . substring ( start , i ) , i , "word" ] ; } ; const extractArray = ( text , start ) : Node | void => { if ( text [ start ] !== "[" ) { return ; } const result = [ ] ; let i = start + 1 ; while ( i < text . length ) { const char = text [ i ] ; if ( char === "]" ) { i += 1 ; break ; } const node = extractArray ( text , i ) || extractStringWithBrackets ( text , i ) || extractStringInQuotes ( text , i ) || extractWord ( text , i ) ; if ( node ) { const [ rawValue , subEnd , nodeType ] = node ; const value = nodeType === "word" ? normalizeValue ( rawValue ) : rawValue ; i = subEnd ; result . push ( value ) ; } else { i += 1 ; } } return [ result , i , "array" ] ; } ; param text export const parseBlockAttributes = ( text ? ) : BlockAttributes => { let textToParse = ( text || "" ) . trim ( ) ; if ( textToParse [ 0 ] === "{" && textToParse [ textToParse . length - 1 ] === "}" ) { textToParse = textToParse . slice ( 1 , - 1 ) ; } const output = { } ; let pendingKey ; let i = 0 ; while ( i < textToParse . length ) { const node = extractArray ( textToParse , i ) || extractStringWithBrackets ( textToParse , i ) || extractStringInQuotes ( textToParse , i ) || extractWord ( textToParse , i ) ; if ( node ) { const keyIsPending = typeof pendingKey === "string" ; const [ rawValue , subEnd , nodeType ] = node ; const value = nodeType === "word" && keyIsPending ? normalizeValue ( rawValue ) : rawValue ; i = subEnd ; if ( keyIsPending ) { output [ pendingKey ! ] = value ; pendingKey = undefined ; } else if ( textToParse [ i ] === "=" ) { pendingKey = value ; } else { const firstChar = value [ 0 ] ; let specialAttribute ; switch ( firstChar ) { case "." : specialAttribute = "class" ; break ; case "#" : specialAttribute = "id" ; break ; } if ( specialAttribute ) { const specialValue = value . substring ( 1 ) ; if ( specialValue . length ) { const previousValue = output [ specialAttribute ] ; output [ specialAttribute ] = typeof previousValue === "undefined" ? specialValue : `${ previousValue } ${ specialValue }` ; } } else { if ( typeof value === "string" ) { output [ value ] = true ; } } } } else { i += 1 ; } } return output ; } ;