Update app.js
This commit is contained in:
parent
8db7aa84d1
commit
bafd4f29af
1 changed files with 43 additions and 10 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
Self-Organizing Static Site Framework v2.3.2
|
Self-Organizing Static Site Framework v2.3.3
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
let INDEX, CURRENT_PATH = null, PATH_TO_EL = new Map();
|
let INDEX, CURRENT_PATH = null, PATH_TO_EL = new Map();
|
||||||
|
|
@ -17,12 +17,30 @@ const sidebar = document.querySelector(".sidebar");
|
||||||
const navToggle = document.getElementById("navToggle");
|
const navToggle = document.getElementById("navToggle");
|
||||||
const overlay = document.querySelector(".overlay");
|
const overlay = document.querySelector(".overlay");
|
||||||
|
|
||||||
/* --- Navigation toggle --- */
|
/* ------------------------------------------------------------
|
||||||
|
Utility: ensure external libs are ready before running
|
||||||
|
------------------------------------------------------------- */
|
||||||
|
async function ensureLibsReady() {
|
||||||
|
let tries = 0;
|
||||||
|
while ((!window.marked || !window.DOMPurify) && tries < 40) {
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
tries++;
|
||||||
|
}
|
||||||
|
if (!window.marked) console.warn("⚠️ marked.js not detected — markdown will show as plain text.");
|
||||||
|
if (!window.DOMPurify) console.warn("⚠️ DOMPurify not detected — HTML not sanitized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------
|
||||||
|
Sidebar toggle and overlay
|
||||||
|
------------------------------------------------------------- */
|
||||||
navToggle.addEventListener("click", () => sidebar.classList.toggle("open"));
|
navToggle.addEventListener("click", () => sidebar.classList.toggle("open"));
|
||||||
overlay.addEventListener("click", () => sidebar.classList.remove("open"));
|
overlay.addEventListener("click", () => sidebar.classList.remove("open"));
|
||||||
|
|
||||||
/* --- Index load --- */
|
/* ------------------------------------------------------------
|
||||||
|
Load and render index.json
|
||||||
|
------------------------------------------------------------- */
|
||||||
async function loadIndex() {
|
async function loadIndex() {
|
||||||
|
await ensureLibsReady();
|
||||||
const res = await fetch("/index.json", { cache: "no-store" });
|
const res = await fetch("/index.json", { cache: "no-store" });
|
||||||
INDEX = await res.json();
|
INDEX = await res.json();
|
||||||
populateFilters();
|
populateFilters();
|
||||||
|
|
@ -49,7 +67,9 @@ function populateFilters() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Tree build --- */
|
/* ------------------------------------------------------------
|
||||||
|
Build directory tree
|
||||||
|
------------------------------------------------------------- */
|
||||||
function rebuildTree() {
|
function rebuildTree() {
|
||||||
treeEl.innerHTML = "";
|
treeEl.innerHTML = "";
|
||||||
PATH_TO_EL.clear();
|
PATH_TO_EL.clear();
|
||||||
|
|
@ -111,7 +131,9 @@ function renderNode(n) {
|
||||||
function iconForExt(ext){return ext===".md"?"📝":"🧩";}
|
function iconForExt(ext){return ext===".md"?"📝":"🧩";}
|
||||||
function fmtDate(ms){return new Date(ms).toISOString().slice(0,10);}
|
function fmtDate(ms){return new Date(ms).toISOString().slice(0,10);}
|
||||||
|
|
||||||
/* --- Path openers --- */
|
/* ------------------------------------------------------------
|
||||||
|
Path navigation
|
||||||
|
------------------------------------------------------------- */
|
||||||
function findDir(p){
|
function findDir(p){
|
||||||
p=p.replace(/\/$/,'');
|
p=p.replace(/\/$/,'');
|
||||||
function search(n){
|
function search(n){
|
||||||
|
|
@ -145,7 +167,9 @@ async function openPath(path){
|
||||||
if(window.innerWidth<900) sidebar.classList.remove("open");
|
if(window.innerWidth<900) sidebar.classList.remove("open");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Markdown renderer (v2.3.2 fix) --- */
|
/* ------------------------------------------------------------
|
||||||
|
Markdown rendering (stable version)
|
||||||
|
------------------------------------------------------------- */
|
||||||
async function renderMarkdown(path){
|
async function renderMarkdown(path){
|
||||||
mdView.innerHTML="<p style='color:var(--muted);font-style:italic;'>Loading…</p>";
|
mdView.innerHTML="<p style='color:var(--muted);font-style:italic;'>Loading…</p>";
|
||||||
htmlView.style.display="none";
|
htmlView.style.display="none";
|
||||||
|
|
@ -164,6 +188,7 @@ async function renderMarkdown(path){
|
||||||
|
|
||||||
requestAnimationFrame(()=>{
|
requestAnimationFrame(()=>{
|
||||||
mdView.innerHTML=safe;
|
mdView.innerHTML=safe;
|
||||||
|
mdView.scrollTop=0; // reset scroll to top
|
||||||
mdView.classList.add("fade-in");
|
mdView.classList.add("fade-in");
|
||||||
mdView.style.display="block";
|
mdView.style.display="block";
|
||||||
});
|
});
|
||||||
|
|
@ -174,14 +199,18 @@ async function renderMarkdown(path){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- HTML viewer --- */
|
/* ------------------------------------------------------------
|
||||||
|
HTML rendering
|
||||||
|
------------------------------------------------------------- */
|
||||||
function renderHTML(path){
|
function renderHTML(path){
|
||||||
htmlView.src="/"+path;
|
htmlView.src="/"+path;
|
||||||
htmlView.style.display="block";
|
htmlView.style.display="block";
|
||||||
mdView.style.display="none";
|
mdView.style.display="none";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Active / Pager --- */
|
/* ------------------------------------------------------------
|
||||||
|
Active state + pager
|
||||||
|
------------------------------------------------------------- */
|
||||||
function setActive(path){
|
function setActive(path){
|
||||||
document.querySelectorAll(".file.active").forEach(el=>el.classList.remove("active"));
|
document.querySelectorAll(".file.active").forEach(el=>el.classList.remove("active"));
|
||||||
const el=PATH_TO_EL.get(path);
|
const el=PATH_TO_EL.get(path);
|
||||||
|
|
@ -212,7 +241,9 @@ function updatePager(){
|
||||||
nextBtn.onclick=()=>i<list.length-1&&openPath(list[i+1].path);
|
nextBtn.onclick=()=>i<list.length-1&&openPath(list[i+1].path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Search / Filter / Sort --- */
|
/* ------------------------------------------------------------
|
||||||
|
Search / filter / sort
|
||||||
|
------------------------------------------------------------- */
|
||||||
let searchTimer;
|
let searchTimer;
|
||||||
searchBox.addEventListener("input",()=>{
|
searchBox.addEventListener("input",()=>{
|
||||||
clearTimeout(searchTimer);
|
clearTimeout(searchTimer);
|
||||||
|
|
@ -221,7 +252,9 @@ searchBox.addEventListener("input",()=>{
|
||||||
sortSel.addEventListener("change",rebuildTree);
|
sortSel.addEventListener("change",rebuildTree);
|
||||||
filterSel.addEventListener("change",rebuildTree);
|
filterSel.addEventListener("change",rebuildTree);
|
||||||
|
|
||||||
/* --- Internal link interception --- */
|
/* ------------------------------------------------------------
|
||||||
|
Internal link interception
|
||||||
|
------------------------------------------------------------- */
|
||||||
document.body.addEventListener("click",e=>{
|
document.body.addEventListener("click",e=>{
|
||||||
const a=e.target.closest("a[href]");
|
const a=e.target.closest("a[href]");
|
||||||
if(!a) return;
|
if(!a) return;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue