@marimo-team/islands 0.21.2-dev6 → 0.21.2-dev62
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/{ConnectedDataExplorerComponent-D0GoOd_c.js → ConnectedDataExplorerComponent-DrWDbHRV.js} +1 -1
- package/dist/{any-language-editor-DlsjUw_l.js → any-language-editor-BRpxklRq.js} +1 -1
- package/dist/{copy-DIK6DiIA.js → copy-BjkXCUxP.js} +12 -2
- package/dist/{esm-BLobyqMs.js → esm-No_6eSQS.js} +1 -1
- package/dist/{glide-data-editor-pZyd9UJ_.js → glide-data-editor-858wsVkd.js} +1 -1
- package/dist/main.js +821 -417
- package/dist/{spec-Bfvf9Hre.js → spec-oVDndBz4.js} +25 -16
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/__mocks__/notebook.ts +9 -9
- package/src/__mocks__/requests.ts +1 -0
- package/src/__tests__/branded.ts +20 -0
- package/src/components/app-config/user-config-form.tsx +5 -4
- package/src/components/data-table/__tests__/utils.test.ts +138 -1
- package/src/components/data-table/charts/__tests__/storage.test.ts +7 -7
- package/src/components/data-table/context-menu.tsx +9 -5
- package/src/components/data-table/data-table.tsx +3 -0
- package/src/components/data-table/range-focus/__tests__/atoms.test.ts +8 -2
- package/src/components/data-table/range-focus/__tests__/test-utils.ts +2 -0
- package/src/components/data-table/range-focus/__tests__/utils.test.ts +82 -8
- package/src/components/data-table/range-focus/atoms.ts +2 -2
- package/src/components/data-table/range-focus/utils.ts +50 -12
- package/src/components/data-table/types.ts +7 -0
- package/src/components/data-table/utils.ts +87 -0
- package/src/components/editor/__tests__/data-attributes.test.tsx +8 -8
- package/src/components/editor/ai/__tests__/completion-utils.test.ts +15 -15
- package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +2 -2
- package/src/components/editor/connections/storage/as-code.ts +2 -2
- package/src/components/editor/file-tree/file-explorer.tsx +16 -2
- package/src/components/editor/file-tree/file-viewer.tsx +17 -3
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +2 -2
- package/src/components/editor/navigation/__tests__/selection.test.ts +7 -6
- package/src/components/editor/navigation/__tests__/state.test.ts +8 -7
- package/src/components/editor/output/MarimoErrorOutput.tsx +7 -7
- package/src/components/editor/output/__tests__/traceback.test.tsx +4 -4
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +4 -4
- package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +8 -1
- package/src/components/storage/storage-file-viewer.tsx +35 -1
- package/src/components/storage/storage-inspector.tsx +9 -4
- package/src/components/storage/storage-snippets.ts +3 -3
- package/src/components/tracing/tracing.tsx +3 -1
- package/src/components/ui/range-slider.tsx +108 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +9 -8
- package/src/core/ai/context/providers/__tests__/cell-output.test.ts +31 -31
- package/src/core/ai/context/providers/__tests__/datasource.test.ts +3 -3
- package/src/core/ai/context/providers/__tests__/tables.test.ts +3 -2
- package/src/core/ai/context/providers/__tests__/variable.test.ts +84 -63
- package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +10 -9
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +6 -6
- package/src/core/ai/tools/edit-notebook-tool.ts +3 -3
- package/src/core/cells/__tests__/add-missing-import.test.ts +3 -3
- package/src/core/cells/__tests__/apply-transaction.test.ts +279 -0
- package/src/core/cells/__tests__/cells.test.ts +198 -135
- package/src/core/cells/__tests__/document-changes.test.ts +575 -0
- package/src/core/cells/__tests__/document-roundtrip.test.ts +376 -0
- package/src/core/cells/__tests__/focus.test.ts +5 -4
- package/src/core/cells/__tests__/logs.test.ts +13 -12
- package/src/core/cells/__tests__/pending-delete-service.test.tsx +3 -3
- package/src/core/cells/__tests__/runs.test.ts +22 -21
- package/src/core/cells/__tests__/scrollCellIntoView.test.ts +8 -7
- package/src/core/cells/__tests__/session.test.ts +23 -22
- package/src/core/cells/cells.ts +29 -4
- package/src/core/cells/document-changes.ts +644 -0
- package/src/core/cells/ids.ts +5 -5
- package/src/core/cells/logs.ts +2 -2
- package/src/core/cells/runs.ts +6 -8
- package/src/core/codemirror/__tests__/format.test.ts +34 -36
- package/src/core/codemirror/__tests__/setup.test.ts +2 -2
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +114 -0
- package/src/core/codemirror/cells/__tests__/traceback-decorations.test.ts +33 -32
- package/src/core/codemirror/cells/extensions.ts +66 -23
- package/src/core/codemirror/completion/__tests__/keymap.test.ts +15 -35
- package/src/core/codemirror/completion/keymap.ts +14 -4
- package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +12 -13
- package/src/core/codemirror/language/__tests__/utils.test.ts +3 -3
- package/src/core/codemirror/language/embedded/__tests__/embedded-python.test.ts +7 -8
- package/src/core/codemirror/language/languages/python.ts +4 -0
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +4 -3
- package/src/core/codemirror/lsp/notebook-lsp.ts +28 -2
- package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +7 -6
- package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
- package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +52 -0
- package/src/core/codemirror/rtc/loro/sync.ts +1 -0
- package/src/core/datasets/__tests__/data-source.test.ts +5 -6
- package/src/core/datasets/state.ts +1 -1
- package/src/core/errors/__tests__/errors.test.ts +2 -1
- package/src/core/export/__tests__/hooks.test.ts +37 -36
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/islands/main.ts +4 -7
- package/src/core/kernel/__tests__/handlers.test.ts +5 -4
- package/src/core/kernel/handlers.ts +7 -4
- package/src/core/network/DeferredRequestRegistry.ts +2 -2
- package/src/core/network/__tests__/CachingRequestRegistry.test.ts +9 -10
- package/src/core/network/__tests__/DeferredRequestRegistry.test.ts +4 -6
- package/src/core/network/requests-lazy.ts +1 -0
- package/src/core/network/requests-network.ts +9 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.tsx +1 -0
- package/src/core/network/types.ts +5 -0
- package/src/core/static/__tests__/virtual-file-tracker.test.ts +8 -8
- package/src/core/static/virtual-file-tracker.ts +1 -1
- package/src/core/storage/__tests__/state.test.ts +31 -21
- package/src/core/storage/state.ts +1 -1
- package/src/core/variables/__tests__/state.test.ts +6 -6
- package/src/core/variables/types.ts +2 -2
- package/src/core/wasm/__tests__/state.test.ts +8 -8
- package/src/core/wasm/bridge.ts +1 -0
- package/src/core/websocket/useMarimoKernelConnection.tsx +31 -16
- package/src/css/app/fonts.css +6 -6
- package/src/css/md-tooltip.css +4 -39
- package/src/css/md.css +7 -0
- package/src/fonts/Fira_Mono/FiraMono-Bold.woff2 +0 -0
- package/src/fonts/Fira_Mono/FiraMono-Medium.woff2 +0 -0
- package/src/fonts/Fira_Mono/FiraMono-Regular.woff2 +0 -0
- package/src/fonts/Lora/Lora-VariableFont_wght.woff2 +0 -0
- package/src/fonts/PT_Sans/PTSans-Bold.woff2 +0 -0
- package/src/fonts/PT_Sans/PTSans-Regular.woff2 +0 -0
- package/src/plugins/core/RenderHTML.tsx +17 -0
- package/src/plugins/core/__test__/RenderHTML.test.ts +45 -0
- package/src/plugins/core/sanitize-html.ts +25 -18
- package/src/plugins/impl/DataTablePlugin.tsx +23 -2
- package/src/plugins/impl/SliderPlugin.tsx +1 -3
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +120 -0
- package/src/plugins/impl/anywidget/model.ts +1 -2
- package/src/stories/cell.stories.tsx +8 -8
- package/src/stories/layout/vertical/one-column.stories.tsx +9 -8
- package/src/stories/log-viewer.stories.tsx +8 -8
- package/src/stories/variables.stories.tsx +2 -2
- package/src/utils/__tests__/download.test.tsx +21 -20
- package/src/utils/copy.ts +18 -5
- package/src/utils/createReducer.ts +26 -11
- package/src/utils/download.ts +4 -3
- package/src/utils/html-to-image.ts +6 -0
- package/src/utils/json/base64.ts +3 -3
- package/src/utils/traceback.ts +5 -3
- package/src/fonts/Fira_Mono/FiraMono-Bold.ttf +0 -0
- package/src/fonts/Fira_Mono/FiraMono-Medium.ttf +0 -0
- package/src/fonts/Fira_Mono/FiraMono-Regular.ttf +0 -0
- package/src/fonts/Lora/Lora-Italic-VariableFont_wght.ttf +0 -0
- package/src/fonts/Lora/Lora-VariableFont_wght.ttf +0 -0
- package/src/fonts/Lora/static/Lora-Bold.ttf +0 -0
- package/src/fonts/Lora/static/Lora-BoldItalic.ttf +0 -0
- package/src/fonts/Lora/static/Lora-Italic.ttf +0 -0
- package/src/fonts/Lora/static/Lora-Medium.ttf +0 -0
- package/src/fonts/Lora/static/Lora-MediumItalic.ttf +0 -0
- package/src/fonts/Lora/static/Lora-Regular.ttf +0 -0
- package/src/fonts/Lora/static/Lora-SemiBold.ttf +0 -0
- package/src/fonts/Lora/static/Lora-SemiBoldItalic.ttf +0 -0
- package/src/fonts/PT_Sans/PTSans-Bold.ttf +0 -0
- package/src/fonts/PT_Sans/PTSans-BoldItalic.ttf +0 -0
- package/src/fonts/PT_Sans/PTSans-Italic.ttf +0 -0
- package/src/fonts/PT_Sans/PTSans-Regular.ttf +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { cellId } from "@/__tests__/branded";
|
|
4
5
|
import type { CellMessage } from "@/core/kernel/messages";
|
|
5
6
|
import { invariant } from "@/utils/invariant";
|
|
6
7
|
import {
|
|
@@ -22,13 +23,13 @@ describe("RunsState Reducer", () => {
|
|
|
22
23
|
let state: RunsState;
|
|
23
24
|
|
|
24
25
|
const runId = "run1" as RunId;
|
|
25
|
-
const
|
|
26
|
+
const testCellId = cellId("cell1");
|
|
26
27
|
const timestamp = Date.now();
|
|
27
28
|
const code = "print('Hello World')";
|
|
28
29
|
|
|
29
30
|
const cellNotification: CellMessage = {
|
|
30
31
|
run_id: runId,
|
|
31
|
-
cell_id:
|
|
32
|
+
cell_id: testCellId,
|
|
32
33
|
timestamp,
|
|
33
34
|
status: "queued",
|
|
34
35
|
};
|
|
@@ -61,9 +62,9 @@ describe("RunsState Reducer", () => {
|
|
|
61
62
|
runStartTime: timestamp,
|
|
62
63
|
cellRuns: new Map([
|
|
63
64
|
[
|
|
64
|
-
|
|
65
|
+
testCellId,
|
|
65
66
|
{
|
|
66
|
-
cellId,
|
|
67
|
+
cellId: testCellId,
|
|
67
68
|
code: code.slice(0, MAX_CODE_LENGTH),
|
|
68
69
|
elapsedTime: 0,
|
|
69
70
|
startTime: timestamp,
|
|
@@ -98,7 +99,7 @@ describe("RunsState Reducer", () => {
|
|
|
98
99
|
payload: {
|
|
99
100
|
cellNotification: {
|
|
100
101
|
run_id: runId2,
|
|
101
|
-
cell_id: "cell2",
|
|
102
|
+
cell_id: cellId("cell2"),
|
|
102
103
|
timestamp,
|
|
103
104
|
status: "queued",
|
|
104
105
|
},
|
|
@@ -124,7 +125,7 @@ describe("RunsState Reducer", () => {
|
|
|
124
125
|
payload: {
|
|
125
126
|
cellNotification: {
|
|
126
127
|
run_id: runId,
|
|
127
|
-
cell_id:
|
|
128
|
+
cell_id: testCellId,
|
|
128
129
|
timestamp: timestamp + 1000,
|
|
129
130
|
status: "running",
|
|
130
131
|
},
|
|
@@ -145,7 +146,7 @@ describe("RunsState Reducer", () => {
|
|
|
145
146
|
payload: {
|
|
146
147
|
cellNotification: {
|
|
147
148
|
run_id: runId,
|
|
148
|
-
cell_id:
|
|
149
|
+
cell_id: testCellId,
|
|
149
150
|
timestamp: runStartTimestamp + 5000,
|
|
150
151
|
status: "success",
|
|
151
152
|
},
|
|
@@ -171,8 +172,8 @@ describe("RunsState Reducer", () => {
|
|
|
171
172
|
type: "addCellNotification",
|
|
172
173
|
payload: {
|
|
173
174
|
cellNotification: {
|
|
174
|
-
run_id: `run${i}
|
|
175
|
-
cell_id: `cell${i}
|
|
175
|
+
run_id: `run${i}` as RunId,
|
|
176
|
+
cell_id: cellId(`cell${i}`),
|
|
176
177
|
timestamp: timestamp,
|
|
177
178
|
status: "queued",
|
|
178
179
|
},
|
|
@@ -198,7 +199,7 @@ describe("RunsState Reducer", () => {
|
|
|
198
199
|
payload: {
|
|
199
200
|
cellNotification: {
|
|
200
201
|
run_id: runId,
|
|
201
|
-
cell_id:
|
|
202
|
+
cell_id: testCellId,
|
|
202
203
|
timestamp,
|
|
203
204
|
status: "queued",
|
|
204
205
|
},
|
|
@@ -220,7 +221,7 @@ describe("RunsState Reducer", () => {
|
|
|
220
221
|
payload: {
|
|
221
222
|
cellNotification: {
|
|
222
223
|
run_id: runId,
|
|
223
|
-
cell_id:
|
|
224
|
+
cell_id: testCellId,
|
|
224
225
|
timestamp: errorTimestamp,
|
|
225
226
|
status: "running",
|
|
226
227
|
output: {
|
|
@@ -248,7 +249,7 @@ describe("RunsState Reducer", () => {
|
|
|
248
249
|
payload: {
|
|
249
250
|
cellNotification: {
|
|
250
251
|
run_id: runId,
|
|
251
|
-
cell_id:
|
|
252
|
+
cell_id: testCellId,
|
|
252
253
|
timestamp: errorTimestamp,
|
|
253
254
|
status: "running",
|
|
254
255
|
output: {
|
|
@@ -273,7 +274,7 @@ describe("RunsState Reducer", () => {
|
|
|
273
274
|
payload: {
|
|
274
275
|
cellNotification: {
|
|
275
276
|
run_id: runId,
|
|
276
|
-
cell_id:
|
|
277
|
+
cell_id: testCellId,
|
|
277
278
|
timestamp,
|
|
278
279
|
output: {
|
|
279
280
|
channel: "marimo-error",
|
|
@@ -288,7 +289,7 @@ describe("RunsState Reducer", () => {
|
|
|
288
289
|
payload: {
|
|
289
290
|
cellNotification: {
|
|
290
291
|
run_id: runId,
|
|
291
|
-
cell_id:
|
|
292
|
+
cell_id: testCellId,
|
|
292
293
|
timestamp: timestamp + 2000,
|
|
293
294
|
status: "running", // shouldn't happen
|
|
294
295
|
},
|
|
@@ -312,7 +313,7 @@ describe("RunsState Reducer", () => {
|
|
|
312
313
|
payload: {
|
|
313
314
|
cellNotification: {
|
|
314
315
|
run_id: runId2,
|
|
315
|
-
cell_id: "cell2",
|
|
316
|
+
cell_id: cellId("cell2"),
|
|
316
317
|
timestamp: timestamp + 1000,
|
|
317
318
|
status: "queued",
|
|
318
319
|
},
|
|
@@ -325,7 +326,7 @@ describe("RunsState Reducer", () => {
|
|
|
325
326
|
payload: {
|
|
326
327
|
cellNotification: {
|
|
327
328
|
run_id: runId3,
|
|
328
|
-
cell_id: "cell3",
|
|
329
|
+
cell_id: cellId("cell3"),
|
|
329
330
|
timestamp: timestamp + 2000,
|
|
330
331
|
status: "queued",
|
|
331
332
|
},
|
|
@@ -345,7 +346,7 @@ describe("RunsState Reducer", () => {
|
|
|
345
346
|
payload: {
|
|
346
347
|
cellNotification: {
|
|
347
348
|
run_id: runId,
|
|
348
|
-
cell_id: "cell2",
|
|
349
|
+
cell_id: cellId("cell2"),
|
|
349
350
|
timestamp: timestamp + 1000,
|
|
350
351
|
status: "queued",
|
|
351
352
|
},
|
|
@@ -367,7 +368,7 @@ describe("RunsState Reducer", () => {
|
|
|
367
368
|
payload: {
|
|
368
369
|
cellNotification: {
|
|
369
370
|
run_id: runId,
|
|
370
|
-
cell_id:
|
|
371
|
+
cell_id: testCellId,
|
|
371
372
|
timestamp: timestamp + 1000,
|
|
372
373
|
status: "running",
|
|
373
374
|
},
|
|
@@ -386,7 +387,7 @@ describe("RunsState Reducer", () => {
|
|
|
386
387
|
payload: {
|
|
387
388
|
cellNotification: {
|
|
388
389
|
run_id: runId,
|
|
389
|
-
cell_id:
|
|
390
|
+
cell_id: testCellId,
|
|
390
391
|
timestamp,
|
|
391
392
|
status: "queued",
|
|
392
393
|
},
|
|
@@ -405,7 +406,7 @@ describe("RunsState Reducer", () => {
|
|
|
405
406
|
payload: {
|
|
406
407
|
cellNotification: {
|
|
407
408
|
run_id: runId,
|
|
408
|
-
cell_id:
|
|
409
|
+
cell_id: testCellId,
|
|
409
410
|
timestamp,
|
|
410
411
|
status: "queued",
|
|
411
412
|
},
|
|
@@ -419,7 +420,7 @@ describe("RunsState Reducer", () => {
|
|
|
419
420
|
payload: {
|
|
420
421
|
cellNotification: {
|
|
421
422
|
run_id: runId,
|
|
422
|
-
cell_id: "cell2",
|
|
423
|
+
cell_id: cellId("cell2"),
|
|
423
424
|
timestamp: timestamp + 1000,
|
|
424
425
|
status: "queued",
|
|
425
426
|
},
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
-
import {
|
|
4
|
+
import { cellId } from "@/__tests__/branded";
|
|
5
|
+
import { HTMLCellId } from "@/core/cells/ids";
|
|
5
6
|
import { Logger } from "@/utils/Logger";
|
|
6
7
|
|
|
7
8
|
// Mock the getCellEditorView function
|
|
@@ -20,12 +21,12 @@ vi.mock("@/core/codemirror/extensions", () => ({
|
|
|
20
21
|
const { scrollCellIntoView } = await import("@/core/cells/scrollCellIntoView");
|
|
21
22
|
|
|
22
23
|
describe("scrollCellIntoView", () => {
|
|
23
|
-
const
|
|
24
|
+
const cid = cellId("test-cell-id");
|
|
24
25
|
let cellElement: HTMLElement;
|
|
25
26
|
|
|
26
27
|
beforeEach(() => {
|
|
27
28
|
cellElement = document.createElement("div");
|
|
28
|
-
cellElement.id = HTMLCellId.create(
|
|
29
|
+
cellElement.id = HTMLCellId.create(cid);
|
|
29
30
|
cellElement.scrollIntoView = vi.fn();
|
|
30
31
|
document.body.append(cellElement);
|
|
31
32
|
|
|
@@ -42,7 +43,7 @@ describe("scrollCellIntoView", () => {
|
|
|
42
43
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
44
|
mockGetCellEditorView.mockReturnValue(mockEditor as any);
|
|
44
45
|
|
|
45
|
-
scrollCellIntoView(
|
|
46
|
+
scrollCellIntoView(cid);
|
|
46
47
|
|
|
47
48
|
expect(mockScrollActiveLineIntoView).toHaveBeenCalledWith(mockEditor, {
|
|
48
49
|
behavior: "instant",
|
|
@@ -51,7 +52,7 @@ describe("scrollCellIntoView", () => {
|
|
|
51
52
|
});
|
|
52
53
|
|
|
53
54
|
it("should scroll cell element when editor is not focused", () => {
|
|
54
|
-
scrollCellIntoView(
|
|
55
|
+
scrollCellIntoView(cid);
|
|
55
56
|
|
|
56
57
|
expect(mockScrollActiveLineIntoView).not.toHaveBeenCalled();
|
|
57
58
|
expect(cellElement.scrollIntoView).toHaveBeenCalledWith({
|
|
@@ -64,10 +65,10 @@ describe("scrollCellIntoView", () => {
|
|
|
64
65
|
const warnSpy = vi.spyOn(Logger, "warn").mockImplementation(vi.fn());
|
|
65
66
|
cellElement.remove();
|
|
66
67
|
|
|
67
|
-
scrollCellIntoView(
|
|
68
|
+
scrollCellIntoView(cid);
|
|
68
69
|
|
|
69
70
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
70
|
-
`[CellFocusManager] scrollCellIntoView: element not found: ${
|
|
71
|
+
`[CellFocusManager] scrollCellIntoView: element not found: ${cid}`,
|
|
71
72
|
);
|
|
72
73
|
warnSpy.mockRestore();
|
|
73
74
|
});
|
|
@@ -4,11 +4,12 @@ import type * as api from "@marimo-team/marimo-api";
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
5
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
import { Mocks } from "@/__mocks__/common";
|
|
7
|
+
import { cellId } from "@/__tests__/branded";
|
|
7
8
|
import { parseOutline } from "@/core/dom/outline";
|
|
8
9
|
import { MultiColumn, visibleForTesting } from "@/utils/id-tree";
|
|
9
10
|
import { invariant } from "@/utils/invariant";
|
|
10
11
|
import { Logger } from "@/utils/Logger";
|
|
11
|
-
import {
|
|
12
|
+
import { SETUP_CELL_ID } from "../ids";
|
|
12
13
|
import { notebookStateFromSession } from "../session";
|
|
13
14
|
|
|
14
15
|
// Mock dependencies
|
|
@@ -22,7 +23,7 @@ type SessionCell = api.Session["NotebookSessionV1"]["cells"][0];
|
|
|
22
23
|
type NotebookCell = api.Notebook["NotebookV1"]["cells"][0];
|
|
23
24
|
|
|
24
25
|
// Test constants
|
|
25
|
-
const CELL_1 = "cell-1"
|
|
26
|
+
const CELL_1 = cellId("cell-1");
|
|
26
27
|
|
|
27
28
|
describe("notebookStateFromSession", () => {
|
|
28
29
|
beforeEach(() => {
|
|
@@ -671,9 +672,9 @@ describe("notebookStateFromSession", () => {
|
|
|
671
672
|
);
|
|
672
673
|
// Should have correct code and output for each cell
|
|
673
674
|
for (const code of ["a", "b", "c", "d", "e", "f"]) {
|
|
674
|
-
const
|
|
675
|
-
expect(result.cellData[
|
|
676
|
-
expect(result.cellRuntime[
|
|
675
|
+
const cid = cellId(`cell-${code}`);
|
|
676
|
+
expect(result.cellData[cid].code).toBe(code);
|
|
677
|
+
expect(result.cellRuntime[cid].output).toEqual({
|
|
677
678
|
channel: "output",
|
|
678
679
|
data: `${code.toUpperCase()}!`,
|
|
679
680
|
mimetype: "text/plain",
|
|
@@ -751,26 +752,26 @@ describe("notebookStateFromSession", () => {
|
|
|
751
752
|
);
|
|
752
753
|
|
|
753
754
|
// Should have correct code for each cell
|
|
754
|
-
expect(result.cellData["cell-a"
|
|
755
|
-
expect(result.cellData["cell-c"
|
|
756
|
-
expect(result.cellData["cell-z"
|
|
757
|
-
expect(result.cellData["cell-e"
|
|
758
|
-
expect(result.cellData["cell-g"
|
|
755
|
+
expect(result.cellData[cellId("cell-a")].code).toBe("a");
|
|
756
|
+
expect(result.cellData[cellId("cell-c")].code).toBe("c");
|
|
757
|
+
expect(result.cellData[cellId("cell-z")].code).toBe("z");
|
|
758
|
+
expect(result.cellData[cellId("cell-e")].code).toBe("e");
|
|
759
|
+
expect(result.cellData[cellId("cell-g")].code).toBe("g");
|
|
759
760
|
|
|
760
761
|
// Should have session outputs for matching cells (a, c, e)
|
|
761
|
-
expect(result.cellRuntime["cell-a"
|
|
762
|
+
expect(result.cellRuntime[cellId("cell-a")].output).toEqual({
|
|
762
763
|
channel: "output",
|
|
763
764
|
data: "A!",
|
|
764
765
|
mimetype: "text/plain",
|
|
765
766
|
timestamp: 0,
|
|
766
767
|
});
|
|
767
|
-
expect(result.cellRuntime["cell-c"
|
|
768
|
+
expect(result.cellRuntime[cellId("cell-c")].output).toEqual({
|
|
768
769
|
channel: "output",
|
|
769
770
|
data: "C!",
|
|
770
771
|
mimetype: "text/plain",
|
|
771
772
|
timestamp: 0,
|
|
772
773
|
});
|
|
773
|
-
expect(result.cellRuntime["cell-e"
|
|
774
|
+
expect(result.cellRuntime[cellId("cell-e")].output).toEqual({
|
|
774
775
|
channel: "output",
|
|
775
776
|
data: "E!",
|
|
776
777
|
mimetype: "text/plain",
|
|
@@ -778,8 +779,8 @@ describe("notebookStateFromSession", () => {
|
|
|
778
779
|
});
|
|
779
780
|
|
|
780
781
|
// Should have no output for new cells (z, g) - they get stub session cells
|
|
781
|
-
expect(result.cellRuntime["cell-z"
|
|
782
|
-
expect(result.cellRuntime["cell-g"
|
|
782
|
+
expect(result.cellRuntime[cellId("cell-z")].output).toBeNull();
|
|
783
|
+
expect(result.cellRuntime[cellId("cell-g")].output).toBeNull();
|
|
783
784
|
|
|
784
785
|
// Should log warning about different cells
|
|
785
786
|
expect(Logger.warn).toHaveBeenCalledWith(
|
|
@@ -875,18 +876,18 @@ describe("notebookStateFromSession", () => {
|
|
|
875
876
|
);
|
|
876
877
|
|
|
877
878
|
// Should have correct code from notebook
|
|
878
|
-
expect(result.cellData["cell-1"
|
|
879
|
-
expect(result.cellData["cell-2"
|
|
880
|
-
expect(result.cellData["cell-3"
|
|
879
|
+
expect(result.cellData[cellId("cell-1")].code).toBe("1 / 0");
|
|
880
|
+
expect(result.cellData[cellId("cell-2")].code).toBe('mo.md("Hello")');
|
|
881
|
+
expect(result.cellData[cellId("cell-3")].code).toBe(
|
|
881
882
|
"x = mo.ui.slider(0, 10)",
|
|
882
883
|
);
|
|
883
884
|
|
|
884
885
|
// cell-1: No matching session cell (hash is null), gets stub session cell
|
|
885
|
-
expect(result.cellRuntime["cell-1"
|
|
886
|
-
expect(result.cellRuntime["cell-1"
|
|
886
|
+
expect(result.cellRuntime[cellId("cell-1")].output).toBeNull();
|
|
887
|
+
expect(result.cellRuntime[cellId("cell-1")].consoleOutputs).toEqual([]);
|
|
887
888
|
|
|
888
889
|
// cell-2: Matches session cell-1 by hash (moMd), gets its output
|
|
889
|
-
expect(result.cellRuntime["cell-2"
|
|
890
|
+
expect(result.cellRuntime[cellId("cell-2")].output).toEqual({
|
|
890
891
|
channel: "output",
|
|
891
892
|
data: "Welcome to marimo!",
|
|
892
893
|
mimetype: "text/markdown",
|
|
@@ -894,7 +895,7 @@ describe("notebookStateFromSession", () => {
|
|
|
894
895
|
});
|
|
895
896
|
|
|
896
897
|
// cell-3: Matches session cell-2 by hash (slider), gets its output
|
|
897
|
-
expect(result.cellRuntime["cell-3"
|
|
898
|
+
expect(result.cellRuntime[cellId("cell-3")].output).toEqual({
|
|
898
899
|
channel: "output",
|
|
899
900
|
data: "",
|
|
900
901
|
mimetype: "text/plain",
|
package/src/core/cells/cells.ts
CHANGED
|
@@ -29,6 +29,7 @@ import type { CellConfig } from "../network/types";
|
|
|
29
29
|
import { isRtcEnabled } from "../rtc/state";
|
|
30
30
|
import { createDeepEqualAtom, store } from "../state/jotai";
|
|
31
31
|
import { prepareCellForExecution, transitionCell } from "./cell";
|
|
32
|
+
import { documentTransactionMiddleware } from "./document-changes";
|
|
32
33
|
import { CellId, SCRATCH_CELL_ID, SETUP_CELL_ID } from "./ids";
|
|
33
34
|
import { type CellLog, getCellLogsForMessage } from "./logs";
|
|
34
35
|
import {
|
|
@@ -174,6 +175,7 @@ export interface CreateNewCellAction {
|
|
|
174
175
|
*/
|
|
175
176
|
const {
|
|
176
177
|
reducer,
|
|
178
|
+
addMiddleware,
|
|
177
179
|
createActions,
|
|
178
180
|
useActions,
|
|
179
181
|
valueAtom: notebookAtom,
|
|
@@ -755,14 +757,29 @@ const {
|
|
|
755
757
|
});
|
|
756
758
|
},
|
|
757
759
|
handleCellMessage: (state, message: CellMessage) => {
|
|
758
|
-
const cellId = message.cell_id
|
|
759
|
-
|
|
760
|
+
const cellId = message.cell_id;
|
|
761
|
+
let nextState = updateCellRuntimeState({
|
|
760
762
|
state,
|
|
761
763
|
cellId,
|
|
762
764
|
cellReducer: (cell) => {
|
|
763
765
|
return transitionCell(cell, message);
|
|
764
766
|
},
|
|
765
767
|
});
|
|
768
|
+
// When a cell is queued for execution, snapshot the current code
|
|
769
|
+
// as lastCodeRun. This clears staleness for cells executed by the
|
|
770
|
+
// kernel (e.g. via code_mode). If the user edits during execution,
|
|
771
|
+
// code !== lastCodeRun keeps the cell stale.
|
|
772
|
+
if (message.status === "queued") {
|
|
773
|
+
nextState = updateCellData({
|
|
774
|
+
state: nextState,
|
|
775
|
+
cellId,
|
|
776
|
+
cellReducer: (cell) => ({
|
|
777
|
+
...cell,
|
|
778
|
+
lastCodeRun: cell.code.trim(),
|
|
779
|
+
edited: false,
|
|
780
|
+
}),
|
|
781
|
+
});
|
|
782
|
+
}
|
|
766
783
|
return {
|
|
767
784
|
...nextState,
|
|
768
785
|
cellLogs: [...nextState.cellLogs, ...getCellLogsForMessage(message)],
|
|
@@ -1405,6 +1422,12 @@ const {
|
|
|
1405
1422
|
},
|
|
1406
1423
|
});
|
|
1407
1424
|
|
|
1425
|
+
// We apply the middleware here (rather than inline in createReducerAndAtoms)
|
|
1426
|
+
// so that the document transaction middleware can import CellActions and
|
|
1427
|
+
// strictly type the dispatched actions without creating a circular dependency.
|
|
1428
|
+
// @ts-expect-error - TODO: We should have better types for the middleware that are strict
|
|
1429
|
+
addMiddleware(documentTransactionMiddleware);
|
|
1430
|
+
|
|
1408
1431
|
function isCellCodeHidden(state: NotebookState, cellId: CellId): boolean {
|
|
1409
1432
|
return (
|
|
1410
1433
|
Boolean(state.cellData[cellId].config.hide_code) &&
|
|
@@ -1789,8 +1812,10 @@ export function createTracebackInfoAtom(
|
|
|
1789
1812
|
* Use this hook to dispatch cell actions. This hook will not cause a re-render
|
|
1790
1813
|
* when cells change.
|
|
1791
1814
|
*/
|
|
1792
|
-
export function useCellActions(
|
|
1793
|
-
|
|
1815
|
+
export function useCellActions(
|
|
1816
|
+
options: { skipMiddleware?: boolean } = {},
|
|
1817
|
+
): CellActions {
|
|
1818
|
+
return useActions(options);
|
|
1794
1819
|
}
|
|
1795
1820
|
|
|
1796
1821
|
/**
|