@marimo-team/islands 0.20.5-dev8 → 0.20.5-dev83
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/{Combination-Du-o_hC9.js → Combination-Dk6JxauT.js} +1 -1
- package/dist/{ConnectedDataExplorerComponent-DUS-zJoR.js → ConnectedDataExplorerComponent-pQ4sWAoT.js} +11 -11
- package/dist/{_baseIsEqual-5cAxzk6f.js → _baseIsEqual-CvgsjYoW.js} +38 -38
- package/dist/{_basePickBy-3JVb5wYm.js → _basePickBy-pTDW2_2A.js} +6 -6
- package/dist/{_baseUniq-DSSiFuIJ.js → _baseUniq-BUFhl85h.js} +1 -1
- package/dist/{any-language-editor-BL9o7y0_.js → any-language-editor-BIj11a2e.js} +19 -19
- package/dist/{architecture-7HQA4BMR-BxkNpYRp.js → architecture-7HQA4BMR-BmtmhGMc.js} +2 -2
- package/dist/{architectureDiagram-VXUJARFQ-DrJeyFHq.js → architectureDiagram-VXUJARFQ-Df0FNeBR.js} +14 -14
- package/dist/assets/__vite-browser-external-Us1ds95c.js +1 -0
- package/dist/assets/{worker-DUYMdbtA.js → worker-D10K3OOz.js} +2 -2
- package/dist/{blockDiagram-VD42YOAC-BJrP6qKc.js → blockDiagram-VD42YOAC-DszWqlLz.js} +7 -7
- package/dist/{button-KYalaJYu.js → button-DQpBib29.js} +24 -11
- package/dist/{c4Diagram-YG6GDRKO-Bo4gytQ5.js → c4Diagram-YG6GDRKO-Dyj8LoUX.js} +4 -4
- package/dist/{channel-IWLGkaBE.js → channel-CUFaIkTh.js} +1 -1
- package/dist/{check-C50jsehH.js → check-DpqPQmzz.js} +1 -1
- package/dist/{chunk-4F5CHEZ2-CxKDFd-t.js → chunk-4F5CHEZ2-CRwwZ2ED.js} +1 -1
- package/dist/{chunk-ABZYJK2D-CRwanrkd.js → chunk-ABZYJK2D-7QYXAAhe.js} +1 -1
- package/dist/{chunk-ATLVNIR6-CMMCMvOK.js → chunk-ATLVNIR6-pmHPAPSd.js} +1 -1
- package/dist/{chunk-B2363JML-e_W7KW1D.js → chunk-B2363JML-BuBMltZc.js} +1 -1
- package/dist/{chunk-B4BG7PRW-BNsHrGHG.js → chunk-B4BG7PRW-Dbta9cTX.js} +4 -4
- package/dist/{chunk-DI55MBZ5-DQeYbfMV.js → chunk-DI55MBZ5-DyKB35wC.js} +4 -4
- package/dist/{chunk-EXTU4WIE-CV_DQeaX.js → chunk-EXTU4WIE-BRFl4iNd.js} +1 -1
- package/dist/{chunk-FRFDVMJY-C7q09nvl.js → chunk-FRFDVMJY-Bk2LD5Te.js} +1 -1
- package/dist/{chunk-JA3XYJ7Z-Cmt--e0q.js → chunk-JA3XYJ7Z-BkrY9SdL.js} +2 -2
- package/dist/{chunk-JZLCHNYA-CkyMJnI9.js → chunk-JZLCHNYA-Bk_Lil-q.js} +4 -4
- package/dist/{chunk-N4CR4FBY-BJfHtJbD.js → chunk-N4CR4FBY-f5n6meOd.js} +5 -5
- package/dist/{chunk-PL6DKKU2-ChKBqnoD.js → chunk-PL6DKKU2-DiFkzMfM.js} +1 -1
- package/dist/{chunk-QN33PNHL-WOLIPUAJ.js → chunk-QN33PNHL-CXfJywHv.js} +1 -1
- package/dist/{chunk-QXUST7PY-DYuD50pU.js → chunk-QXUST7PY-D7-26sj3.js} +5 -5
- package/dist/{chunk-S3R3BYOJ-CsnX6RKs.js → chunk-S3R3BYOJ-BRT9vd1R.js} +3 -3
- package/dist/{chunk-SJTYNZTY-j6_1s5om.js → chunk-SJTYNZTY-BvVkbShU.js} +1 -1
- package/dist/{chunk-TCCFYFTB-DdLCbCTn.js → chunk-TCCFYFTB-DqxhgXG0.js} +31 -31
- package/dist/{chunk-TQ3KTPDO-CGsUIC73.js → chunk-TQ3KTPDO-CPkEruAA.js} +1 -1
- package/dist/{chunk-TZMSLE5B-B3eYTGCw.js → chunk-TZMSLE5B-DSfBOnzx.js} +1 -1
- package/dist/{chunk-UMXZTB3W--LdAK3Bv.js → chunk-UMXZTB3W-C4ypIY3V.js} +1 -1
- package/dist/{classDiagram-v2-WZHVMYZB-UTw37Gg8.js → classDiagram-2ON5EDUG-DphiMW3Y.js} +10 -10
- package/dist/{classDiagram-2ON5EDUG-C7C-oefv.js → classDiagram-v2-WZHVMYZB-BH1x5h4a.js} +10 -10
- package/dist/{clone-BJrS4PdE.js → clone-CEQ-pda1.js} +1 -1
- package/dist/{constants-D1Tbg_6B.js → constants-CytQ_3LM.js} +3 -3
- package/dist/{copy-oc-FcZzt.js → copy-BkBF0Xgk.js} +2 -2
- package/dist/{dagre-6UL2VRFP-BgsUhJrV.js → dagre-6UL2VRFP-DGEbtmgU.js} +12 -12
- package/dist/{dagre-CyZCGfV_.js → dagre-BVnNvbvD.js} +37 -37
- package/dist/{diagram-PSM6KHXK-BIUUOfKo.js → diagram-PSM6KHXK-CG_usglE.js} +15 -15
- package/dist/{diagram-QEK2KX5R-BFjolZQv.js → diagram-QEK2KX5R-CtGFEwzJ.js} +13 -13
- package/dist/{diagram-S2PKOQOG-4jfkWoZw.js → diagram-S2PKOQOG-ClKAGmbv.js} +13 -13
- package/dist/dist-B4MxkKHf.js +8 -0
- package/dist/{dist-De9X_Des.js → dist-B9EjSb9T.js} +1 -1
- package/dist/{dist-IW_ARJ3S.js → dist-BFxYppVR.js} +4 -4
- package/dist/{dist-D7ZGWV_9.js → dist-BGZ7TWS9.js} +3 -3
- package/dist/{dist-CwtEWuFb.js → dist-BSfYc7vq.js} +2 -2
- package/dist/{dist-DMS81OrU.js → dist-BUrWeMEP.js} +1 -1
- package/dist/dist-BYghZv6b.js +5 -0
- package/dist/dist-Be-uQhz5.js +6 -0
- package/dist/{dist-Ch_JuCvc.js → dist-BpMlUdNO.js} +3 -3
- package/dist/{dist-C6z8U-ms.js → dist-Bq5eYK43.js} +2 -2
- package/dist/{dist-BFL9TlzD.js → dist-Bq9zYwJs.js} +5 -5
- package/dist/{dist-7ZF--V_D.js → dist-C4K7pumm.js} +2 -2
- package/dist/{dist-Qjf6pcqK.js → dist-CAKwXCWI.js} +2 -2
- package/dist/dist-CB_xf0ju.js +5 -0
- package/dist/{dist-BwQHkjA9.js → dist-CDHl2i1x.js} +4 -4
- package/dist/dist-CK0qFAbF.js +8 -0
- package/dist/{dist-C4XMUaob.js → dist-CPlGUbk-.js} +2 -2
- package/dist/{dist-BT6_J2eq.js → dist-CSEWGuDq.js} +7 -2
- package/dist/dist-CYEk-qrr.js +8 -0
- package/dist/{dist-CYo3w-nC.js → dist-Cl5iM8xL.js} +3 -3
- package/dist/dist-CmKoWpMk.js +5 -0
- package/dist/{dist-I8MQW60_.js → dist-CseYuPtL.js} +2 -2
- package/dist/dist-D1nf4IQl.js +5 -0
- package/dist/{dist-CsqiXw7J.js → dist-D4gcY469.js} +2 -2
- package/dist/{dist-DUxS2paD.js → dist-D5NMgbbv.js} +2 -2
- package/dist/{dist-UYm1IE5s.js → dist-DERtJN02.js} +2 -2
- package/dist/{dist-CFToYDWO.js → dist-DEj2X26M.js} +2 -2
- package/dist/{dist-BuapEdlD.js → dist-DOoqn-VL.js} +70 -67
- package/dist/{dist-BLThQiU4.js → dist-DUretbKK.js} +2 -2
- package/dist/{dist-DEFZ7dnD.js → dist-D_-CGmlh.js} +2 -2
- package/dist/dist-Df3AcKpt.js +6 -0
- package/dist/dist-DgaFHt_I.js +5 -0
- package/dist/dist-Dk10C3ui.js +5 -0
- package/dist/{dist-D0f6Yrrb.js → dist-DodLQWPg.js} +1 -1
- package/dist/dist-DtyPVMHR.js +5 -0
- package/dist/{dist-Cb3cLT39.js → dist-HoZO6brh.js} +2 -2
- package/dist/{dist-Cqpjy6bK.js → dist-RNGn_-uD.js} +1 -1
- package/dist/{dist-BBcqvpvP.js → dist-Ux6dL_VB.js} +1 -1
- package/dist/{dist-B8Y11RWn.js → dist-WIWVvdBh.js} +2 -2
- package/dist/{dist-CB6qhQ8K.js → dist-gc9KgJuA.js} +1 -1
- package/dist/{dist-ovDpXuSB.js → dist-i-ud9aCA.js} +1 -1
- package/dist/dist-ko7WnHAO.js +5 -0
- package/dist/{dist-BTQbjEKU.js → dist-lNe4i1Nm.js} +1 -1
- package/dist/dist-of7gLRFK.js +8 -0
- package/dist/{erDiagram-Q2GNP2WA-Cq5Bz5lG.js → erDiagram-Q2GNP2WA-DPMseVVp.js} +10 -10
- package/dist/{error-banner-D0tXnwl4.js → error-banner-BctofTCP.js} +2 -2
- package/dist/{esm-BxMbHo0y.js → esm-BBkPJL8N.js} +29 -27
- package/dist/{flowDiagram-NV44I4VS-6WPJVFl7.js → flowDiagram-NV44I4VS-BpAIFwW7.js} +10 -10
- package/dist/{ganttDiagram-JELNMOA3-AfDhh9CI.js → ganttDiagram-JELNMOA3-DXYghZ9C.js} +3 -3
- package/dist/{gitGraph-G5XIXVHT-C0o6gecv.js → gitGraph-G5XIXVHT-ChHUSAop.js} +2 -2
- package/dist/{gitGraphDiagram-V2S2FVAM-BRSwuj0Q.js → gitGraphDiagram-V2S2FVAM-CBL-7g3_.js} +12 -12
- package/dist/{glide-data-editor-ByPNTNVG.js → glide-data-editor-DqxJOnJk.js} +63 -63
- package/dist/{graphlib-DZnBMcsX.js → graphlib-D18eZCT4.js} +10 -10
- package/dist/hasIn-B9AbGLj3.js +86 -0
- package/dist/{info-VBDWY6EO-Bzsods6X.js → info-VBDWY6EO-CwyXEo8E.js} +2 -2
- package/dist/{infoDiagram-HS3SLOUP-Cmxo6jKx.js → infoDiagram-HS3SLOUP-BXGbfBss.js} +12 -12
- package/dist/{isArrayLikeObject-Btu-i6_P.js → isArrayLikeObject-BrYl-ETg.js} +25 -26
- package/dist/{isEmpty-CZvUtYFp.js → isEmpty-C-xMag79.js} +2 -2
- package/dist/{isString-CBr7TEb7.js → isString-D-vNYDBA.js} +1 -1
- package/dist/{isSymbol-BuQsMXhk.js → isSymbol-Dyt2NSnN.js} +1 -1
- package/dist/{journeyDiagram-XKPGCS4Q-CKYr8cSR.js → journeyDiagram-XKPGCS4Q-D5BIjS4N.js} +3 -3
- package/dist/{kanban-definition-3W4ZIXB7-DVvAZzQD.js → kanban-definition-3W4ZIXB7-DhDkqxFB.js} +7 -7
- package/dist/{label-CV0KYhtH.js → label-BLDcDYdI.js} +6 -6
- package/dist/{loader-eJCvvApN.js → loader-DsE3MiYo.js} +2 -2
- package/dist/main.js +1622 -1122
- package/dist/{memoize-P1T1IGb9.js → memoize-Cs8aS5RW.js} +1 -1
- package/dist/merge-NuyC7LN7.js +51 -0
- package/dist/{mermaid-COOB_abB.js → mermaid-DkdSmFY8.js} +42 -42
- package/dist/{mermaid-parser.core-Cd-wu4tE.js → mermaid-parser.core-OkWZ8nr-.js} +8 -8
- package/dist/{min-CMDDtXJP.js → min-ECVRnCdn.js} +30 -30
- package/dist/{mindmap-definition-VGOIOE7T-1ExmnvYy.js → mindmap-definition-VGOIOE7T-BxQi78Vl.js} +9 -9
- package/dist/{now-BxlRp0OQ.js → now-BC2mX0ZT.js} +1 -1
- package/dist/{packet-DYOGHKS2-Bf1CvFco.js → packet-DYOGHKS2-C62XQjZh.js} +2 -2
- package/dist/{pie-VRWISCQL-LY_wbqji.js → pie-VRWISCQL-nfAKQJw3.js} +2 -2
- package/dist/{pieDiagram-ADFJNKIX-CJlIsdsU.js → pieDiagram-ADFJNKIX-DfSJXUHa.js} +13 -13
- package/dist/{purify.es-CyOIw8ru.js → purify.es-DGenX2XH.js} +67 -67
- package/dist/{quadrantDiagram-AYHSOK5B-BU78RiaH.js → quadrantDiagram-AYHSOK5B-CAcVWXc-.js} +2 -2
- package/dist/{radar-ZZBFDIW7-Ro3iXZCk.js → radar-ZZBFDIW7-lopS8_4j.js} +2 -2
- package/dist/{range-Dh0_-r8P.js → range-BKaWvVUE.js} +8 -8
- package/dist/reduce-CqQo8ppc.js +275 -0
- package/dist/{requirementDiagram-UZGBJVZJ-DACHtrFr.js → requirementDiagram-UZGBJVZJ-BU7dwzFM.js} +9 -9
- package/dist/{sankeyDiagram-TZEHDZUN-Bzg7_UWs.js → sankeyDiagram-TZEHDZUN-BVJnR4_b.js} +2 -2
- package/dist/{sequenceDiagram-WL72ISMW-agybEe9J.js → sequenceDiagram-WL72ISMW-CQcFQTwX.js} +4 -4
- package/dist/{slides-component-B0yK5GXP.js → slides-component-DwvL_HJi.js} +2 -2
- package/dist/{spec-Dq_reDGM.js → spec-CbYkiXG3.js} +5 -5
- package/dist/{stateDiagram-FKZM4ZOC-DehQAt8g.js → stateDiagram-FKZM4ZOC-Dx9AIGDe.js} +12 -12
- package/dist/{stateDiagram-v2-4FDKWEC3-8VzeREl9.js → stateDiagram-v2-4FDKWEC3-BIeUs-Ed.js} +10 -10
- package/dist/style.css +1 -1
- package/dist/{timeline-definition-IT6M3QCI-CdCfdaCF.js → timeline-definition-IT6M3QCI-D8B3p7ID.js} +2 -2
- package/dist/{toNumber-By7s5JC_.js → toNumber-CbZ70FdN.js} +2 -2
- package/dist/{toString-Ckpb50uw.js → toString-DbIAWQpF.js} +2 -2
- package/dist/{tooltip-CL8m4f9y.js → tooltip-SPkubVH3.js} +3 -3
- package/dist/{treemap-GDKQZRPO-DRxfDG65.js → treemap-GDKQZRPO-CkR-5ai2.js} +2 -2
- package/dist/{types-BwnzGcE4.js → types-0FB-N7AA.js} +519 -408
- package/dist/{uniq-cCc07Q8K.js → uniq-H2E5nMLq.js} +1 -1
- package/dist/{useAsyncData-B4hMFGnF.js → useAsyncData-D7-oahg5.js} +1 -1
- package/dist/{useDeepCompareMemoize-DuPhOXzr.js → useDeepCompareMemoize-DLS-bHHT.js} +5 -5
- package/dist/{useIframeCapabilities-CAt6D2EI.js → useIframeCapabilities-DFGZKWkO.js} +1 -1
- package/dist/{useTheme-BNYQnvu-.js → useTheme-D0rdoMBF.js} +6 -5
- package/dist/{vega-component-DouPy8AI.js → vega-component-D2knjGgv.js} +10 -10
- package/dist/{xychartDiagram-PRI3JC2R-rEm_SIsC.js → xychartDiagram-PRI3JC2R-XO8FiQjU.js} +5 -5
- package/package.json +9 -9
- package/src/__mocks__/common.ts +41 -8
- package/src/__mocks__/requests.ts +1 -0
- package/src/components/app-config/ai-config.tsx +10 -0
- package/src/components/chat/__tests__/useFileState.test.tsx +2 -3
- package/src/components/chat/acp/__tests__/context-utils.test.ts +2 -6
- package/src/components/datasources/components.tsx +3 -6
- package/src/components/datasources/datasources.tsx +8 -21
- package/src/components/editor/__tests__/data-attributes.test.tsx +2 -11
- package/src/components/editor/actions/types.ts +6 -1
- package/src/components/editor/actions/useNotebookActions.tsx +50 -13
- package/src/components/editor/chrome/types.ts +17 -0
- package/src/components/editor/connections/add-connection-dialog.tsx +27 -2
- package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +105 -6
- package/src/components/editor/connections/database/__tests__/as-code.test.ts +101 -8
- package/src/components/editor/connections/database/as-code.ts +115 -25
- package/src/components/editor/connections/database/schemas.ts +49 -2
- package/src/components/editor/connections/storage/as-code.ts +1 -1
- package/src/components/editor/controls/command-palette.tsx +7 -0
- package/src/components/editor/controls/keyboard-shortcuts.tsx +3 -1
- package/src/components/editor/file-tree/__tests__/requesting-tree.test.ts +2 -3
- package/src/components/editor/file-tree/file-explorer.tsx +48 -62
- package/src/components/editor/file-tree/file-icons.tsx +132 -0
- package/src/components/editor/file-tree/file-viewer.tsx +1 -1
- package/src/components/editor/file-tree/tree-actions.tsx +107 -0
- package/src/components/editor/file-tree/types.ts +2 -96
- package/src/components/editor/header/filename-input.tsx +4 -1
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +2 -4
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +2 -12
- package/src/components/icons/marimo-icons.tsx +2 -2
- package/src/components/pages/home-page.tsx +5 -5
- package/src/components/storage/__tests__/storage-snippets.test.ts +253 -0
- package/src/components/storage/components.tsx +0 -38
- package/src/components/storage/storage-file-viewer.tsx +1 -1
- package/src/components/storage/storage-inspector.tsx +66 -51
- package/src/components/storage/storage-snippets.ts +67 -0
- package/src/components/ui/command.tsx +2 -0
- package/src/components/ui/links.tsx +1 -0
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +206 -0
- package/src/core/ai/tools/run-cells-tool.ts +75 -40
- package/src/core/cells/__tests__/cells.test.ts +62 -0
- package/src/core/cells/__tests__/session.test.ts +2 -7
- package/src/core/cells/cells.ts +25 -3
- package/src/core/cells/ids.ts +2 -1
- package/src/core/codemirror/compat/__tests__/jupyter.test.ts +2 -3
- package/src/core/codemirror/keymaps/vim.ts +32 -3
- package/src/core/codemirror/markdown/__tests__/commands.test.ts +2 -3
- package/src/core/config/__tests__/config-schema.test.ts +6 -2
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/config/feature-flag.tsx +1 -1
- package/src/core/dom/ui-element-constants.ts +15 -0
- package/src/core/dom/ui-element.ts +3 -2
- package/src/core/export/__tests__/hooks.test.ts +3 -10
- package/src/core/hotkeys/__tests__/hotkeys.test.ts +64 -1
- package/src/core/hotkeys/hotkeys.ts +29 -3
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/islands/components/web-components.tsx +2 -1
- package/src/core/network/__tests__/requests-network.test.ts +17 -0
- package/src/core/network/requests-lazy.ts +1 -0
- package/src/core/network/requests-network.ts +9 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.tsx +1 -0
- package/src/core/network/types.ts +1 -0
- package/src/core/runtime/__tests__/runtime.test.ts +2 -8
- package/src/core/storage/__tests__/state.test.ts +1 -0
- package/src/core/wasm/bridge.ts +1 -0
- package/src/core/websocket/useMarimoKernelConnection.tsx +2 -0
- package/src/plugins/impl/DataTablePlugin.tsx +53 -3
- package/src/plugins/impl/FileBrowserPlugin.tsx +8 -5
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +2 -11
- package/src/plugins/impl/__tests__/DropdownPlugin.test.tsx +2 -11
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +4 -1
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +309 -0
- package/src/plugins/impl/mpl-interactive/__tests__/mpl-websocket-shim.test.ts +110 -0
- package/src/plugins/impl/mpl-interactive/mpl-websocket-shim.ts +57 -0
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +8 -2
- package/src/plugins/plugins.ts +2 -0
- package/src/utils/__tests__/download.test.tsx +12 -14
- package/src/utils/__tests__/filenames.test.ts +7 -0
- package/src/utils/__tests__/smartMatch.test.ts +61 -0
- package/src/utils/filenames.ts +3 -0
- package/src/utils/smartMatch.ts +62 -0
- package/dist/_baseProperty-D1nWkRMz.js +0 -93
- package/dist/assets/__vite-browser-external-WSlCcXn_.js +0 -1
- package/dist/dist-BAeGo2rp.js +0 -5
- package/dist/dist-BqwCMSEa.js +0 -5
- package/dist/dist-Bum8FwTO.js +0 -6
- package/dist/dist-C0YiOwt_.js +0 -5
- package/dist/dist-C2uPv4iU.js +0 -5
- package/dist/dist-C5hOLsJN.js +0 -8
- package/dist/dist-C9NIAKMs.js +0 -8
- package/dist/dist-CCrzTtvk.js +0 -5
- package/dist/dist-CFS9i1rS.js +0 -8
- package/dist/dist-CyHZuhPH.js +0 -5
- package/dist/dist-CzcjWdIk.js +0 -6
- package/dist/dist-DaYyUSNC.js +0 -5
- package/dist/dist-DpDcJYNh.js +0 -8
- package/dist/dist-U_BfxcPn.js +0 -5
- package/dist/merge-CGQkMGzr.js +0 -51
- package/dist/reduce-BXFHs7IQ.js +0 -268
|
@@ -27,11 +27,13 @@ export interface Hotkey {
|
|
|
27
27
|
* @default true
|
|
28
28
|
*/
|
|
29
29
|
editable?: boolean;
|
|
30
|
+
additionalKeywords?: string[];
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
interface ResolvedHotkey {
|
|
33
34
|
name: string;
|
|
34
35
|
key: string;
|
|
36
|
+
additionalKeywords?: string[];
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
type ModKey = "Cmd" | "Ctrl";
|
|
@@ -110,6 +112,7 @@ const DEFAULT_HOT_KEY = {
|
|
|
110
112
|
name: "Run",
|
|
111
113
|
group: "Running Cells",
|
|
112
114
|
key: "Mod-Enter",
|
|
115
|
+
additionalKeywords: ["execute", "submit"],
|
|
113
116
|
},
|
|
114
117
|
"cell.runAndNewBelow": {
|
|
115
118
|
name: "Run and new below",
|
|
@@ -132,6 +135,7 @@ const DEFAULT_HOT_KEY = {
|
|
|
132
135
|
name: "Format cell",
|
|
133
136
|
group: "Editing",
|
|
134
137
|
key: "Mod-b",
|
|
138
|
+
additionalKeywords: ["lint"],
|
|
135
139
|
},
|
|
136
140
|
"cell.viewAsMarkdown": {
|
|
137
141
|
name: "View as Markdown",
|
|
@@ -201,6 +205,7 @@ const DEFAULT_HOT_KEY = {
|
|
|
201
205
|
name: "Delete cell",
|
|
202
206
|
group: "Editing",
|
|
203
207
|
key: "Shift-Backspace",
|
|
208
|
+
additionalKeywords: ["remove"],
|
|
204
209
|
},
|
|
205
210
|
"cell.hideCode": {
|
|
206
211
|
name: "Hide cell code",
|
|
@@ -320,6 +325,7 @@ const DEFAULT_HOT_KEY = {
|
|
|
320
325
|
name: "Save file",
|
|
321
326
|
group: "Other",
|
|
322
327
|
key: "Mod-s",
|
|
328
|
+
additionalKeywords: ["write", "persist"],
|
|
323
329
|
},
|
|
324
330
|
"global.commandPalette": {
|
|
325
331
|
name: "Show command palette",
|
|
@@ -485,23 +491,26 @@ export class HotkeyProvider implements IHotkeyProvider {
|
|
|
485
491
|
}
|
|
486
492
|
|
|
487
493
|
getHotkey(action: HotkeyAction): ResolvedHotkey {
|
|
488
|
-
const { name, key } = this.hotkeys[action];
|
|
494
|
+
const { name, key, additionalKeywords } = this.hotkeys[action];
|
|
489
495
|
if (typeof key === "string") {
|
|
490
496
|
return {
|
|
491
497
|
name,
|
|
492
498
|
key: key.replace("Mod", this.mod),
|
|
499
|
+
additionalKeywords,
|
|
493
500
|
};
|
|
494
501
|
}
|
|
495
502
|
if (key === NOT_SET) {
|
|
496
503
|
return {
|
|
497
504
|
name,
|
|
498
505
|
key: "",
|
|
506
|
+
additionalKeywords,
|
|
499
507
|
};
|
|
500
508
|
}
|
|
501
509
|
const platformKey = key[this.platform] || key.main;
|
|
502
510
|
return {
|
|
503
511
|
name,
|
|
504
512
|
key: platformKey.replace("Mod", this.mod),
|
|
513
|
+
additionalKeywords,
|
|
505
514
|
};
|
|
506
515
|
}
|
|
507
516
|
|
|
@@ -535,10 +544,27 @@ export class OverridingHotkeyProvider extends HotkeyProvider {
|
|
|
535
544
|
|
|
536
545
|
override getHotkey(action: HotkeyAction): ResolvedHotkey {
|
|
537
546
|
const base = super.getHotkey(action);
|
|
538
|
-
const
|
|
547
|
+
const override = this.overrides[action];
|
|
539
548
|
return {
|
|
540
549
|
name: base.name,
|
|
541
|
-
key,
|
|
550
|
+
key: override ? normalizeKeyString(override) : base.key,
|
|
551
|
+
additionalKeywords: base.additionalKeywords,
|
|
542
552
|
};
|
|
543
553
|
}
|
|
544
554
|
}
|
|
555
|
+
|
|
556
|
+
const MODIFIER_RE = /^(cmd|ctrl|alt|shift|meta|mod)$/i;
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Capitalize multi-character base key names so they match the
|
|
560
|
+
* casing that KeyboardEvent.key (and therefore CodeMirror) uses.
|
|
561
|
+
* e.g. "Shift-enter" → "Shift-Enter", "Cmd-backspace" → "Cmd-Backspace"
|
|
562
|
+
*/
|
|
563
|
+
export function normalizeKeyString(key: string): string {
|
|
564
|
+
const parts = key.split("-");
|
|
565
|
+
const last = parts[parts.length - 1];
|
|
566
|
+
if (last.length > 1 && !MODIFIER_RE.test(last)) {
|
|
567
|
+
parts[parts.length - 1] = last.charAt(0).toUpperCase() + last.slice(1);
|
|
568
|
+
}
|
|
569
|
+
return parts.join("-");
|
|
570
|
+
}
|
|
@@ -181,6 +181,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
|
181
181
|
sendFileDetails = throwNotImplemented;
|
|
182
182
|
openTutorial = throwNotImplemented;
|
|
183
183
|
exportAsHTML = throwNotImplemented;
|
|
184
|
+
exportAsIPYNB = throwNotImplemented;
|
|
184
185
|
exportAsMarkdown = throwNotImplemented;
|
|
185
186
|
exportAsPDF = throwNotImplemented;
|
|
186
187
|
autoExportAsHTML = throwNotImplemented;
|
|
@@ -6,6 +6,7 @@ import ReactDOM, { type Root } from "react-dom/client";
|
|
|
6
6
|
import { ErrorBoundary } from "@/components/editor/boundary/ErrorBoundary";
|
|
7
7
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
8
8
|
import { notebookAtom } from "@/core/cells/cells";
|
|
9
|
+
import { OBJECT_ID_ATTR } from "@/core/dom/ui-element-constants";
|
|
9
10
|
import { UI_ELEMENT_REGISTRY } from "@/core/dom/uiregistry";
|
|
10
11
|
import { LocaleProvider } from "@/core/i18n/locale-provider";
|
|
11
12
|
import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
@@ -60,7 +61,7 @@ export class MarimoIslandElement extends HTMLElement {
|
|
|
60
61
|
const codeCallback: () => string = optionalEditor
|
|
61
62
|
? () =>
|
|
62
63
|
`${UI_ELEMENT_REGISTRY.lookupValue(
|
|
63
|
-
optionalEditor.props[
|
|
64
|
+
optionalEditor.props[OBJECT_ID_ATTR],
|
|
64
65
|
)}`
|
|
65
66
|
: () => code;
|
|
66
67
|
|
|
@@ -113,5 +113,22 @@ describe("createNetworkRequests", () => {
|
|
|
113
113
|
}),
|
|
114
114
|
);
|
|
115
115
|
});
|
|
116
|
+
|
|
117
|
+
it("exportAsIPYNB should call the new endpoint as text", async () => {
|
|
118
|
+
const requests = createNetworkRequests();
|
|
119
|
+
await requests.exportAsIPYNB({
|
|
120
|
+
download: false,
|
|
121
|
+
} as any);
|
|
122
|
+
|
|
123
|
+
expect(mockClient.POST).toHaveBeenCalledWith(
|
|
124
|
+
"/api/export/ipynb",
|
|
125
|
+
expect.objectContaining({
|
|
126
|
+
body: expect.objectContaining({
|
|
127
|
+
download: false,
|
|
128
|
+
}),
|
|
129
|
+
parseAs: "text",
|
|
130
|
+
}),
|
|
131
|
+
);
|
|
132
|
+
});
|
|
116
133
|
});
|
|
117
134
|
});
|
|
@@ -49,6 +49,7 @@ const ACTIONS: Record<keyof AllRequests, Action> = {
|
|
|
49
49
|
|
|
50
50
|
// Export operations start a connection
|
|
51
51
|
exportAsHTML: "startConnection",
|
|
52
|
+
exportAsIPYNB: "startConnection",
|
|
52
53
|
exportAsMarkdown: "startConnection",
|
|
53
54
|
exportAsPDF: "startConnection",
|
|
54
55
|
readCode: "startConnection",
|
|
@@ -381,6 +381,15 @@ export function createNetworkRequests(): EditRequests & RunRequests {
|
|
|
381
381
|
})
|
|
382
382
|
.then(handleResponse);
|
|
383
383
|
},
|
|
384
|
+
exportAsIPYNB: async (request) => {
|
|
385
|
+
return getClient()
|
|
386
|
+
.POST("/api/export/ipynb", {
|
|
387
|
+
body: request,
|
|
388
|
+
parseAs: "text",
|
|
389
|
+
params: getParams(),
|
|
390
|
+
})
|
|
391
|
+
.then(handleResponse);
|
|
392
|
+
},
|
|
384
393
|
exportAsPDF: async (request) => {
|
|
385
394
|
return getClient()
|
|
386
395
|
.POST("/api/export/pdf", {
|
|
@@ -75,6 +75,7 @@ export function createStaticRequests(): EditRequests & RunRequests {
|
|
|
75
75
|
getRunningNotebooks: throwNotInEditMode,
|
|
76
76
|
shutdownSession: throwNotInEditMode,
|
|
77
77
|
exportAsHTML: throwNotInEditMode,
|
|
78
|
+
exportAsIPYNB: throwNotInEditMode,
|
|
78
79
|
exportAsMarkdown: throwNotInEditMode,
|
|
79
80
|
exportAsPDF: throwNotInEditMode,
|
|
80
81
|
autoExportAsHTML: throwNotInEditMode,
|
|
@@ -60,6 +60,7 @@ export function createErrorToastingRequests(
|
|
|
60
60
|
getRunningNotebooks: "Failed to get running notebooks",
|
|
61
61
|
shutdownSession: "Failed to shutdown session",
|
|
62
62
|
exportAsHTML: "Failed to export HTML",
|
|
63
|
+
exportAsIPYNB: "Failed to export ipynb",
|
|
63
64
|
exportAsMarkdown: "Failed to export Markdown",
|
|
64
65
|
exportAsPDF: "Failed to export PDF",
|
|
65
66
|
autoExportAsHTML: "", // No toast
|
|
@@ -180,6 +180,7 @@ export interface EditRequests {
|
|
|
180
180
|
) => Promise<RunningNotebooksResponse>;
|
|
181
181
|
// Export requests
|
|
182
182
|
exportAsHTML: (request: ExportAsHTMLRequest) => Promise<string>;
|
|
183
|
+
exportAsIPYNB: (request: ExportAsIPYNBRequest) => Promise<string>;
|
|
183
184
|
exportAsMarkdown: (request: ExportAsMarkdownRequest) => Promise<string>;
|
|
184
185
|
exportAsPDF: (request: ExportAsPDFRequest) => Promise<Blob>;
|
|
185
186
|
autoExportAsHTML: (request: ExportAsHTMLRequest) => Promise<null>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { Mocks } from "@/__mocks__/common";
|
|
4
5
|
import type { SessionId } from "@/core/kernel/session";
|
|
5
6
|
import { Logger } from "@/utils/Logger";
|
|
6
7
|
import { RuntimeManager } from "../runtime";
|
|
@@ -11,14 +12,7 @@ vi.mock("@/core/kernel/session", () => ({
|
|
|
11
12
|
getSessionId: () => "test-session-id" as SessionId,
|
|
12
13
|
}));
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
vi.mock("@/utils/Logger", () => ({
|
|
16
|
-
Logger: {
|
|
17
|
-
debug: vi.fn(),
|
|
18
|
-
error: vi.fn(),
|
|
19
|
-
warn: vi.fn(),
|
|
20
|
-
},
|
|
21
|
-
}));
|
|
15
|
+
vi.mock("@/utils/Logger", () => ({ Logger: Mocks.quietLogger() }));
|
|
22
16
|
|
|
23
17
|
describe("RuntimeManager", () => {
|
|
24
18
|
const mockConfig: RuntimeConfig = {
|
|
@@ -10,6 +10,7 @@ function makeNamespace(
|
|
|
10
10
|
overrides: Partial<StorageNamespace> & { name: string },
|
|
11
11
|
): StorageNamespace {
|
|
12
12
|
return {
|
|
13
|
+
backendType: overrides.backendType ?? "obstore",
|
|
13
14
|
displayName: overrides.displayName ?? overrides.name,
|
|
14
15
|
name: overrides.name,
|
|
15
16
|
protocol: overrides.protocol ?? "s3",
|
package/src/core/wasm/bridge.ts
CHANGED
|
@@ -587,6 +587,7 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
587
587
|
getWorkspaceFiles = throwNotImplemented;
|
|
588
588
|
getRunningNotebooks = throwNotImplemented;
|
|
589
589
|
shutdownSession = throwNotImplemented;
|
|
590
|
+
exportAsIPYNB = throwNotImplemented;
|
|
590
591
|
exportAsPDF = throwNotImplemented;
|
|
591
592
|
autoExportAsHTML = throwNotImplemented;
|
|
592
593
|
autoExportAsMarkdown = throwNotImplemented;
|
|
@@ -317,6 +317,8 @@ export function useMarimoKernelConnection(opts: {
|
|
|
317
317
|
codes: msg.data.codes,
|
|
318
318
|
ids: msg.data.cell_ids as CellId[],
|
|
319
319
|
codeIsStale: msg.data.code_is_stale,
|
|
320
|
+
names: msg.data.names,
|
|
321
|
+
configs: msg.data.configs,
|
|
320
322
|
});
|
|
321
323
|
return;
|
|
322
324
|
case "update-cell-ids":
|
|
@@ -60,7 +60,11 @@ import { ContextAwarePanelItem } from "@/components/editor/chrome/panels/context
|
|
|
60
60
|
import { Alert, AlertTitle } from "@/components/ui/alert";
|
|
61
61
|
import { Button } from "@/components/ui/button";
|
|
62
62
|
import { DelayMount } from "@/components/utils/delay-mount";
|
|
63
|
-
import { type CellId, findCellId } from "@/core/cells/ids";
|
|
63
|
+
import { type CellId, findCellId, UIElementId } from "@/core/cells/ids";
|
|
64
|
+
import {
|
|
65
|
+
OBJECT_ID_ATTR,
|
|
66
|
+
RANDOM_ID_ATTR,
|
|
67
|
+
} from "@/core/dom/ui-element-constants";
|
|
64
68
|
import { slotsController } from "@/core/slots/slots";
|
|
65
69
|
import { store } from "@/core/state/jotai";
|
|
66
70
|
import { isStaticNotebook } from "@/core/static/static-state";
|
|
@@ -361,6 +365,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
361
365
|
<LazyDataTableComponent
|
|
362
366
|
isLazy={props.data.lazy}
|
|
363
367
|
preload={props.data.preload}
|
|
368
|
+
host={props.host}
|
|
364
369
|
>
|
|
365
370
|
<LoadingDataTableComponent
|
|
366
371
|
{...props.data}
|
|
@@ -377,21 +382,66 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
377
382
|
);
|
|
378
383
|
});
|
|
379
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Tracks which lazy tables have been previewed across remounts (e.g. tab switches).
|
|
387
|
+
* Keyed by uiElementId (stable across remounts) with randomId as value
|
|
388
|
+
* (changes on cell re-execution, so stale entries are naturally invalidated).
|
|
389
|
+
*/
|
|
390
|
+
const previewedTables = new Map<UIElementId, string>();
|
|
391
|
+
|
|
392
|
+
function wasTablePreviewed(
|
|
393
|
+
uiElementId: UIElementId | null | undefined,
|
|
394
|
+
randomId: string | null | undefined,
|
|
395
|
+
): boolean {
|
|
396
|
+
return (
|
|
397
|
+
uiElementId != null &&
|
|
398
|
+
randomId != null &&
|
|
399
|
+
previewedTables.get(uiElementId) === randomId
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function markTablePreviewed(
|
|
404
|
+
uiElementId: UIElementId | null | undefined,
|
|
405
|
+
randomId: string | null | undefined,
|
|
406
|
+
): void {
|
|
407
|
+
if (uiElementId != null && randomId != null) {
|
|
408
|
+
previewedTables.set(uiElementId, randomId);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
380
412
|
const LazyDataTableComponent = ({
|
|
381
413
|
isLazy: initialIsLazy,
|
|
382
414
|
children,
|
|
383
415
|
preload,
|
|
416
|
+
host,
|
|
384
417
|
}: {
|
|
385
418
|
isLazy: boolean;
|
|
386
419
|
children: React.ReactNode;
|
|
387
420
|
preload: boolean;
|
|
421
|
+
host: HTMLElement;
|
|
388
422
|
}) => {
|
|
389
|
-
const
|
|
423
|
+
const parentElement = host.closest(`[${OBJECT_ID_ATTR}]`);
|
|
424
|
+
const uiElementId = parentElement ? UIElementId.parse(parentElement) : null;
|
|
425
|
+
|
|
426
|
+
const randomId = host
|
|
427
|
+
.closest(`[${RANDOM_ID_ATTR}]`)
|
|
428
|
+
?.getAttribute(RANDOM_ID_ATTR);
|
|
429
|
+
|
|
430
|
+
const [isLazy, setIsLazy] = useState(
|
|
431
|
+
initialIsLazy && !preload && !wasTablePreviewed(uiElementId, randomId),
|
|
432
|
+
);
|
|
390
433
|
|
|
391
434
|
if (isLazy) {
|
|
392
435
|
return (
|
|
393
436
|
<div className="flex h-20 items-center justify-center">
|
|
394
|
-
<Button
|
|
437
|
+
<Button
|
|
438
|
+
variant="outline"
|
|
439
|
+
size="xs"
|
|
440
|
+
onClick={() => {
|
|
441
|
+
markTablePreviewed(uiElementId, randomId);
|
|
442
|
+
setIsLazy(false);
|
|
443
|
+
}}
|
|
444
|
+
>
|
|
395
445
|
<Table2Icon className="mr-2 h-4 w-4" />
|
|
396
446
|
Preview data
|
|
397
447
|
</Button>
|
|
@@ -4,10 +4,10 @@ import { CornerLeftUp } from "lucide-react";
|
|
|
4
4
|
import { type JSX, useEffect, useState } from "react";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import {
|
|
7
|
-
FILE_TYPE_ICONS,
|
|
8
|
-
type FileType,
|
|
9
|
-
guessFileType,
|
|
10
|
-
} from "@/components/editor/file-tree/
|
|
7
|
+
FILE_ICON as FILE_TYPE_ICONS,
|
|
8
|
+
type FileIconType as FileType,
|
|
9
|
+
guessFileIconType as guessFileType,
|
|
10
|
+
} from "@/components/editor/file-tree/file-icons";
|
|
11
11
|
import { Spinner } from "@/components/icons/spinner";
|
|
12
12
|
import { Button } from "@/components/ui/button";
|
|
13
13
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
@@ -15,6 +15,7 @@ import { Label } from "@/components/ui/label";
|
|
|
15
15
|
import { NativeSelect } from "@/components/ui/native-select";
|
|
16
16
|
import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table";
|
|
17
17
|
import { toast } from "@/components/ui/use-toast";
|
|
18
|
+
import { RANDOM_ID_ATTR } from "@/core/dom/ui-element-constants";
|
|
18
19
|
import { useAsyncData } from "@/hooks/useAsyncData";
|
|
19
20
|
import { useInternalStateWithSync } from "@/hooks/useInternalStateWithSync";
|
|
20
21
|
import { cn } from "@/utils/cn";
|
|
@@ -150,7 +151,9 @@ export const FileBrowser = ({
|
|
|
150
151
|
|
|
151
152
|
// HACK: use the random-id of the host element to force a re-render
|
|
152
153
|
// when the random-id changes, this means the cell was re-rendered
|
|
153
|
-
const randomId = host
|
|
154
|
+
const randomId = host
|
|
155
|
+
.closest(`[${RANDOM_ID_ATTR}]`)
|
|
156
|
+
?.getAttribute(RANDOM_ID_ATTR);
|
|
154
157
|
|
|
155
158
|
const { data, error, isPending } = useAsyncData(() => {
|
|
156
159
|
return list_directory({ path: path });
|
|
@@ -4,6 +4,7 @@ import { TooltipProvider } from "@radix-ui/react-tooltip";
|
|
|
4
4
|
import { act, render, screen, waitFor } from "@testing-library/react";
|
|
5
5
|
import { Provider } from "jotai";
|
|
6
6
|
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
7
|
+
import { SetupMocks } from "@/__mocks__/common";
|
|
7
8
|
import type { DownloadAsArgs } from "@/components/data-table/schemas";
|
|
8
9
|
import type { FieldTypesWithExternalType } from "@/components/data-table/types";
|
|
9
10
|
import { store } from "@/core/state/jotai";
|
|
@@ -14,17 +15,7 @@ import {
|
|
|
14
15
|
} from "../DataTablePlugin";
|
|
15
16
|
|
|
16
17
|
beforeAll(() => {
|
|
17
|
-
|
|
18
|
-
observe() {
|
|
19
|
-
// do nothing
|
|
20
|
-
}
|
|
21
|
-
unobserve() {
|
|
22
|
-
// do nothing
|
|
23
|
-
}
|
|
24
|
-
disconnect() {
|
|
25
|
-
// do nothing
|
|
26
|
-
}
|
|
27
|
-
};
|
|
18
|
+
SetupMocks.resizeObserver();
|
|
28
19
|
});
|
|
29
20
|
|
|
30
21
|
describe("LoadingDataTableComponent", () => {
|
|
@@ -3,23 +3,14 @@
|
|
|
3
3
|
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
4
|
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
5
5
|
import type { z } from "zod";
|
|
6
|
+
import { SetupMocks } from "@/__mocks__/common";
|
|
6
7
|
import { initialModeAtom } from "@/core/mode";
|
|
7
8
|
import { store } from "@/core/state/jotai";
|
|
8
9
|
import type { IPluginProps } from "../../types";
|
|
9
10
|
import { DropdownPlugin } from "../DropdownPlugin";
|
|
10
11
|
|
|
11
12
|
beforeAll(() => {
|
|
12
|
-
|
|
13
|
-
observe() {
|
|
14
|
-
// do nothing
|
|
15
|
-
}
|
|
16
|
-
unobserve() {
|
|
17
|
-
// do nothing
|
|
18
|
-
}
|
|
19
|
-
disconnect() {
|
|
20
|
-
// do nothing
|
|
21
|
-
}
|
|
22
|
-
};
|
|
13
|
+
SetupMocks.resizeObserver();
|
|
23
14
|
global.HTMLDivElement.prototype.scrollIntoView = () => {
|
|
24
15
|
// do nothing
|
|
25
16
|
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { AnyWidget } from "@anywidget/types";
|
|
5
5
|
import { useEffect, useRef } from "react";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
import { RANDOM_ID_ATTR } from "@/core/dom/ui-element-constants";
|
|
7
8
|
import { useAsyncData } from "@/hooks/useAsyncData";
|
|
8
9
|
import type { HTMLElementNotDerivedFromRef } from "@/hooks/useEventListener";
|
|
9
10
|
import { createPlugin } from "@/plugins/core/builder";
|
|
@@ -145,7 +146,9 @@ const AnyWidgetSlot = (props: IPluginProps<ModelIdRef, Data>) => {
|
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
// Find the closest parent element with an attribute of `random-id`
|
|
148
|
-
const randomId = props.host
|
|
149
|
+
const randomId = props.host
|
|
150
|
+
.closest(`[${RANDOM_ID_ATTR}]`)
|
|
151
|
+
?.getAttribute(RANDOM_ID_ATTR);
|
|
149
152
|
const key = randomId ?? jsUrl;
|
|
150
153
|
|
|
151
154
|
return (
|