fix(mdedit): root file tree at <project>/working/ even with no trailing slash

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 (<project>/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) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-05-09 22:34:11 -05:00
parent 464c80c1e1
commit 2aa29d1ec4

View file

@ -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.
//
// <project>/working/ → root = <project>/working/
// <project>/working/x/y/ → root = <project>/working/x/y/
// <project>/working → root = <project>/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.)
// <project>/x/y/mdedit.html → root = <project>/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