From 1fc42828b3717ac5b0e731228073bbce18d2609c Mon Sep 17 00:00:00 2001
From: Emil Gulamov <125820963+mearashadowfax@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:59:53 +0400
Subject: [PATCH] Refactor ToC generation and active link handling
The SVG HTML was moved into a constant for cleaner code.
---
src/pages/insights/[...slug].astro | 85 +++++++++++++++---------------
1 file changed, 43 insertions(+), 42 deletions(-)
diff --git a/src/pages/insights/[...slug].astro b/src/pages/insights/[...slug].astro
index 1d6bfcc..66b9921 100644
--- a/src/pages/insights/[...slug].astro
+++ b/src/pages/insights/[...slug].astro
@@ -170,50 +170,20 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
},
});
- // Function to create and add an item to the ToC list
- function addToC(heading: HTMLElement, tocList: HTMLElement | null) {
- const li = document.createElement("li");
- li.className = "toc-level-" + heading.tagName.toLowerCase();
- li.innerHTML =`
-
- ${heading.textContent}`;
- tocList?.appendChild(li);
- return li;
- }
+ const SVG_HTML_STRING = '';
+
+ function setActiveLinkById(id: string | null) {
+ const listItems = document.querySelectorAll("#toc li");
+ listItems.forEach(item => item.classList.remove("selected"));
+
+ if (!id) return;
- function setActiveLink(id: string) {
- document.querySelectorAll("#toc li").forEach((li) => {
- li.classList.remove("selected");
- });
const activeLink = document.querySelector(`#toc a[href="#${id}"]`);
- if (activeLink) {
- const li: HTMLElement | null = activeLink.parentElement;
- li?.classList.add("selected");
- }
- }
- function generateToC(article: HTMLElement | null, tocList: HTMLElement | null) {
- // Observe headings and add them to the ToC
- let headings: NodeListOf | [] = article
- ? article.querySelectorAll("h1, h2, h3, h4, h5, h6")
- : [];
- headings.forEach((heading: Element, i: number) => {
- if (heading instanceof HTMLElement) {
- addToC(heading, tocList);
- gsap.timeline({
- scrollTrigger: {
- trigger: heading,
- start: "top 20%",
- end: () =>
- `bottom top+=${i === headings.length - 1 ? 0 : headings[i + 1].getBoundingClientRect().height}`,
- onEnter: () => setActiveLink(heading.id),
- },
- });
- }
- });
+ if (!activeLink) return;
+
+ const listItem = activeLink.parentElement;
+ listItem?.classList.add("selected");
}
document.addEventListener("DOMContentLoaded", function () {
@@ -221,6 +191,37 @@ const pageTitle: string = `${post.data.title} | ${SITE.title}`;
const article: HTMLElement | null = document.querySelector("article");
// The ToC container element
const tocList: HTMLElement | null = document.querySelector("#toc ul");
- generateToC(article, tocList);
+
+ const headings: NodeListOf | [] = article ? article.querySelectorAll("h1, h2, h3, h4, h5, h6") : [];
+
+ headings.forEach((heading, i) => {
+ if (heading instanceof HTMLElement) {
+ const listItem = document.createElement("li");
+ listItem.className = "toc-level-" + heading.tagName.toLowerCase();
+
+ const tempDiv = document.createElement("div");
+ tempDiv.innerHTML = SVG_HTML_STRING;
+
+ const svg = tempDiv.firstChild;
+ listItem.appendChild(svg as Node);
+
+ const link = document.createElement("a");
+ link.href = "#" + heading.id;
+ link.textContent = heading.textContent;
+ listItem.appendChild(link);
+
+ tocList?.appendChild(listItem);
+
+ gsap.timeline({
+ scrollTrigger: {
+ trigger: heading,
+ start: "top 20%",
+ end: () => `bottom top+=${i === headings.length - 1 ? 0 : (headings[i + 1] as HTMLElement).getBoundingClientRect().height}`,
+ onEnter: () => setActiveLinkById(heading.id),
+ onLeaveBack: () => setActiveLinkById((headings[i - 1] as HTMLElement)?.id),
+ },
+ });
+ }
+ });
});