ZDDC/browse/js
ZDDC 167a56dc07 refactor: virtual file extensions for subtree zip + MD conversion
Replace `?zip=1` / `?convert=docx|html|pdf` query forms with path-suffix
URLs that look like ordinary files. `<dir>.zip` and `<file>.docx` /
`.html` / `.pdf` are virtual files served by the dispatcher when stat
fails at the requested path AND the corresponding base resource exists:

  GET /Project-1/archive.zip          ← if archive/ is a real directory
  GET /Project-1/notes.docx           ← if notes.md exists

Real on-disk files always win — a genuine archive.zip in the tree
serves its bytes normally. The virtual forms only fire when nothing
real is there.

Why: the URL form lets clients emit plain <a href> without query-
string handling; `curl -O` writes a sensible filename; mirror tools
pick up the path through normal recursion; the protocol surface
becomes "every URL is a file". Bash + filesystem mental model.

Server:
- New helpers handler.RecognizeVirtualSubtreeZip /
  RecognizeVirtualConvert (in subtreezip.go and converthandler.go).
- Dispatcher's stat-fails branch checks them between IsDefaultMdlSpec
  and MatchAppHTML. ACL is enforced on the base resource (the source
  directory for zip, the .md source for convert).
- Three legacy query-form branches removed from main.go.

Client:
- browse/js/download.js: `dir + '.zip'` instead of `dir + '/?zip=1'`.
- browse/js/preview-markdown.js: convert anchor hrefs become
  `<mdUrl-minus-.md>.<fmt>` instead of `<mdUrl>?convert=<fmt>`.
- shared/zddc-source.js downloadConverted: same transform.

Tests: subtreezip_test.go test URLs cosmetically updated to the new
shape (the handler is exercised directly, so the URL is metadata only,
but the test reads better).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:23:37 -05:00
..
app.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00
download.js refactor: virtual file extensions for subtree zip + MD conversion 2026-05-14 12:23:37 -05:00
events.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00
grid.js feat(zddc): Phase 4b — grid mode driven by cascade default_tool 2026-05-11 16:15:25 -05:00
hovercard.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00
init.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00
loader.js feat(browse): "Show hidden" toggle — list .-prefixed and _-prefixed entries 2026-05-13 14:45:41 -05:00
preview-markdown.js refactor: virtual file extensions for subtree zip + MD conversion 2026-05-14 12:23:37 -05:00
preview-yaml.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00
preview.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00
tree.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00
upload.js feat(browse): SPA overhaul — context menu, YAML editor, icons, hovercard, deep links, autofilter 2026-05-14 12:12:42 -05:00