@marimo-team/islands 0.25.3-dev244 → 0.25.3-dev245

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.
@@ -135,7 +135,7 @@ function F(e) {
135
135
  }
136
136
  //#endregion
137
137
  //#region src/components/editor/boundary/ErrorBoundary.tsx
138
- var I = (0, T.lazy)(() => import("./feedback-button-C0iLkz-H.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
138
+ var I = (0, T.lazy)(() => import("./feedback-button-WpSRKq8m.js").then((e) => ({ default: e.FeedbackModal }))), L = (e) => {
139
139
  let t = (0, w.c)(2), n;
140
140
  return t[0] === e.children ? n = t[1] : (n = /* @__PURE__ */ (0, j.jsx)(O, {
141
141
  FallbackComponent: R,
@@ -17,7 +17,7 @@ function b() {
17
17
  return e.warn("Failed to get version from mount config"), null;
18
18
  }
19
19
  }
20
- var x = b() || "0.25.3-dev244", S = s(x), C = s(!0);
20
+ var x = b() || "0.25.3-dev245", S = s(x), C = s(!0);
21
21
  s(null);
22
22
  //#endregion
23
23
  //#region src/core/wasm/state.ts
@@ -12,7 +12,7 @@ import { A as Re, C as ze, M as Be, S as Ve, T as He, _ as Ue, b as We, c as Ge,
12
12
  import { $ as ot, $t as st, A as ct, At as lt, B as ut, Bt as dt, C as ft, Ct as pt, D as mt, Dt as ht, E as gt, Et as _t, F as vt, Ft as yt, G as bt, Gt as xt, H as St, Ht as Ct, I as wt, It as Tt, Jt as Et, K as Dt, Kt as Ot, L as kt, Lt as At, M as jt, Mt, N as Nt, Nt as Pt, O as Ft, Ot as It, P as Lt, Pt as Rt, Q as zt, Qt as Bt, R as Vt, Rt as Ht, S as Ut, St as Wt, T as Gt, Tt as Kt, U as qt, Ut as Jt, V as Yt, Vt as Xt, W as Zt, Wt as Qt, X as $t, Xt as en, Yt as tn, Z as nn, Zt as rn, _ as an, _n as on, _t as sn, a as cn, an as ln, at as un, b as dn, bn as fn, bt as pn, cn as mn, ct as hn, d as gn, dn as _n, dt as vn, en as yn, et as bn, f as xn, ft as Sn, gn as Cn, gt as wn, h as Tn, hn as En, ht as Dn, i as On, it as kn, j as An, jt as jn, k as Mn, kt as Nn, l as Pn, lt as Fn, mn as In, mt as Ln, n as Rn, nn as zn, nt as Bn, o as Vn, on as Hn, ot as Un, pn as Wn, q as Gn, qt as Kn, rn as qn, rt as Jn, s as Yn, sn as Xn, st as Zn, t as Qn, tn as $n, tt as er, u as tr, un as nr, ut as rr, vn as ir, vt as ar, wt as or, x as sr, xn as cr, xt as lr, yn as ur, yt as dr, z as fr, zt as pr } from "./dropdown-menu-BRiE7Vnp.js";
13
13
  import { a as mr, n as hr, r as gr, t as _r } from "./config-DbjzjwxX.js";
14
14
  import { A as vr, E as yr, G as br, H as xr, I as Sr, Lt as Cr, Nt as wr, Q as Tr, Rt as Er, T as Dr, Tt as Or, U as kr, V as Ar, b as jr, et as Mr, h as Nr, j as Pr, l as Fr, q as Ir, st as Lr, t as Rr, tt as zr, u as Br, wt as Vr, y as Hr, zt as Ur } from "./error-entries-CRPfxMqm.js";
15
- import { n as Wr, t as Gr } from "./ErrorBoundary-DKniGLW9.js";
15
+ import { n as Wr, t as Gr } from "./ErrorBoundary-DiPu-nOq.js";
16
16
  import { i as Kr, r as qr, s as Jr, t as Yr } from "./strings-BGW-fXVJ.js";
17
17
  import { t as Xr } from "./clsx-CoeGtWvn.js";
18
18
  import { t as Zr } from "./react-dom-DUmH0GXv.js";
@@ -25751,24 +25751,15 @@ async function OR(e) {
25751
25751
  }
25752
25752
  }
25753
25753
  var kR = /* @__PURE__ */ new Set([
25754
- "text/plain",
25755
- "text/csv",
25756
- "text/tab-separated-values",
25757
- "application/json",
25758
- "application/octet-stream",
25759
- "application/pdf",
25760
- "application/zip",
25761
- "application/gzip",
25762
- "image/png",
25763
- "image/jpeg",
25764
- "image/gif",
25765
- "image/webp",
25766
- "image/avif",
25767
- "image/bmp",
25768
- "image/x-icon"
25754
+ "text/html",
25755
+ "text/xml",
25756
+ "application/xml",
25757
+ "text/jscript",
25758
+ "text/livescript",
25759
+ "text/vbscript"
25769
25760
  ]);
25770
25761
  function AR(e) {
25771
- if (!e.trim()) return !1;
25762
+ if (typeof e != "string" || !e.trim()) return !1;
25772
25763
  try {
25773
25764
  let t = i_(e);
25774
25765
  switch (t.protocol) {
@@ -25779,7 +25770,7 @@ function AR(e) {
25779
25770
  let e = t.pathname.indexOf(",");
25780
25771
  if (e === -1) return !1;
25781
25772
  let n = t.pathname.slice(0, e).split(";", 1)[0].trim().toLowerCase();
25782
- return kR.has(n || "text/plain");
25773
+ return !n || /^[\w!#$%&'*+.^`|~-]+\/[\w!#$%&'*+.^`|~-]+$/.test(n) && !kR.has(n) && !/^(?:text|application)\/(?:x-)?(?:java|ecma)script(?:\d+(?:\.\d+)*)?$/.test(n) && !n.endsWith("+xml");
25783
25774
  }
25784
25775
  default: return !1;
25785
25776
  }
@@ -25790,11 +25781,20 @@ function AR(e) {
25790
25781
  function jR(e, t) {
25791
25782
  if (!AR(e)) throw Error("Unsupported download URL");
25792
25783
  let n = document.createElement("a");
25793
- n.href = e, n.download = t ?? "", n.click(), n.remove();
25784
+ n.href = e, n.download = t ?? "";
25785
+ try {
25786
+ n.click();
25787
+ } finally {
25788
+ n.remove();
25789
+ }
25794
25790
  }
25795
25791
  function MR(e, t) {
25796
25792
  let n = URL.createObjectURL(e);
25797
- jR(n, t), URL.revokeObjectURL(n);
25793
+ try {
25794
+ jR(n, t);
25795
+ } finally {
25796
+ URL.revokeObjectURL(n);
25797
+ }
25798
25798
  }
25799
25799
  function NR({ contents: e, filename: t, mediaType: n }) {
25800
25800
  MR(new Blob([e], { type: n }), t);
@@ -2,7 +2,7 @@ import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-sHtZdjeP.js";
3
3
  import { t as n } from "./react-dom-DUmH0GXv.js";
4
4
  import { c as r, l as i, u as a } from "./data-grid-types-0PJ-9N5n.js";
5
- import { a as o, i as s, n as c, r as l } from "./glide-data-editor-8CBjuK8C.js";
5
+ import { a as o, i as s, n as c, r as l } from "./glide-data-editor-CORsDYy3.js";
6
6
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/internal/data-grid-overlay-editor/data-grid-overlay-editor-style.js
7
7
  var u = /* @__PURE__ */ e(t(), 1), d = /* @__PURE__ */ e(n(), 1), f = /*#__PURE__*/ o("div")({
8
8
  name: "DataGridOverlayEditorStyle",
@@ -4,13 +4,13 @@ import { t as r } from "./react-sHtZdjeP.js";
4
4
  import { t as i } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { t as a } from "./copy-icon-CG57cxwb.js";
6
6
  import { A as o, E as s, I as c, K as l, P as u, T as d, i as f, n as p, zt as m } from "./error-entries-CRPfxMqm.js";
7
- import { n as h, t as ee } from "./globals-M9WsksQz.js";
7
+ import { n as h, t as ee } from "./globals-B3f1L5ta.js";
8
8
  import { t as g } from "./strings-BGW-fXVJ.js";
9
9
  import { t as _ } from "./jsx-runtime-3BD1kT0s.js";
10
10
  import { l as te, r as v, x as ne } from "./utils-DXkj82sK.js";
11
11
  import { a as re, i as ie, n as ae, r as oe } from "./dialog-DsZ49mmU.js";
12
12
  import { t as se } from "./useAsyncData-DsZMvNXn.js";
13
- import { t as ce } from "./code-visibility-CIUgREo9.js";
13
+ import { t as ce } from "./code-visibility-B955Xe77.js";
14
14
  //#region src/components/ui/skeleton.tsx
15
15
  var y = /* @__PURE__ */ e(r(), 1), b = i(), x = _(), le = (e) => {
16
16
  let n = (0, b.c)(8), r, i;
@@ -6,7 +6,7 @@ import { i as s, n as c, r as l } from "./copy-icon-CG57cxwb.js";
6
6
  import { c as u, d, i as f, n as p, s as m, t as h } from "./select-BSxlITBo.js";
7
7
  import { d as g, h as _, i as v, l as y, n as b, o as x, q as S, s as C, t as w, u as T } from "./dropdown-menu-BRiE7Vnp.js";
8
8
  import { c as E, d as D, l as O, n as k, o as A, s as ee, t as j, u as te } from "./glide-utils-CQddGpa-.js";
9
- import { n as ne, t as re } from "./ErrorBoundary-DKniGLW9.js";
9
+ import { n as ne, t as re } from "./ErrorBoundary-DiPu-nOq.js";
10
10
  import { i as ie, n as M } from "./strings-BGW-fXVJ.js";
11
11
  import { t as N } from "./react-dom-DUmH0GXv.js";
12
12
  import { t as P } from "./jsx-runtime-3BD1kT0s.js";
@@ -7062,7 +7062,7 @@ function rs(e, t, n, r, i) {
7062
7062
  }
7063
7063
  //#endregion
7064
7064
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/data-editor/data-editor.js
7065
- var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-PstJqwhX.js")), ss = 0;
7065
+ var is = /* @__PURE__ */ e(_r(), 1), as = /* @__PURE__ */ e(xr(), 1), os = K.lazy(async () => await import("./data-grid-overlay-editor-BUnD6AGE.js")), ss = 0;
7066
7066
  function cs(e) {
7067
7067
  return (0, is.default)((0, as.default)((0, as.default)(e).filter((e) => e.span !== void 0).map((e) => (0, Za.default)((e.span?.[0] ?? 0) + 1, (e.span?.[1] ?? 0) + 1))));
7068
7068
  }
@@ -9293,7 +9293,7 @@ function Vs(e, t, n, r, i) {
9293
9293
  }
9294
9294
  //#endregion
9295
9295
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/cells/number-cell.js
9296
- var Hs = K.lazy(async () => await import("./number-overlay-editor-uvNY9IUz.js")), Us = {
9296
+ var Hs = K.lazy(async () => await import("./number-overlay-editor-B5LIxGos.js")), Us = {
9297
9297
  getAccessibilityString: (e) => e.data?.toString() ?? "",
9298
9298
  kind: W.Number,
9299
9299
  needsHover: (e) => e.hoverEffect === !0,
@@ -1,6 +1,6 @@
1
1
  import { m as e } from "./tooltip-C3UnvsRe.js";
2
2
  import { l as t } from "./utils-DXkj82sK.js";
3
- import { r as n } from "./code-visibility-CIUgREo9.js";
3
+ import { r as n } from "./code-visibility-B955Xe77.js";
4
4
  var r = e("triangle-alert", [
5
5
  ["path", {
6
6
  d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
package/dist/main.js CHANGED
@@ -6,7 +6,7 @@ import { i as x, n as S, r as C, t as w } from "./copy-icon-CG57cxwb.js";
6
6
  import { $ as T, A as E, At as D, B as O, Bt as k, Ct as A, F as j, H as M, Ht as N, I as P, It as F, Kt as I, M as L, Nt as R, Ot as z, Pt as B, Q as ee, R as te, Rt as ne, St as re, Tt as ie, U as ae, Ut as oe, V as se, Vt as ce, W as le, Wt as ue, Z as de, _ as fe, _t as pe, a as me, at as he, b as ge, bt as _e, c as ve, et as ye, ft as be, i as xe, it as Se, jt as Ce, kt as we, mt as Te, n as Ee, nt as De, o as Oe, pt as ke, qt as Ae, tt as je, v as Me, w as Ne, x as Pe, xt as Fe, y as Ie, z as Le, zt as Re } from "./html-to-image-Gx4q3ZoD.js";
7
7
  import { a as ze, d as Be, i as Ve, m as He, n as Ue, o as We, p as Ge, r as Ke, t as qe } from "./tooltip-C3UnvsRe.js";
8
8
  import { D as Je, E as Ye, O as Xe, S as Ze, T as Qe, _ as $e, a as et, c as tt, d as nt, f as rt, g as it, h as at, i as ot, l as st, m as ct, n as lt, o as ut, p as dt, r as ft, s as pt, t as mt, u as ht, v as gt, w as _t, x as vt, y as yt } from "./spec-Dq8RNplp.js";
9
- import { $t as bt, A as xt, At as St, B as Ct, Bt as wt, C as Tt, Ct as Et, D as Dt, Dt as Ot, E as kt, Et as At, F as jt, Ft as Mt, G as Nt, Gt as Pt, H as Ft, Ht as It, I as Lt, It as Rt, J as zt, Jt as Bt, K as Vt, Kt as Ht, L as Ut, Lt as Wt, M as Gt, Mt as Kt, N as qt, Nt as Jt, O as Yt, Ot as Xt, P as Zt, Pt as Qt, Qt as $t, R as en, Rt as tn, S as nn, T as rn, Tt as an, U as on, Ut as sn, V as cn, Vt as ln, W as un, Wt as dn, X as fn, Xt as pn, Y as mn, Yt as hn, Z as gn, Zt as _n, _ as vn, _t as yn, an as bn, at as xn, b as Sn, bt as Cn, c as wn, cn as Tn, ct as En, d as Dn, dn as On, dt as kn, en as An, f as jn, fn as Mn, ft as Nn, g as Pn, gn as Fn, gt as In, h as Ln, hn as Rn, ht as zn, in as Bn, it as Vn, j as Hn, jt as Un, k as Wn, kt as Gn, ln as Kn, lt as qn, m as Jn, mn as Yn, mt as Xn, nn as Zn, nt as Qn, on as $n, ot as er, p as tr, pn as nr, pt as rr, q as ir, qt as ar, r as or, rn as sr, rt as cr, st as lr, t as ur, tn as dr, tt as fr, u as pr, un as mr, ut as hr, v as gr, vt as _r, w as vr, wt as yr, x as br, y as xr, yt as Sr, z as Cr, zt as wr } from "./common-DzCPFBsv.js";
9
+ import { $t as bt, A as xt, At as St, B as Ct, Bt as wt, C as Tt, Ct as Et, D as Dt, Dt as Ot, E as kt, Et as At, F as jt, Ft as Mt, G as Nt, Gt as Pt, H as Ft, Ht as It, I as Lt, It as Rt, J as zt, Jt as Bt, K as Vt, Kt as Ht, L as Ut, Lt as Wt, M as Gt, Mt as Kt, N as qt, Nt as Jt, O as Yt, Ot as Xt, P as Zt, Pt as Qt, Qt as $t, R as en, Rt as tn, S as nn, T as rn, Tt as an, U as on, Ut as sn, V as cn, Vt as ln, W as un, Wt as dn, X as fn, Xt as pn, Y as mn, Yt as hn, Z as gn, Zt as _n, _ as vn, _t as yn, an as bn, at as xn, b as Sn, bt as Cn, c as wn, cn as Tn, ct as En, d as Dn, dn as On, dt as kn, en as An, f as jn, fn as Mn, ft as Nn, g as Pn, gn as Fn, gt as In, h as Ln, hn as Rn, ht as zn, in as Bn, it as Vn, j as Hn, jt as Un, k as Wn, kt as Gn, ln as Kn, lt as qn, m as Jn, mn as Yn, mt as Xn, nn as Zn, nt as Qn, on as $n, ot as er, p as tr, pn as nr, pt as rr, q as ir, qt as ar, r as or, rn as sr, rt as cr, st as lr, t as ur, tn as dr, tt as fr, u as pr, un as mr, ut as hr, v as gr, vt as _r, w as vr, wt as yr, x as br, y as xr, yt as Sr, z as Cr, zt as wr } from "./common-CivG9Zso.js";
10
10
  import { a as Tr, n as Er, s as Dr, t as Or } from "./useLifecycle-BquH9ET-.js";
11
11
  import { t as kr } from "./check-Z_vtI3OL.js";
12
12
  import { A as Ar, C as jr, D as Mr, M as Nr, O as Pr, a as Fr, c as Ir, d as Lr, i as Rr, k as zr, l as Br, n as Vr, o as Hr, r as Ur, s as Wr, t as Gr, w as Kr, x as qr } from "./select-BSxlITBo.js";
@@ -15,8 +15,8 @@ import { c as Di, i as Oi, l as ki, o as Ai, s as ji, t as Mi } from "./config-D
15
15
  import { A as Ni, At as Pi, B as Fi, G as Ii, It as Li, J as Ri, K as zi, N as Bi, Nt as Vi, Ot as Hi, Pt as Ui, R as Wi, St as Gi, T as Ki, Tt as qi, V as Ji, X as Yi, Y as Xi, Z as Zi, _ as Qi, at as $i, c as ea, ct as ta, d as na, g as ra, h as ia, jt as aa, k as oa, kt as sa, lt as ca, m as la, ot as ua, p as da, q as fa, s as pa, ut as ma, xt as ha, z as ga } from "./error-entries-CRPfxMqm.js";
16
16
  import { a as _a, c as va, d as ya, f as ba, i as xa, l as Sa, n as Ca, o as wa, r as Ta, s as Ea, t as Da } from "./process-output-D2ISIyIs.js";
17
17
  import { a as Oa, c as ka, d as Aa, i as ja, l as Ma, r as Na, u as Pa } from "./glide-utils-CQddGpa-.js";
18
- import { n as Fa, t as Ia } from "./ErrorBoundary-DKniGLW9.js";
19
- import { n as La, t as Ra } from "./globals-M9WsksQz.js";
18
+ import { n as Fa, t as Ia } from "./ErrorBoundary-DiPu-nOq.js";
19
+ import { n as La, t as Ra } from "./globals-B3f1L5ta.js";
20
20
  import { a as za, i as Ba, n as Va, r as Ha, s as Ua, t as Wa } from "./strings-BGW-fXVJ.js";
21
21
  import { t as Ga } from "./react-dom-DUmH0GXv.js";
22
22
  import { t as Ka } from "./jsx-runtime-3BD1kT0s.js";
@@ -44,7 +44,7 @@ import { t as Hs } from "./useAsyncData-DsZMvNXn.js";
44
44
  import { t as Us } from "./semaphore-89jsoHtS.js";
45
45
  import { D as Ws, O as Gs } from "./vega-loader.browser-B9Pz0EGP.js";
46
46
  import { a as Ks, n as qs } from "./loader-BisjOLiW.js";
47
- import { c as Js, d as Ys, i as Xs, l as Zs, o as Qs, s as $s, t as ec, u as tc } from "./code-visibility-CIUgREo9.js";
47
+ import { c as Js, d as Ys, i as Xs, l as Zs, o as Qs, s as $s, t as ec, u as tc } from "./code-visibility-B955Xe77.js";
48
48
  import { t as nc } from "./useDeepCompareMemoize-KMBBux8C.js";
49
49
  import { t as rc } from "./esm-BgKjMvWw.js";
50
50
  //#region ../node_modules/.pnpm/iconify-icon@2.3.0/node_modules/iconify-icon/dist/iconify-icon.mjs
@@ -12406,7 +12406,7 @@ function _D(e, t) {
12406
12406
  }
12407
12407
  //#endregion
12408
12408
  //#region src/plugins/impl/DataEditorPlugin.tsx
12409
- var vD = J.lazy(() => import("./glide-data-editor-8CBjuK8C.js").then((e) => e.t)), yD = eE("marimo-data-editor", { cssStyles: [CE] }).withData(G({
12409
+ var vD = J.lazy(() => import("./glide-data-editor-CORsDYy3.js").then((e) => e.t)), yD = eE("marimo-data-editor", { cssStyles: [CE] }).withData(G({
12410
12410
  initialValue: G({ edits: K(G({
12411
12411
  rowIdx: W(),
12412
12412
  columnId: U(),
@@ -32194,7 +32194,7 @@ function vH(e) {
32194
32194
  }
32195
32195
  //#endregion
32196
32196
  //#region src/components/editor/renderers/slides-layout/slides-layout.tsx
32197
- var yH = J.lazy(() => import("./reveal-component-GMnfGiUU.js")), bH = (e) => {
32197
+ var yH = J.lazy(() => import("./reveal-component-DvM7Lxss.js")), bH = (e) => {
32198
32198
  let t = (0, X.c)(33), { layout: n, setLayout: r, cells: i, mode: a } = e, o = jo(Wo), s = a === "read" || o, c = jo(ha) > 1, [l, u] = (0, J.useState)(null), d;
32199
32199
  t[0] !== i || t[1] !== n ? (d = gR(i, n), t[0] = i, t[1] = n, t[2] = d) : d = t[2];
32200
32200
  let { slideCells: f, skippedIds: p, noOutputIds: m, slideTypes: h, startCellIndex: g } = d, _;
@@ -1,6 +1,6 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
2
  import { t } from "./react-sHtZdjeP.js";
3
- import { a as n } from "./glide-data-editor-8CBjuK8C.js";
3
+ import { a as n } from "./glide-data-editor-CORsDYy3.js";
4
4
  //#region ../node_modules/.pnpm/@glideapps+glide-data-grid@6.0.4-alpha24_lodash@4.17.21_marked@15.0.12_react-dom@19.3.0_27cffe7f1bc30287d59ac27db3240c5b/node_modules/@glideapps/glide-data-grid/dist/esm/internal/data-grid-overlay-editor/private/number-overlay-editor-style.js
5
5
  var r = /* @__PURE__ */ e(t()), i = /*#__PURE__*/ n("div")({
6
6
  name: "NumberOverlayEditorStyle",
@@ -3,7 +3,7 @@ import { c as t, g as n, h as r, m as i, t as a } from "./button-B6RjDKJx.js";
3
3
  import { t as o } from "./react-sHtZdjeP.js";
4
4
  import { t as s } from "./compiler-runtime-CldRdSsv.js";
5
5
  import { m as c, t as l } from "./tooltip-C3UnvsRe.js";
6
- import { $ as u, Q as d, et as f, i as p, l as m, n as h, on as g, r as _, sn as v, t as y, u as b, un as x } from "./common-DzCPFBsv.js";
6
+ import { $ as u, Q as d, et as f, i as p, l as m, n as h, on as g, r as _, sn as v, t as y, u as b, un as x } from "./common-CivG9Zso.js";
7
7
  import { M as S } from "./select-BSxlITBo.js";
8
8
  import { Y as ee } from "./dropdown-menu-BRiE7Vnp.js";
9
9
  import { Pt as C } from "./error-entries-CRPfxMqm.js";
@@ -11,7 +11,7 @@ import { t as w } from "./jsx-runtime-3BD1kT0s.js";
11
11
  import { r as T } from "./use-restore-focus-BWO0z1lo.js";
12
12
  import { D as E, t as D, x as O } from "./utils-DXkj82sK.js";
13
13
  import { o as k } from "./static-state-BldGd99T.js";
14
- import { a as A, n as te, t as ne } from "./code-visibility-CIUgREo9.js";
14
+ import { a as A, n as te, t as ne } from "./code-visibility-B955Xe77.js";
15
15
  /* empty css */
16
16
  var j = c("sticky-note", [["path", {
17
17
  d: "M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.3-dev244",
3
+ "version": "0.25.3-dev245",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -79,6 +79,11 @@ describe("DownloadPlugin", () => {
79
79
  { data: "data:text/plain,hello", filename: "loaded.txt" },
80
80
  { data: "", filename: "renamed.csv" },
81
81
  { data: "data:text/plain,hello", filename: null },
82
+ { data: "data:audio/x-wav;base64,AAA=", filename: "audio.wav" },
83
+ {
84
+ data: "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,AAA=",
85
+ filename: "results.xlsx",
86
+ },
82
87
  ])("downloads lazy data with metadata fallbacks: %j", async (loadedData) => {
83
88
  const load = vi.fn<Load>().mockResolvedValue(loadedData);
84
89
  const { button } = renderDownload({ lazy: true }, load);
@@ -93,6 +98,7 @@ describe("DownloadPlugin", () => {
93
98
  ]);
94
99
  });
95
100
  expect(load).toHaveBeenCalledExactlyOnceWith({});
101
+ expect(toast).not.toHaveBeenCalled();
96
102
  });
97
103
 
98
104
  it.each([false, true])("ignores disabled clicks (lazy=%s)", (lazy) => {
@@ -122,10 +128,13 @@ describe("DownloadPlugin", () => {
122
128
  },
123
129
  );
124
130
 
125
- it("validates the lazy response even when the initial URL is valid", async () => {
126
- const load = vi
127
- .fn<Load>()
128
- .mockResolvedValue({ data: "javascript:alert(1)" });
131
+ it.each([
132
+ "javascript:alert(1)",
133
+ "data:text/html,<h1>hello</h1>",
134
+ "data:image/svg+xml,<svg/>",
135
+ "data:application/x-javascript,alert(1)",
136
+ ])("validates the lazy response URL %s", async (data) => {
137
+ const load = vi.fn<Load>().mockResolvedValue({ data });
129
138
  const { button } = renderDownload({ lazy: true }, load);
130
139
  fireEvent.click(button);
131
140
 
@@ -11,6 +11,7 @@ import {
11
11
  downloadExportedFile,
12
12
  downloadHTMLAsImage,
13
13
  getImageDataUrlForCell,
14
+ isDownloadUrl,
14
15
  withLoadingToast,
15
16
  } from "../download";
16
17
 
@@ -616,9 +617,26 @@ describe("downloadByURL", () => {
616
617
  "DATA:TEXT/PLAIN;base64,aGVsbG8=",
617
618
  "data:application/json,%7B%7D",
618
619
  "data:application/octet-stream;base64,AAA=",
620
+ "data:audio/x-wav;base64,AAA=",
621
+ "data:AUDIO/MPEG;codecs=mp3;base64,AAA=",
622
+ "data:video/mp4;base64,AAA=",
623
+ "data:image/tiff;base64,AAA=",
624
+ "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,AAA=",
625
+ "data:application/vnd.ms-excel;base64,AAA=",
626
+ "data:application/vnd.apache.parquet;base64,AAA=",
627
+ "data:application/x-hdf5;base64,AAA=",
628
+ "data:application/x-custom-format;base64,AAA=",
629
+ "data:application/geo+json,%7B%7D",
630
+ "data:application/epub+zip;base64,AAA=",
631
+ "data:font/woff2;base64,AAA=",
632
+ "data:text/markdown;charset=utf-8,%23%20Title",
633
+ "data:application/pdf;base64,AAA=",
619
634
  "data:,hello",
620
635
  "data:;base64,aGVsbG8=",
621
636
  "data:text/plain,",
637
+ "data:text/plain,javascript:alert(1)",
638
+ "data:text/plain,hello?name=world#fragment",
639
+ "data:application/javascript-source,source%20code",
622
640
  " https://example.com/results.csv ",
623
641
  ])("downloads %s without an explicit filename", (url) => {
624
642
  downloadByURL(url);
@@ -644,6 +662,31 @@ describe("downloadByURL", () => {
644
662
  "data:image/svg+xml,<svg/>",
645
663
  "data:application/xhtml+xml,<html/>",
646
664
  "data:text/javascript,alert(1)",
665
+ "data:application/javascript;charset=utf-8,alert(1)",
666
+ "data:application/x-javascript;base64,AAA=",
667
+ "data:application/ecmascript,alert(1)",
668
+ "data:application/x-ecmascript,alert(1)",
669
+ "data:text/ecmascript,alert(1)",
670
+ "data:text/x-ecmascript,alert(1)",
671
+ "data:text/x-javascript,alert(1)",
672
+ "data:text/javascript1.0,alert(1)",
673
+ "data:text/javascript1.1,alert(1)",
674
+ "data:text/javascript1.2,alert(1)",
675
+ "data:text/javascript1.3,alert(1)",
676
+ "data:text/javascript1.4,alert(1)",
677
+ "data:text/javascript1.5,alert(1)",
678
+ "data:text/jscript,alert(1)",
679
+ "data:text/livescript,alert(1)",
680
+ "data:text/vbscript,msgbox(1)",
681
+ "data:text/xml,<root/>",
682
+ "data:application/xml,<root/>",
683
+ "data:IMAGE/SVG+XML;charset=utf-8;base64,AAA=",
684
+ "data:application/custom+xml,<root/>",
685
+ "data:invalid,hello",
686
+ "data:text/,hello",
687
+ "data:/plain,hello",
688
+ "data:text/pl ain,hello",
689
+ "data:text/plain/extra,hello",
647
690
  "data:text/plain",
648
691
  "https://[invalid",
649
692
  "",
@@ -654,28 +697,92 @@ describe("downloadByURL", () => {
654
697
  expect(mockAnchor.click).not.toHaveBeenCalled();
655
698
  });
656
699
 
657
- it("downloads an exported file with its returned metadata", async () => {
658
- let downloadedBlob: Blob | undefined;
659
- vi.stubGlobal(
660
- "URL",
661
- class extends URL {
662
- public static override createObjectURL = vi.fn((blob: Blob) => {
663
- downloadedBlob = blob;
664
- return "blob:export";
665
- });
666
- public static override revokeObjectURL = vi.fn();
667
- },
668
- );
669
-
670
- downloadExportedFile({
671
- contents: "notebook",
672
- filename: "résumé.qmd",
673
- mediaType: "text/plain; charset=utf-8",
674
- });
700
+ it.each(Array.from({ length: 33 }, (_, code) => code))(
701
+ "rejects a script scheme with leading ASCII character %i",
702
+ (code) => {
703
+ const url = `${String.fromCharCode(code)}JaVa\nScRi\tPt:alert(1)`;
704
+ expect(() => downloadByURL(url)).toThrow("Unsupported download URL");
705
+ expect(document.createElement).not.toHaveBeenCalled();
706
+ },
707
+ );
675
708
 
676
- expect(downloadedBlob?.type).toBe("text/plain; charset=utf-8");
677
- expect(await downloadedBlob?.text()).toBe("notebook");
678
- expect(mockAnchor.download).toBe("résumé.qmd");
679
- expect(URL.revokeObjectURL).toHaveBeenCalledWith("blob:export");
709
+ it.each([
710
+ "text/html",
711
+ "application/xhtml+xml",
712
+ "image/svg+xml",
713
+ "application/custom+xml",
714
+ "text/javascript1.4",
715
+ "text/javascript2.0",
716
+ "application/x-javascript2.0",
717
+ "text/ecmascript2026",
718
+ "text/livescript",
719
+ ])("rejects normalized and parameterized data MIME type %s", (mimeType) => {
720
+ const urls = [
721
+ `DATA:${mimeType.toUpperCase()},payload`,
722
+ `data: ${mimeType} ;charset=utf-8,payload`,
723
+ `data:${mimeType};charset="utf-8";base64,cGF5bG9hZA==`,
724
+ `da\tta:${mimeType};name=file.txt,payload?query#fragment`,
725
+ ];
726
+ for (const url of urls) {
727
+ expect(() => downloadByURL(url)).toThrow("Unsupported download URL");
728
+ }
729
+ expect(document.createElement).not.toHaveBeenCalled();
680
730
  });
731
+
732
+ it.each([
733
+ null,
734
+ undefined,
735
+ 42,
736
+ false,
737
+ {},
738
+ [],
739
+ new String("https://example.com"),
740
+ ])("rejects non-string input %j without throwing or coercing it", (url) => {
741
+ expect(isDownloadUrl(url)).toBe(false);
742
+ });
743
+
744
+ it.each([false, true])(
745
+ "releases exported files after a click (fails=%s)",
746
+ async (fails) => {
747
+ let downloadedBlob: Blob | undefined;
748
+ vi.stubGlobal(
749
+ "URL",
750
+ class extends URL {
751
+ public static override createObjectURL = vi.fn((blob: Blob) => {
752
+ downloadedBlob = blob;
753
+ return "blob:export";
754
+ });
755
+ public static override revokeObjectURL = vi.fn();
756
+ },
757
+ );
758
+
759
+ if (fails) {
760
+ vi.mocked(mockAnchor.click).mockImplementation(() => {
761
+ throw new Error("Download failed");
762
+ });
763
+ }
764
+ const download = () =>
765
+ downloadExportedFile({
766
+ contents: "notebook",
767
+ filename: "résumé.qmd",
768
+ mediaType: "text/plain; charset=utf-8",
769
+ });
770
+ let caughtError: unknown;
771
+ try {
772
+ download();
773
+ } catch (error) {
774
+ caughtError = error;
775
+ }
776
+
777
+ expect(caughtError).toEqual(
778
+ fails ? new Error("Download failed") : undefined,
779
+ );
780
+
781
+ expect(downloadedBlob?.type).toBe("text/plain; charset=utf-8");
782
+ expect(await downloadedBlob?.text()).toBe("notebook");
783
+ expect(mockAnchor.download).toBe("résumé.qmd");
784
+ expect(mockAnchor.remove).toHaveBeenCalledOnce();
785
+ expect(URL.revokeObjectURL).toHaveBeenCalledWith("blob:export");
786
+ },
787
+ );
681
788
  });
@@ -178,26 +178,18 @@ export async function downloadHTMLAsImage(opts: {
178
178
  }
179
179
  }
180
180
 
181
- const DOWNLOAD_DATA_TYPES = new Set([
182
- "text/plain",
183
- "text/csv",
184
- "text/tab-separated-values",
185
- "application/json",
186
- "application/octet-stream",
187
- "application/pdf",
188
- "application/zip",
189
- "application/gzip",
190
- "image/png",
191
- "image/jpeg",
192
- "image/gif",
193
- "image/webp",
194
- "image/avif",
195
- "image/bmp",
196
- "image/x-icon",
181
+ // mo.download supports arbitrary file formats, so a MIME allowlist is too restrictive.
182
+ const NON_DOWNLOAD_DATA_TYPES = new Set([
183
+ "text/html",
184
+ "text/xml",
185
+ "application/xml",
186
+ "text/jscript",
187
+ "text/livescript",
188
+ "text/vbscript",
197
189
  ]);
198
190
 
199
- export function isDownloadUrl(url: string): boolean {
200
- if (!url.trim()) {
191
+ export function isDownloadUrl(url: unknown): url is string {
192
+ if (typeof url !== "string" || !url.trim()) {
201
193
  return false;
202
194
  }
203
195
  try {
@@ -218,7 +210,18 @@ export function isDownloadUrl(url: string): boolean {
218
210
  .trim()
219
211
  .toLowerCase();
220
212
  // An omitted MIME type defaults to text/plain.
221
- return DOWNLOAD_DATA_TYPES.has(mimeType || "text/plain");
213
+ if (!mimeType) {
214
+ return true;
215
+ }
216
+ return (
217
+ /^[\w!#$%&'*+.^`|~-]+\/[\w!#$%&'*+.^`|~-]+$/.test(mimeType) &&
218
+ !NON_DOWNLOAD_DATA_TYPES.has(mimeType) &&
219
+ // Include versioned and x- aliases without enumerating each version.
220
+ !/^(?:text|application)\/(?:x-)?(?:java|ecma)script(?:\d+(?:\.\d+)*)?$/.test(
221
+ mimeType,
222
+ ) &&
223
+ !mimeType.endsWith("+xml")
224
+ );
222
225
  }
223
226
  default:
224
227
  return false;
@@ -235,14 +238,20 @@ export function downloadByURL(url: string, filename?: string) {
235
238
  const a = document.createElement("a");
236
239
  a.href = url;
237
240
  a.download = filename ?? "";
238
- a.click();
239
- a.remove();
241
+ try {
242
+ a.click();
243
+ } finally {
244
+ a.remove();
245
+ }
240
246
  }
241
247
 
242
248
  export function downloadBlob(blob: Blob, filename: string) {
243
249
  const url = URL.createObjectURL(blob);
244
- downloadByURL(url, filename);
245
- URL.revokeObjectURL(url);
250
+ try {
251
+ downloadByURL(url, filename);
252
+ } finally {
253
+ URL.revokeObjectURL(url);
254
+ }
246
255
  }
247
256
 
248
257
  export function downloadExportedFile({