@marimo-team/frontend 0.16.1 → 0.16.3
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-2wVcyvDj.js → ConnectedDataExplorerComponent-Brtw1DxF.js} +1 -1
- package/dist/assets/{ImageComparisonComponent-D2j6i0hv.js → ImageComparisonComponent-Dxl-PbZX.js} +1 -1
- package/dist/assets/{VegaLite-BckFaf2D.js → VegaLite-BXQF0Cx_.js} +1 -1
- package/dist/assets/_baseEach-BjSm9ht3.js +1 -0
- package/dist/assets/_baseMap-CV4Ezmtf.js +1 -0
- package/dist/assets/_baseUniq-Ci9yZGxz.js +1 -0
- package/dist/assets/{_createAggregator-C5CVY-0t.js → _createAggregator-VFK9K2d9.js} +1 -1
- package/dist/assets/{agent-panel-RGLNjkYe.js → agent-panel-BoscVLCT.js} +7 -7
- package/dist/assets/{any-language-editor-DjuXwGCA.js → any-language-editor-ChaY_VUU.js} +1 -1
- package/dist/assets/{architectureDiagram-W76B3OCA-Dyj4ds_R.js → architectureDiagram-W76B3OCA-CueUUFYd.js} +1 -1
- package/dist/assets/{between-horizontal-start-Dt2aKpPf.js → between-horizontal-start-DAHqmLYT.js} +1 -1
- package/dist/assets/{blockDiagram-QIGZ2CNN-o-i7DDvN.js → blockDiagram-QIGZ2CNN-BYYygyWn.js} +1 -1
- package/dist/assets/{c4Diagram-FPNF74CW-DGHEwWrx.js → c4Diagram-FPNF74CW-DAz3xEh1.js} +1 -1
- package/dist/assets/channel-6SqQ2U_X.js +1 -0
- package/dist/assets/chat-panel-DJkOLrw9.js +3 -0
- package/dist/assets/{chunk-4BX2VUAB-BJecb-Ri.js → chunk-4BX2VUAB-8g-RyHdt.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-CAATkc4w.js → chunk-55IACEB6-iWZZ8Mt6.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DPuNbQ-f.js → chunk-FMBD7UC4-knjss4wk.js} +1 -1
- package/dist/assets/{chunk-K7UQS3LO-C8TWVLiH.js → chunk-K7UQS3LO-DVIwPBgZ.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-DiZZ09q4.js → chunk-QN33PNHL-CBU8pN6I.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BIUM7usu.js → chunk-QZHKN3VN-5ljElUF4.js} +1 -1
- package/dist/assets/{chunk-TVAH2DTR-vGTArPBG.js → chunk-TVAH2DTR-DkIdGINc.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-D2KRqp_x.js → chunk-TZMSLE5B-CIFOSTqh.js} +1 -1
- package/dist/assets/{circle-play-cjeNez0N.js → circle-play-BOdsbq5u.js} +1 -1
- package/dist/assets/classDiagram-KNZD7YFC-DVqXcTYf.js +1 -0
- package/dist/assets/classDiagram-v2-RKCZMP56-DVqXcTYf.js +1 -0
- package/dist/assets/{clear-button-C97JtAez.js → clear-button-GAjXl0CQ.js} +1 -1
- package/dist/assets/clone-DSDb0xen.js +1 -0
- package/dist/assets/command-palette-BUXkqoLh.js +1 -0
- package/dist/assets/{common-Du9rSOwD.js → common-DahoYqdi.js} +1 -1
- package/dist/assets/{compile-CZXqyOxa.js → compile-Bg8uJ7vm.js} +1 -1
- package/dist/assets/{cose-bilkent-S5V4N54A-CqUN5Y9b.js → cose-bilkent-S5V4N54A-z_0gqD9K.js} +1 -1
- package/dist/assets/{dagre-5GWH7T2D-RJqTI9DM.js → dagre-5GWH7T2D-BMt7CNXL.js} +1 -1
- package/dist/assets/{data-grid-overlay-editor-DZN0q1LV.js → data-grid-overlay-editor-Ctn4XtXx.js} +1 -1
- package/dist/assets/datasources-panel-C7sqRIHs.js +1 -0
- package/dist/assets/{dependency-graph-panel-CEog_O7V.js → dependency-graph-panel-DNajptzv.js} +4 -4
- package/dist/assets/{diagram-N5W7TBWH-D-l4zZ9d.js → diagram-N5W7TBWH-BzwvLvAy.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-CCOmBUt-.js → diagram-QEK2KX5R-DRLJ56FS.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-C_I_9jnZ.js → diagram-S2PKOQOG-Bf8x4KTU.js} +1 -1
- package/dist/assets/{documentation-panel-C1BtMZ3M.js → documentation-panel-Dm6Ozl67.js} +1 -1
- package/dist/assets/{edit-page-B-oevUZ9.js → edit-page-CGc9EjuG.js} +53 -42
- package/dist/assets/{ellipsis-vertical-BEb-J8z6.js → ellipsis-vertical-Bj1YXvZe.js} +1 -1
- package/dist/assets/{empty-state-C99UyDE3.js → empty-state-CYev-D31.js} +1 -1
- package/dist/assets/{erDiagram-AWTI2OKA-BePOLi5M.js → erDiagram-AWTI2OKA-DmgzgN_I.js} +1 -1
- package/dist/assets/{error-panel-Bs34jXFh.js → error-panel-BYG4twCa.js} +1 -1
- package/dist/assets/{file-explorer-panel-Ck6UL861.js → file-explorer-panel-BSMiOApi.js} +1 -1
- package/dist/assets/{flowDiagram-PVAE7QVJ-BgjFu5l7.js → flowDiagram-PVAE7QVJ-BdRKkajr.js} +1 -1
- package/dist/assets/{ganttDiagram-OWAHRB6G-YOPb3XSV.js → ganttDiagram-OWAHRB6G-lfRAMnq_.js} +5 -5
- package/dist/assets/{gitGraphDiagram-NY62KEGX-CGhqaDTy.js → gitGraphDiagram-NY62KEGX-CQVTIrHF.js} +1 -1
- package/dist/assets/{glide-data-editor-9QUH6iso.js → glide-data-editor-D5A4pou7.js} +4 -4
- package/dist/assets/{graph-DQQFGrho.js → graph-CBNo279v.js} +1 -1
- package/dist/assets/{home-page-DRKpPCrF.js → home-page-CmdznBJR.js} +2 -2
- package/dist/assets/{index-SGLNXrGP.js → index-0dfGh-Gj.js} +1 -1
- package/dist/assets/{index-aE43R74q.js → index-BDYVSSzB.js} +1 -1
- package/dist/assets/{index-BJNCMUmG.js → index-B_KyDZ94.js} +1 -1
- package/dist/assets/{index-BjgnbONl.js → index-Bfy-I_lW.js} +1 -1
- package/dist/assets/{index-CUFv_thQ.js → index-Bh98Tp-z.js} +1 -1
- package/dist/assets/{index-C2MD0vgD.js → index-BhroIwBL.js} +1 -1
- package/dist/assets/{index-DdnKZNxM.js → index-BtQtesaI.js} +1 -1
- package/dist/assets/index-C0iXCvyY.css +1 -0
- package/dist/assets/index-C1SHFMCp.js +581 -0
- package/dist/assets/{index-C_tkBKNO.js → index-C6DWtSls.js} +1 -1
- package/dist/assets/{index-Aeo6WiK7.js → index-C71cdkH-.js} +1 -1
- package/dist/assets/{index-G5QZppK2.js → index-CT_FTqvK.js} +1 -1
- package/dist/assets/{index-B8jXZ12t.js → index-CU5rRr66.js} +1 -1
- package/dist/assets/{index-BAbIIxHU.js → index-Cb6duXQm.js} +1 -1
- package/dist/assets/{index-BW3k9Gss.js → index-D23e9zQj.js} +1 -1
- package/dist/assets/index-DUGecC2Z.js +68 -0
- package/dist/assets/{index-CFKO7WXI.js → index-DcGIOAQi.js} +1 -1
- package/dist/assets/{index-ClzeQrN7.js → index-PJfa9qXY.js} +1 -1
- package/dist/assets/{index-C1ez98sk.js → index-SPslPC2B.js} +1 -1
- package/dist/assets/{index-BprjMYH5.js → index-VPQlo4Uz.js} +1 -1
- package/dist/assets/{index-CfaDbEdi.js → index-qbTLKWyG.js} +1 -1
- package/dist/assets/infoDiagram-STP46IZ2-DBu8p9gd.js +2 -0
- package/dist/assets/{isEmpty-D-4c7sMv.js → isEmpty-CnOLuQIv.js} +1 -1
- package/dist/assets/{journeyDiagram-BIP6EPQ6-C94u3Mv3.js → journeyDiagram-BIP6EPQ6-6U_vHJBH.js} +1 -1
- package/dist/assets/{kanban-definition-6OIFK2YF-BEXYFzz7.js → kanban-definition-6OIFK2YF-DgnR14ys.js} +1 -1
- package/dist/assets/{layout-Bz2BJ2ru.js → layout-RHmq4fP9.js} +1 -1
- package/dist/assets/{linear-D8s7K76e.js → linear-CLdOVPGV.js} +1 -1
- package/dist/assets/links-Dd1icsEk.js +7 -0
- package/dist/assets/{logs-panel-DC7wpmPz.js → logs-panel-CjbuhBLx.js} +1 -1
- package/dist/assets/{markdown-renderer-DRdSWR9X.js → markdown-renderer-X5YJvAZq.js} +3 -3
- package/dist/assets/{mermaid-Y3x4hmD0.js → mermaid-Bl2T5oEC.js} +1 -1
- package/dist/assets/{mermaid.core-DzthE35Y.js → mermaid.core-CfukBvGI.js} +4 -4
- package/dist/assets/min-BXIes1Za.js +1 -0
- package/dist/assets/{mindmap-definition-Q6HEUPPD-DktvuLe1.js → mindmap-definition-Q6HEUPPD-BXCjP4Lu.js} +1 -1
- package/dist/assets/{number-overlay-editor-BEfwI1IT.js → number-overlay-editor-BUyqkSes.js} +1 -1
- package/dist/assets/{outline-panel-CdsnAy2w.js → outline-panel-BvGcPKdd.js} +1 -1
- package/dist/assets/{packages-panel-DiTA-d_D.js → packages-panel-BichDQWG.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-DQDNQ-de.js → pieDiagram-ADFJNKIX-CMzJFIJM.js} +1 -1
- package/dist/assets/{quadrantDiagram-LMRXKWRM-0kgIXc2-.js → quadrantDiagram-LMRXKWRM-CfGssUlO.js} +1 -1
- package/dist/assets/{react-plotly-DJqqfM7c.js → react-plotly-DR3hV0HW.js} +1 -1
- package/dist/assets/{requirementDiagram-4UW4RH46-B5rb0ypd.js → requirementDiagram-4UW4RH46-CfrFolth.js} +1 -1
- package/dist/assets/{run-page-CFmLrv1R.js → run-page-Bqd_4ePD.js} +1 -1
- package/dist/assets/{sankeyDiagram-GR3RE2ED-Dom7IlnF.js → sankeyDiagram-GR3RE2ED-D_UttKU0.js} +1 -1
- package/dist/assets/{scratchpad-panel-CuHWpHO8.js → scratchpad-panel-D5N15ji1.js} +1 -1
- package/dist/assets/secrets-panel-BpbnAO4R.js +1 -0
- package/dist/assets/{sequenceDiagram-C3RYC4MD-PNJWXQbw.js → sequenceDiagram-C3RYC4MD-MdfQQApP.js} +1 -1
- package/dist/assets/{slides-component-CJgaTRZ0.js → slides-component-C0z7rXmk.js} +1 -1
- package/dist/assets/{snippets-panel-B2EC1txM.js → snippets-panel-wlpZ_Wzx.js} +1 -1
- package/dist/assets/sortBy-BW_zNHP6.js +1 -0
- package/dist/assets/{state-CWict9RU.js → state-CDooX-dk.js} +1 -1
- package/dist/assets/{stateDiagram-KXAO66HF-BE58aJnr.js → stateDiagram-KXAO66HF-H7kfw3ot.js} +1 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-YMeb9qMR.js +1 -0
- package/dist/assets/{storage-DRaR04wR.js → storage-b1QCapTq.js} +6 -6
- package/dist/assets/{terminal-BX3Su5q7.js → terminal-CPV44BXz.js} +1 -1
- package/dist/assets/{time-hUzZfpNE.js → time-DDy3xv5Y.js} +1 -1
- package/dist/assets/{timeline-definition-XQNQX7LJ-CqQP9t51.js → timeline-definition-XQNQX7LJ-J-cPRT2_.js} +1 -1
- package/dist/assets/{tracing-B10Q1n-L.js → tracing-3eHHRUiJ.js} +2 -2
- package/dist/assets/{tracing-panel-Du8WCnno.js → tracing-panel-BMgy3D7d.js} +2 -2
- package/dist/assets/{trash-B81GTiv6.js → trash--tonOuDe.js} +1 -1
- package/dist/assets/{tree-6vW2ogkh.js → tree-ouIGEsVg.js} +1 -1
- package/dist/assets/{treemap-75Q7IDZK-CdwDwwsz.js → treemap-75Q7IDZK-CzJTJ_3R.js} +20 -20
- package/dist/assets/{variable-panel-D5qgJI7k.js → variable-panel-sFTn4Oih.js} +1 -1
- package/dist/assets/{vega-component-DJaJWMJM.js → vega-component-BkPkzX9r.js} +1 -1
- package/dist/assets/{xychartDiagram-6GGTOJPD-WFtXqaM9.js → xychartDiagram-6GGTOJPD-BZ8WOb_8.js} +1 -1
- package/dist/index.html +10 -3
- package/package.json +8 -8
- package/src/__mocks__/common.ts +5 -3
- package/src/__mocks__/notebook.ts +2 -2
- package/src/__mocks__/requests.ts +1 -0
- package/src/__tests__/main.test.tsx +2 -2
- package/src/components/ai/ai-provider-icon.tsx +2 -0
- package/src/components/app-config/ai-config.tsx +32 -1
- package/src/components/app-config/common.tsx +2 -2
- package/src/components/app-config/user-config-form.tsx +26 -0
- package/src/components/audio/audio-recorder.tsx +0 -1
- package/src/components/chat/acp/blocks.tsx +2 -2
- package/src/components/chat/acp/thread.tsx +3 -5
- package/src/components/chat/acp/utils.ts +5 -5
- package/src/components/chat/chat-panel.tsx +1 -1
- package/src/components/data-table/__tests__/columns.test.tsx +38 -0
- package/src/components/data-table/__tests__/data-table.test.tsx +2 -2
- package/src/components/data-table/cell-hover-template/feature.ts +1 -1
- package/src/components/data-table/cell-hover-template/types.ts +1 -1
- package/src/components/data-table/charts/__tests__/altair-generator.test.ts +1 -1
- package/src/components/data-table/charts/chart-spec/tooltips.ts +3 -3
- package/src/components/data-table/charts/components/chart-items.tsx +1 -1
- package/src/components/data-table/charts/components/form-fields.tsx +2 -2
- package/src/components/data-table/charts/constants.ts +1 -1
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +2 -2
- package/src/components/data-table/columns.tsx +22 -3
- package/src/components/data-table/data-table.tsx +35 -3
- package/src/components/data-table/date-popover.tsx +1 -1
- package/src/components/data-table/download-actions.tsx +1 -1
- package/src/components/data-table/range-focus/__tests__/utils.test.ts +5 -5
- package/src/components/data-table/renderers.tsx +22 -13
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +1 -1
- package/src/components/data-table/schemas.ts +16 -0
- package/src/components/data-table/types.ts +4 -3
- package/src/components/datasources/column-preview.tsx +9 -6
- package/src/components/debugger/debugger-code.tsx +1 -1
- package/src/components/dependency-graph/custom-node.tsx +15 -6
- package/src/components/dependency-graph/dependency-graph-minimap.tsx +2 -2
- package/src/components/dependency-graph/dependency-graph-tree.tsx +2 -2
- package/src/components/dependency-graph/dependency-graph.tsx +1 -1
- package/src/components/dependency-graph/elements.ts +7 -7
- package/src/components/dependency-graph/utils/changes.ts +4 -4
- package/src/components/editor/Cell.tsx +7 -1
- package/src/components/editor/ai/transport/chat-transport.tsx +1 -1
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +1 -1
- package/src/components/editor/chrome/panels/packages-panel.tsx +1 -1
- package/src/components/editor/columns/storage.ts +1 -1
- package/src/components/editor/database/__tests__/__snapshots__/as-code.test.ts.snap +36 -0
- package/src/components/editor/database/__tests__/as-code.test.ts +30 -7
- package/src/components/editor/database/add-database-form.tsx +11 -0
- package/src/components/editor/database/as-code.ts +104 -5
- package/src/components/editor/database/schemas.ts +36 -18
- package/src/components/editor/errors/auto-fix.tsx +12 -2
- package/src/components/editor/errors/sql-validation-errors.tsx +40 -0
- package/src/components/editor/navigation/clipboard.ts +2 -2
- package/src/components/editor/output/ConsoleOutput.tsx +14 -2
- package/src/components/editor/output/JsonOutput.tsx +1 -1
- package/src/components/editor/output/MarimoErrorOutput.tsx +60 -1
- package/src/components/editor/output/MarimoTracebackOutput.tsx +17 -2
- package/src/components/editor/renderers/grid-layout/types.ts +2 -2
- package/src/components/editor/renderers/plugins.ts +1 -1
- package/src/components/editor/renderers/types.ts +1 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +7 -7
- package/src/components/forms/form.tsx +5 -5
- package/src/components/ui/links.tsx +1 -0
- package/src/core/ai/__tests__/model-registry.test.ts +0 -10
- package/src/core/ai/context/providers/cell-output.ts +1 -18
- package/src/core/ai/context/providers/error.ts +2 -2
- package/src/core/ai/ids/ids.ts +1 -0
- package/src/core/ai/model-registry.ts +2 -1
- package/src/core/cells/cells.ts +5 -5
- package/src/core/cells/logs.ts +1 -1
- package/src/core/cells/types.ts +1 -1
- package/src/core/codemirror/__tests__/format.test.ts +6 -0
- package/src/core/codemirror/cells/traceback-decorations.ts +1 -1
- package/src/core/codemirror/editing/commands.ts +2 -2
- package/src/core/codemirror/find-replace/navigate.ts +1 -1
- package/src/core/codemirror/language/__tests__/extension.test.ts +24 -0
- package/src/core/codemirror/language/__tests__/sql-validation.test.ts +133 -0
- package/src/core/codemirror/language/__tests__/sql.test.ts +764 -79
- package/src/core/codemirror/language/languages/markdown.ts +4 -1
- package/src/core/codemirror/language/languages/sql/banner-validation-errors.ts +85 -0
- package/src/core/codemirror/language/languages/sql/completion-builder.ts +160 -0
- package/src/core/codemirror/language/languages/sql/completion-sources.tsx +9 -3
- package/src/core/codemirror/language/languages/sql/completion-store.ts +46 -50
- package/src/core/codemirror/language/languages/sql/renderers.tsx +485 -0
- package/src/core/codemirror/language/languages/sql/sql-mode.ts +20 -0
- package/src/core/codemirror/language/languages/sql/sql.ts +218 -4
- package/src/core/codemirror/language/languages/sql/utils.ts +4 -1
- package/src/core/codemirror/language/panel/panel.tsx +8 -2
- package/src/core/codemirror/language/panel/sql.tsx +86 -4
- package/src/core/codemirror/language/utils/ast.ts +3 -3
- package/src/core/codemirror/lsp/federated-lsp.ts +4 -4
- package/src/core/codemirror/lsp/lens.ts +4 -4
- package/src/core/codemirror/lsp/notebook-lsp.ts +1 -1
- package/src/core/codemirror/lsp/types.ts +1 -1
- package/src/core/codemirror/markdown/completions.ts +1 -1
- package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
- package/src/core/codemirror/rtc/loro/awareness.ts +1 -1
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/config/feature-flag.tsx +6 -2
- package/src/core/datasets/request-registry.ts +24 -1
- package/src/core/dom/events.ts +1 -1
- package/src/core/dom/outline.ts +2 -2
- package/src/core/dom/uiregistry.ts +2 -8
- package/src/core/errors/__tests__/errors.test.ts +22 -4
- package/src/core/errors/errors.ts +29 -1
- package/src/core/errors/state.ts +1 -1
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/islands/main.ts +3 -2
- package/src/core/islands/parse.ts +1 -3
- package/src/core/kernel/messages.ts +2 -1
- package/src/core/network/CachingRequestRegistry.ts +74 -0
- package/src/core/network/DeferredRequestRegistry.ts +3 -1
- package/src/core/network/__tests__/CachingRequestRegistry.test.ts +73 -0
- package/src/core/network/requests-network.ts +7 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.ts +1 -0
- package/src/core/network/types.ts +3 -1
- package/src/core/variables/state.ts +2 -2
- package/src/core/wasm/__tests__/state.test.ts +1 -1
- package/src/core/wasm/bridge.ts +5 -0
- package/src/core/websocket/useMarimoWebSocket.tsx +9 -2
- package/src/custom.d.ts +1 -1
- package/src/hooks/useCellRenderCount.ts +1 -0
- package/src/hooks/useResizeHandle.ts +4 -1
- package/src/plugins/core/RenderHTML.tsx +1 -2
- package/src/plugins/core/registerReactComponent.tsx +23 -19
- package/src/plugins/impl/DataTablePlugin.tsx +18 -6
- package/src/plugins/impl/FileUploadPlugin.tsx +1 -1
- package/src/plugins/impl/RefreshPlugin.tsx +1 -1
- package/src/plugins/impl/SliderPlugin.tsx +4 -0
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +27 -9
- package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +58 -2
- package/src/plugins/impl/anywidget/__tests__/model.test.ts +3 -4
- package/src/plugins/impl/anywidget/model.ts +2 -3
- package/src/plugins/impl/data-editor/types.ts +1 -1
- package/src/plugins/impl/data-explorer/components/query-form.tsx +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +17 -5
- package/src/plugins/impl/data-frames/types.ts +1 -1
- package/src/plugins/impl/panel/PanelPlugin.tsx +2 -2
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +3 -3
- package/src/plugins/impl/vega/__tests__/loader.test.ts +2 -2
- package/src/plugins/impl/vega/loader.ts +1 -1
- package/src/plugins/impl/vega/vega-component.tsx +1 -1
- package/src/plugins/impl/vega/vega-loader.ts +2 -2
- package/src/plugins/layout/NavigationMenuPlugin.tsx +1 -1
- package/src/plugins/layout/RoutesPlugin.tsx +1 -2
- package/src/plugins/plugins.ts +2 -2
- package/src/stories/dataframe.stories.tsx +2 -0
- package/src/utils/Logger.ts +1 -1
- package/src/utils/__tests__/data-views.test.ts +30 -68
- package/src/utils/__tests__/dom.test.ts +167 -0
- package/src/utils/__tests__/id-tree.test.ts +49 -1
- package/src/utils/__tests__/storage.test.ts +1 -1
- package/src/utils/__tests__/traceback.test.ts +13 -2
- package/src/utils/arrays.ts +1 -1
- package/src/utils/createReducer.ts +1 -5
- package/src/utils/data-views.ts +6 -19
- package/src/utils/dom.ts +55 -0
- package/src/utils/edit-distance.ts +1 -1
- package/src/utils/fileToBase64.ts +1 -1
- package/src/utils/id-tree.tsx +20 -18
- package/src/utils/json/base64.ts +13 -0
- package/src/utils/json/json-parser.ts +2 -2
- package/src/utils/lru.ts +4 -0
- package/src/utils/mergeRefs.ts +1 -1
- package/src/utils/objects.ts +3 -3
- package/src/utils/pluralize.ts +1 -1
- package/src/utils/routes.ts +2 -2
- package/src/utils/sets.ts +1 -1
- package/src/utils/traceback.ts +45 -15
- package/src/utils/tracer.ts +11 -9
- package/dist/assets/_baseEach-CvTX9w0Y.js +0 -1
- package/dist/assets/_baseMap-CtlwA90f.js +0 -1
- package/dist/assets/_baseUniq-BKktIGQ1.js +0 -1
- package/dist/assets/channel-Co6iMgWq.js +0 -1
- package/dist/assets/chat-panel-9alr8FS4.js +0 -3
- package/dist/assets/classDiagram-KNZD7YFC-BbJ0rY3y.js +0 -1
- package/dist/assets/classDiagram-v2-RKCZMP56-BbJ0rY3y.js +0 -1
- package/dist/assets/clone-BMP0PsTa.js +0 -1
- package/dist/assets/command-palette-B93Pjcky.js +0 -1
- package/dist/assets/datasources-panel-v7H3cR0p.js +0 -1
- package/dist/assets/index-2252nrk6.js +0 -68
- package/dist/assets/index-C7CoaNFb.js +0 -578
- package/dist/assets/index-DadI618h.css +0 -1
- package/dist/assets/infoDiagram-STP46IZ2-CJLOpSAf.js +0 -2
- package/dist/assets/links-BpXlz1GG.js +0 -7
- package/dist/assets/min-BBO3-1Hg.js +0 -1
- package/dist/assets/secrets-panel-CfHc5YD0.js +0 -1
- package/dist/assets/sortBy-DZnlX29-.js +0 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-CdThjimL.js +0 -1
- package/src/__tests__/lru.test.ts +0 -74
package/src/plugins/plugins.ts
CHANGED
|
@@ -54,7 +54,7 @@ import type { IStatelessPlugin } from "./stateless-plugin";
|
|
|
54
54
|
import type { IPlugin } from "./types";
|
|
55
55
|
|
|
56
56
|
// List of UI plugins
|
|
57
|
-
export const UI_PLUGINS:
|
|
57
|
+
export const UI_PLUGINS: IPlugin<any, unknown>[] = [
|
|
58
58
|
new ButtonPlugin(),
|
|
59
59
|
new CheckboxPlugin(),
|
|
60
60
|
DataTablePlugin,
|
|
@@ -91,7 +91,7 @@ export const UI_PLUGINS: Array<IPlugin<any, unknown>> = [
|
|
|
91
91
|
];
|
|
92
92
|
|
|
93
93
|
// List of output / layout plugins
|
|
94
|
-
const LAYOUT_PLUGINS:
|
|
94
|
+
const LAYOUT_PLUGINS: IStatelessPlugin<unknown>[] = [
|
|
95
95
|
new AccordionPlugin(),
|
|
96
96
|
new CalloutPlugin(),
|
|
97
97
|
new CarouselPlugin(),
|
package/src/utils/Logger.ts
CHANGED
|
@@ -1,39 +1,11 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import {
|
|
4
|
-
import type { Base64String, ByteString } from "../json/base64";
|
|
3
|
+
import { updateBufferPaths } from "../data-views";
|
|
5
4
|
|
|
6
5
|
describe("updateBufferPaths", () => {
|
|
7
|
-
it("should return the original object if bufferPaths
|
|
6
|
+
it("should return the original object if bufferPaths.length === 0", () => {
|
|
8
7
|
const input = { a: 1, b: 2 };
|
|
9
|
-
const result = updateBufferPaths(input,
|
|
10
|
-
expect(result).toEqual(input);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("should update buffer paths correctly", () => {
|
|
14
|
-
const input = {
|
|
15
|
-
a: 1,
|
|
16
|
-
b: {
|
|
17
|
-
c: "Hello",
|
|
18
|
-
d: "World",
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
const bufferPaths = [
|
|
22
|
-
["b", "c"],
|
|
23
|
-
["b", "d"],
|
|
24
|
-
];
|
|
25
|
-
const result = updateBufferPaths(input, bufferPaths);
|
|
26
|
-
|
|
27
|
-
expect(result.a).toBe(1);
|
|
28
|
-
expect(result.b.c).toBeInstanceOf(DataView);
|
|
29
|
-
expect(result.b.d).toBeInstanceOf(DataView);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("should handle non-existent paths", () => {
|
|
33
|
-
const input = { a: 1 };
|
|
34
|
-
const bufferPaths = [["b", "c"]];
|
|
35
|
-
const result = updateBufferPaths(input, bufferPaths);
|
|
36
|
-
|
|
8
|
+
const result = updateBufferPaths(input, [], []);
|
|
37
9
|
expect(result).toEqual(input);
|
|
38
10
|
});
|
|
39
11
|
|
|
@@ -49,19 +21,32 @@ describe("updateBufferPaths", () => {
|
|
|
49
21
|
["b", "c"],
|
|
50
22
|
["b", "d"],
|
|
51
23
|
];
|
|
52
|
-
const buffers
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
]
|
|
24
|
+
const buffers = [
|
|
25
|
+
new TextEncoder().encode("Hello"),
|
|
26
|
+
new TextEncoder().encode("World"),
|
|
27
|
+
].map((b) => new DataView(b.buffer));
|
|
56
28
|
const result = updateBufferPaths(input, bufferPaths, buffers);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
29
|
+
expect(result).toMatchInlineSnapshot(`
|
|
30
|
+
{
|
|
31
|
+
"a": 1,
|
|
32
|
+
"b": {
|
|
33
|
+
"c": DataView [
|
|
34
|
+
72,
|
|
35
|
+
101,
|
|
36
|
+
108,
|
|
37
|
+
108,
|
|
38
|
+
111,
|
|
39
|
+
],
|
|
40
|
+
"d": DataView [
|
|
41
|
+
87,
|
|
42
|
+
111,
|
|
43
|
+
114,
|
|
44
|
+
108,
|
|
45
|
+
100,
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
`);
|
|
65
50
|
});
|
|
66
51
|
|
|
67
52
|
it("should throw error when buffers and paths length mismatch", () => {
|
|
@@ -70,7 +55,7 @@ describe("updateBufferPaths", () => {
|
|
|
70
55
|
["b", "c"],
|
|
71
56
|
["b", "d"],
|
|
72
57
|
];
|
|
73
|
-
const buffers
|
|
58
|
+
const buffers = [new DataView(new ArrayBuffer())]; // Only one buffer for two paths
|
|
74
59
|
|
|
75
60
|
expect(() => updateBufferPaths(input, bufferPaths, buffers)).toThrow(
|
|
76
61
|
"Buffers and buffer paths not the same length",
|
|
@@ -80,33 +65,10 @@ describe("updateBufferPaths", () => {
|
|
|
80
65
|
it("should handle empty buffers array", () => {
|
|
81
66
|
const input = { a: 1 };
|
|
82
67
|
const bufferPaths = [["b", "c"]];
|
|
83
|
-
const buffers:
|
|
68
|
+
const buffers: DataView[] = [];
|
|
84
69
|
|
|
85
70
|
expect(() => updateBufferPaths(input, bufferPaths, buffers)).toThrow(
|
|
86
71
|
"Buffers and buffer paths not the same length",
|
|
87
72
|
);
|
|
88
73
|
});
|
|
89
74
|
});
|
|
90
|
-
|
|
91
|
-
describe("byteStringToDataView", () => {
|
|
92
|
-
it("should convert a base64 string to a DataView", () => {
|
|
93
|
-
const input = "Hello" as ByteString;
|
|
94
|
-
const result = byteStringToDataView(input);
|
|
95
|
-
|
|
96
|
-
expect(result).toBeInstanceOf(DataView);
|
|
97
|
-
expect(result.byteLength).toBe(5);
|
|
98
|
-
expect(result.getUint8(0)).toBe(72); // 'H'
|
|
99
|
-
expect(result.getUint8(1)).toBe(101); // 'e'
|
|
100
|
-
expect(result.getUint8(2)).toBe(108); // 'l'
|
|
101
|
-
expect(result.getUint8(3)).toBe(108); // 'l'
|
|
102
|
-
expect(result.getUint8(4)).toBe(111); // 'o'
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it("should handle empty string", () => {
|
|
106
|
-
const input = "" as ByteString;
|
|
107
|
-
const result = byteStringToDataView(input);
|
|
108
|
-
|
|
109
|
-
expect(result).toBeInstanceOf(DataView);
|
|
110
|
-
expect(result.byteLength).toBe(0);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
import { ansiToPlainText, parseHtmlContent } from "../dom";
|
|
5
|
+
|
|
6
|
+
describe("parseHtmlContent", () => {
|
|
7
|
+
test("strips HTML tags and returns plain text", () => {
|
|
8
|
+
const htmlString =
|
|
9
|
+
'<span style="color: red;">Error: Something went wrong</span>';
|
|
10
|
+
const result = parseHtmlContent(htmlString);
|
|
11
|
+
expect(result).toMatchInlineSnapshot(`"Error: Something went wrong"`);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("handles ANSI color span tags", () => {
|
|
15
|
+
const htmlString =
|
|
16
|
+
'<span style="color:#d03050;">ERROR</span>: <span style="color:#8ad03a;">File not found</span>';
|
|
17
|
+
const result = parseHtmlContent(htmlString);
|
|
18
|
+
expect(result).toMatchInlineSnapshot(`"ERROR: File not found"`);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("normalizes whitespace", () => {
|
|
22
|
+
const htmlString = "<span> Multiple \n\n spaces and \t tabs </span>";
|
|
23
|
+
const result = parseHtmlContent(htmlString);
|
|
24
|
+
expect(result).toMatchInlineSnapshot(`
|
|
25
|
+
" Multiple
|
|
26
|
+
|
|
27
|
+
spaces and tabs"
|
|
28
|
+
`);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("handles empty HTML", () => {
|
|
32
|
+
const htmlString = "";
|
|
33
|
+
const result = parseHtmlContent(htmlString);
|
|
34
|
+
expect(result).toMatchInlineSnapshot(`""`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("handles plain text without HTML", () => {
|
|
38
|
+
const htmlString = "Simple error message";
|
|
39
|
+
const result = parseHtmlContent(htmlString);
|
|
40
|
+
expect(result).toMatchInlineSnapshot(`"Simple error message"`);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("handles nested HTML elements", () => {
|
|
44
|
+
const htmlString =
|
|
45
|
+
'<div><span>Traceback:</span><pre><code> File "test.py", line 1\n print("hello"</code></pre></div>';
|
|
46
|
+
const result = parseHtmlContent(htmlString);
|
|
47
|
+
expect(result).toMatchInlineSnapshot(`
|
|
48
|
+
"Traceback: File "test.py", line 1
|
|
49
|
+
print("hello""
|
|
50
|
+
`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("handles complex ANSI-converted HTML with styles", () => {
|
|
54
|
+
const htmlString =
|
|
55
|
+
'<span style="background:#fff;color:#000"> File "</span><span style="background:#fff;color:#0000ff">test.py</span><span style="background:#fff;color:#000">", line </span><span style="background:#fff;color:#008000">1</span>';
|
|
56
|
+
const result = parseHtmlContent(htmlString);
|
|
57
|
+
expect(result).toMatchInlineSnapshot(`" File "test.py", line 1"`);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("ansiToPlainText", () => {
|
|
62
|
+
test("converts ANSI color codes to plain text", () => {
|
|
63
|
+
const ansiString = "\u001B[31mError:\u001B[0m Something went wrong";
|
|
64
|
+
const result = ansiToPlainText(ansiString);
|
|
65
|
+
expect(result).toMatchInlineSnapshot(`"Error: Something went wrong"`);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("handles multiple ANSI color codes", () => {
|
|
69
|
+
const ansiString =
|
|
70
|
+
"\u001B[32mSUCCESS:\u001B[0m \u001B[34mOperation completed\u001B[0m successfully";
|
|
71
|
+
const result = ansiToPlainText(ansiString);
|
|
72
|
+
expect(result).toMatchInlineSnapshot(
|
|
73
|
+
`"SUCCESS: Operation completed successfully"`,
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("handles ANSI bold and color combinations", () => {
|
|
78
|
+
const ansiString =
|
|
79
|
+
"\u001B[1;31mBOLD RED ERROR:\u001B[0m \u001B[33mWarning message\u001B[0m";
|
|
80
|
+
const result = ansiToPlainText(ansiString);
|
|
81
|
+
expect(result).toMatchInlineSnapshot(`"BOLD RED ERROR: Warning message"`);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("handles Python traceback with ANSI codes", () => {
|
|
85
|
+
const ansiString =
|
|
86
|
+
"\u001B[0;36m File \"\u001B[0m\u001B[0;32mtest.py\u001B[0m\u001B[0;36m\", line \u001B[0m\u001B[0;32m1\u001B[0m\u001B[0;36m, in \u001B[0m\u001B[0;35m<module>\u001B[0m\n\u001B[0;31mNameError\u001B[0m: name 'undefined_var' is not defined";
|
|
87
|
+
const result = ansiToPlainText(ansiString);
|
|
88
|
+
expect(result).toMatchInlineSnapshot(`
|
|
89
|
+
" File "test.py", line 1, in <module>
|
|
90
|
+
NameError: name 'undefined_var' is not defined"
|
|
91
|
+
`);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("handles error messages with background colors", () => {
|
|
95
|
+
const ansiString =
|
|
96
|
+
"\u001B[41;37m CRITICAL ERROR \u001B[0m \u001B[31mSystem failure detected\u001B[0m";
|
|
97
|
+
const result = ansiToPlainText(ansiString);
|
|
98
|
+
expect(result).toMatchInlineSnapshot(
|
|
99
|
+
`" CRITICAL ERROR System failure detected"`,
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("handles complex stack trace with mixed formatting", () => {
|
|
104
|
+
const ansiString =
|
|
105
|
+
'Traceback (most recent call last):\n \u001B[36mFile "\u001B[32m/path/to/file.py\u001B[36m", line \u001B[32m42\u001B[36m, in \u001B[35mfunction_name\u001B[0m\n \u001B[31mraise ValueError("Something went wrong")\u001B[0m\n\u001B[31mValueError\u001B[0m: Something went wrong';
|
|
106
|
+
const result = ansiToPlainText(ansiString);
|
|
107
|
+
expect(result).toMatchInlineSnapshot(`
|
|
108
|
+
"Traceback (most recent call last):
|
|
109
|
+
File "/path/to/file.py", line 42, in function_name
|
|
110
|
+
raise ValueError("Something went wrong")
|
|
111
|
+
ValueError: Something went wrong"
|
|
112
|
+
`);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("handles empty string", () => {
|
|
116
|
+
const ansiString = "";
|
|
117
|
+
const result = ansiToPlainText(ansiString);
|
|
118
|
+
expect(result).toMatchInlineSnapshot(`""`);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("handles plain text without ANSI codes", () => {
|
|
122
|
+
const ansiString = "Plain error message without colors";
|
|
123
|
+
const result = ansiToPlainText(ansiString);
|
|
124
|
+
expect(result).toMatchInlineSnapshot(
|
|
125
|
+
`"Plain error message without colors"`,
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("handles whitespace and newlines correctly", () => {
|
|
130
|
+
const ansiString =
|
|
131
|
+
"\u001B[31m Error: \u001B[0m\n\n \u001B[33m Warning \u001B[0m ";
|
|
132
|
+
const result = ansiToPlainText(ansiString);
|
|
133
|
+
expect(result).toMatchInlineSnapshot(`
|
|
134
|
+
" Error:
|
|
135
|
+
|
|
136
|
+
Warning"
|
|
137
|
+
`);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("handles JavaScript error stack trace", () => {
|
|
141
|
+
const ansiString =
|
|
142
|
+
"\u001B[31mReferenceError\u001B[0m: \u001B[33mvariable\u001B[0m is not defined\n at \u001B[36mObject.<anonymous>\u001B[0m (\u001B[32m/path/to/script.js\u001B[0m:\u001B[33m5\u001B[0m:\u001B[33m1\u001B[0m)";
|
|
143
|
+
const result = ansiToPlainText(ansiString);
|
|
144
|
+
expect(result).toMatchInlineSnapshot(`
|
|
145
|
+
"ReferenceError: variable is not defined
|
|
146
|
+
at Object.<anonymous> (/path/to/script.js:5:1)"
|
|
147
|
+
`);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("handles Rust panic with ANSI formatting", () => {
|
|
151
|
+
const ansiString =
|
|
152
|
+
"thread '\u001B[32mmain\u001B[0m' panicked at '\u001B[31massertion failed: `(left == right)`\u001B[0m'\n \u001B[36mleft\u001B[0m: `\u001B[33m5\u001B[0m`\n \u001B[36mright\u001B[0m: `\u001B[33m10\u001B[0m`";
|
|
153
|
+
const result = ansiToPlainText(ansiString);
|
|
154
|
+
expect(result).toMatchInlineSnapshot(`
|
|
155
|
+
"thread 'main' panicked at 'assertion failed: \`(left == right)\`'
|
|
156
|
+
left: \`5\`
|
|
157
|
+
right: \`10\`"
|
|
158
|
+
`);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("handles mix of 8-bit and 256-color ANSI codes", () => {
|
|
162
|
+
const ansiString =
|
|
163
|
+
"\u001B[38;5;196mBright Red\u001B[0m and \u001B[38;5;46mBright Green\u001B[0m text";
|
|
164
|
+
const result = ansiToPlainText(ansiString);
|
|
165
|
+
expect(result).toMatchInlineSnapshot(`"Bright Red and Bright Green text"`);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
@@ -740,7 +740,7 @@ describe("MultiColumn", () => {
|
|
|
740
740
|
});
|
|
741
741
|
|
|
742
742
|
it("creates from ids and columns", () => {
|
|
743
|
-
const idAndColumns:
|
|
743
|
+
const idAndColumns: [string, number | undefined | null][] = [
|
|
744
744
|
["A1", 0],
|
|
745
745
|
["A2", 0],
|
|
746
746
|
["B1", 1],
|
|
@@ -1991,4 +1991,52 @@ describe("CollapsibleTree.fromWithPreviousShape", () => {
|
|
|
1991
1991
|
expect(tree.isCollapsed("one")).toBe(false);
|
|
1992
1992
|
expect(tree.topLevelIds).toEqual(["one", "three", "four"]);
|
|
1993
1993
|
});
|
|
1994
|
+
|
|
1995
|
+
it("reproduces GitHub issue #6188: inOrderIds with nested collapses", () => {
|
|
1996
|
+
// Simplified reproduction case:
|
|
1997
|
+
// Cell A (markdown): # Section 1 Header
|
|
1998
|
+
// Cell B (markdown): ## Subsection 1.1 Header
|
|
1999
|
+
// Cell C (python): print("This cell should be in Subsection 1.1")
|
|
2000
|
+
// Cell D (python): print("This cell should also be in Subsection 1.1")
|
|
2001
|
+
// Cell E (markdown): ## Subsection 1.2 Header
|
|
2002
|
+
// Cell F (python): print("This cell should be in Subsection 1.2")
|
|
2003
|
+
|
|
2004
|
+
const originalOrder = [
|
|
2005
|
+
"CellA", // # Section 1 Header
|
|
2006
|
+
"CellB", // ## Subsection 1.1 Header
|
|
2007
|
+
"CellC", // print("This cell should be in Subsection 1.1")
|
|
2008
|
+
"CellD", // print("This cell should also be in Subsection 1.1")
|
|
2009
|
+
"CellE", // ## Subsection 1.2 Header
|
|
2010
|
+
"CellF", // print("This cell should be in Subsection 1.2")
|
|
2011
|
+
];
|
|
2012
|
+
|
|
2013
|
+
// Create notebook with one column
|
|
2014
|
+
let notebook = MultiColumn.from([originalOrder]);
|
|
2015
|
+
|
|
2016
|
+
// Before collapsing, order should be correct
|
|
2017
|
+
expect(notebook.inOrderIds).toEqual(originalOrder);
|
|
2018
|
+
|
|
2019
|
+
const columnId = notebook.getColumnIds()[0];
|
|
2020
|
+
|
|
2021
|
+
// Follow the exact reproduction steps from the GitHub issue:
|
|
2022
|
+
// 1. Collapse B (subsection 1.1) - includes C, D (stops before E)
|
|
2023
|
+
notebook = notebook.transform(columnId, (tree) =>
|
|
2024
|
+
tree.collapse("CellB", "CellD"),
|
|
2025
|
+
);
|
|
2026
|
+
|
|
2027
|
+
// 2. Collapse E (subsection 1.2) - includes F (to end)
|
|
2028
|
+
notebook = notebook.transform(columnId, (tree) =>
|
|
2029
|
+
tree.collapse("CellE", undefined),
|
|
2030
|
+
);
|
|
2031
|
+
|
|
2032
|
+
// 3. Collapse A (section 1) - includes all the rest (B, E and their children)
|
|
2033
|
+
notebook = notebook.transform(columnId, (tree) =>
|
|
2034
|
+
tree.collapse("CellA", undefined),
|
|
2035
|
+
);
|
|
2036
|
+
|
|
2037
|
+
const finalOrder = notebook.inOrderIds;
|
|
2038
|
+
|
|
2039
|
+
// inOrderIds now correctly preserves logical order even with nested collapses
|
|
2040
|
+
expect(finalOrder).toEqual(originalOrder);
|
|
2041
|
+
});
|
|
1994
2042
|
});
|
|
@@ -6,14 +6,20 @@ import { extractAllTracebackInfo } from "../traceback";
|
|
|
6
6
|
describe("traceback", () => {
|
|
7
7
|
test("extracts cell-link", () => {
|
|
8
8
|
const errors = extractAllTracebackInfo(Tracebacks.raw);
|
|
9
|
-
expect(
|
|
9
|
+
expect(
|
|
10
|
+
errors[0].kind === "file" &&
|
|
11
|
+
errors[0].filePath.endsWith("marimo/_runtime/executor.py"),
|
|
12
|
+
).toBe(true);
|
|
13
|
+
expect(errors.slice(1)).toMatchInlineSnapshot(`
|
|
10
14
|
[
|
|
11
15
|
{
|
|
12
16
|
"cellId": "Hbol",
|
|
17
|
+
"kind": "cell",
|
|
13
18
|
"lineNumber": 4,
|
|
14
19
|
},
|
|
15
20
|
{
|
|
16
21
|
"cellId": "Hbol",
|
|
22
|
+
"kind": "cell",
|
|
17
23
|
"lineNumber": 2,
|
|
18
24
|
},
|
|
19
25
|
]
|
|
@@ -22,10 +28,15 @@ describe("traceback", () => {
|
|
|
22
28
|
|
|
23
29
|
test("extracts cell-link from assertion", () => {
|
|
24
30
|
const info = extractAllTracebackInfo(Tracebacks.assertion);
|
|
25
|
-
expect(
|
|
31
|
+
expect(
|
|
32
|
+
info[0].kind === "file" &&
|
|
33
|
+
info[0].filePath.endsWith("marimo/_runtime/executor.py"),
|
|
34
|
+
).toBe(true);
|
|
35
|
+
expect(info.slice(1)).toMatchInlineSnapshot(`
|
|
26
36
|
[
|
|
27
37
|
{
|
|
28
38
|
"cellId": "Hbol",
|
|
39
|
+
"kind": "cell",
|
|
29
40
|
"lineNumber": 1,
|
|
30
41
|
},
|
|
31
42
|
]
|
package/src/utils/arrays.ts
CHANGED
|
@@ -55,7 +55,7 @@ export function arrayShallowEquals<T>(a: T[], b: T[]): boolean {
|
|
|
55
55
|
export const Arrays = {
|
|
56
56
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
57
|
EMPTY: [] as any,
|
|
58
|
-
zip: <T, U>(a: T[], b: U[]):
|
|
58
|
+
zip: <T, U>(a: T[], b: U[]): [T, U][] => {
|
|
59
59
|
invariant(a.length === b.length, "Arrays must be the same length");
|
|
60
60
|
return a.map((item, i) => [item, b[i]]);
|
|
61
61
|
},
|
|
@@ -79,11 +79,7 @@ type Middleware<State> = (
|
|
|
79
79
|
export function createReducerAndAtoms<
|
|
80
80
|
State,
|
|
81
81
|
RH extends ReducerHandlers<NoInfer<State>>,
|
|
82
|
-
>(
|
|
83
|
-
initialState: () => State,
|
|
84
|
-
reducers: RH,
|
|
85
|
-
middleware?: Array<Middleware<State>>,
|
|
86
|
-
) {
|
|
82
|
+
>(initialState: () => State, reducers: RH, middleware?: Middleware<State>[]) {
|
|
87
83
|
const { reducer, createActions } = createReducer(initialState, reducers);
|
|
88
84
|
|
|
89
85
|
const reducerWithMiddleware = (state: State, action: ReducerAction<any>) => {
|
package/src/utils/data-views.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
-
import {
|
|
2
|
+
import { set } from "lodash-es";
|
|
3
3
|
import { invariant } from "./invariant";
|
|
4
|
-
import { type Base64String, type ByteString, typedAtob } from "./json/base64";
|
|
5
4
|
import { Logger } from "./Logger";
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -9,8 +8,8 @@ import { Logger } from "./Logger";
|
|
|
9
8
|
*/
|
|
10
9
|
export function updateBufferPaths<T extends Record<string, unknown>>(
|
|
11
10
|
inputObject: T,
|
|
12
|
-
bufferPaths:
|
|
13
|
-
buffers
|
|
11
|
+
bufferPaths: readonly (readonly (string | number)[])[],
|
|
12
|
+
buffers: readonly DataView[],
|
|
14
13
|
): T {
|
|
15
14
|
// If no buffer paths, return the original object
|
|
16
15
|
if (!bufferPaths || bufferPaths.length === 0) {
|
|
@@ -30,25 +29,13 @@ export function updateBufferPaths<T extends Record<string, unknown>>(
|
|
|
30
29
|
for (const [i, bufferPath] of bufferPaths.entries()) {
|
|
31
30
|
// If buffers exists, we use that value
|
|
32
31
|
// Otherwise we grab it from inside the inputObject
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
: get(object, bufferPath);
|
|
36
|
-
if (!bytes) {
|
|
32
|
+
const dataView = buffers[i];
|
|
33
|
+
if (!dataView) {
|
|
37
34
|
Logger.warn("Could not find buffer at path", bufferPath);
|
|
38
35
|
continue;
|
|
39
36
|
}
|
|
40
|
-
|
|
41
|
-
object = set(object, bufferPath, buffer);
|
|
37
|
+
object = set(object, bufferPath, dataView);
|
|
42
38
|
}
|
|
43
39
|
|
|
44
40
|
return object;
|
|
45
41
|
}
|
|
46
|
-
|
|
47
|
-
export const byteStringToDataView = (bytes: ByteString) => {
|
|
48
|
-
const buffer = new ArrayBuffer(bytes.length);
|
|
49
|
-
const view = new DataView(buffer);
|
|
50
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
51
|
-
view.setUint8(i, bytes.charCodeAt(i));
|
|
52
|
-
}
|
|
53
|
-
return view;
|
|
54
|
-
};
|
package/src/utils/dom.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { AnsiUp } from "ansi_up";
|
|
4
|
+
import { Logger } from "./Logger";
|
|
5
|
+
|
|
6
|
+
// Create a shared AnsiUp instance
|
|
7
|
+
const ansiUp = new AnsiUp();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extracts plain text content from HTML by removing all HTML tags and normalizing whitespace.
|
|
11
|
+
*
|
|
12
|
+
* @param htmlString The HTML string to parse
|
|
13
|
+
* @returns Plain text content with HTML tags removed and whitespace normalized
|
|
14
|
+
*/
|
|
15
|
+
export function parseHtmlContent(htmlString: string): string {
|
|
16
|
+
try {
|
|
17
|
+
// Create a temporary DOM element to parse HTML
|
|
18
|
+
const tempDiv = document.createElement("div");
|
|
19
|
+
tempDiv.innerHTML = htmlString;
|
|
20
|
+
|
|
21
|
+
// Extract text content, removing HTML tags
|
|
22
|
+
const textContent = tempDiv.textContent || tempDiv.innerText || "";
|
|
23
|
+
const lines = textContent.split("\n");
|
|
24
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
25
|
+
} catch (error) {
|
|
26
|
+
Logger.error("Error parsing HTML content:", error);
|
|
27
|
+
// If parsing fails, return the original string
|
|
28
|
+
return htmlString;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Converts ANSI escape sequences to plain text by first converting to HTML and then stripping HTML tags.
|
|
34
|
+
* This is useful for console output that may contain ANSI color codes or formatting.
|
|
35
|
+
*
|
|
36
|
+
* @param ansiString String that may contain ANSI escape sequences
|
|
37
|
+
* @returns Plain text with ANSI codes removed and HTML stripped
|
|
38
|
+
*/
|
|
39
|
+
export function ansiToPlainText(ansiString: string): string {
|
|
40
|
+
if (!ansiString) {
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
// Convert ANSI escape sequences to HTML
|
|
46
|
+
const htmlString = ansiUp.ansi_to_html(ansiString);
|
|
47
|
+
|
|
48
|
+
// Strip HTML tags and return clean text
|
|
49
|
+
return parseHtmlContent(htmlString);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
Logger.error("Error converting ANSI to plain text:", error);
|
|
52
|
+
// If conversion fails, return the original string
|
|
53
|
+
return ansiString;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -134,7 +134,7 @@ export function mergeArray<T, U>(
|
|
|
134
134
|
arr2: U[],
|
|
135
135
|
equals: (a: T, b: U) => boolean,
|
|
136
136
|
stub: T,
|
|
137
|
-
): { merged:
|
|
137
|
+
): { merged: (T | null)[]; edits: EditDistanceResult } {
|
|
138
138
|
const edits = editDistanceGeneral(arr1, arr2, equals);
|
|
139
139
|
return {
|
|
140
140
|
merged: applyOperationsWithStub(arr1, edits.operations, stub),
|
|
@@ -34,7 +34,7 @@ export function blobToString(
|
|
|
34
34
|
*
|
|
35
35
|
* Returns a promised array of tuples [file name, file contents].
|
|
36
36
|
*/
|
|
37
|
-
export function filesToBase64(files: File[]): Promise<
|
|
37
|
+
export function filesToBase64(files: File[]): Promise<[string, string][]> {
|
|
38
38
|
return Promise.all(
|
|
39
39
|
files.map((file) =>
|
|
40
40
|
blobToString(file, "base64").then(
|