@marimo-team/frontend 0.15.5 → 0.16.0
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/{ConnectedDataExplorerComponent-Cn5-l2X1.js → ConnectedDataExplorerComponent-BErMbWvG.js} +1 -1
- package/dist/assets/{ImageComparisonComponent-CEXMKKA4.js → ImageComparisonComponent-fTHv1Ih0.js} +1 -1
- package/dist/assets/{VegaLite-Bt14Ds9k.js → VegaLite-Bdi-TyfY.js} +6 -6
- package/dist/assets/_baseEach-CNBxBxvS.js +1 -0
- package/dist/assets/_baseMap-D1WHjKrd.js +1 -0
- package/dist/assets/_baseUniq-CCgDNtZb.js +1 -0
- package/dist/assets/_createAggregator-DcD0kTA5.js +1 -0
- package/dist/assets/agent-panel-Crv430aI.js +268 -0
- package/dist/assets/agent-panel-D92Mfy1i.css +1 -0
- package/dist/assets/{any-language-editor-DiwNT6zp.js → any-language-editor-CQh552Wu.js} +1 -1
- package/dist/assets/architectureDiagram-W76B3OCA-BAJeBxzt.js +36 -0
- package/dist/assets/{between-horizontal-start-FyewyCGn.js → between-horizontal-start-Boxgxbt_.js} +1 -1
- package/dist/assets/{blockDiagram-QIGZ2CNN-BrOkAf_c.js → blockDiagram-QIGZ2CNN-CL-1svEK.js} +1 -1
- package/dist/assets/{c4Diagram-FPNF74CW-BHPzDxE2.js → c4Diagram-FPNF74CW-BbEqbCTl.js} +5 -5
- package/dist/assets/channel-_2eNSz0n.js +1 -0
- package/dist/assets/chat-panel-CXh5Wl6C.js +3 -0
- package/dist/assets/{chunk-4BX2VUAB-DLxaCNYh.js → chunk-4BX2VUAB-C--8TXeE.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DdzvO3HR.js → chunk-55IACEB6-Bj00HDqq.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-R5o-nSiG.js → chunk-FMBD7UC4-C-lhB6hN.js} +1 -1
- package/dist/assets/{chunk-K7UQS3LO-DxaMrGgG.js → chunk-K7UQS3LO-B-pGTXPt.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-DqS9-FYm.js → chunk-QN33PNHL-DqUzGhvm.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BZ-TzajS.js → chunk-QZHKN3VN-TntJHfSk.js} +1 -1
- package/dist/assets/{chunk-TVAH2DTR-BsgP2dyv.js → chunk-TVAH2DTR-HUJb1psV.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-D-h3ahXI.js → chunk-TZMSLE5B-BK3C__t3.js} +1 -1
- package/dist/assets/{circle-play-CQtRZ-rT.js → circle-play-DBLOv1Yu.js} +1 -1
- package/dist/assets/classDiagram-KNZD7YFC-BGmh9POF.js +1 -0
- package/dist/assets/classDiagram-v2-RKCZMP56-BGmh9POF.js +1 -0
- package/dist/assets/{clear-button-BY6Z_ViL.js → clear-button-BeoFbEKH.js} +1 -1
- package/dist/assets/clone-BFDSPAj3.js +1 -0
- package/dist/assets/command-palette-CXZiSv0I.js +1 -0
- package/dist/assets/common-C7oJcmCT.js +1 -0
- package/dist/assets/{compile-Ct_jzdKr.js → compile-7L0MwhyI.js} +1 -1
- package/dist/assets/cose-bilkent-S5V4N54A-BMkGLcVC.js +1 -0
- package/dist/assets/dagre-5GWH7T2D-BJtRienS.js +4 -0
- package/dist/assets/{data-grid-overlay-editor-BN_wulc3.js → data-grid-overlay-editor-DBkmGtNs.js} +1 -1
- package/dist/assets/datasources-panel-B7FbYLiy.js +1 -0
- package/dist/assets/{dependency-graph-panel-BOmSCZf7.js → dependency-graph-panel-DEdOxp2X.js} +4 -4
- package/dist/assets/diagram-N5W7TBWH-CmECY3nb.js +24 -0
- package/dist/assets/diagram-QEK2KX5R-DMOVSNKD.js +43 -0
- package/dist/assets/diagram-S2PKOQOG-BiJ96PNQ.js +24 -0
- package/dist/assets/{documentation-panel-BxjJO_Gw.js → documentation-panel-xULhaEv3.js} +1 -1
- package/dist/assets/edit-page-BrYda9VE.js +129 -0
- package/dist/assets/{ellipsis-vertical-UHbmjI2n.js → ellipsis-vertical-BBqXIlc2.js} +1 -1
- package/dist/assets/{empty-state-BIBXzY_0.js → empty-state-B3dA3G5P.js} +1 -1
- package/dist/assets/{erDiagram-AWTI2OKA-E84mAle_.js → erDiagram-AWTI2OKA-MP1DiFRo.js} +1 -1
- package/dist/assets/{error-panel-MEvQ6K7h.js → error-panel-Cc1sv-Ag.js} +1 -1
- package/dist/assets/file-explorer-panel-Bw59Kva1.js +1 -0
- package/dist/assets/{flowDiagram-PVAE7QVJ-DfbIRSAW.js → flowDiagram-PVAE7QVJ-BX7caPp7.js} +1 -1
- package/dist/assets/{ganttDiagram-OWAHRB6G-DR4HZ1z_.js → ganttDiagram-OWAHRB6G-B462g4Yf.js} +3 -3
- package/dist/assets/gitGraphDiagram-NY62KEGX-CGgvZ9-9.js +65 -0
- package/dist/assets/{glide-data-editor-nNmo1lPq.js → glide-data-editor-C0gUFZON.js} +4 -4
- package/dist/assets/graph-CHRVBzY5.js +1 -0
- package/dist/assets/{home-page-9eW6qida.js → home-page-Fb2osjys.js} +3 -3
- package/dist/assets/{index-DMomwMcN.js → index-BVgAenPd.js} +1 -1
- package/dist/assets/{index-B8llrTSo.js → index-BY93Ejhl.js} +1 -1
- package/dist/assets/{index-BFSnz7iM.js → index-C-8WADat.js} +1 -1
- package/dist/assets/{index-CPN7TRA1.js → index-C-GhZ7ti.js} +1 -1
- package/dist/assets/{index-DyLSuOH1.js → index-C1v_Z9et.js} +1 -1
- package/dist/assets/{index-VPWqq2Pg.js → index-C4Tn5NvJ.js} +1 -1
- package/dist/assets/{index-BAH034Ue.js → index-C77h_TXN.js} +1 -1
- package/dist/assets/{index-Dt9UWeWn.js → index-CQDrxQ0j.js} +1 -1
- package/dist/assets/{index-DWOaniGT.js → index-CWMgowgL.js} +1 -1
- package/dist/assets/{index-B1_GXGaP.js → index-Clbi_Yaq.js} +1 -1
- package/dist/assets/{index-B7yXbrLa.js → index-CpTPJo4k.js} +1 -1
- package/dist/assets/{index-CknhX2Vy.css → index-Cx0bsY1w.css} +1 -1
- package/dist/assets/{index-DqzMPAC8.js → index-D1vmG6DS.js} +2 -2
- package/dist/assets/{index-c6If577Q.js → index-D9UKkrr2.js} +1 -1
- package/dist/assets/{index-CB2pnVQG.js → index-DEQvTChO.js} +1 -1
- package/dist/assets/{index-OC46250R.js → index-DKEudB02.js} +205 -197
- package/dist/assets/{index-CSgxTUzD.js → index-DRMm6SNo.js} +1 -1
- package/dist/assets/{index-Bq516OmX.js → index-DoRmcrKM.js} +1 -1
- package/dist/assets/{index-DSU75csX.js → index-lYa_leQE.js} +1 -1
- package/dist/assets/{index-BLu5CX6z.js → index-vmICa5KN.js} +1 -1
- package/dist/assets/{index-uacyUula.js → index-z9bohSQJ.js} +1 -1
- package/dist/assets/infoDiagram-STP46IZ2-CVyrdLc8.js +2 -0
- package/dist/assets/isEmpty-DU_ogP_D.js +1 -0
- package/dist/assets/{journeyDiagram-BIP6EPQ6-BBiFyygf.js → journeyDiagram-BIP6EPQ6-C6EgLP_Q.js} +1 -1
- package/dist/assets/{kanban-definition-6OIFK2YF-DhgA6Nt6.js → kanban-definition-6OIFK2YF-BXzYO1yj.js} +4 -4
- package/dist/assets/layout-jihVw5-i.js +1 -0
- package/dist/assets/linear-C4blANlC.js +1 -0
- package/dist/assets/{links-CbvGxbsJ.js → links-D59GIweI.js} +3 -3
- package/dist/assets/{logs-panel-B9SmTZAW.js → logs-panel-D401qzZh.js} +1 -1
- package/dist/assets/markdown-renderer-Cd9eYyaL.js +263 -0
- package/dist/assets/{agent-panel-DpQ6muj-.css → markdown-renderer-ClyzDMmG.css} +1 -1
- package/dist/assets/mermaid-BEVuRz_O.js +1 -0
- package/dist/assets/{mermaid.core-4nVOEVX3.js → mermaid.core-CaSnaLH0.js} +41 -41
- package/dist/assets/min-DUMu_zeK.js +1 -0
- package/dist/assets/{mindmap-definition-Q6HEUPPD-CVLQNn1q.js → mindmap-definition-Q6HEUPPD-BXUM5MT2.js} +2 -2
- package/dist/assets/{number-overlay-editor-CzRzXLcd.js → number-overlay-editor-4uWXGlPG.js} +1 -1
- package/dist/assets/{outline-panel-uvsS-YEQ.js → outline-panel-DIzkvm2I.js} +1 -1
- package/dist/assets/packages-panel-CJL0MVlj.js +1 -0
- package/dist/assets/{pieDiagram-ADFJNKIX-C5IQ5DBZ.js → pieDiagram-ADFJNKIX-Dxt5PVNo.js} +3 -3
- package/dist/assets/{quadrantDiagram-LMRXKWRM-CFXFnQxx.js → quadrantDiagram-LMRXKWRM-D4pUaA31.js} +1 -1
- package/dist/assets/{react-plotly-mzdv02_Y.js → react-plotly-cJZ0VWBq.js} +1 -1
- package/dist/assets/{requirementDiagram-4UW4RH46-D9bPC89T.js → requirementDiagram-4UW4RH46-DVRTjgas.js} +1 -1
- package/dist/assets/run-page-BUEnMC9w.js +1 -0
- package/dist/assets/sankeyDiagram-GR3RE2ED-CVFnD9C-.js +10 -0
- package/dist/assets/scratchpad-panel-BIgRENkI.js +1 -0
- package/dist/assets/secrets-panel-xY5-V_BD.js +1 -0
- package/dist/assets/{sequenceDiagram-C3RYC4MD-6N7_hY4k.js → sequenceDiagram-C3RYC4MD-_lY4ZN_S.js} +4 -4
- package/dist/assets/{slides-component-EcjC8sDK.js → slides-component-Xjymwj7X.js} +1 -1
- package/dist/assets/snippets-panel-CTPYW41n.js +1 -0
- package/dist/assets/sortBy-BNZKwiq_.js +1 -0
- package/dist/assets/state-C4NiC9tO.js +1 -0
- package/dist/assets/stateDiagram-KXAO66HF-Da0JQWCn.js +1 -0
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-D5lYZOOt.js +1 -0
- package/dist/assets/storage-CMdLzB_c.js +26 -0
- package/dist/assets/terminal-BPwTkXae.js +10 -0
- package/dist/assets/time-Dv5_Ouz_.js +1 -0
- package/dist/assets/{timeline-definition-XQNQX7LJ-BEaynAiY.js → timeline-definition-XQNQX7LJ-Dxh5Zu2e.js} +1 -1
- package/dist/assets/tracing-BCIurUfa.js +2 -0
- package/dist/assets/{tracing-panel-BmuHLPrY.js → tracing-panel-DAzrzNmm.js} +2 -2
- package/dist/assets/{trash-UBqfK4mR.js → trash-Dc6DSjz_.js} +1 -1
- package/dist/assets/{tree-XiEycetl.js → tree-jheoerAX.js} +1 -1
- package/dist/assets/{treemap-75Q7IDZK-CnuVFbBG.js → treemap-75Q7IDZK-IgpxeGaf.js} +21 -21
- package/dist/assets/{ts-tags-CloPe9IY.js → ts-tags-DxCDHihD.js} +1 -1
- package/dist/assets/variable-panel-DYAiLBmF.js +1 -0
- package/dist/assets/{vega-component-DsTH4tuX.js → vega-component-BpfpiPKI.js} +1 -1
- package/dist/assets/{xychartDiagram-6GGTOJPD-Dcz3O-A3.js → xychartDiagram-6GGTOJPD-CmNigJ31.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +8 -4
- package/src/__tests__/mocks.ts +43 -0
- package/src/components/app-config/user-config-form.tsx +32 -0
- package/src/components/chat/acp/__tests__/__snapshots__/prompt.test.ts.snap +55 -23
- package/src/components/chat/acp/__tests__/context-utils.test.ts +222 -0
- package/src/components/chat/acp/__tests__/prompt.test.ts +1 -1
- package/src/components/chat/acp/__tests__/state.test.ts +2 -6
- package/src/components/chat/acp/agent-docs.tsx +33 -6
- package/src/components/chat/acp/agent-panel.css +0 -18
- package/src/components/chat/acp/agent-panel.tsx +397 -72
- package/src/components/chat/acp/agent-selector.tsx +7 -1
- package/src/components/chat/acp/blocks.tsx +40 -10
- package/src/components/chat/acp/common.tsx +10 -2
- package/src/components/chat/acp/context-utils.ts +127 -0
- package/src/components/chat/acp/prompt.ts +34 -10
- package/src/components/chat/acp/state.ts +1 -1
- package/src/components/chat/acp/types.ts +8 -0
- package/src/components/chat/chat-panel.tsx +23 -88
- package/src/components/chat/chat-utils.ts +127 -1
- package/src/components/chat/markdown-renderer.css +39 -0
- package/src/components/chat/markdown-renderer.tsx +7 -38
- package/src/components/chat/tool-call-accordion.tsx +113 -23
- package/src/components/editor/Cell.tsx +6 -0
- package/src/components/editor/actions/name-cell-input.tsx +6 -1
- package/src/components/editor/actions/useCellActionButton.tsx +3 -1
- package/src/components/editor/ai/__tests__/completion-utils.test.ts +178 -1
- package/src/components/editor/ai/add-cell-with-ai.tsx +68 -66
- package/src/components/editor/ai/ai-completion-editor.tsx +29 -26
- package/src/components/editor/ai/completion-handlers.tsx +44 -6
- package/src/components/editor/ai/completion-utils.ts +92 -0
- package/src/components/editor/ai/transport/chat-transport.tsx +36 -0
- package/src/components/editor/cell/StagedAICell.tsx +51 -0
- package/src/components/editor/cell/cell-actions.tsx +2 -1
- package/src/components/terminal/__tests__/state.test.ts +207 -0
- package/src/components/terminal/hooks.ts +41 -0
- package/src/components/terminal/state.ts +75 -0
- package/src/components/terminal/terminal.tsx +334 -13
- package/src/components/terminal/theme.tsx +56 -0
- package/src/core/ai/__tests__/staged-cells.test.ts +356 -0
- package/src/core/ai/staged-cells.ts +208 -0
- package/src/core/cells/cells.ts +1 -1
- package/src/core/codemirror/lsp/federated-lsp.ts +1 -1
- package/src/core/islands/main.ts +2 -2
- package/src/core/kernel/messages.ts +8 -12
- package/src/core/saving/__tests__/filename.test.ts +37 -0
- package/src/core/static/__tests__/download-html.test.ts +43 -1
- package/src/core/websocket/useMarimoWebSocket.tsx +2 -2
- package/src/css/app/Cell.css +11 -0
- package/src/plugins/core/RenderHTML.tsx +36 -2
- package/src/plugins/core/__test__/RenderHTML.test.ts +72 -0
- package/src/plugins/core/registerReactComponent.tsx +28 -0
- package/src/plugins/impl/FileBrowserPlugin.tsx +8 -2
- package/src/stories/cell.stories.tsx +1 -1
- package/src/stories/layout/vertical/one-column.stories.tsx +1 -1
- package/src/utils/__tests__/cell-urls.test.ts +29 -0
- package/src/utils/__tests__/filenames.test.ts +18 -0
- package/src/utils/__tests__/path.test.ts +38 -0
- package/src/utils/__tests__/urls.test.ts +56 -1
- package/src/utils/errors.ts +9 -0
- package/dist/assets/_baseEach-C1FLm7WW.js +0 -1
- package/dist/assets/_baseMap-DBVArUYD.js +0 -1
- package/dist/assets/_baseUniq-Dk7ZPJ3N.js +0 -1
- package/dist/assets/_createAggregator-Bn38fDd3.js +0 -1
- package/dist/assets/agent-panel-COUYnuIK.js +0 -475
- package/dist/assets/architectureDiagram-W76B3OCA-DBzWQKKu.js +0 -36
- package/dist/assets/channel-CjhbjOv4.js +0 -1
- package/dist/assets/chat-panel-BPXKoTnZ.js +0 -7
- package/dist/assets/chat-panel-Brrs_eeH.css +0 -1
- package/dist/assets/classDiagram-KNZD7YFC-DHs5cFzy.js +0 -1
- package/dist/assets/classDiagram-v2-RKCZMP56-DHs5cFzy.js +0 -1
- package/dist/assets/clone-DM1YNjEn.js +0 -1
- package/dist/assets/command-palette-S0bzQp7v.js +0 -1
- package/dist/assets/common-B8U9k2Ly.js +0 -1
- package/dist/assets/cose-bilkent-S5V4N54A-wz1Sfx7j.js +0 -1
- package/dist/assets/dagre-5GWH7T2D-BfpcVBgq.js +0 -4
- package/dist/assets/datasources-panel-DfuURLJw.js +0 -1
- package/dist/assets/diagram-N5W7TBWH-Bf0oqqQh.js +0 -24
- package/dist/assets/diagram-QEK2KX5R-ZTc3qikh.js +0 -43
- package/dist/assets/diagram-S2PKOQOG-tLScBy7Z.js +0 -24
- package/dist/assets/edit-page-DJ8kJZ9w.js +0 -129
- package/dist/assets/file-explorer-panel-CzNUJ63G.js +0 -1
- package/dist/assets/gitGraphDiagram-NY62KEGX-C1t6QtVa.js +0 -65
- package/dist/assets/graph-CssCVWIq.js +0 -1
- package/dist/assets/index-DcCIe7np.js +0 -28
- package/dist/assets/infoDiagram-STP46IZ2-CwiAoz9f.js +0 -2
- package/dist/assets/layout-DpQrxGW-.js +0 -1
- package/dist/assets/linear-NsreOeBF.js +0 -1
- package/dist/assets/mermaid-DSt0r6IQ.js +0 -1
- package/dist/assets/min-D259kI3t.js +0 -1
- package/dist/assets/packages-panel-xMz9W2hW.js +0 -1
- package/dist/assets/run-page-Bb68qdhQ.js +0 -1
- package/dist/assets/sankeyDiagram-GR3RE2ED-BSJOau8E.js +0 -10
- package/dist/assets/scratchpad-panel-BF4BO-U4.js +0 -1
- package/dist/assets/secrets-panel-CdIX44dQ.js +0 -1
- package/dist/assets/snippets-panel-Dco9h0rb.js +0 -1
- package/dist/assets/sortBy-aLGA-PGK.js +0 -1
- package/dist/assets/stateDiagram-KXAO66HF-Bd68WT3b.js +0 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-BXz_GSwb.js +0 -1
- package/dist/assets/storage-CGlP4lCF.js +0 -26
- package/dist/assets/terminal-CxkHubcu.js +0 -9
- package/dist/assets/time-D2nr1UgQ.js +0 -1
- package/dist/assets/tracing-kTqHxa7q.js +0 -2
- package/dist/assets/variable-panel-noTnH-AQ.js +0 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { EDGE_CASE_FILENAMES } from "../../../__tests__/mocks";
|
|
4
|
+
import { Filenames } from "../../../utils/filenames";
|
|
5
|
+
import { Paths } from "../../../utils/paths";
|
|
3
6
|
import { visibleForTesting } from "../download-html";
|
|
4
7
|
|
|
5
8
|
const { updateAssetUrl } = visibleForTesting;
|
|
@@ -39,3 +42,42 @@ describe("updateAssetUrl", () => {
|
|
|
39
42
|
expect(updateAssetUrl(existingUrl, assetBaseUrl)).toBe(existingUrl);
|
|
40
43
|
});
|
|
41
44
|
});
|
|
45
|
+
|
|
46
|
+
describe("filename handling for downloads", () => {
|
|
47
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
48
|
+
"should handle edge case filenames in download operations: %s",
|
|
49
|
+
(filename) => {
|
|
50
|
+
// Test that basename extraction works correctly for downloads
|
|
51
|
+
const basename = Paths.basename(filename);
|
|
52
|
+
expect(basename).toBe(filename);
|
|
53
|
+
|
|
54
|
+
// Test filename conversion for HTML downloads
|
|
55
|
+
const htmlFilename = Filenames.toHTML(filename);
|
|
56
|
+
expect(htmlFilename).toMatch(/\.html$/);
|
|
57
|
+
expect(htmlFilename).toContain(Filenames.withoutExtension(filename));
|
|
58
|
+
|
|
59
|
+
// Ensure unicode and spaces are preserved in basename
|
|
60
|
+
const withoutExt = Filenames.withoutExtension(filename);
|
|
61
|
+
expect(withoutExt).not.toBe("");
|
|
62
|
+
expect(typeof withoutExt).toBe("string");
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
it("should handle blob download filename generation", () => {
|
|
67
|
+
// Mock URL.createObjectURL for blob testing
|
|
68
|
+
const mockCreateObjectURL = vi.fn().mockReturnValue("blob:mock-url");
|
|
69
|
+
global.URL.createObjectURL = mockCreateObjectURL;
|
|
70
|
+
|
|
71
|
+
EDGE_CASE_FILENAMES.forEach((filename) => {
|
|
72
|
+
const htmlFilename = Filenames.toHTML(filename);
|
|
73
|
+
|
|
74
|
+
// Verify blob can be created with unicode filenames
|
|
75
|
+
expect(() => new Blob(["test"], { type: "text/html" })).not.toThrow();
|
|
76
|
+
expect(htmlFilename).toMatch(/\.html$/);
|
|
77
|
+
|
|
78
|
+
// Verify filename maintains unicode characters
|
|
79
|
+
const baseName = Filenames.withoutExtension(filename);
|
|
80
|
+
expect(htmlFilename).toContain(baseName);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -86,7 +86,7 @@ export function useMarimoWebSocket(opts: {
|
|
|
86
86
|
|
|
87
87
|
const handleMessage = (e: MessageEvent<JsonString<OperationMessage>>) => {
|
|
88
88
|
const msg = jsonParseWithSpecialChar(e.data);
|
|
89
|
-
switch (msg.op) {
|
|
89
|
+
switch (msg.data.op) {
|
|
90
90
|
case "reload":
|
|
91
91
|
reloadSafe();
|
|
92
92
|
return;
|
|
@@ -267,7 +267,7 @@ export function useMarimoWebSocket(opts: {
|
|
|
267
267
|
setCellIds({ cellIds: msg.data.cell_ids as CellId[] });
|
|
268
268
|
return;
|
|
269
269
|
default:
|
|
270
|
-
logNever(msg);
|
|
270
|
+
logNever(msg.data);
|
|
271
271
|
}
|
|
272
272
|
};
|
|
273
273
|
|
package/src/css/app/Cell.css
CHANGED
|
@@ -23,6 +23,17 @@
|
|
|
23
23
|
outline: none;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
&:has(.mo-ai-generated-cell)::before {
|
|
27
|
+
content: "";
|
|
28
|
+
position: absolute;
|
|
29
|
+
inset: 0;
|
|
30
|
+
border-radius: 10px;
|
|
31
|
+
pointer-events: none;
|
|
32
|
+
opacity: 0.5;
|
|
33
|
+
box-shadow: 0px 0px 10px 0px var(--cyan-9);
|
|
34
|
+
z-index: 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
26
37
|
&:focus-within {
|
|
27
38
|
z-index: 20;
|
|
28
39
|
}
|
|
@@ -5,7 +5,7 @@ import parse, {
|
|
|
5
5
|
Element,
|
|
6
6
|
type HTMLReactParserOptions,
|
|
7
7
|
} from "html-react-parser";
|
|
8
|
-
import React, { type JSX, type ReactNode, useId } from "react";
|
|
8
|
+
import React, { isValidElement, type JSX, type ReactNode, useId } from "react";
|
|
9
9
|
import { CopyClipboardIcon } from "@/components/icons/copy-icon";
|
|
10
10
|
|
|
11
11
|
type ReplacementFn = NonNullable<HTMLReactParserOptions["replace"]>;
|
|
@@ -23,6 +23,36 @@ const replaceValidTags = (domNode: DOMNode) => {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
const removeWrappingBodyTags: TransformFn = (
|
|
27
|
+
reactNode: ReactNode,
|
|
28
|
+
domNode: DOMNode,
|
|
29
|
+
) => {
|
|
30
|
+
// Remove body tags and just render their children
|
|
31
|
+
if (domNode instanceof Element && domNode.name === "body") {
|
|
32
|
+
if (isValidElement(reactNode) && "props" in reactNode) {
|
|
33
|
+
const props = reactNode.props as { children?: ReactNode };
|
|
34
|
+
const children = props.children;
|
|
35
|
+
return <>{children}</>; // eslint-disable-line react/jsx-no-useless-fragment
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const removeWrappingHtmlTags: TransformFn = (
|
|
42
|
+
reactNode: ReactNode,
|
|
43
|
+
domNode: DOMNode,
|
|
44
|
+
) => {
|
|
45
|
+
// Remove html tags and just render their children
|
|
46
|
+
if (domNode instanceof Element && domNode.name === "html") {
|
|
47
|
+
if (isValidElement(reactNode) && "props" in reactNode) {
|
|
48
|
+
const props = reactNode.props as { children?: ReactNode };
|
|
49
|
+
const children = props.children;
|
|
50
|
+
return <>{children}</>; // eslint-disable-line react/jsx-no-useless-fragment
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
26
56
|
const replaceValidIframes = (domNode: DOMNode) => {
|
|
27
57
|
// For iframe, we just want to use dangerouslySetInnerHTML so:
|
|
28
58
|
// 1) we can remount the iframe when the src changes
|
|
@@ -110,7 +140,11 @@ export const renderHTML = ({ html, additionalReplacements = [] }: Options) => {
|
|
|
110
140
|
...additionalReplacements,
|
|
111
141
|
];
|
|
112
142
|
|
|
113
|
-
const transformFunctions: TransformFn[] = [
|
|
143
|
+
const transformFunctions: TransformFn[] = [
|
|
144
|
+
addCopyButtonToCodehilite,
|
|
145
|
+
removeWrappingBodyTags,
|
|
146
|
+
removeWrappingHtmlTags,
|
|
147
|
+
];
|
|
114
148
|
|
|
115
149
|
return parse(html, {
|
|
116
150
|
replace: (domNode: DOMNode, index: number) => {
|
|
@@ -121,6 +121,78 @@ describe("RenderHTML", () => {
|
|
|
121
121
|
</p>
|
|
122
122
|
`);
|
|
123
123
|
});
|
|
124
|
+
|
|
125
|
+
test("removes body tags but preserves children", () => {
|
|
126
|
+
const html = "<body><h1>Hello</h1><p>World</p></body>";
|
|
127
|
+
expect(renderHTML({ html })).toMatchInlineSnapshot(`
|
|
128
|
+
<React.Fragment>
|
|
129
|
+
<h1>
|
|
130
|
+
Hello
|
|
131
|
+
</h1>
|
|
132
|
+
<p>
|
|
133
|
+
World
|
|
134
|
+
</p>
|
|
135
|
+
</React.Fragment>
|
|
136
|
+
`);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("removes nested body tags", () => {
|
|
140
|
+
const html = "<div><body><span>Content</span></body></div>";
|
|
141
|
+
expect(renderHTML({ html })).toMatchInlineSnapshot(`
|
|
142
|
+
<div>
|
|
143
|
+
<React.Fragment>
|
|
144
|
+
<span>
|
|
145
|
+
Content
|
|
146
|
+
</span>
|
|
147
|
+
</React.Fragment>
|
|
148
|
+
</div>
|
|
149
|
+
`);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("removes html tags but preserves children", () => {
|
|
153
|
+
const html =
|
|
154
|
+
"<html><head><title>Test</title></head><body><p>Content</p></body></html>";
|
|
155
|
+
expect(renderHTML({ html })).toMatchInlineSnapshot(`
|
|
156
|
+
<React.Fragment>
|
|
157
|
+
<head>
|
|
158
|
+
<title>
|
|
159
|
+
Test
|
|
160
|
+
</title>
|
|
161
|
+
</head>
|
|
162
|
+
<React.Fragment>
|
|
163
|
+
<p>
|
|
164
|
+
Content
|
|
165
|
+
</p>
|
|
166
|
+
</React.Fragment>
|
|
167
|
+
</React.Fragment>
|
|
168
|
+
`);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("removes nested html tags", () => {
|
|
172
|
+
const html = "<div><html><span>Content</span></html></div>";
|
|
173
|
+
expect(renderHTML({ html })).toMatchInlineSnapshot(`
|
|
174
|
+
<div>
|
|
175
|
+
<React.Fragment>
|
|
176
|
+
<span>
|
|
177
|
+
Content
|
|
178
|
+
</span>
|
|
179
|
+
</React.Fragment>
|
|
180
|
+
</div>
|
|
181
|
+
`);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("remove nested body in html", () => {
|
|
185
|
+
const html = "<html><body><span>Content</span></body></html>";
|
|
186
|
+
expect(renderHTML({ html })).toMatchInlineSnapshot(`
|
|
187
|
+
<React.Fragment>
|
|
188
|
+
<React.Fragment>
|
|
189
|
+
<span>
|
|
190
|
+
Content
|
|
191
|
+
</span>
|
|
192
|
+
</React.Fragment>
|
|
193
|
+
</React.Fragment>
|
|
194
|
+
`);
|
|
195
|
+
});
|
|
124
196
|
});
|
|
125
197
|
|
|
126
198
|
describe("RenderHTML with < nad >", () => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
2
3
|
/* eslint-disable unicorn/prefer-spread */
|
|
3
4
|
/**
|
|
4
5
|
* WebComponent Factory for React Components
|
|
@@ -21,16 +22,21 @@ import React, {
|
|
|
21
22
|
import ReactDOM, { type Root } from "react-dom/client";
|
|
22
23
|
import useEvent from "react-use-event-hook";
|
|
23
24
|
import type { ZodSchema } from "zod";
|
|
25
|
+
import { notebookAtom } from "@/core/cells/cells.ts";
|
|
26
|
+
import { findCellId } from "@/core/cells/ids.ts";
|
|
27
|
+
import { isUninstantiated } from "@/core/cells/utils";
|
|
24
28
|
import { createInputEvent, MarimoValueUpdateEvent } from "@/core/dom/events";
|
|
25
29
|
import { getUIElementObjectId } from "@/core/dom/ui-element";
|
|
26
30
|
import { UIElementRegistry } from "@/core/dom/uiregistry";
|
|
27
31
|
import { FUNCTIONS_REGISTRY } from "@/core/functions/FunctionRegistry";
|
|
32
|
+
import { store } from "@/core/state/jotai";
|
|
28
33
|
import {
|
|
29
34
|
type HTMLElementNotDerivedFromRef,
|
|
30
35
|
useEventListener,
|
|
31
36
|
} from "@/hooks/useEventListener";
|
|
32
37
|
import { StyleNamespace } from "@/theme/namespace";
|
|
33
38
|
import { useTheme } from "@/theme/useTheme";
|
|
39
|
+
import { CellNotInitializedError } from "@/utils/errors.ts";
|
|
34
40
|
import { Functions } from "@/utils/functions";
|
|
35
41
|
import { shallowCompare } from "@/utils/shallow-compare";
|
|
36
42
|
import { defineCustomElement } from "../../core/dom/defineCustomElement";
|
|
@@ -78,6 +84,7 @@ interface PluginSlotProps<T> {
|
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
/* Handles synchronization of value on behalf of the component */
|
|
87
|
+
|
|
81
88
|
// eslint-disable-next-line react/function-component-definition
|
|
82
89
|
function PluginSlotInternal<T>(
|
|
83
90
|
{ hostElement, plugin, children, getInitialValue }: PluginSlotProps<T>,
|
|
@@ -172,6 +179,27 @@ function PluginSlotInternal<T>(
|
|
|
172
179
|
);
|
|
173
180
|
const objectId = getUIElementObjectId(hostElement);
|
|
174
181
|
invariant(objectId, "Object ID should exist");
|
|
182
|
+
|
|
183
|
+
const cellId = findCellId(hostElement);
|
|
184
|
+
invariant(cellId, "Cell ID should exist");
|
|
185
|
+
|
|
186
|
+
const notebookState = store.get(notebookAtom);
|
|
187
|
+
const cellRuntime = notebookState.cellRuntime[cellId];
|
|
188
|
+
const cellData = notebookState.cellData[cellId];
|
|
189
|
+
|
|
190
|
+
const cellNotInitialized = isUninstantiated({
|
|
191
|
+
executionTime:
|
|
192
|
+
cellRuntime.runElapsedTimeMs ?? cellData.lastExecutionTime,
|
|
193
|
+
status: cellRuntime.status,
|
|
194
|
+
errored: cellRuntime.errored,
|
|
195
|
+
interrupted: cellRuntime.interrupted,
|
|
196
|
+
stopped: cellRuntime.stopped,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (cellNotInitialized) {
|
|
200
|
+
throw new CellNotInitializedError();
|
|
201
|
+
}
|
|
202
|
+
|
|
175
203
|
const response = await FUNCTIONS_REGISTRY.request({
|
|
176
204
|
args: prettyParse(input, args[0]),
|
|
177
205
|
functionName: key,
|
|
@@ -12,7 +12,7 @@ import { Button } from "@/components/ui/button";
|
|
|
12
12
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
13
13
|
import { Label } from "@/components/ui/label";
|
|
14
14
|
import { NativeSelect } from "@/components/ui/native-select";
|
|
15
|
-
import { Table, TableCell, TableRow } from "@/components/ui/table";
|
|
15
|
+
import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table";
|
|
16
16
|
import { toast } from "@/components/ui/use-toast";
|
|
17
17
|
import { useAsyncData } from "@/hooks/useAsyncData";
|
|
18
18
|
import { useInternalStateWithSync } from "@/hooks/useInternalStateWithSync";
|
|
@@ -158,6 +158,10 @@ export const FileBrowser = ({
|
|
|
158
158
|
return null;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
if (!data && error) {
|
|
162
|
+
return <Banner kind="danger">{error.message}</Banner>;
|
|
163
|
+
}
|
|
164
|
+
|
|
161
165
|
let { files } = data || {};
|
|
162
166
|
if (files === undefined) {
|
|
163
167
|
files = [];
|
|
@@ -458,7 +462,9 @@ export const FileBrowser = ({
|
|
|
458
462
|
className="mt-3 overflow-y-auto w-full border"
|
|
459
463
|
style={{ height: "14rem" }}
|
|
460
464
|
>
|
|
461
|
-
<Table className="cursor-pointer table-fixed">
|
|
465
|
+
<Table className="cursor-pointer table-fixed">
|
|
466
|
+
<TableBody>{fileRows}</TableBody>
|
|
467
|
+
</Table>
|
|
462
468
|
</div>
|
|
463
469
|
<div className="mt-4">
|
|
464
470
|
{value.length > 0 && (
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { defaultUserConfig } from "@/core/config/config-schema";
|
|
12
12
|
import { connectionAtom } from "@/core/network/connection";
|
|
13
13
|
import { requestClientAtom } from "@/core/network/requests";
|
|
14
|
-
import { resolveRequestClient } from "@/core/network/resolve
|
|
14
|
+
import { resolveRequestClient } from "@/core/network/resolve";
|
|
15
15
|
import type { CellConfig } from "@/core/network/types";
|
|
16
16
|
import { WebSocketState } from "@/core/websocket/types";
|
|
17
17
|
import { MultiColumn } from "@/utils/id-tree";
|
|
@@ -9,7 +9,7 @@ import { defaultUserConfig, parseAppConfig } from "@/core/config/config-schema";
|
|
|
9
9
|
import { showCodeInRunModeAtom } from "@/core/meta/state";
|
|
10
10
|
import { connectionAtom } from "@/core/network/connection";
|
|
11
11
|
import { requestClientAtom } from "@/core/network/requests";
|
|
12
|
-
import { resolveRequestClient } from "@/core/network/resolve
|
|
12
|
+
import { resolveRequestClient } from "@/core/network/resolve";
|
|
13
13
|
import { WebSocketState } from "@/core/websocket/types";
|
|
14
14
|
import { MultiColumn } from "@/utils/id-tree";
|
|
15
15
|
import type { Milliseconds, Seconds } from "@/utils/time";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
3
|
+
import { EDGE_CASE_CELL_NAMES } from "../../__tests__/mocks";
|
|
3
4
|
import {
|
|
4
5
|
canLinkToCell,
|
|
5
6
|
createCellLink,
|
|
@@ -89,4 +90,32 @@ describe("cell-urls utilities", () => {
|
|
|
89
90
|
expect(canLinkToCell("_")).toBe(false);
|
|
90
91
|
});
|
|
91
92
|
});
|
|
93
|
+
|
|
94
|
+
describe("edge case cell names with unicode and special characters", () => {
|
|
95
|
+
it.each(EDGE_CASE_CELL_NAMES)(
|
|
96
|
+
"should handle unicode cell names in createCellLink: %s",
|
|
97
|
+
(cellName) => {
|
|
98
|
+
const url = createCellLink(cellName);
|
|
99
|
+
expect(url).toContain("scrollTo=");
|
|
100
|
+
expect(url).toContain(encodeURIComponent(cellName));
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
it.each(EDGE_CASE_CELL_NAMES)(
|
|
105
|
+
"should round-trip unicode cell names correctly: %s",
|
|
106
|
+
(cellName) => {
|
|
107
|
+
const url = createCellLink(cellName);
|
|
108
|
+
const hash = url.split("#")[1];
|
|
109
|
+
const extracted = extractCellNameFromHash(`#${hash}`);
|
|
110
|
+
expect(extracted).toBe(cellName);
|
|
111
|
+
},
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
it.each(EDGE_CASE_CELL_NAMES)(
|
|
115
|
+
"should allow linking to unicode cell names: %s",
|
|
116
|
+
(cellName) => {
|
|
117
|
+
expect(canLinkToCell(cellName)).toBe(true);
|
|
118
|
+
},
|
|
119
|
+
);
|
|
120
|
+
});
|
|
92
121
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { EDGE_CASE_FILENAMES } from "../../__tests__/mocks";
|
|
4
5
|
import { Filenames } from "../filenames";
|
|
5
6
|
|
|
6
7
|
describe("Filenames", () => {
|
|
@@ -27,4 +28,21 @@ describe("Filenames", () => {
|
|
|
27
28
|
expect(Filenames.withoutExtension("test.txt")).toEqual("test");
|
|
28
29
|
expect(Filenames.withoutExtension("test.foo.txt")).toEqual("test.foo");
|
|
29
30
|
});
|
|
31
|
+
|
|
32
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
33
|
+
"should handle edge case filenames: %s",
|
|
34
|
+
(filename) => {
|
|
35
|
+
// Test all filename operations with edge cases
|
|
36
|
+
const withoutExt = Filenames.withoutExtension(filename);
|
|
37
|
+
|
|
38
|
+
expect(Filenames.toMarkdown(filename)).toEqual(`${withoutExt}.md`);
|
|
39
|
+
expect(Filenames.toHTML(filename)).toEqual(`${withoutExt}.html`);
|
|
40
|
+
expect(Filenames.toPNG(filename)).toEqual(`${withoutExt}.png`);
|
|
41
|
+
expect(Filenames.toPY(filename)).toEqual(`${withoutExt}.py`);
|
|
42
|
+
|
|
43
|
+
// Ensure operations preserve unicode and special characters in base name
|
|
44
|
+
expect(withoutExt).not.toEqual("");
|
|
45
|
+
expect(typeof withoutExt).toBe("string");
|
|
46
|
+
},
|
|
47
|
+
);
|
|
30
48
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { EDGE_CASE_FILENAMES } from "../../__tests__/mocks";
|
|
3
4
|
import { type FilePath, PathBuilder, Paths } from "../paths";
|
|
4
5
|
|
|
5
6
|
describe("Paths", () => {
|
|
@@ -167,4 +168,41 @@ describe("PathBuilder", () => {
|
|
|
167
168
|
expect(Paths.extension("file.tar.gz")).toBe("gz");
|
|
168
169
|
});
|
|
169
170
|
});
|
|
171
|
+
|
|
172
|
+
describe("edge case filenames", () => {
|
|
173
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
174
|
+
"should handle unicode and spaces in basename: %s",
|
|
175
|
+
(filename) => {
|
|
176
|
+
const basename = Paths.basename(filename);
|
|
177
|
+
expect(basename).toBe(filename);
|
|
178
|
+
expect(typeof basename).toBe("string");
|
|
179
|
+
expect(basename).not.toBe("");
|
|
180
|
+
},
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
184
|
+
"should handle unicode and spaces in dirname: %s",
|
|
185
|
+
(filename) => {
|
|
186
|
+
const fullPath = `/path/to/${filename}`;
|
|
187
|
+
const dirname = Paths.dirname(fullPath);
|
|
188
|
+
expect(dirname).toBe("/path/to");
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
193
|
+
"should handle unicode and spaces in path operations: %s",
|
|
194
|
+
(filename) => {
|
|
195
|
+
const baseName = Paths.basename(filename);
|
|
196
|
+
const extension = Paths.extension(filename);
|
|
197
|
+
|
|
198
|
+
// Should preserve unicode characters in basename
|
|
199
|
+
expect(baseName).toContain(filename.split(".")[0]);
|
|
200
|
+
|
|
201
|
+
// Should correctly extract extension
|
|
202
|
+
if (filename.includes(".")) {
|
|
203
|
+
expect(extension).toBe(filename.split(".").pop());
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
);
|
|
207
|
+
});
|
|
170
208
|
});
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
EDGE_CASE_FILENAMES,
|
|
5
|
+
URL_SPECIAL_CHAR_FILENAMES,
|
|
6
|
+
} from "../../__tests__/mocks";
|
|
7
|
+
import { isUrl, updateQueryParams } from "../urls";
|
|
4
8
|
|
|
5
9
|
describe("isUrl", () => {
|
|
6
10
|
it("should return true for a valid URL", () => {
|
|
@@ -8,3 +12,54 @@ describe("isUrl", () => {
|
|
|
8
12
|
expect(isUrl("curl -X GET http://example.com")).toBe(false);
|
|
9
13
|
});
|
|
10
14
|
});
|
|
15
|
+
|
|
16
|
+
describe("URL parameter handling with edge case filenames", () => {
|
|
17
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
18
|
+
"should handle unicode filenames in URL parameters: %s",
|
|
19
|
+
(filename) => {
|
|
20
|
+
// Test that updateQueryParams can handle unicode filenames
|
|
21
|
+
updateQueryParams((params) => {
|
|
22
|
+
params.set("file", filename);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Verify URL encoding/decoding works with unicode
|
|
26
|
+
const encoded = encodeURIComponent(filename);
|
|
27
|
+
const decoded = decodeURIComponent(encoded);
|
|
28
|
+
expect(decoded).toBe(filename);
|
|
29
|
+
|
|
30
|
+
// Verify filename can be safely added to URL parameters
|
|
31
|
+
const url = new URL("https://example.com");
|
|
32
|
+
url.searchParams.set("file", filename);
|
|
33
|
+
expect(url.searchParams.get("file")).toBe(filename);
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
it("should preserve unicode in query string round-trip", () => {
|
|
38
|
+
EDGE_CASE_FILENAMES.forEach((filename) => {
|
|
39
|
+
const url = new URL("https://example.com");
|
|
40
|
+
url.searchParams.set("filename", filename);
|
|
41
|
+
|
|
42
|
+
// Convert to string and back
|
|
43
|
+
const urlString = url.toString();
|
|
44
|
+
const reconstructed = new URL(urlString);
|
|
45
|
+
const retrievedFilename = reconstructed.searchParams.get("filename");
|
|
46
|
+
|
|
47
|
+
expect(retrievedFilename).toBe(filename);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should handle special characters in updateQueryParams", () => {
|
|
52
|
+
URL_SPECIAL_CHAR_FILENAMES.forEach((filename) => {
|
|
53
|
+
let res: string | null = null;
|
|
54
|
+
expect(() => {
|
|
55
|
+
updateQueryParams((params) => {
|
|
56
|
+
// To and from conversion
|
|
57
|
+
params.set("file", filename);
|
|
58
|
+
res = params.get("file");
|
|
59
|
+
});
|
|
60
|
+
}).not.toThrow();
|
|
61
|
+
expect(res).not.toBeNull();
|
|
62
|
+
expect(res).toBe(filename);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
package/src/utils/errors.ts
CHANGED
|
@@ -61,3 +61,12 @@ function safeJSONParse(message: string): unknown {
|
|
|
61
61
|
return message;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
export class CellNotInitializedError extends Error {
|
|
66
|
+
constructor(
|
|
67
|
+
message: string = "The cell containing this UI element has not been run yet. Please run the cell first.",
|
|
68
|
+
) {
|
|
69
|
+
super(message);
|
|
70
|
+
this.name = "CellNotInitializedError";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{ev as m,ew as l,ex as w,aC as b,ey as g,ez as h,eA as A,eB as C,ct as z,eC as B,cu as D,aY as Y,eD as k,A as q}from"./index-OC46250R.js";function j(r){return r==r&&!w(r)}function p(r,e){return function(n){return n!=null&&n[r]===e&&(e!==void 0||r in Object(n))}}function E(r){var e=(function(n){for(var t=b(n),u=t.length;u--;){var f=t[u],o=n[f];t[u]=[f,o,j(o)]}return t})(r);return e.length==1&&e[0][2]?p(e[0][0],e[0][1]):function(n){return n===r||(function(t,u,f,o){var i=f.length,c=i;if(t==null)return!c;for(t=Object(t);i--;){var a=f[i];if(a[2]?a[1]!==t[a[0]]:!(a[0]in t))return!1}for(;++i<c;){var s=(a=f[i])[0],v=t[s],O=a[1];if(a[2]){if(v===void 0&&!(s in t))return!1}else{var x=new m;if(!l(O,v,3,o,x))return!1}}return!0})(n,0,e)}}function F(r){return g(r)?B(h(r)):(function(e){return function(n){return z(n,e)}})(r)}function G(r){return typeof r=="function"?r:r==null?D:typeof r=="object"?Y(r)?(e=r[0],n=r[1],g(e)&&j(n)?p(h(e),n):function(t){var u=A(t,e);return u===void 0&&u===n?C(t,e):l(n,u,3)}):E(r):F(r);var e,n}function d(r,e){return r&&k(r,e,b)}var y,H=(y=d,function(r,e){if(r==null)return r;if(!q(r))return y(r,e);for(var n=r.length,t=-1,u=Object(r);++t<n&&e(u[t],t,u)!==!1;);return r});export{G as a,H as b,d as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as m}from"./_baseEach-C1FLm7WW.js";import{A as s}from"./index-OC46250R.js";function e(r,o){var a=-1,t=s(r)?Array(r.length):[];return m(r,function(n,f,i){t[++a]=o(n,f,i)}),t}export{e as b};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{fb as p,aC as d,er as m,fc as F,fd as X,fe as Z,ff as _,fg as rr,fh as M,fi as B,fj as er,fk as D,fl as x,cv as k,fm as A,ex as nr,fn as tr,fo as cr,fp as or,fq as ar,ev as ur,fr,aY as g,fs as sr,cu as ir,ft as br,cs as jr,fu as lr,fv as S,fw as C,fx as vr,fy as yr}from"./index-OC46250R.js";import{b as U,a as I}from"./_baseEach-C1FLm7WW.js";function N(){}function P(r,e){for(var n=-1,u=r==null?0:r.length;++n<u&&e(r[n],n,r)!==!1;);return r}function R(r,e,n,u){for(var s=r.length,a=n+-1;++a<s;)if(e(r[a],a,r))return a;return-1}function pr(r){return r!=r}function V(r,e,n){return e==e?(function(u,s,a){for(var c=a-1,f=u.length;++c<f;)if(u[c]===s)return c;return-1})(r,e,n):R(r,pr,n)}function q(r,e){return!!(r!=null&&r.length)&&V(r,e,0)>-1}var G=Object.getOwnPropertySymbols?function(r){for(var e=[];r;)Z(e,F(r)),r=_(r);return e}:X;function L(r){return rr(r,m,G)}var Ar=Object.prototype.hasOwnProperty,gr=/\w*$/,W=B?B.prototype:void 0,Y=W?W.valueOf:void 0;function hr(r,e,n){var u,s,a,c=r.constructor;switch(e){case"[object ArrayBuffer]":return M(r);case"[object Boolean]":case"[object Date]":return new c(+r);case"[object DataView]":return(function(f,b){var v=b?M(f.buffer):f.buffer;return new f.constructor(v,f.byteOffset,f.byteLength)})(r,n);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]":return er(r,n);case"[object Map]":case"[object Set]":return new c;case"[object Number]":case"[object String]":return new c(r);case"[object RegExp]":return(a=new(s=r).constructor(s.source,gr.exec(s))).lastIndex=s.lastIndex,a;case"[object Symbol]":return u=r,Y?Object(Y.call(u)):{}}}var $=A&&A.isMap,wr=$?k($):function(r){return D(r)&&x(r)=="[object Map]"},z=A&&A.isSet,dr=z?k(z):function(r){return D(r)&&x(r)=="[object Set]"},H="[object Arguments]",J="[object Function]",K="[object Object]",o={};function h(r,e,n,u,s,a){var c,f=1&e,b=2&e,v=4&e;if(c!==void 0)return c;if(!nr(r))return r;var l=g(r);if(l){if(c=(function(t){var i=t.length,w=new t.constructor(i);return i&&typeof t[0]=="string"&&Ar.call(t,"index")&&(w.index=t.index,w.input=t.input),w})(r),!f)return tr(r,c)}else{var j=x(r),y=j==J||j=="[object GeneratorFunction]";if(cr(r))return or(r,f);if(j==K||j==H||y&&!s){if(c=b||y?{}:ar(r),!f)return b?(function(t,i){return p(t,G(t),i)})(r,(function(t,i){return t&&p(i,m(i),t)})(c,r)):(function(t,i){return p(t,F(t),i)})(r,(function(t,i){return t&&p(i,d(i),t)})(c,r))}else{if(!o[j])return s?r:{};c=hr(r,j,f)}}a||(a=new ur);var O=a.get(r);if(O)return O;a.set(r,c),dr(r)?r.forEach(function(t){c.add(h(t,e,n,t,r,a))}):wr(r)&&r.forEach(function(t,i){c.set(i,h(t,e,n,i,r,a))});var E=l?void 0:(v?b?L:fr:b?m:d)(r);return P(E||r,function(t,i){E&&(t=r[i=t]),sr(c,i,h(t,e,n,i,r,a))}),c}function Q(r){return typeof r=="function"?r:ir}function mr(r,e){return(g(r)?P:U)(r,Q(e))}function T(r,e){var n=[];return U(r,function(u,s,a){e(u,s,a)&&n.push(u)}),n}function xr(r,e){return(g(r)?br:T)(r,I(e))}function Sr(r){return r==null?[]:(function(e,n){return jr(n,function(u){return e[u]})})(r,d(r))}function Ur(r){return r===void 0}function Or(r,e,n,u,s){return s(r,function(a,c,f){n=u?(u=!1,a):e(n,a,c,f)}),n}function Er(r,e,n){var u=g(r)?lr:Or,s=arguments.length<3;return u(r,I(e),n,s,U)}o[H]=o["[object Array]"]=o["[object ArrayBuffer]"]=o["[object DataView]"]=o["[object Boolean]"]=o["[object Date]"]=o["[object Float32Array]"]=o["[object Float64Array]"]=o["[object Int8Array]"]=o["[object Int16Array]"]=o["[object Int32Array]"]=o["[object Map]"]=o["[object Number]"]=o[K]=o["[object RegExp]"]=o["[object Set]"]=o["[object String]"]=o["[object Symbol]"]=o["[object Uint8Array]"]=o["[object Uint8ClampedArray]"]=o["[object Uint16Array]"]=o["[object Uint32Array]"]=!0,o["[object Error]"]=o[J]=o["[object WeakMap]"]=!1;var Fr=S&&1/C(new S([,-0]))[1]==1/0?function(r){return new S(r)}:N;function Mr(r,e,n){var u=-1,s=q,a=r.length,c=!0,f=[],b=f;if(a>=200){var v=e?null:Fr(r);if(v)return C(v);c=!1,s=yr,b=new vr}else b=e?[]:f;r:for(;++u<a;){var l=r[u],j=e?e(l):l;if(l=l!==0?l:0,c&&j==j){for(var y=b.length;y--;)if(b[y]===j)continue r;e&&b.push(j),f.push(l)}else s(b,j,n)||(b!==f&&b.push(j),f.push(l))}return f}export{Mr as a,h as b,mr as c,R as d,Q as e,xr as f,q as g,V as h,Ur as i,L as j,T as k,N as n,Er as r,Sr as v};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as c,a as e}from"./_baseEach-C1FLm7WW.js";import{aY as f}from"./index-OC46250R.js";function m(r,o,u,t){for(var n=-1,a=r==null?0:r.length;++n<a;){var i=r[n];o(t,i,u(i),r)}return t}function s(r,o,u,t){return c(r,function(n,a,i){o(t,n,u(n),i)}),t}function l(r,o){return function(u,t){var n=f(u)?m:s,a=o?o():{};return n(u,r,e(t),a)}}export{l as c};
|