@marimo-team/frontend 0.23.6-dev15 → 0.23.6-dev16

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.
Files changed (32) hide show
  1. package/dist/assets/{JsonOutput-BQaSLDBi.js → JsonOutput-vLKwARbP.js} +1 -1
  2. package/dist/assets/{MarimoErrorOutput-Dm4hVwDq.js → MarimoErrorOutput-BV73ko7W.js} +1 -1
  3. package/dist/assets/RenderHTML-Cv8cr_an.js +1 -0
  4. package/dist/assets/{add-connection-dialog-C3IbqmBw.js → add-connection-dialog-C3cn-x1B.js} +1 -1
  5. package/dist/assets/{agent-panel-fc1sKlOo.js → agent-panel-C-5MUkzV.js} +1 -1
  6. package/dist/assets/{cell-editor-Cf8hoAWZ.js → cell-editor-C33HDTDM.js} +1 -1
  7. package/dist/assets/{chat-display-Cmk2MWy-.js → chat-display-YfE-PieK.js} +1 -1
  8. package/dist/assets/{chat-panel-B9_sKM5C.js → chat-panel-CGR5FQXH.js} +1 -1
  9. package/dist/assets/{chat-ui-W3rV7Y85.js → chat-ui-CzB2bGbZ.js} +1 -1
  10. package/dist/assets/{column-preview-B1oiFlur.js → column-preview-z4x0_KlJ.js} +1 -1
  11. package/dist/assets/{command-palette-tORi89eP.js → command-palette-Ft577HZi.js} +1 -1
  12. package/dist/assets/{documentation-panel-Bi7B6BDD.js → documentation-panel-CL6z2pC-.js} +1 -1
  13. package/dist/assets/{edit-page-CrUPfrQN.js → edit-page-DTof11Ql.js} +3 -3
  14. package/dist/assets/{error-panel-Elx5tZAZ.js → error-panel-CrL_-c65.js} +1 -1
  15. package/dist/assets/{file-explorer-panel-omTFPhXg.js → file-explorer-panel-DxWjS8x0.js} +1 -1
  16. package/dist/assets/{form-CpNkZ10P.js → form-BeWsuyiN.js} +1 -1
  17. package/dist/assets/{hooks-dKyWh547.js → hooks-CenNRyn0.js} +1 -1
  18. package/dist/assets/{index-5vJlRIve.js → index-CMy5rqL5.js} +4 -4
  19. package/dist/assets/{layout-Cb89Nchy.js → layout-C0mYexWg.js} +3 -3
  20. package/dist/assets/{panels-KV8AsQsX.js → panels-C-FuTmb5.js} +1 -1
  21. package/dist/assets/{reveal-component-CBxtzgFZ.js → reveal-component-Dm1r-VqB.js} +1 -1
  22. package/dist/assets/{run-page-DIAemNxL.js → run-page-Bg9tp_B4.js} +1 -1
  23. package/dist/assets/{scratchpad-panel-C73QbV5j.js → scratchpad-panel-BTCY4gJu.js} +1 -1
  24. package/dist/assets/{session-panel-BAAW6R7U.js → session-panel-CQ0WCDPM.js} +1 -1
  25. package/dist/assets/{snippets-panel-roW3_D4d.js → snippets-panel-CYRWuEqZ.js} +1 -1
  26. package/dist/assets/{state-D5aL5woK.js → state-B1sEnd95.js} +1 -1
  27. package/dist/assets/{useNotebookActions-D6_uVA9-.js → useNotebookActions-C0IbJuzO.js} +1 -1
  28. package/dist/index.html +7 -7
  29. package/package.json +1 -1
  30. package/src/plugins/core/RenderHTML.tsx +49 -3
  31. package/src/plugins/core/__test__/RenderHTML.test.ts +54 -0
  32. package/dist/assets/RenderHTML-CA4tujDX.js +0 -1
