From de4a660eb2594109bb826cbcc75bb139b519dc20 Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Sat, 21 Jun 2025 09:30:55 +0500 Subject: [PATCH] clipper: add svg screenshots for debugging --- packages/clipper/src/domtoimage.ts | 34 +++++++++++++++++++++--------- packages/clipper/src/index.ts | 21 ++++++++++-------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/packages/clipper/src/domtoimage.ts b/packages/clipper/src/domtoimage.ts index c8d1ad365..751e6b797 100644 --- a/packages/clipper/src/domtoimage.ts +++ b/packages/clipper/src/domtoimage.ts @@ -73,6 +73,15 @@ function toBlob(body: HTMLElement, head: HTMLHeadElement, options: Options) { ); } +function toSvg(body: HTMLElement, head: HTMLHeadElement, options: Options) { + return makeSvg( + body, + head, + options.width || width(body), + options.height || height(body) + ); +} + async function draw( body: HTMLElement, head: HTMLHeadElement, @@ -80,10 +89,12 @@ async function draw( ) { options = { ...defaultOptions, ...options }; const uri = makeSvgDataUri( - body, - head, - options.width || width(body), - options.height || height(body) + makeSvg( + body, + head, + options.width || width(body), + options.height || height(body) + ) ); return createImage(uri, options.fetchOptions) @@ -130,7 +141,7 @@ function embedFonts(node: HTMLElement, options?: FetchOptions) { }); } -function makeSvgDataUri( +function makeSvg( body: HTMLElement, head: HTMLHeadElement, width: number, @@ -163,7 +174,7 @@ function makeSvgDataUri( xhtml + ""; - const svgStr = + return ( '' + xstyles + foreignObject + - ""; - - return "data:image/svg+xml; charset=utf8, " + encodeURIComponent(svgStr); + "" + ); } -export { toJpeg, toBlob, toPng, getInlinedNode }; +function makeSvgDataUri(str: string) { + return "data:image/svg+xml; charset=utf8, " + encodeURIComponent(str); +} + +export { toJpeg, toBlob, toPng, toSvg, getInlinedNode }; function finalize(root: HTMLElement) { for (const element of root.querySelectorAll("*")) { diff --git a/packages/clipper/src/index.ts b/packages/clipper/src/index.ts index 44be0f513..4c1ed3498 100644 --- a/packages/clipper/src/index.ts +++ b/packages/clipper/src/index.ts @@ -20,7 +20,7 @@ along with this program. If not, see . import { Readability } from "@mozilla/readability"; import { injectCss } from "./utils.js"; import { app, h, text } from "hyperapp"; -import { getInlinedNode, toBlob, toJpeg, toPng } from "./domtoimage.js"; +import { getInlinedNode, toBlob, toJpeg, toPng, toSvg } from "./domtoimage.js"; import { Config, InlineOptions } from "./types.js"; import { FetchOptions } from "./fetch.js"; import { addStylesToHead } from "./styles.js"; @@ -85,10 +85,8 @@ async function clipArticle( } async function clipScreenshot< - TOutputFormat extends "jpeg" | "png" | "raw", - TOutput extends TOutputFormat extends "jpeg" - ? string - : TOutputFormat extends "png" + TOutputFormat extends "jpeg" | "png" | "raw" | "svg", + TOutput extends TOutputFormat extends "jpeg" | "png" | "svg" ? string : Blob | undefined >( @@ -96,15 +94,19 @@ async function clipScreenshot< output: TOutputFormat = "jpeg" as TOutputFormat, config?: Config ): Promise { - // const screenshotTarget = target || document.body; - const fetchOptions = resolveFetchOptions(config); - // await inlineAllImages(screenshotTarget, fetchOptions); const { body, head } = await getPage(document, config, false); if (!body || !head) return null; - const func = output === "jpeg" ? toJpeg : output === "png" ? toPng : toBlob; + const func = + output === "jpeg" + ? toJpeg + : output === "png" + ? toPng + : output === "svg" + ? toSvg + : toBlob; const screenshot = await func(body, head, { quality: 1, backgroundColor: "white", @@ -121,6 +123,7 @@ async function clipScreenshot< if (output === "jpeg" || output === "png") return `` as TOutput; + else if (output === "svg") return screenshot as TOutput; else return screenshot as TOutput; }