From 95c6feed167477e88cbd732bc9ab4e7f2487eec4 Mon Sep 17 00:00:00 2001 From: ZDDC Date: Wed, 13 May 2026 12:55:21 -0500 Subject: [PATCH] chore(embedded): cut v0.0.17-beta --- zddc/internal/apps/embedded/archive.html | 2 +- zddc/internal/apps/embedded/browse.html | 99 +++++++++++--------- zddc/internal/apps/embedded/classifier.html | 2 +- zddc/internal/apps/embedded/index.html | 2 +- zddc/internal/apps/embedded/transmittal.html | 2 +- zddc/internal/apps/embedded/versions.txt | 14 +-- zddc/internal/handler/tables.html | 2 +- 7 files changed, 67 insertions(+), 56 deletions(-) diff --git a/zddc/internal/apps/embedded/archive.html b/zddc/internal/apps/embedded/archive.html index f7dbf8e..a541a97 100644 --- a/zddc/internal/apps/embedded/archive.html +++ b/zddc/internal/apps/embedded/archive.html @@ -2470,7 +2470,7 @@ td[data-field="trackingNumber"] {
ZDDC Archive - v0.0.17-beta · 2026-05-13 17:17:48 · 7aec631 + v0.0.17-beta · 2026-05-13 17:55:11 · 9245017
diff --git a/zddc/internal/apps/embedded/browse.html b/zddc/internal/apps/embedded/browse.html index a6c2ab1..e7ce223 100644 --- a/zddc/internal/apps/embedded/browse.html +++ b/zddc/internal/apps/embedded/browse.html @@ -1657,7 +1657,7 @@ html, body {
ZDDC Browse - v0.0.17-beta · 2026-05-13 17:17:49 · 7aec631 + v0.0.17-beta · 2026-05-13 17:55:11 · 9245017
@@ -6743,25 +6743,33 @@ var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Arr sourceEl.textContent = 'server'; } - // Download-as-{docx,html,pdf} buttons. Server-mode + .md only: - // the server endpoint runs pandoc/chromium in a container and - // returns the converted bytes. Click handlers wire up below - // (after save() is defined) because they auto-save first when - // the buffer is dirty. + // Download-as-{docx,html,pdf} affordances. Server-mode + .md + // only: the server endpoint runs pandoc/chromium in a + // container and returns the converted bytes. + // + // These are real elements with href + download attributes, + // styled like buttons. That means right-click → "Copy link + // address" / "Open in new tab" / "Save link as" all work + // natively — users can share the conversion URL or download + // through their preferred path. Click is intercepted only + // when the buffer is dirty (auto-save first, then re-fire + // the click so the browser fetches the saved bytes). var serverModeMd = window.app && window.app.state && window.app.state.source === 'server' && node.url && /\.md$/i.test(node.name); var convertBtns = []; - if (serverModeMd && window.zddc && window.zddc.source && - typeof window.zddc.source.downloadConverted === 'function') { + if (serverModeMd) { ['docx', 'html', 'pdf'].forEach(function (fmt) { - var btn = document.createElement('button'); - btn.className = 'btn btn-sm btn-secondary md-shell__download'; - btn.type = 'button'; - btn.textContent = fmt.toUpperCase(); - btn.title = 'Download as ' + fmt.toUpperCase(); - btn.dataset.fmt = fmt; - convertBtns.push(btn); + var a = document.createElement('a'); + a.className = 'btn btn-sm btn-secondary md-shell__download'; + a.href = node.url + '?convert=' + encodeURIComponent(fmt); + a.download = node.name.replace(/\.md$/i, '') + '.' + fmt; + a.textContent = fmt.toUpperCase(); + a.title = 'Download as ' + fmt.toUpperCase() + + ' (right-click to copy link or open in new tab)'; + a.dataset.fmt = fmt; + a.rel = 'noopener'; + convertBtns.push(a); }); } @@ -6960,39 +6968,42 @@ var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Arr } }); - // Download-as-* click handlers. Auto-save when the buffer is - // dirty so the converted file reflects what's on screen. If - // the save fails the existing toast/status surfaces it; we - // bail without firing the conversion. - convertBtns.forEach(function (btn) { - btn.addEventListener('click', async function () { - var fmt = btn.dataset.fmt; - if (currentInstance.dirty) { - if (!writable) { - if (window.zddc && window.zddc.toast) { - window.zddc.toast( - 'This source is read-only — save a copy elsewhere first.', - 'error'); - } - return; - } - btn.disabled = true; - try { await save(); } finally { btn.disabled = false; } - if (currentInstance.dirty) return; // save failed + // Download-as-* click handlers. The anchors are real + // links so right-click / middle-click / Copy Link Address all + // work natively. The JS handler only steps in when the buffer + // is dirty — auto-save first, then re-fire the click so the + // browser fetches the just-saved bytes. After the click is + // re-fired, currentInstance.dirty is false so the handler + // is a no-op on the second pass and the native navigation + // proceeds. + convertBtns.forEach(function (a) { + a.addEventListener('click', async function (e) { + var fmt = a.dataset.fmt; + if (!currentInstance.dirty) { + // Clean — let the browser handle the click. The + // server's response (DOCX/HTML/PDF bytes, 422, + // 503, etc.) lands in whatever target the user + // picked (current tab, new tab, save-as). + return; } - btn.disabled = true; - try { - statusEl.textContent = 'Converting to ' + fmt.toUpperCase() + '…'; - await window.zddc.source.downloadConverted(node.url, node.name, fmt); - statusEl.textContent = 'Downloaded ' + fmt.toUpperCase(); - } catch (e) { - statusEl.textContent = (e && e.message) || String(e); + // Dirty: intercept, save, retry. + e.preventDefault(); + if (!writable) { if (window.zddc && window.zddc.toast) { - window.zddc.toast((e && e.message) || String(e), 'error'); + window.zddc.toast( + 'This source is read-only — save a copy elsewhere first.', + 'error'); } - } finally { - btn.disabled = false; + return; } + statusEl.textContent = 'Saving before download…'; + try { await save(); } catch (_) { /* save() surfaces its own error */ } + if (currentInstance.dirty) return; // save failed; toast already shown + statusEl.textContent = 'Downloading ' + fmt.toUpperCase() + '…'; + // Re-trigger the click. dirty=false now so the handler + // exits early on the second pass and the browser + // processes the native navigation. + a.click(); }); }); } diff --git a/zddc/internal/apps/embedded/classifier.html b/zddc/internal/apps/embedded/classifier.html index 1a4d7a0..8fe6b68 100644 --- a/zddc/internal/apps/embedded/classifier.html +++ b/zddc/internal/apps/embedded/classifier.html @@ -1681,7 +1681,7 @@ body.help-open .app-header {
ZDDC Classifier - v0.0.17-beta · 2026-05-13 17:17:48 · 7aec631 + v0.0.17-beta · 2026-05-13 17:55:11 · 9245017
diff --git a/zddc/internal/apps/embedded/index.html b/zddc/internal/apps/embedded/index.html index 146be7c..2e3bd80 100644 --- a/zddc/internal/apps/embedded/index.html +++ b/zddc/internal/apps/embedded/index.html @@ -1424,7 +1424,7 @@ body {
ZDDC - v0.0.17-beta · 2026-05-13 17:17:49 · 7aec631 + v0.0.17-beta · 2026-05-13 17:55:11 · 9245017
diff --git a/zddc/internal/apps/embedded/transmittal.html b/zddc/internal/apps/embedded/transmittal.html index cff0734..b23f0e4 100644 --- a/zddc/internal/apps/embedded/transmittal.html +++ b/zddc/internal/apps/embedded/transmittal.html @@ -2523,7 +2523,7 @@ dialog.modal--narrow {
ZDDC Transmittal - v0.0.17-beta · 2026-05-13 17:17:48 · 7aec631 + v0.0.17-beta · 2026-05-13 17:55:10 · 9245017
JavaScript not available