From d8274230e3f9ff0e41fbaa8305d474ae6ccbf464 Mon Sep 17 00:00:00 2001 From: Suryaansh Rai Date: Mon, 31 Aug 2026 21:00:29 +0530 Subject: [PATCH 1/2] fix: remove debug console logging and duplicate tree rebuilds buildFileTrie() and handleNavOrRender() had ~10 unconditional console.log("[Explorer] ...") calls with no verbose/debug flag to gate them, so every navigation flooded the console with tracing output ("Fetching content index...", "Entry count: N", "Trie root children: N", "Rendering N children", "Render complete...", etc). Removed all of them, keeping the console.error/console.warn calls that report real failures. Also, handleNavOrRender was bound directly to both the "nav" and "render" events. When both fire for the same navigation (e.g. a plugin dispatching "render" after updating the content index), the file tree was rebuilt twice. Added a microtask-coalescing wrapper so same-tick nav/render dispatches trigger a single rebuild, while still keeping the most recent url in the merged event detail. No behavior change beyond removed logging and de-duplicated rebuilds. --- .changeset/quiet-explorer-console.md | 5 +++ src/components/scripts/explorer.inline.ts | 43 ++++++++++++++--------- 2 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 .changeset/quiet-explorer-console.md diff --git a/.changeset/quiet-explorer-console.md b/.changeset/quiet-explorer-console.md new file mode 100644 index 0000000..18f92ba --- /dev/null +++ b/.changeset/quiet-explorer-console.md @@ -0,0 +1,5 @@ +--- +"@quartz-community/explorer": patch +--- + +Remove leftover debug `console.log` calls that fired on every navigation, and coalesce the `nav`/`render` event handlers so the file tree is rebuilt once per navigation instead of twice. diff --git a/src/components/scripts/explorer.inline.ts b/src/components/scripts/explorer.inline.ts index 2e2c2a1..b14267b 100644 --- a/src/components/scripts/explorer.inline.ts +++ b/src/components/scripts/explorer.inline.ts @@ -109,9 +109,7 @@ function processTrie(trie, sortFn, filterFn, mapFn) { // Build trie from content index data async function buildFileTrie(dataFns) { try { - console.log("[Explorer] Fetching content index..."); const data = await fetchData; - console.log("[Explorer] Fetched data keys:", Object.keys(data).slice(0, 5)); if (!data) { console.error("[Explorer] No data received"); @@ -122,15 +120,12 @@ async function buildFileTrie(dataFns) { const contentData = data.content || data; const entries = Object.entries(contentData); - console.log("[Explorer] Entry count:", entries.length); - if (entries.length === 0) { console.warn("[Explorer] No content entries found"); return null; } const trie = FileTrieNode.fromEntries(entries); - console.log("[Explorer] Trie root children:", trie.children.length); // Parse data functions from string if provided let sortFn = defaultSortFn; @@ -237,10 +232,8 @@ function renderTree(node, container, currentSlug, folderBehavior, savedState, pa async function handleNavOrRender(e) { const thisGeneration = ++currentRenderGeneration; try { - console.log("[Explorer] Nav event received, generation:", thisGeneration); const currentSlug = (e.detail?.url || "").replace(/^\/+/, ""); const allExplorers = document.querySelectorAll("div.explorer"); - console.log("[Explorer] Found", allExplorers.length, "explorers"); const savedState = {}; try { @@ -267,22 +260,17 @@ async function handleNavOrRender(e) { const folderBehavior = explorer.dataset.behavior || "collapse"; // Build and render the tree - console.log("[Explorer] Starting tree build..."); const trie = await buildFileTrie(dataFns); // Check if another nav event started while we were fetching if (thisGeneration === currentRenderGeneration) { - console.log("[Explorer] Render generation is current, rendering tree"); - console.log("[Explorer] Trie result:", trie ? "success" : "null"); if (trie && trie.children && trie.children.length > 0) { // Clear again before rendering to ensure clean state explorerUl.innerHTML = '
  • '; - console.log("[Explorer] Rendering", trie.children.length, "children"); for (const child of trie.children) { renderTree(child, explorerUl, currentSlug, folderBehavior, savedState, ""); } - console.log("[Explorer] Render complete, final list length:", explorerUl.children.length); } else { console.warn("[Explorer] No trie or empty children"); } @@ -297,8 +285,6 @@ async function handleNavOrRender(e) { activeElement.scrollIntoView({ behavior: "smooth" }); } } - } else { - console.log("[Explorer] Stale render generation, skipping tree render"); } // Always set up event listeners, regardless of render generation @@ -409,8 +395,33 @@ async function handleNavOrRender(e) { } } -document.addEventListener("nav", handleNavOrRender); -document.addEventListener("render", handleNavOrRender); +// "nav" and "render" can both fire for the same navigation (e.g. a plugin +// that dispatches "render" right after "nav" to signal a content-index +// update). Coalesce same-tick dispatches into a single tree rebuild instead +// of rebuilding once per event, while still keeping the most recent url. +let pendingDetail = null; +let isRenderScheduled = false; + +function scheduleNavOrRender(e) { + if (e?.detail?.url) { + pendingDetail = { ...(pendingDetail || {}), ...e.detail }; + } else if (!pendingDetail) { + pendingDetail = e?.detail || {}; + } + + if (!isRenderScheduled) { + isRenderScheduled = true; + queueMicrotask(() => { + const detail = pendingDetail; + isRenderScheduled = false; + pendingDetail = null; + handleNavOrRender({ detail }); + }); + } +} + +document.addEventListener("nav", scheduleNavOrRender); +document.addEventListener("render", scheduleNavOrRender); document.addEventListener("prenav", () => { const explorer = document.querySelector(".explorer-ul"); From ab8bf5ff7b045a95affee59c7c10f86831adcb00 Mon Sep 17 00:00:00 2001 From: Suryaansh Rai Date: Mon, 31 Aug 2026 21:12:13 +0530 Subject: [PATCH 2/2] fix: don't drop falsy url values when coalescing nav/render events Copilot review caught that gating the merge on e?.detail?.url being truthy would silently discard a legitimate falsy url (e.g. "" for the root page) and skip merging any other detail fields on that event. Merge detail unconditionally and only fall back to the previous url when the new one is null/undefined. --- src/components/scripts/explorer.inline.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/scripts/explorer.inline.ts b/src/components/scripts/explorer.inline.ts index b14267b..869b8e9 100644 --- a/src/components/scripts/explorer.inline.ts +++ b/src/components/scripts/explorer.inline.ts @@ -403,10 +403,13 @@ let pendingDetail = null; let isRenderScheduled = false; function scheduleNavOrRender(e) { - if (e?.detail?.url) { - pendingDetail = { ...(pendingDetail || {}), ...e.detail }; - } else if (!pendingDetail) { - pendingDetail = e?.detail || {}; + const previousUrl = pendingDetail?.url; + pendingDetail = { ...(pendingDetail || {}), ...(e?.detail || {}) }; + // Only fall back to the previous url if this event didn't carry one at + // all (e.g. "render" with no detail) — an explicit "" url (root page) is + // a real value and must not be discarded. + if (pendingDetail.url == null && previousUrl != null) { + pendingDetail.url = previousUrl; } if (!isRenderScheduled) {