fix(tables): handle bare-directory URLs served as default_tool
Visiting `/Project-1/archive/PartyA/mdl` (no trailing slash) errored with `Unrecognized table URL` because tableNameFromUrl only matched `…/<rowsdir>/table.html`. The cascade declares `default_tool: tables` at `archive/<party>/mdl`, so the server serves the tables HTML at the bare directory URL — a shape the client didn't recognize. Two coordinated fixes: - shared/zddc-source.js `pathToDir`: was over-eagerly stripping the last segment when the URL didn't end in `/`. Now checks whether the last segment contains a dot — file URLs strip to parent (original behavior preserved), bare-directory URLs append the missing slash. Only call site is detectServerRoot, so blast radius is contained. - tables/js/context.js `tableNameFromUrl` + `rowEditUrl`: accept both legacy `…/<rowsdir>/table.html` and the new bare-directory shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a62960b712
commit
e5ba2b6168
2 changed files with 43 additions and 11 deletions
|
|
@ -289,14 +289,34 @@
|
||||||
// Top-level helpers
|
// Top-level helpers
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
// Strip a trailing tool .html (e.g. classifier.html) from a path
|
// Resolve "the directory the tool was opened in" for the current
|
||||||
// to land on the "directory the tool was opened in".
|
// page URL. Two URL shapes serve a tool:
|
||||||
|
//
|
||||||
|
// /…/<tool>.html — file URL; strip the trailing filename.
|
||||||
|
// /…/<dir>/ — trailing-slash directory URL; keep it.
|
||||||
|
// /…/<dir> — bare-directory URL served by the
|
||||||
|
// cascade's `default_tool` (e.g.
|
||||||
|
// archive/<party>/mdl serves the tables
|
||||||
|
// tool). Treat as the directory itself
|
||||||
|
// and append the missing slash.
|
||||||
|
//
|
||||||
|
// Discrimination is "does the last segment contain a dot?" — a dot
|
||||||
|
// is a reliable proxy for "looks like a file with an extension"
|
||||||
|
// since neither directory names nor default_tool paths contain
|
||||||
|
// them in this system.
|
||||||
function pathToDir(pathname) {
|
function pathToDir(pathname) {
|
||||||
if (!pathname) return '/';
|
if (!pathname) return '/';
|
||||||
if (pathname.endsWith('/')) return pathname;
|
if (pathname.endsWith('/')) return pathname;
|
||||||
var slash = pathname.lastIndexOf('/');
|
var slash = pathname.lastIndexOf('/');
|
||||||
|
var lastSeg = slash >= 0 ? pathname.substring(slash + 1) : pathname;
|
||||||
|
if (lastSeg.indexOf('.') !== -1) {
|
||||||
|
// Has an extension → looks like a file URL → strip the
|
||||||
|
// filename to land on the parent directory.
|
||||||
return slash >= 0 ? pathname.substring(0, slash + 1) : '/';
|
return slash >= 0 ? pathname.substring(0, slash + 1) : '/';
|
||||||
}
|
}
|
||||||
|
// No extension → the URL IS the directory; just close it.
|
||||||
|
return pathname + '/';
|
||||||
|
}
|
||||||
|
|
||||||
// Probe the server-mode root for the current page. Returns:
|
// Probe the server-mode root for the current page. Returns:
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function tableNameFromUrl(pathname) {
|
function tableNameFromUrl(pathname) {
|
||||||
// /<dir>/.../<rowsdir>/table.html → name is the rows-dir's
|
// Two URL shapes resolve to a table page:
|
||||||
// basename.
|
// Form A — /<…>/<rowsdir>/table.html (legacy/explicit
|
||||||
const m = String(pathname || '').match(/\/([^\/]+)\/table\.html$/);
|
// entry-point; the tool was opened via the
|
||||||
return m ? m[1] : null;
|
// literal file URL).
|
||||||
|
// Form B — /<…>/<rowsdir> or /<…>/<rowsdir>/ (served
|
||||||
|
// by the cascade's `default_tool: tables` at
|
||||||
|
// archive/<party>/mdl; the URL is the directory
|
||||||
|
// itself, no trailing filename).
|
||||||
|
// In both cases the table name is the rows-directory basename.
|
||||||
|
const a = String(pathname || '').match(/\/([^\/]+)\/table\.html$/);
|
||||||
|
if (a) return a[1];
|
||||||
|
const trimmed = String(pathname || '').replace(/\/$/, '');
|
||||||
|
const b = trimmed.match(/\/([^\/]+)$/);
|
||||||
|
return b ? b[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripDotSlash(p) {
|
function stripDotSlash(p) {
|
||||||
|
|
@ -198,11 +208,13 @@
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-edit URL for one row. Page is at /<dir>/table.html; row file
|
// Re-edit URL for one row. The page directory is the same
|
||||||
// lives at /<dir>/<basename>.yaml; form re-edit URL is
|
// directory the rows live in, regardless of which URL shape
|
||||||
// /<dir>/<basename>.yaml.html — same directory.
|
// (Form A `…/table.html` vs Form B bare `…/<rowsdir>`) we were
|
||||||
|
// opened with — see tableNameFromUrl.
|
||||||
function rowEditUrl(rowFileName) {
|
function rowEditUrl(rowFileName) {
|
||||||
const pageDir = location.pathname.replace(/\/table\.html$/, '/');
|
let pageDir = location.pathname.replace(/\/table\.html$/, '/');
|
||||||
|
if (!pageDir.endsWith('/')) pageDir += '/';
|
||||||
return pageDir + rowFileName + '.html';
|
return pageDir + rowFileName + '.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue