@marimo-team/islands 0.24.1-dev29 → 0.24.1-dev30

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.
@@ -36337,7 +36337,7 @@ ${d}`,
36337
36337
  return Logger.warn("Failed to get version from mount config"), null;
36338
36338
  }
36339
36339
  }
36340
- marimoVersionAtom = atom(getVersionFromMountConfig() || "0.24.1-dev29");
36340
+ marimoVersionAtom = atom(getVersionFromMountConfig() || "0.24.1-dev30");
36341
36341
  showCodeInRunModeAtom = atom(true);
36342
36342
  atom(null);
36343
36343
  var import_compiler_runtime = require_compiler_runtime();
package/dist/main.js CHANGED
@@ -26,7 +26,7 @@ import { $ as notebookOutline, $t as isUninstantiated, A as ChevronDownIcon, An
26
26
  import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-BRZ_XYUw.js";
27
27
  import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist-j30bBjjN.js";
28
28
  import { A as SquareFunction, C as DEFAULT_COLOR_SCHEME, D as SCALE_TYPE_DESCRIPTIONS, E as EMPTY_VALUE$1, O as TIME_UNIT_DESCRIPTIONS, S as DEFAULT_AGGREGATION, T as DEFAULT_TIME_UNIT, _ as AGGREGATION_TYPE_DESCRIPTIONS, a as AGGREGATION_FNS, b as COLOR_SCHEMES, c as COLOR_BY_FIELDS, d as NONE_VALUE, f as SELECTABLE_DATA_TYPES, g as TIME_UNITS, h as STRING_AGGREGATION_FNS, i as convertDataTypeToSelectable, j as ChartColumn, k as escapeFieldName, l as COMBINED_TIME_UNITS, m as SORT_TYPES, n as createSpecWithoutData, o as BIN_AGGREGATION, p as SINGLE_TIME_UNITS, r as isFieldSet, s as CHART_TYPES, t as augmentSpecWithData, u as ChartType, v as AGGREGATION_TYPE_ICON, w as DEFAULT_MAX_BINS_FACET, x as COUNT_FIELD, y as CHART_TYPE_ICON } from "./spec-DR1CyTOo.js";
29
- import { $ as CommandSeparator, $t as Kbd, A as ErrorState, At as getPageIndexForRow, B as ContextMenuTrigger, Bt as dateToLocalISODate, C as downloadHTMLAsImage, Ct as inferFieldTypes, D as ColumnName, Dt as DelayMount, E as downloadSizeLimitAtom, Et as ColumnChartSpecModel, F as getUserColumnVisibilityCounts, Ft as TOO_MANY_ROWS, G as DateRangePicker, Gt as TabsList, H as useSelectList, Ht as dateToLocalISOTime, I as ContextMenu, It as toFieldTypes, J as Command, Jt as ChartInfoState, K as Combobox, Kt as TabsTrigger, L as ContextMenuContent, Lt as getMimeValues, M as prettifyRowColumnCount, Mt as loadTableData, N as prettifyRowCount, Nt as INDEX_COLUMN_NAME, O as ColumnPreviewContainer, Ot as useIntersectionObserver, P as getColumnCountForDisplay, Pt as SELECT_COLUMN_ID, Q as CommandList, Qt as RenderTextWithLinks, R as ContextMenuItem, Rt as isNullishFilter, S as downloadExportedFile, St as generateColumns, T as Filenames, Tt as ColumnChartContext, U as CompactChipRow, Ut as Tabs, V as useInternalStateWithSync, Vt as dateToLocalISODateTime, W as DatePicker, Wt as TabsContent, X as CommandInput, Xt as LazyVegaEmbed, Y as CommandEmpty, Yt as ChartLoadingState, Z as CommandItem, Zt as useOverflowDetection, _ as DataTable, _n as ChevronLeft, _t as TableCell, an as TextWrap, at as contextAwarePanelType, b as downloadBlob, bt as TableRow, c as SLIDE_TYPE_OPTIONS_BY_VALUE, cn as EyeOff, ct as slotsController, d as Switch, dn as Download, en as HtmlOutput, et as smartMatch, f as RadioGroup, fn as Code, g as OutputRenderer, gn as ChevronsDownUp, gt as TableBody, h as OutputArea, hn as ChevronsLeft, ht as Table, i as showCodeInRunModeAtom, in as $fae977aafc393c5c$export$6b862160d295c8e, it as contextAwarePanelOwner, j as LoadingState, jt as loadTableAndRawData, k as EmptyState, kt as usePrevious$1, lt as Toggle, m as JsonOutput, mn as ChevronsRight, mt as Provider$1, n as useNotebookCodeAvailable, nn as safeLocale, nt as PANEL_TYPES, on as GripHorizontal, ot as isCellAwareAtom, p as RadioGroupItem, pn as ChevronsUpDown, pt as Fill, q as ComboboxItem, qt as ChartErrorState, r as marimoVersionAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelOpen, sn as Funnel, st as SlotNames, t as cellDomProps, tn as EmotionCacheProvider, tt as ContextAwarePanelItem, u as Slide, un as Ellipsis, v as InstallPackageButton, vn as ArrowDownWideNarrow, vt as TableHead, w as Progress, wt as renderCellValue, x as downloadByURL, xt as NAMELESS_COLUMN_PREFIX, y as ADD_PRINTING_CLASS, yt as TableHeader, z as ContextMenuSeparator, zt as Maps, __tla as __tla_2 } from "./common-DWZbOZtC.js";
29
+ import { $ as CommandSeparator, $t as Kbd, A as ErrorState, At as getPageIndexForRow, B as ContextMenuTrigger, Bt as dateToLocalISODate, C as downloadHTMLAsImage, Ct as inferFieldTypes, D as ColumnName, Dt as DelayMount, E as downloadSizeLimitAtom, Et as ColumnChartSpecModel, F as getUserColumnVisibilityCounts, Ft as TOO_MANY_ROWS, G as DateRangePicker, Gt as TabsList, H as useSelectList, Ht as dateToLocalISOTime, I as ContextMenu, It as toFieldTypes, J as Command, Jt as ChartInfoState, K as Combobox, Kt as TabsTrigger, L as ContextMenuContent, Lt as getMimeValues, M as prettifyRowColumnCount, Mt as loadTableData, N as prettifyRowCount, Nt as INDEX_COLUMN_NAME, O as ColumnPreviewContainer, Ot as useIntersectionObserver, P as getColumnCountForDisplay, Pt as SELECT_COLUMN_ID, Q as CommandList, Qt as RenderTextWithLinks, R as ContextMenuItem, Rt as isNullishFilter, S as downloadExportedFile, St as generateColumns, T as Filenames, Tt as ColumnChartContext, U as CompactChipRow, Ut as Tabs, V as useInternalStateWithSync, Vt as dateToLocalISODateTime, W as DatePicker, Wt as TabsContent, X as CommandInput, Xt as LazyVegaEmbed, Y as CommandEmpty, Yt as ChartLoadingState, Z as CommandItem, Zt as useOverflowDetection, _ as DataTable, _n as ChevronLeft, _t as TableCell, an as TextWrap, at as contextAwarePanelType, b as downloadBlob, bt as TableRow, c as SLIDE_TYPE_OPTIONS_BY_VALUE, cn as EyeOff, ct as slotsController, d as Switch, dn as Download, en as HtmlOutput, et as smartMatch, f as RadioGroup, fn as Code, g as OutputRenderer, gn as ChevronsDownUp, gt as TableBody, h as OutputArea, hn as ChevronsLeft, ht as Table, i as showCodeInRunModeAtom, in as $fae977aafc393c5c$export$6b862160d295c8e, it as contextAwarePanelOwner, j as LoadingState, jt as loadTableAndRawData, k as EmptyState, kt as usePrevious$1, lt as Toggle, m as JsonOutput, mn as ChevronsRight, mt as Provider$1, n as useNotebookCodeAvailable, nn as safeLocale, nt as PANEL_TYPES, on as GripHorizontal, ot as isCellAwareAtom, p as RadioGroupItem, pn as ChevronsUpDown, pt as Fill, q as ComboboxItem, qt as ChartErrorState, r as marimoVersionAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelOpen, sn as Funnel, st as SlotNames, t as cellDomProps, tn as EmotionCacheProvider, tt as ContextAwarePanelItem, u as Slide, un as Ellipsis, v as InstallPackageButton, vn as ArrowDownWideNarrow, vt as TableHead, w as Progress, wt as renderCellValue, x as downloadByURL, xt as NAMELESS_COLUMN_PREFIX, y as ADD_PRINTING_CLASS, yt as TableHeader, z as ContextMenuSeparator, zt as Maps, __tla as __tla_2 } from "./common-Cy9zypnG.js";
30
30
  import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-Bw4wRj_O.js";
31
31
  import { t as Check } from "./check-58HHfHKy.js";
32
32
  import { A as Icon, C as logNever, D as $18f2051aff69b9bf$export$a54013f0d02a8f82, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, F as createCollection, I as X, M as clamp$2, N as usePrevious$2, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, d as NativeSelect, i as SelectContent, j as Trigger$1, l as SelectTrigger, n as capitalize, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue, w as $a916eb452884faea$export$b7a616150fdb9f44 } from "./strings-DMLVGXRo.js";
@@ -38307,7 +38307,7 @@ ${c}
38307
38307
  function _temp2$2(e) {
38308
38308
  e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
38309
38309
  }
38310
- var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-Dnn6UpHR.js"));
38310
+ var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-2JQ2YfIT.js"));
38311
38311
  const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
38312
38312
  var _a5;
38313
38313
  let u = useAtomValue(kioskModeAtom), d = l === "read" || u, f = useAtomValue(numColumnsAtom) > 1, [p, m] = (0, import_react.useState)(null), { slideCells: h, skippedIds: g, noOutputIds: _, slideTypes: v, startCellIndex: y } = (0, import_react.useMemo)(() => computeSlideCellsInfo(c, e), [
@@ -9,7 +9,7 @@ import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
9
9
  import { ut as outputIsStale } from "./html-to-image-BzT-fb14.js";
10
10
  import "./chunk-5FQGJX7Z-BRZ_XYUw.js";
11
11
  import { u as createLucideIcon } from "./dist-j30bBjjN.js";
12
- import { a as DEFAULT_DECK_TRANSITION, cn as EyeOff, dt as PanelGroup, fn as Code, ft as PanelResizeHandle, l as SlideSidebar, ln as Expand, n as useNotebookCodeAvailable, o as DEFAULT_DECK_VERTICAL_ALIGN, s as DEFAULT_SLIDE_TYPE, t as cellDomProps, u as Slide, ut as Panel } from "./common-DWZbOZtC.js";
12
+ import { a as DEFAULT_DECK_TRANSITION, cn as EyeOff, dt as PanelGroup, fn as Code, ft as PanelResizeHandle, l as SlideSidebar, ln as Expand, n as useNotebookCodeAvailable, o as DEFAULT_DECK_VERTICAL_ALIGN, s as DEFAULT_SLIDE_TYPE, t as cellDomProps, u as Slide, ut as Panel } from "./common-Cy9zypnG.js";
13
13
  import { R as ChevronDown } from "./strings-DMLVGXRo.js";
14
14
  import { X as useDebouncedCallback } from "./input-CqV2ZPgL.js";
15
15
  import { v as kioskModeAtom } from "./toDate-CjUYDkFI.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.24.1-dev29",
3
+ "version": "0.24.1-dev30",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -117,6 +117,49 @@ exports[`generateStorageCode > GCS > without service account key (default creden
117
117
  store = GCSStore("my-bucket")"
118
118
  `;
119
119
 
120
+ exports[`generateStorageCode > GitHub > public repo 1`] = `
121
+ "from fsspec.implementations.github import GithubFileSystem
122
+
123
+ fs = GithubFileSystem(
124
+ org="marimo-team",
125
+ repo="marimo",
126
+ )"
127
+ `;
128
+
129
+ exports[`generateStorageCode > GitHub > with sha 1`] = `
130
+ "from fsspec.implementations.github import GithubFileSystem
131
+
132
+ fs = GithubFileSystem(
133
+ org="marimo-team",
134
+ repo="marimo",
135
+ sha="main",
136
+ )"
137
+ `;
138
+
139
+ exports[`generateStorageCode > GitHub > with username and token 1`] = `
140
+ "from fsspec.implementations.github import GithubFileSystem
141
+
142
+ fs = GithubFileSystem(
143
+ org="marimo-team",
144
+ repo="marimo",
145
+ username="octocat",
146
+ token="ghp_example",
147
+ )"
148
+ `;
149
+
150
+ exports[`generateStorageCode > GitHub > with username and token from secrets 1`] = `
151
+ "from fsspec.implementations.github import GithubFileSystem
152
+ import os
153
+
154
+ _token = os.environ.get("GITHUB_TOKEN")
155
+ fs = GithubFileSystem(
156
+ org="marimo-team",
157
+ repo="marimo",
158
+ username="octocat",
159
+ token=_token,
160
+ )"
161
+ `;
162
+
120
163
  exports[`generateStorageCode > Google Drive > with default auth (no credentials) 1`] = `
121
164
  "from gdrive_fsspec import GoogleDriveFileSystem
122
165
 
@@ -329,6 +329,83 @@ describe("generateStorageCode", () => {
329
329
  });
330
330
  });
