feat: add copy & download buttons to the web file viewer (and fix CSP-blocked modal controls)#56
Merged
Merged
Conversation
The web demo's file-preview modal now has Copy and Download buttons, so users can grab a generated doc's contents without manually selecting text. - Copy uses the async Clipboard API, raced against a 1s timeout and backed by a document.execCommand fallback, so it never hangs and degrades gracefully. - Download saves the previewed content as a Blob named after the file. While wiring these, found that the modal's existing close button and click-outside-to-dismiss used inline `onclick` handlers that the server's Content-Security-Policy (`script-src-attr 'none'`) silently blocked — they did nothing. Moved ALL modal controls to addEventListener, which both complies with the CSP and fixes the previously-dead close/dismiss controls. Tests: templates unit tests assert the buttons, the CSP-safe wiring (no inline onclick), the clipboard-with-fallback path, and the Blob download. The Playwright web-ui spec now grants clipboard permission and exercises Copy (label flips to "Copied!") and Download (asserts the download filename). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The web demo's file-preview modal now has Copy and Download buttons, so users can grab a generated doc's contents without manually selecting text in the preview.
document.execCommandfallback, so it never hangs and degrades gracefully on browsers/contexts where the async API is unavailable or denied.BOOTCAMP.md).Bonus fix: CSP-blocked modal controls
While wiring the new buttons, I discovered the modal's existing close button (
×) and click-outside-to-dismiss were implemented with inlineonclickhandlers — which the web server's Content-Security-Policy (script-src-attr 'none', set by Helmet) silently blocks. Those controls were effectively dead; the modal could only be closed with the Escape key.I moved all modal controls to
addEventListener, which both complies with the CSP and restores the close/dismiss behavior. There are now zero inline event handlers in the page.Testing
test/templates.test.ts): asserts the Copy/Download/Close buttons exist, that the page usesaddEventListenerwith no inlineonclick(a regression guard for the CSP issue), the clipboard-with-fallback code path, thePromise.racetimeout guard, and the Blob download wiring.test/playwright/web-ui.e2e.spec.ts): grants clipboard permission, opens a generated file, clicks Copy (asserts the label flips to "Copied!" and back), and clicks Download (asserts adownloadevent withsuggestedFilename() === "BOOTCAMP.md").npm test→ 1101 passing; Playwright web-ui spec passing; typecheck + lint + build clean.🤖 Generated with Claude Code