diff --git a/.vscode/extensions.json b/.vscode/extensions.json
deleted file mode 100644
index d43d599..0000000
--- a/.vscode/extensions.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "recommendations": [
- "wscats.eno",
- "formulahendry.auto-rename-tag",
- "yandeu.five-server",
- "bungcip.better-toml"
- ]
-}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a1c4910..28a51d5 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,3 @@
{
- "compile-hero.disable-compile-files-on-did-save-code": true
+ "compile-hero.disable-compile-files-on-did-save-code": false
}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d10e164
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# Website
+### [My website's](https://ari-web.netlify.app) source code.
+
+# Customising when self-hosting
+See the `/content/styles/config` and `/content/js/config` directories.
diff --git a/content/js/config/index.js b/content/js/config/index.js
new file mode 100644
index 0000000..bcef4d7
--- /dev/null
+++ b/content/js/config/index.js
@@ -0,0 +1,47 @@
+const boot = document.getElementById('boot');
+const site_name = 'ari-web';
+const boot_message = {
+ 0: {
+ "type": 'ok',
+ "text": `Booting '${site_name}'...`,
+ "sleep_time": 0
+ }
+}
+const do_sleep = false;
+const locations = {
+ 0: {
+ "url": "https://github.com/TruncatedDinosour/website",
+ "desc": "The source code of this website",
+ "aliases": [
+ "src","source",
+ "git", "github"
+ ]
+ },
+
+ 1: {
+ "url": "/",
+ "desc": "The home page",
+ "aliases": [
+ "home","root",
+ "index"
+ ]
+ },
+
+ 2: {
+ "url": "/page/reset",
+ "desc": "Reset your account",
+ "aliases": [
+ "reset","erase",
+ "del", "delete"
+ ]
+ },
+
+ 3: {
+ "url": "/page/minimal.txt",
+ "desc": "The minimal page",
+ "aliases": [
+ "mini","minimal",
+ "txt"
+ ]
+ }
+}
diff --git a/content/js/generic/index.js b/content/js/generic/index.js
new file mode 100644
index 0000000..3c54e61
--- /dev/null
+++ b/content/js/generic/index.js
@@ -0,0 +1,61 @@
+var root = false;
+
+add_boot_entry(boot_message)
+
+async function main() {
+ let is_logged_in = (
+ localStorage.getItem('username') &&
+ localStorage.getItem('password')
+ )
+
+ let tmp_boot_entries = {
+ 0: {
+ "type": 'error',
+ "text": 'No user account found'
+ },
+ 1: {
+ "type": 'warning',
+ "text": 'Creating account',
+ "sleep_time": 500
+ },
+ 3: {
+ "type": 'ok',
+ "text": `Found user account: ${localStorage.getItem('username')}`
+ },
+ 4: {
+ "type": 'ok',
+ "text": 'Loading HTML'
+ },
+ 5: {
+ "type": 'ok',
+ "text": 'Loading a basic shell'
+ },
+ 6: {
+ "type": 'ok',
+ "text": `'${site_name}' has been booted! enjoy`
+ }
+ }
+
+ if (!is_logged_in) {
+ await add_boot_entry({0: tmp_boot_entries[0], 1: tmp_boot_entries[1]});
+ await sleep(500);
+ user_account_create();
+
+ return 1;
+ } else {
+ await add_boot_entry({
+ 0: tmp_boot_entries[3]
+ });
+ await add_boot_entry({
+ 0: tmp_boot_entries[4],
+ 1: tmp_boot_entries[5],
+ 2: tmp_boot_entries[6]
+ });
+
+ document.getElementById("shell").style.display = 'block';
+ document.getElementById('prompt').focus();
+ }
+}
+
+
+main();
diff --git a/content/js/handlers/user_account.js b/content/js/handlers/user_account.js
new file mode 100644
index 0000000..c68dc8f
--- /dev/null
+++ b/content/js/handlers/user_account.js
@@ -0,0 +1,45 @@
+async function user_account_create() {
+ let username = prompt(`Enter your username`);
+ let password = prompt(`Enter the password for '${username}'`);
+ let password_confirm = prompt(`Confirm the password for '${username}'`);
+
+ let tmp_boot_entries = {
+ 0: {
+ "type": 'error',
+ "text": "User account not created: canceled by user",
+ "sleep_time": 0
+ }
+ }
+
+ let valid = (
+ username &&
+ password &&
+ password_confirm &&
+ password.length > 6 &&
+ password == password_confirm
+ )
+
+ if (!valid) {
+ if (confirm('The credentials you entered are not valid, try again?')) {
+ user_account_create();
+ return 1;
+ }
+
+ add_boot_entry({0: tmp_boot_entries[0]});
+ await sleep(2500);
+ window.location.reload();
+ } else {
+ alert('The next popup will show your credentials, press OK to proceed')
+ let confirm_credentials = confirm(`Are these credentials correct?:
+ USER: ${username}
+ PASS: ${password}`);
+
+ if (confirm_credentials) {
+ localStorage.setItem('username', username)
+ localStorage.setItem('password', hash(password))
+
+ alert('Credentials saved!')
+ window.location.reload();
+ }
+ }
+}
diff --git a/content/js/helpers/index.js b/content/js/helpers/index.js
new file mode 100644
index 0000000..c472e7f
--- /dev/null
+++ b/content/js/helpers/index.js
@@ -0,0 +1,54 @@
+function sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+
+async function add_boot_entry(entry_object) {
+ for (const entry in entry_object) {
+
+ if (do_sleep) {
+ let sleep_time;
+ if (typeof entry_object[entry]['sleep_time'] !== 'undefined') {
+ sleep_time = entry_object[entry]['sleep_time'];
+ } else {
+ sleep_time = Math.floor((Math.random() * 2000) + 500);
+ }
+ await sleep(sleep_time);
+ }
+
+
+ let new_entry = document.createElement('p');
+ new_entry.innerHTML = entry_object[entry]['text'];
+ new_entry.classList.add("bmsg")
+
+ let entry_class;
+ switch (entry_object[entry]['type']) {
+ case 'error':
+ entry_class = 'error';
+ break;
+
+ case 'warning':
+ entry_class = 'warn'
+ break;
+
+ case 'ok':
+ entry_class = 'ok'
+ break;
+
+ default:
+ throw `Type '${entry_object[entry]['type']}' not found.`;
+ }
+
+ new_entry.setAttribute("bmsg_type", entry_class);
+ boot.appendChild(new_entry);
+ }
+}
+
+
+function hash(string){
+ return string.split("").reduce(
+ function (a, b) {
+ a = ((a << 5) - a) + b.charCodeAt(0);
+ return a & a
+ }, 0);
+}
diff --git a/content/js/shell/commands.js b/content/js/shell/commands.js
new file mode 100644
index 0000000..9517746
--- /dev/null
+++ b/content/js/shell/commands.js
@@ -0,0 +1,102 @@
+var commands = {
+ "clear": {
+ "func": clear,
+ "root_only": false,
+ "help": {
+ "desc": "A command to clear the screen",
+ "short_desc": "Clear the screen",
+ "examples": [
+ "clear"
+ ]
+ }
+ },
+
+ "reboot": {
+ "func": reboot,
+ "root_only": true,
+ "help": {
+ "desc": "A command to reboot",
+ "short_desc": "Reboot",
+ "examples": [
+ "reboot"
+ ]
+ }
+ },
+
+ "help": {
+ "func": help,
+ "root_only": false,
+ "help": {
+ "desc": "A command to print help",
+ "short_desc": "Print help",
+ "examples": [
+ "help",
+ "help help"
+ ]
+ }
+ },
+
+ "show": {
+ "func": show,
+ "root_only": false,
+ "help": {
+ "desc": "A command to show pages",
+ "short_desc": "Show page",
+ "examples": [
+ "show",
+ "show src"
+ ]
+ }
+ },
+
+ "goto": {
+ "func": goto,
+ "root_only": false,
+ "help": {
+ "desc": "A command to go to pages",
+ "short_desc": "Goto a page",
+ "examples": [
+ "goto",
+ "goto src"
+ ]
+ }
+ },
+
+ "ls": {
+ "func": list,
+ "root_only": false,
+ "help": {
+ "desc": "A command to list available pages",
+ "short_desc": "List pages",
+ "examples": [
+ "ls",
+ "ls src"
+ ]
+ }
+ },
+
+ "su": {
+ "func": su,
+ "root_only": false,
+ "help": {
+ "desc": "A command to run commands as root, use 'su .' to switch between the users.",
+ "short_desc": "Run as root",
+ "examples": [
+ "su .",
+ "su reboot"
+ ]
+ }
+ },
+
+ "passwd": {
+ "func": passwd,
+ "root_only": true,
+ "help": {
+ "desc": "A command to change your password",
+ "short_desc": "Change password",
+ "examples": [
+ "passwd"
+ ]
+ }
+ },
+}
diff --git a/content/js/shell/func.js b/content/js/shell/func.js
new file mode 100644
index 0000000..da9b899
--- /dev/null
+++ b/content/js/shell/func.js
@@ -0,0 +1,145 @@
+function clear() {
+ document.getElementById('command_output').innerHTML = '';
+ document.getElementById('cmd_hist').innerHTML = '';
+ document.getElementById('content').innerHTML = '';
+
+ return '';
+}
+
+function reboot() {
+ window.location.reload();
+ return 'Rebooting...';
+}
+
+function help(cmd) {
+ let help_page = '';
+ let help_cmd = cmd[0];
+
+ if (help_cmd && !commands[help_cmd]) {
+ return `Help page for '${help_cmd}' does not exist`
+ }
+
+ if (help_cmd) {
+ let cmd_help = commands[help_cmd]['help']
+
+ help_page += `NAME: ${help_cmd}
`;
+ help_page += `SUID: ${commands[help_cmd]['root_only']}
`;
+ help_page += `DESCRIPTION: ${cmd_help['desc']}
`;
+ help_page += `EXAMPLES:
`;
+
+ for (const example in cmd_help['examples']) {
+ help_page += `$ ${cmd_help['examples'][example]}
`
+ }
+ } else {
+ for (const h in commands) {
+ let cmd_help = commands[h]['help']
+
+ help_page += `NAME: ${h}
`
+ help_page += `SUID: ${commands[h]['root_only']}
`;
+ help_page += `DESCRIPTION: ${cmd_help['short_desc']}
`
+ help_page += `EXAMPLE: ${cmd_help['examples'][0]}
`
+ help_page += `
`
+ }
+ }
+
+ return help_page;
+}
+
+function show(dest) {
+ let dst = dest[0];
+ let iframe = document.createElement('iframe');
+ iframe.setAttribute('class', 'iframe');
+
+ if (!dst) {
+ return help(['show']);
+ } else {
+ for (const l in locations) {
+ if (locations[l]['aliases'].includes(dst)) {
+ iframe.setAttribute('src', locations[l]['url']);
+ break;
+ }
+ }
+ }
+
+ if (iframe.src) {
+ return iframe.outerHTML;
+ } else {
+ return `Page '${dst}' not found`;
+ }
+}
+
+function goto(dest) {
+ let dst = dest[0];
+
+ if (!dst) {
+ window.location = '/';
+ return 'Returning to the home page'
+ } else {
+ for (const l in locations) {
+ if (locations[l]['aliases'].includes(dst)) {
+ window.location = locations[l]['url'];
+ return `Going to ${locations[l]['url']}`
+ }
+ }
+ }
+
+ return `Page ${dst} does not exist`
+}
+
+function list() {
+ let locs = '';
+
+ for (const l in locations) {
+ let loc = locations[l];
+ locs += `URL: ${loc['url']}
`
+ locs += `DESCRIPTION: ${loc['desc']}
`
+ locs += `ALISES: ${loc['aliases'].join(", ")}
`
+ locs += `
`
+ }
+
+ return locs;
+}
+
+function su(cmd) {
+ let password_hash;
+ if (!root) {
+ password_hash = hash(prompt('Enter your password'));
+ }
+
+ if (!password_hash) {
+ return 'Not authenticated. (empty password)'
+ }
+
+ if (password_hash != localStorage.getItem('password') && !root) {
+ return 'Wrong password.';
+ }
+
+ if (cmd[0]) {
+ if (cmd[0] == '.') {
+ root = !root
+ return `Switched to the ${root ? 'root' : localStorage.getItem('username')} user.`
+ } else {
+ return commands[cmd[0]]['func'](cmd.slice(1));
+ }
+ } else {
+ return help(['su']);
+ }
+}
+
+
+function passwd() {
+ let current_password = hash(prompt("Current password"));
+ let password1 = prompt("New password");
+ let password2 = prompt("Confirm new password");
+
+ if (current_password == localStorage.getItem('password')) {
+ if (password1 === password2) {
+ localStorage.setItem("password", bash(password1))
+ alert(`password set to '${password1}'`);
+ } else {
+ return "Passwords don't match"
+ }
+ } else {
+ return 'Wrong password'
+ }
+}
diff --git a/content/js/shell/index.js b/content/js/shell/index.js
new file mode 100644
index 0000000..fa9f6c8
--- /dev/null
+++ b/content/js/shell/index.js
@@ -0,0 +1,63 @@
+let cmd_prompt = document.getElementById('prompt');
+let cmd_output = document.getElementById('command_output');
+let cmd_history = document.getElementById('cmd_hist');
+let shell = document.getElementById('shell');
+var is_root = false;
+
+function main() {
+ cmd_prompt.onkeypress = (e) => {
+ if (!cmd_prompt.value) return;
+
+ let code = (e.keyCode ? e.keyCode : e.which);
+ if (code == 13) {
+ let command_list = cmd_prompt.value.split(' ');
+ let command = command_list[0];
+ let argv = command_list.slice(1);
+
+
+ if (commands[command]) {
+ if (commands[command]['root_only'] && !root) {
+ cmd_output.innerHTML = `'${command}' can only be ran as root. see help su`
+ } else {
+ cmd_output.innerHTML = commands[command]['func'](argv);
+ }
+ } else {
+ cmd_output.innerHTML = `${command}: command not found`
+ }
+
+
+ if (cmd_output.innerHTML.toString().replace(/\s/g, '')) {
+ let shell_old = document.createElement('div');
+ shell_old.setAttribute('class', 'shell');
+ shell_old.setAttribute('prompt', shell.getAttribute('prompt'));
+
+ let cmd = document.createElement('input');
+ cmd.setAttribute('class', 'prompt');
+ cmd.setAttribute('value', cmd_prompt.value);
+ cmd.setAttribute('readonly', '');
+
+ let output = document.createElement('div');
+ output.setAttribute('class', 'output')
+ output.innerHTML = cmd_output.innerHTML;
+
+ shell_old.appendChild(cmd);
+ shell_old.appendChild(output);
+
+ cmd_history.appendChild(shell_old);
+ }
+
+ cmd_prompt.value = '';
+ cmd_output.innerHTML = '';
+
+ window.scrollTo(0, document.body.scrollHeight);
+
+ if (root) {
+ shell.setAttribute('prompt', 'root')
+ } else {
+ shell.setAttribute('prompt', '')
+ }
+ }
+ };
+}
+
+main()
diff --git a/content/styles/boot/main.css b/content/styles/boot/main.css
new file mode 100644
index 0000000..57e5a33
--- /dev/null
+++ b/content/styles/boot/main.css
@@ -0,0 +1,44 @@
+.boot {
+ margin: 1em 0em 1em 1em;
+ font-size: 1.5em;
+}
+.boot #bootver {
+ color: #9acd32;
+ margin-left: 1.12em;
+ /* makes it that it aligns with 'boot' messages */
+}
+.boot #bootver::before {
+ content: "WEBrc version " "1.0";
+}
+.boot .bmsg[bmsg_type=ok]::after {
+ content: "[OK]";
+ float: right;
+ color: #0fd30f;
+}
+.boot .bmsg[bmsg_type=ok]::before {
+ content: " * ";
+ color: #0fd30f;
+}
+.boot .bmsg[bmsg_type=warn]::after {
+ content: "[WARNING]";
+ float: right;
+ color: #ffff00;
+}
+.boot .bmsg[bmsg_type=warn]::before {
+ content: " * ";
+ color: #ffff00;
+}
+.boot .bmsg[bmsg_type=error]::after {
+ content: "[ERROR]";
+ float: right;
+ color: #ff0000;
+}
+.boot .bmsg[bmsg_type=error]::before {
+ content: " * ";
+ color: #ff0000;
+}
+.boot .bmsg {
+ text-transform: capitalize;
+ word-wrap: break-word;
+ word-break: break-all;
+}
\ No newline at end of file
diff --git a/content/styles/boot/main.scss b/content/styles/boot/main.scss
new file mode 100644
index 0000000..9407f43
--- /dev/null
+++ b/content/styles/boot/main.scss
@@ -0,0 +1,61 @@
+@import '../config/main';
+
+.boot {
+ margin: 1em 0em 1em 1em;
+ font-size: 1.5em;
+
+ #bootver {
+ color: $boot_header_colour;
+ margin-left: 1.12em; /* makes it that it aligns with 'boot' messages */
+ }
+
+ #bootver::before {
+ content: 'WEBrc version ' $boot_ver;
+ }
+
+ .bmsg[bmsg_type=ok] {
+ &::after {
+ content: '[OK]';
+ float: right;
+ color: $ok_colour;
+ }
+
+ &::before {
+ content: ' * ';
+ color: $ok_colour;
+ }
+ }
+
+
+ .bmsg[bmsg_type=warn] {
+ &::after {
+ content: '[WARNING]';
+ float: right;
+ color: $warn_colour;
+ }
+
+ &::before {
+ content: ' * ';
+ color: $warn_colour;
+ }
+ }
+
+ .bmsg[bmsg_type=error] {
+ &::after {
+ content: '[ERROR]';
+ float: right;
+ color: $error_colour;
+ }
+
+ &::before {
+ content: ' * ';
+ color: $error_colour;
+ }
+ }
+
+ .bmsg {
+ text-transform: capitalize;
+ word-wrap: break-word;
+ word-break: break-all;
+ }
+}
diff --git a/content/styles/config/_main.css b/content/styles/config/_main.css
new file mode 100644
index 0000000..e69de29
diff --git a/content/styles/config/_main.scss b/content/styles/config/_main.scss
new file mode 100644
index 0000000..3ae0396
--- /dev/null
+++ b/content/styles/config/_main.scss
@@ -0,0 +1,10 @@
+$ok_colour: #0fd30f;
+$warn_colour: #ffff00;
+$error_colour: #ff0000;
+$bg_colour: #070707;
+$default_content_colour: #ffffff;
+$boot_header_colour: #9acd32;
+$font_default: monospace;
+$boot_ver: '1.0';
+$shell_colour: $ok_colour;
+$shell_font_size: 1.7em;
diff --git a/content/styles/generic/main.css b/content/styles/generic/main.css
new file mode 100644
index 0000000..7860356
--- /dev/null
+++ b/content/styles/generic/main.css
@@ -0,0 +1,18 @@
+* {
+ box-sizing: border-box;
+ padding: 0;
+ margin: 0;
+ font-family: monospace;
+ color: #ffffff;
+}
+
+html, body {
+ background-color: #070707;
+ margin-bottom: 2em;
+}
+
+.iframe {
+ width: 50%;
+ min-width: 300px;
+ max-width: 1000px;
+}
\ No newline at end of file
diff --git a/content/styles/generic/main.scss b/content/styles/generic/main.scss
new file mode 100644
index 0000000..56b5e83
--- /dev/null
+++ b/content/styles/generic/main.scss
@@ -0,0 +1,23 @@
+@import '../config/main';
+
+
+* {
+ box-sizing: border-box;
+ padding: 0;
+ margin: 0;
+
+ font-family: $font_default;
+ color: $default_content_colour;
+}
+
+html, body {
+ background-color: $bg_colour;
+ margin-bottom: 2em;
+}
+
+
+.iframe {
+ width: 50%;
+ min-width: 300px;
+ max-width: 1000px;
+}
diff --git a/content/styles/shell/main.css b/content/styles/shell/main.css
new file mode 100644
index 0000000..14c6b93
--- /dev/null
+++ b/content/styles/shell/main.css
@@ -0,0 +1,26 @@
+.shell {
+ margin: 2em;
+}
+.shell .prompt {
+ color: #0fd30f;
+ background-color: #070707;
+ border: none;
+ font-size: 1.7em;
+ width: 90%;
+ padding: 0 0 1.2em 0;
+}
+.shell .output {
+ font-size: 1.4166666667em;
+}
+
+.shell::before {
+ content: "$ ";
+ font-size: 1.7em;
+ color: #ffffff;
+}
+
+.shell[prompt=root]::before {
+ content: "# ";
+ font-size: 1.7em;
+ color: #ffffff;
+}
\ No newline at end of file
diff --git a/content/styles/shell/main.scss b/content/styles/shell/main.scss
new file mode 100644
index 0000000..13dcac9
--- /dev/null
+++ b/content/styles/shell/main.scss
@@ -0,0 +1,32 @@
+@import '../config/main';
+
+
+.shell {
+ margin: 2em;
+
+ .prompt {
+ color: $shell_colour;
+ background-color: $bg_colour;
+ border: none;
+
+ font-size: $shell_font_size;
+ width: 90%;
+ padding: 0 0 1.2em 0;
+ }
+
+ .output {
+ font-size: $shell_font_size / 1.2;
+ }
+}
+
+.shell::before {
+ content: '$ ';
+ font-size: $shell_font_size;
+ color: $default_content_colour;
+}
+
+.shell[prompt=root]::before {
+ content: '# ';
+ font-size: $shell_font_size;
+ color: $default_content_colour;
+}
\ No newline at end of file
diff --git a/git.sh b/git.sh
new file mode 100755
index 0000000..2fccf02
--- /dev/null
+++ b/git.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+git add .
+git commit -m "update @ $(date)"
+git push -u origin terminal
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..41bad40
--- /dev/null
+++ b/index.html
@@ -0,0 +1,47 @@
+
+
+
+