331
331
 
332
+ describe("GitHub", () => {
333
+ it("public repo", () => {
334
+ expect(
335
+ generateStorageCode(
336
+ { type: "github", org: "marimo-team", repo: "marimo" },
337
+ { library: "fsspec" },
338
+ ),
339
+ ).toMatchSnapshot();
340
+ });
341
+
342
+ it("with sha", () => {
343
+ expect(
344
+ generateStorageCode(
345
+ {
346
+ type: "github",
347
+ org: "marimo-team",
348
+ repo: "marimo",
349
+ sha: "main",
350
+ },
351
+ { library: "fsspec" },
352
+ ),
353
+ ).toMatchSnapshot();
354
+ });
355
+
356
+ it("escapes quotes and backslashes in sha", () => {
357
+ expect(
358
+ generateStorageCode(
359
+ {
360
+ type: "github",
361
+ org: "marimo-team",
362
+ repo: "marimo",
363
+ sha: 'feature/\\"new"',
364
+ },
365
+ { library: "fsspec" },
366
+ ),
367
+ ).toMatchInlineSnapshot(`
368
+ "from fsspec.implementations.github import GithubFileSystem
369
+
370
+ fs = GithubFileSystem(
371
+ org="marimo-team",
372
+ repo="marimo",
373
+ sha="feature/\\\\\\"new\\"",
374
+ )"
375
+ `);
376
+ });
377
+
378
+ it("with username and token", () => {
379
+ expect(
380
+ generateStorageCode(
381
+ {
382
+ type: "github",
383
+ org: "marimo-team",
384
+ repo: "marimo",
385
+ username: "octocat",
386
+ token: "ghp_example",
387
+ },
388
+ { library: "fsspec" },
389
+ ),
390
+ ).toMatchSnapshot();
391
+ });
392
+
393
+ it("with username and token from secrets", () => {
394
+ expect(
395
+ generateStorageCode(
396
+ {
397
+ type: "github",
398
+ org: "marimo-team",
399
+ repo: "marimo",
400
+ username: "octocat",
401
+ token: prefixSecret("GITHUB_TOKEN"),
402
+ },
403
+ { library: "fsspec" },
404
+ ),
405
+ ).toMatchSnapshot();
406
+ });
407
+ });
408
+
332
409
  describe("invalid cases", () => {
333
410
  it("throws for empty S3 bucket", () => {
334
411
  expect(() =>
@@ -397,5 +474,55 @@ describe("generateStorageCode", () => {
397
474
  ),
398
475
  ).toThrow();
399
476
  });
477
+
478
+ it("throws for empty GitHub org", () => {
479
+ expect(() =>
480
+ generateStorageCode(
481
+ { type: "github", org: "", repo: "marimo" } as StorageConnection,
482
+ { library: "fsspec" },
483
+ ),
484
+ ).toThrow();
485
+ });
486
+
487
+ it("throws for empty GitHub repo", () => {
488
+ expect(() =>
489
+ generateStorageCode(
490
+ {
491
+ type: "github",
492
+ org: "marimo-team",
493
+ repo: "",
494
+ } as StorageConnection,
495
+ { library: "fsspec" },
496
+ ),
497
+ ).toThrow();
498
+ });
499
+
500
+ it("throws when GitHub username is set without token", () => {
501
+ expect(() =>
502
+ generateStorageCode(
503
+ {
504
+ type: "github",
505
+ org: "marimo-team",
506
+ repo: "marimo",
507
+ username: "octocat",
508
+ },
509
+ { library: "fsspec" },
510
+ ),
511
+ ).toThrow();
512
+ });
513
+
514
+ it("throws when GitHub token is set without username", () => {
515
+ expect(() =>
516
+ generateStorageCode(
517
+ {
518
+ type: "github",
519
+ org: "marimo-team",
520
+ repo: "marimo",
521
+ token: "ghp_example",
522
+ },
523
+ { library: "fsspec" },
524
+ ),
525
+ ).toThrow();
526
+ });
400
527
  });
401
528
  });
