Conversation
|
E2E Tests 🚀 |
9139c0e to
4329f09
Compare
- Replace `targetImageDataUrl` mutable property on cell model with `menuActionOptions` arg forwarding through context menu service - Add `POSITRON_NOTEBOOK_OUTPUT_IMAGE_TARGETED` context key so "Copy Image" only appears when an image is actually targeted (right-click on image or ellipsis menu for cell with image output) - Fix misclick UX: right-clicking near but not on an image no longer shows "Copy Image" - Add unit test for new context key - Wrap e2e test menu verification in toPass retry for CI stability Addresses PR #12331 review feedback.
7170b69 to
23a30d9
Compare
seeM
left a comment
There was a problem hiding this comment.
Looks great! One question about the dynamic actions in the overflow menu. It would also be nice if the e2e test could cover a case with >1 image, but not a blocker.
| const logService = accessor.get(ILogService); | ||
|
|
||
| // Look for a CopyImageMenuArg forwarded from the context menu | ||
| const menuArg = args.find(isCopyImageMenuArg); |
There was a problem hiding this comment.
Neat pattern for command args
| const imageDataUrl = parsed.dataUrl; | ||
| actions.push(toAction({ | ||
| id: `positronNotebook.cell.copyOutputImage.${i}`, | ||
| label: localize('positronNotebook.cell.copyPlotN', "Copy Plot {0}", i + 1), |
There was a problem hiding this comment.
Hmm do you think these actions are helpful? It feels easier to right click on image. Even if you have a really long output with images scattered throughout, you'd need to scroll to them to see which image you want.
There was a problem hiding this comment.
If we keep them, can you please rename to Copy Image N since they could be images other than plots and to match the current single action case Copy Image?
Add ability to copy plot/image outputs from Positron notebook cells via right-click context menu and Cmd+C keyboard shortcut. - New context key `positronNotebookCellHasImageOutput` tracks whether the active cell has image outputs - New "Copy Image" action in the output context menu (ellipsis button and right-click), visible only when the cell has image output - Cmd+C keybinding in command mode copies the image when available - Uses IClipboardService.writeImage() which routes through Electron's native clipboard API, matching the plots pane approach - New "Copy" action group in output menu, shown above visibility actions
Unit tests: - Output parsing for PNG, SVG, text, and stdout mime types - Cell outputs observable correctly reports image outputs - Dynamic output addition updates the observable - Image detection works with mixed output types (text + image) E2E tests: - Right-click context menu shows "Copy Image" for plot output - Clicking "Copy Image" writes image data to clipboard - Cmd+C in command mode copies image when cell has plot output
- Clear clipboard before asserting in e2e copy image test to prevent false positives from stale clipboard data - Add full payload validation to PNG parsing unit test
- Let browser handle right-click on images natively so the correct image is copied in multi-image outputs (addresses @seeM's comment about always copying the first image) - Update unit test to check context keys directly via bindCellContextKeys and getContextKeyValue instead of re-checking the raw expression - Rewrite e2e test to use the ellipsis menu instead of right-click, which is more reliable in CI and matches the new behavior
Remove the Cmd+C keybinding that copies images in command mode, as it overrides the expected cell source copy behavior. Image copy via Cmd+C will be re-added once output-focused state is implemented (tracked in #12434). The ellipsis menu and browser right-click remain available for copying images.
When a cell has multiple image outputs, right-clicking on a specific image now copies that image rather than always the first. The clicked image's data URL is stored on the cell before the context menu opens, and the Copy Image action reads it before falling back to the first image (for the ellipsis menu path).
- Replace `targetImageDataUrl` mutable property on cell model with `menuActionOptions` arg forwarding through context menu service - Add `POSITRON_NOTEBOOK_OUTPUT_IMAGE_TARGETED` context key so "Copy Image" only appears when an image is actually targeted (right-click on image or ellipsis menu for cell with image output) - Fix misclick UX: right-clicking near but not on an image no longer shows "Copy Image" - Add unit test for new context key - Wrap e2e test menu verification in toPass retry for CI stability Addresses PR #12331 review feedback.
- Use useMemo to bind POSITRON_NOTEBOOK_OUTPUT_IMAGE_TARGETED once per context key service instead of re-binding on every render (which resets the key to its default) - Clear outputImageTargeted to false in onHide callbacks so stale interaction state does not persist after menu dismissal
- Remove BRANCH-SUMMARY development artifact file - Replace hardcoded app.code.wait(500) with toPass retry in e2e test
SVG notebook outputs use URL-encoded data URIs (data:image/svg+xml,...), but IClipboardService.writeImage() expects base64 encoding. Add toBase64DataUrl() to convert URL-encoded data URIs to base64 before writing to the clipboard.
Replace btoa() with encodeBase64(VSBuffer.fromString(...)) in toBase64DataUrl(). btoa() only handles Latin-1 characters and would throw for SVG content containing Unicode. The existing encodeBase64 utility handles arbitrary bytes correctly via UTF-8 encoding.
SVG payloads may contain literal '%' characters that are not URL-encoded, causing decodeURIComponent to throw URIError. Wrap in try/catch and fall back to using the raw payload.
When a cell produces multiple plot outputs, the ellipsis menu now shows "Copy Plot 1", "Copy Plot 2", etc. (up to 5) instead of a single "Copy Image" that only copies the first image. When there are more than 5 plots, a disabled hint tells users to right-click to copy additional plots. Single-image output retains the existing "Copy Image" behavior.
…ImageUtils Moves CopyImageMenuArg, isCopyImageMenuArg, and toBase64DataUrl from contribution.ts to a shared copyImageUtils.ts module, eliminating the duplicated interface in CellOutputLeftActionMenu.tsx. Adds unit tests covering base64 passthrough, URL-encoded SVG conversion, raw percent signs, and Unicode content.
For multiple image outputs, users can right-click individual images to copy them instead of using menu entries.
1925421 to
689c454
Compare
Addresses #10806.
Adds the ability to copy plot/image outputs from Positron notebook cells to the clipboard, matching feature parity with old notebooks and the plots pane.
Summary
positronNotebookCellHasImageOutputcontext key tracks whether the active cell has image outputsIClipboardService.writeImage()which routes through Electron's native clipboard APIDemo
Showing copying multiple plots work by respecting which one is clicked on. Also demonstrates the dynamic copy plot menu for a cell output.
Screen.Recording.2026-03-13.at.3.26.22.PM.mov
Architecture
Context key approach: Rather than checking for image outputs at action execution time only, a reactive
hasImageOutputcontext key is maintained via the existinguseCellContextKeysobservable pattern. This keeps the menu visibility declarative and consistent with how other cell state (e.g.,hasOutputs,outputIsCollapsed) is managed.Clipboard path: Reuses the same
IClipboardService.writeImage()path used by the plots pane, which routes through Electron's native clipboard API. This avoids duplicating clipboard logic and ensures consistent behavior across the IDE.Multi-image right-click: When the user right-clicks directly on an
<img>in the output area, the image's data URL is stored on the cell (targetImageDataUrl) before showing the context menu. The "Copy Image" action uses this targeted URL when available, falling back to the first image output when triggered from the ellipsis menu. The stored URL is cleared when the menu closes.Cmd+C keybinding: Deferred to #12434, which will add an output-focused state so Cmd+C can be context-dependent -- copying images when the output area is focused and copying cell source when the cell container is focused.
Action group ordering: A new
Copyaction group (0_copy) is added before the existingVisibilitygroup (renumbered to1_visibility) so copy actions appear at the top of the output menu.Tests added
Unit tests (
notebookOutputUtils.test.ts,positronNotebookCellOutputs.test.ts):applyEditsupdates the observablehasImageOutputis correctly set viabindCellContextKeyswhen cell has mixed output typesE2E tests (
notebook-copy-output-image.test.ts):Release Notes
New Features
QA Notes
@:positron-notebooksprint("hello")) and verify "Copy Image" does not appear