mirror of
https://github.com/bckelley/terminal-portfolio.git
synced 2026-08-24 03:24:13 -05:00
init commit
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
node_modules/
|
||||
.env
|
||||
bckelleyResume.docx
|
||||
app.js
|
||||
package*
|
||||
@@ -0,0 +1,12 @@
|
||||
# Terminal Portfolio
|
||||
|
||||
A simple Express.js application for a terminal portfolio.
|
||||
|
||||
## Installation
|
||||
|
||||
Clone the repository and run:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
@@ -0,0 +1,131 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 15px 20px;
|
||||
min-height: 99%;
|
||||
width: 100%;
|
||||
min-width: 550px;
|
||||
color: #519975;
|
||||
background: #211D1B;
|
||||
font-family: cursor, monospace;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
::selection {
|
||||
color: #211830;
|
||||
background-color: #519975;
|
||||
}
|
||||
::-moz-selection {
|
||||
color: #211830;
|
||||
background-color: #519975;
|
||||
}
|
||||
textarea {
|
||||
left: -1000px;
|
||||
position: absolute;
|
||||
}
|
||||
b {
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* Cursor Start */
|
||||
.cursor {
|
||||
font-size: 12px;
|
||||
color: #73ABAD;
|
||||
background-color: #73ABAD;
|
||||
position: relative;
|
||||
opacity: 1;
|
||||
height: 1.5em;
|
||||
width: 10px;
|
||||
max-width: 10px;
|
||||
transform: translateY(4px);
|
||||
overflow: hidden;
|
||||
text-indent: -5px;
|
||||
display: inline-block;
|
||||
text-decoration: blink;
|
||||
animation: blinker 1s linear infinite;
|
||||
}
|
||||
@keyframes blinker {
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
#command {
|
||||
cursor: text;
|
||||
height: 50px;
|
||||
color: #73ABAD;
|
||||
}
|
||||
#liner {
|
||||
line-height: 1.3em;
|
||||
margin-top: -2px;
|
||||
animation: show 0.5s ease forwards;
|
||||
animation-delay: 1.2s;
|
||||
opacity: 0;
|
||||
}
|
||||
#liner::before {
|
||||
color: #519975;
|
||||
content: "visitor@bckelley.com:~$";
|
||||
}
|
||||
#liner.password::before {
|
||||
content: "Password:";
|
||||
}
|
||||
@keyframes show {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
/* Cursor End */
|
||||
p {
|
||||
display: block;
|
||||
line-height: 1.3em;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
letter-spacing: 0.05em;
|
||||
animation: typing 0.5s steps(30, end);
|
||||
}
|
||||
.no-animation {
|
||||
animation: typing 0 steps(30, end);
|
||||
}
|
||||
.margin {
|
||||
margin-left: 20px;
|
||||
}
|
||||
@keyframes typing {
|
||||
from {
|
||||
width: 0;
|
||||
}
|
||||
to {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.index {
|
||||
color: #DCDCCC;
|
||||
}
|
||||
.color2 {
|
||||
color: #B89076;
|
||||
}
|
||||
.command {
|
||||
color: #73ABAD;
|
||||
text-shadow: 0 0 5px #73ABAD;
|
||||
}
|
||||
.error {
|
||||
color: #B89076;
|
||||
}
|
||||
.white {
|
||||
color: #fff;
|
||||
}
|
||||
.inherit,
|
||||
a {
|
||||
color: #9C8394;
|
||||
}
|
||||
a {
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
background: #73ABAD;
|
||||
color: #211830;
|
||||
}
|
||||
a:focus {
|
||||
outline: 0;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-6364M55Q6C"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-6364M55Q6C');
|
||||
</script>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<title>bckelley | Terminal</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="../css/style.css" />
|
||||
<link rel="icon" type="image/x-icon" href="./favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="terminal">
|
||||
<a id="before"></a>
|
||||
</div>
|
||||
<div id="command" onclick="$('texter').focus();">
|
||||
<textarea
|
||||
type="text"
|
||||
id="texter"
|
||||
onkeyup="typeIt(this, event)"
|
||||
onkeydown="typeIt(this, event);
|
||||
moveIt(this.value.length, event)"
|
||||
onkeypress="typeIt(this, event);"
|
||||
autofocus
|
||||
></textarea>
|
||||
<div id="liner">
|
||||
<span id="typer"></span><b class="cursor" id="cursor">█</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../js/caret.js"></script>
|
||||
<script src="../js/commands.js"></script>
|
||||
<script src="../js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,38 @@
|
||||
function $(elid) {
|
||||
return document.getElementById(elid);
|
||||
}
|
||||
|
||||
var cursor;
|
||||
window.onload = init;
|
||||
|
||||
function init() {
|
||||
cursor = $("cursor");
|
||||
cursor.style.left = "0px";
|
||||
}
|
||||
|
||||
function nl2br(txt) {
|
||||
return txt.replace(/\n/g, '');
|
||||
}
|
||||
|
||||
function typeIt(from, e) {
|
||||
e = e || window.event;
|
||||
var w = $("typer");
|
||||
var tw = from.value;
|
||||
if (!pw){
|
||||
w.innerHTML = nl2br(tw);
|
||||
}
|
||||
}
|
||||
|
||||
function moveIt(count, e) {
|
||||
e = e || window.event;
|
||||
var keycode = e.keyCode || e.which;
|
||||
if (keycode == 37 && parseInt(cursor.style.left) >= (0 - ((count - 1) * 10))) {
|
||||
cursor.style.left = parseInt(cursor.style.left) - 10 + "px";
|
||||
} else if (keycode == 39 && (parseInt(cursor.style.left) + 10) <= 0) {
|
||||
cursor.style.left = parseInt(cursor.style.left) + 10 + "px";
|
||||
}
|
||||
}
|
||||
|
||||
function alert(txt) {
|
||||
console.log(txt);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
var youtube = "";
|
||||
var twitter = "";
|
||||
var instagram = "";
|
||||
var threads = "";
|
||||
var github = "https://github.com/bckelley/";
|
||||
var linkedin = "https://www.linkedin.com/in/bckelley2/";
|
||||
var password = "phpRulez";
|
||||
var email = 'mailto:admin@bradonckelley.me';
|
||||
|
||||
whois = [
|
||||
"<br>",
|
||||
"Hey! My name is Bradon 👋 and I am a back-end developer with a passion for PHP and technology.",
|
||||
"I have 12 of experience and have worked on projects like my SimplePHPDB which can read about on github.",
|
||||
"You can connect with me on linkedin or check out my work on github",
|
||||
"<br>"
|
||||
];
|
||||
|
||||
whoami = [
|
||||
"<br>",
|
||||
"The paradox of “Who am I?” is a labyrinth with no map, yet we tirelessly",
|
||||
"explore its winding paths. Each step reveals a new facet of ourselves, a",
|
||||
"reflection in the ever-shifting mirror of experience. And so, the journey",
|
||||
"becomes the answer, the quest for self-discovery a tapestry woven from the",
|
||||
"threads of existence.",
|
||||
"<br>"
|
||||
];
|
||||
|
||||
social = [
|
||||
"<br>",
|
||||
(youtube !== "") ? 'youtube <a href="' + youtube + '" target="_blank">youtube/' + "</a>" : '',
|
||||
(twitter !== "") ? 'twitter <a href="' + twitter + '" target="_blank">twitter/' + '</a>' : '',
|
||||
(linkedin !== "") ? 'linkedin <a href="' + linkedin + '" target="_blank">linkedin/bckelley' + "</a>" : '',
|
||||
(instagram !== "") ? 'instagram <a href="' + instagram + '" target="_blank">instagram/' + '</a>' : '',
|
||||
(threads !== "") ? 'threads <a href="' + threads + '" target="_blank">threads/' + '</a>' : '',
|
||||
(github !== "") ? 'github <a href="' + github + '" target="_blank">github/bckelley' + "</a>" : '',
|
||||
"<br>"
|
||||
];
|
||||
|
||||
secret = [
|
||||
"<br>",
|
||||
"<span class=\"command\">sudo</span> We trust you have received the usual lecture from the local",
|
||||
" System Administrator. It usually boils down to these three things: ",
|
||||
" #1) Respect the privacy of others. ",
|
||||
" #2) Think before you type. ",
|
||||
" #3) With great power comes great responsibility. ",
|
||||
"<br>"
|
||||
];
|
||||
|
||||
projects = [
|
||||
"<br>",
|
||||
"Still curating... most projects are offline, on GitHub, or confidential.",
|
||||
(github !== "") ? '[ github/todo-list ]: <a href="' + github + 'todo-list' +'" target="_blank">github/bckelley/todo-list' + "</a>" : '',
|
||||
(github !== "") ? '[ github/RouteEaseMVC ]: <a href="' + github + 'RouteEaseMVC' + '" target="_blank">github/bckelley/TouteEaseMVC' + "</a>" : '',
|
||||
(github !== "") ? '[ github/SimplePHPDB ]: <a href="' + github + 'SimplePHPDB' + '" target="_blank">github/bckelley/SimplePHPDB' + "</a>" : '',
|
||||
// (github !== "") ? '[ github/ ]: <a href="' + github + '' +'" target="_blank">github/bckelley/' + "</a>" : '',
|
||||
"<br>"
|
||||
];
|
||||
|
||||
help = [
|
||||
"<br>",
|
||||
'<span class="command">whois</span> Who is bckelley?',
|
||||
'<span class="command">whoami</span> Who are you?',
|
||||
(youtube !== "")?'<span class="command">video</span> View YouTube videos': '',
|
||||
'<span class="command">social</span> Display social networks',
|
||||
'<span class="command">secret</span> Find the password',
|
||||
'<span class="command">projects</span> View coding projects',
|
||||
'<span class="command">history</span> View command history',
|
||||
'<span class="command">help</span> You obviously already know what this does',
|
||||
'<span class="command">email</span> Do not email me',
|
||||
'<span class="command">clear</span> Clear terminal',
|
||||
'<span class="command">banner</span> Display the header',
|
||||
"<br>",
|
||||
];
|
||||
|
||||
license = [
|
||||
'<br>',
|
||||
'<span class="index"><p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://github.com/bckelley/terminal-portfolio">bckelley Terminal Portfolio</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://github.com/bckelley">bckelley</a> is licensed under <br> <a href="https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=chooser-v1" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International <img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nc.svg?ref=chooser-v1" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/nd.svg?ref=chooser-v1" alt=""></a></p>'
|
||||
];
|
||||
|
||||
|
||||
banner = [
|
||||
'<span class="index">Bradon Kelley (BK) Not A Corporation. All rights reserved.</span>',
|
||||
' ',
|
||||
' ,dPYb, ,dPYb, ,dPYb, ,dPYb, ',
|
||||
' IP\'`Yb IP\'`Yb IP\'`Yb IP\'`Yb ',
|
||||
' I8 8I I8 8I I8 8I I8 8I ',
|
||||
' I8 8\' I8 8bgg, I8 8\' I8 8\' ',
|
||||
' I8 dP ,gggg, I8 dP" "8 ,ggg, I8 dP I8 dP ,ggg, gg gg ',
|
||||
' I8dP 88gg dP" "Yb I8d8bggP" i8" "8i I8dP I8dP i8" "8i I8 8I ',
|
||||
' I8P 8I i8\' I8P\' "Yb, I8, ,8I I8P I8P I8, ,8I I8, ,8I ',
|
||||
' ,d8b, ,8I ,d8,_ _,d8 `Yb, `YbadP\' ,d8b,_ ,d8b,_ `YbadP\' ,d8b, ,d8I ',
|
||||
' 8P\'"Y88P"\' P""Y8888PP88P Y8888P"Y8888P\'"Y888P\'"Y88888P"Y888P""Y88P"888 ',
|
||||
' ,d8I\' ',
|
||||
' ,dP\'8I ',
|
||||
' ,8" 8I ',
|
||||
' I8 8I ',
|
||||
' `8, ,8I ',
|
||||
' `Y8P\' ',
|
||||
'<span class="color2">Welcome to my interactive web terminal.</span>',
|
||||
'<span class="color2">For a list of available commands, type</span> <span class="command">\'help\'</span><span class="color2">.</span>',
|
||||
];
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
var before = document.getElementById("before");
|
||||
var liner = document.getElementById("liner");
|
||||
var command = document.getElementById("typer");
|
||||
var textarea = document.getElementById("texter");
|
||||
var terminal = document.getElementById("terminal");
|
||||
|
||||
var git = 0;
|
||||
var pw = false;
|
||||
let pwd = false;
|
||||
var commands = [];
|
||||
|
||||
setTimeout(function() {
|
||||
loopLines(banner, "", 80);
|
||||
textarea.focus();
|
||||
}, 100);
|
||||
|
||||
window.addEventListener("keyup", enterKey);
|
||||
|
||||
console.log(
|
||||
"%cYou hacked my password!😠",
|
||||
"color: #04ff00; font-weight: bold; font-size: 24px;"
|
||||
);
|
||||
console.log("%cPassword: '" + password + "' - I wonder what it does?🤔", "color: grey");
|
||||
|
||||
//init
|
||||
textarea.value = "";
|
||||
command.innerHTML = textarea.value;
|
||||
|
||||
function enterKey(e) {
|
||||
if (e.keyCode == 181) {
|
||||
document.location.reload(true);
|
||||
}
|
||||
if (pw) {
|
||||
let et = "*";
|
||||
let w = textarea.value.length;
|
||||
command.innerHTML = et.repeat(w);
|
||||
if (textarea.value === password) {
|
||||
pwd = true;
|
||||
}
|
||||
if (pwd && e.keyCode == 13) {
|
||||
loopLines(secret, "color2 margin", 120);
|
||||
command.innerHTML = "";
|
||||
textarea.value = "";
|
||||
pwd = false;
|
||||
pw = false;
|
||||
liner.classList.remove("password");
|
||||
} else if (e.keyCode == 13) {
|
||||
addLine("Wrong password", "error", 0);
|
||||
command.innerHTML = "";
|
||||
textarea.value = "";
|
||||
pw = false;
|
||||
liner.classList.remove("password");
|
||||
}
|
||||
} else {
|
||||
if (e.keyCode == 13) {
|
||||
commands.push(command.innerHTML);
|
||||
git = commands.length;
|
||||
addLine("visitor@bckelley.com:~$ " + command.innerHTML, "no-animation", 0);
|
||||
commander(command.innerHTML.toLowerCase());
|
||||
command.innerHTML = "";
|
||||
textarea.value = "";
|
||||
}
|
||||
if (e.keyCode == 38 && git != 0) {
|
||||
git -= 1;
|
||||
textarea.value = commands[git];
|
||||
command.innerHTML = textarea.value;
|
||||
}
|
||||
if (e.keyCode == 40 && git != commands.length) {
|
||||
git += 1;
|
||||
if (commands[git] === undefined) {
|
||||
textarea.value = "";
|
||||
} else {
|
||||
textarea.value = commands[git];
|
||||
}
|
||||
command.innerHTML = textarea.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function commander(cmd) {
|
||||
switch (cmd.toLowerCase()) {
|
||||
case "help":
|
||||
loopLines(help, "color2 margin", 80);
|
||||
break;
|
||||
case "whois":
|
||||
loopLines(whois, "color2 margin", 80);
|
||||
break;
|
||||
case "whoami":
|
||||
loopLines(whoami, "color2 margin", 80);
|
||||
break;
|
||||
case "video":
|
||||
addLine("Opening YouTube...", "color2", 80);
|
||||
newTab(youtube);
|
||||
break;
|
||||
case "sudo":
|
||||
addLine("Oh no, you're not admin...", "color2", 80);
|
||||
setTimeout(function() {
|
||||
window.open('https://youtu.be/uRGljemfwUE?si=V-SJLK5v-Dj9FIE3');
|
||||
}, 1000);
|
||||
break;
|
||||
case "social":
|
||||
loopLines(social, "color2 margin", 80);
|
||||
break;
|
||||
case "secret":
|
||||
liner.classList.add("password");
|
||||
pw = true;
|
||||
break;
|
||||
case "projects":
|
||||
loopLines(projects, "color2 margin", 80);
|
||||
break;
|
||||
case "password":
|
||||
addLine("<span class=\"inherit\"> Lol! You're joking, right? You\'re gonna have to try harder than that!😂</span>", "error", 100);
|
||||
break;
|
||||
case "history":
|
||||
addLine("<br>", "", 0);
|
||||
loopLines(commands, "color2", 80);
|
||||
addLine("<br>", "command", 80 * commands.length + 50);
|
||||
break;
|
||||
case "email":
|
||||
addLine(`Opening <a href="${email}">${email}</a>...`, "color2", 80);
|
||||
newTab(email);
|
||||
break;
|
||||
case "clear":
|
||||
setTimeout(function() {
|
||||
terminal.innerHTML = '<a id="before"></a>';
|
||||
before = document.getElementById("before");
|
||||
}, 1);
|
||||
break;
|
||||
case "banner":
|
||||
loopLines(banner, "", 80);
|
||||
break;
|
||||
// socials
|
||||
case "youtube":
|
||||
addLine("Opening YouTube...", "color2", 80);
|
||||
newTab(youtube);
|
||||
break;
|
||||
case "twitter":
|
||||
addLine("Opening Twitter...", "color2", 0);
|
||||
newTab(twitter);
|
||||
break;
|
||||
case "linkedin":
|
||||
addLine("Opening LinkedIn...", "color2", 0);
|
||||
newTab(linkedin);
|
||||
break;
|
||||
case "instagram":
|
||||
addLine("Opening Instagram...", "color2", 0);
|
||||
newTab(instagram);
|
||||
break;
|
||||
case "github":
|
||||
addLine("Opening GitHub...", "color2", 0);
|
||||
newTab(github);
|
||||
break;
|
||||
case "license":
|
||||
loopLines(license, "", 80);
|
||||
break;
|
||||
default:
|
||||
addLine("<span class=\"inherit\">Command not found. For a list of commands, type <span class=\"command\">'help'</span>.</span>", "error", 100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function newTab(link) {
|
||||
setTimeout(function() {
|
||||
window.open(link, "_blank");
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function addLine(text, style, time) {
|
||||
var t = "";
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
if (text.charAt(i) == " " && text.charAt(i + 1) == " ") {
|
||||
t += " ";
|
||||
i++;
|
||||
} else {
|
||||
t += text.charAt(i);
|
||||
}
|
||||
}
|
||||
setTimeout(function() {
|
||||
var next = document.createElement("p");
|
||||
next.innerHTML = t;
|
||||
next.className = style;
|
||||
|
||||
before.parentNode.insertBefore(next, before);
|
||||
|
||||
window.scrollTo(0, document.body.offsetHeight);
|
||||
}, time);
|
||||
}
|
||||
|
||||
function loopLines(name, style, time) {
|
||||
name.forEach(function(item, index) {
|
||||
addLine(item, style, index * time);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user