feat: final refactor for port
This commit is contained in:
parent
cd9bd06eef
commit
c08e4ce9d5
4 changed files with 131 additions and 140 deletions
128
public/scripts/index.js
Normal file
128
public/scripts/index.js
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
import { getTopicColor } from "../../src/utils/colors.js";
|
||||||
|
|
||||||
|
const TERMINAL_PROMPT = "barrett@ruth:~$ ";
|
||||||
|
let typing = false;
|
||||||
|
let clearing = false;
|
||||||
|
|
||||||
|
function clearPrompt(delay, callback) {
|
||||||
|
if (clearing) return;
|
||||||
|
clearing = true;
|
||||||
|
|
||||||
|
const terminalPrompt = document.querySelector(".terminal-prompt");
|
||||||
|
if (!terminalPrompt) {
|
||||||
|
clearing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const topicLength =
|
||||||
|
terminalPrompt.innerHTML.length - TERMINAL_PROMPT.length;
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
function removeChar() {
|
||||||
|
if (i++ < topicLength) {
|
||||||
|
terminalPrompt.textContent = terminalPrompt.textContent.slice(0, -1);
|
||||||
|
setTimeout(removeChar, delay / topicLength);
|
||||||
|
} else {
|
||||||
|
i = 0;
|
||||||
|
clearing = false;
|
||||||
|
callback && callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, () => {
|
||||||
|
let i = 0;
|
||||||
|
function typechar() {
|
||||||
|
if (i < terminalText.length) {
|
||||||
|
terminalPrompt.innerHTML += terminalText.charAt(i++);
|
||||||
|
setTimeout(typechar, delay / terminalText.length);
|
||||||
|
} else {
|
||||||
|
renderPosts(topic);
|
||||||
|
typing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typechar();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPosts(topic) {
|
||||||
|
const posts = document.getElementById("posts");
|
||||||
|
posts.innerHTML = "";
|
||||||
|
|
||||||
|
const categoryPosts = postsByCategory[topic];
|
||||||
|
|
||||||
|
if (!categoryPosts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = getTopicColor(topicName);
|
||||||
|
topic.style.color = color;
|
||||||
|
});
|
||||||
|
|
||||||
|
topic.addEventListener("mouseleave", () => {
|
||||||
|
if (!topic.classList.contains("active")) {
|
||||||
|
topic.style.color = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("beforeunload", () => {
|
||||||
|
const terminalPrompt = document.querySelector(".terminal-prompt");
|
||||||
|
if (terminalPrompt) {
|
||||||
|
terminalPrompt.innerHTML = TERMINAL_PROMPT;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -55,7 +55,7 @@ const topicColor = getTopicColor(category);
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<slot name="scripts" slot="scripts">
|
<slot name="scripts" slot="scripts">
|
||||||
<script src="/scripts/dateHeadings.js" is:inline></script>
|
<script src="/scripts/centerKatex.js" is:inline></script>
|
||||||
{frontmatter.scripts?.map(script => (
|
{frontmatter.scripts?.map(script => (
|
||||||
<script src={script} type="module"></script>
|
<script src={script} type="module"></script>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -48,144 +48,7 @@ Object.keys(postsByCategory).forEach((category) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script slot="scripts" define:vars={{ postsByCategory }}>
|
<script slot="scripts" define:vars={{ postsByCategory }}>
|
||||||
function getTopicColor(topicName) {
|
window.postsByCategory = postsByCategory;
|
||||||
switch (topicName) {
|
|
||||||
case "software":
|
|
||||||
return "#0073e6";
|
|
||||||
case "algorithms":
|
|
||||||
return "#d50032";
|
|
||||||
case "meditations":
|
|
||||||
return "#6a0dad";
|
|
||||||
default:
|
|
||||||
return "#000000";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const TERMINAL_PROMPT = "barrett@ruth:~$ ";
|
|
||||||
let typing = false;
|
|
||||||
let clearing = false;
|
|
||||||
|
|
||||||
function clearPrompt(delay, callback) {
|
|
||||||
if (clearing) return;
|
|
||||||
clearing = true;
|
|
||||||
|
|
||||||
const terminalPrompt = document.querySelector(".terminal-prompt");
|
|
||||||
if (!terminalPrompt) {
|
|
||||||
clearing = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const topicLength =
|
|
||||||
terminalPrompt.innerHTML.length - TERMINAL_PROMPT.length;
|
|
||||||
let i = 0;
|
|
||||||
|
|
||||||
function removeChar() {
|
|
||||||
if (i++ < topicLength) {
|
|
||||||
terminalPrompt.textContent = terminalPrompt.textContent.slice(0, -1);
|
|
||||||
setTimeout(removeChar, delay / topicLength);
|
|
||||||
} else {
|
|
||||||
i = 0;
|
|
||||||
clearing = false;
|
|
||||||
callback && callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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, () => {
|
|
||||||
let i = 0;
|
|
||||||
function typechar() {
|
|
||||||
if (i < terminalText.length) {
|
|
||||||
terminalPrompt.innerHTML += terminalText.charAt(i++);
|
|
||||||
setTimeout(typechar, delay / terminalText.length);
|
|
||||||
} else {
|
|
||||||
renderPosts(topic);
|
|
||||||
typing = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typechar();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderPosts(topic) {
|
|
||||||
const posts = document.getElementById("posts");
|
|
||||||
posts.innerHTML = "";
|
|
||||||
|
|
||||||
const categoryPosts = postsByCategory[topic];
|
|
||||||
|
|
||||||
if (!categoryPosts) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = getTopicColor(topicName);
|
|
||||||
topic.style.color = color;
|
|
||||||
});
|
|
||||||
|
|
||||||
topic.addEventListener("mouseleave", () => {
|
|
||||||
if (!topic.classList.contains("active")) {
|
|
||||||
topic.style.color = "";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener("beforeunload", () => {
|
|
||||||
const terminalPrompt = document.querySelector(".terminal-prompt");
|
|
||||||
if (terminalPrompt) {
|
|
||||||
terminalPrompt.innerHTML = TERMINAL_PROMPT;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
<script slot="scripts" type="module" src="/scripts/index.js"></script>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue