@@ -32,6 +32,7 @@ const baseURLPrefix = (() => {
3232$ ( document ) . ready ( function ( ) {
3333 BrowserFallbacks . init ( ) ;
3434 DarkMode . init ( ) ;
35+ GitTurns20 . init ( ) ;
3536 Search . init ( ) ;
3637 Dropdowns . init ( ) ;
3738 Forms . init ( ) ;
@@ -102,6 +103,56 @@ var BrowserFallbacks = {
102103
103104}
104105
106+ var GitTurns20 = {
107+ keySequence : '20' ,
108+ keySequenceOffset : 0 ,
109+
110+ init : function ( ) {
111+ const today = new Date ( ) ;
112+ if ( today . getFullYear ( ) === 2025 && today . getMonth ( ) === 3 && today . getDate ( ) === 7 ) {
113+ this . celebrate ( ) ;
114+ }
115+ } ,
116+
117+ keydown : function ( e ) {
118+ if ( this . keySequenceOffset >= this . keySequence . length ) return ;
119+ if ( this . keySequence [ this . keySequenceOffset ] === e . key ) {
120+ if ( ++ this . keySequenceOffset === this . keySequence . length ) {
121+ this . celebrate ( ) ;
122+ this . keySequenceOffset = 0 ;
123+ }
124+ }
125+ } ,
126+
127+ celebrate : function ( ) {
128+ document . documentElement . dataset . celebration = 'git-turns-20' ;
129+ $ ( "#tagline" ) . html ( '<a href="https://discord.com/channels/1042895022950994071/1356927327388434564">--20th-anniversary</a>' ) ;
130+ if ( $ ( "#masthead" ) . length ) { // only do this on the front page
131+ ( async ( ) => {
132+ await import ( 'https://cdn.jsdelivr.net/npm/[email protected] /dist/confetti.browser.min.js' ) ; 133+ const count = 200 ;
134+ const defaults = {
135+ origin : { y : 0.7 }
136+ } ;
137+
138+ for ( const [ particleRatio , opts ] of [
139+ [ 0.25 , { spread : 26 , startVelocity : 55 } ] ,
140+ [ 0.2 , { spread : 60 } ] ,
141+ [ 0.35 , { spread : 100 , decay : 0.91 , scalar : 0.8 } ] ,
142+ [ 0.1 , { spread : 120 , startVelocity : 25 , decay : 0.92 , scalar : 1.2 } ] ,
143+ [ 0.1 , { spread : 120 , startVelocity : 45 } ] ,
144+ ] ) {
145+ window . confetti ( {
146+ ...defaults ,
147+ ...opts ,
148+ particleCount : Math . floor ( count * particleRatio )
149+ } ) ;
150+ }
151+ } ) ( ) . catch ( console . error ) ;
152+ }
153+ }
154+ } ;
155+
105156var Search = {
106157 searching : false ,
107158 currentSearch : '' ,
@@ -166,6 +217,7 @@ var Search = {
166217 e . preventDefault ( ) ;
167218 $ ( 'form#search input' ) . focus ( ) ;
168219 }
220+ else if ( e . target . tagName . toUpperCase ( ) !== 'INPUT' ) GitTurns20 . keydown ( e ) ;
169221 } ) ;
170222 } ,
171223
@@ -343,11 +395,11 @@ var Search = {
343395 ( async ( ) => {
344396 const pagefindURL =
345397 `${ baseURLPrefix } pagefind/pagefind.js`
346- // adjust the `baseURLPrefix` if it is relative: the `import`
347- // is relative to the _script URL_ here, which is in /js/.
348- // That is different from other uses of `baseURLPrefix`, which
349- // replace `href` and `src` attributes which are relative to the
350- // page itself that is outside of /js/.
398+ // adjust the `baseURLPrefix` if it is relative: the `import`
399+ // is relative to the _script URL_ here, which is in /js/.
400+ // That is different from other uses of `baseURLPrefix`, which
401+ // replace `href` and `src` attributes which are relative to the
402+ // page itself that is outside of /js/.
351403 . replace ( / ^ \. \/ / , '../' )
352404 Search . pagefind = await import ( pagefindURL ) ;
353405 const options = {
0 commit comments