diff --git a/public/scripts/index.js b/public/scripts/index.js
index d8cdc30..e176442 100644
--- a/public/scripts/index.js
+++ b/public/scripts/index.js
@@ -1,126 +1,194 @@
-const TERMINAL_PROMPT = "barrett@ruth:~$ ";
-let typing = false;
-let clearing = false;
+(() => {
+ if (window.__BT_INDEX_INIT) return;
+ window.__BT_INDEX_INIT = true;
-function clearPrompt(delay, callback) {
- if (clearing) return;
- clearing = true;
+ const TERMINAL_PROMPT = "barrett@ruth:~$ ";
+ let typing = false;
+ let clearing = false;
- const terminalPrompt = document.querySelector(".terminal-prompt");
- if (!terminalPrompt) {
- clearing = false;
- return;
+ function promptEl() {
+ return document.querySelector(".terminal-prompt");
}
- const topicLength =
- terminalPrompt.innerHTML.length - TERMINAL_PROMPT.length;
- let i = 0;
+ (function restorePrompt() {
+ const saved = sessionStorage.getItem("terminalPromptText");
+ const el = promptEl();
+ if (saved && el) el.textContent = saved;
+ sessionStorage.removeItem("terminalPromptText");
+ })();
- function removeChar() {
- if (i++ < topicLength) {
- terminalPrompt.textContent = terminalPrompt.textContent.slice(0, -1);
- setTimeout(removeChar, delay / topicLength);
- } else {
- i = 0;
+ function clearPrompt(delay, callback) {
+ if (clearing) return;
+ clearing = true;
+ const el = promptEl();
+ if (!el) {
clearing = false;
- callback && callback();
+ return;
}
- }
-
- removeChar();
-}
-
-function typechars(e) {
- e.preventDefault();
-
- const topicElement = e.target;
- if (topicElement.classList.contains("active")) return;
- if (typing) return;
- typing = true;
-
- const topic = topicElement.dataset.topic;
- const terminalText = ` /${topic.toLowerCase()}`;
- const terminalPrompt = document.querySelector(".terminal-prompt");
- const delay =
- terminalPrompt.innerHTML.length > TERMINAL_PROMPT.length ? 250 : 500;
-
- const topics = document.querySelectorAll(".topic a");
- topics.forEach((t) => {
- t.classList.remove("active");
- t.style.color = "";
- });
-
- topicElement.classList.add("active");
- topicElement.style.color = getTopicColor(topic);
-
- clearPrompt(delay, () => {
+ const excess = el.textContent.length - TERMINAL_PROMPT.length;
let i = 0;
- function typechar() {
- if (i < terminalText.length) {
- terminalPrompt.innerHTML += terminalText.charAt(i++);
- setTimeout(typechar, delay / terminalText.length);
+ function tick() {
+ if (i++ < excess) {
+ el.textContent = el.textContent.slice(0, -1);
+ setTimeout(tick, delay / Math.max(excess, 1));
} else {
- renderPosts(topic);
- typing = false;
+ clearing = false;
+ callback && callback();
}
}
- typechar();
- });
-}
-
-function renderPosts(topic) {
- const posts = document.getElementById("posts");
- posts.innerHTML = "";
-
- const categoryPosts = postsByCategory[topic];
-
- if (!categoryPosts) {
- return;
+ tick();
}
- categoryPosts.forEach((post) => {
- const postDiv = document.createElement("div");
- postDiv.classList.add("post");
-
- const link = document.createElement("a");
- const slug = post.id
- .split("/")
- .pop()
- .replace(/\.mdx?$/, "");
-
- link.href = `/posts/${topic}/${slug}.html`;
- link.textContent = post.data.title;
- link.style.textDecoration = "underline";
-
- postDiv.appendChild(link);
- posts.appendChild(postDiv);
- });
-}
-
-document.addEventListener("DOMContentLoaded", function () {
- const topics = document.querySelectorAll(".topic a");
-
- topics.forEach((topic) => {
- topic.addEventListener("click", typechars);
-
- const topicName = topic.dataset.topic;
-
- topic.addEventListener("mouseenter", () => {
- const color = window.getTopicColor(topicName);
- topic.style.color = color;
- });
-
- topic.addEventListener("mouseleave", () => {
- if (!topic.classList.contains("active")) {
- topic.style.color = "";
+ function typeTerminalPath(topic, delay, callback) {
+ if (typing) return;
+ typing = true;
+ const el = promptEl();
+ if (!el) return;
+ const txt = ` /${topic}`;
+ clearPrompt(delay, () => {
+ let i = 0;
+ function step() {
+ if (i < txt.length) {
+ el.textContent += txt.charAt(i++);
+ setTimeout(step, delay / txt.length);
+ } else {
+ typing = false;
+ callback && callback();
+ }
}
+ step();
+ });
+ }
+
+ function persistPrompt() {
+ const el = promptEl();
+ if (el) sessionStorage.setItem("terminalPromptText", el.textContent);
+ }
+
+ function renderPosts(topic) {
+ if (!window.postsByCategory) return;
+ const posts = document.getElementById("posts");
+ if (!posts) return;
+ posts.innerHTML = "";
+ const arr = window.postsByCategory[topic];
+ if (!arr) return;
+ for (const post of arr) {
+ const div = document.createElement("div");
+ div.className = "post";
+ const a = document.createElement("a");
+ const slug = post.id.split("/").pop().replace(/\.mdx?$/, "");
+ a.href = `/posts/${topic}/${slug}.html`;
+ a.textContent = post.data.title;
+ a.style.textDecoration = "underline";
+ div.appendChild(a);
+ posts.appendChild(div);
+ }
+ }
+
+ function handleDataTopicClick(e) {
+ const link = e.target.closest("[data-topic]");
+ if (!link) return;
+ e.preventDefault();
+ if (typing) return;
+
+ const topic = link.dataset.topic.toLowerCase();
+ const href = link.getAttribute("href") || "/";
+ const delay = 500;
+ const path = window.location.pathname;
+
+ const colorFn = window.getTopicColor || (() => "");
+ const topics = document.querySelectorAll("[data-topic]");
+ topics.forEach((t) => {
+ t.classList.remove("active");
+ t.style.color = "";
+ });
+ link.classList.add("active");
+ const c = colorFn(topic);
+ if (c) link.style.color = c;
+
+ typeTerminalPath(topic, delay, () => {
+ persistPrompt();
+
+ if (path === "/" || path === "/index.html") {
+ if (window.postsByCategory && window.postsByCategory[topic]) {
+ renderPosts(topic);
+ return;
+ }
+ }
+
+ const isMail = href.startsWith("mailto:");
+ if (isMail) {
+ window.location.href = href;
+ return;
+ }
+
+ if (link.target === "_blank") {
+ window.open(href, "_blank");
+ return;
+ }
+
+ window.location.href = href;
+ });
+ }
+
+ function handleHomeClick(e) {
+ const home = e.target.closest(".home-link");
+ if (!home) return;
+ e.preventDefault();
+ const isHome =
+ window.location.pathname === "/" ||
+ window.location.pathname === "/index.html";
+ if (isHome) {
+ clearPrompt(500, () => {
+ const posts = document.getElementById("posts");
+ if (posts) posts.innerHTML = "";
+ const topics = document.querySelectorAll("[data-topic].active");
+ topics.forEach((t) => {
+ t.classList.remove("active");
+ t.style.color = "";
+ });
+ });
+ } else {
+ persistPrompt();
+ clearPrompt(500, () => {
+ window.location.href = "/";
+ });
+ }
+ }
+
+ document.addEventListener("DOMContentLoaded", () => {
+ document.body.addEventListener("click", (e) => {
+ if (e.target.closest(".home-link")) return handleHomeClick(e);
+ if (e.target.closest("[data-topic]")) return handleDataTopicClick(e);
+ });
+
+ document.body.addEventListener(
+ "mouseenter",
+ (e) => {
+ const link = e.target.closest("[data-topic]");
+ if (!link) return;
+ const color =
+ (window.getTopicColor &&
+ window.getTopicColor(link.dataset.topic.toLowerCase())) ||
+ "";
+ if (color) link.style.color = color;
+ },
+ true
+ );
+
+ document.body.addEventListener(
+ "mouseleave",
+ (e) => {
+ const link = e.target.closest("[data-topic]");
+ if (!link) return;
+ if (!link.classList.contains("active")) link.style.color = "";
+ },
+ true
+ );
+
+ window.addEventListener("beforeunload", () => {
+ const el = promptEl();
+ if (el) el.textContent = TERMINAL_PROMPT;
});
});
-
- window.addEventListener("beforeunload", () => {
- const terminalPrompt = document.querySelector(".terminal-prompt");
- if (terminalPrompt) {
- terminalPrompt.innerHTML = TERMINAL_PROMPT;
- }
- });
-});
+})();
diff --git a/src/components/Footer.astro b/src/components/Footer.astro
index bd1df64..2f0d501 100644
--- a/src/components/Footer.astro
+++ b/src/components/Footer.astro
@@ -1,14 +1,10 @@
@@ -20,23 +16,12 @@
align-items: center;
justify-content: space-between;
}
-
.footer-links a {
margin-left: 25px;
text-decoration: none;
+ cursor: pointer;
}
-
- if (host.includes("localhost") || host.includes("127.0.0.1")) {
- gistLink.href = "http://localhost:4321/gist.html";
- gitLink.href = "http://localhost:4321/git.html";
- } else {
- gistLink.href = "https://barrettruth.com/gist.html";
- gitLink.href = "https://barrettruth.com/git.html";
- }
-
diff --git a/src/components/Header.astro b/src/components/Header.astro
index 34cf25e..781d626 100644
--- a/src/components/Header.astro
+++ b/src/components/Header.astro
@@ -1,11 +1,11 @@
---
const path = Astro.url.pathname;
-const isHome = path === "/" || path === "/index.html";
const is404 = path === "/404.html" || path === "/404";
-function getTopic() {
+function deriveTopic() {
if (is404) return "/not-found";
if (path.startsWith("/about")) return "/about";
+ if (path === "/gist" || path.startsWith("/gist/")) return "/gist";
if (path === "/git" || path.startsWith("/git/")) return "/git";
if (path.startsWith("/posts/")) {
const parts = path.replace(/\/+$/, "").split("/");
@@ -14,132 +14,35 @@ function getTopic() {
return "";
}
-const topic = getTopic();
+const topic = deriveTopic();
const promptText = topic ? `barrett@ruth:~$ ${topic}` : "barrett@ruth:~$";
---
-
-
+
+
diff --git a/src/layouts/PostLayout.astro b/src/layouts/PostLayout.astro
index f94bf21..c57607c 100644
--- a/src/layouts/PostLayout.astro
+++ b/src/layouts/PostLayout.astro
@@ -55,6 +55,7 @@ const topicColor = getTopicColor(category);
+
{frontmatter.scripts?.map(script => (
diff --git a/src/pages/gist.astro b/src/pages/gist.astro
index 9d3d4fa..07b1709 100644
--- a/src/pages/gist.astro
+++ b/src/pages/gist.astro
@@ -10,15 +10,23 @@ gists.sort((a, b) => a.slug.localeCompare(b.slug));
+
+
diff --git a/src/pages/git.astro b/src/pages/git.astro
index 4a92d95..0557bd0 100644
--- a/src/pages/git.astro
+++ b/src/pages/git.astro
@@ -7,12 +7,11 @@ const title = "Git Repositories";
+
@@ -31,16 +30,16 @@ const title = "Git Repositories";
repos.sort((a, b) => a.localeCompare(b));
for (const name of repos) {
- const label = name.replace(/\.git$/,"");
- const cls = `repo-${label}`;
+ const label = name.replace(/\.git$/, "");
const li = document.createElement("li");
- li.className = `topic ${cls}`;
+ li.className = `topic repo-${label}`;
const a = document.createElement("a");
- a.href = `${window.location.origin}/git/${label}.html`;
+ a.href = `/git/${label}.html`;
a.textContent = label;
- a.setAttribute("data-topic", name);
+ a.dataset.topic = "git";
+ a.dataset.repo = label;
li.appendChild(a);
listEl.appendChild(li);
@@ -51,3 +50,4 @@ const title = "Git Repositories";
loadRepos();
+