Portfolio — Riric (DotRiric)
-CEO · Founder · Architect — discover my world in a Debian terminal.
-diff --git a/public/css/portfolio.css b/public/css/portfolio.css index c350daf..04abc98 100644 --- a/public/css/portfolio.css +++ b/public/css/portfolio.css @@ -1,187 +1,112 @@ -/* Terminal portfolio — zektyc */ -:root { - --term-bg: #0b0e12; - --term-bg-bar: #151a20; - --term-text: #c9d1d9; - --term-dim: #8b949e; - --term-green: #56d364; - --term-blue: #58a6ff; - --term-red: #ff6b6b; - --term-border: rgba(88, 166, 255, 0.18); +/* Terminal portfolio — zektyc — console Debian plein ecran */ +html, +body { + margin: 0; + padding: 0; + height: 100%; + background: #000; } -.portfolio-main { - max-width: 900px; - margin: 2rem auto; - padding: 0 1.25rem; - flex: 1 0 auto; - width: 100%; -} - -.portfolio-head { - margin-bottom: 1rem; -} - -.portfolio-head h1 { - font-family: var(--font-head); - font-size: clamp(1.6rem, 4vw, 2.2rem); - margin-bottom: 0.25rem; -} - -.portfolio-head p { - color: var(--text-muted); +body { + font-family: ui-monospace, "Cascadia Code", Menlo, Consolas, "DejaVu Sans Mono", monospace; + color: #d8d8d8; } .terminal { - --radius: 12px; - background: var(--term-bg); - border: 1px solid var(--term-border); - border-radius: var(--radius); + height: 100vh; + height: 100dvh; overflow: hidden; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45); - font-family: var(--font-mono); - font-size: 0.9rem; - line-height: 1.55; - width: 100%; -} - -[data-theme="dark"] .terminal { - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.7); -} - -.terminal-bar { - display: flex; - align-items: center; - gap: 0.5rem; - background: var(--term-bg-bar); - padding: 0.55rem 0.85rem; - border-bottom: 1px solid var(--term-border); - color: var(--term-dim); - font-size: 0.75rem; - user-select: none; -} - -.terminal-dots { - display: flex; - gap: 0.35rem; -} - -.terminal-dots i { - width: 0.7rem; - height: 0.7rem; - border-radius: 50%; - display: inline-block; -} - -.terminal-dots i:nth-child(1) { background: #ff5f57; } -.terminal-dots i:nth-child(2) { background: #febc2e; } -.terminal-dots i:nth-child(3) { background: #28c840; } - -.terminal-title { - flex: 1; - text-align: center; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; } .terminal-body { - padding: 0.9rem 1rem 1.2rem; - height: min(62vh, 620px); + box-sizing: border-box; + height: 100%; overflow-y: auto; overflow-x: hidden; + padding: 10px 14px 18px; + font-size: 15px; + line-height: 1.45; + scrollbar-width: thin; + scrollbar-color: #2a2a2a #000; +} + +.terminal-body::-webkit-scrollbar { + width: 10px; +} + +.terminal-body::-webkit-scrollbar-track { + background: #000; +} + +.terminal-body::-webkit-scrollbar-thumb { + background: #2a2a2a; + border-radius: 5px; } .terminal-line { white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere; - min-height: 1.2em; + min-height: 1.25em; } -.terminal-line .t-dim { color: var(--term-dim); } -.terminal-line .t-green { color: var(--term-green); } -.terminal-line .t-blue { color: var(--term-blue); } -.terminal-line .t-red { color: var(--term-red); } - -.terminal-line a { - color: var(--term-blue); - text-decoration: underline; - text-underline-offset: 2px; +.term-line-input { + display: flex; + align-items: baseline; } .term-ascii { - color: var(--term-green); white-space: pre; - line-height: 1.2; -} - -.term-prompts { - margin-top: 0.6rem; -} - -.term-input-row { - display: flex; - align-items: baseline; - gap: 0.45rem; + line-height: 1.25; + color: #4af626; } .term-prompt { - color: var(--term-green); white-space: nowrap; } .term-prompt .t-user { - color: var(--term-green); + color: #4af626; } .term-prompt .t-path { - color: var(--term-blue); + color: #5387ff; } .term-input { flex: 1; min-width: 0; - background: transparent; - border: none; - outline: none; - color: var(--term-text); - font-family: inherit; - font-size: inherit; - line-height: inherit; + margin: 0; padding: 0; - caret-color: var(--term-green); + border: 0; + outline: none; + background: transparent; + color: inherit; + font: inherit; + caret-color: #4af626; } .term-input::selection { - background: rgba(88, 166, 255, 0.35); + background: rgba(84, 135, 255, 0.4); } -.term-cursor-blink { - animation: term-blink 1.1s steps(1) infinite; +.terminal-line a { + color: #5387ff; + text-decoration: underline; + text-underline-offset: 2px; } -@keyframes term-blink { - 50% { opacity: 0; } +.terminal-line .t-dim { + color: #9a9a9a; +} + +.terminal-line .t-red { + color: #ff5252; } @media (max-width: 760px) { - .portfolio-main { - margin-top: 1.25rem; - padding: 0 0.6rem; - } - .terminal-body { - height: min(70vh, 520px); - font-size: 0.78rem; - padding: 0.7rem 0.75rem 1rem; - } - - .terminal-bar { - padding: 0.45rem 0.6rem; - } - - .term-ascii { - font-size: 0.72rem; + font-size: 16px; + padding: 8px 10px 14px; } } \ No newline at end of file diff --git a/public/js/portfolio.js b/public/js/portfolio.js index 65a7d8f..94f1489 100644 --- a/public/js/portfolio.js +++ b/public/js/portfolio.js @@ -4,14 +4,12 @@ var FR = /^\/en(\/|$)/.test(location.pathname) ? false : true; var T = { - title: FR ? "dotriric@zektyc: ~ — bash" : "dotriric@zektyc: ~ — bash", boot: FR ? ["Debian GNU/Linux 12 (bookworm) tty1", "zektyc login: dotriric", "Password: ********", "Last login: a l'instant depuis votre navigateur", "Bienvenue sur le terminal de presentation de Riric.", "Tapez 'help' pour la liste des commandes."] : ["Debian GNU/Linux 12 (bookworm) tty1", "zektyc login: dotriric", "Password: ********", "Last login: right now from your browser", "Welcome to Riric's presentation terminal.", "Type 'help' for the list of commands."], promptUser: "dotriric", promptHost: "zektyc", unknown: function (c) { return FR ? ("bash: " + c + " : commande introuvable") : ("bash: " + c + ": command not found"); }, - pwEmpty: FR ? "bash: passage en racine impossible : ne peut pas se connecter en tant que root" : "bash: cannot become root: cannot login as root", helpLines: FR ? [ "Commandes disponibles :", @@ -115,13 +113,10 @@ contact: FR ? ["Email: riric65@protonmail.com", "Mastodon: @zektyc@piaille.fr", "Repond generalement en francais ou en anglais."] : ["Email: riric65@protonmail.com", "Mastodon: @zektyc@piaille.fr", "Usually replies in French or English."], - files: ["about.txt", "projects.txt", "contact.txt", ".bashrc", ".profile"], - contactFile: FR ? ["ouvrez contact.txt, ou tapez 'contact'"] : ["open contact.txt, or type 'contact'"], bashrc: FR ? ["# Config bash de dotriric", 'export PS1="dotriric@zektyc:~$ "', "alias ll='ls -alF'", "# Je n'aime pas le sucre."] : ["# dotriric's bash config", 'export PS1="dotriric@zektyc:~$ "', "alias ll='ls -alF'", "# I don't like sugar."], profile: FR ? ["# .profile — charge le bashrc", "source ~/.bashrc", "# Bienvenue."] : ["# .profile — loads bashrc", "source ~/.bashrc", "# Welcome."], sudo: FR ? ["dotriric n'est pas dans le fichier sudoers. Cet incident sera signale."] : ["dotriric is not in the sudoers file. This incident will be reported."], apt: FR ? ["Lecture des listes de paquets... Termine.", "Construction de l'arbre des dependances... Termine.", "0 paquet(s) mis a niveau."] : ["Reading package lists... Done.", "Building dependency tree... Done.", "0 packages can be upgraded."], - contactCmd: FR ? "Me contacter : taper 'contact'" : "To contact me: type 'contact'", shutdown: FR ? ["connexion fermee.", "terminal de presentation quitte — la page reste, evidemment. :)"] : ["connection closed.", "presentation terminal exited — the page stays, of course. :)"], }; @@ -130,21 +125,9 @@ if (!root) return; var body = root.querySelector(".terminal-body"); - var input = root.querySelector(".term-input"); var history = []; var histIdx = -1; - - function makeLine(text, cls) { - var div = document.createElement("div"); - div.className = "terminal-line"; - if (cls) div.classList.add(cls); - if (typeof text === "string") { - div.textContent = text; - } else { - div.appendChild(text); - } - return div; - } + var locked = false; function makeLink(text, href) { var a = document.createElement("a"); @@ -191,30 +174,90 @@ body.scrollTop = body.scrollHeight; } - function promptLine() { - var p = document.createElement("div"); + function promptEl() { + var p = document.createElement("span"); p.className = "term-prompt"; var sp = document.createElement("span"); sp.className = "t-user"; sp.textContent = T.promptUser + "@" + T.promptHost; var ct = document.createElement("span"); ct.className = "t-path"; - ct.textContent = ":" + "\u007e" + "$ "; + ct.textContent = ":~$ "; p.appendChild(sp); p.appendChild(ct); return p; } - function runCommand(raw) { - var cmd = raw.trim(); + function currentPrompt() { + return body.querySelector(".prompt-line"); + } + + function newPrompt() { var line = document.createElement("div"); - line.className = "terminal-line"; - line.appendChild(promptLine()); - line.appendChild(document.createTextNode(raw)); + line.className = "terminal-line prompt-line term-line-input"; + line.appendChild(promptEl()); + var inp = document.createElement("input"); + inp.type = "text"; + inp.className = "term-input"; + inp.setAttribute("autocomplete", "off"); + inp.setAttribute("autocapitalize", "off"); + inp.setAttribute("spellcheck", "false"); + inp.setAttribute("aria-label", FR ? "Commande" : "Command"); + line.appendChild(inp); body.appendChild(line); + bindInput(inp); + scrollDown(); + return inp; + } - if (!cmd) { scrollDown(); return; } + function bindInput(inp) { + inp.addEventListener("keydown", function (e) { + if (e.key === "Enter") { + e.preventDefault(); + submit(inp); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + if (history.length) { + histIdx = Math.max(0, histIdx - 1); + inp.value = history[histIdx] || ""; + } + } else if (e.key === "ArrowDown") { + e.preventDefault(); + if (history.length) { + histIdx = Math.min(history.length, histIdx + 1); + inp.value = histIdx >= history.length ? "" : history[histIdx]; + } + } + }); + inp.addEventListener("input", scrollDown); + } + function submit(inp) { + var raw = inp.value; + var line = inp.closest(".prompt-line"); + var txt = document.createElement("span"); + txt.textContent = raw; + inp.replaceWith(txt); + + if (raw.trim()) history.push(raw); + histIdx = history.length; + + var cmd = raw.trim(); + if (cmd === "clear" || cmd === "cls") { + body.innerHTML = ""; + newPrompt().focus(); + return; + } + + if (cmd) runCommand(cmd); + + if (locked) return; + + newPrompt().focus(); + scrollDown(); + } + + function runCommand(cmd) { var parts = cmd.split(/[ \t]+/); var c = parts[0].toLowerCase(); var arg = parts.slice(1).join(" "); @@ -223,9 +266,6 @@ case c === "help" || c === "h" || c === "?": print(T.helpLines); break; - case c === "clear" || c === "cls": - body.innerHTML = ""; - break; case c === "whoami": print("dotriric"); break; @@ -298,8 +338,7 @@ break; case c === "exit" || c === "logout" || c === "quit": print(T.shutdown); - input.disabled = true; - input.setAttribute("placeholder", ""); + locked = true; break; case c === "echo": print(arg || ""); @@ -310,45 +349,21 @@ default: print(T.unknown(c)); } - scrollDown(); } - function submit() { - var v = input.value; - if (v.trim()) history.push(v); - histIdx = history.length; - runCommand(v); - input.value = ""; - } - - input.addEventListener("keydown", function (e) { - if (e.key === "Enter") { - e.preventDefault(); - submit(); - } else if (e.key === "ArrowUp") { - e.preventDefault(); - if (history.length) { - histIdx = Math.max(0, histIdx - 1); - input.value = history[histIdx] || ""; - } - } else if (e.key === "ArrowDown") { - e.preventDefault(); - if (history.length) { - histIdx = Math.min(history.length, histIdx + 1); - input.value = histIdx >= history.length ? "" : history[histIdx]; - } - } - }); - root.addEventListener("click", function () { - if (!input.disabled) input.focus(); + var ln = currentPrompt(); + if (ln) { + var inp = ln.querySelector(".term-input"); + if (inp && !inp.disabled) inp.focus(); + } }); (function boot() { printAscii(["", T.boot.join("\n"), ""]); + var inp = newPrompt(); + setTimeout(function () { + inp.focus(); + }, 50); })(); - - setTimeout(function () { - input.focus(); - }, 50); })(); \ No newline at end of file diff --git a/public/portfolio/en/index.html b/public/portfolio/en/index.html index 1145b4f..80272e8 100644 --- a/public/portfolio/en/index.html +++ b/public/portfolio/en/index.html @@ -5,16 +5,16 @@ -
CEO · Founder · Architect — discover my world in a Debian terminal.
-