export type CssBuilder = { openBlock ( selectors ) : void ; openBlockAt ( identifier , rule ? ) : void ; closeBlock ( ) : void ; addDec ( property , value ? ) : void ; addDecAt ( identifier , value ? ) : void ; build ( ) : string ; } ; export function createCssBuilder ( ) { const openBlockBuffer = [ ] ; let atImports = '' ; let atNamespaces = '' ; let atOthers = '' ; let cssString = '' ; let indent = '' ; const builder = { openBlock : ( selectors ) => { openBlockBuffer . push ( indent + selectors . join ( ',\n' + indent ) + ' {\n' ) ; indent += '  ' ; } , openBlockAt : ( identifier , rule ) => { openBlockBuffer . push ( indent + ( rule ? identifier + ' ' + rule : identifier ) + ' {\n' ) ; indent += '  ' ; } , closeBlock : ( ) => { indent = indent . slice ( 0 , - 2 ) ; if ( openBlockBuffer . length ) { openBlockBuffer . pop ( ) ; } else { cssString += indent + '}\n' ; } } , addDec : ( key , value = '' ) => { if ( ! key || ! value ) { return ; } while ( openBlockBuffer . length ) { cssString += openBlockBuffer . shift ( ) ; } cssString += indent + key + ': ' + value + ';\n' ; } , addDecAt : ( identifier , value = '' ) => { if ( identifier . length < 2 || identifier === '@charset' || ! value ) { return ; } const declaration = identifier + ' ' + value + ';\n' ; if ( identifier === '@import' ) { atImports += declaration ; } else if ( identifier === '@namespace' ) { atNamespaces += declaration ; } else { atOthers += declaration ; } } , build : ( ) => { return atImports + atNamespaces + atOthers + cssString ; } , } ; return builder ; }