2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  {  RenderingSpecification ,  SpecialVisualization  }  from  "./SpecialVisualization"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								export  default  class  SpecialVisualisationUtils  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  For  a  given  string ,  returns  a  specification  what  parts  are  fixed  and  what  parts  are  special  renderings . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Note  that  _normal_  substitutions  are  ignored . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  import  SpecialVisualisations  from  "./SpecialVisualizations" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  // Return empty list on empty input
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  SpecialVisualisationUtils . constructSpecification ( "" ,  SpecialVisualisations . specialVisualisationsDict )  // => []
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  // Simple case
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  const  oh  =  SpecialVisualisationUtils . constructSpecification ( "The opening hours with value {opening_hours} can be seen in the following table: <br/> {opening_hours_table()}" ,  SpecialVisualisations . specialVisualisationsDict ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								     *  oh [ 0 ]  // => "The opening hours with value {opening_hours} can be seen in the following table: <br/> "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  oh [ 1 ] . func . funcName  // => "opening_hours_table"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  // Advanced cases with commas, braces and newlines should be handled without problem
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  const  templates  =  SpecialVisualisationUtils . constructSpecification ( "{send_email(&LBRACEemail&RBRACE,Broken bicycle pump,Hello&COMMA\n\nWith this email&COMMA I'd like to inform you that the bicycle pump located at https://mapcomplete.org/cyclofix?lat=&LBRACE_lat&RBRACE&lon=&LBRACE_lon&RBRACE&z=18#&LBRACEid&RBRACE is broken.\n\n Kind regards,Report this bicycle pump as broken)}" ,   SpecialVisualisations . specialVisualisationsDict ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								     *  const  templ  =  < Exclude < RenderingSpecification ,  string > >  templates [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  templ . func . funcName  // => "send_email"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  templ . args [ 0 ]  =  "{email}" 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 01:54:14 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  // Regression test - multiple special functions should all be found
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  const  spec  =  "{create_review()}{list_reviews()}" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  const  parsed  =  SpecialVisualisationUtils . constructSpecification ( spec ,  SpecialVisualisations . specialVisualisationsDict ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  parsed [ 0 ] . func . funcName  // => "create_review"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  parsed [ 1 ] . func . funcName  // => "list_reviews"
 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    public  static  constructSpecification ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        template : string , 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        specialVisualisations : Map < string ,  SpecialVisualization > , 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 13:53:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        extraMappings : SpecialVisualization [ ]  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    ) :  RenderingSpecification [ ]  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( template  ===  "" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( template [ "type" ]  !==  undefined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            console . trace ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                "Got a non-expanded template while constructing the specification, it still has a 'special-key':" , 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 13:53:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                template 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            throw  "Got a non-expanded template while constructing the specification" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Note: the '.*?' in the regex reads as 'any character, but in a non-greedy way'
 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-23 13:13:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  matched  =  template . match ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new  RegExp ( ` (.*?){ \ ([a-zA-Z_]+ \ ) \\ ((.*?) \\ )(:.*)?}(.*) ` ,  "s" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( matched  ===  null )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // IF we end up here, no changes have to be made - except to remove any resting {}
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  [ template ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  fName  =  matched [ 2 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  knownSpecial  =  specialVisualisations . get ( fName ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 13:53:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! knownSpecial  &&  extraMappings ? . length  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            knownSpecial  =  extraMappings . find ( ( em )  = >  em . funcName  ===  fName ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 13:53:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! knownSpecial )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            throw  "Didn't find a special visualisation: "  +  fName  +  " in "  +  template 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Always a boring string
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  partBefore : string  =  matched [ 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  argument : string  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            matched [ 3 ]  /* .trim()  // We don't trim, as spaces might be relevant, e.g. "what is ... of {title()}"*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  style : string  =  matched [ 4 ] ? . substring ( 1 )  ? ?  "" 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 13:53:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  partAfter : RenderingSpecification [ ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            SpecialVisualisationUtils . constructSpecification ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                matched [ 5 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                specialVisualisations , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                extraMappings 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  args : string [ ]  =  knownSpecial . args . map ( ( arg )  = >  arg . defaultValue  ? ?  "" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( argument . length  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            const  realArgs  =  argument 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                . split ( "," ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                . map ( ( str )  = >  SpecialVisualisationUtils . undoEncoding ( str ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  ( let  i  =  0 ;  i  <  realArgs . length ;  i ++ )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( args . length  <=  i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    args . push ( realArgs [ i ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    args [ i ]  =  realArgs [ i ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  element : RenderingSpecification  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            args , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            style , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            func : knownSpecial , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        partAfter . unshift ( element ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-14 13:53:56 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( partBefore . length  >  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-13 17:56:33 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            partAfter . unshift ( partBefore ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  partAfter 
							 
						 
					
						
							
								
									
										
										
										
											2024-01-25 13:41:33 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    private  static  undoEncoding ( str : string )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  str 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            . trim ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            . replace ( /&LPARENS/g ,  "(" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            . replace ( /&RPARENS/g ,  ")" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            . replace ( /&LBRACE/g ,  "{" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            . replace ( /&RBRACE/g ,  "}" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            . replace ( /&COMMA/g ,  "," ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}