diff --git a/markdown-svg-renderer.docs.md b/markdown-svg-renderer.docs.md
index a35c4c34..2025a49a 100644
--- a/markdown-svg-renderer.docs.md
+++ b/markdown-svg-renderer.docs.md
@@ -1,3 +1,3 @@
-View and render markdown content with live preview. Paste markdown directly or load from a raw URL or GitHub Gist, with support for standard formatting, tables, code blocks, and SVG previews featuring tabbed display for rendered output, PNG/JPEG export, MP4 generation for animated SVGs, and source code viewing. Toggle between split editor and full-screen viewer modes.
+View and render markdown content with live preview. Paste markdown directly or load from a raw URL or GitHub Gist, with support for standard formatting, tables, code blocks, and SVG previews featuring tabbed display for rendered output, PNG/JPEG/WebP export, MP4 generation for animated SVGs, and source code viewing. Toggle between split editor and full-screen viewer modes.
\ No newline at end of file
diff --git a/markdown-svg-renderer.html b/markdown-svg-renderer.html
index 51a86e77..cdb49f10 100644
--- a/markdown-svg-renderer.html
+++ b/markdown-svg-renderer.html
@@ -499,6 +499,32 @@
"https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd";
const FFMPEG_DOWNLOAD_MB = 31;
+// Raster export formats offered as tabs on each SVG block.
+const IMAGE_FORMATS = {
+ png: { mimeType: "image/png", label: "PNG", filename: "image.png" },
+ jpeg: { mimeType: "image/jpeg", label: "JPEG", filename: "image.jpg" },
+ webp: { mimeType: "image/webp", label: "WebP", filename: "image.webp" }
+};
+
+// canvas.toDataURL() silently falls back to PNG when the browser has no
+// encoder for the requested format (older Safari cannot encode WebP), so
+// probe a 1x1 canvas once and hide the WebP tab if it is unsupported.
+let _webpSupported = null;
+function browserCanEncodeWebp() {
+ if (_webpSupported === null) {
+ try {
+ const canvas = document.createElement("canvas");
+ canvas.width = canvas.height = 1;
+ _webpSupported = canvas
+ .toDataURL("image/webp")
+ .startsWith("data:image/webp");
+ } catch (err) {
+ _webpSupported = false;
+ }
+ }
+ return _webpSupported;
+}
+
async function fetchAsBlobUrl(url, mimeType) {
const res = await fetch(url);
if (!res.ok) throw new Error(`Fetch of ${url} returned ${res.status}`);
@@ -598,6 +624,20 @@
const shadow = this.attachShadow({ mode: "open" });
this._animation = detectSvgAnimation(code);
+ const webpTab = browserCanEncodeWebp()
+ ? ''
+ : "";
+ const webpPanel = browserCanEncodeWebp()
+ ? `