@@ -407,6 +407,18 @@ <h1 class="section-title">App Store</h1>
407407 } ) ;
408408 } ) ;
409409
410+ // Intercept downloads for GitHub raw Python files
411+ document . addEventListener ( 'click' , function ( e ) {
412+ const link = e . target . closest ( 'a' ) ;
413+ if ( ! link ) return ;
414+
415+ const href = link . getAttribute ( 'href' ) ;
416+ if ( href && href . startsWith ( 'https://raw.githubusercontent.com/' ) && href . endsWith ( '.py' ) ) {
417+ e . preventDefault ( ) ;
418+ downloadFile ( href ) ;
419+ }
420+ } ) ;
421+
410422 // Initial Load
411423 fetch ( 'meta.json' )
412424 . then ( response => response . json ( ) )
@@ -429,6 +441,27 @@ <h1 class="section-title">App Store</h1>
429441 . catch ( error => console . error ( 'Error:' , error ) ) ;
430442 } ) ;
431443
444+ async function downloadFile ( url ) {
445+ try {
446+ const response = await fetch ( url ) ;
447+ const blob = await response . blob ( ) ;
448+ const downloadUrl = window . URL . createObjectURL ( blob ) ;
449+ const a = document . createElement ( 'a' ) ;
450+ a . href = downloadUrl ;
451+ // Extract filename from URL
452+ const filename = url . split ( '/' ) . pop ( ) || 'download.py' ;
453+ a . download = filename ;
454+ document . body . appendChild ( a ) ;
455+ a . click ( ) ;
456+ window . URL . revokeObjectURL ( downloadUrl ) ;
457+ a . remove ( ) ;
458+ } catch ( error ) {
459+ console . error ( 'Download failed:' , error ) ;
460+ // Fallback to default behavior if fetch fails
461+ window . open ( url , '_blank' ) ;
462+ }
463+ }
464+
432465 function setFilter ( filter ) {
433466 // UI Update
434467 document . querySelectorAll ( '.filter-btn' ) . forEach ( btn => {
0 commit comments