@marimo-team/frontend 0.23.16-dev34 → 0.23.16-dev36
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-CmojVYzm.js → CellStatus-Dua-Q5qp.js} +1 -1
- package/dist/assets/{JsonOutput-BwwRpByA.js → JsonOutput-BjTsPSAI.js} +12 -12
- package/dist/assets/{MarimoErrorOutput-BWte8vjk.js → MarimoErrorOutput-BSyqD6Hg.js} +8 -8
- package/dist/assets/{RenderHTML-DRltV71H.js → RenderHTML-DG0Fm01X.js} +1 -1
- package/dist/assets/{RunButton-DIegd2mN.js → RunButton-DFs1N-c9.js} +1 -1
- package/dist/assets/{add-cell-with-ai-BBFD-M9V.js → add-cell-with-ai-C6Kxfu_D.js} +17 -17
- package/dist/assets/{add-connection-dialog-CECJ8507.js → add-connection-dialog-DAqIrB2O.js} +1 -1
- package/dist/assets/{agent-panel-YaS0WXP1.js → agent-panel-GtkUm7qc.js} +5 -5
- package/dist/assets/ai-model-dropdown-UEHQ_Tx0.js +5 -0
- package/dist/assets/{app-config-button-BW-w01aF.js → app-config-button-BmBlROBo.js} +1 -1
- package/dist/assets/{cell-editor-EV-1IccQ.js → cell-editor-DKzBZjFa.js} +10 -10
- package/dist/assets/{cell-link-C5gpAn3R.js → cell-link-CRHwRCw2.js} +1 -1
- package/dist/assets/cells-C-9Qa_6_.js +235 -0
- package/dist/assets/{chat-display-8BbC5B-D.js → chat-display-CqB9H1kF.js} +1 -1
- package/dist/assets/{chat-panel-CMOZp5xW.js → chat-panel-C3wpuHtk.js} +2 -2
- package/dist/assets/{chat-ui-DWhJ2Ozy.js → chat-ui-DF2nZlBy.js} +1 -1
- package/dist/assets/{column-preview-DeXESYpM.js → column-preview-Bp4QHPE2.js} +1 -1
- package/dist/assets/{command-palette-Dx6AkiPd.js → command-palette-DaJdKaQz.js} +1 -1
- package/dist/assets/{common-XVELED_O.js → common-DeheUlBO.js} +1 -1
- package/dist/assets/{components-BLHpmhXx.js → components-Dk-7Tn_8.js} +1 -1
- package/dist/assets/{datasource-CTqa8bf-.js → datasource-D-oZZRFN.js} +2 -2
- package/dist/assets/{dependency-graph-panel-C4Nzcddp.js → dependency-graph-panel-JK4qjNID.js} +3 -3
- package/dist/assets/{documentation-panel-Bym4G7IS.js → documentation-panel-C_TxLeX8.js} +1 -1
- package/dist/assets/{download-HKgqJX4l.js → download-QhwPYWYu.js} +2 -2
- package/dist/assets/{edit-page-Jtp6Qqjl.js → edit-page-C8yy6X_7.js} +6 -6
- package/dist/assets/{error-entries-CxyvaxEM.js → error-entries-B8hPG61B.js} +2 -2
- package/dist/assets/{error-panel-CfSy7uUr.js → error-panel-BOBOm9wN.js} +1 -1
- package/dist/assets/{file-explorer-panel-Dd5Xn2TK.js → file-explorer-panel-CQOFpuIG.js} +4 -4
- package/dist/assets/{file-icons-CSjJ3JC6.js → file-icons-DoBeqg86.js} +1 -1
- package/dist/assets/{file-name-input-CrKtrXMl.js → file-name-input-B8d-QPzY.js} +1 -1
- package/dist/assets/{floating-outline-ByQ8vvif.js → floating-outline-ylNOBTvA.js} +1 -1
- package/dist/assets/{focus-CVONl-Dy.js → focus-CJzSyxLL.js} +1 -1
- package/dist/assets/{form-Ca3yd_Od.js → form-C2_p_FeE.js} +2 -2
- package/dist/assets/{home-page-FpAawj9s.js → home-page-D_6eKuGc.js} +2 -2
- package/dist/assets/{html-to-image-C-4ysbGe.js → html-to-image-DfyxinVN.js} +2 -2
- package/dist/assets/{index-CiJmYQBT.js → index-D-wPCBTa.js} +7 -7
- package/dist/assets/{index-xs-zSSrX.css → index-D6Dp_PFj.css} +1 -1
- package/dist/assets/{layout-Dtql_o_T.js → layout-BWV4OadK.js} +5 -5
- package/dist/assets/logs-panel-DpMLUEOB.js +1 -0
- package/dist/assets/{markdown-renderer-dABDqZDw.js → markdown-renderer-DtzxgcfB.js} +2 -2
- package/dist/assets/{name-cell-input-Y4knmEIU.js → name-cell-input-SbknxDvi.js} +1 -1
- package/dist/assets/{outline-panel-CQ_KWLip.js → outline-panel-kV7ARoXE.js} +1 -1
- package/dist/assets/{packages-panel-Ijt7d51P.js → packages-panel-B3biBPQ1.js} +1 -1
- package/dist/assets/{panels-DfU1Oikj.js → panels-BsrSW0bC.js} +2 -2
- package/dist/assets/process-output-DCAOrKEU.js +1 -0
- package/dist/assets/{radio-group-22eWJ9fv.js → radio-group-BWAhJtjV.js} +1 -1
- package/dist/assets/readonly-code-display-D_rgEfAm.js +1 -0
- package/dist/assets/{readonly-python-code-n_TrLmsR.js → readonly-python-code-B5ABqdqK.js} +1 -1
- package/dist/assets/{reveal-component-CCLTV1q6.js → reveal-component-CrcdxGl_.js} +2 -2
- package/dist/assets/{run-page-DbezK7Qs.js → run-page-DFHpKr66.js} +1 -1
- package/dist/assets/{scratchpad-panel-C2wAEv5n.js → scratchpad-panel-CfqnZK3C.js} +1 -1
- package/dist/assets/{session-panel-BZGNcZmp.js → session-panel-DWS61Z1x.js} +1 -1
- package/dist/assets/{skeleton-BzlKcq21.js → skeleton-PJnQ2_IA.js} +1 -1
- package/dist/assets/{snippets-panel-DNaNtkR0.js → snippets-panel-D1eovB0O.js} +1 -1
- package/dist/assets/{state-jCdh8Dcx.js → state-BjouLTuw.js} +1 -1
- package/dist/assets/{state-DFPAfLw7.js → state-Bu-aMpIc.js} +3 -3
- package/dist/assets/{textarea-DuEtSOCl.js → textarea-DhPaQ0wx.js} +1 -1
- package/dist/assets/{tracing-ttUd3J7U.js → tracing-B2ux60rQ.js} +1 -1
- package/dist/assets/{tracing-panel-rVAa3En0.js → tracing-panel-CF8H5wRv.js} +2 -2
- package/dist/assets/{tree-actions-UCr1tMHw.js → tree-actions-CPSDN4eE.js} +1 -1
- package/dist/assets/useCellActionButton-k2OXllYI.js +1 -0
- package/dist/assets/{useDeleteCell-PrgejW8A.js → useDeleteCell-C3nmnuxK.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-5jc-_-hy.js → useDependencyPanelTab-D14Lna3z.js} +1 -1
- package/dist/assets/{useNotebookActions-4vw_NiRs.js → useNotebookActions-CHM0Ardg.js} +3 -3
- package/dist/assets/useRunCells-C4qD32Ix.js +1 -0
- package/dist/assets/useSplitCell-BEebdldD.js +1 -0
- package/dist/index.html +23 -23
- package/package.json +2 -3
- package/src/components/editor/chrome/panels/__tests__/logs-panel.test.tsx +25 -0
- package/src/components/editor/chrome/panels/logs-panel.tsx +12 -2
- package/src/core/cells/__tests__/cells.test.ts +12 -2
- package/src/core/cells/__tests__/logs.test.ts +5 -5
- package/src/core/cells/cells.ts +13 -0
- package/src/core/cells/document-changes.ts +1 -0
- package/src/core/cells/logs.ts +14 -4
- package/src/core/codemirror/copilot/__tests__/language-server.test.ts +396 -100
- package/src/core/codemirror/copilot/__tests__/transport.test.ts +128 -540
- package/src/core/codemirror/copilot/language-server.ts +182 -70
- package/src/core/codemirror/copilot/transport.ts +15 -207
- package/src/core/codemirror/copilot/types.ts +9 -2
- package/src/core/codemirror/language/languages/python.ts +23 -11
- package/src/core/codemirror/lsp/__tests__/federated-lsp.test.ts +161 -0
- package/src/core/codemirror/lsp/__tests__/log-messages.test.ts +53 -0
- package/src/core/codemirror/lsp/__tests__/normalize-markdown-math.test.ts +25 -0
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +598 -156
- package/src/core/codemirror/lsp/__tests__/transports.test.ts +112 -0
- package/src/core/codemirror/lsp/federated-lsp.ts +76 -23
- package/src/core/codemirror/lsp/log-messages.ts +37 -0
- package/src/core/codemirror/lsp/normalize-markdown-math.ts +8 -4
- package/src/core/codemirror/lsp/notebook-lsp.ts +220 -56
- package/src/core/codemirror/lsp/transports.ts +8 -1
- package/src/core/codemirror/lsp/types.ts +68 -8
- package/src/core/codemirror/lsp/utils.ts +14 -0
- package/src/core/lsp/__tests__/transport.test.ts +509 -337
- package/src/core/lsp/transport.ts +304 -132
- package/src/css/app/codemirror.css +16 -2
- package/src/stories/log-viewer.stories.tsx +12 -6
- package/dist/assets/ai-model-dropdown-BpVBUZnz.js +0 -5
- package/dist/assets/cells-6yd8nOAu.js +0 -231
- package/dist/assets/logs-panel-5u1wUBn1.js +0 -1
- package/dist/assets/process-output-Dd11YI04.js +0 -1
- package/dist/assets/readonly-code-display-BjK-TEri.js +0 -1
- package/dist/assets/useCellActionButton-CJknR0XY.js +0 -1
- package/dist/assets/useRunCells-DHsd7HGL.js +0 -1
- package/dist/assets/useSplitCell-MZpER0Bh.js +0 -1
|
@@ -38,7 +38,11 @@ import { createLspMarkdownRenderer } from "../../lsp/markdown-renderer";
|
|
|
38
38
|
import { NotebookLanguageServerClient } from "../../lsp/notebook-lsp";
|
|
39
39
|
import { createTransport } from "../../lsp/transports";
|
|
40
40
|
import { CellDocumentUri, type ILanguageServerClient } from "../../lsp/types";
|
|
41
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
getLspRootUri,
|
|
43
|
+
getLspWorkspaceFolders,
|
|
44
|
+
isKnownCellDocumentUri,
|
|
45
|
+
} from "../../lsp/utils";
|
|
42
46
|
import {
|
|
43
47
|
clickablePlaceholderExtension,
|
|
44
48
|
smartPlaceholderExtension,
|
|
@@ -338,6 +342,21 @@ export class PythonLanguageAdapter implements LanguageAdapter<{}> {
|
|
|
338
342
|
clients.length === 1
|
|
339
343
|
? (clients[0] as NotebookLanguageServerClient)
|
|
340
344
|
: new FederatedLanguageServerClient(clients);
|
|
345
|
+
const openExternalLocation = (result: { uri: string }) => {
|
|
346
|
+
Logger.debug("openExternalLocation", result);
|
|
347
|
+
// Neither the merged document nor a cell is a file on disk. The
|
|
348
|
+
// plugin handles same-cell locations itself; revealing a location in
|
|
349
|
+
// another cell isn't supported yet.
|
|
350
|
+
if (
|
|
351
|
+
client.documentUri === result.uri ||
|
|
352
|
+
isKnownCellDocumentUri(result.uri)
|
|
353
|
+
) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
getRequestClient().openFile({
|
|
357
|
+
path: result.uri.replace("file://", ""),
|
|
358
|
+
});
|
|
359
|
+
};
|
|
341
360
|
|
|
342
361
|
return [
|
|
343
362
|
languageServerWithClient({
|
|
@@ -346,6 +365,7 @@ export class PythonLanguageAdapter implements LanguageAdapter<{}> {
|
|
|
346
365
|
allowHTMLContent: true,
|
|
347
366
|
markdownRenderer: createLspMarkdownRenderer(),
|
|
348
367
|
useSnippetOnCompletion: true,
|
|
368
|
+
clientSideFiltering: true,
|
|
349
369
|
hoverConfig: hoverOptions,
|
|
350
370
|
completionConfig: autocompleteOptions,
|
|
351
371
|
// Default to false
|
|
@@ -362,16 +382,8 @@ export class PythonLanguageAdapter implements LanguageAdapter<{}> {
|
|
|
362
382
|
rename: hotkeys.getHotkey("cell.renameSymbol").key,
|
|
363
383
|
},
|
|
364
384
|
completionMatchBefore,
|
|
365
|
-
onGoToDefinition:
|
|
366
|
-
|
|
367
|
-
if (client.documentUri === result.uri) {
|
|
368
|
-
// Local definition
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
getRequestClient().openFile({
|
|
372
|
-
path: result.uri.replace("file://", ""),
|
|
373
|
-
});
|
|
374
|
-
},
|
|
385
|
+
onGoToDefinition: openExternalLocation,
|
|
386
|
+
onShowLocation: openExternalLocation,
|
|
375
387
|
}),
|
|
376
388
|
documentUri.of(CellDocumentUri.of(cellId)),
|
|
377
389
|
];
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it, type Mocked, vi } from "vitest";
|
|
4
|
+
import type * as LSP from "vscode-languageserver-protocol";
|
|
5
|
+
import { FederatedLanguageServerClient } from "../federated-lsp";
|
|
6
|
+
import type { ILanguageServerClient } from "../types";
|
|
7
|
+
|
|
8
|
+
function createClient(
|
|
9
|
+
supportedMethods: string[] = [],
|
|
10
|
+
): Mocked<ILanguageServerClient> {
|
|
11
|
+
const client: Mocked<ILanguageServerClient> = {
|
|
12
|
+
ready: true,
|
|
13
|
+
capabilities: {},
|
|
14
|
+
initializePromise: Promise.resolve(),
|
|
15
|
+
clientCapabilities: {},
|
|
16
|
+
initialize: vi.fn(),
|
|
17
|
+
close: vi.fn(),
|
|
18
|
+
hasCapability: vi.fn((method) => supportedMethods.includes(method)),
|
|
19
|
+
textDocumentDidOpen: vi.fn().mockResolvedValue(false),
|
|
20
|
+
textDocumentDidChange: vi.fn(),
|
|
21
|
+
textDocumentDidClose: vi.fn(),
|
|
22
|
+
textDocumentWillSave: vi.fn(),
|
|
23
|
+
textDocumentWillSaveWaitUntil: vi.fn().mockResolvedValue(null),
|
|
24
|
+
textDocumentDidSave: vi.fn(),
|
|
25
|
+
textDocumentHover: vi.fn().mockResolvedValue({ contents: [] }),
|
|
26
|
+
textDocumentCompletion: vi.fn().mockResolvedValue(null),
|
|
27
|
+
completionItemResolve: vi.fn(),
|
|
28
|
+
textDocumentDefinition: vi.fn().mockResolvedValue(null),
|
|
29
|
+
textDocumentCodeAction: vi.fn().mockResolvedValue(null),
|
|
30
|
+
codeActionResolve: vi.fn(),
|
|
31
|
+
textDocumentRename: vi.fn().mockResolvedValue(null),
|
|
32
|
+
textDocumentPrepareRename: vi.fn().mockResolvedValue(null),
|
|
33
|
+
textDocumentSignatureHelp: vi.fn().mockResolvedValue(null),
|
|
34
|
+
onNotification: vi.fn().mockReturnValue(() => true),
|
|
35
|
+
};
|
|
36
|
+
return client;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("FederatedLanguageServerClient", () => {
|
|
40
|
+
it("routes requests using dynamic method capabilities", async () => {
|
|
41
|
+
const staticOnlyClient = createClient();
|
|
42
|
+
const dynamicClient = createClient(["textDocument/definition"]);
|
|
43
|
+
const definition: LSP.Location = {
|
|
44
|
+
uri: "file:///definition.py",
|
|
45
|
+
range: {
|
|
46
|
+
start: { line: 1, character: 2 },
|
|
47
|
+
end: { line: 1, character: 5 },
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
dynamicClient.textDocumentDefinition.mockResolvedValue(definition);
|
|
51
|
+
const client = new FederatedLanguageServerClient([
|
|
52
|
+
staticOnlyClient,
|
|
53
|
+
dynamicClient,
|
|
54
|
+
]);
|
|
55
|
+
const params: LSP.DefinitionParams = {
|
|
56
|
+
textDocument: { uri: "file:///notebook.py" },
|
|
57
|
+
position: { line: 0, character: 0 },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
await expect(client.textDocumentDefinition(params)).resolves.toEqual(
|
|
61
|
+
definition,
|
|
62
|
+
);
|
|
63
|
+
expect(client.hasCapability("textDocument/definition")).toBe(true);
|
|
64
|
+
expect(staticOnlyClient.textDocumentDefinition).not.toHaveBeenCalled();
|
|
65
|
+
expect(dynamicClient.textDocumentDefinition).toHaveBeenCalledWith(params);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("prefers the first client's willSaveWaitUntil edits regardless of latency", async () => {
|
|
69
|
+
const slowEdits: LSP.TextEdit[] = [
|
|
70
|
+
{
|
|
71
|
+
range: {
|
|
72
|
+
start: { line: 0, character: 0 },
|
|
73
|
+
end: { line: 0, character: 1 },
|
|
74
|
+
},
|
|
75
|
+
newText: "first",
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
const first = createClient();
|
|
79
|
+
const second = createClient();
|
|
80
|
+
// Answers last, but still wins
|
|
81
|
+
first.textDocumentWillSaveWaitUntil.mockImplementation(
|
|
82
|
+
() => new Promise((resolve) => setTimeout(() => resolve(slowEdits), 5)),
|
|
83
|
+
);
|
|
84
|
+
second.textDocumentWillSaveWaitUntil.mockResolvedValue([
|
|
85
|
+
{
|
|
86
|
+
range: {
|
|
87
|
+
start: { line: 1, character: 0 },
|
|
88
|
+
end: { line: 1, character: 1 },
|
|
89
|
+
},
|
|
90
|
+
newText: "second",
|
|
91
|
+
},
|
|
92
|
+
]);
|
|
93
|
+
const client = new FederatedLanguageServerClient([first, second]);
|
|
94
|
+
|
|
95
|
+
await expect(
|
|
96
|
+
client.textDocumentWillSaveWaitUntil({
|
|
97
|
+
textDocument: { uri: "file:///notebook.py" },
|
|
98
|
+
reason: 1,
|
|
99
|
+
}),
|
|
100
|
+
).resolves.toEqual(slowEdits);
|
|
101
|
+
expect(second.textDocumentWillSaveWaitUntil).toHaveBeenCalled();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("skips clients that reject willSaveWaitUntil", async () => {
|
|
105
|
+
const failing = createClient();
|
|
106
|
+
const working = createClient();
|
|
107
|
+
const edits: LSP.TextEdit[] = [
|
|
108
|
+
{
|
|
109
|
+
range: {
|
|
110
|
+
start: { line: 0, character: 0 },
|
|
111
|
+
end: { line: 0, character: 1 },
|
|
112
|
+
},
|
|
113
|
+
newText: "ok",
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
failing.textDocumentWillSaveWaitUntil.mockRejectedValue(
|
|
117
|
+
new Error("server exploded"),
|
|
118
|
+
);
|
|
119
|
+
working.textDocumentWillSaveWaitUntil.mockResolvedValue(edits);
|
|
120
|
+
const client = new FederatedLanguageServerClient([failing, working]);
|
|
121
|
+
|
|
122
|
+
await expect(
|
|
123
|
+
client.textDocumentWillSaveWaitUntil({
|
|
124
|
+
textDocument: { uri: "file:///notebook.py" },
|
|
125
|
+
reason: 1,
|
|
126
|
+
}),
|
|
127
|
+
).resolves.toEqual(edits);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("fans out document lifecycle and save notifications", async () => {
|
|
131
|
+
const first = createClient();
|
|
132
|
+
const second = createClient();
|
|
133
|
+
second.textDocumentDidOpen.mockResolvedValue(true);
|
|
134
|
+
const client = new FederatedLanguageServerClient([first, second]);
|
|
135
|
+
const openParams: LSP.DidOpenTextDocumentParams = {
|
|
136
|
+
textDocument: {
|
|
137
|
+
uri: "file:///notebook.py",
|
|
138
|
+
languageId: "python",
|
|
139
|
+
version: 1,
|
|
140
|
+
text: "value = 1",
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
const closeParams: LSP.DidCloseTextDocumentParams = {
|
|
144
|
+
textDocument: { uri: "file:///notebook.py" },
|
|
145
|
+
};
|
|
146
|
+
const saveParams: LSP.DidSaveTextDocumentParams = {
|
|
147
|
+
textDocument: { uri: "file:///notebook.py" },
|
|
148
|
+
text: "value = 1",
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
await expect(client.textDocumentDidOpen(openParams)).resolves.toBe(true);
|
|
152
|
+
await client.textDocumentDidClose(closeParams);
|
|
153
|
+
await client.textDocumentDidSave(saveParams);
|
|
154
|
+
|
|
155
|
+
for (const child of [first, second]) {
|
|
156
|
+
expect(child.textDocumentDidOpen).toHaveBeenCalledWith(openParams);
|
|
157
|
+
expect(child.textDocumentDidClose).toHaveBeenCalledWith(closeParams);
|
|
158
|
+
expect(child.textDocumentDidSave).toHaveBeenCalledWith(saveParams);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type { JSONRPCMessage } from "@marimo-team/codemirror-languageserver";
|
|
4
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
5
|
+
import { initialNotebookState, notebookAtom } from "@/core/cells/cells";
|
|
6
|
+
import { store } from "@/core/state/jotai";
|
|
7
|
+
import { handleLogMessage } from "../log-messages";
|
|
8
|
+
|
|
9
|
+
function logMessage(type: number, message: string): JSONRPCMessage {
|
|
10
|
+
return {
|
|
11
|
+
jsonrpc: "2.0",
|
|
12
|
+
method: "window/logMessage",
|
|
13
|
+
params: { type, message },
|
|
14
|
+
} as JSONRPCMessage;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe("handleLogMessage", () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
store.set(notebookAtom, initialNotebookState());
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("adds a log for each message, erroring on Error and Warning", () => {
|
|
23
|
+
handleLogMessage("pylsp", logMessage(1, "failed to start"));
|
|
24
|
+
handleLogMessage("pylsp", logMessage(2, "plugin not installed"));
|
|
25
|
+
handleLogMessage("pylsp", logMessage(3, "indexing"));
|
|
26
|
+
|
|
27
|
+
expect(store.get(notebookAtom).cellLogs).toMatchObject([
|
|
28
|
+
{ level: "stderr", message: "failed to start" },
|
|
29
|
+
{ level: "stderr", message: "plugin not installed" },
|
|
30
|
+
{
|
|
31
|
+
level: "stdout",
|
|
32
|
+
message: "indexing",
|
|
33
|
+
source: { type: "lsp", name: "pylsp" },
|
|
34
|
+
},
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("ignores messages that aren't logs", () => {
|
|
39
|
+
handleLogMessage("pylsp", { jsonrpc: "2.0", id: 1 } as JSONRPCMessage);
|
|
40
|
+
handleLogMessage("pylsp", {
|
|
41
|
+
jsonrpc: "2.0",
|
|
42
|
+
method: "textDocument/publishDiagnostics",
|
|
43
|
+
params: { uri: "file:///a", diagnostics: [] },
|
|
44
|
+
} as JSONRPCMessage);
|
|
45
|
+
handleLogMessage("pylsp", {
|
|
46
|
+
jsonrpc: "2.0",
|
|
47
|
+
method: "window/logMessage",
|
|
48
|
+
params: { type: 1 },
|
|
49
|
+
} as JSONRPCMessage);
|
|
50
|
+
|
|
51
|
+
expect(store.get(notebookAtom).cellLogs).toEqual([]);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -90,6 +90,31 @@ Use \`:math:\` as text and :math:\`z\` as math.
|
|
|
90
90
|
expect(normalized).not.toContain(":math:`z`");
|
|
91
91
|
expect(normalized).toContain("||(z||)");
|
|
92
92
|
});
|
|
93
|
+
|
|
94
|
+
it("leaves markdown-escaped brackets in type annotations alone", () => {
|
|
95
|
+
const markdown =
|
|
96
|
+
'on\\_change (Optional\\[Callable\\]) and editable\\_columns (Union\\[list\\[str\\], Literal\\["all"\\]\\])';
|
|
97
|
+
|
|
98
|
+
expect(normalizeMarkdownMath(markdown)).toBe(markdown);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("keeps the newlines around fenced code blocks", () => {
|
|
102
|
+
const markdown = `
|
|
103
|
+
\`\`\`python
|
|
104
|
+
class data_editor()
|
|
105
|
+
\`\`\`
|
|
106
|
+
---
|
|
107
|
+
Inline \\[z^2\\] math forces normalization.
|
|
108
|
+
|
|
109
|
+
Done.
|
|
110
|
+
`.trim();
|
|
111
|
+
|
|
112
|
+
// A closing fence glued to the next line stops closing the block, and the
|
|
113
|
+
// rest of the document is swallowed into it.
|
|
114
|
+
expect(normalizeMarkdownMath(markdown)).toContain(
|
|
115
|
+
"class data_editor()\n```\n---\n",
|
|
116
|
+
);
|
|
117
|
+
});
|
|
93
118
|
});
|
|
94
119
|
|
|
95
120
|
describe("normalizeLspDocumentation", () => {
|