@marimo-team/islands 0.19.7-dev19 → 0.19.7-dev20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js
CHANGED
|
@@ -60930,6 +60930,17 @@ ${r}
|
|
|
60930
60930
|
VY
|
|
60931
60931
|
]
|
|
60932
60932
|
}), r[18] = BY, r[19] = VY, r[20] = IY, r[21] = HY) : HY = r[21], HY;
|
|
60933
|
+
}, Filenames = {
|
|
60934
|
+
toMarkdown: (e) => Filenames.replace(e, "md"),
|
|
60935
|
+
toHTML: (e) => Filenames.replace(e, "html"),
|
|
60936
|
+
toPNG: (e) => Filenames.replace(e, "png"),
|
|
60937
|
+
toPDF: (e) => Filenames.replace(e, "pdf"),
|
|
60938
|
+
toPY: (e) => Filenames.replace(e, "py"),
|
|
60939
|
+
withoutExtension: (e) => {
|
|
60940
|
+
let r = e.split(".");
|
|
60941
|
+
return r.length === 1 ? e : r.slice(0, -1).join(".");
|
|
60942
|
+
},
|
|
60943
|
+
replace: (e, r) => e.endsWith(`.${r}`) ? e : `${Filenames.withoutExtension(e)}.${r}`
|
|
60933
60944
|
};
|
|
60934
60945
|
function resolveUrl(e, r) {
|
|
60935
60946
|
if (e.match(/^[a-z]+:\/\//i)) return e;
|
|
@@ -61370,21 +61381,27 @@ ${r}
|
|
|
61370
61381
|
let { width: c, height: d } = getImageSize(e, r), f = await createImage(await toSvg(e, r)), _ = document.createElement("canvas"), v = _.getContext("2d"), y = r.pixelRatio || getPixelRatio(), S = r.canvasWidth || c, w = r.canvasHeight || d;
|
|
61371
61382
|
return _.width = S * y, _.height = w * y, r.skipAutoScale || checkCanvasDimensions(_), _.style.width = `${S}`, _.style.height = `${w}`, r.backgroundColor && (v.fillStyle = r.backgroundColor, v.fillRect(0, 0, _.width, _.height)), v.drawImage(f, 0, 0, _.width, _.height), _;
|
|
61372
61383
|
}
|
|
61373
|
-
async function toPng(e, r = {}) {
|
|
61384
|
+
async function toPng$1(e, r = {}) {
|
|
61374
61385
|
return (await toCanvas(e, r)).toDataURL();
|
|
61375
61386
|
}
|
|
61376
|
-
const
|
|
61377
|
-
|
|
61378
|
-
|
|
61379
|
-
|
|
61380
|
-
|
|
61381
|
-
|
|
61382
|
-
|
|
61383
|
-
let r = e.split(".");
|
|
61384
|
-
return r.length === 1 ? e : r.slice(0, -1).join(".");
|
|
61387
|
+
const defaultHtmlToImageOptions = {
|
|
61388
|
+
filter: (e) => {
|
|
61389
|
+
try {
|
|
61390
|
+
return "classList" in e ? !e.classList.contains("mpl-toolbar") : true;
|
|
61391
|
+
} catch (e2) {
|
|
61392
|
+
return Logger.error("Error filtering node:", e2), true;
|
|
61393
|
+
}
|
|
61385
61394
|
},
|
|
61386
|
-
|
|
61395
|
+
onImageErrorHandler: (e) => {
|
|
61396
|
+
Logger.error("Error loading image:", e);
|
|
61397
|
+
}
|
|
61387
61398
|
};
|
|
61399
|
+
function toPng(e, r) {
|
|
61400
|
+
return toPng$1(e, {
|
|
61401
|
+
...defaultHtmlToImageOptions,
|
|
61402
|
+
...r
|
|
61403
|
+
});
|
|
61404
|
+
}
|
|
61388
61405
|
async function downloadHTMLAsImage(e) {
|
|
61389
61406
|
let { element: r, filename: c, prepare: d } = e, f = document.getElementById("App"), _ = (f == null ? void 0 : f.scrollTop) ?? 0, v;
|
|
61390
61407
|
d ? v = d(r) : document.body.classList.add("printing");
|
|
@@ -72896,7 +72913,7 @@ Image URL: ${r.imageUrl}`)), contextToXml({
|
|
|
72896
72913
|
return Logger.warn("Failed to get version from mount config"), null;
|
|
72897
72914
|
}
|
|
72898
72915
|
}
|
|
72899
|
-
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.19.7-
|
|
72916
|
+
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.19.7-dev20"), showCodeInRunModeAtom = atom(true);
|
|
72900
72917
|
atom(null);
|
|
72901
72918
|
var import_compiler_runtime$89 = require_compiler_runtime();
|
|
72902
72919
|
function useKeydownOnElement(e, r) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marimo-team/islands",
|
|
3
|
-
"version": "0.19.7-
|
|
3
|
+
"version": "0.19.7-dev20",
|
|
4
4
|
"main": "dist/main.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"eslint-plugin-header": "^3.1.1",
|
|
129
129
|
"htm": "^3.1.1",
|
|
130
130
|
"html-react-parser": "^5.2.11",
|
|
131
|
-
"html-to-image": "
|
|
131
|
+
"html-to-image": "1.11.13",
|
|
132
132
|
"humanize-duration": "^3.33.2",
|
|
133
133
|
"iconify-icon": "^2.3.0",
|
|
134
134
|
"jotai": "^2.16.1",
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import type { Completion } from "@codemirror/autocomplete";
|
|
4
4
|
import type { FileUIPart } from "ai";
|
|
5
|
-
import { toPng } from "html-to-image";
|
|
6
5
|
import { processOutput } from "@/components/editor/output/console/process-output";
|
|
7
6
|
import { type NotebookState, notebookAtom } from "@/core/cells/cells";
|
|
8
7
|
import { type CellId, CellOutputId } from "@/core/cells/ids";
|
|
@@ -10,6 +9,7 @@ import { displayCellName } from "@/core/cells/names";
|
|
|
10
9
|
import { isOutputEmpty } from "@/core/cells/outputs";
|
|
11
10
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
12
11
|
import type { JotaiStore } from "@/core/state/jotai";
|
|
12
|
+
import { toPng } from "@/utils/html-to-image";
|
|
13
13
|
import { Logger } from "@/utils/Logger";
|
|
14
14
|
import { type AIContextItem, AIContextProvider } from "../registry";
|
|
15
15
|
import { contextToXml } from "../utils";
|
|
@@ -137,7 +137,13 @@ describe("useEnrichCellOutputs", () => {
|
|
|
137
137
|
expect(document.getElementById).toHaveBeenCalledWith(
|
|
138
138
|
CellOutputId.create(cellId),
|
|
139
139
|
);
|
|
140
|
-
expect(toPng).toHaveBeenCalledWith(
|
|
140
|
+
expect(toPng).toHaveBeenCalledWith(
|
|
141
|
+
mockElement,
|
|
142
|
+
expect.objectContaining({
|
|
143
|
+
filter: expect.any(Function),
|
|
144
|
+
onImageErrorHandler: expect.any(Function),
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
141
147
|
expect(output).toEqual({
|
|
142
148
|
[cellId]: ["image/png", mockDataUrl],
|
|
143
149
|
});
|
|
@@ -155,7 +155,13 @@ describe("getImageDataUrlForCell", () => {
|
|
|
155
155
|
const result = await getImageDataUrlForCell("cell-1" as CellId);
|
|
156
156
|
|
|
157
157
|
expect(result).toBe(mockDataUrl);
|
|
158
|
-
expect(toPng).toHaveBeenCalledWith(
|
|
158
|
+
expect(toPng).toHaveBeenCalledWith(
|
|
159
|
+
mockElement,
|
|
160
|
+
expect.objectContaining({
|
|
161
|
+
filter: expect.any(Function),
|
|
162
|
+
onImageErrorHandler: expect.any(Function),
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
159
165
|
});
|
|
160
166
|
|
|
161
167
|
it("should add printing classes before capture when enablePrintMode is true", async () => {
|
|
@@ -352,7 +358,13 @@ describe("downloadHTMLAsImage", () => {
|
|
|
352
358
|
|
|
353
359
|
await downloadHTMLAsImage({ element: mockElement, filename: "test" });
|
|
354
360
|
|
|
355
|
-
expect(toPng).toHaveBeenCalledWith(
|
|
361
|
+
expect(toPng).toHaveBeenCalledWith(
|
|
362
|
+
mockElement,
|
|
363
|
+
expect.objectContaining({
|
|
364
|
+
filter: expect.any(Function),
|
|
365
|
+
onImageErrorHandler: expect.any(Function),
|
|
366
|
+
}),
|
|
367
|
+
);
|
|
356
368
|
expect(mockAnchor.href).toBe(mockDataUrl);
|
|
357
369
|
expect(mockAnchor.download).toBe("test.png");
|
|
358
370
|
expect(mockAnchor.click).toHaveBeenCalled();
|
|
@@ -488,7 +500,13 @@ describe("downloadCellOutputAsImage", () => {
|
|
|
488
500
|
|
|
489
501
|
await downloadCellOutputAsImage("cell-1" as CellId, "result");
|
|
490
502
|
|
|
491
|
-
expect(toPng).toHaveBeenCalledWith(
|
|
503
|
+
expect(toPng).toHaveBeenCalledWith(
|
|
504
|
+
mockElement,
|
|
505
|
+
expect.objectContaining({
|
|
506
|
+
filter: expect.any(Function),
|
|
507
|
+
onImageErrorHandler: expect.any(Function),
|
|
508
|
+
}),
|
|
509
|
+
);
|
|
492
510
|
expect(mockAnchor.download).toBe("result.png");
|
|
493
511
|
});
|
|
494
512
|
|
package/src/utils/download.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import { toast } from "@/components/ui/use-toast";
|
|
4
4
|
import { type CellId, CellOutputId } from "@/core/cells/ids";
|
|
5
5
|
import { getRequestClient } from "@/core/network/requests";
|
|
6
6
|
import { Filenames } from "@/utils/filenames";
|
|
7
7
|
import { Paths } from "@/utils/paths";
|
|
8
8
|
import { prettyError } from "./errors";
|
|
9
|
+
import { toPng } from "./html-to-image";
|
|
9
10
|
import { Logger } from "./Logger";
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { toPng as htmlToImageToPng } from "html-to-image";
|
|
3
|
+
import { Logger } from "./Logger";
|
|
4
|
+
|
|
5
|
+
export type HtmlToImageOptions = Parameters<typeof htmlToImageToPng>[1];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Default options for html-to-image conversions.
|
|
9
|
+
* These handle common edge cases like filtering out toolbars and logging errors.
|
|
10
|
+
*/
|
|
11
|
+
export const defaultHtmlToImageOptions: HtmlToImageOptions = {
|
|
12
|
+
filter: (node) => {
|
|
13
|
+
try {
|
|
14
|
+
if ("classList" in node) {
|
|
15
|
+
// Filter out matplotlib toolbars
|
|
16
|
+
return !node.classList.contains("mpl-toolbar");
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
Logger.error("Error filtering node:", error);
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
onImageErrorHandler: (event) => {
|
|
25
|
+
Logger.error("Error loading image:", event);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert an HTML element to a PNG data URL.
|
|
31
|
+
* This is a wrapper around html-to-image's toPng with default options applied.
|
|
32
|
+
*/
|
|
33
|
+
export function toPng(
|
|
34
|
+
element: HTMLElement,
|
|
35
|
+
options?: HtmlToImageOptions,
|
|
36
|
+
): Promise<string> {
|
|
37
|
+
return htmlToImageToPng(element, {
|
|
38
|
+
...defaultHtmlToImageOptions,
|
|
39
|
+
...options,
|
|
40
|
+
});
|
|
41
|
+
}
|