@@ -16,6 +16,7 @@ import {
16
16
  AzureStorageSchema,
17
17
  CoreWeaveStorageSchema,
18
18
  GCSStorageSchema,
19
+ GithubStorageSchema,
19
20
  GoogleDriveStorageSchema,
20
21
  HuggingfaceStorageSchema,
21
22
  S3StorageSchema,
@@ -89,6 +90,15 @@ const STORAGE_PROVIDERS = [
89
90
  preferred: "huggingface_hub",
90
91
  },
91
92
  },
93
+ {
94
+ name: "GitHub",
95
+ schema: GithubStorageSchema,
96
+ protocol: "github",
97
+ storageLibraries: {
98
+ libraries: ["fsspec"],
99
+ preferred: "fsspec",
100
+ },
101
+ },
92
102
  ] satisfies StorageProviderSchema[];
93
103
 
94
104
  const StorageProviderSelector: React.FC<{
@@ -105,7 +115,7 @@ const StorageProviderSelector: React.FC<{
105
115
  <ProtocolIcon
106
116
  protocol={protocol as KnownStorageProtocol}
107
117
  forceDark={true}
108
- className="w-7.5 h-7.5"
118
+ className="w-7.5 h-7.5 text-white"
109
119
  />
110
120
  }
111
121
  onSelect={() => onSelect(schema)}
@@ -43,7 +43,7 @@ class SecretContainer {
43
43
  this.secrets[privateVar] = `os.environ.get("${envVar}")`;
44
44
  return privateVar;
45
45
  }
46
- return `"${value}"`;
46
+ return `"${escapePythonString(value)}"`;
47
47
  }