@@ -60,6 +60,60 @@ describe("parseHtml", () => {
60
60
  `);
61
61
  });
62
62
 
63
+ test("img has key derived from src so React remounts on src change", () => {
64
+ const html = '<img src="https://cdn.example.com/a.png" alt="a">';
65
+ const result = parseHtml({ html }) as React.ReactElement;
66
+ expect(result.key).toBe("https://cdn.example.com/a.png-0");
67
+ });
68
+
69
+ test("multiple imgs each get distinct keys", () => {
70
+ const html =
71
+ '<div><img src="https://cdn.example.com/a.png"><img src="https://cdn.example.com/b.png"></div>';
72
+ const result = parseHtml({ html }) as React.ReactElement<{
73
+ children: React.ReactElement[];
74
+ }>;
75
+ const children = result.props.children;
76
+ expect(children[0].key).toBe("https://cdn.example.com/a.png-0");
77
+ expect(children[1].key).toBe("https://cdn.example.com/b.png-1");
78
+ });
79
+
80
+ test("img without src is left alone", () => {
81
+ const html = "<img>";
82
+ const result = parseHtml({ html }) as React.ReactElement;
83
+ expect(result.key).toBeNull();
84
+ });
85
+
86
+ test("img with data: URI is not keyed (inline, no network fetch)", () => {
87
+ const longPayload = "A".repeat(10_000);
88
+ const html = `<img src="data:image/png;base64,${longPayload}">`;
89
+ const result = parseHtml({ html }) as React.ReactElement;
90
+ // No remount-on-src needed for inline images, so we leave the key
91
+ // unset rather than bloat it with the base64 payload.
92
+ expect(result.key).toBeNull();
93
+ });
94
+
95
+ test("img with uppercase DATA: URI is also skipped (scheme is case-insensitive)", () => {
96
+ const html = `<img src="DATA:image/png;base64,${"A".repeat(100)}">`;
97
+ const result = parseHtml({ html }) as React.ReactElement;
98
+ expect(result.key).toBeNull();
99
+ });
100
+
101
+ test("img wrapped by data-tooltip is still keyed by src", () => {
102
+ const html =
103
+ '<img src="https://cdn.example.com/a.png" data-tooltip="hi" alt="a">';
104
+ const result = parseHtml({ html }) as React.ReactElement;
105
+ // Outer Tooltip carries the src-based key so it remounts on src change,
106
+ // forcing the inner <img> to remount as well.
107
+ expect(result.key).toBe("https://cdn.example.com/a.png-0");
108
+ });
109
+
110
+ test("img wrapped by data-marimo-doc is still keyed by src", () => {
111
+ const html =
112
+ '<img src="https://cdn.example.com/b.png" data-marimo-doc="foo.bar">';
113
+ const result = parseHtml({ html }) as React.ReactElement;
114
+ expect(result.key).toBe("https://cdn.example.com/b.png-0");
115
+ });
116
+
63
117
  test("codehilite with copy button", () => {
64
118
  const html =
65
119
  '<div class="codehilite"><pre><code>console.log("Hello");</code></pre></div>';
@@ -1 +0,0 @@
1
- import{s as x}from"./chunk-LvLJmgfZ.js";import{i as g,p as T,u as C}from"./useEvent-D91BmmQi.js";import{t as M}from"./react-Bj1aDYRI.js";import{Sn as H,ci as I,it as j,li as c,m as L,vn as N,yt as k}from"./cells-Jdt48eTG.js";import{t as E}from"./compiler-runtime-B3qBwwSJ.js";import{_ as w}from"./useEventListener-BR0C1MaI.js";import{o as _}from"./utils-DIGrmLDO.js";import{t as A}from"./jsx-runtime-BqBOg78p.js";import{t as F}from"./tooltip-Gcwqb_SK.js";import{t as O}from"./copy-icon-BYNydU7b.js";import{t as W}from"./usePress-CfcdTqJM.js";import{n as q}from"./useDebounce-CLMpJfhX.js";import{t as R}from"./useRunCells-BeRcytF8.js";var z=E(),m=x(M(),1),l=x(A(),1);const V=e=>{let t=(0,z.c)(16),r,n,i;t[0]===e?(r=t[1],n=t[2],i=t[3]):({href:n,children:r,...i}=e,t[0]=e,t[1]=r,t[2]=n,t[3]=i);let a=(0,m.useRef)(null),o;t[4]===n?o=t[5]:(o=()=>{let p=new URL(globalThis.location.href);p.hash=n,globalThis.history.pushState({},"",p.toString()),globalThis.dispatchEvent(new HashChangeEvent("hashchange"));let S=n.slice(1),y=document.getElementById(S);y&&y.scrollIntoView({behavior:"smooth",block:"start"})},t[4]=n,t[5]=o);let s=o,f;t[6]===s?f=t[7]:(f={onPress:()=>{s()}},t[6]=s,t[7]=f);let{pressProps:h}=W(f),u;t[8]===s?u=t[9]:(u=p=>{p.preventDefault(),s()},t[8]=s,t[9]=u);let b=u,d;return t[10]!==r||t[11]!==b||t[12]!==n||t[13]!==h||t[14]!==i?(d=(0,l.jsx)("a",{ref:a,href:n,...h,onClick:b,...i,children:r}),t[10]=r,t[11]=b,t[12]=n,t[13]=h,t[14]=i,t[15]=d):d=t[15],d};async function P(e){let t=L().inOrderIds.at(0);if(t)try{let r=await N.request({document:e,cellId:t});if(!r||r.options.length===0)return;let n=e.split(".").pop()??e,i=r.options[0],a=r.options.find(o=>o.name===n)??i;a!=null&&a.completion_info&&g.set(H,{documentation:a.completion_info})}catch(r){w.debug(`Doc lookup failed for "${e}"`,r)}}var D=E();const $=e=>{let t=(0,D.c)(8),{qualifiedName:r,children:n}=e,i;t[0]===r?i=t[1]:(i=()=>{P(r)},t[0]=r,t[1]=i);let a=q(i,100),o;t[2]===a?o=t[3]:(o=()=>a.cancel(),t[2]=a,t[3]=o);let s;return t[4]!==n||t[5]!==a||t[6]!==o?(s=(0,l.jsx)("span",{onMouseEnter:a,onMouseLeave:o,children:n}),t[4]=n,t[5]=a,t[6]=o,t[7]=s):s=t[7],s};function B(e){if(typeof e!="object"||!e)return!1;let t=e;return!(t.trusted!==!0||t.notebookCode!==void 0&&typeof t.notebookCode!="string")}function U(){let e=window==null?void 0:window.__MARIMO_EXPORT_CONTEXT__;return B(e)?e:void 0}function v(){var e;return((e=U())==null?void 0:e.trusted)===!0}function X(){if(g.get(R)||v()||g.get(_))return!0;try{if(j()==="read")return!0}catch{}return!1}var G=T(e=>{let t=e(R),r=e(_);if(t||r||v())return!1;let n=!0;try{n=j()==="read"}catch{return!0}return!n});function K(){return C(G)}var Z=E(),J=e=>{if(e instanceof c.Element&&!/^[A-Za-z][\w-]*$/.test(e.name))return m.createElement(m.Fragment)},Q=(e,t)=>{if(t instanceof c.Element&&t.name==="body"){if((0,m.isValidElement)(e)&&"props"in e){let r=e.props.children;return(0,l.jsx)(l.Fragment,{children:r})}return}},Y=(e,t)=>{if(t instanceof c.Element&&t.name==="html"){if((0,m.isValidElement)(e)&&"props"in e){let r=e.props.children;return(0,l.jsx)(l.Fragment,{children:r})}return}},tt=e=>{if(e instanceof c.Element&&e.attribs&&e.name==="iframe"){let t=document.createElement("iframe");return Object.entries(e.attribs).forEach(([r,n])=>{r.startsWith('"')&&r.endsWith('"')&&(r=r.slice(1,-1)),t.setAttribute(r,n)}),(0,l.jsx)("div",{dangerouslySetInnerHTML:{__html:t.outerHTML}})}},et=e=>{if(e instanceof c.Element&&e.name==="script"){let t=e.attribs.src;if(!t)return;if(!X())return w.warn(`[RenderHTML] refusing <script src> in untrusted context: ${t}`),(0,l.jsx)(l.Fragment,{});if(![...document.querySelectorAll("script[src]")].some(r=>r.getAttribute("src")===t)){let r=document.createElement("script");r.src=t,document.head.append(r)}return(0,l.jsx)(l.Fragment,{})}},rt=(e,t)=>{if(t instanceof c.Element&&t.name==="a"){let r=t.attribs.href;if(r!=null&&r.startsWith("#")&&!r.startsWith("#code/")){let n=null;return(0,m.isValidElement)(e)&&"props"in e&&(n=e.props.children),(0,l.jsx)(V,{href:r,...t.attribs,children:n})}}},nt=(e,t,r)=>{var n,i;if(t instanceof c.Element&&t.name==="div"&&((i=(n=t.attribs)==null?void 0:n.class)!=null&&i.includes("codehilite")))return(0,l.jsx)(ot,{children:e},r)},it=(e,t)=>{var r;if(t instanceof c.Element&&((r=t.attribs)!=null&&r["data-marimo-doc"])){let n=t.attribs["data-marimo-doc"];return(0,l.jsx)($,{qualifiedName:n,children:e})}},at=(e,t)=>{var r,n;if(t instanceof c.Element&&((r=t.attribs)!=null&&r["data-tooltip"])){if((((n=t.name)==null?void 0:n.toLowerCase())??"").startsWith("marimo-"))return;let i=t.attribs["data-tooltip"];return(0,l.jsx)(F,{content:i,children:e})}},ot=e=>{let t=(0,Z.c)(3),{children:r}=e,n=(0,m.useRef)(null),i;t[0]===Symbol.for("react.memo_cache_sentinel")?(i=(0,l.jsx)("div",{className:"absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity",children:(0,l.jsx)(O,{tooltip:!1,className:"p-1",value:()=>{var s;let o=(s=n.current)==null?void 0:s.firstChild;return o&&o.textContent||""}})}),t[0]=i):i=t[0];let a;return t[1]===r?a=t[2]:(a=(0,l.jsxs)("div",{className:"relative group codehilite-wrapper",ref:n,children:[r,i]}),t[1]=r,t[2]=a),a};const st=({html:e,additionalReplacements:t=[],alwaysSanitizeHtml:r=!0})=>(0,l.jsx)(lt,{html:e,alwaysSanitizeHtml:r,additionalReplacements:t});var lt=({html:e,additionalReplacements:t=[],alwaysSanitizeHtml:r})=>{let n=K();return ct({html:(0,m.useMemo)(()=>r||n?k(e):e,[e,r,n]),additionalReplacements:t})};function ct({html:e,additionalReplacements:t=[]}){let r=[J,tt,et,...t],n=[nt,rt,it,at,Q,Y];return I(e,{replace:(i,a)=>{for(let o of r){let s=o(i,a);if(s)return s}return i},transform:(i,a,o)=>{for(let s of n){let f=s(i,a,o);if(f)return f}return i}})}export{v as n,st as t};