@marimo-team/frontend 0.22.1-dev26 → 0.22.1-dev27
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/package.json +4 -5
- package/src/__tests__/main.test.tsx +12 -14
- package/src/components/ai/ai-provider-icon.tsx +1 -2
- package/src/components/data-table/cell-selection/types.ts +3 -2
- package/src/components/data-table/column-formatting/types.ts +3 -2
- package/src/components/data-table/column-header.tsx +4 -2
- package/src/components/data-table/column-wrapping/types.ts +3 -2
- package/src/components/data-table/copy-column/types.ts +3 -2
- package/src/components/data-table/focus-row/types.ts +3 -2
- package/src/components/data-table/range-focus/__tests__/atoms.test.ts +11 -11
- package/src/components/data-table/range-focus/__tests__/use-cell-range-selection.test.ts +9 -11
- package/src/components/editor/__tests__/data-attributes.test.tsx +93 -94
- package/src/components/editor/actions/name-cell-input.tsx +4 -2
- package/src/components/editor/actions/useCellActionButton.tsx +4 -2
- package/src/components/editor/cell/CellStatus.tsx +4 -5
- package/src/components/editor/cell/cell-context-menu.tsx +4 -2
- package/src/components/editor/cell/code/cell-editor.tsx +2 -1
- package/src/components/editor/cell/toolbar.tsx +2 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +11 -12
- package/src/components/storage/__tests__/storage-snippets.test.ts +4 -6
- package/src/components/tracing/tracing.test.tsx +30 -30
- package/src/components/ui/badge.tsx +2 -1
- package/src/components/ui/button.tsx +2 -1
- package/src/components/ui/calendar.tsx +3 -2
- package/src/components/ui/combobox.tsx +2 -1
- package/src/components/ui/date-input.tsx +7 -6
- package/src/components/ui/date-picker.tsx +6 -4
- package/src/components/ui/field.tsx +1 -2
- package/src/components/ui/progress.tsx +3 -2
- package/src/components/ui/query-param-preserving-link.tsx +4 -2
- package/src/components/ui/sheet.tsx +2 -1
- package/src/components/ui/textarea.tsx +1 -2
- package/src/core/ai/context/providers/cell-output.ts +1 -2
- package/src/core/ai/tools/edit-notebook-tool.ts +4 -3
- package/src/core/ai/tools/run-cells-tool.ts +4 -3
- package/src/core/cells/__tests__/add-missing-import.test.ts +23 -22
- package/src/core/cells/__tests__/cell.test.ts +14 -13
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +15 -17
- package/src/core/codemirror/language/languages/markdown.ts +1 -3
- package/src/core/codemirror/language/languages/python.ts +1 -1
- package/src/core/codemirror/language/languages/sql/completion-sources.tsx +4 -6
- package/src/core/codemirror/language/languages/sql/sql.ts +1 -3
- package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +28 -42
- package/src/core/datasets/data-source-connections.ts +4 -2
- package/src/core/dom/__tests__/htmlUtils.test.ts +8 -14
- package/src/core/dom/__tests__/outline.test.ts +2 -3
- package/src/core/islands/__tests__/parse.test.ts +8 -7
- package/src/core/saving/__tests__/filename.test.ts +7 -6
- package/src/core/static/__tests__/download-html.test.ts +16 -15
- package/src/core/static/__tests__/files.test.ts +30 -28
- package/src/css/app/Cell.css +11 -11
- package/src/css/globals.css +40 -14
- package/src/plugins/impl/DataEditorPlugin.tsx +4 -2
- package/src/plugins/impl/FormPlugin.tsx +1 -2
- package/src/plugins/impl/data-frames/forms/__tests__/form.test.tsx +7 -9
- package/src/plugins/impl/vega/__tests__/make-selectable.test.ts +13 -14
- package/src/plugins/layout/ImageComparisonPlugin.tsx +1 -3
- package/src/plugins/stateless-plugin.ts +4 -2
- package/src/utils/__tests__/cell-urls.test.ts +24 -21
- package/src/utils/__tests__/filenames.test.ts +15 -14
- package/src/utils/__tests__/json-parser.test.ts +14 -21
- package/src/utils/__tests__/path.test.ts +34 -31
- package/src/utils/__tests__/urls.test.ts +19 -18
|
@@ -183,8 +183,9 @@ const Calendar = <T extends AriaDateValue>({
|
|
|
183
183
|
);
|
|
184
184
|
};
|
|
185
185
|
|
|
186
|
-
interface RangeCalendarProps<
|
|
187
|
-
extends
|
|
186
|
+
interface RangeCalendarProps<
|
|
187
|
+
T extends AriaDateValue,
|
|
188
|
+
> extends AriaRangeCalendarProps<T> {
|
|
188
189
|
errorMessage?: string;
|
|
189
190
|
}
|
|
190
191
|
|
|
@@ -230,7 +230,8 @@ interface ComboboxItemOptions<TValue> {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
export interface ComboboxItemProps<TValue>
|
|
233
|
-
extends
|
|
233
|
+
extends
|
|
234
|
+
ComboboxItemOptions<TValue>,
|
|
234
235
|
Omit<
|
|
235
236
|
React.ComponentProps<typeof CommandItem>,
|
|
236
237
|
keyof ComboboxItemOptions<TValue> | "onSelect" | "role"
|
|
@@ -41,8 +41,7 @@ const DateSegment = ({ className, ...props }: AriaDateSegmentProps) => {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
interface DateInputProps
|
|
44
|
-
extends AriaDateInputProps,
|
|
45
|
-
VariantProps<typeof fieldGroupVariants> {}
|
|
44
|
+
extends AriaDateInputProps, VariantProps<typeof fieldGroupVariants> {}
|
|
46
45
|
|
|
47
46
|
const DateInput = ({
|
|
48
47
|
className,
|
|
@@ -61,8 +60,9 @@ const DateInput = ({
|
|
|
61
60
|
);
|
|
62
61
|
};
|
|
63
62
|
|
|
64
|
-
interface DateFieldProps<
|
|
65
|
-
extends
|
|
63
|
+
interface DateFieldProps<
|
|
64
|
+
T extends AriaDateValue,
|
|
65
|
+
> extends AriaDateFieldProps<T> {
|
|
66
66
|
label?: string;
|
|
67
67
|
description?: string;
|
|
68
68
|
errorMessage?: string | ((validation: AriaValidationResult) => string);
|
|
@@ -94,8 +94,9 @@ const DateField = <T extends AriaDateValue>({
|
|
|
94
94
|
);
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
-
interface TimeFieldProps<
|
|
98
|
-
extends
|
|
97
|
+
interface TimeFieldProps<
|
|
98
|
+
T extends AriaTimeValue,
|
|
99
|
+
> extends AriaTimeFieldProps<T> {
|
|
99
100
|
label?: string;
|
|
100
101
|
description?: string;
|
|
101
102
|
errorMessage?: string | ((validation: AriaValidationResult) => string);
|
|
@@ -51,8 +51,9 @@ const DatePickerContent = ({
|
|
|
51
51
|
</Popover>
|
|
52
52
|
);
|
|
53
53
|
|
|
54
|
-
interface DatePickerProps<
|
|
55
|
-
extends
|
|
54
|
+
interface DatePickerProps<
|
|
55
|
+
T extends AriaDateValue,
|
|
56
|
+
> extends AriaDatePickerProps<T> {
|
|
56
57
|
label?: string;
|
|
57
58
|
description?: string;
|
|
58
59
|
errorMessage?: string | ((validation: AriaValidationResult) => string);
|
|
@@ -115,8 +116,9 @@ const DatePicker = <T extends AriaDateValue>({
|
|
|
115
116
|
);
|
|
116
117
|
};
|
|
117
118
|
|
|
118
|
-
interface DateRangePickerProps<
|
|
119
|
-
extends
|
|
119
|
+
interface DateRangePickerProps<
|
|
120
|
+
T extends AriaDateValue,
|
|
121
|
+
> extends AriaDateRangePickerProps<T> {
|
|
120
122
|
label?: string;
|
|
121
123
|
description?: string;
|
|
122
124
|
errorMessage?: string | ((validation: AriaValidationResult) => string);
|
|
@@ -66,8 +66,7 @@ const fieldGroupVariants = cva("", {
|
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
interface GroupProps
|
|
69
|
-
extends AriaGroupProps,
|
|
70
|
-
VariantProps<typeof fieldGroupVariants> {}
|
|
69
|
+
extends AriaGroupProps, VariantProps<typeof fieldGroupVariants> {}
|
|
71
70
|
|
|
72
71
|
const FieldGroup = ({ className, variant, ...props }: GroupProps) => {
|
|
73
72
|
return (
|
|
@@ -5,8 +5,9 @@ import * as React from "react";
|
|
|
5
5
|
|
|
6
6
|
import { cn } from "@/utils/cn";
|
|
7
7
|
|
|
8
|
-
interface ProgressProps
|
|
9
|
-
|
|
8
|
+
interface ProgressProps extends React.ComponentPropsWithoutRef<
|
|
9
|
+
typeof ProgressPrimitive.Root
|
|
10
|
+
> {
|
|
10
11
|
/**
|
|
11
12
|
* When true, shows an indeterminate animated progress bar.
|
|
12
13
|
*/
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
import React, { useRef } from "react";
|
|
4
4
|
import { usePress } from "react-aria";
|
|
5
5
|
|
|
6
|
-
interface QueryParamPreservingLinkProps
|
|
7
|
-
|
|
6
|
+
interface QueryParamPreservingLinkProps extends Omit<
|
|
7
|
+
React.HTMLAttributes<HTMLAnchorElement>,
|
|
8
|
+
"href"
|
|
9
|
+
> {
|
|
8
10
|
href: string;
|
|
9
11
|
children: React.ReactNode;
|
|
10
12
|
}
|
|
@@ -51,7 +51,8 @@ const sheetVariants = cva(
|
|
|
51
51
|
);
|
|
52
52
|
|
|
53
53
|
interface SheetContentProps
|
|
54
|
-
extends
|
|
54
|
+
extends
|
|
55
|
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
|
55
56
|
VariantProps<typeof sheetVariants> {}
|
|
56
57
|
|
|
57
58
|
const SheetContent = React.forwardRef<
|
|
@@ -6,8 +6,7 @@ import { useDebounceControlledState } from "@/hooks/useDebounce";
|
|
|
6
6
|
import { cn } from "@/utils/cn";
|
|
7
7
|
import { Events } from "@/utils/events";
|
|
8
8
|
|
|
9
|
-
export interface TextareaProps
|
|
10
|
-
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
9
|
+
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
11
10
|
bottomAdornment?: React.ReactNode;
|
|
12
11
|
}
|
|
13
12
|
|
|
@@ -34,8 +34,7 @@ export interface CellOutputData {
|
|
|
34
34
|
// For the context provider
|
|
35
35
|
// Currently, we enforce that cellOutput is present.
|
|
36
36
|
interface CellOutputContextData
|
|
37
|
-
extends CellOutputData,
|
|
38
|
-
Record<string, unknown> {
|
|
37
|
+
extends CellOutputData, Record<string, unknown> {
|
|
39
38
|
cellOutput: BaseOutput;
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -72,9 +72,10 @@ type EditNotebookInput = z.infer<typeof editNotebookSchema>;
|
|
|
72
72
|
type EditOperation = EditNotebookInput["edit"];
|
|
73
73
|
export type EditType = EditOperation["type"];
|
|
74
74
|
|
|
75
|
-
export class EditNotebookTool
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
export class EditNotebookTool implements AiTool<
|
|
76
|
+
EditNotebookInput,
|
|
77
|
+
ToolOutputBase
|
|
78
|
+
> {
|
|
78
79
|
readonly name = "edit_notebook_tool";
|
|
79
80
|
readonly description = description;
|
|
80
81
|
readonly schema = editNotebookSchema;
|
|
@@ -50,9 +50,10 @@ const filePartSchema = z.object({
|
|
|
50
50
|
mediaType: z.string(),
|
|
51
51
|
}) satisfies z.ZodType<FileUIPart>;
|
|
52
52
|
|
|
53
|
-
export class RunStaleCellsTool
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
export class RunStaleCellsTool implements AiTool<
|
|
54
|
+
EmptyToolInput,
|
|
55
|
+
RunStaleCellsOutput
|
|
56
|
+
> {
|
|
56
57
|
readonly name = "run_stale_cells_tool";
|
|
57
58
|
readonly description = description;
|
|
58
59
|
readonly schema = z.object({});
|
|
@@ -48,28 +48,29 @@ describe("maybeAddMissingImport", () => {
|
|
|
48
48
|
"import marimo as mo\nimport marimo as mo",
|
|
49
49
|
"import marimo as mo",
|
|
50
50
|
];
|
|
51
|
-
it.each(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
51
|
+
it.each(VALID_IMPORTS)(
|
|
52
|
+
"should not add an import if the import statement already exists in the notebook",
|
|
53
|
+
(code) => {
|
|
54
|
+
const appStore = createStore();
|
|
55
|
+
appStore.set(variablesAtom, {} as Variables);
|
|
56
|
+
appStore.set(
|
|
57
|
+
notebookAtom,
|
|
58
|
+
MockNotebook.notebookState({
|
|
59
|
+
cellData: {
|
|
60
|
+
[Cell1]: { code: code },
|
|
61
|
+
},
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
const onAddImport = vi.fn();
|
|
65
|
+
maybeAddMissingImport({
|
|
66
|
+
moduleName: "marimo",
|
|
67
|
+
variableName: "mo",
|
|
68
|
+
onAddImport,
|
|
69
|
+
appStore,
|
|
70
|
+
});
|
|
71
|
+
expect(onAddImport).not.toHaveBeenCalled();
|
|
72
|
+
},
|
|
73
|
+
);
|
|
73
74
|
|
|
74
75
|
it("should add an import if the variable is not in the variables state and the import statement does not exist in the notebook", () => {
|
|
75
76
|
const appStore = createStore();
|
|
@@ -43,19 +43,20 @@ describe("outputIsLoading", () => {
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
describe("outputIsStale", () => {
|
|
46
|
-
it.each(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
it.each(STATUSES)(
|
|
47
|
+
"should return true if the cell is edited and status is %s",
|
|
48
|
+
(status) => {
|
|
49
|
+
const cell = {
|
|
50
|
+
status: status,
|
|
51
|
+
staleInputs: true,
|
|
52
|
+
output: null,
|
|
53
|
+
runStartTimestamp: null,
|
|
54
|
+
interrupted: false,
|
|
55
|
+
};
|
|
56
|
+
const edited = true;
|
|
57
|
+
expect(outputIsStale(cell, edited)).toBe(true);
|
|
58
|
+
},
|
|
59
|
+
);
|
|
59
60
|
|
|
60
61
|
it("should return true if the cell is loading", () => {
|
|
61
62
|
const cell = {
|
|
@@ -18,24 +18,22 @@ function createTransaction(spec: TransactionSpec) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
describe("shouldAutorunMarkdownUpdate", () => {
|
|
21
|
-
it.each([
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
changes: { from: 0, insert: "#" },
|
|
29
|
-
annotations: [Transaction.userEvent.of(userEvent)],
|
|
30
|
-
});
|
|
21
|
+
it.each(["input.type", "delete.backward", "undo", "redo"])(
|
|
22
|
+
"accepts local %s transactions",
|
|
23
|
+
(userEvent) => {
|
|
24
|
+
const transaction = createTransaction({
|
|
25
|
+
changes: { from: 0, insert: "#" },
|
|
26
|
+
annotations: [Transaction.userEvent.of(userEvent)],
|
|
27
|
+
});
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
expect(
|
|
30
|
+
shouldAutorunMarkdownUpdate({
|
|
31
|
+
docChanged: transaction.docChanged,
|
|
32
|
+
transactions: [transaction],
|
|
33
|
+
}),
|
|
34
|
+
).toBe(true);
|
|
35
|
+
},
|
|
36
|
+
);
|
|
39
37
|
|
|
40
38
|
it("ignores formatting changes", () => {
|
|
41
39
|
const transaction = createTransaction({
|
|
@@ -38,9 +38,7 @@ export const MARKDOWN_INITIAL_HIDE_CODE = true;
|
|
|
38
38
|
/**
|
|
39
39
|
* Language adapter for Markdown.
|
|
40
40
|
*/
|
|
41
|
-
export class MarkdownLanguageAdapter
|
|
42
|
-
implements LanguageAdapter<MarkdownLanguageAdapterMetadata>
|
|
43
|
-
{
|
|
41
|
+
export class MarkdownLanguageAdapter implements LanguageAdapter<MarkdownLanguageAdapterMetadata> {
|
|
44
42
|
private parser = new MarkdownParser();
|
|
45
43
|
|
|
46
44
|
readonly type = "markdown";
|
|
@@ -184,7 +184,7 @@ const tyLspClient = once((_: LSPConfig) => {
|
|
|
184
184
|
const pyreflyClient = once(
|
|
185
185
|
(lspConfig: LSPConfig & { diagnostics: DiagnosticsConfig }) => {
|
|
186
186
|
// oxlint-disable-next-line prefer-const -- reassigned after closure capture
|
|
187
|
-
|
|
187
|
+
let resyncCallback: (() => Promise<void>) | undefined;
|
|
188
188
|
|
|
189
189
|
const transport = createTransport("pyrefly", async () => {
|
|
190
190
|
await resyncCallback?.();
|
|
@@ -91,13 +91,11 @@ export function customKeywordCompletionSource(): CompletionSource {
|
|
|
91
91
|
|
|
92
92
|
// e.g. lazily load keyword docs
|
|
93
93
|
const getKeywordDocs = once(async (): Promise<Record<string, unknown>> => {
|
|
94
|
-
const keywords =
|
|
95
|
-
"@marimo-team/codemirror-sql/data/common-keywords.json"
|
|
96
|
-
);
|
|
94
|
+
const keywords =
|
|
95
|
+
await import("@marimo-team/codemirror-sql/data/common-keywords.json");
|
|
97
96
|
// Include DuckDB for now, but we can remove this once we have a better way to handle dialect-specific keywords
|
|
98
|
-
const duckdbKeywords =
|
|
99
|
-
"@marimo-team/codemirror-sql/data/duckdb-keywords.json"
|
|
100
|
-
);
|
|
97
|
+
const duckdbKeywords =
|
|
98
|
+
await import("@marimo-team/codemirror-sql/data/duckdb-keywords.json");
|
|
101
99
|
return {
|
|
102
100
|
...keywords.default.keywords,
|
|
103
101
|
...duckdbKeywords.default.keywords,
|
|
@@ -77,9 +77,7 @@ function getLatestEngine(): ConnectionName {
|
|
|
77
77
|
/**
|
|
78
78
|
* Language adapter for SQL.
|
|
79
79
|
*/
|
|
80
|
-
export class SQLLanguageAdapter
|
|
81
|
-
implements LanguageAdapter<SQLLanguageAdapterMetadata>
|
|
82
|
-
{
|
|
80
|
+
export class SQLLanguageAdapter implements LanguageAdapter<SQLLanguageAdapterMetadata> {
|
|
83
81
|
private parser = new SQLParser();
|
|
84
82
|
readonly type = "sql";
|
|
85
83
|
sqlModeEnabled: boolean;
|
|
@@ -45,9 +45,8 @@ def foo(x):
|
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
test("should handle lambda parameters", () => {
|
|
48
|
-
expect(
|
|
49
|
-
|
|
50
|
-
).toMatchInlineSnapshot(`
|
|
48
|
+
expect(runHighlight(["a", "b"], "result = lambda a: a + b"))
|
|
49
|
+
.toMatchInlineSnapshot(`
|
|
51
50
|
"
|
|
52
51
|
result = lambda a: a + b
|
|
53
52
|
^
|
|
@@ -56,9 +55,8 @@ def foo(x):
|
|
|
56
55
|
});
|
|
57
56
|
|
|
58
57
|
test("should handle comprehension variables", () => {
|
|
59
|
-
expect(
|
|
60
|
-
|
|
61
|
-
).toMatchInlineSnapshot(`
|
|
58
|
+
expect(runHighlight(["a", "data"], "result = [a for a in data]"))
|
|
59
|
+
.toMatchInlineSnapshot(`
|
|
62
60
|
"
|
|
63
61
|
result = [a for a in data]
|
|
64
62
|
^^^^
|
|
@@ -146,9 +144,8 @@ def factorial(n):
|
|
|
146
144
|
});
|
|
147
145
|
|
|
148
146
|
test("function param vs global", () => {
|
|
149
|
-
expect(
|
|
150
|
-
|
|
151
|
-
).toMatchInlineSnapshot(`
|
|
147
|
+
expect(runHighlight(["a", "b"], "def foo(a): return a + b"))
|
|
148
|
+
.toMatchInlineSnapshot(`
|
|
152
149
|
"
|
|
153
150
|
def foo(a): return a + b
|
|
154
151
|
^
|
|
@@ -157,9 +154,8 @@ def factorial(n):
|
|
|
157
154
|
});
|
|
158
155
|
|
|
159
156
|
test("lambda param vs global", () => {
|
|
160
|
-
expect(
|
|
161
|
-
|
|
162
|
-
).toMatchInlineSnapshot(`
|
|
157
|
+
expect(runHighlight(["x", "b"], "func = lambda x: x + b"))
|
|
158
|
+
.toMatchInlineSnapshot(`
|
|
163
159
|
"
|
|
164
160
|
func = lambda x: x + b
|
|
165
161
|
^
|
|
@@ -168,9 +164,8 @@ def factorial(n):
|
|
|
168
164
|
});
|
|
169
165
|
|
|
170
166
|
test("lambda with multiple params", () => {
|
|
171
|
-
expect(
|
|
172
|
-
|
|
173
|
-
).toMatchInlineSnapshot(`
|
|
167
|
+
expect(runHighlight(["x", "y", "z"], "f = lambda x, y: x + y + z"))
|
|
168
|
+
.toMatchInlineSnapshot(`
|
|
174
169
|
"
|
|
175
170
|
f = lambda x, y: x + y + z
|
|
176
171
|
^
|
|
@@ -187,9 +182,8 @@ def factorial(n):
|
|
|
187
182
|
});
|
|
188
183
|
|
|
189
184
|
test("nested comprehension", () => {
|
|
190
|
-
expect(
|
|
191
|
-
|
|
192
|
-
).toMatchInlineSnapshot(`
|
|
185
|
+
expect(runHighlight(["a", "b"], "[(a + b) for a, b in [(1,2), (3,4)]]"))
|
|
186
|
+
.toMatchInlineSnapshot(`
|
|
193
187
|
"
|
|
194
188
|
[(a + b) for a, b in [(1,2), (3,4)]]
|
|
195
189
|
"
|
|
@@ -225,9 +219,8 @@ def factorial(n):
|
|
|
225
219
|
});
|
|
226
220
|
|
|
227
221
|
test("class body using globals", () => {
|
|
228
|
-
expect(
|
|
229
|
-
|
|
230
|
-
).toMatchInlineSnapshot(`
|
|
222
|
+
expect(runHighlight(["a", "b"], "class MyClass:\n value = a + b"))
|
|
223
|
+
.toMatchInlineSnapshot(`
|
|
231
224
|
"
|
|
232
225
|
class MyClass:
|
|
233
226
|
value = a + b
|
|
@@ -237,9 +230,8 @@ def factorial(n):
|
|
|
237
230
|
});
|
|
238
231
|
|
|
239
232
|
test("decorator using global", () => {
|
|
240
|
-
expect(
|
|
241
|
-
|
|
242
|
-
).toMatchInlineSnapshot(`
|
|
233
|
+
expect(runHighlight(["logger"], "@logger\ndef decorated(): pass"))
|
|
234
|
+
.toMatchInlineSnapshot(`
|
|
243
235
|
"
|
|
244
236
|
@logger
|
|
245
237
|
^^^^^^
|
|
@@ -317,9 +309,8 @@ ${" ".repeat(8)}
|
|
|
317
309
|
});
|
|
318
310
|
|
|
319
311
|
test("multiple assignment", () => {
|
|
320
|
-
expect(
|
|
321
|
-
|
|
322
|
-
).toMatchInlineSnapshot(`
|
|
312
|
+
expect(runHighlight(["x", "y", "z", "a"], "x = y = z + a"))
|
|
313
|
+
.toMatchInlineSnapshot(`
|
|
323
314
|
"
|
|
324
315
|
x = y = z + a
|
|
325
316
|
^ ^
|
|
@@ -353,9 +344,8 @@ ${" ".repeat(8)}
|
|
|
353
344
|
});
|
|
354
345
|
|
|
355
346
|
test("global in return", () => {
|
|
356
|
-
expect(
|
|
357
|
-
|
|
358
|
-
).toMatchInlineSnapshot(`
|
|
347
|
+
expect(runHighlight(["config"], "def get_config(): return config"))
|
|
348
|
+
.toMatchInlineSnapshot(`
|
|
359
349
|
"
|
|
360
350
|
def get_config(): return config
|
|
361
351
|
^^^^^^
|
|
@@ -410,9 +400,8 @@ class Configurable:
|
|
|
410
400
|
});
|
|
411
401
|
|
|
412
402
|
test("comprehension shadows global 2", () => {
|
|
413
|
-
expect(
|
|
414
|
-
|
|
415
|
-
).toMatchInlineSnapshot(`
|
|
403
|
+
expect(runHighlight(["i"], "squares = [i**2 for i in range(10)]"))
|
|
404
|
+
.toMatchInlineSnapshot(`
|
|
416
405
|
"
|
|
417
406
|
squares = [i**2 for i in range(10)]
|
|
418
407
|
"
|
|
@@ -420,9 +409,8 @@ class Configurable:
|
|
|
420
409
|
});
|
|
421
410
|
|
|
422
411
|
test("comprehension with global in condition", () => {
|
|
423
|
-
expect(
|
|
424
|
-
|
|
425
|
-
).toMatchInlineSnapshot(`
|
|
412
|
+
expect(runHighlight(["x", "z"], "filtered = [x for x in [] if x > z]"))
|
|
413
|
+
.toMatchInlineSnapshot(`
|
|
426
414
|
"
|
|
427
415
|
filtered = [x for x in [] if x > z]
|
|
428
416
|
^
|
|
@@ -459,9 +447,8 @@ def make_adder(x):
|
|
|
459
447
|
});
|
|
460
448
|
|
|
461
449
|
test("rebinding in list comprehension", () => {
|
|
462
|
-
expect(
|
|
463
|
-
|
|
464
|
-
).toMatchInlineSnapshot(`
|
|
450
|
+
expect(runHighlight(["x"], "rebinding = [x for x in range(5)]"))
|
|
451
|
+
.toMatchInlineSnapshot(`
|
|
465
452
|
"
|
|
466
453
|
rebinding = [x for x in range(5)]
|
|
467
454
|
"
|
|
@@ -644,9 +631,8 @@ def run(polars):
|
|
|
644
631
|
});
|
|
645
632
|
|
|
646
633
|
test("mixed comprehension and outer globals", () => {
|
|
647
|
-
expect(
|
|
648
|
-
|
|
649
|
-
).toMatchInlineSnapshot(`
|
|
634
|
+
expect(runHighlight(["y", "z"], "values = [y + z for y in range(5)]"))
|
|
635
|
+
.toMatchInlineSnapshot(`
|
|
650
636
|
"
|
|
651
637
|
values = [y + z for y in range(5)]
|
|
652
638
|
^
|
|
@@ -32,8 +32,10 @@ const initialConnections: ConnectionsMap = new Map([
|
|
|
32
32
|
]);
|
|
33
33
|
|
|
34
34
|
// Extend the backend type but override the name property with the strongly typed ConnectionName
|
|
35
|
-
export interface DataSourceConnection
|
|
36
|
-
|
|
35
|
+
export interface DataSourceConnection extends Omit<
|
|
36
|
+
DataSourceConnectionType,
|
|
37
|
+
"name"
|
|
38
|
+
> {
|
|
37
39
|
name: ConnectionName;
|
|
38
40
|
}
|
|
39
41
|
|
|
@@ -6,20 +6,14 @@ import { UIElementRegistry } from "../uiregistry";
|
|
|
6
6
|
const registry = UIElementRegistry.INSTANCE;
|
|
7
7
|
|
|
8
8
|
describe("htmlUtils", () => {
|
|
9
|
-
it.each([
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"",
|
|
18
|
-
])("can parse element.dataset.initialValue", (initialValue) => {
|
|
19
|
-
const div = document.createElement("div");
|
|
20
|
-
div.dataset.initialValue = JSON.stringify(initialValue);
|
|
21
|
-
expect(parseInitialValue(div, registry)).toEqual(initialValue);
|
|
22
|
-
});
|
|
9
|
+
it.each([false, { a: 1 }, true, 0, 1, [{ a: 1 }, { b: 2 }], "hello", ""])(
|
|
10
|
+
"can parse element.dataset.initialValue",
|
|
11
|
+
(initialValue) => {
|
|
12
|
+
const div = document.createElement("div");
|
|
13
|
+
div.dataset.initialValue = JSON.stringify(initialValue);
|
|
14
|
+
expect(parseInitialValue(div, registry)).toEqual(initialValue);
|
|
15
|
+
},
|
|
16
|
+
);
|
|
23
17
|
|
|
24
18
|
it("can parse an element with no initialValue", () => {
|
|
25
19
|
const div = document.createElement("div");
|
|
@@ -439,9 +439,8 @@ const OUTLINE_2: Outline = {
|
|
|
439
439
|
};
|
|
440
440
|
|
|
441
441
|
it("mergeOutlines", () => {
|
|
442
|
-
expect(
|
|
443
|
-
|
|
444
|
-
).toMatchInlineSnapshot(`
|
|
442
|
+
expect(mergeOutlines([OUTLINE_1, null, OUTLINE_2, null]))
|
|
443
|
+
.toMatchInlineSnapshot(`
|
|
445
444
|
{
|
|
446
445
|
"items": [
|
|
447
446
|
{
|
|
@@ -78,11 +78,12 @@ describe("parseIslandCode", () => {
|
|
|
78
78
|
|
|
79
79
|
codes = [...codes, ...codes.map(encodeURIComponent)];
|
|
80
80
|
|
|
81
|
-
it.each(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
it.each(codes)(
|
|
82
|
+
"should return the code without leading or trailing whitespace",
|
|
83
|
+
(code) => {
|
|
84
|
+
const result = parseIslandCode(code);
|
|
85
|
+
const expected = 'def __():\n print("Hello, World!")\n return';
|
|
86
|
+
expect(result).toBe(expected);
|
|
87
|
+
},
|
|
88
|
+
);
|
|
88
89
|
});
|
|
@@ -5,12 +5,13 @@ import { EDGE_CASE_FILENAMES } from "../../../__tests__/mocks";
|
|
|
5
5
|
import { Paths } from "../../../utils/paths";
|
|
6
6
|
|
|
7
7
|
describe("filename handling logic", () => {
|
|
8
|
-
it.each(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
9
|
+
"should extract basename correctly for document title: %s",
|
|
10
|
+
(filename) => {
|
|
11
|
+
const basename = Paths.basename(filename);
|
|
12
|
+
expect(basename).toBe(filename); // Since no path separator
|
|
13
|
+
},
|
|
14
|
+
);
|
|
14
15
|
|
|
15
16
|
it("should handle full paths with unicode filenames", () => {
|
|
16
17
|
EDGE_CASE_FILENAMES.forEach((filename) => {
|