this._traces.length)&&(this._traces.push(new i.Trace({x:this._width*(this._randomRocketsPoint?(0,o.randomInt)(0,100):this.rocketsPoint)/100,y:this._height,dx:this._mx&&this.mouse.move||this._m?this._mx:(0,o.randomInt)(this.boundaries.x,this.boundaries.width-2*this.boundaries.x),dy:this._my&&this.mouse.move||this._m?this._my:(0,o.randomInt)(this.boundaries.y,.5*this.boundaries.height),ctx:this._ctx,hue:(0,o.randomInt)(this.hue.min,this.hue.max),speed:this.speed,acceleration:this.acceleration,traceLength:this.trace})),this._tick=0)}drawTrace(){for(var t=this._traces.length;t--;)this._traces[t].draw(),this._traces[t].update(((i,s,e)=>{this.initExplosion(i,s,e),this._sound.play(),this._traces.splice(t,1)}))}initExplosion(t,i,s){for(var e=this.particles;e--;)this._explosions.push(new n.Explosion({x:t,y:i,ctx:this._ctx,hue:s,friction:this.friction,gravity:this.gravity,explosionLength:this.explosion,brightness:this.brightness,exp:this._experimentals}))}drawExplosion(){for(var t=this._explosions.length;t--;)this._explosions[t].draw(),this._explosions[t].update((()=>{this._explosions.splice(t,1)}))}}})(),e})()}));","/**\n * @typedef Command\n * @property {string} command\n * @property {string} responseType\n * @property {string?} value\n * @property {string[]?} headers\n * @property {string[]?} rows\n */\n\n/**\n * @type {Command[]} commands\n */\nimport commands from \"./resources/commands.json\";\nimport { getCV, pif, rmRf, setDarkMode } from \"./custom-comands\";\nimport { dragElement } from \"./draggable\";\n\n// Table containing the orders (useful for the completion of the orders)\nlet commandsList = [];\ncommands.forEach((c) => {\n commandsList.push(c.command);\n});\n\n// Commands that require JS processing\nconst customCommands = [\"clear\", \"dark\", \"light\", \"get cv\"];\ncommandsList = commandsList.concat(customCommands);\n\n// Eyster eggs' commands not available for autocompletion\nconst hiddenCommands = [\"pif\", \"rm -rf /\"];\n\n// Added the ability to move the window for PCs\nif (window.innerWidth > 1024) {\n dragElement(document.querySelector(\".terminal\"));\n}\n\n// Order history table\nconst commandsHistory = [];\nlet historyMode = false;\nlet historyIndex = -1;\nconst terminalBody = document.querySelector(\".terminal__body\");\n\n// Adding the default line\naddNewLine();\n\n// December Easter egg, adding snowflakes\nconst now = new Date();\nif (now.getMonth() === 11) {\n let htmlFlakes = \"\";\n for (let i = 0; i < 6; i++) {\n htmlFlakes += `❅
❆
`;\n }\n const html = `${htmlFlakes}
`;\n document.body.append(stringToDom(html));\n}\n\n// Set to dark mode if the browser theme is dark\nif (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {\n setDarkMode(true);\n}\n\n/**\n * Returns the HTML of the response for a given command\n * @param {string} command\n */\nfunction getDomForCommand(command) {\n const commandObj = commands.find((el) => el.command === command);\n let html = \"\";\n if (commandObj === undefined) {\n html = `'${\n command.split(\" \")[0]\n }' is not recognized as an internal command or external command, operable program or batch file. Type the help
command to display a list of available commands.`;\n } else {\n if (commandObj.responseType === \"list\" && Array.isArray(commandObj.value)) {\n html = \"\";\n html += commandObj.value.map((s) => `- ${s}
`).join(\"\");\n html += \"
\";\n } else if (commandObj.responseType === \"text\") {\n html = commandObj.value;\n } else if (commandObj.responseType === \"table\") {\n const headers = commandObj.headers;\n const rows = commandObj.rows;\n const thsHtml = headers.map((h) => `${h} | `).join(\"\");\n const tdsHtml = rows\n .map((r) => `${r.map((rtd) => `${rtd} | `).join(\"\")}
`)\n .join(\"\");\n html = ``;\n } else if (commandObj.responseType === \"code\") {\n html = `${commandObj.value.join(\"\\n\")}
`;\n }\n }\n\n return html;\n}\n\n/**\n * Adds a new command input line and disables the previous one.\n * @param {string|null} previousUid uid de la ligne précédente.\n */\nfunction addNewLine(previousUid = null) {\n const uid = Math.random().toString(36).replace(\"0.\", \"\");\n // terminal__line\n const terminalLineEl = document.createElement(\"div\");\n terminalLineEl.classList.add(\"terminal__line\");\n\n // terminal__response\n const terminalResponseEl = document.createElement(\"div\");\n terminalResponseEl.classList.add(\"terminal__response\");\n terminalResponseEl.id = `response-${uid}`;\n\n // input text\n const inputEl = document.createElement(\"input\");\n inputEl.type = \"text\";\n inputEl.id = `input-${uid}`;\n inputEl.autocapitalize = \"off\";\n inputEl.dataset.uid = uid;\n inputEl.dataset.active = \"1\"; // Needed for focus\n inputEl.addEventListener(\"keydown\", onCommandInput);\n\n terminalLineEl.appendChild(inputEl);\n if (previousUid) {\n const previousInputEl = document.getElementById(previousUid);\n if (previousInputEl) {\n previousInputEl.setAttribute(\"disabled\", \"true\");\n previousInputEl.removeEventListener(\"keydown\", onCommandInput);\n delete previousInputEl.dataset.active;\n }\n }\n document.getElementById(\"terminal\").appendChild(terminalLineEl);\n document.getElementById(\"terminal\").appendChild(terminalResponseEl);\n\n inputEl.focus(); // Adds the focus as soon as the field is created\n}\n\n/**\n * Manages the keydown on the command input.\n * @param e\n */\nfunction onCommandInput(e) {\n const commandValue = e.target.value.trim().toLowerCase();\n if (e.keyCode === 13) {\n // ENTER\n if (commandValue !== \"\") {\n historyMode = false;\n const idResponse = `response-${e.target.dataset.uid}`;\n const responseEl = document.getElementById(idResponse);\n let html;\n if (\n hiddenCommands.includes(commandValue) ||\n customCommands.includes(commandValue)\n ) {\n html = handleCustomCommands(commandValue);\n } else {\n html = getDomForCommand(commandValue);\n }\n if (responseEl) {\n responseEl.innerHTML = html;\n commandsHistory.push(commandValue);\n addNewLine(e.target.id);\n }\n }\n } else if (e.keyCode === 9) {\n // TAB\n e.preventDefault();\n if (commandValue === \"\") {\n this.value = \"help\";\n } else {\n const matchingCommand = commandsList.find((c) =>\n c.startsWith(commandValue)\n );\n if (matchingCommand) {\n this.value = matchingCommand;\n }\n }\n historyMode = false;\n } else if (e.keyCode === 38 || e.keyCode === 40) {\n // UP / DOWN\n // History management\n if (commandsHistory.length > 0) {\n if (historyMode === false) {\n historyIndex = commandsHistory.length - 1;\n } else {\n if (e.keyCode === 38 && historyIndex !== 0) {\n // UP\n historyIndex--;\n } else if (\n e.keyCode === 40 &&\n historyIndex !== commandsHistory.length - 1\n ) {\n historyIndex++;\n }\n }\n this.value = commandsHistory[historyIndex];\n }\n historyMode = true;\n }\n}\n\n/**\n * Allows to manage hidden commands (not proposed in the autocompletion)\n * @param {string} command\n * @returns {string|void} Html to be displayed in the response of the command\n */\nfunction handleCustomCommands(command) {\n switch (command) {\n case \"pif\":\n pif();\n return \"Let's go !\";\n case \"light\":\n if (!document.body.classList.contains(\"dark-mode\"))\n return \"You are already in light mode.\";\n setDarkMode(false);\n return \"Your are now in light mode.\";\n case \"dark\":\n if (document.body.classList.contains(\"dark-mode\"))\n return \"You are already in dark mode.\";\n setDarkMode(true);\n return \"You are now in dark mode.\";\n case \"get cv\":\n getCV();\n return \"The CV will be downloaded.\";\n case \"rm -rf /\":\n rmRf();\n return \"🎆\";\n case \"clear\":\n terminalBody.innerHTML = ``;\n return;\n }\n}\n\n/**\n * Convert HTML to DOM object\n * @param html\n * @returns {DocumentFragment}\n */\nfunction stringToDom(html) {\n return document.createRange().createContextualFragment(html);\n}\n\n// ------------------------------------------------------------------------------------\n// EVENT LISTENNER\n// ------------------------------------------------------------------------------------\n\n// Added focus on the input even if you click on the body (to keep the cursor)\ndocument.body.addEventListener(\"click\", function (e) {\n if (e.target.tagName !== \"INPUT\") {\n const activeInput = document.querySelector(\"input[data-active]\");\n activeInput.focus();\n }\n});\n\ndocument.querySelector(\".fake-close\").addEventListener(\"click\", function (e) {\n const terminalEl = document.querySelector(\".terminal\");\n terminalEl.parentElement.removeChild(terminalEl);\n});\n","export function dragElement(elmnt) {\n var pos1 = 0,\n pos2 = 0,\n pos3 = 0,\n pos4 = 0;\n const element = document.querySelector(\".terminal__header\");\n if (element) {\n // if present, the header is where you move the DIV from:\n element.onmousedown = dragMouseDown;\n } else {\n // otherwise, move the DIV from anywhere inside the DIV:\n elmnt.onmousedown = dragMouseDown;\n }\n\n function dragMouseDown(e) {\n e = e || window.event;\n e.preventDefault();\n // get the mouse cursor position at startup:\n pos3 = e.clientX;\n pos4 = e.clientY;\n document.onmouseup = closeDragElement;\n // call a function whenever the cursor moves:\n document.onmousemove = elementDrag;\n }\n\n function elementDrag(e) {\n e = e || window.event;\n e.preventDefault();\n // calculate the new cursor position:\n pos1 = pos3 - e.clientX;\n pos2 = pos4 - e.clientY;\n pos3 = e.clientX;\n pos4 = e.clientY;\n // set the element's new position:\n elmnt.style.top = elmnt.offsetTop - pos2 + \"px\";\n elmnt.style.left = elmnt.offsetLeft - pos1 + \"px\";\n }\n\n function closeDragElement() {\n // stop moving when mouse button is released:\n document.onmouseup = null;\n document.onmousemove = null;\n }\n}\n"],"names":["$d8a01dcfa0a5762f$exports","JSON","parse","$eebc2c287dcd06b1$var$module","main","global","module","isWorker","workerSize","canUseWorker","Worker","Blob","Promise","OffscreenCanvas","OffscreenCanvasRenderingContext2D","HTMLCanvasElement","prototype","transferControlToOffscreen","URL","createObjectURL","noop","promise","func","ModulePromise","exports","Prom","frame","cancel","TIME","frames","lastFrameTime","worker","prom","resolves","defaultFire","raf","Math","floor","requestAnimationFrame","cancelAnimationFrame","cb","id","random","onFrame","time","setTimeout","timer","clearTimeout","getWorker","code","toString","join","e","console","warn","execute","options","callback","postMessage","init","canvas","offscreen","fire","size","done","slice","resolve","workerDone","msg","data","removeEventListener","addEventListener","bind","reset","decorate","defaults","particleCount","angle","spread","startVelocity","decay","gravity","drift","ticks","x","y","shapes","zIndex","colors","disableForReducedMotion","scalar","prop","name","transform","val","convert","onlyPositiveInt","number","toDecimal","str","parseInt","colorsToRgb","map","hexToRgb","String","replace","length","r","substring","g","b","setCanvasWindowSize","width","document","documentElement","clientWidth","height","clientHeight","setCanvasRectSize","rect","getBoundingClientRect","animate","fettis","resizer","animationFrame","destroy","animatingFettis","context","getContext","onDone","clearRect","update","filter","fetti","cos","angle2D","velocity","sin","wobble","wobbleSpeed","tiltAngle","tiltSin","tiltCos","wobbleX","wobbleY","progress","tick","totalTicks","x1","y1","x2","y2","fillStyle","color","beginPath","shape","ellipse","abs","ovalScalar","PI","radiusX","radiusY","rotation","startAngle","endAngle","antiClockwise","save","translate","rotate","scale","arc","restore","moveTo","lineTo","closePath","fill","updateFetti","addFettis","concat","confettiCannon","globalOpts","animationObj","isLibCanvas","allowResize","globalDisableForReducedMotion","Boolean","initialized","__confetti_initialized","preferLessMotion","matchMedia","matches","fireLocal","opts","radAngle","radSpread","min","max","Number","origin","Object","getOrigin","temp","startX","startY","push","createElement","style","position","top","left","pointerEvents","getCanvas","body","appendChild","onResize","obj","resize","removeChild","getDefaultFire","useWorker","apply","this","arguments","create","window","self","$eebc2c287dcd06b1$export$2e2bcd8739ae039","$dcf1a4d0a69352ac$export$faf76607d863714d","value","classList","add","remove","t","i","$cb75fafee029b816$exports","define","amd","s","t1","defineProperty","Explosion","ctx","h","hue","n","exp","o","a","friction","brightness","c","explosionLength","_","_coordinates","_alpha","_x","_y","_exp","_ctx","_gravity","_friction","_explosionLength","_angle","randomFloat","_speed","randomInt","_hue","_brightness","_decay","pop","unshift","draw","hsla","strokeStyle","stroke","getDistance","pow","sqrt","__awaiter","next","throw","then","Sound","_buffer","onInit","_audioContext","AudioContext","webkitAudioContext","assign","enabled","files","volume","load","fetch","arrayBuffer","decodeAudioData","catch","play","createBufferSource","createGain","buffer","gain","connect","destination","start","Trace","dx","dy","speed","traceLength","acceleration","_currentDistance","_sx","_sy","_dx","_dy","_traceLength","_acceleration","_totalDistance","atan2","call","t2","Fireworks","autoresize","boundaries","delay","mouse","sound","trace","explosion","d","u","opacity","l","particles","p","rocketsPoint","m","v","_tick","_version","_running","_randomRocketsPoint","_experimentals","_m","_container","_canvas","_sound","setSize","setBoundaries","visible","click","move","windowResize","mouseDown","mouseUp","mouseMove","isRunning","version","clear","render","stop","unmount","pause","_traces","_explosions","_width","_height","setOptions","entries","hasOwnProperty","Error","useMouse","_mx","pageX","offsetLeft","_my","pageY","offsetTop","globalCompositeOperation","fillRect","drawBoundaries","initTrace","drawTrace","drawExplosion","_ds","initExplosion","splice","$1e660b916d30a31c$var$commandsList","$parcel$interopDefault","forEach","command","$1e660b916d30a31c$var$customCommands","$1e660b916d30a31c$var$hiddenCommands","innerWidth","elmnt","pos1","pos2","pos3","pos4","element","querySelector","dragMouseDown","event","preventDefault","clientX","clientY","onmouseup","closeDragElement","onmousemove","elementDrag","onmousedown","$a701256f05b28a22$export$69374dc2b307e4","$1e660b916d30a31c$var$commandsHistory","$1e660b916d30a31c$var$historyMode","$1e660b916d30a31c$var$historyIndex","$1e660b916d30a31c$var$terminalBody","$1e660b916d30a31c$var$addNewLine","Date","getMonth","htmlFlakes","html","append","createRange","createContextualFragment","$1e660b916d30a31c$var$stringToDom","previousUid","uid","terminalLineEl","terminalResponseEl","inputEl","type","autocapitalize","dataset","active","$1e660b916d30a31c$var$onCommandInput","previousInputEl","getElementById","setAttribute","focus","commandValue","target","trim","toLowerCase","keyCode","idResponse","responseEl","includes","particleRatio","$dcf1a4d0a69352ac$export$6de48e3f8be72096","contains","href","$dcf1a4d0a69352ac$export$9dab01f508b084d5","innerHTML","$1e660b916d30a31c$var$handleCustomCommands","commandObj","find","el","undefined","split","responseType","Array","isArray","headers","rows","rtd","$1e660b916d30a31c$var$getDomForCommand","matchingCommand","startsWith","tagName","terminalEl","parentElement"],"version":3,"file":"index.aeb8f1b0.js.map"}