48
48
 
49
49
  formatSecrets(): string {
@@ -260,6 +260,32 @@ function generateHuggingfaceCode(
260
260
  return { imports, code: `hf = HfApi(token=${token})` };
261
261
  }
262
262
 
263
+ function generateGithubCode(
264
+ connection: Extract<StorageConnection, { type: "github" }>,
265
+ secrets: SecretContainer,
266
+ ): { imports: Set<string>; code: string } {
267
+ const imports = new Set([
268
+ "from fsspec.implementations.github import GithubFileSystem",
269
+ ]);
270
+ const params: string[] = [
271
+ `org=${secrets.print("org", connection.org)},`,
272
+ `repo=${secrets.print("repo", connection.repo)},`,
273
+ ];
274
+
275
+ if (connection.sha) {
276
+ params.push(`sha=${secrets.print("sha", connection.sha)},`);
277
+ }
278
+ if (connection.username && connection.token) {
279
+ params.push(
280
+ `username=${secrets.print("username", connection.username)},`,
281
+ `token=${secrets.print("token", connection.token)},`,
282
+ );
283
+ }
284
+
285
+ const paramsStr = params.map((param) => ` ${param}`).join("\n");
286
+ return { imports, code: `fs = GithubFileSystem(\n${paramsStr}\n)` };
287
+ }
288
+
263
289
  export function generateStorageCode(
264
290
  connection: StorageConnection,
265
291
  options: StorageCodeOptions,
@@ -291,6 +317,9 @@ export function generateStorageCode(
291
317
  case "huggingface":
292
318
  result = generateHuggingfaceCode(connection, secrets);
293
319
  break;
320
+ case "github":
321
+ result = generateGithubCode(connection, secrets);
322
+ break;
294
323
  default:
295
324
  assertNever(connection);
296
325
  }
@@ -238,6 +238,68 @@ export const HuggingfaceStorageSchema = z
238
238
  })
