docs(reports): JPEG image paste investigation + proposed fix#257
docs(reports): JPEG image paste investigation + proposed fix#257amikofalvy wants to merge 1 commit intomainfrom
Conversation
Root cause for "JPEGs aren't supported" is in the clipboard dispatcher, not the upload pipeline. When the clipboard carries both a File and text/html (typical for Preview/Photos/Finder/browser image copy on macOS), `createHandlePaste` Branch D fires on the HTML, inserts a broken `<img src="file://...">` PM node, and returns true — preempting `@tiptap/extension-file-handler`, so the actual File is never uploaded. Not JPEG-specific (PNG/GIF/WebP fail identically with the same clipboard shape); appears JPEG-biased because Cmd+Shift+4 screenshots produce file-only clipboards that fall through cleanly. Report proposes a ~5-line guard at the top of createHandlePaste that defers to FileHandler when clipboardData.files contains an ALLOWED_IMAGE_MIME_TYPES image. Evidence probes (jpeg-paste-probe, jpeg-mixed-paste-probe, png-mixed-paste-probe, jpeg-drop-probe, jpeg-browser-probe, jpeg-html-probe) reproduce the failure and confirm every other path (upload endpoint, markdown source reference, drop, slash-command picker, file-only paste) already works for JPEG. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
There was a problem hiding this comment.
PR Review Summary
(4) Total Issues | Risk: Low
🟠⚠️ Major (1) 🟠⚠️
Inline Comments:
- 🟠 Major:
REPORT.md:1-5Frontmatter schema doesn't match repository report format
🟡 Minor (2) 🟡
Inline Comments:
- 🟡 Minor:
REPORT.md:188Recommendation wording is confusing ("option 1" mismatch) - 🟡 Minor:
REPORT.md:243Evidence location statement is outdated
💭 Consider (1) 💭
💭 1) REPORT.md:60 Brittle line number reference
Issue: The root cause section references TiptapEditor.tsx:138 which may become stale after refactoring.
Why: Line number references in documentation become misleading over time.
Fix: Consider describing the wiring without the line number: "wired as editorProps.handlePaste in TiptapEditor.tsx via the handlePaste prop on EditorContent"
💡 APPROVE WITH SUGGESTIONS
Summary: Excellent investigation report with thorough root cause analysis, clear reproduction steps, and a well-reasoned proposed fix. The technical analysis is accurate — I verified the proposed fix location in handle-paste.ts and the dispatcher branch ordering matches the report's description. The six Playwright probes correctly reproduce the bug and control cases.
The only blocking issue is the frontmatter schema mismatch, which prevents proper catalogue indexing. The other suggestions are minor documentation polish.
On the proposed fix itself: The guard placement at the top of createHandlePaste (above all branches) is the correct approach. It's small (~5 lines), well-scoped, and doesn't introduce coupling between tryBranchHtml and FileHandler. Looking forward to the follow-up PR that implements it with the described unit and E2E tests.
Discarded (0)
No findings discarded.
Reviewers (2)
| Reviewer | Returned | Main Findings | Consider | While You're Here | Inline Comments | Pending Recs | Discarded |
|---|---|---|---|---|---|---|---|
pr-review-docs |
6 | 0 | 1 | 0 | 3 | 0 | 2 |
pr-review-standards |
0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Total | 6 | 0 | 1 | 0 | 3 | 0 | 2 |
Note: pr-review-standards found no issues in the evidence probes — they correctly simulate clipboard events and reproduce the documented bug.
| --- | ||
| title: JPEG images aren't supported on paste (it's actually all images — JPEG-biased by observation) | ||
| description: Investigation of why JPEGs "don't work" when pasted into the markdown editor. Root cause is in the clipboard dispatcher, not the upload pipeline, and the same bug affects PNG/GIF/WebP when the clipboard carries both a `File` object and a `text/html` payload. | ||
| tags: [report, editor, clipboard, paste, images] | ||
| --- |
There was a problem hiding this comment.
🟠 MAJOR: Frontmatter schema doesn't match repository report format
Issue: The frontmatter uses tags: [...] but the repository's established report format uses a richer schema with createdAt, updatedAt, subjects, and topics fields.
Why: The report won't be properly indexed by the catalogue generator (generate-catalogue.ts) which expects these fields. The catalogue at reports/CATALOGUE.md displays these in its index table.
Fix:
| --- | |
| title: JPEG images aren't supported on paste (it's actually all images — JPEG-biased by observation) | |
| description: Investigation of why JPEGs "don't work" when pasted into the markdown editor. Root cause is in the clipboard dispatcher, not the upload pipeline, and the same bug affects PNG/GIF/WebP when the clipboard carries both a `File` object and a `text/html` payload. | |
| tags: [report, editor, clipboard, paste, images] | |
| --- | |
| --- | |
| title: "JPEG Image Paste Support: Investigation and Proposed Fix" | |
| description: "Investigation of why JPEGs don't work when pasted into the markdown editor. Root cause is in the clipboard dispatcher, not the upload pipeline, and the same bug affects PNG/GIF/WebP when the clipboard carries both a File object and a text/html payload." | |
| createdAt: 2026-04-22 | |
| updatedAt: 2026-04-22 | |
| subjects: | |
| - TipTap | |
| - ProseMirror | |
| - "@tiptap/extension-file-handler" | |
| - clipboard API | |
| topics: | |
| - clipboard paste behavior | |
| - image upload | |
| - paste dispatcher | |
| - FileHandler | |
| --- |
Refs:
- reports/CATALOGUE.md — shows expected fields
| 3. **Let both handlers run and de-dupe** — not possible; first-returns-true stops dispatch. Rejected. | ||
| 4. **Stop using `tryBranchHtml` for `<img>`-only HTML** — plausible follow-up but doesn't fix clipboards that carry mixed `<img>` + real rich-text content. Insufficient. | ||
|
|
||
| Recommend option 1 as documented in the diff above. Small, local, well-scoped. |
There was a problem hiding this comment.
🟡 Minor: Recommendation wording is confusing
Issue: "Recommend option 1" refers to the first alternative listed (return early inside Branch D), but the proposed fix is actually a guard at the top of createHandlePaste — which is distinct from all the listed alternatives.
Why: A reader following the alternatives section would be confused about which approach is being recommended.
Fix:
| Recommend option 1 as documented in the diff above. Small, local, well-scoped. | |
| Recommend the guard at the top of `createHandlePaste` as documented in the diff above. Small, local, well-scoped. |
| - `png-mixed-paste-probe.mjs` — Same shape with PNG; confirms bug is not JPEG-specific. | ||
| - `jpeg-drop-probe.mjs` — Drag-and-drop of JPEG; verifies `FileHandler.handleDrop` works. | ||
|
|
||
| These should move into `reports/jpeg-image-paste-support/evidence/` as part of the PR that lands the fix (or be deleted once the Playwright e2e test described above exists). |
There was a problem hiding this comment.
🟡 Minor: Evidence location statement is outdated
Issue: This says the probes "should move into reports/jpeg-image-paste-support/evidence/" but they're already there in this PR.
Why: Creates confusion about the current state of the PR.
Fix:
| These should move into `reports/jpeg-image-paste-support/evidence/` as part of the PR that lands the fix (or be deleted once the Playwright e2e test described above exists). | |
| These are located in `evidence/` in this report directory (or can be deleted once the Playwright e2e test described above exists). |
|
This pull request has been automatically marked as stale because it has not had recent activity. If this PR is still relevant:
Thank you for your contributions! |
Summary
packages/app/src/editor/clipboard/handle-paste.ts), not the upload pipeline — the upload endpoint, sibling-asset filter, drag-and-drop, slash-command picker, markdown-source rendering, and sirv serving all already work for JPEG (verified with Playwright against a live dev server).Fileand atext/htmlpayload — typical for macOS Preview, Photos, Finder "Copy" on an image, and browser "Copy image". In that case Branch D (tryBranchHtml) handles the HTML first, inserts a PM image node withsrc="file://..."(which the browser can't load from anhttp://origin), and returnstrue, preempting@tiptap/extension-file-handler's paste handler that would have uploaded the actualFile.Cmd+Shift+4screenshots (the main PNG source) produce file-only clipboards that fall through cleanly.Proposed fix
~5-line guard at the top of
createHandlePastethat returnsfalsewhenclipboardData.filescontains an image onALLOWED_IMAGE_MIME_TYPES, deferring toFileHandler. Full diff, rationale, rejected alternatives, and unit + Playwright test plan are in the report. Not applied in this PR — this is the proposal for your review.Evidence
Six Playwright probes under
reports/jpeg-image-paste-support/evidence/reproduce both the bug and the happy paths:jpeg-mixed-paste-probe.mjs<img src="file://...">inserted (bug)png-mixed-paste-probe.mjsjpeg-paste-probe.mjsjpeg-drop-probe.mjsjpeg-browser-probe.mjsrenders correctly (control)jpeg-html-probe.mjs<img>structureTest plan
reports/jpeg-image-paste-support/REPORT.mdand confirm the proposed fix is in the right place (top ofcreateHandlePaste, above all branches).handle-paste.test.ts, and adds the Playwright e2e file described in §6 topackages/app/tests/stress/paste-image.e2e.ts.🤖 Generated with Claude Code