@@ -1416,18 +1416,43 @@ const setupDevToolsShortcuts = () => {
14161416const setupExternalLinkHandling = ( ) => {
14171417 if ( ! win ) return ;
14181418
1419+ // Helper function to check if URL is external
1420+ const isExternalUrl = ( url : string ) : boolean => {
1421+ try {
1422+ const urlObj = new URL ( url ) ;
1423+ // Allow localhost and internal URLs
1424+ if ( urlObj . hostname === 'localhost' || urlObj . hostname === '127.0.0.1' ) {
1425+ return false ;
1426+ }
1427+ // Allow hash navigation
1428+ if ( url . startsWith ( '#' ) || url . startsWith ( '/#' ) ) {
1429+ return false ;
1430+ }
1431+ // External URLs start with http/https and are not localhost
1432+ return urlObj . protocol === 'http:' || urlObj . protocol === 'https:' ;
1433+ } catch {
1434+ return false ;
1435+ }
1436+ } ;
1437+
14191438 // handle new window open
14201439 win . webContents . setWindowOpenHandler ( ( { url } ) => {
1421- if ( url . startsWith ( 'https:' ) || url . startsWith ( 'http:' ) ) {
1440+ if ( isExternalUrl ( url ) ) {
14221441 shell . openExternal ( url ) ;
1442+ return { action : 'deny' } ;
14231443 }
14241444 return { action : 'deny' } ;
14251445 } ) ;
14261446
14271447 // handle navigation
14281448 win . webContents . on ( 'will-navigate' , ( event , url ) => {
1429- event . preventDefault ( ) ;
1430- shell . openExternal ( url ) ;
1449+ // Only prevent navigation and open external URLs
1450+ // Allow internal navigation like hash changes
1451+ if ( isExternalUrl ( url ) ) {
1452+ event . preventDefault ( ) ;
1453+ shell . openExternal ( url ) ;
1454+ }
1455+ // For internal URLs (localhost, hash navigation), allow navigation to proceed
14311456 } ) ;
14321457} ;
14331458
0 commit comments