Skip to content

Let a host page say it saves exported PNGs itself - #78

Merged
CSSFrancis merged 2 commits into
mainfrom
feat/host-saves-png
Sep 17, 2026
Merged

CSSFrancis merged 2 commits into
mainfrom
feat/host-saves-png

Conversation

@CSSFrancis

Copy link
Copy Markdown
Owner

In an iframe, the export menu's Save PNG… can't download, so it posts the image to the parent and shows an in-figure preview captioned "Right-click the image → Save image as…". A desktop app that embeds figures (SpyDE, on Electron) has its own Save dialog and a webview with no such right-click menu, so that preview left users with no way to save.

Change

  • The parent can post {type: 'anyplotlib_host', savesPng: true} to the figure's frame. The page template's PNG_HARVEST_LISTENER records it in globalThis.__aplHostSavesPng, accepting it from window.parent only.
  • When set, a framed save only posts {type: 'anyplotlib_export_png_result', requestId: null, dataUrl, width, height, filename}. There's no preview, and no Save as… (choose folder) row, because the host's dialog already chooses the folder (_hostSavesPng, _canPickFile).
  • Hosts that don't announce anything behave as before. The navigated embed gets the listener too, since it installs the same block.

Docs

  • docs/exporting.rst documents the message a framed save posts and the host announcement.
  • FIGURE_ESM.md describes the host-save path. The insertion shifted 26 anchors; I shifted them by the diff hunks and checked every function anchor against its declaration line (105 checked, no mismatches).
  • The line count in AGENTS.md is updated to 12,438.

Tests

  • New tests/test_embed/test_host_saves_png.py, run in a parent page with the figure in an iframe:
    • without an announcement: the image is posted and the preview is shown;
    • with one: the image is posted, there's no preview and no "choose folder" row (this test fails on main);
    • a message from the frame itself, rather than its parent, is ignored.
  • tests/test_embed, tests/test_plotxy and tests/test_documentation pass locally.

In a frame, "Save PNG…" cannot download, so it posts the image to the parent
and shows an in-figure preview captioned "Right-click the image → Save image
as…". A desktop app embedding figures (SpyDE, in Electron) has its own Save
dialog and a webview with no such right-click menu, so the preview left the
user with no way to save at all.

The parent can now post {type: 'anyplotlib_host', savesPng: true}. The page
template records it (from window.parent only) in globalThis.__aplHostSavesPng,
and the figure then only posts the image: no preview, and no "Save as… (choose
folder)" entry, since the host's dialog already chooses the folder.

The listener lives in PNG_HARVEST_LISTENER, so the navigated embed gets it too.
FIGURE_ESM.md: 26 anchors shifted by the diff hunks, every function anchor
checked against its declaration.
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.20%. Comparing base (b38ca67) to head (0da5c94).

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #78   +/-   ##
=======================================
  Coverage   91.20%   91.20%           
=======================================
  Files          41       41           
  Lines        4880     4880           
=======================================
  Hits         4451     4451           
  Misses        429      429           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The host-save path is documented and tested, with existing behavior preserved.

Pull request overview

Adds an opt-in host-managed PNG export path for framed figures, preserving existing behavior when no host announcement is made.

Changes:

  • Handles parent-only host announcements.
  • Suppresses preview and folder-picker UI for host-managed saves.
  • Adds tests and documentation updates.
File summaries
File Description
upcoming_changes/78.new_feature.rst Adds the changelog entry.
docs/exporting.rst Documents the host export protocol.
anyplotlib/tests/test_embed/test_host_saves_png.py Tests announced and unannounced host behavior.
anyplotlib/FIGURE_ESM.md Updates renderer documentation and anchors.
anyplotlib/figure_esm.js Implements host-aware PNG export behavior.
anyplotlib/_repr_utils.py Adds the host announcement listener.
AGENTS.md Updates renderer line-count metadata.
Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@CSSFrancis
CSSFrancis merged commit de81f89 into main Sep 17, 2026
13 checks passed
@CSSFrancis CSSFrancis mentioned this pull request Sep 17, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants