78 lines
2.9 KiB
JavaScript
78 lines
2.9 KiB
JavaScript
// Loads a lesson's markdown (DSA/*.md) into the right-hand content pane
|
|
// when a sidebar link with [data-lesson] is clicked, renders it with
|
|
// marked.js, syntax-highlights code blocks with highlight.js, and adds a
|
|
// copy button to each code block.
|
|
(() => {
|
|
"use strict";
|
|
|
|
const COPY_ICON = `<svg viewBox="0 0 16 16"><path d="M4 2a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h1a.5.5 0 0 0 0-1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v1a.5.5 0 0 0 1 0V4a2 2 0 0 0-2-2H4z"/><path d="M7 6a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h5a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2H7zm-1 2a1 1 0 0 1 1-1h5a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V8z"/></svg>`;
|
|
const CHECK_ICON = `<svg viewBox="0 0 16 16"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/></svg>`;
|
|
|
|
const addCopyButtons = (container) => {
|
|
container.querySelectorAll("pre code").forEach((codeEl) => {
|
|
const pre = codeEl.parentElement;
|
|
const wrapper = document.createElement("div");
|
|
wrapper.className = "code-block";
|
|
pre.replaceWith(wrapper);
|
|
wrapper.appendChild(pre);
|
|
|
|
const button = document.createElement("button");
|
|
button.type = "button";
|
|
button.className = "code-copy-btn";
|
|
button.setAttribute("aria-label", "Copy code");
|
|
button.innerHTML = COPY_ICON;
|
|
|
|
button.addEventListener("click", async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(codeEl.textContent);
|
|
button.innerHTML = CHECK_ICON;
|
|
button.classList.add("copied");
|
|
setTimeout(() => {
|
|
button.innerHTML = COPY_ICON;
|
|
button.classList.remove("copied");
|
|
}, 1500);
|
|
} catch (err) {
|
|
console.error("Copy failed", err);
|
|
}
|
|
});
|
|
|
|
wrapper.appendChild(button);
|
|
});
|
|
};
|
|
|
|
const loadLesson = async (url, pane) => {
|
|
pane.innerHTML = `<p class="lesson-placeholder">Loading…</p>`;
|
|
try {
|
|
const response = await fetch(url);
|
|
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
|
|
const markdown = await response.text();
|
|
|
|
pane.innerHTML = marked.parse(markdown);
|
|
pane.querySelectorAll("pre code").forEach((block) => {
|
|
hljs.highlightElement(block);
|
|
});
|
|
addCopyButtons(pane);
|
|
} catch (err) {
|
|
pane.innerHTML = `<p class="lesson-placeholder">Couldn't load this lesson (${err.message}).</p>`;
|
|
}
|
|
};
|
|
|
|
window.addEventListener("DOMContentLoaded", () => {
|
|
const pane = document.getElementById("lesson-pane");
|
|
if (!pane) return;
|
|
|
|
document.querySelectorAll("[data-lesson]").forEach((link) => {
|
|
link.addEventListener("click", (event) => {
|
|
event.preventDefault();
|
|
|
|
document
|
|
.querySelectorAll("[data-lesson].active")
|
|
.forEach((el) => el.classList.remove("active"));
|
|
link.classList.add("active");
|
|
|
|
loadLesson(link.dataset.lesson, pane);
|
|
});
|
|
});
|
|
});
|
|
})();
|