@marimo-team/islands 0.23.14-dev17 → 0.23.14-dev19
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/{chat-ui-C6y6xLcn.js → chat-ui-9wA4feLE.js} +3034 -3034
- package/dist/{code-visibility-Cb6UrZYv.js → code-visibility-CxDvzm2S.js} +90 -90
- package/dist/{html-to-image-DcTkcjmm.js → html-to-image-DBHfshED.js} +63 -62
- package/dist/main.js +1111 -1090
- package/dist/{process-output-2FbS8KgW.js → process-output-Dw6We6B6.js} +1 -1
- package/dist/{reveal-component-BFhE2zHY.js → reveal-component-tJhA77Am.js} +2 -2
- package/package.json +1 -1
- package/src/components/editor/chrome/panels/snippets-panel.tsx +3 -3
- package/src/components/editor/code/readonly-python-code.tsx +16 -2
- package/src/components/editor/renderers/vertical-layout/__tests__/vertical-layout.test.ts +1 -27
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +2 -19
- package/src/components/slides/slide-cell-view.tsx +7 -6
- package/src/core/cells/__tests__/readonly-code-display.test.ts +46 -0
- package/src/core/cells/readonly-code-display.ts +35 -0
- package/src/components/editor/chrome/panels/__tests__/snippet-display.test.ts +0 -22
- package/src/components/editor/chrome/panels/snippet-display.ts +0 -27
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
2
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
3
|
-
import { at as parseHtmlContent, it as ansiToPlainText } from "./html-to-image-
|
|
3
|
+
import { at as parseHtmlContent, it as ansiToPlainText } from "./html-to-image-DBHfshED.js";
|
|
4
4
|
import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
|
|
5
5
|
import { t as Strings } from "./strings-Dq_j3Rxw.js";
|
|
6
6
|
import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
|
|
@@ -6,10 +6,10 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
|
6
6
|
import { _ as Logger, g as cn, h as Events, l as useEventListener, t as Button } from "./button-BacYv-bE.js";
|
|
7
7
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
8
8
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
9
|
-
import { lt as kioskModeAtom } from "./html-to-image-
|
|
9
|
+
import { lt as kioskModeAtom } from "./html-to-image-DBHfshED.js";
|
|
10
10
|
import "./chunk-5FQGJX7Z-BbqSm5gU.js";
|
|
11
11
|
import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
|
|
12
|
-
import { a as DEFAULT_SLIDE_TYPE, c as Slide, ct as PanelGroup, i as DEFAULT_DECK_TRANSITION, lt as PanelResizeHandle, on as EyeOff, s as SlideSidebar, sn as Expand, st as Panel, t as useNotebookCodeAvailable, un as Code } from "./code-visibility-
|
|
12
|
+
import { a as DEFAULT_SLIDE_TYPE, c as Slide, ct as PanelGroup, i as DEFAULT_DECK_TRANSITION, lt as PanelResizeHandle, on as EyeOff, s as SlideSidebar, sn as Expand, st as Panel, t as useNotebookCodeAvailable, un as Code } from "./code-visibility-CxDvzm2S.js";
|
|
13
13
|
import { X as useDebouncedCallback } from "./input-BSdZp5Ng.js";
|
|
14
14
|
import "./toDate-D1Z7ZXWh.js";
|
|
15
15
|
import "./react-dom-BTJzcVJ9.js";
|
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ import { cn } from "@/utils/cn";
|
|
|
31
31
|
import { HideInKioskMode } from "../../kiosk-mode";
|
|
32
32
|
import { ContributeSnippetButton } from "../components/contribute-snippet-button";
|
|
33
33
|
import { usePanelOrientation, usePanelSection } from "./panel-context";
|
|
34
|
-
import {
|
|
34
|
+
import { getReadonlyCodeDisplay } from "@/core/cells/readonly-code-display";
|
|
35
35
|
|
|
36
36
|
const extensions = [EditorView.lineWrapping];
|
|
37
37
|
|
|
@@ -188,7 +188,7 @@ const SnippetViewer: React.FC<{ snippet: Snippet; onClose: () => void }> = ({
|
|
|
188
188
|
return null;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
const { language,
|
|
191
|
+
const { language, code: displayCode } = getReadonlyCodeDisplay(code);
|
|
192
192
|
|
|
193
193
|
return (
|
|
194
194
|
<div
|
|
@@ -216,7 +216,7 @@ const SnippetViewer: React.FC<{ snippet: Snippet; onClose: () => void }> = ({
|
|
|
216
216
|
language={language}
|
|
217
217
|
className="cm border rounded overflow-hidden"
|
|
218
218
|
extensions={extensions}
|
|
219
|
-
value={
|
|
219
|
+
value={displayCode}
|
|
220
220
|
readOnly={true}
|
|
221
221
|
/>
|
|
222
222
|
</Suspense>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
+
import { markdown } from "@codemirror/lang-markdown";
|
|
3
4
|
import { sql } from "@codemirror/lang-sql";
|
|
4
5
|
import CodeMirror, {
|
|
5
6
|
EditorView,
|
|
@@ -11,6 +12,7 @@ import { useAddCodeToNewCell } from "@/components/editor/cell/useAddCell";
|
|
|
11
12
|
import { Button } from "@/components/ui/button";
|
|
12
13
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
13
14
|
import { toast } from "@/components/ui/use-toast";
|
|
15
|
+
import type { LanguageAdapterType } from "@/core/codemirror/language/types";
|
|
14
16
|
import { customPythonLanguageSupport } from "@/core/codemirror/language/languages/python";
|
|
15
17
|
import { useTheme } from "@/theme/useTheme";
|
|
16
18
|
import { cn } from "@/utils/cn";
|
|
@@ -22,6 +24,18 @@ const pythonExtensions = [
|
|
|
22
24
|
EditorView.lineWrapping,
|
|
23
25
|
];
|
|
24
26
|
const sqlExtensions = [sql(), EditorView.lineWrapping];
|
|
27
|
+
const markdownExtensions = [markdown(), EditorView.lineWrapping];
|
|
28
|
+
|
|
29
|
+
function readonlyCodeExtensions(language: LanguageAdapterType) {
|
|
30
|
+
switch (language) {
|
|
31
|
+
case "sql":
|
|
32
|
+
return sqlExtensions;
|
|
33
|
+
case "markdown":
|
|
34
|
+
return markdownExtensions;
|
|
35
|
+
default:
|
|
36
|
+
return pythonExtensions;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
25
39
|
|
|
26
40
|
/**
|
|
27
41
|
* A readonly code component that can be used to display code in a readonly state.
|
|
@@ -42,7 +56,7 @@ export const ReadonlyCode = memo(
|
|
|
42
56
|
showHideCode?: boolean;
|
|
43
57
|
showCopyCode?: boolean;
|
|
44
58
|
insertNewCell?: boolean;
|
|
45
|
-
language?:
|
|
59
|
+
language?: LanguageAdapterType;
|
|
46
60
|
} & ReactCodeMirrorProps,
|
|
47
61
|
) => {
|
|
48
62
|
const { theme } = useTheme();
|
|
@@ -84,7 +98,7 @@ export const ReadonlyCode = memo(
|
|
|
84
98
|
theme={theme === "dark" ? "dark" : "light"}
|
|
85
99
|
height="100%"
|
|
86
100
|
editable={!hideCode}
|
|
87
|
-
extensions={language
|
|
101
|
+
extensions={readonlyCodeExtensions(language)}
|
|
88
102
|
value={code}
|
|
89
103
|
readOnly={true}
|
|
90
104
|
/>
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
/* oxlint-disable typescript/no-explicit-any */
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
4
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
5
|
-
import {
|
|
6
|
-
groupCellsByColumn,
|
|
7
|
-
readonlyDisplay,
|
|
8
|
-
shouldHideCode,
|
|
9
|
-
} from "../vertical-layout";
|
|
5
|
+
import { groupCellsByColumn, shouldHideCode } from "../vertical-layout";
|
|
10
6
|
|
|
11
7
|
describe("groupCellsByColumn", () => {
|
|
12
8
|
it("should group cells by column and maintain order", () => {
|
|
@@ -175,25 +171,3 @@ describe("shouldHideCode", () => {
|
|
|
175
171
|
});
|
|
176
172
|
});
|
|
177
173
|
});
|
|
178
|
-
|
|
179
|
-
describe("readonlyDisplay", () => {
|
|
180
|
-
it("unwraps SQL cells to their inner query and marks them as sql", () => {
|
|
181
|
-
const result = readonlyDisplay('my_table = mo.sql("""SELECT 1 AS id""")');
|
|
182
|
-
expect(result.language).toBe("sql");
|
|
183
|
-
expect(result.code).toBe("SELECT 1 AS id");
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it("leaves plain Python cells untouched", () => {
|
|
187
|
-
const code = "x = 1 + 2";
|
|
188
|
-
const result = readonlyDisplay(code);
|
|
189
|
-
expect(result.language).toBe("python");
|
|
190
|
-
expect(result.code).toBe(code);
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it("leaves non-SQL cells (e.g. markdown) unchanged as python", () => {
|
|
194
|
-
const code = 'mo.md("""## Heading""")';
|
|
195
|
-
const result = readonlyDisplay(code);
|
|
196
|
-
expect(result.language).toBe("python");
|
|
197
|
-
expect(result.code).toBe(code);
|
|
198
|
-
});
|
|
199
|
-
});
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
Loader2Icon,
|
|
11
11
|
MoreHorizontalIcon,
|
|
12
12
|
} from "lucide-react";
|
|
13
|
-
import { SQLParser } from "@marimo-team/smart-cells";
|
|
14
13
|
import type React from "react";
|
|
15
14
|
import { memo, useRef, useState } from "react";
|
|
16
15
|
import { z } from "zod";
|
|
@@ -30,6 +29,7 @@ import { outputIsLoading, outputIsStale } from "@/core/cells/cell";
|
|
|
30
29
|
import type { CellId } from "@/core/cells/ids";
|
|
31
30
|
import { isOutputEmpty } from "@/core/cells/outputs";
|
|
32
31
|
import type { CellData, CellRuntimeState } from "@/core/cells/types";
|
|
32
|
+
import { getReadonlyCodeDisplay } from "@/core/cells/readonly-code-display";
|
|
33
33
|
import { MarkdownLanguageAdapter } from "@/core/codemirror/language/languages/markdown";
|
|
34
34
|
import { useResolvedMarimoConfig } from "@/core/config/config";
|
|
35
35
|
import { CSSClasses, KnownQueryParams } from "@/core/constants";
|
|
@@ -386,7 +386,7 @@ const VerticalCell = memo(
|
|
|
386
386
|
// Hide the code if it's pure markdown and there's an output, or if the code is empty
|
|
387
387
|
const hideCode = shouldHideCode(code, output);
|
|
388
388
|
// Only unwrap SQL when the code will actually be rendered.
|
|
389
|
-
const display = hideCode ? null :
|
|
389
|
+
const display = hideCode ? null : getReadonlyCodeDisplay(code);
|
|
390
390
|
|
|
391
391
|
return (
|
|
392
392
|
<div
|
|
@@ -500,20 +500,3 @@ export function shouldHideCode(code: string, output: OutputMessage | null) {
|
|
|
500
500
|
const hasOutput = output !== null && !isOutputEmpty(output);
|
|
501
501
|
return (isPureMarkdown && hasOutput) || code.trim() === "";
|
|
502
502
|
}
|
|
503
|
-
|
|
504
|
-
const sqlParser = new SQLParser();
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* Unwrap SQL cells to their inner query so read-only views highlight them as
|
|
508
|
-
* SQL instead of showing the raw `mo.sql(...)` wrapper.
|
|
509
|
-
*/
|
|
510
|
-
export function readonlyDisplay(code: string): {
|
|
511
|
-
code: string;
|
|
512
|
-
language: "python" | "sql";
|
|
513
|
-
} {
|
|
514
|
-
const trimmed = code.trim();
|
|
515
|
-
if (sqlParser.isSupported(trimmed)) {
|
|
516
|
-
return { code: sqlParser.transformIn(trimmed).code, language: "sql" };
|
|
517
|
-
}
|
|
518
|
-
return { code, language: "python" };
|
|
519
|
-
}
|
|
@@ -26,7 +26,7 @@ import { connectionAtom } from "@/core/network/connection";
|
|
|
26
26
|
import { useTheme } from "@/theme/useTheme";
|
|
27
27
|
import { cn } from "@/utils/cn";
|
|
28
28
|
import { ReadonlyCode } from "../editor/code/readonly-python-code";
|
|
29
|
-
import {
|
|
29
|
+
import { getReadonlyCodeDisplay } from "@/core/cells/readonly-code-display";
|
|
30
30
|
|
|
31
31
|
type RuntimeCell = CellRuntimeState & CellData;
|
|
32
32
|
|
|
@@ -188,10 +188,7 @@ export const SlideCellReadOnlyView = ({ cell }: { cell: RuntimeCell }) => {
|
|
|
188
188
|
const [userConfig] = useUserConfig();
|
|
189
189
|
const cellOutputPosition = userConfig.display.cell_output;
|
|
190
190
|
|
|
191
|
-
const
|
|
192
|
-
const adapter = languageAdapterFromCode(cell.code.trim());
|
|
193
|
-
return adapter.type === "sql" ? "sql" : "python";
|
|
194
|
-
}, [cell.code]);
|
|
191
|
+
const display = useMemo(() => getReadonlyCodeDisplay(cell.code), [cell.code]);
|
|
195
192
|
|
|
196
193
|
const output = (
|
|
197
194
|
<CellOutputSlide
|
|
@@ -203,7 +200,11 @@ export const SlideCellReadOnlyView = ({ cell }: { cell: RuntimeCell }) => {
|
|
|
203
200
|
|
|
204
201
|
const editor = (
|
|
205
202
|
<div className="marimo-cell">
|
|
206
|
-
<ReadonlyCode
|
|
203
|
+
<ReadonlyCode
|
|
204
|
+
code={display.code}
|
|
205
|
+
language={display.language}
|
|
206
|
+
showHideCode={false}
|
|
207
|
+
/>
|
|
207
208
|
</div>
|
|
208
209
|
);
|
|
209
210
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { getReadonlyCodeDisplay } from "../readonly-code-display";
|
|
5
|
+
|
|
6
|
+
describe("getReadonlyCodeDisplay", () => {
|
|
7
|
+
it("unwraps SQL cells to their inner query and marks them as sql", () => {
|
|
8
|
+
const result = getReadonlyCodeDisplay(
|
|
9
|
+
'my_table = mo.sql("""SELECT 1 AS id""")',
|
|
10
|
+
);
|
|
11
|
+
expect(result.language).toBe("sql");
|
|
12
|
+
expect(result.code).toBe("SELECT 1 AS id");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("unwraps f-string SQL cells", () => {
|
|
16
|
+
const result = getReadonlyCodeDisplay(
|
|
17
|
+
'my_table = mo.sql(f"""SELECT 1 AS id""")',
|
|
18
|
+
);
|
|
19
|
+
expect(result.language).toBe("sql");
|
|
20
|
+
expect(result.code).toBe("SELECT 1 AS id");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("leaves plain Python cells untouched", () => {
|
|
24
|
+
const code = "x = 1 + 2\nprint(x)";
|
|
25
|
+
const result = getReadonlyCodeDisplay(code);
|
|
26
|
+
expect(result.language).toBe("python");
|
|
27
|
+
expect(result.code).toBe(code);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("unwraps markdown cells to their inner content", () => {
|
|
31
|
+
const result = getReadonlyCodeDisplay('mo.md("""## Heading""")');
|
|
32
|
+
expect(result.language).toBe("markdown");
|
|
33
|
+
expect(result.code).toBe("## Heading");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("treats empty or whitespace-only code as python", () => {
|
|
37
|
+
expect(getReadonlyCodeDisplay("")).toEqual({
|
|
38
|
+
code: "",
|
|
39
|
+
language: "python",
|
|
40
|
+
});
|
|
41
|
+
expect(getReadonlyCodeDisplay(" \n\t ")).toEqual({
|
|
42
|
+
code: " \n\t ",
|
|
43
|
+
language: "python",
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { MarkdownParser, SQLParser } from "@marimo-team/smart-cells";
|
|
4
|
+
import type { LanguageAdapterType } from "@/core/codemirror/language/types";
|
|
5
|
+
|
|
6
|
+
export interface ReadonlyCodeDisplay {
|
|
7
|
+
code: string;
|
|
8
|
+
language: LanguageAdapterType;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const markdownParser = new MarkdownParser();
|
|
12
|
+
const sqlParser = new SQLParser();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Unwrap SQL and markdown cells so read-only views show inner content with the
|
|
16
|
+
* correct syntax highlighting instead of the raw Python wrapper.
|
|
17
|
+
*/
|
|
18
|
+
export function getReadonlyCodeDisplay(code: string): ReadonlyCodeDisplay {
|
|
19
|
+
const trimmed = code.trim();
|
|
20
|
+
if (!trimmed) {
|
|
21
|
+
return { code, language: "python" };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (markdownParser.isSupported(trimmed)) {
|
|
25
|
+
return {
|
|
26
|
+
code: markdownParser.transformIn(trimmed).code,
|
|
27
|
+
language: "markdown",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (sqlParser.isSupported(trimmed)) {
|
|
32
|
+
return { code: sqlParser.transformIn(trimmed).code, language: "sql" };
|
|
33
|
+
}
|
|
34
|
+
return { code, language: "python" };
|
|
35
|
+
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
3
|
-
import { describe, expect, it } from "vitest";
|
|
4
|
-
import { getSnippetDisplay } from "../snippet-display";
|
|
5
|
-
|
|
6
|
-
describe("getSnippetDisplay", () => {
|
|
7
|
-
it("shows sql cells as the sql query", () => {
|
|
8
|
-
const { language, value } = getSnippetDisplay(
|
|
9
|
-
'df = mo.sql("""SELECT * FROM users LIMIT 5""")',
|
|
10
|
-
);
|
|
11
|
-
expect(language).toBe("sql");
|
|
12
|
-
expect(value).toBe("SELECT * FROM users LIMIT 5");
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("keeps plain python cells as python", () => {
|
|
16
|
-
const code = "x = 1 + 2\nprint(x)";
|
|
17
|
-
expect(getSnippetDisplay(code)).toEqual({
|
|
18
|
-
language: "python",
|
|
19
|
-
value: code,
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
3
|
-
import { SQLParser } from "@marimo-team/smart-cells";
|
|
4
|
-
|
|
5
|
-
export type SnippetLanguage = "python" | "sql";
|
|
6
|
-
|
|
7
|
-
export interface SnippetDisplay {
|
|
8
|
-
language: SnippetLanguage;
|
|
9
|
-
value: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const sqlParser = new SQLParser();
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Decide how a snippet's code should be shown in the panel.
|
|
16
|
-
*
|
|
17
|
-
* SQL cells are stored as python `mo.sql(...)`. Unwrap the inner query and
|
|
18
|
-
* highlight it as SQL, matching how the cell renders once the snippet is
|
|
19
|
-
* inserted. Everything else stays python.
|
|
20
|
-
*/
|
|
21
|
-
export function getSnippetDisplay(code: string): SnippetDisplay {
|
|
22
|
-
if (sqlParser.isSupported(code)) {
|
|
23
|
-
const { code: query } = sqlParser.transformIn(code);
|
|
24
|
-
return { language: "sql", value: query };
|
|
25
|
-
}
|
|
26
|
-
return { language: "python", value: code };
|
|
27
|
-
}
|