From 151dea768c0cb5abd68539fdf25d39eca720d607 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 4 May 2026 20:20:17 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=A9=B9=20fix:=20surface=20PPTX/DOCX=20fal?= =?UTF-8?q?lback=20reason=20(inline=20+=20console)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Manual e2e on PR #12934: "Preview unavailable" appears in the iframe with no way to know what actually failed. The reason was tucked into the fallback element's `title` attribute (hover-only tooltip) — easy to miss and impossible to copy/paste. Now surfaces three ways: 1. Visible inline via a `
` element with the reason in monospace, folded so the friendly message stays primary but the diagnostic is one click away in the iframe itself. 2. `title` attribute (preserved) for hover tooltip. 3. `console.error('[pptx-preview] fallback fired:', reason)` so DevTools shows it in red — also the only reliable way to see the reason if the iframe is detached / re-mounted. DOCX gets the same console mirror (as `console.warn` since the fallback there is "high-fidelity unavailable, showing simplified preview" — informational, not error). The DOCX fallback already displays the mammoth-rendered content visibly, so no `
` needed there. Tests: regression assertions pin the diagnostic surfacing — the `
` element, the `title` write, and the `console.error` call must all be present in the bootstrap. --- packages/api/src/files/documents/html.spec.ts | 12 +++++++ packages/api/src/files/documents/html.ts | 31 +++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/packages/api/src/files/documents/html.spec.ts b/packages/api/src/files/documents/html.spec.ts index 54aa036e2f..eca519f9a6 100644 --- a/packages/api/src/files/documents/html.spec.ts +++ b/packages/api/src/files/documents/html.spec.ts @@ -486,6 +486,18 @@ describe('Office HTML producers', () => { expect(html).toContain("addEventListener('error'"); // The 8-second timeout safety net for silent renderer failures. expect(html).toContain('renderer-timeout'); + /* Diagnostic surfacing: the failure reason must be exposed + * three ways so a debugging user can find it without reading + * source — manual e2e on PR #12934 ("'Preview unavailable' + * with no way to know why"): + * 1. Visible inline via a `
` element so it's one + * click away in the iframe itself + * 2. `title` attribute on the fallback for hover tooltip + * 3. `console.error` so DevTools shows it in red */ + expect(html).toContain('id="lc-fallback-reason"'); + expect(html).toContain('Diagnostic details'); + expect(html).toContain('fallback.title = reasonText'); + expect(html).toContain("console.error('[pptx-preview] fallback fired:'"); }); test('size-fallback threshold is the documented 350 KB', () => { diff --git a/packages/api/src/files/documents/html.ts b/packages/api/src/files/documents/html.ts index ae09282706..2503ce9b80 100644 --- a/packages/api/src/files/documents/html.ts +++ b/packages/api/src/files/documents/html.ts @@ -482,9 +482,15 @@ ${DOCX_EXTRA_CSS} var render = document.getElementById('lc-render'); if (render) { render.hidden = true; } var fallback = document.getElementById('lc-fallback'); + var reasonText = reason ? String(reason).slice(0, 500) : 'no reason reported'; if (fallback) { fallback.hidden = false; - if (reason) { fallback.title = String(reason).slice(0, 200); } + fallback.title = reasonText; + } + /* Mirror to DevTools so the reason is visible without inspecting + * the title attribute or expanding details elements. */ + if (typeof console !== 'undefined' && console.warn) { + console.warn('[docx-preview] CDN renderer fell through to mammoth:', reasonText); } } if (typeof docx === 'undefined' || typeof docx.renderAsync !== 'function') { @@ -1138,7 +1144,13 @@ html, body { margin: 0; padding: 0; background: var(--bg); color: var(--fg); fon
Loading preview…
- +