From 2aa29d1ec4c83ee740540b946b25aeab256e6b8f Mon Sep 17 00:00:00 2001 From: ZDDC Date: Sat, 9 May 2026 22:34:11 -0500 Subject: [PATCH] fix(mdedit): root file tree at /working/ even with no trailing slash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mdedit's loadServerDirectory derived its file-tree root by stripping back to the last "/" in window.location.href. For a no-trailing-slash canonical URL (/working) that gave the wrong root: the parent project directory rather than working/ itself. Visible symptom on zddc-server's auto-served URLs after the recent dispatcher changes — mdedit at /Project/working would show the project's archive, working, staging, etc. all together instead of being sandboxed to working/. Detect the directory-shaped URL by checking whether the last path segment contains "." (file marker). No dot = directory; treat the whole path as the root and append the trailing slash internally. /Project/working → root /Project/working/ (was /Project/) /Project/working/x/y/ → root /Project/working/x/y/ (unchanged) /Project/x/mdedit.html → root /Project/x/ (file URL; unchanged) Co-Authored-By: Claude Opus 4.7 (1M context) --- mdedit/js/file-system.js | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/mdedit/js/file-system.js b/mdedit/js/file-system.js index 810cb2c..f805e0f 100644 --- a/mdedit/js/file-system.js +++ b/mdedit/js/file-system.js @@ -683,9 +683,38 @@ async function readServerDirectory(dirUrl, parentNode, depth) { async function loadServerDirectory() { if (!(location.protocol === 'http:' || location.protocol === 'https:')) return; + // Compute the directory URL the file tree should be rooted at. + // + // /working/ → root = /working/ + // /working/x/y/ → root = /working/x/y/ + // /working → root = /working/ (no-slash + // canonical-folder URL — the dispatcher + // routes mdedit here directly without + // a redirect, so we infer "directory" + // from the absence of a `.` in the + // last segment rather than stripping + // back to the parent.) + // /x/y/mdedit.html → root = /x/y/ (the leaf + // segment IS a file; strip to parent.) + // + // The rule: if the last path segment contains a "." it's a file, + // strip it; otherwise treat the whole path as the directory. let href = window.location.href.split('?')[0].split('#')[0]; - const lastSlash = href.lastIndexOf('/'); - const baseUrl = (lastSlash >= 0) ? href.substring(0, lastSlash + 1) : href + '/'; + let baseUrl; + if (href.endsWith('/')) { + baseUrl = href; + } else { + const lastSlash = href.lastIndexOf('/'); + const lastSeg = lastSlash >= 0 ? href.substring(lastSlash + 1) : href; + if (lastSeg.indexOf('.') !== -1) { + // Looks like a file (has an extension) — strip to parent. + baseUrl = lastSlash >= 0 ? href.substring(0, lastSlash + 1) : href + '/'; + } else { + // Looks like a directory — append the trailing slash so all + // subsequent listing URLs are computed correctly. + baseUrl = href + '/'; + } + } // Only enter server-source mode if the host actually serves JSON directory // listings (zddc-server / Caddy). On a plain static host the probe fails