239
239
  .describe(FieldOptions.of({ direction: "two-columns" }));
240
240
 
241
+ function isFilled(value: string | undefined): boolean {
242
+ return value != null && value !== "";
243
+ }
244
+
245
+ export const GithubStorageSchema = z
246
+ .object({
247
+ type: z.literal("github"),
248
+ org: z
249
+ .string()
250
+ .nonempty()
251
+ .describe(
252
+ FieldOptions.of({
253
+ label: "Organization or user",
254
+ }),
255
+ ),
256
+ repo: z
257
+ .string()
258
+ .nonempty()
259
+ .describe(
260
+ FieldOptions.of({
261
+ label: "Repository",
262
+ }),
263
+ ),
264
+ sha: z
265
+ .string()
266
+ .optional()
267
+ .describe(
268
+ FieldOptions.of({
269
+ label: "Branch, tag, or commit",
270
+ placeholder: "main",
271
+ description: "Leave empty to use the default branch",
272
+ }),
273
+ ),
274
+ username: z
275
+ .string()
276
+ .optional()
277
+ .describe(
278
+ FieldOptions.of({
279
+ label: "Username",
280
+ description: "Set this together with access token",
281
+ optionRegex: "(github.?username|github.?user)",
282
+ }),
283
+ ),
284
+ token: z
285
+ .string()
286
+ .optional()
287
+ .describe(
288
+ FieldOptions.of({
289
+ label: "Access Token",
290
+ description:
291
+ "Set this together with username. Required for private repos and to avoid GitHub's rate limits.",
292
+ inputType: "password",
293
+ optionRegex: "(github.?token|gh.?token|github.?pat)",
294
+ }),
295
+ ),
296
+ })
297
+ .refine((value) => isFilled(value.username) === isFilled(value.token), {
298
+ message: "Username and access token are required together",
299
+ path: ["token"],
300
+ })
301
+ .describe(FieldOptions.of({ direction: "two-columns" }));
302
+
241
303
  export const StorageConnectionSchema = z.discriminatedUnion("type", [
242
304
  S3StorageSchema,
243
305
  GCSStorageSchema,
@@ -245,6 +307,7 @@ export const StorageConnectionSchema = z.discriminatedUnion("type", [
245
307
  CoreWeaveStorageSchema,
246
308
  GoogleDriveStorageSchema,
247
309
  HuggingfaceStorageSchema,
310
+ GithubStorageSchema,
248
311
  ]);
249
312
 
250
313
  export type StorageConnection = z.infer<typeof StorageConnectionSchema>;