Refactors site to use interactive terminal UI
Moves site from static HTML to a dynamic terminal interface. This commit represents a major overhaul, introducing: - A functional terminal emulator implemented in JavaScript. - Command parsing and execution framework. - Various terminal commands for navigation and utility functions. - SASS conversion. The old CSS and simple HTML are completely removed. A new Hugo theme is implemented.
|
|
@ -1,48 +0,0 @@
|
|||
.buy-me-a-coffee {
|
||||
text-align: center;
|
||||
border-radius: var(--radius);
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
|
||||
background-color: var(--secondary);
|
||||
color: var(--tertiary);
|
||||
padding: var(--gap);
|
||||
}
|
||||
|
||||
article a[href^="http"]:not(article .social-icons a, .paginav a, .buy-me-a-coffee a, .post-tags a, a.entry-link),
|
||||
article a[href^="https://"]:not(article .social-icons a, .paginav a, .buy-me-a-coffee a, .post-tags a, a.entry-link)
|
||||
{
|
||||
box-shadow: none;
|
||||
background: linear-gradient(to left, #c34722, #fdbb2d 100%);
|
||||
background-position: 0 100%;
|
||||
background-size: 100% 2px;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-basis: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.photo {
|
||||
flex: 25%;
|
||||
|
||||
img {
|
||||
border-radius: var(--radius);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
flex: 75%;
|
||||
}
|
||||
41
assets/js/commands/core.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Core Commands Module
|
||||
// These are essential commands for the terminal
|
||||
|
||||
// Help command
|
||||
window.terminal.registerCommand("help", "Display available commands", () => {
|
||||
window.terminal.print("Available commands:", "success");
|
||||
window.terminal.print("");
|
||||
|
||||
const commands = Object.keys(window.terminal.commands).sort();
|
||||
commands.forEach((cmd) => {
|
||||
const desc = window.terminal.commands[cmd].description || "No description";
|
||||
window.terminal.print(` ${cmd.padEnd(15)} - ${desc}`);
|
||||
});
|
||||
window.terminal.print("");
|
||||
});
|
||||
|
||||
// Clear command
|
||||
window.terminal.registerCommand("clear", "Clear the terminal screen", () => {
|
||||
window.terminal.clear();
|
||||
});
|
||||
|
||||
// Echo command
|
||||
window.terminal.registerCommand("echo", "Echo text to the terminal", (args) => {
|
||||
window.terminal.print(args.join(" "));
|
||||
});
|
||||
|
||||
// History command
|
||||
window.terminal.registerCommand("history", "Show command history", () => {
|
||||
if (window.terminal.history.length === 0) {
|
||||
window.terminal.print("No commands in history");
|
||||
return;
|
||||
}
|
||||
|
||||
window.terminal.print("Command history:", "info");
|
||||
window.terminal.history
|
||||
.slice()
|
||||
.reverse()
|
||||
.forEach((cmd, idx) => {
|
||||
window.terminal.print(` ${idx + 1}. ${cmd}`);
|
||||
});
|
||||
});
|
||||
101
assets/js/commands/custom.js
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
// Custom Commands Module
|
||||
// Add your custom commands here!
|
||||
// This file is a template for creating your own commands
|
||||
|
||||
// Example: Weather command (placeholder)
|
||||
// window.terminal.registerCommand(
|
||||
// "weather",
|
||||
// "Show weather information",
|
||||
// (args) => {
|
||||
// const city = args.length > 0 ? args.join(" ") : "your location";
|
||||
// window.terminal.printInfo(`Fetching weather for ${city}...`);
|
||||
// window.terminal.print("☀️ Sunny, 72°F");
|
||||
// window.terminal.print("");
|
||||
// window.terminal.printWarning(
|
||||
// "Note: This is a placeholder. Integrate with a real weather API!",
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
|
||||
// Example: Random quote
|
||||
// window.terminal.registerCommand("quote", "Display a random quote", () => {
|
||||
// const quotes = [
|
||||
// "The only way to do great work is to love what you do. - Steve Jobs",
|
||||
// "Innovation distinguishes between a leader and a follower. - Steve Jobs",
|
||||
// "Stay hungry, stay foolish. - Steve Jobs",
|
||||
// "First, solve the problem. Then, write the code. - John Johnson",
|
||||
// ];
|
||||
|
||||
// const randomQuote = quotes[Math.floor(Math.random() * quotes.length)];
|
||||
// window.terminal.printSuccess(randomQuote);
|
||||
// });
|
||||
|
||||
// Example: List command (demonstrates dynamic content)
|
||||
// window.terminal.registerCommand(
|
||||
// "list",
|
||||
// "List items in a collection",
|
||||
// (args) => {
|
||||
// if (args.length === 0) {
|
||||
// window.terminal.printError("Usage: list <category>");
|
||||
// window.terminal.print("Available categories: files, users, tasks");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const category = args[0].toLowerCase();
|
||||
|
||||
// switch (category) {
|
||||
// case "files":
|
||||
// window.terminal.print("Files:", "info");
|
||||
// window.terminal.print(" 📄 document.txt");
|
||||
// window.terminal.print(" 📄 notes.md");
|
||||
// window.terminal.print(" 📁 projects/");
|
||||
// break;
|
||||
// case "users":
|
||||
// window.terminal.print("Users:", "info");
|
||||
// window.terminal.print(" 👤 admin");
|
||||
// window.terminal.print(" 👤 guest");
|
||||
// break;
|
||||
// case "tasks":
|
||||
// window.terminal.print("Tasks:", "info");
|
||||
// window.terminal.print(" ✓ Complete terminal setup");
|
||||
// window.terminal.print(" ☐ Add more commands");
|
||||
// window.terminal.print(" ☐ Customize appearance");
|
||||
// break;
|
||||
// default:
|
||||
// window.terminal.printError(`Unknown category: ${category}`);
|
||||
// }
|
||||
// },
|
||||
// );
|
||||
|
||||
// Example: Color command (demonstrates HTML output)
|
||||
window.terminal.registerCommand("colors", "Display available colors", () => {
|
||||
window.terminal.print("Available terminal colors:", "info");
|
||||
window.terminal.print("");
|
||||
window.terminal.printHTML("<span>● Standard (green)</span>");
|
||||
window.terminal.printHTML('<span class="error">● Error (red)</span>');
|
||||
window.terminal.printHTML(
|
||||
'<span class="success">● Success (bright green)</span>',
|
||||
);
|
||||
window.terminal.printHTML('<span class="info">● Info (blue)</span>');
|
||||
window.terminal.printHTML('<span class="warning">● Warning (orange)</span>');
|
||||
});
|
||||
|
||||
// ADD YOUR OWN COMMANDS BELOW THIS LINE
|
||||
// ========================================
|
||||
|
||||
// Template for new command:
|
||||
/*
|
||||
window.terminal.registerCommand('commandname', 'Command description', (args) => {
|
||||
// args is an array of arguments
|
||||
// Example: if user types "mycommand hello world"
|
||||
// args will be ['hello', 'world']
|
||||
|
||||
// Print output using:
|
||||
window.terminal.print('Regular text');
|
||||
window.terminal.printSuccess('Success message');
|
||||
window.terminal.printError('Error message');
|
||||
window.terminal.printInfo('Info message');
|
||||
window.terminal.printWarning('Warning message');
|
||||
window.terminal.printHTML('<strong>HTML content</strong>');
|
||||
});
|
||||
*/
|
||||
52
assets/js/commands/navigation.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Navigation Commands Module
|
||||
// Commands for navigating to different pages or URLs
|
||||
|
||||
// Navigate to URL command
|
||||
window.terminal.registerCommand("goto", "Navigate to a URL", (args) => {
|
||||
if (args.length === 0) {
|
||||
window.terminal.printError("Usage: goto <url>");
|
||||
window.terminal.print("Examples:");
|
||||
window.terminal.print(" goto google.com");
|
||||
window.terminal.print(" goto https://github.com");
|
||||
return;
|
||||
}
|
||||
|
||||
const url = args[0];
|
||||
window.terminal.printInfo(`Navigating to ${url}...`);
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = url.startsWith("http") ? url : `https://${url}`;
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// Open in new tab command
|
||||
window.terminal.registerCommand("open", "Open URL in new tab", (args) => {
|
||||
if (args.length === 0) {
|
||||
window.terminal.printError("Usage: open <url>");
|
||||
window.terminal.print("Examples:");
|
||||
window.terminal.print(" open google.com");
|
||||
window.terminal.print(" open https://github.com");
|
||||
return;
|
||||
}
|
||||
|
||||
const url = args[0];
|
||||
window.terminal.printInfo(`Opening ${url} in new tab...`);
|
||||
|
||||
const fullUrl = url.startsWith("http") ? url : `https://${url}`;
|
||||
window.open(fullUrl, "_blank");
|
||||
});
|
||||
|
||||
// Reload page command
|
||||
window.terminal.registerCommand("reload", "Reload the current page", () => {
|
||||
window.terminal.printInfo("Reloading page...");
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// PAGE NAVIGATION
|
||||
|
||||
// About command
|
||||
window.terminal.registerCommand("about", "About this site", () => {
|
||||
window.location.href = "/about/";
|
||||
});
|
||||
97
assets/js/commands/utility.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Utility Commands Module
|
||||
// Useful utility commands
|
||||
|
||||
// Time command
|
||||
window.terminal.registerCommand("time", "Display current time", () => {
|
||||
const now = new Date();
|
||||
window.terminal.print(`Current time: ${now.toLocaleString()}`);
|
||||
});
|
||||
|
||||
// Calculator command
|
||||
window.terminal.registerCommand("calc", "Simple calculator", (args) => {
|
||||
if (args.length === 0) {
|
||||
window.terminal.printError("Usage: calc <expression>");
|
||||
window.terminal.print("Example: calc 5 + 3");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const expression = args.join(" ");
|
||||
// Note: eval is dangerous in production! This is just for demo purposes
|
||||
const result = eval(expression);
|
||||
window.terminal.printSuccess(`Result: ${result}`);
|
||||
} catch (error) {
|
||||
window.terminal.printError("Invalid expression");
|
||||
}
|
||||
});
|
||||
|
||||
// Demo command
|
||||
// window.terminal.registerCommand("demo", "Show demo content", () => {
|
||||
// window.terminal.printSuccess("=== Demo Content ===");
|
||||
// window.terminal.print("");
|
||||
// window.terminal.print("This is regular text");
|
||||
// window.terminal.printInfo("This is info text");
|
||||
// window.terminal.printWarning("This is warning text");
|
||||
// window.terminal.printError("This is error text");
|
||||
// window.terminal.print("");
|
||||
// window.terminal.printHTML(
|
||||
// 'You can also use <strong>HTML</strong> with <a href="#">links</a>!',
|
||||
// );
|
||||
// });
|
||||
|
||||
// ASCII art command
|
||||
// window.terminal.registerCommand("ascii", "Display ASCII art", () => {
|
||||
// const art = `
|
||||
// _____ _ _
|
||||
// |_ _|__ _ __ _ __ ___ (_)_ __ __ _| |
|
||||
// | |/ _ \\ '__| '_ \` _ \\| | '_ \\ / _\` | |
|
||||
// | | __/ | | | | | | | | | | | (_| | |
|
||||
// |_|\\___|_| |_| |_| |_|_|_| |_|\\__,_|_|
|
||||
// `;
|
||||
// window.terminal.print(art, "success");
|
||||
// });
|
||||
|
||||
// ASCII art command
|
||||
window.terminal.registerCommand("nerv", "Display NERV logo", () => {
|
||||
const art = `
|
||||
# ## %*###
|
||||
#******************
|
||||
#*******************
|
||||
********************
|
||||
%* **************************
|
||||
*** #*****************************
|
||||
** *******************************%
|
||||
*# *********************************
|
||||
%* %************************************
|
||||
******************************************
|
||||
*************************************
|
||||
**********************# ******#*
|
||||
*** *% %** %**********************
|
||||
*%**# * ** #*************************
|
||||
* *** * ** *************************
|
||||
* %**# * **#####*************************#
|
||||
* *** * ** * %**********************%
|
||||
* %**#* ** #*********************
|
||||
* *** ** %% ********************#
|
||||
*% %* %** ** *******************
|
||||
%******************
|
||||
#********# #*******************
|
||||
** #** ******************
|
||||
** **# *** *************#
|
||||
** #** **# ************
|
||||
*******# **% %**********
|
||||
** %** ** *%#*******#
|
||||
** *** #**#* ******
|
||||
** #**% *** ****#
|
||||
%****% ***% * %***
|
||||
#*
|
||||
|
||||
`;
|
||||
window.terminal.print(art, "success");
|
||||
});
|
||||
|
||||
// Greet command
|
||||
window.terminal.registerCommand("greet", "Greet the user", (args) => {
|
||||
const name = args.length > 0 ? args.join(" ") : "User";
|
||||
window.terminal.printSuccess(`Hello, ${name}! Welcome to the terminal.`);
|
||||
});
|
||||
16
assets/js/init.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Terminal Initialization Script
|
||||
// This script creates the terminal instance immediately
|
||||
// so command modules can register commands
|
||||
|
||||
// Create global terminal instance immediately
|
||||
window.terminal = new TerminalShell();
|
||||
|
||||
// Boot the terminal when DOM is ready
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
terminal.boot();
|
||||
});
|
||||
} else {
|
||||
// DOM already loaded
|
||||
terminal.boot();
|
||||
}
|
||||
70
assets/js/lavalamp.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
(function () {
|
||||
const lavaLamp = document.getElementById("lavaLamp");
|
||||
let blobs = [];
|
||||
let baseSpeed = 0.8;
|
||||
|
||||
function createBlob() {
|
||||
const blob = document.createElement("div");
|
||||
blob.className = "blob";
|
||||
const size = Math.random() * 30 + 20; // Smaller blobs (20-50px)
|
||||
const startY = Math.random() * 100; // Within ~150px height
|
||||
const duration = (Math.random() * 8 + 12) / baseSpeed;
|
||||
const maxX = 60 - size; // Adjusted for narrower tube (80px wide)
|
||||
const startX = Math.random() * maxX;
|
||||
|
||||
blob.style.width = `${size}px`;
|
||||
blob.style.height = `${size}px`;
|
||||
blob.style.left = `${startX}px`;
|
||||
blob.style.setProperty("--duration", `${duration}s`);
|
||||
blob.style.setProperty("--start-x", "0px");
|
||||
blob.style.setProperty("--start-y", `${startY}px`);
|
||||
blob.style.setProperty("--mid1-x", `${Math.random() * 15 - 15}px`);
|
||||
blob.style.setProperty("--mid1-y", `${Math.random() * -40 - 40}px`);
|
||||
blob.style.setProperty("--mid2-x", `${Math.random() * 20 - 20}px`);
|
||||
blob.style.setProperty("--mid2-y", `${Math.random() * -80 - 40}px`);
|
||||
blob.style.setProperty("--mid3-x", `${Math.random() * 15 - 15}px`);
|
||||
blob.style.setProperty("--mid3-y", `${Math.random() * -60 - 10}px`);
|
||||
blob.style.setProperty("--scale1", (Math.random() * 0.3 + 1.0).toFixed(2));
|
||||
blob.style.setProperty("--scale2", (Math.random() * 0.3 + 0.85).toFixed(2));
|
||||
blob.style.setProperty("--scale3", (Math.random() * 0.3 + 0.95).toFixed(2));
|
||||
blob.style.animationDelay = `${Math.random() * -20}s`;
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
function updateBlobColors() {
|
||||
const color1 = "#FF7800";
|
||||
const color2 = "#E01B24";
|
||||
const gradient = `radial-gradient(circle at 30% 30%, ${color1}, ${color2})`;
|
||||
blobs.forEach((blob) => {
|
||||
blob.style.background = gradient;
|
||||
});
|
||||
}
|
||||
|
||||
function updateLampBackground() {
|
||||
const bg1 = "#F8E45C";
|
||||
const bg2 = "#FF7800";
|
||||
lavaLamp.style.background = `linear-gradient(180deg, ${bg1} 0%, ${bg2} 100%)`;
|
||||
}
|
||||
|
||||
function updateBlobCount() {
|
||||
const count = parseInt(6);
|
||||
while (blobs.length > count) {
|
||||
const blob = blobs.pop();
|
||||
lavaLamp.removeChild(blob);
|
||||
}
|
||||
while (blobs.length < count) {
|
||||
const blob = createBlob();
|
||||
blobs.push(blob);
|
||||
lavaLamp.appendChild(blob);
|
||||
updateBlobColors();
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
updateBlobCount();
|
||||
updateLampBackground();
|
||||
}
|
||||
|
||||
init();
|
||||
})();
|
||||
190
assets/js/terminal.js
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// Terminal Shell System
|
||||
class TerminalShell {
|
||||
constructor() {
|
||||
this.output = document.getElementById("output");
|
||||
this.input = document.getElementById("input");
|
||||
this.inputContainer = document.getElementById("input-container");
|
||||
this.history = [];
|
||||
this.historyIndex = -1;
|
||||
this.commands = {};
|
||||
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
// Boot sequence
|
||||
async boot() {
|
||||
const bootMessages = [
|
||||
" _ _ _____ ______ __",
|
||||
" | \\ | | ____| _ \\ \\ / /",
|
||||
" | \\| | _| | |_) \\ \\ / / ",
|
||||
" | |\\ | |___| _ < \\ V / ",
|
||||
" |_| \\_|_____|_| \\_\\ \\_/ ",
|
||||
"",
|
||||
"NERV OS v2.015 - MAGI System Interface",
|
||||
"Initializing A.T. Field protocols...",
|
||||
"CASPER... ONLINE",
|
||||
"BALTHASAR... ONLINE",
|
||||
"MELCHIOR... ONLINE",
|
||||
"Synchronization ratio: 41.3%... 67.8%... 89.2%... OK",
|
||||
"Loading Evangelion Unit-01 core drivers... OK",
|
||||
"Mounting LCL interface... OK",
|
||||
"Neural connection established... OK",
|
||||
"",
|
||||
"Running pattern analysis... PATTERN BLUE",
|
||||
"",
|
||||
"All systems optimal.",
|
||||
"",
|
||||
"",
|
||||
];
|
||||
for (let i = 0; i < bootMessages.length; i++) {
|
||||
await this.sleep(100);
|
||||
const line = document.createElement("div");
|
||||
line.className = "output-line boot-line";
|
||||
line.textContent = bootMessages[i];
|
||||
line.style.animationDelay = "0s";
|
||||
this.output.appendChild(line);
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
this.printHTML(
|
||||
'<span class="info">Type "help" for available commands.</span>',
|
||||
);
|
||||
|
||||
this.printHTML(
|
||||
'<span class="warning">This site is under contstruction. There\'s nothing of interest here yet.</span>',
|
||||
);
|
||||
|
||||
this.inputContainer.classList.remove("hidden");
|
||||
this.input.focus();
|
||||
}
|
||||
|
||||
// Utility function for delays
|
||||
sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
// Setup event listeners
|
||||
setupEventListeners() {
|
||||
this.input.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
this.executeCommand(this.input.value.trim());
|
||||
this.input.value = "";
|
||||
} else if (e.key === "ArrowUp") {
|
||||
e.preventDefault();
|
||||
this.navigateHistory("up");
|
||||
} else if (e.key === "ArrowDown") {
|
||||
e.preventDefault();
|
||||
this.navigateHistory("down");
|
||||
}
|
||||
});
|
||||
|
||||
// Keep input focused
|
||||
document.addEventListener("click", () => {
|
||||
this.input.focus();
|
||||
});
|
||||
}
|
||||
|
||||
// Command history navigation
|
||||
navigateHistory(direction) {
|
||||
if (this.history.length === 0) return;
|
||||
|
||||
if (direction === "up") {
|
||||
if (this.historyIndex < this.history.length - 1) {
|
||||
this.historyIndex++;
|
||||
this.input.value = this.history[this.historyIndex];
|
||||
}
|
||||
} else if (direction === "down") {
|
||||
if (this.historyIndex > 0) {
|
||||
this.historyIndex--;
|
||||
this.input.value = this.history[this.historyIndex];
|
||||
} else {
|
||||
this.historyIndex = -1;
|
||||
this.input.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Execute command
|
||||
executeCommand(commandString) {
|
||||
if (!commandString) return;
|
||||
|
||||
// Echo the command
|
||||
this.print(`> ${commandString}`);
|
||||
|
||||
// Add to history
|
||||
this.history.unshift(commandString);
|
||||
this.historyIndex = -1;
|
||||
|
||||
// Parse command and arguments
|
||||
const parts = commandString.split(" ");
|
||||
const command = parts[0].toLowerCase();
|
||||
const args = parts.slice(1);
|
||||
|
||||
// Execute command
|
||||
if (this.commands[command]) {
|
||||
try {
|
||||
this.commands[command](args);
|
||||
} catch (error) {
|
||||
this.printError(`Error executing command: ${error.message}`);
|
||||
}
|
||||
} else {
|
||||
this.printError(`Command not found: ${command}`);
|
||||
}
|
||||
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
// Register a new command
|
||||
registerCommand(name, description, callback) {
|
||||
this.commands[name.toLowerCase()] = callback;
|
||||
this.commands[name.toLowerCase()].description = description;
|
||||
}
|
||||
|
||||
// Print methods
|
||||
print(text, className = "") {
|
||||
const line = document.createElement("div");
|
||||
line.className = `output-line ${className}`;
|
||||
|
||||
if (typeof text === "string") {
|
||||
line.textContent = text;
|
||||
} else {
|
||||
line.appendChild(text);
|
||||
}
|
||||
|
||||
this.output.appendChild(line);
|
||||
}
|
||||
|
||||
printHTML(html, className = "") {
|
||||
const line = document.createElement("div");
|
||||
line.className = `output-line ${className}`;
|
||||
line.innerHTML = html;
|
||||
this.output.appendChild(line);
|
||||
}
|
||||
|
||||
printError(text) {
|
||||
this.print(text, "error");
|
||||
}
|
||||
|
||||
printSuccess(text) {
|
||||
this.print(text, "success");
|
||||
}
|
||||
|
||||
printInfo(text) {
|
||||
this.print(text, "info");
|
||||
}
|
||||
|
||||
printWarning(text) {
|
||||
this.print(text, "warning");
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this.output.parentElement.scrollTop =
|
||||
this.output.parentElement.scrollHeight;
|
||||
}
|
||||
|
||||
// Clear the terminal
|
||||
clear() {
|
||||
this.output.innerHTML = "";
|
||||
}
|
||||
}
|
||||
255
assets/sass/_normalize.scss
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*! modern-normalize | MIT License | https://github.com/sindresorhus/modern-normalize */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Use a better box model (opinionated).
|
||||
*/
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: inherit;
|
||||
&::before, &::after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a more readable tab size (opinionated).
|
||||
*/
|
||||
|
||||
:root {
|
||||
-moz-tab-size: 4;
|
||||
tab-size: 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15;
|
||||
/* 1 */
|
||||
-webkit-text-size-adjust: 100%;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
|
||||
*/
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct height in Firefox.
|
||||
*/
|
||||
|
||||
hr {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct text decoration in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b, strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3)
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code, kbd, samp, pre {
|
||||
font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
||||
/* 1 */
|
||||
font-size: 1em;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in all browsers.
|
||||
*/
|
||||
|
||||
sub, sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button, input, optgroup, select, textarea {
|
||||
font-family: inherit;
|
||||
/* 1 */
|
||||
font-size: 100%;
|
||||
/* 1 */
|
||||
line-height: 1.15;
|
||||
/* 1 */
|
||||
margin: 0;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge and Firefox.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button, select {
|
||||
/* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button, [type='button'], [type='reset'], [type='submit'] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner, [type='button']::-moz-focus-inner, [type='reset']::-moz-focus-inner, [type='submit']::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring, [type='button']:-moz-focusring, [type='reset']:-moz-focusring, [type='submit']:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the padding so developers are not caught out when they zero out `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome and Firefox.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Safari.
|
||||
*/
|
||||
|
||||
[type='number'] {
|
||||
&::-webkit-inner-spin-button, &::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type='search'] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
outline-offset: -2px;
|
||||
/* 2 */
|
||||
&::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
font: inherit;
|
||||
/* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Chrome and Safari.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
23
assets/sass/partials/_global-styles.scss
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
footer[role="contentinfo"] {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 10000;
|
||||
background: #000; // or whatever color you want
|
||||
color: #0f0; // match your terminal green theme
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
font-family: monospace;
|
||||
border-top: 1px solid #0f0;
|
||||
border-left: 1px solid #0f0;
|
||||
border-top-left-radius: 5px;
|
||||
|
||||
a {
|
||||
color: #0f0;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
122
assets/sass/partials/_lavalamp.scss
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
.lava-lamp-container {
|
||||
position: absolute;
|
||||
bottom: 20%;
|
||||
left: 20%;
|
||||
width: 80px;
|
||||
height: 150px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.lamp-cap {
|
||||
width: 60%;
|
||||
height: 10%;
|
||||
background: linear-gradient(180deg, #c0c0c0 0%, #888 50%, #666 100%);
|
||||
border-radius: 60px 60px 0 0;
|
||||
box-shadow:
|
||||
0 2px 8px rgba(0, 0, 0, 0.5),
|
||||
inset 0 2px 4px rgba(255, 255, 255, 0.3);
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.lava-lamp {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 102%; /*Being above 100% fixes the occasional gap when resizing the page, theoretically */
|
||||
background: var(--lamp-bg, linear-gradient(180deg, #2a1a4a 0%, #1a0a3a 100%));
|
||||
clip-path: polygon(20% 0, 80% 0, 100% 100%, 0% 100%);
|
||||
overflow: hidden;
|
||||
box-shadow:
|
||||
inset 0 0 60px rgba(0, 0, 0, 0.3),
|
||||
inset -10px 0 40px rgba(255, 255, 255, 0.1),
|
||||
inset 10px 0 40px rgba(0, 0, 0, 0.2);
|
||||
filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
|
||||
.lava-lamp::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent 0%,
|
||||
rgba(255, 255, 255, 0.15) 20%,
|
||||
rgba(255, 255, 255, 0.05) 40%,
|
||||
transparent 60%
|
||||
);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.lamp-base {
|
||||
width: 100%;
|
||||
height: 20%;
|
||||
background: linear-gradient(180deg, #888 0%, #555 40%, #333 100%);
|
||||
border-radius: 0 0 40px 40px / 0 0 60px 60px;
|
||||
box-shadow:
|
||||
0 10px 30px rgba(0, 0, 0, 0.6),
|
||||
inset 0 5px 10px rgba(255, 255, 255, 0.2),
|
||||
inset 0 -5px 10px rgba(0, 0, 0, 0.5);
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.blob {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background: var(
|
||||
--blob-color,
|
||||
radial-gradient(circle at 30% 30%, #ff6b9d, #c44569)
|
||||
);
|
||||
filter: url(#goo);
|
||||
animation: float var(--duration) ease-in-out infinite;
|
||||
opacity: 0.95;
|
||||
mix-blend-mode: normal;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translate(var(--start-x), var(--start-y)) scale(1);
|
||||
}
|
||||
25% {
|
||||
transform: translate(var(--mid1-x), var(--mid1-y)) scale(var(--scale1, 1.1));
|
||||
}
|
||||
50% {
|
||||
transform: translate(var(--mid2-x), var(--mid2-y)) scale(var(--scale2, 0.9));
|
||||
}
|
||||
75% {
|
||||
transform: translate(var(--mid3-x), var(--mid3-y))
|
||||
scale(var(--scale3, 1.05));
|
||||
}
|
||||
}
|
||||
|
||||
.lamp-text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-35%, -50%) rotate(85deg);
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
color: rgba(224, 27, 36, 0);
|
||||
transition: color 0.5s ease;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.lava-lamp:hover .lamp-text {
|
||||
color: rgba(224, 27, 36, 0.7);
|
||||
}
|
||||
|
||||
.lava-lamp:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
28
assets/sass/partials/_now-playing.scss
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.nowplayingcard {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.nowplayingcontainer-inner {
|
||||
transition: 0.3s;
|
||||
display: inline-flex;
|
||||
|
||||
.trackInfo {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#album {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
img#trackart {
|
||||
transition: 0.3s;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
filter: grayscale(60%);
|
||||
}
|
||||
|
||||
img#trackart[src=""] {
|
||||
display: none;
|
||||
}
|
||||
99
assets/sass/partials/_terminal.scss
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#terminal {
|
||||
padding: 3px;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.output-line {
|
||||
margin: 2px 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.boot-line {
|
||||
opacity: 0;
|
||||
animation: fadeIn 0.1s forwards;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.input-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.prompt {
|
||||
color: #00ff00;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
#input {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #00ff00;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
outline: none;
|
||||
flex: 1;
|
||||
caret-color: #00ff00;
|
||||
}
|
||||
|
||||
.cursor {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 18px;
|
||||
background: #00ff00;
|
||||
animation: blink 1s infinite;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
0%,
|
||||
49% {
|
||||
opacity: 1;
|
||||
}
|
||||
50%,
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #ff4444;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: #44ff44;
|
||||
}
|
||||
|
||||
.info {
|
||||
color: #00ffff;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: #ff9900;
|
||||
}
|
||||
|
||||
#terminal::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
#terminal::-webkit-scrollbar-track {
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
#terminal::-webkit-scrollbar-thumb {
|
||||
background: #00ff00;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
191
assets/sass/partials/_vu-meter.scss
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/* VU Meter on desk */
|
||||
.vu-meter {
|
||||
position: absolute;
|
||||
bottom: 18%;
|
||||
right: 30%;
|
||||
width: 120px;
|
||||
height: 60px;
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
.vu-meter-body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(180deg, #2a2a2a 0%, #1a1a1a 100%);
|
||||
border: 2px solid #333;
|
||||
border-radius: 4px;
|
||||
box-shadow:
|
||||
0 4px 12px rgba(0, 0, 0, 0.7),
|
||||
inset 0 2px 4px rgba(255, 255, 255, 0.1),
|
||||
inset 0 -2px 4px rgba(0, 0, 0, 0.3);
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.vu-meter-screen {
|
||||
flex: 1;
|
||||
background: #0a0a0a;
|
||||
border-radius: 2px;
|
||||
padding: 6px 4px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.vu-bars {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-around;
|
||||
height: 100%;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.vu-bar {
|
||||
flex: 1;
|
||||
background: linear-gradient(
|
||||
to top,
|
||||
#0f0 0%,
|
||||
#0f0 60%,
|
||||
#ff0 60%,
|
||||
#ff0 85%,
|
||||
#f00 85%,
|
||||
#f00 100%
|
||||
);
|
||||
border-radius: 1px;
|
||||
box-shadow:
|
||||
0 0 4px rgba(0, 255, 0, 0.6),
|
||||
inset 0 0 2px rgba(255, 255, 255, 0.2);
|
||||
animation: vu-bounce 1.5s ease-in-out infinite;
|
||||
animation-delay: var(--delay);
|
||||
height: var(--height);
|
||||
min-height: 10%;
|
||||
}
|
||||
|
||||
@keyframes vu-bounce {
|
||||
0%,
|
||||
100% {
|
||||
height: var(--height);
|
||||
filter: brightness(1);
|
||||
}
|
||||
25% {
|
||||
height: calc(var(--height) * 0.6);
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
50% {
|
||||
height: calc(var(--height) * 1.2);
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
75% {
|
||||
height: calc(var(--height) * 0.8);
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
/* Peak indicator line */
|
||||
.vu-peak-line {
|
||||
position: absolute;
|
||||
top: 15%;
|
||||
left: 4px;
|
||||
right: 4px;
|
||||
height: 1px;
|
||||
background: #f00;
|
||||
opacity: 0.6;
|
||||
box-shadow: 0 0 3px #f00;
|
||||
animation: peak-pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes peak-pulse {
|
||||
0%,
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
top: 15%;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.3;
|
||||
top: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
/* LED indicators */
|
||||
.vu-leds {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.vu-led {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.vu-led.green {
|
||||
background: #0f0;
|
||||
box-shadow:
|
||||
0 0 6px #0f0,
|
||||
inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
animation: led-blink-green 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.vu-led.yellow {
|
||||
background: #880;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
animation: led-blink-yellow 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.vu-led.red {
|
||||
background: #400;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
animation: led-blink-red 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes led-blink-green {
|
||||
0%,
|
||||
100% {
|
||||
background: #0f0;
|
||||
box-shadow:
|
||||
0 0 6px #0f0,
|
||||
inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
50% {
|
||||
background: #0a0;
|
||||
box-shadow:
|
||||
0 0 3px #0a0,
|
||||
inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes led-blink-yellow {
|
||||
0%,
|
||||
40%,
|
||||
100% {
|
||||
background: #880;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
50%,
|
||||
60% {
|
||||
background: #ff0;
|
||||
box-shadow:
|
||||
0 0 6px #ff0,
|
||||
inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes led-blink-red {
|
||||
0%,
|
||||
85%,
|
||||
100% {
|
||||
background: #400;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
90%,
|
||||
95% {
|
||||
background: #f00;
|
||||
box-shadow:
|
||||
0 0 6px #f00,
|
||||
inset 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
1762
assets/sass/style.scss
Normal file
88
config.yml
|
|
@ -1,53 +1,22 @@
|
|||
baseURL: "https://ritual.sh/"
|
||||
title: ritual.sh
|
||||
paginate: 5
|
||||
theme: PaperMod
|
||||
|
||||
theme: "hugo-starter"
|
||||
enableRobotsTXT: true
|
||||
buildDrafts: false
|
||||
buildFuture: false
|
||||
buildExpired: false
|
||||
|
||||
googleAnalytics: UA-123-45
|
||||
|
||||
enableEmoji: true
|
||||
|
||||
# Fixed: Changed from 'paginate: 5' to pagination block
|
||||
pagination:
|
||||
pagerSize: 5
|
||||
|
||||
minify:
|
||||
disableXML: true
|
||||
minifyOutput: true
|
||||
|
||||
params:
|
||||
env: production # to enable google analytics, opengraph, twitter-cards and schema.
|
||||
title: ritual
|
||||
description: "Personal website of Dan Baker - Software Engineer"
|
||||
keywords: [Blog]
|
||||
author: Me
|
||||
# author: ["Me", "You"] # multiple authors
|
||||
images: ["<link or path of image for opengraph, twitter-cards>"]
|
||||
DateFormat: "January 2, 2006"
|
||||
defaultTheme: dark # dark, light
|
||||
disableThemeToggle: false
|
||||
|
||||
ShowReadingTime: true
|
||||
ShowShareButtons: false
|
||||
ShowPostNavLinks: true
|
||||
ShowBreadCrumbs: false
|
||||
ShowCodeCopyButtons: false
|
||||
ShowWordCount: true
|
||||
ShowRssButtonInSectionTermList: true
|
||||
UseHugoToc: true
|
||||
disableSpecial1stPost: false
|
||||
disableScrollToTop: false
|
||||
comments: true
|
||||
hidemeta: false
|
||||
hideSummary: false
|
||||
hideAuthor: true
|
||||
showtoc: false
|
||||
tocopen: false
|
||||
|
||||
mainSections:
|
||||
- posts
|
||||
- gear
|
||||
env: production
|
||||
|
||||
label:
|
||||
text: "ritual"
|
||||
|
|
@ -55,9 +24,8 @@ params:
|
|||
iconImageHeight: 35
|
||||
iconHeight: 70
|
||||
|
||||
# profile-mode
|
||||
profileMode:
|
||||
enabled: false # needs to be explicitly set
|
||||
enabled: false
|
||||
title: ExampleSite
|
||||
subtitle: "This is subtitle"
|
||||
imageUrl: "<img location>"
|
||||
|
|
@ -70,11 +38,6 @@ params:
|
|||
- name: Tags
|
||||
url: tags
|
||||
|
||||
# home-info mode
|
||||
homeInfoParams:
|
||||
Title: "I’m Dan. I live in the Golden Valley, Herefordshire. I work remotely as a software engineer, team leader, and system architect. "
|
||||
Content: "I like to talk about engineering, networking, and system design. There’s a higher change I will also talk about many of my other interests – photography, digital minimalism, lego, gaming and game dev, coffee, or the great outdoors."
|
||||
|
||||
socialIcons:
|
||||
- name: instagram
|
||||
url: "https://www.instagram.com/ritualphotos"
|
||||
|
|
@ -85,26 +48,12 @@ params:
|
|||
- name: lastfm
|
||||
url: "https://www.last.fm/user/ritualplays"
|
||||
|
||||
analytics:
|
||||
google:
|
||||
SiteVerificationTag: "XYZabc"
|
||||
bing:
|
||||
SiteVerificationTag: "XYZabc"
|
||||
yandex:
|
||||
SiteVerificationTag: "XYZabc"
|
||||
|
||||
cover:
|
||||
hidden: false # hide everywhere but not in structured data
|
||||
hiddenInList: true # hide on list pages and home
|
||||
hiddenInSingle: false # hide on single page
|
||||
hidden: false
|
||||
hiddenInList: true
|
||||
hiddenInSingle: false
|
||||
|
||||
editPost:
|
||||
URL: "https://github.com/<path_to_repo>/content"
|
||||
Text: "Suggest Changes" # edit text
|
||||
appendFilePath: true # to append file path to Edit link
|
||||
|
||||
# for search
|
||||
# https://fusejs.io/api/options.html
|
||||
fuseOpts:
|
||||
isCaseSensitive: false
|
||||
shouldSort: true
|
||||
|
|
@ -112,8 +61,9 @@ params:
|
|||
distance: 1000
|
||||
threshold: 0.4
|
||||
minMatchCharLength: 0
|
||||
limit: 10 # refer: https://www.fusejs.io/api/methods.html#search
|
||||
limit: 10
|
||||
keys: ["title", "permalink", "summary", "content"]
|
||||
|
||||
menu:
|
||||
main:
|
||||
- identifier: about
|
||||
|
|
@ -132,17 +82,19 @@ menu:
|
|||
name: tags
|
||||
url: /tags/
|
||||
weight: 20
|
||||
# Read: https://github.com/adityatelange/hugo-PaperMod/wiki/FAQs#using-hugos-syntax-highlighter-chroma
|
||||
|
||||
pygmentsUseClasses: true
|
||||
|
||||
markup:
|
||||
highlight:
|
||||
noClasses: false
|
||||
# anchorLineNos: true
|
||||
# codeFences: true
|
||||
# guessSyntax: true
|
||||
# lineNos: true
|
||||
# style: monokai
|
||||
# Fixed: Added goldmark renderer to allow raw HTML
|
||||
goldmark:
|
||||
renderer:
|
||||
unsafe: true
|
||||
|
||||
module:
|
||||
imports:
|
||||
- path: github.com/hugo-mods/lazyimg
|
||||
|
||||
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
title: Finding the right dumb phone for me
|
||||
author: Dan
|
||||
type: post
|
||||
date: -001-11-30T00:00:00+00:00
|
||||
draft: true
|
||||
url: /?p=178
|
||||
categories:
|
||||
- Digital Minimalism
|
||||
|
||||
---
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
title: Going back to an MP3 player in 2024
|
||||
author: Dan
|
||||
type: post
|
||||
date: -001-11-30T00:00:00+00:00
|
||||
draft: true
|
||||
url: /?p=190
|
||||
categories:
|
||||
- Uncategorised
|
||||
|
||||
---
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
title: My Every Day Carry (EDC) – Early 2024 Edition
|
||||
author: Dan
|
||||
type: post
|
||||
date: -001-11-30T00:00:00+00:00
|
||||
draft: true
|
||||
url: /?p=192
|
||||
categories:
|
||||
- Digital Minimalism
|
||||
- Life
|
||||
tags:
|
||||
- edc
|
||||
- every day carry
|
||||
- tech
|
||||
|
||||
---
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
{{- define "main" }}
|
||||
|
||||
{{- if (and site.Params.profileMode.enabled .IsHome) }}
|
||||
{{- partial "index_profile.html" . }}
|
||||
{{- else }} {{/* if not profileMode */}}
|
||||
|
||||
{{- if not .IsHome | and .Title }}
|
||||
<header class="page-header">
|
||||
{{- partial "breadcrumbs.html" . }}
|
||||
<h1>
|
||||
{{ .Title }}
|
||||
{{- if and (or (eq .Kind `term`) (eq .Kind `section`)) (.Param "ShowRssButtonInSectionTermList") }}
|
||||
{{- with .OutputFormats.Get "rss" }}
|
||||
<a href="{{ .RelPermalink }}" title="RSS" aria-label="RSS">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round" height="23">
|
||||
<path d="M4 11a9 9 0 0 1 9 9" />
|
||||
<path d="M4 4a16 16 0 0 1 16 16" />
|
||||
<circle cx="5" cy="19" r="1" />
|
||||
</svg>
|
||||
</a>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
</h1>
|
||||
{{- if .Description }}
|
||||
<div class="post-description">
|
||||
{{ .Description | markdownify }}
|
||||
</div>
|
||||
{{- end }}
|
||||
</header>
|
||||
{{- end }}
|
||||
|
||||
{{- if .Content }}
|
||||
<div class="post-content">
|
||||
{{- if not (.Param "disableAnchoredHeadings") }}
|
||||
{{- partial "anchored_headings.html" .Content -}}
|
||||
{{- else }}{{ .Content }}{{ end }}
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
{{- $pages := union .RegularPages .Sections }}
|
||||
|
||||
{{- if .IsHome }}
|
||||
{{- $pages = where site.RegularPages "Type" "in" site.Params.mainSections }}
|
||||
{{- $pages = where $pages "Params.hiddenInHomeList" "!=" "true" }}
|
||||
{{- end }}
|
||||
|
||||
{{- $paginator := .Paginate $pages }}
|
||||
|
||||
{{- if and .IsHome site.Params.homeInfoParams (eq $paginator.PageNumber 1) }}
|
||||
{{- partial "home_info.html" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- $term := .Data.Term }}
|
||||
{{- range $index, $page := $paginator.Pages }}
|
||||
|
||||
{{- $class := "post-entry" }}
|
||||
|
||||
{{- $user_preferred := or site.Params.disableSpecial1stPost site.Params.homeInfoParams }}
|
||||
{{- if (and $.IsHome (eq $paginator.PageNumber 1) (eq $index 0) (not $user_preferred)) }}
|
||||
{{- $class = "first-entry" }}
|
||||
{{- else if $term }}
|
||||
{{- $class = "post-entry tag-entry" }}
|
||||
{{- end }}
|
||||
|
||||
<article class="{{ $class }}">
|
||||
{{- $isHidden := (.Param "cover.hiddenInList") | default (.Param "cover.hidden") | default false }}
|
||||
{{- partial "cover.html" (dict "cxt" . "IsSingle" false "isHidden" $isHidden) }}
|
||||
<header class="entry-header">
|
||||
<h2 class="entry-hint-parent">
|
||||
{{- .Title }}
|
||||
{{- if .Draft }}
|
||||
<span class="entry-hint" title="Draft">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 -960 960 960" fill="currentColor">
|
||||
<path
|
||||
d="M160-410v-60h300v60H160Zm0-165v-60h470v60H160Zm0-165v-60h470v60H160Zm360 580v-123l221-220q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q9 9 13 20t4 22q0 11-4.5 22.5T862.09-380L643-160H520Zm300-263-37-37 37 37ZM580-220h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z" />
|
||||
</svg>
|
||||
</span>
|
||||
{{- end }}
|
||||
</h2>
|
||||
</header>
|
||||
{{- if (ne (.Param "hideSummary") true) }}
|
||||
<div class="entry-content">
|
||||
<p>{{ .Summary | plainify | htmlUnescape }}{{ if .Truncated }}...{{ end }}</p>
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- if not (.Param "hideMeta") }}
|
||||
<footer class="entry-footer">
|
||||
{{- partial "post_meta.html" . -}}
|
||||
</footer>
|
||||
{{- end }}
|
||||
<a class="entry-link" aria-label="post link to {{ .Title | plainify }}" href="{{ .Permalink }}"></a>
|
||||
</article>
|
||||
{{- end }}
|
||||
|
||||
{{- if gt $paginator.TotalPages 1 }}
|
||||
<footer class="page-footer">
|
||||
<nav class="pagination">
|
||||
{{- if $paginator.HasPrev }}
|
||||
<a class="prev" href="{{ $paginator.Prev.URL | absURL }}">
|
||||
« {{ i18n "prev_page" }}
|
||||
{{- if (.Param "ShowPageNums") }}
|
||||
{{- sub $paginator.PageNumber 1 }}/{{ $paginator.TotalPages }}
|
||||
{{- end }}
|
||||
</a>
|
||||
{{- end }}
|
||||
{{- if $paginator.HasNext }}
|
||||
<a class="next" href="{{ $paginator.Next.URL | absURL }}">
|
||||
{{- i18n "next_page" }}
|
||||
{{- if (.Param "ShowPageNums") }}
|
||||
{{- add 1 $paginator.PageNumber }}/{{ $paginator.TotalPages }}
|
||||
{{- end }} »
|
||||
</a>
|
||||
{{- end }}
|
||||
</nav>
|
||||
</footer>
|
||||
{{- end }}
|
||||
|
||||
{{- end }}{{/* end profileMode */}}
|
||||
|
||||
{{- end }}{{- /* end main */ -}}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
{{- define "main" }}
|
||||
|
||||
<article class="post-single">
|
||||
<header class="post-header">
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<h1 class="post-title entry-hint-parent">
|
||||
{{ .Title }}
|
||||
{{- if .Draft }}
|
||||
<span class="entry-hint" title="Draft">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="35" viewBox="0 -960 960 960" fill="currentColor">
|
||||
<path
|
||||
d="M160-410v-60h300v60H160Zm0-165v-60h470v60H160Zm0-165v-60h470v60H160Zm360 580v-123l221-220q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q9 9 13 20t4 22q0 11-4.5 22.5T862.09-380L643-160H520Zm300-263-37-37 37 37ZM580-220h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z" />
|
||||
</svg>
|
||||
</span>
|
||||
{{- end }}
|
||||
</h1>
|
||||
{{- if .Description }}
|
||||
<div class="post-description">
|
||||
{{ .Description }}
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- if not (.Param "hideMeta") }}
|
||||
<div class="post-meta">
|
||||
{{- partial "post_meta.html" . -}}
|
||||
{{- partial "post_canonical.html" . -}}
|
||||
</div>
|
||||
{{- end }}
|
||||
</header>
|
||||
{{- $isHidden := (.Param "cover.hiddenInSingle") | default (.Param "cover.hidden") | default false }}
|
||||
{{- partial "cover.html" (dict "cxt" . "IsSingle" true "isHidden" $isHidden) }}
|
||||
{{- if (.Param "ShowToc") }}
|
||||
{{- partial "toc.html" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Content }}
|
||||
<div class="post-content">
|
||||
{{- if not (.Param "disableAnchoredHeadings") }}
|
||||
{{- partial "anchored_headings.html" .Content -}}
|
||||
{{- else }}{{ .Content }}{{ end }}
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
<footer class="post-footer">
|
||||
{{- $tags := .Language.Params.Taxonomies.tag | default "tags" }}
|
||||
<ul class="post-tags">
|
||||
{{- range ($.GetTerms $tags) }}
|
||||
<li><a href="{{ .Permalink }}">{{ .LinkTitle }}</a></li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
|
||||
{{- if ne .Params.disableCoffee true }}
|
||||
{{- partial "buy_me_a_coffee.html" . -}}
|
||||
{{- end }}
|
||||
|
||||
{{- if (.Param "ShowPostNavLinks") }}
|
||||
{{- partial "post_nav_links.html" . }}
|
||||
{{- end }}
|
||||
{{- if (and site.Params.ShowShareButtons (ne .Params.disableShare true)) }}
|
||||
{{- partial "share_icons.html" . -}}
|
||||
{{- end }}
|
||||
|
||||
</footer>
|
||||
|
||||
{{- if (.Param "comments") }}
|
||||
{{- partial "comments.html" . }}
|
||||
{{- end }}
|
||||
</article>
|
||||
|
||||
{{- end }}{{/* end main */}}
|
||||
401
layouts/index.html
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
{{ define "main" }}
|
||||
<div class="wall"></div>
|
||||
|
||||
<!-- Neon sign above monitor -->
|
||||
<div class="neon-sign">
|
||||
<div class="neon-text">ritual.sh</div>
|
||||
</div>
|
||||
|
||||
<!-- Sticky notes -->
|
||||
<div class="sticky-note note1">fix bugs</div>
|
||||
<div class="sticky-note note2">pwd:<br />puppies</div>
|
||||
<div class="sticky-note note3">finish<br />coffee</div>
|
||||
<div class="sticky-note note4">CALL<br />WIFE</div>
|
||||
|
||||
<!-- Papers pinned to wall -->
|
||||
<div class="wall-paper paper1"></div>
|
||||
<div class="wall-paper paper2"></div>
|
||||
|
||||
<!-- X-Files "I want to believe" poster -->
|
||||
<div class="xfiles-poster">
|
||||
<div class="xfiles-content">
|
||||
<div class="ufo-illustration">
|
||||
<div class="ufo-dome"></div>
|
||||
<div class="ufo-body">
|
||||
<div class="ufo-lights">
|
||||
<div class="ufo-light"></div>
|
||||
<div class="ufo-light"></div>
|
||||
<div class="ufo-light"></div>
|
||||
<div class="ufo-light"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="light-beam"></div>
|
||||
</div>
|
||||
<div class="believe-text">I WANT TO<br />BELIEVE</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Poster on wall -->
|
||||
<div class="poster">
|
||||
<div class="poster-image" id="posterImage">
|
||||
<script src="/js/nowplaying.js"></script>
|
||||
|
||||
<div class="nowplayingcard">
|
||||
<div class="nowplayingcontainer-inner">
|
||||
<img id="trackart" src="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="now-playing-note">Recently Played</div>
|
||||
<div class="now-playing-artist">
|
||||
<div class="trackInfo">
|
||||
<span id="artist"></span>
|
||||
<a id="tracktitle" style="display: none"></a>
|
||||
<a id="album" style="display: none"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
setInterval(
|
||||
getLastTrack("ritualplays", "3a4fef48fecc593d25e0f9a40df1fefe"),
|
||||
10 * 1000,
|
||||
);
|
||||
</script>
|
||||
|
||||
<!-- Desk -->
|
||||
<div class="desk"></div>
|
||||
|
||||
<!-- Curved cables on desk using SVG -->
|
||||
<svg
|
||||
class="cable-svg"
|
||||
style="position: absolute; bottom: 8%; left: 15%; width: 200px; height: 150px"
|
||||
>
|
||||
<path
|
||||
d="M 20 10 Q 40 60, 80 120"
|
||||
stroke="#222"
|
||||
stroke-width="3"
|
||||
fill="none"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
class="cable-svg"
|
||||
style="
|
||||
position: absolute;
|
||||
bottom: 8%;
|
||||
right: 20%;
|
||||
width: 180px;
|
||||
height: 140px;
|
||||
"
|
||||
>
|
||||
<path
|
||||
d="M 150 20 Q 100 70, 40 130"
|
||||
stroke="#1a1a1a"
|
||||
stroke-width="3"
|
||||
fill="none"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
class="cable-svg"
|
||||
style="position: absolute; bottom: 8%; left: 28%; width: 220px; height: 160px"
|
||||
>
|
||||
<path
|
||||
d="M 10 30 Q 80 40, 160 140"
|
||||
stroke="#252525"
|
||||
stroke-width="2.5"
|
||||
fill="none"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
class="cable-svg"
|
||||
style="
|
||||
position: absolute;
|
||||
bottom: 8%;
|
||||
right: 35%;
|
||||
width: 150px;
|
||||
height: 120px;
|
||||
"
|
||||
>
|
||||
<path
|
||||
d="M 130 15 Q 70 50, 20 110"
|
||||
stroke="#2a2a2a"
|
||||
stroke-width="2.5"
|
||||
fill="none"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
class="cable-svg"
|
||||
style="position: absolute; bottom: 8%; left: 42%; width: 160px; height: 130px"
|
||||
>
|
||||
<path
|
||||
d="M 30 20 Q 60 80, 120 125"
|
||||
stroke="#1f1f1f"
|
||||
stroke-width="2"
|
||||
fill="none"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<div class="monitor-stand-small"></div>
|
||||
|
||||
<!-- Desk monitor -->
|
||||
<div class="secondary-screen desk-monitor">
|
||||
<div class="screen-display large crt">
|
||||
SYSTEM LOAD<br />
|
||||
CPU: 67%<br />
|
||||
RAM: 4.2/8GB<br />
|
||||
NET: 2.4MB/s<br />
|
||||
DISK: 89%<br />
|
||||
<span class="cursor-blink">_</span>
|
||||
</div>
|
||||
<div class="monitor-stand-small"></div>
|
||||
</div>
|
||||
|
||||
<!-- Desk clutter -->
|
||||
<div class="desk-item keyboard"></div>
|
||||
<div class="desk-item mouse"></div>
|
||||
<div class="desk-item coffee-mug"></div>
|
||||
|
||||
<!-- VU Meter on desk -->
|
||||
<div class="vu-meter">
|
||||
<div class="vu-meter-body">
|
||||
<div class="vu-meter-screen">
|
||||
<div class="vu-bars crt">
|
||||
<div class="vu-bar" style="--delay: 0s; --height: 45%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.1s; --height: 65%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.2s; --height: 80%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.3s; --height: 55%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.4s; --height: 90%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.5s; --height: 70%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.6s; --height: 85%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.7s; --height: 60%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.8s; --height: 75%"></div>
|
||||
<div class="vu-bar" style="--delay: 0.9s; --height: 50%"></div>
|
||||
<div class="vu-bar" style="--delay: 1s; --height: 65%"></div>
|
||||
<div class="vu-bar" style="--delay: 1.1s; --height: 40%"></div>
|
||||
<div class="vu-bar" style="--delay: 1.2s; --height: 55%"></div>
|
||||
<div class="vu-bar" style="--delay: 1.3s; --height: 70%"></div>
|
||||
<div class="vu-bar" style="--delay: 1.4s; --height: 45%"></div>
|
||||
<div class="vu-bar" style="--delay: 1.5s; --height: 35%"></div>
|
||||
</div>
|
||||
<!-- Peak indicator line -->
|
||||
<div class="vu-peak-line"></div>
|
||||
</div>
|
||||
<!-- VU Meter LEDs -->
|
||||
<div class="vu-leds">
|
||||
<div class="vu-led green"></div>
|
||||
<div class="vu-led green"></div>
|
||||
<div class="vu-led yellow"></div>
|
||||
<div class="vu-led red"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- iPod group - container keeps all elements positioned relative to each other -->
|
||||
<div class="ipod-group">
|
||||
<div class="ipod">
|
||||
<div class="ipod-wheel"></div>
|
||||
</div>
|
||||
|
||||
<!-- Earbud cables within the group container -->
|
||||
<svg class="ipod-cables" viewBox="0 0 150 100" style="overflow: visible">
|
||||
<defs>
|
||||
<linearGradient id="cableGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color: #6b4fb3" />
|
||||
<stop offset="100%" style="stop-color: #4169e1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- Main cable: plugs in at top RIGHT of iPod, makes a big loop to the LEFT, then hangs down -->
|
||||
<!-- Start at x=85 (top right), arc way left to x=30, then come back down on the left side -->
|
||||
<path
|
||||
d="M 85,3 C 85,-12 75,-22 55,-22 C 35,-22 25,-15 25,0 C 25,15 28,35 32,50 L 35,65"
|
||||
stroke="url(#cableGradient)"
|
||||
stroke-width="2.5"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
<!-- Left branch to left earbud -->
|
||||
<path
|
||||
d="M 35,65 C 28,72 20,82 5,88"
|
||||
stroke="url(#cableGradient)"
|
||||
stroke-width="1.8"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
<!-- Right branch to right earbud -->
|
||||
<path
|
||||
d="M 35,65 C 55,73 95,82 125,83"
|
||||
stroke="url(#cableGradient)"
|
||||
stroke-width="1.8"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<div class="earbud earbud-left"></div>
|
||||
<div class="earbud earbud-right"></div>
|
||||
</div>
|
||||
|
||||
<!-- Widgets and gadgets -->
|
||||
<div class="widget router"></div>
|
||||
<div class="widget hard-drive"></div>
|
||||
|
||||
{{ partial "lavalamp.html" . }}
|
||||
|
||||
<!-- CRT Monitor -->
|
||||
<div class="crt-container">
|
||||
<div class="crt-monitor">
|
||||
<div class="crt-screen">
|
||||
<div class="content crt">
|
||||
<div id="terminal">
|
||||
<div id="output"></div>
|
||||
<div id="input-container" class="input-line hidden">
|
||||
<span class="prompt">></span>
|
||||
<input
|
||||
type="text"
|
||||
id="input"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="monitor-stand">
|
||||
<div class="stand-neck"></div>
|
||||
<div class="stand-base"></div>
|
||||
</div>
|
||||
|
||||
<!-- Wall-mounted monitors -->
|
||||
<div class="secondary-screen wall-monitor-1">
|
||||
<div class="screen-display crt">
|
||||
> netstat -an<br />
|
||||
<pre>
|
||||
tcp 0 0 127.0.0.1:33842 0.0.0.0:* LISTEN
|
||||
tcp 0 0 127.0.0.1:41267 0.0.0.0:* LISTEN
|
||||
tcp 0 0 127.0.0.54:53 0.0.0.0:* LISTEN
|
||||
tcp 0 0 127.0.0.1:52918 127.0.0.1:38471 ESTABLISHED
|
||||
tcp 0 0 192.168.1.147:44321 52.143.67.201:443 ESTABLISHED
|
||||
tcp 0 0 192.168.1.147:39854 104.26.15.88:80 TIME_WAIT
|
||||
tcp 0 0 127.0.0.1:38471 127.0.0.1:52918 ESTABLISHED
|
||||
tcp 0 0 127.0.0.1:56732 127.0.0.1:8080 ESTABLISHED
|
||||
tcp 0 0 192.168.1.147:41209 13.107.42.16:443 ESTABLISHED
|
||||
tcp 0 0 127.0.0.1:49563 127.0.0.1:8080 TIME_WAIT
|
||||
|
||||
Proto RefCnt Flags Type State I-Node Path
|
||||
unix 3 [ ] STREAM CONNECTED 50896 /run/user/1000/bus
|
||||
</pre
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="secondary-screen wall-monitor-2">
|
||||
<div class="screen-display tiny cyan crt">
|
||||
<div class="scroll-text">
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
[PKT] 172.16.0.1:22<br />
|
||||
[PKT] 192.168.1.1:443<br />
|
||||
[PKT] 10.0.0.15:8080<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="secondary-screen wall-monitor-3">
|
||||
<div class="screen-display crt">
|
||||
PING 8.8.8.8<br />
|
||||
64 bytes: 12ms<br />
|
||||
64 bytes: 11ms<br />
|
||||
64 bytes: 13ms<br />
|
||||
<span class="cursor-blink">_</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="secondary-screen wall-monitor-4">
|
||||
<div class="screen-display tiny amber crt">
|
||||
> tail -f /var/log<br />
|
||||
[INFO] Process OK<br />
|
||||
[WARN] High load detected - time for coffee break<br />
|
||||
[INFO] Connected to database (it's in a relationship now)<br />
|
||||
[ERROR] 404: Motivation not found<br />
|
||||
[WARN] Firewall detected actual fire, calling emergency services<br />
|
||||
[INFO] Successfully hacked into mainframe (jk it's just localhost)<br />
|
||||
[ERROR] Keyboard not found. Press F1 to continue.<br />
|
||||
[WARN] Too many open tabs. Browser having existential crisis.<br />
|
||||
[INFO] Ping 127.0.0.1 - there's no place like home<br />
|
||||
[ERROR] SQL injection attempt detected. Nice try, Bobby Tables.<br />
|
||||
<span class="cursor-blink">_</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<div class="buy-me-a-coffee">
|
||||
If you found this article useful, consider <a href="https://ko-fi.com/ritual" target="_blank">buying me a coffee</a>. Every tip received makes my electricity bill seem less bad.
|
||||
</div>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<script src="https://utteranc.es/client.js"
|
||||
repo="unbolt/ritual.sh-comments"
|
||||
issue-term="pathname"
|
||||
theme="photon-dark"
|
||||
crossorigin="anonymous"
|
||||
async>
|
||||
</script>
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
{{- if not (.Param "hideFooter") }}
|
||||
<footer class="footer">
|
||||
{{- if site.Copyright }}
|
||||
<span>{{ site.Copyright | markdownify }}</span>
|
||||
{{- else }}
|
||||
<span>© {{ now.Year }} <a href="{{ "" | absLangURL }}">Dan Baker</a></span>
|
||||
{{- end }}
|
||||
</footer>
|
||||
{{- end }}
|
||||
|
||||
{{- if (not site.Params.disableScrollToTop) }}
|
||||
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
|
||||
<path d="M12 6H0l6-6z" />
|
||||
</svg>
|
||||
</a>
|
||||
{{- end }}
|
||||
|
||||
{{- partial "extend_footer.html" . }}
|
||||
|
||||
<script>
|
||||
let menu = document.getElementById('menu')
|
||||
if (menu) {
|
||||
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
|
||||
menu.onscroll = function () {
|
||||
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener("click", function (e) {
|
||||
e.preventDefault();
|
||||
var id = this.getAttribute("href").substr(1);
|
||||
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||||
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
|
||||
behavior: "smooth"
|
||||
});
|
||||
} else {
|
||||
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
|
||||
}
|
||||
if (id === "top") {
|
||||
history.replaceState(null, null, " ");
|
||||
} else {
|
||||
history.pushState(null, null, `#${id}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{{- if (not site.Params.disableScrollToTop) }}
|
||||
<script>
|
||||
var mybutton = document.getElementById("top-link");
|
||||
window.onscroll = function () {
|
||||
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
|
||||
mybutton.style.visibility = "visible";
|
||||
mybutton.style.opacity = "1";
|
||||
} else {
|
||||
mybutton.style.visibility = "hidden";
|
||||
mybutton.style.opacity = "0";
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
{{- end }}
|
||||
|
||||
{{- if (not site.Params.disableThemeToggle) }}
|
||||
<script>
|
||||
document.getElementById("theme-toggle").addEventListener("click", () => {
|
||||
if (document.body.className.includes("dark")) {
|
||||
document.body.classList.remove('dark');
|
||||
localStorage.setItem("pref-theme", 'light');
|
||||
} else {
|
||||
document.body.classList.add('dark');
|
||||
localStorage.setItem("pref-theme", 'dark');
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
{{- end }}
|
||||
|
||||
{{- if (and (eq .Kind "page") (ne .Layout "archives") (ne .Layout "search") (.Param "ShowCodeCopyButtons")) }}
|
||||
<script>
|
||||
document.querySelectorAll('pre > code').forEach((codeblock) => {
|
||||
const container = codeblock.parentNode.parentNode;
|
||||
|
||||
const copybutton = document.createElement('button');
|
||||
copybutton.classList.add('copy-code');
|
||||
copybutton.innerHTML = '{{- i18n "code_copy" | default "copy" }}';
|
||||
|
||||
function copyingDone() {
|
||||
copybutton.innerHTML = '{{- i18n "code_copied" | default "copied!" }}';
|
||||
setTimeout(() => {
|
||||
copybutton.innerHTML = '{{- i18n "code_copy" | default "copy" }}';
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
copybutton.addEventListener('click', (cb) => {
|
||||
if ('clipboard' in navigator) {
|
||||
navigator.clipboard.writeText(codeblock.textContent);
|
||||
copyingDone();
|
||||
return;
|
||||
}
|
||||
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(codeblock);
|
||||
const selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
copyingDone();
|
||||
} catch (e) { };
|
||||
selection.removeRange(range);
|
||||
});
|
||||
|
||||
if (container.classList.contains("highlight")) {
|
||||
container.appendChild(copybutton);
|
||||
} else if (container.parentNode.firstChild == container) {
|
||||
// td containing LineNos
|
||||
} else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
|
||||
// table containing LineNos and code
|
||||
codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
|
||||
} else {
|
||||
// code blocks not having highlight as parent class
|
||||
codeblock.parentNode.appendChild(copybutton);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{{- end }}
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
{{- if hugo.IsProduction | or (eq site.Params.env "production") | and (ne .Params.robotsNoIndex true) }}
|
||||
<meta name="robots" content="index, follow">
|
||||
{{- else }}
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
{{- end }}
|
||||
|
||||
{{- /* Title */}}
|
||||
<title>{{ if .IsHome }}{{ else }}{{ if .Title }}{{ .Title }} | {{ end }}{{ end }}{{ site.Title }}</title>
|
||||
|
||||
{{- /* Meta */}}
|
||||
{{- if .IsHome }}
|
||||
{{ with site.Params.keywords -}}<meta name="keywords" content="{{- range $i, $e := . }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}">{{ end }}
|
||||
{{- else }}
|
||||
<meta name="keywords" content="{{ if .Params.keywords -}}
|
||||
{{- range $i, $e := .Params.keywords }}{{ if $i }}, {{ end }}{{ $e }}{{ end }} {{- else }}
|
||||
{{- range $i, $e := .Params.tags }}{{ if $i }}, {{ end }}{{ $e }}{{ end }} {{- end -}}">
|
||||
{{- end }}
|
||||
<meta name="description" content="{{- with .Description }}{{ . }}{{- else }}{{- if or .IsPage .IsSection}}
|
||||
{{- .Summary | default (printf "%s - %s" .Title site.Title) }}{{- else }}
|
||||
{{- with site.Params.description }}{{ . }}{{- end }}{{- end }}{{- end -}}">
|
||||
<meta name="author" content="{{ (partial "author.html" . ) }}">
|
||||
<link rel="canonical" href="{{ if .Params.canonicalURL -}} {{ trim .Params.canonicalURL " " }} {{- else -}} {{ .Permalink }} {{- end }}">
|
||||
{{- if site.Params.analytics.google.SiteVerificationTag }}
|
||||
<meta name="google-site-verification" content="{{ site.Params.analytics.google.SiteVerificationTag }}">
|
||||
{{- end }}
|
||||
{{- if site.Params.analytics.yandex.SiteVerificationTag }}
|
||||
<meta name="yandex-verification" content="{{ site.Params.analytics.yandex.SiteVerificationTag }}">
|
||||
{{- end }}
|
||||
{{- if site.Params.analytics.bing.SiteVerificationTag }}
|
||||
<meta name="msvalidate.01" content="{{ site.Params.analytics.bing.SiteVerificationTag }}">
|
||||
{{- end }}
|
||||
{{- if site.Params.analytics.naver.SiteVerificationTag }}
|
||||
<meta name="naver-site-verification" content="{{ site.Params.analytics.naver.SiteVerificationTag }}">
|
||||
{{- end }}
|
||||
|
||||
{{- /* Styles */}}
|
||||
|
||||
{{- /* includes */}}
|
||||
{{- $includes := slice }}
|
||||
{{- $includes = $includes | append (" " | resources.FromString "assets/css/includes-blank.css")}}
|
||||
|
||||
{{- if not (eq site.Params.assets.disableScrollBarStyle true) }}
|
||||
{{- $ScrollStyle := (resources.Get "css/includes/scroll-bar.css") }}
|
||||
{{- $includes = (append $ScrollStyle $includes) }}
|
||||
{{- end }}
|
||||
|
||||
{{- $includes_all := $includes | resources.Concat "assets/css/includes.css" }}
|
||||
|
||||
{{- $theme_vars := (resources.Get "css/core/theme-vars.css") }}
|
||||
{{- $reset := (resources.Get "css/core/reset.css") }}
|
||||
{{- $media := (resources.Get "css/core/zmedia.css") }}
|
||||
{{- $license_css := (resources.Get "css/core/license.css") }}
|
||||
{{- $common := (resources.Match "css/common/*.css") | resources.Concat "assets/css/common.css" }}
|
||||
|
||||
{{- /* markup.highlight.noClasses should be set to `false` */}}
|
||||
{{- $chroma_styles := (resources.Get "css/includes/chroma-styles.css") }}
|
||||
{{- $chroma_mod := (resources.Get "css/includes/chroma-mod.css") }}
|
||||
|
||||
{{- /* order is important */}}
|
||||
{{- $core := (slice $theme_vars $reset $common $chroma_styles $chroma_mod $includes_all $media) | resources.Concat "assets/css/core.css" | resources.Minify }}
|
||||
{{- $extended := (resources.Match "css/extended/*.css") | resources.Concat "assets/css/extended.css" | resources.Minify }}
|
||||
|
||||
{{- /* bundle all required css */}}
|
||||
{{- /* Add extended css after theme style */ -}}
|
||||
{{- $stylesheet := (slice $license_css $core $extended) | resources.Concat "assets/css/stylesheet.css" }}
|
||||
|
||||
{{- if not site.Params.assets.disableFingerprinting }}
|
||||
{{- $stylesheet := $stylesheet | fingerprint }}
|
||||
<link crossorigin="anonymous" href="{{ $stylesheet.RelPermalink }}" integrity="{{ $stylesheet.Data.Integrity }}" rel="preload stylesheet" as="style">
|
||||
{{- else }}
|
||||
<link crossorigin="anonymous" href="{{ $stylesheet.RelPermalink }}" rel="preload stylesheet" as="style">
|
||||
{{- end }}
|
||||
|
||||
{{- /* Search */}}
|
||||
{{- if (eq .Layout `search`) -}}
|
||||
<link crossorigin="anonymous" rel="preload" as="fetch" href="../index.json">
|
||||
{{- $fastsearch := resources.Get "js/fastsearch.js" | js.Build (dict "params" (dict "fuseOpts" site.Params.fuseOpts)) | resources.Minify }}
|
||||
{{- $fusejs := resources.Get "js/fuse.basic.min.js" }}
|
||||
{{- $license_js := resources.Get "js/license.js" }}
|
||||
{{- if not site.Params.assets.disableFingerprinting }}
|
||||
{{- $search := (slice $fusejs $license_js $fastsearch ) | resources.Concat "assets/js/search.js" | fingerprint }}
|
||||
<script defer crossorigin="anonymous" src="{{ $search.RelPermalink }}" integrity="{{ $search.Data.Integrity }}"></script>
|
||||
{{- else }}
|
||||
{{- $search := (slice $fusejs $fastsearch ) | resources.Concat "assets/js/search.js" }}
|
||||
<script defer crossorigin="anonymous" src="{{ $search.RelPermalink }}"></script>
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{- /* Favicons */}}
|
||||
<link rel="icon" href="{{ site.Params.assets.favicon | default "favicon.ico" | absURL }}">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ site.Params.assets.favicon16x16 | default "favicon-16x16.png" | absURL }}">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ site.Params.assets.favicon32x32 | default "favicon-32x32.png" | absURL }}">
|
||||
<link rel="apple-touch-icon" href="{{ site.Params.assets.apple_touch_icon | default "apple-touch-icon.png" | absURL }}">
|
||||
<link rel="mask-icon" href="{{ site.Params.assets.safari_pinned_tab | default "safari-pinned-tab.svg" | absURL }}">
|
||||
<meta name="theme-color" content="{{ site.Params.assets.theme_color | default "#2e2e33" }}">
|
||||
<meta name="msapplication-TileColor" content="{{ site.Params.assets.msapplication_TileColor | default "#2e2e33" }}">
|
||||
|
||||
{{- /* RSS */}}
|
||||
{{ range .AlternativeOutputFormats -}}
|
||||
<link rel="{{ .Rel }}" type="{{ .MediaType.Type | html }}" href="{{ .Permalink | safeURL }}">
|
||||
{{ end -}}
|
||||
{{- range .AllTranslations -}}
|
||||
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}">
|
||||
{{ end -}}
|
||||
|
||||
<noscript>
|
||||
<style>
|
||||
#theme-toggle,
|
||||
.top-link {
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
{{- if (and (ne site.Params.defaultTheme "light") (ne site.Params.defaultTheme "dark")) }}
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme: rgb(29, 30, 32);
|
||||
--entry: rgb(46, 46, 51);
|
||||
--primary: rgb(218, 218, 219);
|
||||
--secondary: rgb(155, 156, 157);
|
||||
--tertiary: rgb(65, 66, 68);
|
||||
--content: rgb(196, 196, 197);
|
||||
--code-block-bg: rgb(46, 46, 51);
|
||||
--code-bg: rgb(55, 56, 62);
|
||||
--border: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.list {
|
||||
background: var(--theme);
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-track {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.list:not(.dark)::-webkit-scrollbar-thumb {
|
||||
border-color: var(--theme);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
{{- end }}
|
||||
</noscript>
|
||||
|
||||
{{- partial "extend_head.html" . -}}
|
||||
|
||||
{{- /* Misc */}}
|
||||
{{- if hugo.IsProduction | or (eq site.Params.env "production") }}
|
||||
{{- template "_internal/google_analytics.html" . }}
|
||||
{{- template "partials/templates/opengraph.html" . }}
|
||||
{{- template "partials/templates/twitter_cards.html" . }}
|
||||
{{- template "partials/templates/schema_json.html" . }}
|
||||
{{- end -}}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
{{- /* theme-toggle is enabled */}}
|
||||
{{- if (not site.Params.disableThemeToggle) }}
|
||||
{{- /* theme is light */}}
|
||||
{{- if (eq site.Params.defaultTheme "light") }}
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
{{- /* theme is dark */}}
|
||||
{{- else if (eq site.Params.defaultTheme "dark") }}
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
}
|
||||
|
||||
</script>
|
||||
{{- else }}
|
||||
{{- /* theme is auto */}}
|
||||
<script>
|
||||
if (localStorage.getItem("pref-theme") === "dark") {
|
||||
document.body.classList.add('dark');
|
||||
} else if (localStorage.getItem("pref-theme") === "light") {
|
||||
document.body.classList.remove('dark')
|
||||
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
{{- end }}
|
||||
{{- /* theme-toggle is disabled and theme is auto */}}
|
||||
{{- else if (and (ne site.Params.defaultTheme "light") (ne site.Params.defaultTheme "dark"))}}
|
||||
<script>
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
|
||||
</script>
|
||||
{{- end }}
|
||||
|
||||
<header class="header">
|
||||
<nav class="nav">
|
||||
<div class="logo">
|
||||
{{- $label_text := (site.Params.label.text | default site.Title) }}
|
||||
{{- if site.Title }}
|
||||
<a href="{{ "" | absLangURL }}" accesskey="h" title="{{ $label_text }} (Alt + H)">
|
||||
{{- if site.Params.label.icon }}
|
||||
{{- $img := resources.Get site.Params.label.icon }}
|
||||
{{- if $img }}
|
||||
{{- $processableFormats := (slice "jpg" "jpeg" "png" "tif" "bmp" "gif") -}}
|
||||
{{- if hugo.IsExtended -}}
|
||||
{{- $processableFormats = $processableFormats | append "webp" -}}
|
||||
{{- end -}}
|
||||
{{- $prod := (hugo.IsProduction | or (eq site.Params.env "production")) }}
|
||||
{{- if and (in $processableFormats $img.MediaType.SubType) (eq $prod true)}}
|
||||
{{- if site.Params.label.iconHeight }}
|
||||
{{- $img = $img.Resize (printf "x%d" site.Params.label.iconHeight) }}
|
||||
{{ else }}
|
||||
{{- $img = $img.Resize "x30" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
<img src="{{ $img.Permalink }}" alt="" aria-label="logo"
|
||||
height="{{- site.Params.label.iconImageHeight | default "30" -}}">
|
||||
{{- else }}
|
||||
<img src="{{- site.Params.label.icon | absURL -}}" alt="" aria-label="logo"
|
||||
height="{{- site.Params.label.iconHeight | default "30" -}}">
|
||||
{{- end -}}
|
||||
{{- else if hasPrefix site.Params.label.iconSVG "<svg" }}
|
||||
{{ site.Params.label.iconSVG | safeHTML }}
|
||||
{{- end -}}
|
||||
{{- $label_text -}}
|
||||
</a>
|
||||
{{- end }}
|
||||
<div class="logo-switches">
|
||||
{{- if (not site.Params.disableThemeToggle) }}
|
||||
<button id="theme-toggle" accesskey="t" title="(Alt + T)">
|
||||
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||||
</svg>
|
||||
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
|
||||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="5"></circle>
|
||||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||||
</svg>
|
||||
</button>
|
||||
{{- end }}
|
||||
|
||||
{{- $lang := .Lang}}
|
||||
{{- $separator := or $label_text (not site.Params.disableThemeToggle)}}
|
||||
{{- with site.Home.AllTranslations }}
|
||||
<ul class="lang-switch">
|
||||
{{- if $separator }}<li>|</li>{{ end }}
|
||||
{{- range . -}}
|
||||
{{- if ne $lang .Lang }}
|
||||
<li>
|
||||
<a href="{{- .Permalink -}}" title="{{ .Language.Params.languageAltTitle | default (.Language.LanguageName | emojify) | default (.Lang | title) }}"
|
||||
aria-label="{{ .Language.LanguageName | default (.Lang | title) }}">
|
||||
{{- if (and site.Params.displayFullLangName (.Language.LanguageName)) }}
|
||||
{{- .Language.LanguageName | emojify -}}
|
||||
{{- else }}
|
||||
{{- .Lang | title -}}
|
||||
{{- end -}}
|
||||
</a>
|
||||
</li>
|
||||
{{- end -}}
|
||||
{{- end}}
|
||||
</ul>
|
||||
{{- end }}
|
||||
</div>
|
||||
</div>
|
||||
{{- $currentPage := . }}
|
||||
<ul id="menu">
|
||||
{{- range site.Menus.main }}
|
||||
{{- $menu_item_url := (cond (strings.HasSuffix .URL "/") .URL (printf "%s/" .URL) ) | absLangURL }}
|
||||
{{- $page_url:= $currentPage.Permalink | absLangURL }}
|
||||
{{- $is_search := eq (site.GetPage .KeyName).Layout `search` }}
|
||||
<li>
|
||||
<a href="{{ .URL | absLangURL }}" title="{{ .Title | default .Name }} {{- cond $is_search (" (Alt + /)" | safeHTMLAttr) ("" | safeHTMLAttr ) }}"
|
||||
{{- cond $is_search (" accesskey=/" | safeHTMLAttr) ("" | safeHTMLAttr ) }}>
|
||||
<span {{- if eq $menu_item_url $page_url }} class="active" {{- end }}>
|
||||
{{- .Pre }}
|
||||
{{- .Name -}}
|
||||
{{ .Post -}}
|
||||
</span>
|
||||
{{- if (findRE "://" .URL) }}
|
||||
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="12" width="12">
|
||||
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
|
||||
<path d="M15 3h6v6"></path>
|
||||
<path d="M10 14L21 3"></path>
|
||||
</svg>
|
||||
{{- end }}
|
||||
</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
{{- with site.Params.homeInfoParams }}
|
||||
<article class="first-entry home-info">
|
||||
<header class="entry-header">
|
||||
<h1>{{ .Title | markdownify }}</h1>
|
||||
</header>
|
||||
|
||||
<div class="entry-content">
|
||||
|
||||
<div class="row">
|
||||
<div class="col photo">
|
||||
{{- $me := resources.Get "/images/me.webp" }}
|
||||
<img src="{{ $me.Permalink }}">
|
||||
</div>
|
||||
<div class="col intro-text">
|
||||
{{ .Content | markdownify }}
|
||||
|
||||
<div class="entry-content">
|
||||
{{- partial "nowplaying.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<footer class="entry-footer">
|
||||
{{ partial "social_icons.html" (dict "align" site.Params.homeInfoParams.AlignSocialIconsTo) }}
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
{{- end -}}
|
||||
25
layouts/partials/lavalamp.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<div class="container">
|
||||
<svg style="position: absolute; width: 0; height: 0">
|
||||
<defs>
|
||||
<filter id="goo">
|
||||
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
|
||||
<feColorMatrix
|
||||
in="blur"
|
||||
mode="matrix"
|
||||
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9"
|
||||
result="goo"
|
||||
/>
|
||||
<feComposite in="SourceGraphic" in2="goo" operator="atop" />
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<a href="/about/">
|
||||
<div class="lava-lamp-container">
|
||||
<div class="lamp-cap"></div>
|
||||
<div class="lava-lamp" id="lavaLamp">
|
||||
<div class="lamp-text">ABOUT</div>
|
||||
</div>
|
||||
<div class="lamp-base"></div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
<div class="nowplayingcard">
|
||||
<div class="nowplayingcontainer-inner">
|
||||
<div class="trackInfo">
|
||||
<p><strong>Recently listening to:</strong></p>
|
||||
🎵 <span id="artist"></span> - <a id="tracktitle"></a>
|
||||
<a id="album"></a>
|
||||
</div>
|
||||
|
|
|
|||
0
layouts/partials/terminal.html
Normal file
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 20 KiB |
|
|
@ -1,28 +0,0 @@
|
|||
.nowplayingcard {
|
||||
margin: auto;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.nowplayingcontainer-inner {
|
||||
transition: 0.3s;
|
||||
display: inline-flex;
|
||||
|
||||
.trackInfo {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#album {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
img#trackart {
|
||||
transition: 0.3s;
|
||||
width: 60px;
|
||||
height: 50px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
img#trackart[src=""] {
|
||||
display: none;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
static/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
3
static/favicon.svg
Normal file
|
After Width: | Height: | Size: 251 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
21
static/site.webmanifest
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "ritual.sh",
|
||||
"short_name": "ritual.sh",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/web-app-manifest-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/web-app-manifest-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
BIN
static/web-app-manifest-192x192.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
static/web-app-manifest-512x512.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 66904cc4c2b292e6a3686d483e4054904a9f3954
|
||||
1
themes/hugo-starter
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit d876912bf596a5257b3c3fab674a0ff6bf544c5b
|
||||