@marimo-team/islands 0.20.3-dev91 → 0.20.3-dev94

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
@@ -32103,6 +32103,13 @@ ${c.sqlString}
32103
32103
  svg: true,
32104
32104
  mathMl: true
32105
32105
  },
32106
+ ADD_TAGS: [
32107
+ "use"
32108
+ ],
32109
+ ADD_ATTR: [
32110
+ "href",
32111
+ "xlink:href"
32112
+ ],
32106
32113
  FORCE_BODY: true,
32107
32114
  CUSTOM_ELEMENT_HANDLING: {
32108
32115
  tagNameCheck: /^(marimo-[A-Za-z][\w-]*|iconify-icon)$/,
@@ -70351,7 +70358,7 @@ Image URL: ${r.imageUrl}`)), contextToXml({
70351
70358
  return Logger.warn("Failed to get version from mount config"), null;
70352
70359
  }
70353
70360
  }
70354
- const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.3-dev91"), showCodeInRunModeAtom = atom(true);
70361
+ const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.3-dev94"), showCodeInRunModeAtom = atom(true);
70355
70362
  atom(null);
70356
70363
  var import_compiler_runtime$88 = require_compiler_runtime();
70357
70364
  function useKeydownOnElement(e, r) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.20.3-dev91",
3
+ "version": "0.20.3-dev94",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -13,6 +13,7 @@ import {
13
13
  FileSpreadsheetIcon,
14
14
  FileTextIcon,
15
15
  FileVideoIcon,
16
+ GithubIcon,
16
17
  GlobeIcon,
17
18
  HardDriveIcon,
18
19
  ImageIcon,
@@ -66,6 +67,7 @@ const PROTOCOL_ICONS: Record<KnownStorageProtocol, IconEntry> = {
66
67
  http: GlobeIcon,
67
68
  file: HardDriveIcon,
68
69
  "in-memory": DatabaseZapIcon,
70
+ github: GithubIcon,
69
71
  };
70
72
 
71
73
  export const ProtocolIcon: React.FC<{
@@ -70,7 +70,7 @@ describe("notebookStateFromSession", () => {
70
70
  cells: SessionCell[],
71
71
  ): api.Session["NotebookSessionV1"] => ({
72
72
  version: "1",
73
- metadata: { marimo_version: "1" },
73
+ metadata: { marimo_version: "1", script_metadata_hash: null },
74
74
  cells,
75
75
  });
76
76
 
@@ -54,4 +54,5 @@ export type KnownStorageProtocol =
54
54
  | "cloudflare"
55
55
  | "http"
56
56
  | "file"
57
- | "in-memory";
57
+ | "in-memory"
58
+ | "github";
@@ -288,9 +288,54 @@ describe("sanitizeHtml", () => {
288
288
  expect(sanitizeHtml(html)).toMatchInlineSnapshot(`"<div>Text</div>"`);
289
289
  });
290
290
 
291
- test("removes use element from SVG", () => {
291
+ test("preserves use element in SVG", () => {
292
292
  const html = '<svg><use xlink:href="#icon"></use></svg>';
293
- expect(sanitizeHtml(html)).toMatchInlineSnapshot(`"<svg></svg>"`);
293
+ expect(sanitizeHtml(html)).toMatchInlineSnapshot(
294
+ `"<svg><use xlink:href="#icon"></use></svg>"`,
295
+ );
296
+ });
297
+
298
+ test("preserves SVG defs and use pattern", () => {
299
+ const html = [
300
+ '<svg width="60" height="60">',
301
+ '<circle cx="30" cy="30" r="30" fill="orange"></circle>',
302
+ '<defs><circle id="myCircle" cx="0" cy="0" r="10" fill="green"></circle></defs>',
303
+ '<use href="#myCircle" x="20" y="20"></use>',
304
+ "</svg>",
305
+ ].join("");
306
+ expect(sanitizeHtml(html)).toMatchInlineSnapshot(
307
+ `"<svg width="60" height="60"><circle cx="30" cy="30" r="30" fill="orange"></circle><defs><circle id="myCircle" cx="0" cy="0" r="10" fill="green"></circle></defs><use href="#myCircle" x="20" y="20"></use></svg>"`,
308
+ );
309
+ });
310
+
311
+ test("strips javascript: href from SVG use element", () => {
312
+ const html = '<svg><use href="javascript:alert(1)"></use></svg>';
313
+ expect(sanitizeHtml(html)).toMatchInlineSnapshot(
314
+ `"<svg><use></use></svg>"`,
315
+ );
316
+ });
317
+
318
+ test("strips javascript: xlink:href from SVG use element", () => {
319
+ const html = '<svg><use xlink:href="javascript:alert(1)"></use></svg>';
320
+ expect(sanitizeHtml(html)).toMatchInlineSnapshot(
321
+ `"<svg><use></use></svg>"`,
322
+ );
323
+ });
324
+
325
+ test("preserves external href on SVG use element", () => {
326
+ const html =
327
+ '<svg><use href="https://example.com/sprite.svg#icon"></use></svg>';
328
+ expect(sanitizeHtml(html)).toMatchInlineSnapshot(
329
+ `"<svg><use href="https://example.com/sprite.svg#icon"></use></svg>"`,
330
+ );
331
+ });
332
+
333
+ test("preserves external xlink:href on SVG use element", () => {
334
+ const html =
335
+ '<svg><use xlink:href="https://example.com/sprite.svg#icon"></use></svg>';
336
+ expect(sanitizeHtml(html)).toMatchInlineSnapshot(
337
+ `"<svg><use xlink:href="https://example.com/sprite.svg#icon"></use></svg>"`,
338
+ );
294
339
  });
295
340
 
296
341
  test("removes javascript in SVG href", () => {
@@ -74,6 +74,10 @@ export function sanitizeHtml(html: string) {
74
74
  const sanitizationOptions: Config = {
75
75
  // Default to permit HTML, SVG and MathML, this limits to HTML only
76
76
  USE_PROFILES: { html: true, svg: true, mathMl: true },
77
+ // Allow SVG <use> elements and their href attributes, which are needed
78
+ // for SVGs that reference <defs> (e.g., Matplotlib SVG output).
79
+ ADD_TAGS: ["use"],
80
+ ADD_ATTR: ["href", "xlink:href"],
77
81
  // glue elements like style, script or others to document.body and prevent unintuitive browser behavior in several edge-cases
78
82
  FORCE_BODY: true,
79
83
  CUSTOM_ELEMENT_HANDLING: {