@marimo-team/frontend 0.21.2-dev37 → 0.21.2-dev40
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/assets/{CellStatus-DYdGvia_.js → CellStatus-IHJk0CT8.js} +1 -1
- package/dist/assets/{JsonOutput-CN6rPeEV.js → JsonOutput-BIbkaOuk.js} +9 -9
- package/dist/assets/{MarimoErrorOutput-BhfAlCn4.js → MarimoErrorOutput-hYOXA8Ml.js} +5 -5
- package/dist/assets/{RenderHTML-BS4HOKgA.js → RenderHTML-DduaBOBv.js} +1 -1
- package/dist/assets/{add-cell-with-ai-pEba6oGB.js → add-cell-with-ai-Cbktc1B0.js} +9 -9
- package/dist/assets/{add-connection-dialog-9odisycO.js → add-connection-dialog-BewAq3li.js} +23 -23
- package/dist/assets/{agent-panel-BSEF-vxf.js → agent-panel-CtAqa-P9.js} +5 -5
- package/dist/assets/{ai-model-dropdown-CBQHQst1.js → ai-model-dropdown-DgMZ5T_L.js} +3 -3
- package/dist/assets/{app-config-button-XC0eJuj1.js → app-config-button-BLGBmcfT.js} +1 -1
- package/dist/assets/{azure-Cl-hv4CT.js → azure-BeB26UeM.js} +1 -1
- package/dist/assets/{cell-editor-CtnuCOtA.js → cell-editor-Ti3F6axu.js} +12 -13
- package/dist/assets/{cell-link-D8ZUYcpP.js → cell-link-BEnixmCb.js} +1 -1
- package/dist/assets/{cells-DZyIQGyJ.js → cells-DqKJsMUm.js} +79 -78
- package/dist/assets/{chat-display-CvRHSFG6.js → chat-display-B0hV2K6L.js} +1 -1
- package/dist/assets/{chat-panel-BAGhr_FT.js → chat-panel-CNGIGWIs.js} +2 -2
- package/dist/assets/{column-preview-BuB6sz5V.js → column-preview-CVqBaB8R.js} +1 -1
- package/dist/assets/{command-DxWyVVPx.js → command-DpusMohg.js} +1 -1
- package/dist/assets/{command-palette-BjbqAF2r.js → command-palette-BfuIslSf.js} +1 -1
- package/dist/assets/{common-DJx7lN8H.js → common-CYWtZYKm.js} +1 -1
- package/dist/assets/{components-ENebof0d.js → components-C4dDqD7U.js} +1 -1
- package/dist/assets/{components-DSj55gbq.js → components-DZQ7ndNS.js} +1 -1
- package/dist/assets/{context-aware-panel-C4GJI0g0.js → context-aware-panel-DEVrXLoa.js} +3 -3
- package/dist/assets/{datasource-Be25L0nm.js → datasource-Bo8w993m.js} +2 -2
- package/dist/assets/{dependency-graph-panel-DwIVdeIJ.js → dependency-graph-panel-u9oPy09H.js} +4 -4
- package/dist/assets/{documentation-panel-78VOc9_O.js → documentation-panel-BQRmNRb_.js} +1 -1
- package/dist/assets/{download-BlNsDzA2.js → download-DtyAt8iO.js} +1 -1
- package/dist/assets/{edit-page-vExGqsee.js → edit-page-Cqvk7zWH.js} +7 -7
- package/dist/assets/{error-panel-D8Yl4tpB.js → error-panel-DclemF57.js} +1 -1
- package/dist/assets/{file-explorer-panel-CbIYi1SW.js → file-explorer-panel-D706RRJ-.js} +3 -3
- package/dist/assets/{file-icons-zgA9qh-d.js → file-icons-D4HcGlr_.js} +1 -1
- package/dist/assets/{floating-outline-vyq-JnTK.js → floating-outline-B86gVj23.js} +1 -1
- package/dist/assets/{focus-Cnr-VB8o.js → focus-B85PAbhR.js} +1 -1
- package/dist/assets/{form-LO1BJ8WB.js → form--K3o18rQ.js} +2 -2
- package/dist/assets/{globals-3fE4PBWj.js → globals-C_t1YYpc.js} +1 -1
- package/dist/assets/{home-page-DFcaf-s1.js → home-page-C5LO1JXE.js} +1 -1
- package/dist/assets/{hooks-NxoY-x2K.js → hooks-W-qT5c6l.js} +1 -1
- package/dist/assets/{html-to-image-DDWA96Ex.js → html-to-image-CoMmxXBd.js} +1 -1
- package/dist/assets/{index-OH-GH0bF.js → index-BSzIstPK.js} +14 -14
- package/dist/assets/{kiosk-mode-D4FbpWVp.js → kiosk-mode-zv0zIGqw.js} +1 -1
- package/dist/assets/{layout-qNHT912R.js → layout-C_JVKYrz.js} +3 -3
- package/dist/assets/{logs-panel-14Cp2UUn.js → logs-panel-DowtOCA5.js} +1 -1
- package/dist/assets/{markdown-renderer-CH1ffrUG.js → markdown-renderer-CNaYgTOF.js} +1 -1
- package/dist/assets/{mode-OBdgd6Zz.js → mode-Bn_XF6AW.js} +1 -1
- package/dist/assets/{name-cell-input-BmkGdvnh.js → name-cell-input-CVt9kv6F.js} +1 -1
- package/dist/assets/{outline-panel-Bn1SN1eu.js → outline-panel-ClI23gcy.js} +1 -1
- package/dist/assets/{packages-panel-Cyb4BUmM.js → packages-panel-BW2m-sNe.js} +1 -1
- package/dist/assets/{panels-DfEUpHpA.js → panels-B2DAaT1E.js} +1 -1
- package/dist/assets/{process-output-CC4VhdkC.js → process-output-BewZuQwI.js} +1 -1
- package/dist/assets/{readonly-python-code-Cq9EKL61.js → readonly-python-code-BgTK_w0H.js} +1 -1
- package/dist/assets/{run-page-Df9bi2J7.js → run-page-DMpRvHgf.js} +1 -1
- package/dist/assets/{scratchpad-panel-vKbONRfT.js → scratchpad-panel-ClDi2sdV.js} +1 -1
- package/dist/assets/{session-panel-DPoC2CoL.js → session-panel-C-RbWN-G.js} +1 -1
- package/dist/assets/{snippets-panel-D7W6PE7E.js → snippets-panel-DCdeI2hB.js} +1 -1
- package/dist/assets/{state-Br7baqTT.js → state-CJ2HIW-e.js} +1 -1
- package/dist/assets/{switch-Cds8TleW.js → switch-O_7alg7G.js} +1 -1
- package/dist/assets/tracing-BxcUfhUv.js +1 -0
- package/dist/assets/{tracing-panel-BpKr5n4H.js → tracing-panel-DK4YfdoZ.js} +2 -2
- package/dist/assets/{useAddCell-XcxY_cZw.js → useAddCell-BpBkEpP6.js} +1 -1
- package/dist/assets/{useBoolean-0C18DvVA.js → useBoolean-Cb23qnhy.js} +1 -1
- package/dist/assets/{useCellActionButton-DFNSBzoc.js → useCellActionButton-fJ6SGX-Z.js} +1 -1
- package/dist/assets/{useDeleteCell-DLdqnODD.js → useDeleteCell-B4nKRnTM.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-_E0t8nfy.js → useDependencyPanelTab-BUjZxWnG.js} +1 -1
- package/dist/assets/{useNotebookActions-DlbYUPWD.js → useNotebookActions-CooxVonM.js} +1 -1
- package/dist/assets/{useRunCells-YR_s_yuq.js → useRunCells-D5wCIJdU.js} +1 -1
- package/dist/assets/{useSplitCell-BNkvoKCq.js → useSplitCell-D8kqiCTS.js} +1 -1
- package/dist/index.html +32 -32
- package/package.json +1 -1
- package/src/__mocks__/notebook.ts +9 -9
- package/src/__tests__/branded.ts +20 -0
- package/src/components/data-table/charts/__tests__/storage.test.ts +7 -7
- 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/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-inspector.tsx +1 -2
- package/src/components/tracing/tracing.tsx +3 -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__/cells.test.ts +192 -135
- 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 +1 -1
- 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/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/lsp/__tests__/notebook-lsp.test.ts +4 -3
- 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/main.ts +2 -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/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/websocket/useMarimoKernelConnection.tsx +12 -15
- 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 +19 -18
- package/src/utils/json/base64.ts +3 -3
- package/src/utils/traceback.ts +5 -3
- package/dist/assets/tracing-DFGiZoMP.js +0 -1
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { closeCompletion, completionStatus } from "@codemirror/autocomplete";
|
|
4
4
|
import { type Extension, Prec } from "@codemirror/state";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
EditorView,
|
|
7
|
+
type KeyBinding,
|
|
8
|
+
keymap,
|
|
9
|
+
type ViewUpdate,
|
|
10
|
+
} from "@codemirror/view";
|
|
6
11
|
import { createTracebackInfoAtom } from "@/core/cells/cells";
|
|
7
12
|
import { type CellId, HTMLCellId, SCRATCH_CELL_ID } from "@/core/cells/ids";
|
|
13
|
+
import { loroSyncAnnotation } from "@/core/codemirror/rtc/loro/sync";
|
|
8
14
|
import type { KeymapConfig } from "@/core/config/config-schema";
|
|
9
15
|
import type { HotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
10
16
|
import { duplicateWithCtrlModifier } from "@/core/hotkeys/shortcuts";
|
|
@@ -330,6 +336,53 @@ function cellCodeEditing(hotkeys: HotkeyProvider): Extension[] {
|
|
|
330
336
|
return [onChangePlugin, formatKeymapExtension(hotkeys)];
|
|
331
337
|
}
|
|
332
338
|
|
|
339
|
+
const MARKDOWN_AUTORUN_USER_EVENTS = ["input", "delete", "undo", "redo"];
|
|
340
|
+
|
|
341
|
+
function shouldAutorunMarkdownUpdate({
|
|
342
|
+
docChanged,
|
|
343
|
+
transactions,
|
|
344
|
+
predicate = () => true,
|
|
345
|
+
hasFocus = false,
|
|
346
|
+
}: Pick<ViewUpdate, "docChanged" | "transactions"> & {
|
|
347
|
+
predicate?: () => boolean;
|
|
348
|
+
hasFocus?: boolean;
|
|
349
|
+
}): boolean {
|
|
350
|
+
// If the doc didn't change, ignore.
|
|
351
|
+
if (!docChanged) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// The caller decides when markdown autorun is allowed, e.g. not for
|
|
356
|
+
// f-strings where rerunning on every keystroke is usually incorrect.
|
|
357
|
+
if (!predicate()) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// This happens on mount when we start in markdown mode.
|
|
362
|
+
// Ignore formatting changes so language switches don't trigger autorun.
|
|
363
|
+
const isFormattingChange = transactions.some((tr) =>
|
|
364
|
+
tr.effects.some((effect) => effect.is(formattingChangeEffect)),
|
|
365
|
+
);
|
|
366
|
+
if (isFormattingChange) {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return transactions.some((tr) => {
|
|
371
|
+
// Ignore RTC sync changes to avoid duplicate runs from remote edits.
|
|
372
|
+
if (tr.annotation(loroSyncAnnotation) !== undefined) {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Prefer explicit local edit transactions, but keep a focused fallback for
|
|
377
|
+
// local rewrite paths like split-cell, which can update markdown content
|
|
378
|
+
// without annotating a user event.
|
|
379
|
+
return (
|
|
380
|
+
MARKDOWN_AUTORUN_USER_EVENTS.some((kind) => tr.isUserEvent(kind)) ||
|
|
381
|
+
hasFocus
|
|
382
|
+
);
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
333
386
|
/**
|
|
334
387
|
* Extension for auto-running markdown cells
|
|
335
388
|
*/
|
|
@@ -339,30 +392,16 @@ export function markdownAutoRunExtension({
|
|
|
339
392
|
predicate: () => boolean;
|
|
340
393
|
}): Extension {
|
|
341
394
|
return EditorView.updateListener.of((update) => {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (!predicate()) {
|
|
395
|
+
if (
|
|
396
|
+
!shouldAutorunMarkdownUpdate({
|
|
397
|
+
docChanged: update.docChanged,
|
|
398
|
+
transactions: update.transactions,
|
|
399
|
+
predicate,
|
|
400
|
+
hasFocus: update.view.hasFocus,
|
|
401
|
+
})
|
|
402
|
+
) {
|
|
354
403
|
return;
|
|
355
404
|
}
|
|
356
|
-
|
|
357
|
-
// This happens on mount when we start in markdown mode
|
|
358
|
-
const isFormattingChange = update.transactions.some((tr) =>
|
|
359
|
-
tr.effects.some((effect) => effect.is(formattingChangeEffect)),
|
|
360
|
-
);
|
|
361
|
-
if (isFormattingChange) {
|
|
362
|
-
// Ignore formatting changes
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
405
|
const actions = update.view.state.facet(cellActionsState);
|
|
367
406
|
actions.onRun();
|
|
368
407
|
});
|
|
@@ -388,3 +427,7 @@ export function cellBundle({
|
|
|
388
427
|
),
|
|
389
428
|
];
|
|
390
429
|
}
|
|
430
|
+
|
|
431
|
+
export const exportedForTesting = {
|
|
432
|
+
shouldAutorunMarkdownUpdate,
|
|
433
|
+
};
|
|
@@ -3,28 +3,27 @@
|
|
|
3
3
|
import { EditorState } from "@codemirror/state";
|
|
4
4
|
import { EditorView } from "@codemirror/view";
|
|
5
5
|
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { cellId, variableName } from "@/__tests__/branded";
|
|
6
7
|
import { initialNotebookState, notebookAtom } from "@/core/cells/cells";
|
|
7
|
-
import type { CellId } from "@/core/cells/ids";
|
|
8
8
|
import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
9
9
|
import { store } from "@/core/state/jotai";
|
|
10
10
|
import { variablesAtom } from "@/core/variables/state";
|
|
11
|
-
import type { VariableName, Variables } from "@/core/variables/types";
|
|
12
11
|
import { MultiColumn } from "@/utils/id-tree";
|
|
13
12
|
import { cellConfigExtension } from "../../config/extension";
|
|
14
13
|
import { adaptiveLanguageConfiguration } from "../../language/extension";
|
|
15
14
|
import { getCodes, getTopologicalCellIds } from "../getCodes";
|
|
16
15
|
|
|
17
16
|
const Cells = {
|
|
18
|
-
cell1: "cell1"
|
|
19
|
-
cell2: "cell2"
|
|
20
|
-
cell3: "cell3"
|
|
21
|
-
cell4: "cell4"
|
|
17
|
+
cell1: cellId("cell1"),
|
|
18
|
+
cell2: cellId("cell2"),
|
|
19
|
+
cell3: cellId("cell3"),
|
|
20
|
+
cell4: cellId("cell4"),
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
const Variables = {
|
|
25
|
-
var1: "var1"
|
|
26
|
-
var2: "var2"
|
|
27
|
-
var3: "var3"
|
|
24
|
+
var1: variableName("var1"),
|
|
25
|
+
var2: variableName("var2"),
|
|
26
|
+
var3: variableName("var3"),
|
|
28
27
|
};
|
|
29
28
|
|
|
30
29
|
function createMockEditorView(code: string) {
|
|
@@ -33,7 +32,7 @@ function createMockEditorView(code: string) {
|
|
|
33
32
|
doc: code,
|
|
34
33
|
extensions: [
|
|
35
34
|
adaptiveLanguageConfiguration({
|
|
36
|
-
cellId: "cell1"
|
|
35
|
+
cellId: cellId("cell1"),
|
|
37
36
|
completionConfig: {
|
|
38
37
|
copilot: false,
|
|
39
38
|
activate_on_typing: true,
|
|
@@ -45,7 +44,7 @@ function createMockEditorView(code: string) {
|
|
|
45
44
|
lspConfig: {},
|
|
46
45
|
}),
|
|
47
46
|
cellConfigExtension({
|
|
48
|
-
cellId: "cell1"
|
|
47
|
+
cellId: cellId("cell1"),
|
|
49
48
|
completionConfig: {
|
|
50
49
|
copilot: false,
|
|
51
50
|
activate_on_typing: true,
|
|
@@ -71,7 +70,7 @@ describe("getTopologicalCellIds", () => {
|
|
|
71
70
|
it("should return topologically sorted cell IDs", () => {
|
|
72
71
|
// Setup mock data
|
|
73
72
|
const cellIds = [Cells.cell1, Cells.cell2, Cells.cell3, Cells.cell4];
|
|
74
|
-
const variables
|
|
73
|
+
const variables = {
|
|
75
74
|
[Variables.var1]: {
|
|
76
75
|
name: Variables.var1,
|
|
77
76
|
declaredBy: [Cells.cell1],
|
|
@@ -125,7 +124,7 @@ describe("getTopologicalCellIds", () => {
|
|
|
125
124
|
|
|
126
125
|
it("should put new cells (with no dependencies) at the end", () => {
|
|
127
126
|
const cellIds = [Cells.cell1, Cells.cell2, Cells.cell3, Cells.cell4];
|
|
128
|
-
const variables
|
|
127
|
+
const variables = {
|
|
129
128
|
[Variables.var1]: {
|
|
130
129
|
name: Variables.var1,
|
|
131
130
|
declaredBy: [Cells.cell2],
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { EditorState } from "@codemirror/state";
|
|
4
4
|
import { EditorView } from "@codemirror/view";
|
|
5
5
|
import { describe, expect, it } from "vitest";
|
|
6
|
-
import
|
|
6
|
+
import { cellId } from "@/__tests__/branded";
|
|
7
7
|
import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
8
8
|
import { cellConfigExtension } from "../../config/extension";
|
|
9
9
|
import { adaptiveLanguageConfiguration, switchLanguage } from "../extension";
|
|
@@ -26,12 +26,12 @@ function createEditor(doc: string) {
|
|
|
26
26
|
codeium_api_key: null,
|
|
27
27
|
},
|
|
28
28
|
hotkeys: new OverridingHotkeyProvider({}),
|
|
29
|
-
cellId: "cell1"
|
|
29
|
+
cellId: cellId("cell1"),
|
|
30
30
|
placeholderType: "marimo-import",
|
|
31
31
|
lspConfig: {},
|
|
32
32
|
}),
|
|
33
33
|
cellConfigExtension({
|
|
34
|
-
cellId: "cell1"
|
|
34
|
+
cellId: cellId("cell1"),
|
|
35
35
|
completionConfig: {
|
|
36
36
|
activate_on_typing: true,
|
|
37
37
|
signature_hint_on_typing: false,
|
|
@@ -5,10 +5,9 @@ import { python } from "@codemirror/lang-python";
|
|
|
5
5
|
import { EditorState } from "@codemirror/state";
|
|
6
6
|
import type { InlineContext } from "@lezer/markdown";
|
|
7
7
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
8
|
-
import
|
|
8
|
+
import { cellId, variableName } from "@/__tests__/branded";
|
|
9
9
|
import { store } from "@/core/state/jotai";
|
|
10
10
|
import { variablesAtom } from "@/core/variables/state";
|
|
11
|
-
import type { VariableName, Variables } from "@/core/variables/types";
|
|
12
11
|
import { parsePython, variableCompletionSource } from "../embedded-python";
|
|
13
12
|
|
|
14
13
|
const IS_ACTIVE = () => true;
|
|
@@ -51,16 +50,16 @@ describe("parsePython", () => {
|
|
|
51
50
|
|
|
52
51
|
describe("variableCompletionSource", () => {
|
|
53
52
|
beforeEach(() => {
|
|
54
|
-
const mockCellId = "cell-1"
|
|
55
|
-
const mockVariables
|
|
56
|
-
["var1"
|
|
57
|
-
name: "var1"
|
|
53
|
+
const mockCellId = cellId("cell-1");
|
|
54
|
+
const mockVariables = {
|
|
55
|
+
[variableName("var1")]: {
|
|
56
|
+
name: variableName("var1"),
|
|
58
57
|
dataType: "int",
|
|
59
58
|
declaredBy: [mockCellId],
|
|
60
59
|
usedBy: [mockCellId],
|
|
61
60
|
},
|
|
62
|
-
["var2"
|
|
63
|
-
name: "var2"
|
|
61
|
+
[variableName("var2")]: {
|
|
62
|
+
name: variableName("var2"),
|
|
64
63
|
dataType: "str",
|
|
65
64
|
declaredBy: [mockCellId],
|
|
66
65
|
usedBy: [mockCellId],
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from "@marimo-team/codemirror-languageserver";
|
|
9
9
|
import { beforeEach, describe, expect, it, type Mocked, vi } from "vitest";
|
|
10
10
|
import * as LSP from "vscode-languageserver-protocol";
|
|
11
|
+
import { cellId } from "@/__tests__/branded";
|
|
11
12
|
import type { CellId } from "@/core/cells/ids";
|
|
12
13
|
import { store } from "@/core/state/jotai";
|
|
13
14
|
import { topologicalCodesAtom } from "../../copilot/getCodes";
|
|
@@ -19,9 +20,9 @@ import { NotebookLanguageServerClient } from "../notebook-lsp";
|
|
|
19
20
|
import { CellDocumentUri, type ILanguageServerClient } from "../types";
|
|
20
21
|
|
|
21
22
|
const Cells = {
|
|
22
|
-
cell1: "cell1"
|
|
23
|
-
cell2: "cell2"
|
|
24
|
-
cell3: "cell3"
|
|
23
|
+
cell1: cellId("cell1"),
|
|
24
|
+
cell2: cellId("cell2"),
|
|
25
|
+
cell3: cellId("cell3"),
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
describe("createNotebookLens", () => {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import { python } from "@codemirror/lang-python";
|
|
4
4
|
import { EditorState } from "@codemirror/state";
|
|
5
5
|
import { describe, expect, test } from "vitest";
|
|
6
|
-
import
|
|
7
|
-
import type {
|
|
6
|
+
import { cellId, variableName } from "@/__tests__/branded";
|
|
7
|
+
import type { Variables } from "@/core/variables/types";
|
|
8
8
|
import { findReactiveVariables, type ReactiveVariableRange } from "../analyzer";
|
|
9
9
|
|
|
10
10
|
describe("findReactiveVariables - Lexical Scoping", () => {
|
|
@@ -1199,16 +1199,17 @@ class Foo:
|
|
|
1199
1199
|
function runHighlight(variableNames: string[], code: string): string {
|
|
1200
1200
|
const variables: Variables = {};
|
|
1201
1201
|
for (const name of variableNames) {
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1202
|
+
const varName = variableName(name);
|
|
1203
|
+
variables[varName] = {
|
|
1204
|
+
name: varName,
|
|
1205
|
+
declaredBy: [cellId("other-cell")],
|
|
1205
1206
|
usedBy: [],
|
|
1206
1207
|
value: "test-value",
|
|
1207
1208
|
dataType: "str",
|
|
1208
1209
|
};
|
|
1209
1210
|
}
|
|
1210
1211
|
const ranges = findReactiveVariables({
|
|
1211
|
-
cellId: "current-cell"
|
|
1212
|
+
cellId: cellId("current-cell"),
|
|
1212
1213
|
state: EditorState.create({
|
|
1213
1214
|
doc: code,
|
|
1214
1215
|
extensions: [python()],
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { syntaxTree } from "@codemirror/language";
|
|
4
4
|
import type { EditorState } from "@codemirror/state";
|
|
5
5
|
import type { SyntaxNode, Tree, TreeCursor } from "@lezer/common";
|
|
6
|
-
import type
|
|
6
|
+
import { type CellId, SETUP_CELL_ID } from "@/core/cells/ids";
|
|
7
7
|
import type { VariableName, Variables } from "@/core/variables/types";
|
|
8
8
|
|
|
9
9
|
export interface ReactiveVariableRange {
|
|
@@ -52,7 +52,7 @@ export function findReactiveVariables(options: {
|
|
|
52
52
|
const variable = options.variables[name as VariableName];
|
|
53
53
|
return (
|
|
54
54
|
variable.dataType !== "module" &&
|
|
55
|
-
!variable.declaredBy.includes(
|
|
55
|
+
!variable.declaredBy.includes(SETUP_CELL_ID) &&
|
|
56
56
|
!variable.declaredBy.includes(options.cellId)
|
|
57
57
|
);
|
|
58
58
|
}),
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { EditorState } from "@codemirror/state";
|
|
4
|
+
import type { EditorView } from "@codemirror/view";
|
|
5
|
+
import { LoroDoc, LoroText } from "loro-crdt";
|
|
6
|
+
import { describe, expect, it, vi } from "vitest";
|
|
7
|
+
import { LoroSyncPluginValue, loroSyncAnnotation } from "../sync";
|
|
8
|
+
|
|
9
|
+
describe("LoroSyncPluginValue", () => {
|
|
10
|
+
it("annotates the initial reconciliation dispatch as RTC sync", async () => {
|
|
11
|
+
const dispatch = vi.fn();
|
|
12
|
+
const view = {
|
|
13
|
+
state: EditorState.create({ doc: "local" }),
|
|
14
|
+
dispatch,
|
|
15
|
+
} as unknown as EditorView;
|
|
16
|
+
|
|
17
|
+
const doc = new LoroDoc();
|
|
18
|
+
const text = doc
|
|
19
|
+
.getMap("codes")
|
|
20
|
+
.getOrCreateContainer("cell-1", new LoroText());
|
|
21
|
+
text.insert(0, "remote");
|
|
22
|
+
|
|
23
|
+
const plugin = new LoroSyncPluginValue(
|
|
24
|
+
view,
|
|
25
|
+
doc,
|
|
26
|
+
["codes", "cell-1"],
|
|
27
|
+
() => text,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
await Promise.resolve();
|
|
31
|
+
|
|
32
|
+
expect(dispatch).toHaveBeenCalledTimes(1);
|
|
33
|
+
expect(dispatch).toHaveBeenCalledWith(
|
|
34
|
+
expect.objectContaining({
|
|
35
|
+
changes: [
|
|
36
|
+
{
|
|
37
|
+
from: 0,
|
|
38
|
+
to: view.state.doc.length,
|
|
39
|
+
insert: "remote",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
annotations: [
|
|
43
|
+
expect.objectContaining({
|
|
44
|
+
type: loroSyncAnnotation,
|
|
45
|
+
}),
|
|
46
|
+
],
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
plugin.destroy();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
3
|
+
import { variableName } from "@/__tests__/branded";
|
|
3
4
|
import type { DataTable } from "@/core/kernel/messages";
|
|
4
5
|
import type { VariableName } from "@/core/variables/types";
|
|
5
6
|
import {
|
|
@@ -182,7 +183,7 @@ describe("filtering data sources", () => {
|
|
|
182
183
|
});
|
|
183
184
|
|
|
184
185
|
it("keeps matching variables and internal engines", () => {
|
|
185
|
-
const filtered = filterDataSources(["conn1"
|
|
186
|
+
const filtered = filterDataSources([variableName("conn1")]);
|
|
186
187
|
expect(filtered.connectionsMap.size).toBe(defaultConnSize + 1);
|
|
187
188
|
expect(filtered.connectionsMap.has("conn1" as ConnectionName)).toBe(true);
|
|
188
189
|
for (const engine of INTERNAL_SQL_ENGINES) {
|
|
@@ -191,16 +192,14 @@ describe("filtering data sources", () => {
|
|
|
191
192
|
});
|
|
192
193
|
|
|
193
194
|
it("filters out non-matching variables", () => {
|
|
194
|
-
const filtered = filterDataSources([
|
|
195
|
-
"non_existent" as unknown as VariableName,
|
|
196
|
-
]);
|
|
195
|
+
const filtered = filterDataSources([variableName("non_existent")]);
|
|
197
196
|
expect(filtered.connectionsMap.size).toBe(defaultConnSize);
|
|
198
197
|
});
|
|
199
198
|
|
|
200
199
|
it("handles mix of matching and non-matching variables", () => {
|
|
201
200
|
const filtered = filterDataSources([
|
|
202
|
-
"conn1"
|
|
203
|
-
"non_existent"
|
|
201
|
+
variableName("conn1"),
|
|
202
|
+
variableName("non_existent"),
|
|
204
203
|
]);
|
|
205
204
|
expect(filtered.connectionsMap.size).toBe(defaultConnSize + 1);
|
|
206
205
|
expect(filtered.connectionsMap.has("conn1" as ConnectionName)).toBe(true);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { cellId } from "@/__tests__/branded";
|
|
3
4
|
import type { MarimoError } from "@/core/kernel/messages";
|
|
4
5
|
import { getAutoFixes, getImportCode } from "../errors";
|
|
5
6
|
|
|
@@ -25,7 +26,7 @@ describe("getAutoFixes", () => {
|
|
|
25
26
|
const error: MarimoError = {
|
|
26
27
|
type: "multiple-defs",
|
|
27
28
|
name: "foo",
|
|
28
|
-
cells: ["foo"],
|
|
29
|
+
cells: [cellId("foo")],
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
const fixes = getAutoFixes(error, opts);
|