2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								/ * *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  Copyright  2017  Google  Inc .  All  rights  reserved . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  Licensed  under  the  Apache  License ,  Version  2.0  ( the  "License" ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  you  may  not  use  this  file  except  in  compliance  with  the  License . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  You  may  obtain  a  copy  of  the  License  at 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *      http : //www.apache.org/licenses/LICENSE-2.0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  Unless  required  by  applicable  law  or  agreed  to  in  writing ,  software 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  distributed  under  the  License  is  distributed  on  an  "AS IS"  BASIS , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  WITHOUT  WARRANTIES  OR  CONDITIONS  OF  ANY  KIND ,  either  express  or  implied . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  See  the  License  for  the  specific  language  governing  permissions  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  limitations  under  the  License . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								const  path  =  require ( 'path' ) ;  
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								const  Message  =  require ( '../Message' ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-22 11:03:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								function  runCommands ( sources ,  { libversion ,  chromiumVersion ,  firefoxVersion ,  onlyBrowserVersions } )  {  
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  // Release version is everything that doesn't include "-".
 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-13 18:26:38 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								  const  isReleaseVersion  =  ! libversion . includes ( '-' ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  messages  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( const  source  of  sources )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  text  =  source . text ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  commandStartRegex  =  /<!--\s*gen:([a-z-]+)\s*-->/ig ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  commandEndRegex  =  /<!--\s*gen:stop\s*-->/ig ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    let  start ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    const  sourceEdits  =  new  SourceEdits ( source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // Extract all commands from source
 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    while  ( start  =  commandStartRegex . exec ( text ) )  {  // eslint-disable-line no-cond-assign
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      commandEndRegex . lastIndex  =  commandStartRegex . lastIndex ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      const  end  =  commandEndRegex . exec ( text ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      if  ( ! end )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        messages . push ( Message . error ( ` Failed to find 'gen:stop' for command  ${ start [ 0 ] } ` ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return  messages ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      } 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								      const  commandName  =  start [ 1 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      const  from  =  commandStartRegex . lastIndex ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      const  to  =  end . index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      commandStartRegex . lastIndex  =  commandEndRegex . lastIndex ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								      let  newText  =  null ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-22 11:03:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								      if  ( commandName  ===  'chromium-version' ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  chromiumVersion ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( commandName  ===  'firefox-version' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  firefoxVersion ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( commandName  ===  'chromium-version-badge' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  ` [](https://www.chromium.org/Home) ` ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( commandName  ===  'firefox-version-badge' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  ` [](https://www.mozilla.org/en-US/firefox/new/) ` ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-22 11:03:35 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( onlyBrowserVersions ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( commandName  ===  'version' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  isReleaseVersion  ?  'v'  +  libversion  :  'Tip-Of-Tree' ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( commandName  ===  'toc' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  generateTableOfContents ( source . text ( ) ,  to ,  false  /* topLevelOnly */ ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( commandName  ===  'toc-top-level' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  generateTableOfContents ( source . text ( ) ,  to ,  true  /* topLevelOnly */ ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      else  if  ( commandName . startsWith ( 'toc-extends-' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        newText  =  generateTableOfContentsForSuperclass ( source . text ( ) ,  'class: '  +  commandName . substring ( 'toc-extends-' . length ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      if  ( newText  ===  null ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        messages . push ( Message . error ( ` Unknown command 'gen: ${ commandName } ' ` ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        sourceEdits . edit ( from ,  to ,  newText ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    sourceEdits . commit ( messages ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  return  messages ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								function  getTOCEntriesForText ( text )  {  
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  ids  =  new  Set ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  titles  =  [ ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-04 22:28:09 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								  const  titleRegex  =  /^(#+)\s+(.*)$/ ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  let  insideCodeBlock  =  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								  let  offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  text . split ( '\n' ) . forEach ( ( aLine ,  lineNumber )  =>  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  line  =  aLine . trim ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( line . startsWith ( '```' ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      insideCodeBlock  =  ! insideCodeBlock ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-04 22:28:09 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    else  if  ( ! insideCodeBlock  &&  line . match ( titleRegex ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								      titles . push ( { line ,  offset :  offset  +  lineNumber } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    offset  +=  aLine . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  let  tocEntries  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( const  { line ,  offset }  of  titles )  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-04 22:28:09 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    const  [ ,  nesting ,  name ]  =  line . match ( titleRegex ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  delinkifiedName  =  name . replace ( /\[([^\]]+)\]\([^)]+\)/g ,  '$1' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								    const  id  =  delinkifiedName . trim ( ) . toLowerCase ( ) . replace ( /\s/g ,  '-' ) . replace ( /[^-0-9a-zа  ,  '' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    let  dedupId  =  id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    let  counter  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    while  ( ids . has ( dedupId ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      dedupId  =  id  +  '-'  +  ( ++ counter ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    ids . add ( dedupId ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    tocEntries . push ( { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      level :  nesting . length , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      name :  delinkifiedName , 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								      id :  dedupId , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      offset , 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								  return  tocEntries ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-03-18 15:34:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								/ * *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 *  @ param  { string }  text 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 * / 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								function  autocorrectInvalidLinks ( projectRoot ,  sources ,  allowedFilePaths )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  pathToHashLinks  =  new  Map ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-18 15:34:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( const  source  of  sources )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  text  =  source . text ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    const  hashLinks  =  new  Set ( getTOCEntriesForText ( text ) . map ( entry  =>  entry . id ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    pathToHashLinks . set ( source . filePath ( ) ,  hashLinks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  messages  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( const  source  of  sources )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  allRelativePaths  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    for  ( const  filepath  of  allowedFilePaths )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      allRelativePaths . push ( '/'  +  path . relative ( projectRoot ,  filepath ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      allRelativePaths . push ( path . relative ( path . dirname ( source . filePath ( ) ) ,  filepath ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-18 15:34:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								    const  sourceEdits  =  new  SourceEdits ( source ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    let  offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  edits  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  lines  =  source . text ( ) . split ( '\n' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    lines . forEach ( ( line ,  lineNumber )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      const  linkRegex  =  /\]\(([^\)]*)\)/gm ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      let  match ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      while  ( match  =  linkRegex . exec ( line ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        const  hrefOffset  =  offset  +  lineNumber  +  match . index  +  2 ;  // +2 since we have to skip ](
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        const  [ ,  href ]  =  match ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( href . startsWith ( 'http://' )  ||  href . startsWith ( 'https://' )  ||  href . startsWith ( 'mailto:' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        const  [ relativePath ,  hash ]  =  href . split ( '#' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        const  hashOffset  =  hrefOffset  +  relativePath . length  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        let  resolvedPath  =  resolveLinkPath ( source ,  relativePath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        let  hashLinks  =  pathToHashLinks . get ( resolvedPath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( ! hashLinks )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          // Attempt to autocorrect
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          const  newRelativePath  =  autocorrectText ( relativePath ,  allRelativePaths ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          if  ( ! newRelativePath )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            messages . push ( Message . error ( ` Bad link in  ${ source . projectPath ( ) } : ${ lineNumber  +  1 } : file  ${ relativePath }  does not exist ` ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          resolvedPath  =  resolveLinkPath ( source ,  newRelativePath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          hashLinks  =  pathToHashLinks . get ( resolvedPath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          sourceEdits . edit ( hrefOffset ,  hrefOffset  +  relativePath . length ,  newRelativePath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( ! hash  ||  hashLinks . has ( hash ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        const  newHashLink  =  autocorrectText ( hash ,  [ ... hashLinks ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        if  ( newHashLink )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          sourceEdits . edit ( hashOffset ,  hashOffset  +  hash . length ,  newHashLink ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								          messages . push ( Message . error ( ` Bad link in  ${ source . projectPath ( ) } : ${ lineNumber  +  1 } : hash "# ${ hash } " does not exist in " ${ path . relative ( projectRoot ,  resolvedPath ) } " ` ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      offset  +=  line . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    sourceEdits . commit ( messages ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-18 15:34:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  return  messages ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  function  resolveLinkPath ( source ,  relativePath )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! relativePath ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      return  source . filePath ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( relativePath . startsWith ( '/' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      return  path . resolve ( projectRoot ,  '.'  +  relativePath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  path . resolve ( path . dirname ( source . filePath ( ) ) ,  relativePath ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								class  SourceEdits  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  constructor ( source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    this . _source  =  source ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    this . _edits  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  edit ( from ,  to ,  newText )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    this . _edits . push ( { from ,  to ,  newText } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  commit ( messages  =  [ ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( ! this . _edits . length ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    this . _edits . sort ( ( a ,  b )  =>  a . from  -  b . from ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    for  ( const  edit  of  this . _edits )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      if  ( edit . from  >  edit . to )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        messages . push ( Message . error ( 'INTERNAL ERROR: incorrect edit!' ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    for  ( let  i  =  0 ;  i  <  this . _edits . length  -  1 ;  ++ i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      if  ( this . _edits [ i ] . to  >  this . _edits [ i  +  1 ] . from )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        messages . push ( Message . error ( 'INTERNAL ERROR: edits are overlapping!' ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    this . _edits . reverse ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    let  text  =  this . _source . text ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    for  ( const  edit  of  this . _edits ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      text  =  text . substring ( 0 ,  edit . from )  +  edit . newText  +  text . substring ( edit . to ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    this . _source . setText ( text ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								function  autocorrectText ( text ,  options ,  maxCorrectionsRatio  =  0.5 )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  if  ( ! options . length ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  scores  =  options . map ( option  =>  ( { option ,  score :  levenshteinDistance ( text ,  option ) } ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  scores . sort ( ( a ,  b )  =>  a . score  -  b . score ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  if  ( scores [ 0 ] . score  >  text . length  *  maxCorrectionsRatio ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  return  scores [ 0 ] . option ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								function  levenshteinDistance ( a ,  b )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  N  =  a . length ,  M  =  b . length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  d  =  new  Int32Array ( N  *  M ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( let  i  =  0 ;  i  <  N  *  M ;  ++ i ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    d [ i ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( let  j  =  0 ;  j  <  M ;  ++ j ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    d [ j ]  =  j ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( let  i  =  0 ;  i  <  N ;  ++ i ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    d [ i  *  M ]  =  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( let  i  =  1 ;  i  <  N ;  ++ i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    for  ( let  j  =  1 ;  j  <  M ;  ++ j )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      const  cost  =  a [ i ]  ===  b [ j ]  ?  0  :  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      d [ i  *  M  +  j ]  =  Math . min ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        d [ ( i  -  1 )  *  M  +  j ]  +  1 ,  // d[i-1][j] + 1
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        d [ i  *  M  +  j  -  1 ]  +  1 ,  // d[i][j - 1] + 1
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        d [ ( i  -  1 )  *  M  +  j  -  1 ]  +  cost  // d[i - 1][j - 1] + cost
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  return  d [ N  *  M  -  1 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-18 15:34:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								function  generateTableOfContents ( text ,  offset ,  topLevelOnly )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  allTocEntries  =  getTOCEntriesForText ( text ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  let  tocEntries  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  let  nesting  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( const  tocEntry  of  allTocEntries )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( tocEntry . offset  <  offset ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( tocEntries . length )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      nesting  +=  tocEntry . level  -  tocEntries [ tocEntries . length  -  1 ] . level ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      if  ( nesting  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    tocEntries . push ( tocEntry ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  minLevel  =  Math . min ( ... tocEntries . map ( entry  =>  entry . level ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  tocEntries . forEach ( entry  =>  entry . level  -=  minLevel ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-22 12:21:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								  if  ( topLevelOnly ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    tocEntries  =  tocEntries . filter ( entry  =>  ! entry . level ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-11-18 18:18:28 -08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  return  '\n'  +  tocEntries . map ( entry  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  prefix  =  entry . level  %  2  ===  0  ?  '-'  :  '*' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  padding  =  '  ' . repeat ( entry . level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  ` ${ padding } ${ prefix }  [ ${ entry . name } ](# ${ entry . id } ) ` ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } ) . join ( '\n' )  +  '\n' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2020-01-27 10:05:04 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								function  generateTableOfContentsForSuperclass ( text ,  name )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  const  allTocEntries  =  getTOCEntriesForText ( text ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  for  ( const  tocEntry  of  allTocEntries )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    if  ( tocEntry . name  !==  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								      continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    const  offset  =  text . indexOf ( '<!-- GEN:stop -->' ,  tocEntry . offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    return  generateTableOfContents ( text ,  offset ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  return  text ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2020-03-18 15:34:53 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-23 19:52:06 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
								
									
								 
							
							
								module . exports  =  { autocorrectInvalidLinks ,  runCommands } ;