From c44cdb0bc0bfdb5ffcdbf24f84acef6fc5d8aeb9 Mon Sep 17 00:00:00 2001 From: ZHUO Xu Date: Thu, 29 Aug 2024 15:16:29 +0800 Subject: [PATCH] Collection of SecretNote Improvement (until 0829) (#57) * feat: baseline version * feat: add about bar * feat: stable node color for same name * feat: add metrics panel * feat: support metrics monitoring of nodes * feat: add more docs * feat: support get versions * feat: misc changes * feat: add more comments * fix: clear outputarea when restart kernel * feat: more node info and supports LSP * feat: use customized drive to take over contents manager's * feat: make customized drive simple * fix: download notebook file * refactor: format all * feat: support ws auth in lsp connection * fix: format all * fix: encode token * feat: support file viewing when no kernel is available * fix: top toolbar run is invalid * feat: use markdown to render welcome docs * feat: toolbar run button and show loading when uploading * fix: the time sequence of defaultServerManager's launch * chore: misc changes to the toolchain * feat: correct file path for new drive and add busy status for file list * fix: stream stderr being missing * fix: rename welcome * fix: sanitize code * chore: sanitize deps * fix: remove debug settings * refactor: format all * chore: optimize packaging --- docker/app/Dockerfile | 1 + packages/secretnote-lite/.gitignore | 2 + packages/secretnote-lite/package.json | 31 +- packages/secretnote-lite/react-shim.js | 2 + .../src/components/dropdown-menu/index.less | 2 +- .../src/components/dropdown-menu/index.tsx | 4 +- .../markdown-editor/extensions/index.tsx | 7 +- .../src/components/ribbon/index.tsx | 2 +- packages/secretnote-lite/src/index.tsx | 10 +- .../src/lang/bundle.l10n.en-US.json | 4 +- .../src/lang/bundle.l10n.zh-CN.json | 4 +- packages/secretnote-lite/src/lang/index.ts | 17 +- .../src/modules/editor/cell/view.tsx | 134 +- .../editor/contents/contents-contrib.ts | 17 +- .../src/modules/editor/model.ts | 83 +- .../src/modules/editor/module.ts | 1 + .../src/modules/editor/output/outputarea.tsx | 124 +- .../src/modules/editor/workspace.ts | 21 +- .../src/modules/file/extra-view.tsx | 1 - .../src/modules/file/module.ts | 9 +- .../src/modules/file/preview-view.tsx | 10 +- .../{ => preview}/csv-preview-contrib.tsx | 4 +- .../{ => preview}/jsonl-preview-contrib.tsx | 3 +- .../{ => preview}/log-preview-contrib.tsx | 2 +- .../src/modules/file/service.ts | 22 +- .../secretnote-lite/src/modules/file/view.tsx | 71 +- .../src/modules/kernel/kernel-connection.ts | 58 + .../src/modules/kernel/kernel-manager.ts | 99 +- .../src/modules/kernel/module.ts | 20 + .../src/modules/layout/index.less | 16 +- .../src/modules/layout/module.ts | 9 +- .../src/modules/layout/sidebar.tsx | 79 +- .../src/modules/markdown-editor/module.ts | 2 + .../src/modules/markdown-editor/view.tsx | 2 +- .../src/modules/metrics/index.less | 24 + .../src/modules/metrics/index.ts | 1 + .../src/modules/metrics/module.ts | 17 + .../src/modules/metrics/service.ts | 207 +++ .../src/modules/metrics/view.tsx | 72 + .../src/modules/node/index.less | 17 +- .../src/modules/node/module.ts | 3 +- .../src/modules/node/service.ts | 66 +- .../secretnote-lite/src/modules/node/view.tsx | 263 ++- .../src/modules/notebook/drive.ts | 102 ++ .../src/modules/notebook/editor-view.tsx | 11 +- .../src/modules/notebook/index.less | 3 +- .../src/modules/notebook/module.ts | 2 + .../src/modules/notebook/service.ts | 250 ++- .../src/modules/notebook/view.tsx | 35 +- .../modules/server/language-client-manager.ts | 27 + .../src/modules/server/module.ts | 2 + .../src/modules/server/protocol.ts | 9 +- .../src/modules/server/server-manager.ts | 211 +-- .../src/modules/toolbar/index.less | 12 + .../modules/toolbar/side-toolbar-run-item.tsx | 28 +- .../src/modules/toolbar/toolbar-contrib.ts | 21 +- .../modules/toolbar/top-toolbar-run-item.tsx | 79 + .../src/modules/welcome/index.less | 81 +- .../src/modules/welcome/view.tsx | 279 +--- .../src/modules/welcome/welcome.md | 51 + packages/secretnote-lite/src/utils/color.ts | 19 +- packages/secretnote-lite/src/utils/error.ts | 31 + packages/secretnote-lite/src/utils/file.ts | 32 +- packages/secretnote-lite/src/utils/index.ts | 7 +- packages/secretnote-lite/src/utils/request.ts | 150 +- packages/secretnote-lite/src/utils/string.ts | 61 +- packages/secretnote-lite/tsconfig.json | 8 +- packages/secretnote-lite/tsup.config.js | 16 +- pnpm-lock.yaml | 1415 +++++++++++++++-- pyprojects/secretnote/.jupyter/config_dev.py | 26 +- 70 files changed, 3321 insertions(+), 1190 deletions(-) create mode 100644 packages/secretnote-lite/.gitignore create mode 100644 packages/secretnote-lite/react-shim.js rename packages/secretnote-lite/src/modules/file/{ => preview}/csv-preview-contrib.tsx (95%) rename packages/secretnote-lite/src/modules/file/{ => preview}/jsonl-preview-contrib.tsx (93%) rename packages/secretnote-lite/src/modules/file/{ => preview}/log-preview-contrib.tsx (86%) create mode 100644 packages/secretnote-lite/src/modules/kernel/kernel-connection.ts create mode 100644 packages/secretnote-lite/src/modules/metrics/index.less create mode 100644 packages/secretnote-lite/src/modules/metrics/index.ts create mode 100644 packages/secretnote-lite/src/modules/metrics/module.ts create mode 100644 packages/secretnote-lite/src/modules/metrics/service.ts create mode 100644 packages/secretnote-lite/src/modules/metrics/view.tsx create mode 100644 packages/secretnote-lite/src/modules/notebook/drive.ts create mode 100644 packages/secretnote-lite/src/modules/server/language-client-manager.ts create mode 100644 packages/secretnote-lite/src/modules/toolbar/top-toolbar-run-item.tsx create mode 100644 packages/secretnote-lite/src/modules/welcome/welcome.md create mode 100644 packages/secretnote-lite/src/utils/error.ts diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile index 14f8429c..2d6e878a 100644 --- a/docker/app/Dockerfile +++ b/docker/app/Dockerfile @@ -40,6 +40,7 @@ RUN npm config set registry https://registry.npmmirror.com RUN npm install @difizen/libro-analyzer COPY --from=build /dist /dist +RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ RUN pip install /dist/pyprojects/secretnote/dist/*.whl WORKDIR /home/secretnote diff --git a/packages/secretnote-lite/.gitignore b/packages/secretnote-lite/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/packages/secretnote-lite/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/packages/secretnote-lite/package.json b/packages/secretnote-lite/package.json index 3d24cf1d..196bc8c7 100644 --- a/packages/secretnote-lite/package.json +++ b/packages/secretnote-lite/package.json @@ -1,6 +1,6 @@ { "name": "@alipay/secretnote-lite", - "version": "0.0.34", + "version": "0.0.42", "license": "Apache-2.0", "author": "vectorse@126.com", "repository": "https://github.com/secretflow/secretnote/tree/main/packages/secretnote", @@ -9,12 +9,12 @@ "dist", "src" ], - "main": "dist/index.cjs.js", - "module": "dist/index.esm.js", - "types": "dist/typing/index.d.ts", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", "scripts": { "setup": "tsup src/index.tsx", - "build": "tsup src/index.tsx", + "build": "tsup src/index.tsx --inject ./react-shim.js", "dev": "tsup src/index.tsx --watch", "lint:eslint": "eslint src", "lint:stylelint": "stylelint 'src/**/*.{css,less}'", @@ -22,12 +22,14 @@ }, "dependencies": { "@antv/s2": "^1.52.0", - "@difizen/libro-jupyter": "^0.1.22", - "@difizen/mana-app": "^0.1.10", - "@difizen/mana-common": "^0.1.10", - "@difizen/mana-l10n": "^0.1.10", - "@difizen/mana-react": "^0.1.10", + "@difizen/libro-jupyter": "^0.2.20", + "@difizen/libro-language-client": "^0.2.20", + "@difizen/mana-app": "^0.1.19", + "@difizen/mana-common": "^0.1.19", + "@difizen/mana-l10n": "^0.1.19", + "@difizen/mana-react": "^0.1.19", "@kanaries/web-data-loader": "^0.1.7", + "@lumino/polling": "^2.1.3", "@tiptap/core": "^2.1.11", "@tiptap/extension-color": "^2.1.11", "@tiptap/extension-highlight": "^2.1.11", @@ -43,11 +45,13 @@ "@tiptap/starter-kit": "^2.1.11", "@tiptap/suggestion": "^2.1.11", "ahooks": "^3.7.8", + "canvas-confetti": "^1.9.0", "classnames": "^2.3.2", "d3-dsv": "^3.0.1", "highlight.js": "^11.9.0", "lodash-es": "^4.17.21", "lucide-react": "^0.284.0", + "markdown-it": "^14.1.0", "monaco-editor": "^0.45.0", "monaco-editor-webpack-plugin": "^7.1.0", "styled-components": "^6.1.0", @@ -57,8 +61,7 @@ "xterm-addon-canvas": "^0.5.0", "xterm-addon-fit": "^0.8.0", "xterm-addon-search": "^0.13.0", - "xterm-addon-web-links": "^0.9.0", - "canvas-confetti": "^1.9.0" + "xterm-addon-web-links": "^0.9.0" }, "peerDependencies": { "antd": "^5.10.1", @@ -71,7 +74,9 @@ "@types/react": "^18.2.28", "@types/react-dom": "^18.2.13", "colorette": "^2.0.19", - "esbuild-plugin-svgr": "^1.1.0" + "esbuild-plugin-svgr": "^1.1.0", + "tsup": "^8.2.4", + "typescript": "^5.5.4" }, "publishConfig": { "registry": "https://registry.antgroup-inc.cn" diff --git a/packages/secretnote-lite/react-shim.js b/packages/secretnote-lite/react-shim.js new file mode 100644 index 00000000..e76c207d --- /dev/null +++ b/packages/secretnote-lite/react-shim.js @@ -0,0 +1,2 @@ +import React from 'react'; +export { React }; diff --git a/packages/secretnote-lite/src/components/dropdown-menu/index.less b/packages/secretnote-lite/src/components/dropdown-menu/index.less index 5189b430..83b239db 100644 --- a/packages/secretnote-lite/src/components/dropdown-menu/index.less +++ b/packages/secretnote-lite/src/components/dropdown-menu/index.less @@ -10,7 +10,7 @@ .ant-dropdown-menu-item { padding: 4px 8px; border-radius: 0; - font-size: 12px; + font-size: 13px; font-weight: 400; .ant-dropdown-menu-item-icon { diff --git a/packages/secretnote-lite/src/components/dropdown-menu/index.tsx b/packages/secretnote-lite/src/components/dropdown-menu/index.tsx index 114552c5..2c1df5bd 100644 --- a/packages/secretnote-lite/src/components/dropdown-menu/index.tsx +++ b/packages/secretnote-lite/src/components/dropdown-menu/index.tsx @@ -11,10 +11,11 @@ interface IProps { onClick?: (key: string) => void; trigger?: ('click' | 'hover' | 'contextMenu')[]; icon?: React.ReactNode; + disabled?: boolean; } function DropdownMenu(props: IProps) { - const { items, onClick, icon, trigger } = props; + const { items, onClick, icon, trigger, disabled } = props; if (items.length === 0) { return null; @@ -34,6 +35,7 @@ function DropdownMenu(props: IProps) { }} overlayClassName="secretnote-dropdown-menu" trigger={trigger || ['click']} + disabled={disabled} > e.stopPropagation()}> {icon ? icon : } diff --git a/packages/secretnote-lite/src/components/markdown-editor/extensions/index.tsx b/packages/secretnote-lite/src/components/markdown-editor/extensions/index.tsx index fbeb5911..5f2f6a1e 100644 --- a/packages/secretnote-lite/src/components/markdown-editor/extensions/index.tsx +++ b/packages/secretnote-lite/src/components/markdown-editor/extensions/index.tsx @@ -1,3 +1,4 @@ +import { l10n } from '@difizen/mana-l10n'; import { InputRule } from '@tiptap/core'; import { Color } from '@tiptap/extension-color'; import { Highlight } from '@tiptap/extension-highlight'; @@ -9,9 +10,7 @@ import { TaskList } from '@tiptap/extension-task-list'; import { TextStyle } from '@tiptap/extension-text-style'; import TiptapUnderline from '@tiptap/extension-underline'; import { StarterKit } from '@tiptap/starter-kit'; -import React from 'react'; import { Markdown } from 'tiptap-markdown'; - import SlashCommand from './slash-command'; export const defaultExtensions = [ @@ -88,9 +87,9 @@ export const defaultExtensions = [ Placeholder.configure({ placeholder: ({ node }) => { if (node.type.name === 'heading') { - return `Heading ${node.attrs.level}`; + return `标题 ${node.attrs.level}`; } - return "Press '/' for commands"; + return l10n.t('键入 / 查看更多命令'); }, includeChildren: true, }), diff --git a/packages/secretnote-lite/src/components/ribbon/index.tsx b/packages/secretnote-lite/src/components/ribbon/index.tsx index 95819cba..bd2a71b0 100644 --- a/packages/secretnote-lite/src/components/ribbon/index.tsx +++ b/packages/secretnote-lite/src/components/ribbon/index.tsx @@ -25,7 +25,7 @@ function Ribbon(props: RibbonProps) { const getLabel = (values: string[]) => { const filterItems = items.filter((item) => values.includes(item.key)); if (filterItems.length === 0) { - return 'Select Nodes'; + return l10n.t('选择执行节点...'); } return filterItems.map((item) => item.label).join(','); }; diff --git a/packages/secretnote-lite/src/index.tsx b/packages/secretnote-lite/src/index.tsx index 6e6b3d7f..ebaf95d7 100644 --- a/packages/secretnote-lite/src/index.tsx +++ b/packages/secretnote-lite/src/index.tsx @@ -1,6 +1,6 @@ import '@/lang'; import { ManaAppPreset, ManaComponents } from '@difizen/mana-app'; -import React from 'react'; +import { message } from 'antd'; import { EditorModule } from '@/modules/editor'; import { FileModule } from '@/modules/file'; @@ -12,6 +12,7 @@ import { StorageModule } from '@/modules/storage'; import { ThemeModule } from '@/modules/theme'; import { ToolbarModule } from '@/modules/toolbar'; import { WelcomeModule } from '@/modules/welcome'; +import { MetricsModule } from './modules/metrics'; import './override.less'; const App = (): JSX.Element => { @@ -25,6 +26,7 @@ const App = (): JSX.Element => { ThemeModule, StorageModule, EditorModule, + MetricsModule, NodeModule, NotebookModule, FileModule, @@ -32,6 +34,12 @@ const App = (): JSX.Element => { ToolbarModule, WelcomeModule, ]} + onReady={() => { + // do some initialization + message.config({ + maxCount: 1, + }); + }} /> ); }; diff --git a/packages/secretnote-lite/src/lang/bundle.l10n.en-US.json b/packages/secretnote-lite/src/lang/bundle.l10n.en-US.json index c53ffca3..599e7842 100644 --- a/packages/secretnote-lite/src/lang/bundle.l10n.en-US.json +++ b/packages/secretnote-lite/src/lang/bundle.l10n.en-US.json @@ -196,7 +196,7 @@ "运行 Cell": "Run Cell", "运行上方所有 Cell": "Run all cells above", "运行当前及下方所有 Cell": "Run the current and all cells below", - "kernel准备中,无法执行": "kernel preparation, unable to execute", + "Kernel 准备中,无法执行": "Kernel preparation, unable to execute", "运行当前Cell": "Run the current Cell", "运行全部": "Run all", "运行之前所有cell": "All cells before running", @@ -320,4 +320,4 @@ "类型": "Type", "请选择节点类型": "Please select a node type", "通用": "Common" -} +} \ No newline at end of file diff --git a/packages/secretnote-lite/src/lang/bundle.l10n.zh-CN.json b/packages/secretnote-lite/src/lang/bundle.l10n.zh-CN.json index b83fdc0e..8006abe1 100644 --- a/packages/secretnote-lite/src/lang/bundle.l10n.zh-CN.json +++ b/packages/secretnote-lite/src/lang/bundle.l10n.zh-CN.json @@ -196,7 +196,7 @@ "运行 Cell": "运行 Cell", "运行上方所有 Cell": "运行上方所有 Cell", "运行当前及下方所有 Cell": "运行当前及下方所有 Cell", - "kernel准备中,无法执行": "kernel准备中,无法执行", + "Kernel 准备中,无法执行": "Kernel 准备中,无法执行", "运行当前Cell": "运行当前Cell", "运行全部": "运行全部", "运行之前所有cell": "运行之前所有cell", @@ -320,4 +320,4 @@ "类型": "类型", "请选择节点类型": "请选择节点类型", "通用": "通用" -} +} \ No newline at end of file diff --git a/packages/secretnote-lite/src/lang/index.ts b/packages/secretnote-lite/src/lang/index.ts index e6939c13..a46b5813 100644 --- a/packages/secretnote-lite/src/lang/index.ts +++ b/packages/secretnote-lite/src/lang/index.ts @@ -1,13 +1,12 @@ -import type { LanguageBundles } from '@difizen/mana-l10n'; -import { l10n, L10nLang } from '@difizen/mana-l10n'; +// Multilingual support -import lang_en_us from './bundle.l10n.en-US.json'; -import lang_zh_cn from './bundle.l10n.zh-CN.json'; +import { l10n, L10nLang } from '@difizen/mana-l10n'; -export const langBundles: LanguageBundles = { - 'zh-CN': lang_zh_cn, - 'en-US': lang_en_us, -}; +import bundleENUS from './bundle.l10n.en-US.json'; +import bundleZHCN from './bundle.l10n.zh-CN.json'; -l10n.loadLangBundles(langBundles); +l10n.loadLangBundles({ + 'zh-CN': bundleZHCN, + 'en-US': bundleENUS, +}); l10n.changeLang(L10nLang.zhCN); diff --git a/packages/secretnote-lite/src/modules/editor/cell/view.tsx b/packages/secretnote-lite/src/modules/editor/cell/view.tsx index e6d91949..a6705299 100644 --- a/packages/secretnote-lite/src/modules/editor/cell/view.tsx +++ b/packages/secretnote-lite/src/modules/editor/cell/view.tsx @@ -1,14 +1,16 @@ +// This is the customized view for a single cell (editable area). + import type { + CellViewOptions, ExecutionMeta, KernelMessage, - CellViewOptions, } from '@difizen/libro-jupyter'; import { CellEditorMemo, CellService, + CodeEditorManager, JupyterCodeCellView, KernelError, - CodeEditorManager, } from '@difizen/libro-jupyter'; import { getOrigin, @@ -24,7 +26,7 @@ import { import { l10n } from '@difizen/mana-l10n'; import { message } from 'antd'; import { isUndefined } from 'lodash-es'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; import { Ribbon } from '@/components/ribbon'; import { SecretNoteKernelManager } from '@/modules/kernel'; @@ -42,9 +44,7 @@ const SecretNoteCodeCellComponent = forwardRef((props, ref) => { ({ label: name, key: name }))} value={parties} - onChange={(val) => { - instance.onPartiesChange(val); - }} + onChange={(val) => instance.onPartiesChange(val)} > @@ -63,8 +63,7 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView { view = SecretNoteCodeCellComponent; - @prop() - parties: string[] = []; + @prop() parties: string[] = []; get partyList() { return this.serverManager.servers @@ -86,16 +85,16 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView { this.parties = this.getInitializedParties(); } - getUsableConnections() { + /** + * Get usable kernel connections for the cell to execute. + */ + getUsableKernels() { const libroModel = this.parent.model as unknown as SecretNoteModel; - if (!libroModel) { return []; } - const kernelConnections = getOrigin(libroModel.kernelConnections); - - return kernelConnections.filter((connection) => { + return getOrigin(libroModel.kernelConnections).filter((connection) => { if (connection.isDisposed) { return false; } @@ -108,86 +107,106 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView { }); } + /** + * Execute a single cell. + */ async run() { const cellModel = this.model; - const kernelConnections = this.getUsableConnections(); - - if (kernelConnections.length === 0) { - message.info(l10n.t('No available node to execute')); + const kernels = this.getUsableKernels(); + if (kernels.length === 0) { + message.info(l10n.t('无可用的 Kernel 连接,请检查是否存在并选中可用节点')); return false; } - this.clearExecution(); - this.updateExecutionStatus({ executing: true }); + this.clearExecution(); // clear the previous execution output area + this.updateExecutionStatus({ executing: true }); // mark the cell as executing this.updateExecutionTime({ - toExecute: new Date().toISOString(), + toExecute: new Date().toISOString(), // record the time when execution is fired }); - this.savePartiesToMeta(); + this.savePartiesToMeta(); // ensure the parties are saved to the cell metadata try { - const list: Promise[] = []; - for (let i = 0, len = kernelConnections.length; i < len; i += 1) { - const connection = kernelConnections[i]; - const future = connection.requestExecute({ - code: cellModel.value, - }); + const futures: Promise[] = []; + // dispatch the code to all usable kernels + kernels.forEach((kernel) => { + const future = kernel.requestExecute( + { + code: cellModel.value, + }, + /* disposeOnDone */ true, + ); + // handle IOPub messages future.onIOPub = ( msg: KernelMessage.IIOPubMessage, ) => { if (msg.header.msg_type === 'execute_input') { + // the execution request is accpeted by the kernel and started to execute this.updateExecutionStatus({ kernelExecuting: true }); this.updateExecutionTime({ start: msg.header.date }); } + // This event will be handled inside `output/outputarea.tsx` cellModel.msgChangeEmitter.fire({ - connection, + kernel, msg, }); }; - + // handle Reply messages future.onReply = (msg: KernelMessage.IExecuteReplyMsg) => { + // This event will be handled inside `output/outputarea.tsx` cellModel.msgChangeEmitter.fire({ - connection, + kernel, msg, }); }; + // store the done signal + futures.push(future.done); + }); - list.push(future.done); - } - - const futureDoneList = await Promise.all(list); + // wait for all kernels to finish the execution and update corresponding status + const presents = await Promise.all(futures); this.updateExecutionStatus({ executing: false, kernelExecuting: false }); - this.updateExecutionTime(this.parseMessageTime(futureDoneList)); + this.updateExecutionTime(this.parseMessagesTimeRange(presents)); - const ok = futureDoneList.every((msg) => msg.content.status === 'ok'); - if (ok) { + // check if all kernels finish the execution successfully + const notOks = presents.filter((msg) => msg.content.status !== 'ok'); + if (notOks.length === 0) { return true; } else { - const error = futureDoneList.find((msg) => msg.content.status !== 'ok'); - if (error) { - throw new KernelError(error.content); + // TODO: handle all the error messages + const errors = presents.filter((msg) => msg.content.status !== 'ok'); + if (errors) { + throw new KernelError(errors[0].content); } return false; } - } catch (reason) { - if (reason instanceof Error && reason.message.startsWith('Canceled')) { + } catch (e) { + if (e instanceof Error && e.message.startsWith('Canceled')) { return false; } - throw reason; + + throw e; } } + /** + * Update the execution status of the cell. + * `executing` means the application is executing the cell. + * `kernelExecuting` means some kernel is executing the cell. + */ updateExecutionStatus(status: { executing?: boolean; kernelExecuting?: boolean }) { const { executing, kernelExecuting } = status; - if (!isUndefined(executing)) { - this.model.executing = executing; - } - if (!isUndefined(kernelExecuting)) { - this.model.kernelExecuting = kernelExecuting; - } + !isUndefined(executing) && (this.model.executing = executing); + !isUndefined(kernelExecuting) && (this.model.kernelExecuting = kernelExecuting); } - updateExecutionTime(times: { start?: string; end?: string; toExecute?: string }) { + /** + * Update the execution time of the cell. + * `toExecute` is the time when the execution request is sent to the kernel by the application. + * `start` is the time when the kernel starts to execute the code. + * `end` is the time when the kernel finishes the execution. + */ + updateExecutionTime(times: { toExecute?: string; start?: string; end?: string }) { const meta = this.model.metadata.execution as ExecutionMeta; if (meta) { const { start, end, toExecute } = times; @@ -203,9 +222,12 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView { } } - parseMessageTime(msgs: KernelMessage.IExecuteReplyMsg[]) { - let start = ''; - let end = ''; + /** + * Parse the execution time from a section of Websocket messages. + */ + parseMessagesTimeRange(msgs: KernelMessage.IExecuteReplyMsg[]) { + let start = '', + end = ''; msgs.forEach((msg) => { const startTime = msg.metadata.started as string; const endTime = msg.header.date; @@ -220,6 +242,9 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView { return { start, end }; } + /** + * Handle the change of parties user selected on the right-top corner of the cell. + */ onPartiesChange(parties: string[]) { this.parties = parties; this.savePartiesToMeta(parties); @@ -242,6 +267,9 @@ export class SecretNoteCodeCellView extends JupyterCodeCellView { return this.partyList; } + /** + * Save the parties user selected to the cell model metadata. + */ savePartiesToMeta(parties: string[] = this.parties) { const execution = this.model.metadata.execution as ExecutionMeta; if (execution) { diff --git a/packages/secretnote-lite/src/modules/editor/contents/contents-contrib.ts b/packages/secretnote-lite/src/modules/editor/contents/contents-contrib.ts index 7d9697bc..01d9cf17 100644 --- a/packages/secretnote-lite/src/modules/editor/contents/contents-contrib.ts +++ b/packages/secretnote-lite/src/modules/editor/contents/contents-contrib.ts @@ -1,13 +1,18 @@ import type { NotebookModel, NotebookOption } from '@difizen/libro-jupyter'; import { ContentContribution } from '@difizen/libro-jupyter'; -import { URI, singleton } from '@difizen/mana-app'; - -import { getRemoteBaseUrl } from '@/utils'; +import { URI, inject, singleton } from '@difizen/mana-app'; +import { NotebookFileService } from '@/modules/notebook'; import type { SecretNoteModel } from '../model'; @singleton({ contrib: ContentContribution }) export class SecretNoteContentContribution implements ContentContribution { + protected readonly notebookFileService: NotebookFileService; + + constructor(@inject(NotebookFileService) notebookFileService: NotebookFileService) { + this.notebookFileService = notebookFileService; + } + canHandle = () => { return 3; }; @@ -16,16 +21,14 @@ export class SecretNoteContentContribution implements ContentContribution { const secretNoteModel = model as SecretNoteModel; const fireUri = new URI(options.resource); const filePath = fireUri.path.toString(); + const currentFileContents = await this.notebookFileService.getFile(filePath); - const currentFileContents = await secretNoteModel.contentsManager.get(filePath, { - baseUrl: getRemoteBaseUrl(), - content: true, - }); if (currentFileContents) { currentFileContents.content.nbformat_minor = 5; secretNoteModel.currentFileContents = currentFileContents; secretNoteModel.filePath = currentFileContents.path; + // @ts-ignore if (!secretNoteModel.quickEditMode && !secretNoteModel.readOnly) { secretNoteModel.startKernelConnection(); } diff --git a/packages/secretnote-lite/src/modules/editor/model.ts b/packages/secretnote-lite/src/modules/editor/model.ts index 4def7f6c..96470273 100644 --- a/packages/secretnote-lite/src/modules/editor/model.ts +++ b/packages/secretnote-lite/src/modules/editor/model.ts @@ -1,6 +1,5 @@ import type { IContentsModel, IKernelConnection } from '@difizen/libro-jupyter'; import { - ContentsManager, DocumentCommands, ExecutedWithKernelCellModel, LibroModel, @@ -16,9 +15,9 @@ import { import { debounce } from 'lodash-es'; import { SecretNoteKernelManager } from '@/modules/kernel'; -import { SecretNoteServerManager } from '@/modules/server'; import type { IServer } from '@/modules/server'; -import { getRemoteBaseUrl } from '@/utils'; +import { SecretNoteServerManager } from '@/modules/server'; +import { NotebookFileService } from '../notebook'; @transient() export class SecretNoteModel extends LibroModel { @@ -26,28 +25,31 @@ export class SecretNoteModel extends LibroModel { private readonly serverManager: SecretNoteServerManager; private readonly modalService: ModalService; private readonly commandRegistry: CommandRegistry; + private readonly notebookFileService: NotebookFileService; public currentFileContents!: IContentsModel; - public readonly contentsManager: ContentsManager; - - @prop() - kernelConnecting = false; - - @prop() - kernelConnections: IKernelConnection[] = []; - @prop() - filePath = ''; + @prop() kernelConnecting = false; + @prop() kernelConnections: IKernelConnection[] = []; + @prop() filePath = ''; + @prop() lspEnabled = true; - @prop() - lspEnabled = true; + protected readonly autoSave = debounce(() => { + this.commandRegistry.executeCommand(DocumentCommands.Save.id); + }, 500); + /** + * Check whether all kernels are idle. + */ get isKernelIdle() { return this.kernelConnections.every((item) => { return item.status === 'idle'; }); } + /** + * Get a representative kernel connection. + */ get kernelConnection() { return this.kernelConnections[0]; } @@ -55,16 +57,16 @@ export class SecretNoteModel extends LibroModel { constructor( @inject(SecretNoteKernelManager) kernelManager: SecretNoteKernelManager, @inject(SecretNoteServerManager) serverManager: SecretNoteServerManager, - @inject(ContentsManager) contentsManager: ContentsManager, @inject(ModalService) modalService: ModalService, @inject(CommandRegistry) commandRegistry: CommandRegistry, + @inject(NotebookFileService) notebookFileService: NotebookFileService, ) { super(); this.kernelManager = kernelManager; this.serverManager = serverManager; - this.contentsManager = contentsManager; this.modalService = modalService; this.commandRegistry = commandRegistry; + this.notebookFileService = notebookFileService; this.serverManager.onServerAdded(this.onServerAdded.bind(this)); this.serverManager.onServerDeleted(this.onServerDeleted.bind(this)); this.serverManager.onServerStarted(this.onServerAdded.bind(this)); @@ -75,10 +77,12 @@ export class SecretNoteModel extends LibroModel { async startKernelConnection() { this.kernelConnecting = true; const fileInfo = this.currentFileContents; + if (!fileInfo) { return; } const connections = this.kernelManager.getKernelConnections(fileInfo); + if (connections.length > 0) { this.kernelConnections = connections; this.kernelConnecting = false; @@ -99,11 +103,10 @@ export class SecretNoteModel extends LibroModel { let res: IContentsModel | undefined; try { - res = await this.contentsManager.save(this.currentFileContents.path, { + res = await this.notebookFileService.saveFile(this.currentFileContents.path, { type: this.currentFileContents.type, content: notebookContent, format: this.currentFileContents.format, - baseUrl: getRemoteBaseUrl(), }); if (!res) { @@ -127,6 +130,7 @@ export class SecretNoteModel extends LibroModel { throw new Error('File Save Error'); } + // checkpoint (see https://stackoverflow.com/questions/46421663/) is not supported in SecretNote // await this.createCheckpoint(); } @@ -173,6 +177,9 @@ export class SecretNoteModel extends LibroModel { } } + /** + * Restart all kernels. + */ async restart() { if (this.kernelConnections.length === 0) { await this.startKernelConnection(); @@ -205,44 +212,4 @@ export class SecretNoteModel extends LibroModel { this.scrollToView(this.cells[runningCellIndex]); } } - - async createCheckpoint() { - if (this.currentFileContents) { - await this.contentsManager.createCheckpoint(this.currentFileContents.path, { - baseUrl: getRemoteBaseUrl(), - }); - } - } - - async listCheckpoints() { - if (this.currentFileContents) { - await this.contentsManager.listCheckpoints(this.currentFileContents.path, { - baseUrl: getRemoteBaseUrl(), - }); - } - } - - async restoreCheckpoint(checkpointID: string) { - if (this.currentFileContents) { - await this.contentsManager.restoreCheckpoint( - this.currentFileContents.path, - checkpointID, - { baseUrl: getRemoteBaseUrl() }, - ); - } - } - - async deleteCheckpoint(checkpointID: string) { - if (this.currentFileContents) { - await this.contentsManager.deleteCheckpoint( - this.currentFileContents.path, - checkpointID, - { baseUrl: getRemoteBaseUrl() }, - ); - } - } - - autoSave = debounce(() => { - this.commandRegistry.executeCommand(DocumentCommands.Save.id); - }, 500); } diff --git a/packages/secretnote-lite/src/modules/editor/module.ts b/packages/secretnote-lite/src/modules/editor/module.ts index 14928653..ef012175 100644 --- a/packages/secretnote-lite/src/modules/editor/module.ts +++ b/packages/secretnote-lite/src/modules/editor/module.ts @@ -20,6 +20,7 @@ export const EditorModule = ManaModule.create() SecretNoteContentContribution, SecretNoteOutputArea, JupyterWorkspaceService, + // Local customization { token: LibroModel, useClass: SecretNoteModel }, { token: LibroCodeCellModel, useClass: SecretNoteCodeCellModel }, { token: LibroCodeCellView, useClass: SecretNoteCodeCellView }, diff --git a/packages/secretnote-lite/src/modules/editor/output/outputarea.tsx b/packages/secretnote-lite/src/modules/editor/output/outputarea.tsx index d08522b1..b157d2d8 100644 --- a/packages/secretnote-lite/src/modules/editor/output/outputarea.tsx +++ b/packages/secretnote-lite/src/modules/editor/output/outputarea.tsx @@ -1,10 +1,15 @@ +// Outputarea is the area below each cell displaying the output of the cell execution. +// Different from common Jupyter Server, Since SecretNote supports multiple parties executions, +// the output area is customized to display the output of each party properly. + import type { ExecutableCellModel, + IDisplayData, IKernelConnection, IMimeBundle, IOutput, - KernelMessage, IOutputAreaOption, + KernelMessage, } from '@difizen/libro-jupyter'; import { isDisplayDataMsg, @@ -18,15 +23,15 @@ import { removeOverwrittenChars, } from '@difizen/libro-jupyter'; import { inject, transient, view, ViewOption } from '@difizen/mana-app'; -import React from 'react'; import { SecretNoteKernelManager } from '@/modules/kernel'; +import { l10n } from '@difizen/mana-l10n'; @transient() @view('libro-output-area') export class SecretNoteOutputArea extends LibroOutputArea { kernelManager: SecretNoteKernelManager; - connectionId2Message: Record = {}; + kernelOutputs: Record = {}; // kernel id -> outputs from it constructor( @inject(ViewOption) option: IOutputAreaOption, @@ -34,28 +39,32 @@ export class SecretNoteOutputArea extends LibroOutputArea { ) { super(option); this.kernelManager = kernelManager; - this.connectionId2Message = {}; - this.handleMsg(); + // manually control the outputs of each kernel and synchronize them with LibroOutputArea.outputs + this.kernelOutputs = {}; + this.startMsgHandler(); } - handleMsg() { + /** + * Start handling the message from the kernel connection passed from `cell`. + * Transform it to proper outputs. + */ + startMsgHandler() { + // cell that has output area is always an executable cell instead of a markdown cell, cast it const cellModel = this.cell.model as unknown as ExecutableCellModel; + + // this event is fired inside `cell/view.tsx` + // about messaging, see https://jupyter-client.readthedocs.io/en/latest/messaging.html cellModel.msgChangeEmitter.event( - ({ - connection, - msg, - }: { - connection: IKernelConnection; - msg: KernelMessage.IMessage; - }) => { + ({ kernel, msg }: { kernel: IKernelConnection; msg: KernelMessage.IMessage }) => { + // ignore heartbeat messages if (msg.header.msg_type === 'status') { return; - } - if (msg.header.msg_type === 'execute_input') { - // eslint-disable-next-line @typescript-eslint/no-explicit-any + } else if (msg.header.msg_type === 'execute_input') { cellModel.executeCount = (msg.content as any).execution_count; } - if ( + // handle `display_data`, `stream`, `error`, `execute_result` messages + // these are most common output types + else if ( isDisplayDataMsg(msg) || isStreamMsg(msg) || isErrorMsg(msg) || @@ -65,13 +74,13 @@ export class SecretNoteOutputArea extends LibroOutputArea { ...msg.content, output_type: msg.header.msg_type, }; - this.addOutput(connection, output); + this.addOutput(kernel, output); } - - if (isExecuteReplyMsg(msg)) { + // handle `execute_reply` message + else if (isExecuteReplyMsg(msg)) { const content = msg.content; if (content.status !== 'ok') { - return; + return; // TODO just ignore? } const payload = content && content.payload; if (!payload || !payload.length) { @@ -81,74 +90,95 @@ export class SecretNoteOutputArea extends LibroOutputArea { if (!pages.length) { return; } - const page = JSON.parse(JSON.stringify(pages[0])); const output: IOutput = { output_type: 'display_data', data: page.data as IMimeBundle, metadata: {}, }; - this.addOutput(connection, output); + this.addOutput(kernel, output); } }, ); } - addOutput(connection: IKernelConnection, output: IOutput) { - const outputs = this.connectionId2Message[connection.id] || []; + /** + * Append a kernel's output to the output area. + */ + addOutput(kernel: IKernelConnection, output: IOutput) { + const outputs = this.kernelOutputs[kernel.id] || []; + // add the leading output if the outputs are empty if (outputs.length === 0) { - outputs.push(this.getBreakOutput(connection)); + outputs.push(this.makeLeadingOutput(kernel)); } + const lastIndex = outputs.length - 1; const preOutput = outputs[lastIndex]; - if (isStream(output) && isStream(preOutput) && output.name === preOutput.name) { + // merge two continuous outputs to the same stream + // handle backspace and carriage-return, concat the text output.text = removeOverwrittenChars(preOutput.text + normalize(output.text)); + // just replace the previous output, don't push new outputs[lastIndex] = output; this.flushOutputs(); return; - } - - if (isStream(output)) { + } else if (isStream(output)) { + // handle the first stream output output.text = removeOverwrittenChars(normalize(output.text)); } + // no extra logics for other types of outputs + // update the outputs of the kernel and flush it outputs.push(output); - this.connectionId2Message[connection.id] = outputs; - + this.kernelOutputs[kernel.id] = outputs; this.flushOutputs(); } + /** + * Flush all kernel outputs to the output area. + */ async flushOutputs() { - const connectionNum = Object.keys(this.connectionId2Message).length; - let outputs = Object.values(this.connectionId2Message).flat(); - if (connectionNum < 2) { - outputs = outputs.filter((output) => !output.breakFlag); + const kernelCount = Object.keys(this.kernelOutputs).length; + let outputs = Object.values(this.kernelOutputs).flat(); + if (kernelCount < 2) { + // remove the leading output title if there is only one kernel + outputs = outputs.filter((output) => !output.isLeading); } - this.outputs.forEach((output) => { - output.dispose(); - }); + // dispose all previous outputs + this.outputs.forEach((output) => output.dispose()); + // create new outputs this.outputs = await Promise.all( outputs.map((output) => this.doCreateOutput(output)), ); } - getBreakOutput(connection: IKernelConnection) { - const server = this.kernelManager.getServerByKernelConnection(connection); - const name = server?.name || connection.clientId; - const output: IOutput = { + /** + * Construct a special `leading output` (as display_data) displayed as title on + * the very first line of each kernel's output to indicate the output source. + */ + makeLeadingOutput(kernel: IKernelConnection) { + const server = this.kernelManager.getServerByKernelConnection(kernel); + const name = server?.name || kernel.clientId; + + const output: IDisplayData = { output_type: 'display_data', data: { - 'text/html': `

${name}'s Output:

`, + 'text/html': `

${name} ${l10n.t('的输出')}

`, }, metadata: {}, - breakFlag: true, + isLeading: true, // a flag to indicate the leading output }; + return output; } + /** + * Clear the all kernel outputs of current cell. + * @override LibroOutputArea.clear + */ clear() { - super.clear(); - this.connectionId2Message = {}; + super.clear.call(this, false); + this.kernelOutputs = {}; + this.flushOutputs(); } } diff --git a/packages/secretnote-lite/src/modules/editor/workspace.ts b/packages/secretnote-lite/src/modules/editor/workspace.ts index ef44390f..fcfbf1f8 100644 --- a/packages/secretnote-lite/src/modules/editor/workspace.ts +++ b/packages/secretnote-lite/src/modules/editor/workspace.ts @@ -1,25 +1,26 @@ -import { BaseWorkspaceService, ILibroWorkspaceService } from '@difizen/libro-jupyter'; -import { ApplicationContribution } from '@difizen/mana-app'; -import { URI } from '@difizen/mana-app'; -import { singleton } from '@difizen/mana-app'; +// Mocked workspace concept for SecretNote to allow LSP (mainly `libro-analyzer` +// because the code intelligence is cross-file) to work properly. -interface JupyterWorkspaceData { - rootUri: string; -} +import { BaseWorkspaceService, ILibroWorkspaceService } from '@difizen/libro-jupyter'; +import { ApplicationContribution, singleton, URI } from '@difizen/mana-app'; @singleton({ contrib: [ILibroWorkspaceService, ApplicationContribution] }) export class JupyterWorkspaceService extends BaseWorkspaceService implements ILibroWorkspaceService, ApplicationContribution { - protected workspaceData: JupyterWorkspaceData = { rootUri: '' }; - onViewStart() { + // no extra logics. resolve directly. this.deferred.resolve(); } + // Since SecretNote doesn't care about workspace because all notebook files + // are considered individual and usually no foreign .py file importing are used, + // we just return empty `notebooks` and `files` list, and mock `workspaceRoot` + // with an arbitary path that the system user running Jupyter Server can read and write. + MOCK_WORKSPACE_ROOT = '/tmp'; override get workspaceRoot() { - return new URI(this.workspaceData.rootUri); + return new URI(this.MOCK_WORKSPACE_ROOT); } override get notebooks() { return []; diff --git a/packages/secretnote-lite/src/modules/file/extra-view.tsx b/packages/secretnote-lite/src/modules/file/extra-view.tsx index 1cee08bf..12871106 100644 --- a/packages/secretnote-lite/src/modules/file/extra-view.tsx +++ b/packages/secretnote-lite/src/modules/file/extra-view.tsx @@ -9,7 +9,6 @@ import { import { l10n } from '@difizen/mana-l10n'; import { message, Tooltip } from 'antd'; import { RefreshCw } from 'lucide-react'; -import React from 'react'; import { FileService } from './service'; diff --git a/packages/secretnote-lite/src/modules/file/module.ts b/packages/secretnote-lite/src/modules/file/module.ts index 70979924..7b6c6934 100644 --- a/packages/secretnote-lite/src/modules/file/module.ts +++ b/packages/secretnote-lite/src/modules/file/module.ts @@ -1,14 +1,17 @@ +// The file module. It's about those files on the nodes (servers) that are not notebooks usually. +// E.g., data files (csv, jsonl), log files (log), etc. + import { LibroJupyterModule } from '@difizen/libro-jupyter'; import { createViewPreference, ManaModule } from '@difizen/mana-app'; import { PreviewLayoutArea } from '@/modules/layout'; import { SecretNoteServerModule } from '@/modules/server'; -import { CsvPreview } from './csv-preview-contrib'; import { ExtraView } from './extra-view'; -import { JsonlPreview } from './jsonl-preview-contrib'; -import { LogPreview } from './log-preview-contrib'; import { FilePreviewView } from './preview-view'; +import { CsvPreview } from './preview/csv-preview-contrib'; +import { JsonlPreview } from './preview/jsonl-preview-contrib'; +import { LogPreview } from './preview/log-preview-contrib'; import { FilePreviewContribution } from './protocol'; import { FileService } from './service'; import { FileView, fileViewKey } from './view'; diff --git a/packages/secretnote-lite/src/modules/file/preview-view.tsx b/packages/secretnote-lite/src/modules/file/preview-view.tsx index ec965759..3c6c52a2 100644 --- a/packages/secretnote-lite/src/modules/file/preview-view.tsx +++ b/packages/secretnote-lite/src/modules/file/preview-view.tsx @@ -1,8 +1,8 @@ // eslint-disable-next-line @typescript-eslint/consistent-type-imports -import { Contribution } from '@difizen/mana-app'; import { BaseView, contrib, + Contribution, inject, prop, singleton, @@ -39,14 +39,12 @@ export class FilePreviewView extends BaseView { readonly fileService: FileService; readonly providers: Contribution.Provider; - @prop() - data = ''; - - @prop() - type = ''; + @prop() data = ''; + @prop() type = ''; constructor( @inject(FileService) fileService: FileService, + // @ts-ignore @contrib(FilePreviewContribution) providers: Contribution.Provider, ) { diff --git a/packages/secretnote-lite/src/modules/file/csv-preview-contrib.tsx b/packages/secretnote-lite/src/modules/file/preview/csv-preview-contrib.tsx similarity index 95% rename from packages/secretnote-lite/src/modules/file/csv-preview-contrib.tsx rename to packages/secretnote-lite/src/modules/file/preview/csv-preview-contrib.tsx index 9a9f4023..05cd184e 100644 --- a/packages/secretnote-lite/src/modules/file/csv-preview-contrib.tsx +++ b/packages/secretnote-lite/src/modules/file/preview/csv-preview-contrib.tsx @@ -1,10 +1,10 @@ import { TableSheet } from '@antv/s2'; import { singleton } from '@difizen/mana-app'; -import React, { useEffect, useRef } from 'react'; +import { useEffect, useRef } from 'react'; import { parseCSV } from '@/utils'; -import { FilePreviewContribution } from './protocol'; +import { FilePreviewContribution } from '../protocol'; const TableView = (props: { data: string }) => { const ref = useRef(null); diff --git a/packages/secretnote-lite/src/modules/file/jsonl-preview-contrib.tsx b/packages/secretnote-lite/src/modules/file/preview/jsonl-preview-contrib.tsx similarity index 93% rename from packages/secretnote-lite/src/modules/file/jsonl-preview-contrib.tsx rename to packages/secretnote-lite/src/modules/file/preview/jsonl-preview-contrib.tsx index c686a7ca..e8105e22 100644 --- a/packages/secretnote-lite/src/modules/file/jsonl-preview-contrib.tsx +++ b/packages/secretnote-lite/src/modules/file/preview/jsonl-preview-contrib.tsx @@ -1,11 +1,10 @@ import { singleton } from '@difizen/mana-app'; import hljs from 'highlight.js'; import { useEffect } from 'react'; -import React from 'react'; import styled from 'styled-components'; -import { FilePreviewContribution } from './protocol'; import 'highlight.js/styles/xcode.css'; // 选择主题 https://highlightjs.org/demo +import { FilePreviewContribution } from '../protocol'; const CodeWrapper = styled.pre` width: 100%; diff --git a/packages/secretnote-lite/src/modules/file/log-preview-contrib.tsx b/packages/secretnote-lite/src/modules/file/preview/log-preview-contrib.tsx similarity index 86% rename from packages/secretnote-lite/src/modules/file/log-preview-contrib.tsx rename to packages/secretnote-lite/src/modules/file/preview/log-preview-contrib.tsx index 7bc8e596..82b4f3ff 100644 --- a/packages/secretnote-lite/src/modules/file/log-preview-contrib.tsx +++ b/packages/secretnote-lite/src/modules/file/preview/log-preview-contrib.tsx @@ -1,7 +1,7 @@ import { singleton } from '@difizen/mana-app'; import React from 'react'; -import { FilePreviewContribution } from './protocol'; +import { FilePreviewContribution } from '../protocol'; const LogViewer = React.lazy(() => import('@/components/log-viewer')); diff --git a/packages/secretnote-lite/src/modules/file/service.ts b/packages/secretnote-lite/src/modules/file/service.ts index c6915496..eb7b476f 100644 --- a/packages/secretnote-lite/src/modules/file/service.ts +++ b/packages/secretnote-lite/src/modules/file/service.ts @@ -3,7 +3,11 @@ import { ContentsManager } from '@difizen/libro-jupyter'; import { inject, prop, singleton } from '@difizen/mana-app'; import type { DataNode } from 'antd/es/tree'; -import { downloadFileByUrl as download, getRemoteBaseUrl } from '@/utils'; +import { + downloadFileByURL as download, + genericErrorHandler, + getRemoteBaseUrl, +} from '@/utils'; import { SecretNoteServerManager, ServerStatus } from '../server'; @@ -14,8 +18,7 @@ export class FileService { protected readonly contentsManager: ContentsManager; protected readonly serverManager: SecretNoteServerManager; - @prop() - fileTree: DataNode[] = []; + @prop() fileTree: DataNode[] = []; constructor( @inject(ContentsManager) contentsManager: ContentsManager, @@ -30,9 +33,13 @@ export class FileService { } async getFileTree() { - const servers = (await this.serverManager.getServerList()).filter( - (s) => s.status === ServerStatus.Succeeded, - ); + const maybeServerList = await this.serverManager.getServerList(); + if (!maybeServerList) { + genericErrorHandler('Failed to get server list'); + return; + } + + const servers = maybeServerList.filter((s) => s.status === ServerStatus.Succeeded); const fileTree: DataNode[] = []; for (const server of servers) { @@ -64,8 +71,7 @@ export class FileService { serverNode.children = sortedFileNodeList; fileTree.push(serverNode); } catch (err) { - // eslint-disable-next-line no-console - console.log(err); + genericErrorHandler(err); } } diff --git a/packages/secretnote-lite/src/modules/file/view.tsx b/packages/secretnote-lite/src/modules/file/view.tsx index cf12d188..2d35fbcb 100644 --- a/packages/secretnote-lite/src/modules/file/view.tsx +++ b/packages/secretnote-lite/src/modules/file/view.tsx @@ -1,3 +1,5 @@ +// Views about file (file tree, file operations, etc.) management. + import { BaseView, inject, @@ -8,7 +10,7 @@ import { } from '@difizen/mana-app'; import { l10n } from '@difizen/mana-l10n'; import type { UploadProps } from 'antd'; -import { message, Modal, Space, Tree, Upload } from 'antd'; +import { message, Modal, Space, Spin, Tree, Upload } from 'antd'; import type { DataNode } from 'antd/es/tree'; import { ChevronDown, @@ -19,17 +21,17 @@ import { ScrollText, Table, Trash, - Upload as UploadIcon, + UploadIcon, } from 'lucide-react'; -import React from 'react'; +import React, { useState } from 'react'; -import { DropdownMenu } from '@/components/dropdown-menu'; import type { Menu } from '@/components/dropdown-menu'; +import { DropdownMenu } from '@/components/dropdown-menu'; import { SideBarContribution } from '@/modules/layout'; -import { readFile } from '@/utils'; +import { genericErrorHandler, readFile } from '@/utils'; import './index.less'; -import { FileService, FILE_EXTS } from './service'; +import { FILE_EXTS, FileService } from './service'; const { DirectoryTree } = Tree; @@ -43,6 +45,7 @@ const IconMap: Record = { export const FileComponent = () => { const instance = useInject(ViewInstance); const fileService = instance.fileService; + const [isUploading, setIsUploading] = useState(false); const onMenuClick = (key: string, node: DataNode) => { switch (key) { @@ -54,7 +57,9 @@ export const FileComponent = () => { Modal.confirm({ title: l10n.t('删除文件'), centered: true, - content: l10n.t('文件 {name} 将被删除', { name: node.title as string }), + content: l10n.t('文件 {name} 将被删除', { + name: node.title as string, + }), okText: l10n.t('删除文件'), cancelText: l10n.t('取消'), okType: 'danger', @@ -77,15 +82,16 @@ export const FileComponent = () => { }; const uploadFile = async (nodeData: DataNode, file: File) => { + setIsUploading(true); const content = await readFile(file); try { await fileService.uploadFile(nodeData, file.name, content); await fileService.getFileTree(); message.success(l10n.t('文件上传成功')); } catch (e) { - if (e instanceof Error) { - message.error(e.message); - } + genericErrorHandler(e); + } finally { + setIsUploading(false); } }; @@ -98,8 +104,10 @@ export const FileComponent = () => { Modal.confirm({ title: l10n.t('上传文件'), centered: true, - content: l10n.t('文件 {name} 已经存在,是否覆盖?', { name: file.name }), - okText: 'Overwrite', + content: l10n.t('文件 {name} 已经存在,是否覆盖?', { + name: file.name, + }), + okText: l10n.t('覆盖'), cancelText: l10n.t('取消'), okType: 'danger', async onOk(close) { @@ -134,7 +142,11 @@ export const FileComponent = () => { const isLeaf = nodeData.isLeaf; const folderMenuItems: Menu[] = [ - { key: 'upload', label: uploadRender(nodeData), icon: }, + { + key: 'upload', + label: uploadRender(nodeData), + icon: , + }, ]; const dataMenuItems: Menu[] = [ // { key: 'view', label: l10n.t('查看'), icon: }, @@ -145,20 +157,39 @@ export const FileComponent = () => { }, { key: 'download', label: l10n.t('下载'), icon: }, { type: 'divider' }, - { key: 'delete', label: l10n.t('删除'), icon: , danger: true }, + { + key: 'delete', + label: l10n.t('删除'), + icon: , + danger: true, + }, ]; return (
- - - {getFileIcon(nodeData)} - {nodeData.title as string} - - + + {getFileIcon(nodeData)} + {nodeData.title as string} + + + + {l10n.t('正忙...')} + + + ) : ( + void 0 + ) + } // undefined fallbacks to default "..." icon items={isLeaf ? dataMenuItems : folderMenuItems} + disabled={isUploading} onClick={(key) => { + if (isUploading) { + return; + } onMenuClick(key, nodeData); }} /> diff --git a/packages/secretnote-lite/src/modules/kernel/kernel-connection.ts b/packages/secretnote-lite/src/modules/kernel/kernel-connection.ts new file mode 100644 index 00000000..d7c7b264 --- /dev/null +++ b/packages/secretnote-lite/src/modules/kernel/kernel-connection.ts @@ -0,0 +1,58 @@ +// In SecretFlow, many APIs spawn new processes or new threads, which means some subsequent +// cell's outputs might internally belong to previous cells even if previous cells are settled +// already after `execute_reply` message and `idle` status. (To reproduce, catch some WebSocket +// messages when a cell makes SecretFlow error, observe their `parent_header`'s `msg_id` +// and you'll know the issue.) This leads to some unwanted behaviors. +// 1. By default, the `future` of previous cells are disposed on done +// (see `kernel.requestExecute` in `SecretNoteCodeCellView`'s `run`), +// making subsequent cells orphaned (whose `parent_header` includes a disposed `msg_id`). +// These messages will be then discarded by Libro (see `_handleMessage` in `libro-kernel`'s +// `KernelConnection`) and never be displayed in the output area, confusing users. +// 2. If we set `disposeOnDone` to `false`, some subsequent outputs that are born when the +// current cell is executed will still be displayed in the previous wrong cell (usually +// the one that SecretFlow is initialized in) instead of current one. Also, we need to +// manually dispose those `future`s to avoid memory leaks which is bothersome. +// Worth readings: +// jupyter/jupyter_client/issues/297; jupyter/notebook/issues/518; jupyterlab/jupyterlab/issues/629; +// ipykernel/iostream.py/OutStream/parent_header +// To solve this, we need to customize the `KernelConnection`. + +import { + isErrorMsg, + isExecuteInputMsg, + isStreamMsg, + KernelConnection, + type KernelMessage, +} from '@difizen/libro-jupyter'; +import { transient } from '@difizen/mana-app'; + +@transient() +export class SecretNoteKernelConnection extends KernelConnection { + // keep recording the last execute_request message sent from the frontend + // so that the orphaned messages can be linked to this corresponding cell + protected _lastExecuteRequestHeader: KernelMessage.IHeader | null = null; + + override _handleMessage(msg: KernelMessage.IMessage): Promise { + if ( + msg.channel === 'iopub' && // on iopub channel + (isStreamMsg(msg) || isErrorMsg(msg)) && // is stream or error message + msg.parent_header && // has parent header + !this._futures?.get(msg.parent_header.msg_id) // but orphaned now + ) { + // assign its parent to be the latest execution's message + this._lastExecuteRequestHeader && + (msg.parent_header = this._lastExecuteRequestHeader); + } + + // call the parent method as usual + const res = super._handleMessage(msg); + + // update the last execute request header + if (msg.channel === 'iopub' && isExecuteInputMsg(msg)) { + // the latest execute_input's parent is the latest execute_request + this._lastExecuteRequestHeader = msg.parent_header as KernelMessage.IHeader; + } + + return res; + } +} diff --git a/packages/secretnote-lite/src/modules/kernel/kernel-manager.ts b/packages/secretnote-lite/src/modules/kernel/kernel-manager.ts index 31484555..0e0c4561 100644 --- a/packages/secretnote-lite/src/modules/kernel/kernel-manager.ts +++ b/packages/secretnote-lite/src/modules/kernel/kernel-manager.ts @@ -1,3 +1,7 @@ +// Kernel Manager manages all kernel connections. +// Different from common Jupyter Server, since SecretNote supports multiple parties executions, +// the kernel manager is customized to manage multiple kernel connections properly. + import type { IContentsModel, IKernelConnection, @@ -11,8 +15,8 @@ import { } from '@difizen/libro-jupyter'; import { inject, singleton, StorageService } from '@difizen/mana-app'; -import { SecretNoteServerManager, ServerStatus } from '@/modules/server'; import type { IServer } from '@/modules/server'; +import { SecretNoteServerManager, ServerStatus } from '@/modules/server'; import { getRemoteBaseUrl, getRemoteWsUrl } from '@/utils'; interface StoredSessionInfo { @@ -20,16 +24,16 @@ interface StoredSessionInfo { serverId: string; options: { model: { - id: string; // kernel.id, - name: string; // kernel.name, + id: string; + name: string; }; }; } @singleton() export class SecretNoteKernelManager { - private file2KernelConnections = new Map(); - private kernelConnection2Server = new Map(); + private fileToKernelConnections = new Map(); // File's stored key -> Kernel connections + private kernelConnectionToServer = new Map(); // Kernel id -> Server id protected sessionRestAPI: SessionRestAPI; protected kernelRestAPI: KernelRestAPI; @@ -52,12 +56,16 @@ export class SecretNoteKernelManager { this.storageService = storageService; } + /** + * Create kernel connections for the given file. + */ async createKernelConnections(fileInfo: IContentsModel) { - const servers = await this.serverManager.getServerList(); - const availableServers = (servers || []).filter( + // get available servers + const availableServers = ((await this.serverManager.getServerList()) || []).filter( (s) => s.status === ServerStatus.Succeeded, ); const kernelConnections: IKernelConnection[] = []; + // get stored sessions const storedSessions = await this.storageService.getData( this.storedKey(fileInfo), [], @@ -88,26 +96,32 @@ export class SecretNoteKernelManager { } if (connection) { kernelConnections.push(connection); - this.kernelConnection2Server.set(connection.id, s.id); + this.kernelConnectionToServer.set(connection.id, s.id); } } - this.file2KernelConnections.set(this.storedKey(fileInfo), kernelConnections); + this.fileToKernelConnections.set(this.storedKey(fileInfo), kernelConnections); return kernelConnections; } + /** + * Add a kernel connection on a server for a file. + */ async addKernelConnectionOnServer(fileInfo: IContentsModel, server: IServer) { const connection = await this.createKernelConnection(fileInfo, server); if (connection) { - this.kernelConnection2Server.set(connection.id, server.id); - const existed = this.file2KernelConnections.get(this.storedKey(fileInfo)) || []; - this.file2KernelConnections.set(this.storedKey(fileInfo), [ + this.kernelConnectionToServer.set(connection.id, server.id); + const existed = this.fileToKernelConnections.get(this.storedKey(fileInfo)) || []; + this.fileToKernelConnections.set(this.storedKey(fileInfo), [ ...existed, connection, ]); } } + /** + * Delete a kernel connection on a server for a file. + */ async deleteKernelConnectionOnServer(fileInfo: IContentsModel, server: IServer) { const storedSessions = await this.storageService.getData( this.storedKey(fileInfo), @@ -118,13 +132,15 @@ export class SecretNoteKernelManager { await this.removeStoredSession(fileInfo, hit); } - const kernelConnections = this.file2KernelConnections.get(this.storedKey(fileInfo)); + const kernelConnections = this.fileToKernelConnections.get( + this.storedKey(fileInfo), + ); if (kernelConnections) { const deleteIds: string[] = []; kernelConnections.forEach((kc) => { const ownerServer = this.getServerByKernelConnection(kc); if (ownerServer && ownerServer.id === server.id) { - this.kernelConnection2Server.delete(kc.id); + this.kernelConnectionToServer.delete(kc.id); kc.shutdown(); deleteIds.push(kc.id); } @@ -132,37 +148,48 @@ export class SecretNoteKernelManager { const newKernelConnections = kernelConnections.filter( (kc) => !deleteIds.includes(kc.id), ); - this.file2KernelConnections.set(this.storedKey(fileInfo), newKernelConnections); + this.fileToKernelConnections.set(this.storedKey(fileInfo), newKernelConnections); } } + /** + * Shutdown all kernel connections for a file. + */ async shutdownKernelConnections(fileInfo: IContentsModel) { - const kernelConnections = this.file2KernelConnections.get(this.storedKey(fileInfo)); + const kernelConnections = this.fileToKernelConnections.get( + this.storedKey(fileInfo), + ); if (kernelConnections) { kernelConnections.forEach((kc) => { - this.kernelConnection2Server.delete(kc.id); + this.kernelConnectionToServer.delete(kc.id); kc.shutdown(); }); await this.clearStoredSessions(fileInfo); - this.file2KernelConnections.delete(this.storedKey(fileInfo)); + this.fileToKernelConnections.delete(this.storedKey(fileInfo)); } } - getKernelConnections(fileInfo: IContentsModel): IKernelConnection[] { - return this.file2KernelConnections.get(this.storedKey(fileInfo)) || []; + /** + * Get all kernel connections for a file. + */ + getKernelConnections(fileInfo: IContentsModel) { + return this.fileToKernelConnections.get(this.storedKey(fileInfo)) || []; } - getServerByKernelConnection(connection: IKernelConnection): IServer | undefined { - const serverId = this.kernelConnection2Server.get(connection.id); + /** + * Get the server that a kernel connection belongs to. + */ + getServerByKernelConnection(connection: IKernelConnection) { + const serverId = this.kernelConnectionToServer.get(connection.id); if (serverId) { return this.serverManager.servers.find((s) => s.id === serverId); } } - protected async createKernelConnection( - fileInfo: IContentsModel, - server: IServer, - ): Promise { + /** + * Create a kernel connection on a server for a file. + */ + protected async createKernelConnection(fileInfo: IContentsModel, server: IServer) { const kernelName = this.getDefaultKernelName(fileInfo, server); const newSession = await this.sessionRestAPI.startSession( { @@ -212,9 +239,12 @@ export class SecretNoteKernelManager { return kernelConnection; } - protected async isKernelAlive(id: string, server: IServer): Promise { + /** + * Test if a kernel is alive. + */ + protected async isKernelAlive(kernelId: string, server: IServer) { try { - const data = await this.kernelRestAPI.getKernelModel(id, { + const data = await this.kernelRestAPI.getKernelModel(kernelId, { baseUrl: getRemoteBaseUrl(server.id), wsUrl: getRemoteWsUrl(server.id), }); @@ -224,10 +254,16 @@ export class SecretNoteKernelManager { } } - protected storedKey(fileInfo: IContentsModel): string { + /** + * Generate a key for a file's session storage record. + */ + protected storedKey(fileInfo: IContentsModel) { return `secretnote_${fileInfo.path}_${fileInfo.name}`; } + /** + * Append a stored session for a file. + */ protected async addStoredSession(fileInfo: IContentsModel, info: StoredSessionInfo) { let sessions = await this.storageService.getData( this.storedKey(fileInfo), @@ -254,11 +290,14 @@ export class SecretNoteKernelManager { await this.storageService.setData(this.storedKey(fileInfo), sessions); } + /** + * Clear all stored sessions for a file. + */ protected async clearStoredSessions(fileInfo: IContentsModel) { await this.storageService.setData(this.storedKey(fileInfo), undefined); } - protected getDefaultKernelName(fileInfo: IContentsModel, server: IServer): string { + protected getDefaultKernelName(fileInfo: IContentsModel, server: IServer) { const kernelName = fileInfo.content.metadata.kernelspec?.name || server.kernelspec?.default || diff --git a/packages/secretnote-lite/src/modules/kernel/module.ts b/packages/secretnote-lite/src/modules/kernel/module.ts index 2142e12f..294f3f88 100644 --- a/packages/secretnote-lite/src/modules/kernel/module.ts +++ b/packages/secretnote-lite/src/modules/kernel/module.ts @@ -1,7 +1,27 @@ import { ManaModule } from '@difizen/mana-app'; +import { + KernelConnectionOptions, + LibroKernelConnectionFactory, +} from '@difizen/libro-jupyter'; +import { SecretNoteKernelConnection } from './kernel-connection'; import { SecretNoteKernelManager } from './kernel-manager'; export const SecretNoteKernelModule = ManaModule.create().register( SecretNoteKernelManager, + SecretNoteKernelConnection, + // replace the default kernel connection factory with our customized one + { + token: LibroKernelConnectionFactory, + useFactory: (ctx) => { + return (options: KernelConnectionOptions) => { + const child = ctx.container.createChild(); + child.register({ + token: KernelConnectionOptions, + useValue: options, + }); + return child.get(SecretNoteKernelConnection); + }; + }, + }, ); diff --git a/packages/secretnote-lite/src/modules/layout/index.less b/packages/secretnote-lite/src/modules/layout/index.less index 25d86ff4..c692db13 100644 --- a/packages/secretnote-lite/src/modules/layout/index.less +++ b/packages/secretnote-lite/src/modules/layout/index.less @@ -47,6 +47,7 @@ } .secretnote-header { + background: #fff; border-bottom: 1px solid var(--mana-secretnote-divider-color); .logo { @@ -71,10 +72,21 @@ border-right: 1px solid var(--mana-secretnote-divider-color); background-color: var(--mana-secretnote-sidebar-background); - .statusbar { + .bottom-bar { position: absolute; - bottom: 150px; + bottom: 0; width: 100%; border-top: 1px solid var(--mana-secretnote-divider-color); + text-align: center; + padding: 12px; + } + + .about-bar { + a.ant-typography { + color: var(--custom-blue-400) !important; + } + .icon-container { + line-height: 0; + } } } diff --git a/packages/secretnote-lite/src/modules/layout/module.ts b/packages/secretnote-lite/src/modules/layout/module.ts index 75f63b68..9bbe0143 100644 --- a/packages/secretnote-lite/src/modules/layout/module.ts +++ b/packages/secretnote-lite/src/modules/layout/module.ts @@ -1,10 +1,12 @@ +// Module for the layout of the whole page. + import { createSlotPreference, ManaModule, RootSlotId } from '@difizen/mana-app'; import { HeaderView } from './header'; import { LayoutArea, LayoutView } from './layout'; import { PreviewLayoutArea, PreviewLayoutView } from './preview'; import { SideBarContribution } from './protocol'; -import { SideBarView } from './sidebar'; +import { AboutBarView, aboutBarViewKey, SideBarView } from './sidebar'; export const LayoutModule = ManaModule.create() .contribution(SideBarContribution) @@ -12,6 +14,7 @@ export const LayoutModule = ManaModule.create() HeaderView, SideBarView, LayoutView, + AboutBarView, createSlotPreference({ slot: RootSlotId, view: LayoutView, @@ -24,6 +27,10 @@ export const LayoutModule = ManaModule.create() slot: LayoutArea.sidebar, view: SideBarView, }), + createSlotPreference({ + slot: aboutBarViewKey, + view: AboutBarView, + }), ); export const PreviewLayoutModule = ManaModule.create().register( diff --git a/packages/secretnote-lite/src/modules/layout/sidebar.tsx b/packages/secretnote-lite/src/modules/layout/sidebar.tsx index a3bcd16d..6630740b 100644 --- a/packages/secretnote-lite/src/modules/layout/sidebar.tsx +++ b/packages/secretnote-lite/src/modules/layout/sidebar.tsx @@ -1,30 +1,82 @@ +// Sidebar is the bar displayed on the left which displays notebook file list, server data file list, +// node CPU/MEM usage, and "about" information of the application. + // eslint-disable-next-line @typescript-eslint/consistent-type-imports -import { Contribution } from '@difizen/mana-app'; import { + BaseView, contrib, + Contribution, DefaultSlotView, + inject, singleton, Slot, useInject, view, ViewInstance, ViewManager, - inject, } from '@difizen/mana-app'; -import { Collapse } from 'antd'; +import { Collapse, Space, Tooltip, Typography } from 'antd'; +import { InfoIcon } from 'lucide-react'; import React from 'react'; +import LibroJupyterPkgJSON from '@difizen/libro-jupyter/package.json'; +import ManaAppPkgJSON from '@difizen/mana-app/package.json'; +import SecretNotePkgJSON from '../../../package.json'; + +import { l10n } from '@difizen/mana-l10n'; import { SideBarContribution } from './protocol'; -export enum SideBarArea { - notebook = 'notebook', - notebookExtra = 'notebookExtra', - file = 'file', - FileExtra = 'dataExtra', - integration = 'integration', - integrationExtra = 'integrationExtra', +export const metricsMonitorKey = 'metricsMonitor'; + +// About bar on the bottom of the sidebar +const AboutBarComponent = () => { + const instance = useInject(ViewInstance); + const fmtPackageVersions = instance.fmtPackageVersions; + + return ( + + + SecretFlow + + + SecretNote + +
+ + + +
+
+ ); +}; + +export const aboutBarViewKey = 'aboutBar'; +@singleton() +@view('secretnote-aboutBar-view') +export class AboutBarView extends BaseView { + key = aboutBarViewKey; + view = AboutBarComponent; + + // expose versions of important packages + packageVersions = { + 'secretnote-lite': SecretNotePkgJSON.version, + 'libro-jupyter': LibroJupyterPkgJSON.version, + 'mana-app': ManaAppPkgJSON.version, + } as const; + fmtPackageVersions: string; + + constructor() { + super(); + this.fmtPackageVersions = + l10n.t('版本信息') + + ': ' + + Object.entries(this.packageVersions) + .map(([k, v]) => `${k}@${v ?? '-'}`) + .join('; '); + } } +// Compose the sidebar with contributions from each part export const SideBar: React.FC = () => { const instance = useInject(ViewInstance); const providers = instance.providers.getContributions(); @@ -47,6 +99,10 @@ export const SideBar: React.FC = () => { return (
+ + + +
); }; @@ -59,7 +115,8 @@ export class SideBarView extends DefaultSlotView { constructor( // @ts-ignore - @contrib(SideBarContribution) providers: Contribution.Provider, + @contrib(SideBarContribution) + providers: Contribution.Provider, @inject(ViewManager) viewManager: ViewManager, ) { super(undefined, viewManager); diff --git a/packages/secretnote-lite/src/modules/markdown-editor/module.ts b/packages/secretnote-lite/src/modules/markdown-editor/module.ts index 0dc516d8..e848e518 100644 --- a/packages/secretnote-lite/src/modules/markdown-editor/module.ts +++ b/packages/secretnote-lite/src/modules/markdown-editor/module.ts @@ -1,3 +1,5 @@ +// Module for markdown cell. + import { CellOptions } from '@difizen/libro-jupyter'; import { ManaModule } from '@difizen/mana-app'; diff --git a/packages/secretnote-lite/src/modules/markdown-editor/view.tsx b/packages/secretnote-lite/src/modules/markdown-editor/view.tsx index f5a5331a..2204ab17 100644 --- a/packages/secretnote-lite/src/modules/markdown-editor/view.tsx +++ b/packages/secretnote-lite/src/modules/markdown-editor/view.tsx @@ -1,7 +1,7 @@ import type { CellCollapsible } from '@difizen/libro-jupyter'; import { LibroEditorCellView } from '@difizen/libro-jupyter'; import { prop, transient, useInject, view, ViewInstance } from '@difizen/mana-app'; -import React, { forwardRef } from 'react'; +import { forwardRef } from 'react'; import { Editor } from '@/components/markdown-editor'; diff --git a/packages/secretnote-lite/src/modules/metrics/index.less b/packages/secretnote-lite/src/modules/metrics/index.less new file mode 100644 index 00000000..0fbd50d6 --- /dev/null +++ b/packages/secretnote-lite/src/modules/metrics/index.less @@ -0,0 +1,24 @@ +.secretnote-kernel-status { + .title { + color: var(--mana-secretnote-text-color); + font-size: 14px; + font-weight: 600; + } + + .kernel-status-item { + padding: 8px; + background-color: var(--mana-secretnote-sidebar-background); + } + + .server-name { + color: var(--mana-secretnote-text-color); + font-size: 14px; + font-weight: 600; + text-align: left; + margin-bottom: 4px; + } + + .placeholder { + color: var(--mana-secretnote-text-color); + } +} diff --git a/packages/secretnote-lite/src/modules/metrics/index.ts b/packages/secretnote-lite/src/modules/metrics/index.ts new file mode 100644 index 00000000..20a96c9a --- /dev/null +++ b/packages/secretnote-lite/src/modules/metrics/index.ts @@ -0,0 +1 @@ +export * from './module'; diff --git a/packages/secretnote-lite/src/modules/metrics/module.ts b/packages/secretnote-lite/src/modules/metrics/module.ts new file mode 100644 index 00000000..12332bdb --- /dev/null +++ b/packages/secretnote-lite/src/modules/metrics/module.ts @@ -0,0 +1,17 @@ +// Metrics provides CPU/MEM usage information of each node. + +import { createViewPreference, ManaModule } from '@difizen/mana-app'; + +import { metricsMonitorKey } from '../layout'; +import { MetricsService } from './service'; +import { MetricsView } from './view'; + +export const MetricsModule = ManaModule.create().register( + MetricsView, + MetricsService, + createViewPreference({ + slot: metricsMonitorKey, + view: MetricsView, + autoCreate: true, + }), +); diff --git a/packages/secretnote-lite/src/modules/metrics/service.ts b/packages/secretnote-lite/src/modules/metrics/service.ts new file mode 100644 index 00000000..0d5b18f8 --- /dev/null +++ b/packages/secretnote-lite/src/modules/metrics/service.ts @@ -0,0 +1,207 @@ +// Service for metrics. + +import { inject, prop, singleton } from '@difizen/mana-app'; +import { Poll } from '@lumino/polling'; + +import { SecretNoteKernelManager } from '@/modules/kernel'; +import type { IServer, ServerStatus } from '@/modules/server'; +import { SecretNoteServerManager } from '@/modules/server'; +import { genericErrorHandler, request } from '@/utils'; + +import { IKernelConnection } from '@difizen/libro-jupyter'; +import { NotebookFileService } from '../notebook'; + +// The metrics information of one single server. +interface ServerMetric { + name: string; + status: ServerStatus; + cpu: number; // CPU usage percentage + memory: number; // Memory usage in bytes + totalMemory: number; // Total memory in bytes +} + +// The metrics information of all servers. +type ServerMetrics = Record; // server id -> server status + +@singleton() +export class MetricsService { + private _poller: Poll; // poller for metrics update + + protected readonly serverManager: SecretNoteServerManager; + protected readonly kernelManager: SecretNoteKernelManager; + protected readonly notebookFileService: NotebookFileService; + + @prop() metrics: ServerMetrics = {}; + @prop() dataSource: 'kernel_usage' | 'fallback' = 'kernel_usage'; + @prop() status: 'working' | 'no_notebook' | 'no_data' = 'no_data'; + @prop() enabled = false; + + constructor( + @inject(SecretNoteServerManager) serverManager: SecretNoteServerManager, + @inject(SecretNoteKernelManager) kernelManager: SecretNoteKernelManager, + @inject(NotebookFileService) notebookFileService: NotebookFileService, + ) { + this.serverManager = serverManager; + this.kernelManager = kernelManager; + this.notebookFileService = notebookFileService; + + this._poller = new Poll({ + auto: false, + factory: () => this.refresh(), + frequency: { + interval: 5000, + backoff: true, + max: 300 * 1000, + }, + name: 'metrics', + standby: 'when-hidden', + }); + } + + /** + * Enable the metrics monitor. + */ + async enable() { + await this.refresh(true); + await this._poller.start(); + await this._poller.tick; + this.enabled = true; + } + + /** + * Disable the metrics monitor. + */ + async disable() { + await this._poller.stop(); + this.enabled = false; + } + + /** + * Manually tick the poller. + */ + async tick() { + if (this.enabled) { + await this._poller.refresh(); + await this._poller.tick; + } + } + + /** + * Function on the poll to update metrics of all servers, + * or reset the metrics to default value. + */ + async refresh(reset = false) { + // get current notebook file + const currentNotebookFile = this.notebookFileService.currentNotebookFile; + if (!currentNotebookFile) { + this.status = 'no_notebook'; + return; + } + + // get all kernel connections + const kernelConnections = + this.kernelManager.getKernelConnections(currentNotebookFile); + + const serverIds: string[] = []; + kernelConnections.forEach(async (kernelConnection) => { + // get corresponding server + const server = this.kernelManager.getServerByKernelConnection(kernelConnection); + // fetch metrics + if (server) { + serverIds.push(server.id); + const data = reset ? {} : await this.fetchKernelUsage(kernelConnection, server); + this.metrics[server.id] = { + name: server.name, + status: server.status, + cpu: data.cpu || 0, + memory: data.memory || 0, + totalMemory: data.totalMemory || 0, + }; + } + }); + + // remove unavailable servers' metrics + for (const id in this.metrics) { + if (!serverIds.includes(id)) { + delete this.metrics[id]; + } + } + + this.status = 'working'; + } + + /** + * Fetch current kernel's resource usage from Jupyter Server's jupyter-resource-usage extension API. + */ + async fetchKernelUsage( + kernel: IKernelConnection, + server: IServer, + ): Promise>> { + // prefer to use kernel_usage API + if (this.dataSource === 'kernel_usage') { + try { + const { content } = await request< + { + content: Partial<{ + reason: string; + host_cpu_percent: number; + host_virtual_memory: { + total: number; + used: number; + percent: number; + }; + }>; + } & { [key: string]: any } + >( + `/api/metrics/v1/kernel_usage/get_usage/${kernel.id}`, + { method: 'GET' }, + server.id, + ); + if (content?.reason) { + throw new Error(content.reason); + } + + const { host_virtual_memory: vm } = content; + return { + cpu: content?.host_cpu_percent, + memory: vm?.total && vm?.percent ? (vm.total * vm.percent) / 100 : void 0, + totalMemory: vm?.total, + }; + } catch (e) { + // Sometimes this request will fail due to a upstream bug + // @see https://github.com/jupyter-server/jupyter-resource-usage/issues/220 + // we skip current tick and change the datasource for next ticks + genericErrorHandler(e, { silent: true }); + this.dataSource = 'fallback'; + } + } + + // use a fallback method to get metrics + if (this.dataSource === 'fallback') { + try { + const content = (await request( + `/api/metrics/v1`, + { method: 'GET' }, + server.id, + )) as Partial<{ + rss: number; + pss: number; + cpu_percent: number; + }>; + + return { + cpu: content?.cpu_percent, + memory: content?.pss || content?.rss, + totalMemory: void 0, // unknown + }; + } catch (e) { + // simply skip current tick + genericErrorHandler(e, { silent: true }); + } + } + + // noway to get metrics, give up + this.status = 'no_data'; + return {}; + } +} diff --git a/packages/secretnote-lite/src/modules/metrics/view.tsx b/packages/secretnote-lite/src/modules/metrics/view.tsx new file mode 100644 index 00000000..15399727 --- /dev/null +++ b/packages/secretnote-lite/src/modules/metrics/view.tsx @@ -0,0 +1,72 @@ +// The metrics panel component. + +import { + BaseView, + inject, + singleton, + useInject, + view, + ViewInstance, +} from '@difizen/mana-app'; +import { l10n } from '@difizen/mana-l10n'; +import { useEffect } from 'react'; + +import { convertSizeUnit } from '@/utils'; +import { Tag } from 'antd'; +import './index.less'; +import { MetricsService } from './service'; + +const MetricsComponent = () => { + const instance = useInject(ViewInstance); + const service = instance.service; + const { metrics, status } = service; + + useEffect(() => { + service.enable(); + + return () => { + service.disable(); + }; + }, []); + + const formatMetric = (v: (typeof metrics)[1]) => + `${l10n.t('CPU')} ${v.cpu.toFixed(1)} (%)` + + ` / ${l10n.t('内存')} ` + + `${convertSizeUnit(v.memory, 'GB').toFixed(1)} (GB)`; + + return ( +
+

{l10n.t('节点监控')}

+ + {Object.keys(metrics).length > 0 ? ( + Object.entries(metrics).map(([id, v]) => ( +
+
{v.name}
+ {formatMetric(v)} +
+ )) + ) : ( +
+ + {status === 'no_notebook' + ? l10n.t('暂无打开的 Notebook') + : l10n.t('暂无数据')} + +
+ )} +
+ ); +}; + +@singleton() +@view('secretnote-metrics-view') +export class MetricsView extends BaseView { + view = MetricsComponent; + service: MetricsService; + + constructor(@inject(MetricsService) service: MetricsService) { + super(); + + this.service = service; + } +} diff --git a/packages/secretnote-lite/src/modules/node/index.less b/packages/secretnote-lite/src/modules/node/index.less index efc29f07..be790dfd 100644 --- a/packages/secretnote-lite/src/modules/node/index.less +++ b/packages/secretnote-lite/src/modules/node/index.less @@ -5,6 +5,10 @@ padding-right: 24px; float: right; + .title { + color: var(--mana-secretnote-text-color) !important; + } + .ant-avatar-group .ant-badge:not(:first-child) { margin-left: -8px; } @@ -29,8 +33,8 @@ .secretnote-node-description { padding: 16px; - .ant-btn { - padding: 0; + .ant-descriptions-item { + padding-bottom: 8px !important; } .ant-typography { @@ -43,9 +47,16 @@ } .secretnote-add-node { - width: 400px; + width: 320px; padding: 16px; + .title { + font-size: 16px; + font-weight: 600; + color: rgba(45, 55, 72, 0.88); + margin-bottom: 20px; + } + label { color: var(--mana-secretnote-text-color) !important; } diff --git a/packages/secretnote-lite/src/modules/node/module.ts b/packages/secretnote-lite/src/modules/node/module.ts index f251c094..c21a4fbb 100644 --- a/packages/secretnote-lite/src/modules/node/module.ts +++ b/packages/secretnote-lite/src/modules/node/module.ts @@ -1,7 +1,8 @@ +// Node module is for node management displayed on right-top of the header area. + import { createViewPreference, ManaModule } from '@difizen/mana-app'; import { HeaderArea } from '@/modules/layout'; - import { NodeService } from './service'; import { NodeView } from './view'; diff --git a/packages/secretnote-lite/src/modules/node/service.ts b/packages/secretnote-lite/src/modules/node/service.ts index 1e2cda5d..9705587c 100644 --- a/packages/secretnote-lite/src/modules/node/service.ts +++ b/packages/secretnote-lite/src/modules/node/service.ts @@ -1,20 +1,27 @@ import { inject, singleton } from '@difizen/mana-app'; -import type { ServerStatus } from '@/modules/server'; +import type { IServer } from '@/modules/server'; import { SecretNoteServerManager } from '@/modules/server'; -import { randomHex } from '@/utils'; -export interface Node { - id: string; - name: string; - color: string; - status: ServerStatus; - service?: string; - podIp?: string; -} +/** + * Definition of a remote Node serving as Jupyter Server. + * Except those fields that Jupyter Server should have, we also have some + * additional fields because it's running inside K8s cluster. + */ +export type SecretNoteNode = IServer & { + service?: string; // service name inside K8s cluster + podIp?: string; // pod ip address inside K8s cluster + // resources and versions of internals + resourcesAndVersions?: Partial<{ + cpu: number; + memory: string; + image: string; + python: string; + secretflow: string; + }>; +}; -export type ServerStatusTag = 'processing' | 'default' | 'error' | 'success'; -const NODE_COLOR = randomHex(); +export type NodeStatusTag = 'processing' | 'default' | 'error' | 'success'; @singleton() export class NodeService { @@ -24,41 +31,48 @@ export class NodeService { this.serverManager = serverManager; } + /** + * Get loading status of the server manager. + */ get loading() { return this.serverManager.loading; } - get nodes() { + /** + * Get all remote nodes serving as Jupyter Server. + */ + get nodes(): SecretNoteNode[] { return this.serverManager.servers.map((server) => ({ ...server, - color: NODE_COLOR, + resourcesAndVersions: this.serverManager.resourcesAndVersions, })); } + /** + * Add a remote node serving as Jupyter Server to under management. + */ async addNode({ name }: { name: string; address: string }) { - return await this.serverManager.addServer({ - name: name.trim(), - }); + return await this.serverManager.addServer(name); } + /** + * Delete a remote node serving as Jupyter Server. + */ async deleteNode(id: string) { await this.serverManager.deleteServer(id); } + /** + * Start a remote node serving as Jupyter Server. + */ async startNode(id: string) { await this.serverManager.startServer(id); } + /** + * Stop a remote node serving as Jupyter Server. + */ async stopNode(id: string) { await this.serverManager.stopServer(id); } - - async updateNodeName(id: string, name: string) { - await this.serverManager.updateServer(id, { name }); - } - - protected checkName(name: string) { - const isValid = this.nodes.every((node) => node.name !== name); - return isValid; - } } diff --git a/packages/secretnote-lite/src/modules/node/view.tsx b/packages/secretnote-lite/src/modules/node/view.tsx index a5085d4b..f7eea0bb 100644 --- a/packages/secretnote-lite/src/modules/node/view.tsx +++ b/packages/secretnote-lite/src/modules/node/view.tsx @@ -1,3 +1,5 @@ +// The node management popover component. + import { BaseView, inject, @@ -12,161 +14,127 @@ import { Badge, Button, Descriptions, + Divider, Form, Input, message, Popover, + Progress, Space, - Typography, Spin, + Typography, } from 'antd'; import { Plus } from 'lucide-react'; import { useState } from 'react'; -import React from 'react'; - -import { invert } from '@/utils'; +import { genericErrorHandler, invert, randomColorByName, wait } from '@/utils'; import { ServerStatus } from '../server'; - import './index.less'; -import type { Node, ServerStatusTag } from './service'; +import type { NodeStatusTag, SecretNoteNode } from './service'; import { NodeService } from './service'; const { Paragraph } = Typography; -const getNodeStatus = (node: Node): { status: ServerStatusTag; text: string } => { - const status = node.status; - +/** + * Format the node status to a badge. + */ +const formatNodeStatus = ( + node: SecretNoteNode, +): { status: NodeStatusTag; text: string } => { + const { status } = node; if (status === ServerStatus.Pending) { return { status: 'processing', text: l10n.t('启动中'), }; } - if (status === ServerStatus.Succeeded || status === ServerStatus.Running) { return { status: 'success', text: l10n.t('在线'), }; } - return { status: 'error', text: l10n.t('离线'), }; }; -const NodeDetails = (props: { node: Node }) => { - const { node } = props; +/** + * The detailed information component of a node. + */ +const NodeDetails = (props: { node: SecretNoteNode }) => { const instance = useInject(ViewInstance); - const { status, text } = getNodeStatus(node); + const service = instance.service; + const { node } = props; + const { status, text } = formatNodeStatus(node); const [loading, setLoading] = useState(false); - // const [editableStr, setEditableStr] = useState(node.name); - - const deleteNode = async (id: string) => { - setLoading(true); - try { - await instance.service.deleteNode(id); - message.success(l10n.t('删除成功')); - } catch (e) { - if (e instanceof Error) { - message.error(e.message); - } - } finally { - setLoading(false); - } - }; - const startNode = async (id: string) => { + /** + * Alter the status of a node. + */ + const altNode = async ( + method: (id: string) => Promise, + id: string, + successText: string, + ) => { setLoading(true); try { - await instance.service.startNode(id); - message.success(l10n.t('启动成功')); + await method.call(service, id); + message.success(l10n.t(successText)); } catch (e) { - if (e instanceof Error) { - message.error(e.message); - } + genericErrorHandler(e); } finally { setLoading(false); } }; - const stopNode = async (id: string) => { - setLoading(true); - try { - await instance.service.stopNode(id); - message.success(l10n.t('停止成功')); - } catch (e) { - if (e instanceof Error) { - message.error(e.message); - } - } finally { - setLoading(false); - } - }; - - // const onChangeNodeName = async (n: Node, name: string) => { - // if (n.name === name) { - // return; - // } - // try { - // await instance.service.updateNodeName(n.id, name); - // setEditableStr(name); - // } catch (e) { - // if (e instanceof Error) { - // message.error(e.message); - // } - // } - // }; - return (
- - {node.name} - {/* onChangeNodeName(node, str), - tooltip: false, - }} - > - {editableStr} - */} - + {node.name} - {node.podIp || '暂无数据'} + + {node.podIp || l10n.t('暂无数据')} + + + + {`${node.resourcesAndVersions?.cpu}C` || l10n.t('暂无数据')} /{' '} + {node.resourcesAndVersions?.memory || l10n.t('暂无数据')} + + + {node.resourcesAndVersions?.image || l10n.t('暂无数据')} + + + {node.resourcesAndVersions?.python || l10n.t('暂无数据')} /{' '} + {node.resourcesAndVersions?.secretflow || l10n.t('暂无数据')} + {node.status === ServerStatus.Terminated && ( )} {node.status === ServerStatus.Succeeded && ( @@ -181,40 +149,43 @@ export const NodeComponent = () => { const [form] = Form.useForm(); const [addFormVisible, setAddFormVisible] = useState(false); const [addLoading, setAddLoading] = useState(false); + const [addProgress, setAddProgress] = useState(0); const instance = useInject(ViewInstance); + const service = instance.service; - const addNode = () => { - form - .validateFields() - .then(async (values) => { - setAddLoading(true); - - try { - const server = await instance.service.addNode(values); - if (server.status === ServerStatus.Succeeded) { - message.success(l10n.t('节点添加成功')); - } else { - message.info('节点添加成功,但是节点处于离线状态,请联系管理员'); - } - } catch (e) { - if (e instanceof Error) { - message.error(e.message); - } - } - - setAddFormVisible(false); - form.resetFields(); - setAddLoading(false); - return; - }) - .catch(() => { - // - }); + const handleAddNode = async () => { + const values = await form.validateFields(); + setAddLoading(true); + // Simulate the progress of adding a node + const interval = setInterval( + () => setAddProgress((prev) => (prev >= 95 ? prev : Math.min(prev + 3, 95))), + 1000, // ~30s in total + ); + try { + const server = await service.addNode(values); + if (server.status === ServerStatus.Succeeded) { + message.success(l10n.t('节点添加成功')); + } else { + message.info(l10n.t('节点添加成功,但处于离线状态,请刷新页面或联系管理员')); + } + setAddProgress(100); + await wait(1000); + } catch (e) { + genericErrorHandler(e); + } finally { + setAddLoading(false); + clearInterval(interval); + form.resetFields(); + setAddProgress(0); + setAddFormVisible(false); + } }; const addNodeFormContent = (
+
{l10n.t('添加节点')}
{ rules={[ { required: true, message: l10n.t('请输入名称') }, { max: 16, message: l10n.t('名称过长') }, - { pattern: /^[A-Za-z]+$/, message: l10n.t('名称只能包含英文字母') }, + { + pattern: /^[a-z]+$/, + message: l10n.t('名称只能包含小写英文字母'), + }, ]} + style={{ marginBottom: '12px' }} > + {addLoading && ( + + + + )} - - - +
@@ -253,24 +235,33 @@ export const NodeComponent = () => { return (
+ 节点列表:  - {instance.service.nodes.map((item) => ( + {service.nodes.map((node) => ( } + key={node.id} + content={} title="" overlayStyle={{ width: 380 }} trigger="click" placement="bottomLeft" arrow={false} > - + - - {item.name.slice(0, 1).toUpperCase()} + + {node.name.slice(0, 1).toUpperCase()} @@ -279,8 +270,7 @@ export const NodeComponent = () => { { }} arrow={false} > + {/* Add two nodes at most */} {instance.service.nodes.length < 2 && ( - )} -
- ); -}; - -const PrepareDatasetDes = (props: DescriptionProps) => { - return ( -
-
- 我们需要一个数据集来构建垂直分区的场景。可以点击下面的两个链接下载数据集。 -
- -
下载后分别上传到两个节点上。
- upload file -
    -
  • 最大上传文件大小限制为 32M。
  • -
  • 只支持上传 csv、txt 格式文件。
  • -
- {!props.finished && ( - - )} -
- ); -}; - -const RunningNotebookDes = (props: DescriptionProps) => { - return ( -
-
- 我们继续点击下面的链接下载一份示例代码,然后导入到 Notebook 列表中。 -
- -
- Notebook 的操作方式和 Jupyter Notebook - 一致,并且在此基础上做了许多针对性的功能优化,比如 Python - 单元格可以选择多个节点同时去执行,然后将执行结果汇总起来输出。这给隐语多控制器执行的开发模式带来了较大的便利。 -
- python cell -
    -
  • 需要将示例代码中的 address 替换成对应节点的 IP,端口号不需要修改。
  • -
  • - 如果需要安装额外的 pip 包,请使用阿里云镜像 pip install --index - https://mirrors.aliyun.com/pypi/simple/ package_name -
  • -
- {!props.finished && ( - - )} -
- ); -}; - -const CheckResultDes = (props: DescriptionProps) => { - return ( -
-
- 完成执行后,刷新文件列表,会看到新生成的隐私求交结果文件。 -
- view file -
    -
  • - 由于资源有限,每个人默认会有 10h 体验时间, - 添加两个节点时间会累加,所以推荐使用单个节点仿真模式进行开发,验证的时候使用两个节点。 -
  • -
  • - 请在离开页面之前停止或者删除计算节点,否则会持续计时,造成计算资源浪费。如果时间到期,请联系管理员进行升级。 -
  • -
- {!props.finished && ( - - )} -
- ); -}; +import WelcomeMarkdown from './welcome.md'; export const WelcomeComponent = () => { const instance = useInject(ViewInstance); + // Parse markdown content. + const _markdowns = mdToHTMLSegments(WelcomeMarkdown as unknown as string); + const titleMarkdown = _markdowns[0]; + const contentMarkdowns = _markdowns.slice(1); + useConfetti({ zIndex: 2000, spread: 500, predicate: () => { - if (instance.currentStep > 3 && !instance.finished) { - return new Promise((resolve) => { - setTimeout(() => resolve('confetti'), 100); - }); + if (instance.currentStep > contentMarkdowns.length - 1 && !instance.finished) { + return new Promise((resolve) => setTimeout(() => resolve('confetti'), 100)); } return Promise.resolve(undefined); }, }); - const done = (step: number) => { - instance.setCurrentStep(step + 1); - }; - return (
-
-
-
欢迎使用在线实验环境
-
- 下面是一个在两方节点上执行 - -  SPU 隐私求交  - - 的示例,请跟随示例一步步熟悉基本操作吧! -
-
- - 准备节点
, - description: ( - 0} done={done} /> - ), - }, - { - title:
准备数据
, - description: ( - 1} done={done} /> - ), - }, - { - title:
运行 Notebook
, - description: ( - 2} done={done} /> - ), - }, - { - title:
验证结果
, - description: ( - 3} done={done} /> - ), - }, - ]} - /> -
+
+ { + return { + description: ( +
+
+ {idx === instance.currentStep && ( + + )} +
+ ), + }; + })} + />
); }; @@ -244,29 +74,18 @@ export const WelcomeComponent = () => { @view('secretnote-welcome-view') export class WelcomeView extends BaseView { view = WelcomeComponent; - protected storageService: StorageService; - - @prop() - currentStep = 0; - @prop() - finished = false; + @prop() currentStep = 0; + @prop() finished = false; - constructor(@inject(StorageService) storageService: StorageService) { + constructor() { super(); - this.storageService = storageService; - this.getCurrentStep(); - } - - async getCurrentStep() { - const step = await this.storageService.getData('tutorial-step'); - this.currentStep = step || 0; - this.finished = step === 4; - return step; } - async setCurrentStep(step: number) { - this.currentStep = step; - await this.storageService.setData('tutorial-step', step); + /** + * Go to the next step. + */ + nextStep() { + this.currentStep += 1; } } diff --git a/packages/secretnote-lite/src/modules/welcome/welcome.md b/packages/secretnote-lite/src/modules/welcome/welcome.md new file mode 100644 index 00000000..cb5d7ea5 --- /dev/null +++ b/packages/secretnote-lite/src/modules/welcome/welcome.md @@ -0,0 +1,51 @@ +# 欢迎使用 SecretNote 在线实验环境 + +下面是一个在两方节点上执行 [SPU 隐私求交](https://www.secretflow.org.cn/docs/secretflow/latest/zh-Hans/tutorial/PSI_On_SPU) 的示例。请跟随示例一步步熟悉基本操作吧! + +--- + +## 准备节点 + +在页面右上角点击添加节点,输入节点名称即可添加一个计算节点。 + +![add_node](https://mdn.alipayobjects.com/huamei_usjdcg/afts/img/A*eW10TZkpAbgAAAAAAAAAAAAADo6HAQ/fmt.webp) + +- 添加过程大概需要 30s,请耐心等待。 +- 节点名称后续会在初始化代码中使用。 +- 添加成功后,节点详情中可看到节点 IP,作为节点之间的通信地址。 + +--- + +## 准备数据 + +我们需要一个数据集来构建垂直分区的场景。可以点击 [iris_alice.csv](https://github.com/secretflow/secretnote/blob/main/docs/guide/data/iris_alice.csv) 和 [iris_bob.csv](https://github.com/secretflow/secretnote/blob/main/docs/guide/data/iris_bob.csv) 下载示例数据集。下载后分别上传到两个节点上。 + +![upload_data](https://mdn.alipayobjects.com/huamei_usjdcg/afts/img/A*GR6hSori6ekAAAAAAAAAAAAADo6HAQ/fmt.webp) + +- 只支持上传 csv 和 txt 格式的文件。 +- 最大上传文件大小限制为 32M。 +- 如需使用其他外部数据集,请在本地下载后上传至节点,不建议直接通过代码在节点上下载。 + +--- + +## 运行 Notebook + +我们继续点击 [psi.ipynb](https://github.com/secretflow/secretnote/blob/main/docs/guide/data/psi.ipynb) 下载一份示例代码,然后导入到 Notebook 列表中。 + +SecretNote 的操作方式和 Jupyter Notebook 基本一致,并做了许多针对性的功能优化。比如 Python 单元格可选择多个节点同时执行,然后将执行结果汇总输出,这给隐语多控制器执行的开发模式带来了便利。 + +![python_cell](https://mdn.alipayobjects.com/huamei_usjdcg/afts/img/A*dJVKTbT0KwAAAAAAAAAAAAAADo6HAQ/fmt.webp) + +- 需将示例代码中的 address 替换成对应节点的 IP,端口号不需要修改。 +- 如需安装其他 pip 包,请执行 `!pip install -i https://mirrors.aliyun.com/pypi/simple/ <包名>` 指定阿里云源安装 + +--- + +## 验证结果 + +完成执行后,刷新文件列表,会看到新生成的隐私求交结果文件。 + +![view_result](https://mdn.alipayobjects.com/huamei_usjdcg/afts/img/A*0LTDTYc9Tl4AAAAAAAAAAAAADo6HAQ/fmt.webp) + +- 因资源有限,每个人默认有 10h 体验时间。添加两个节点时间会累加,故推荐使用单节点仿真模式进行实验,而验证时使用两个节点。 +- 请在离开页面前停止或删除节点,否则会持续计时,造成计算资源浪费。如果时间用尽,请联系管理员进行升级。 diff --git a/packages/secretnote-lite/src/utils/color.ts b/packages/secretnote-lite/src/utils/color.ts index 60f1f2d3..927f14ee 100644 --- a/packages/secretnote-lite/src/utils/color.ts +++ b/packages/secretnote-lite/src/utils/color.ts @@ -1,10 +1,14 @@ -export function randomHex() { - const letters = '0123456789ABCDEF'; - let color = '#'; - for (let i = 0; i < 6; i += 1) { - color += letters[Math.floor(Math.random() * 16)]; +/** + * Hash an ascii string to a hex color. + */ +export function randomColorByName(name: string) { + let hash = 0; + for (let i = 0; i < name.length; i++) { + hash = name.charCodeAt(i) + hash * 7; // 7 is a prime number randomly picked } - return color; + const c = (hash & 0x00ffffff).toString(16).padStart(6, '0'); + + return `#${c}`; } export function hex2rgb(hex: string): [number, number, number] { @@ -25,6 +29,9 @@ export function hex2rgb(hex: string): [number, number, number] { return [bgr[2], bgr[1], bgr[0]]; } +/** + * Determine a suitable text color (black or white) for a given background color. + */ export function invert(hex: string): string { const [r, g, b] = hex2rgb(hex); return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? '#000000' : '#ffffff'; diff --git a/packages/secretnote-lite/src/utils/error.ts b/packages/secretnote-lite/src/utils/error.ts new file mode 100644 index 00000000..1417aac8 --- /dev/null +++ b/packages/secretnote-lite/src/utils/error.ts @@ -0,0 +1,31 @@ +import { message } from 'antd'; + +/** + * A generic error handler that shows a message and logs the error. + */ +export function genericErrorHandler( + e: any, + options: { + silent?: boolean; + reThrow?: boolean; + } = {}, +) { + if (!options?.silent) { + message.error(e?.message || e.toString()); + console.error(e); + } + // eslint-disable-next-line no-console + if (options?.reThrow) { + throw e; + } +} + +/** + * Create an not-implemented function placeholder. + */ +export function createNotImplemented(name: string) { + return (...args: any) => { + throw new Error(`Method \`${name}\` is not implemented.`); + return void 0 as any; + }; +} diff --git a/packages/secretnote-lite/src/utils/file.ts b/packages/secretnote-lite/src/utils/file.ts index 1f3417e8..5e46ddaa 100644 --- a/packages/secretnote-lite/src/utils/file.ts +++ b/packages/secretnote-lite/src/utils/file.ts @@ -53,7 +53,7 @@ export async function readFile(file: File): Promise { }); } -export async function readCsvFile(file: File): Promise { +export async function readCSVFile(file: File): Promise { return await CsvFileReader.csvReader({ file: file, config: { @@ -84,7 +84,10 @@ export const downloadFileByBlob = (url: string, filename = '', method = 'GET') = }); }; -export const downloadFileByUrl = (url: string, filename: string, target?: string) => { +/** + * Create a download link and click it to download the file. + */ +export const downloadFileByURL = (url: string, filename: string, target?: string) => { const downloadElement = document.createElement('a'); downloadElement.style.display = 'none'; downloadElement.href = url; @@ -99,3 +102,28 @@ export const downloadFileByUrl = (url: string, filename: string, target?: string downloadElement.click(); document.body.removeChild(downloadElement); }; + +/** + * Convert byte to other size unit. + */ +export const convertSizeUnit = ( + byte: number, + unit: 'B' | 'KB' | 'MB' | 'GB' | 'TB' | 'PB', +) => { + const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; + const index = units.indexOf(unit); + let size = byte; + for (let i = 0; i < index; i++) { + size /= 1024; + } + return size; +}; + +/** + * Normalize a extension name, guarantee it starts with a dot. + */ +export function normalizeExtension(extension: string): string { + return extension.length > 0 && extension.indexOf('.') !== 0 + ? `.${extension}` + : extension; +} diff --git a/packages/secretnote-lite/src/utils/index.ts b/packages/secretnote-lite/src/utils/index.ts index 0848bff1..8b730038 100644 --- a/packages/secretnote-lite/src/utils/index.ts +++ b/packages/secretnote-lite/src/utils/index.ts @@ -1,6 +1,7 @@ -export * from './color'; export * from './array'; +export * from './color'; +export * from './error'; export * from './file'; -export * from './string'; -export * from './request'; export * from './promise'; +export * from './request'; +export * from './string'; diff --git a/packages/secretnote-lite/src/utils/request.ts b/packages/secretnote-lite/src/utils/request.ts index 77600f87..bd29bd89 100644 --- a/packages/secretnote-lite/src/utils/request.ts +++ b/packages/secretnote-lite/src/utils/request.ts @@ -1,6 +1,14 @@ -import type { ISettings } from '@difizen/libro-jupyter'; +// Customized request definitions and functions for SecretNote. + +import type { ISettings, JSONPrimitive } from '@difizen/libro-jupyter'; import { URL as LibroURL } from '@difizen/libro-jupyter'; +import { genericErrorHandler } from './error'; +/** + * Get the base URL of a remote server for HTTP requests. + * If `targetId` is provided, the base URL goes into a specific K8s Pod. + * Otherwise it goes to the default web server. + */ export const getRemoteBaseUrl = (targetId = '', endSlash = false) => { const backendUrl = process.env.PB_BACKEND_URL; const origin = @@ -9,6 +17,11 @@ export const getRemoteBaseUrl = (targetId = '', endSlash = false) => { return origin + '/secretnote/' + targetId + `${endSlash ? '/' : ''}`; }; +/** + * Get the base URL of a remote server for WebSocket requests. + * If `targetId` is provided, the base URL goes into a specific K8s Pod. + * Otherwise it goes to the default web server. + */ export const getRemoteWsUrl = (targetId = '', endSlash = false) => { return getRemoteBaseUrl(targetId, endSlash).replace(/^http/, 'ws'); }; @@ -27,47 +40,58 @@ export class ResponseError extends Error { } } +/** + * Create a ResponseError from a Response object. + */ export const createResponseError = async (response: Response) => { try { const data = await response.json(); - if (data.message) { - return new ResponseError(response, data.message); - } - return new ResponseError(response); + return new ResponseError(response, data?.message); } catch (e) { - // eslint-disable-next-line no-console - console.log(e); + genericErrorHandler(e, { silent: true }); return new ResponseError(response); } }; -const normalizeUrl = (url: string, targetId = '') => { +/** + * Normalize a URL, prepending the base URL of a remote server. + * If `targetId` is provided, the base URL goes into a specific K8s Pod. + * Otherwise it goes to the default web server. + */ +const normalizeURL = (url: string, targetId = '') => { const urlObj = new URL(LibroURL.join(getRemoteBaseUrl(targetId), url)); return urlObj.href; }; -const getCookie = (name: string): string | undefined => { - // From http://www.tornadoweb.org/en/stable/guide/security.html +/** + * Get a cookie by name. + */ +const getCookie = (name: string) => { + // from http://www.tornadoweb.org/en/stable/guide/security.html const matches = document.cookie.match('\\b' + name + '=([^;]*)\\b'); return matches?.[1]; }; -export const getToken = () => { - const auth = localStorage.getItem('pocketbase_auth'); +/** + * Get the authentication token from the local storage. + */ +export const getToken = (key = 'pocketbase_auth'): string | null => { + const auth = localStorage.getItem(key); if (auth) { try { - const parsedAuth = JSON.parse(auth); - return parsedAuth.token; + return JSON.parse(auth).token; } catch (e) { - // eslint-disable-next-line no-console - console.error(e); + genericErrorHandler(e); return null; } } return null; }; -export const getDefaultConnectionSettings: () => Partial = () => { +/** + * Default server connection settings and token for API about notebooks. + */ +export const getDefaultServerConnectionSettings = () => { return { init: { cache: 'no-store', @@ -78,48 +102,90 @@ export const getDefaultConnectionSettings: () => Partial = () => { }, token: getToken(), appendToken: true, - }; + } as Partial; }; -export const request = async (url: string, init: RequestInit, targetId = '') => { - let requestUrl = normalizeUrl(url, targetId); - - const cache = init.cache ?? 'no-store'; - if (cache === 'no-store') { - requestUrl += (/\?/.test(url) ? '&' : '?') + new Date().getTime(); - } - +/** + * Make a never-cache HTTP request to the server. + * If `targetId` is provided, the request goes into a specific K8s Pod. + * Otherwise it goes to the default web server. + * Token will be carried if there are any. + * This method will not unpack the Response to JSON. + */ +export const requestNoUnpack = async ( + url: string, + init: RequestInit, + targetId = '', +) => { + // normalize the URL + let requestUrl = normalizeURL(url, targetId); + // forcely avoid caching by adding a timestamp + // because some clients or servers might not handle cache headers properly + requestUrl += (/\?/.test(url) ? '&' : '?') + new Date().getTime(); + + // construct the Request for fetch API const req = new window.Request(requestUrl, { cache: 'no-store', credentials: 'same-origin', ...init, }); - + // handle authentication const token = getToken(); - if (token) { - req.headers.append('Authorization', token); - } - if (typeof document !== 'undefined' && document?.cookie) { + token && req.headers.append('Authorization', token); + // handle XSRF protection + if (document?.cookie) { const xsrfToken = getCookie('_xsrf'); - if (xsrfToken !== undefined) { - req.headers.append('X-XSRFToken', xsrfToken); - } + xsrfToken && req.headers.append('X-XSRFToken', xsrfToken); } - + // all requests are JSON req.headers.set('Content-Type', 'application/json'); - const response = await window.fetch(req); + // fire the request + return await window.fetch(req); +}; +/** + * Make a never-cache HTTP request to the server. + * If `targetId` is provided, the request goes into a specific K8s Pod. + * Otherwise it goes to the default web server. + * Token will be carried if there are any. + */ +export const request = async ( + url: string, + init: RequestInit, + targetId = '', +): Promise => { + const response = await requestNoUnpack(url, init, targetId); + // handle the response if (response.status === 204) { - return; + return {} as T; } - if (response.status === 200) { - const data = await response.json(); - return data; + return await response.json(); } + throw await createResponseError(response); +}; - const err = await createResponseError(response); +/** + * node:querystring.stringify replacement for unnested values. + */ +export function querystringStringify( + params: Record, +) { + return Object.entries(params) + .filter(([_, v]) => v !== void 0) + .map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`) + .join('&'); +} - throw err; +/** + * Get search parameters of current location by keys. + */ +export const getSearchParams = (...key: string[]) => { + const searchParams = new URLSearchParams(window.location.search); + const res: string[] = []; + key.forEach((k) => { + res.push(searchParams.get(k) || ''); + }); + return res; }; diff --git a/packages/secretnote-lite/src/utils/string.ts b/packages/secretnote-lite/src/utils/string.ts index aed210d3..d3bb59f5 100644 --- a/packages/secretnote-lite/src/utils/string.ts +++ b/packages/secretnote-lite/src/utils/string.ts @@ -1,3 +1,7 @@ +import Markdown from 'markdown-it'; +/** + * Generate a random UUID. + */ export function uuid(): string { let res = ''; const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'; @@ -11,23 +15,46 @@ export function uuid(): string { return res; } -export const getSearchParams = (...key: string[]) => { - const searchParams = new URLSearchParams(window.location.search); - const res: string[] = []; - key.forEach((k) => { - res.push(searchParams.get(k) || ''); - }); - return res; +/** + * Compare two date strings and return 1 if a > b, -1 if a < b, 0 elsewise. + */ +export const compareDateString = (a: string, b: string) => { + const aDate = new Date(a), + bDate = new Date(b); + + return aDate > bDate ? 1 : aDate < bDate ? -1 : 0; }; -export const compareDateString = (a: string, b: string) => { - const aDate = new Date(a); - const bDate = new Date(b); - if (aDate > bDate) { - return 1; - } - if (aDate < bDate) { - return -1; +/** + * Convert a markdown string to HTML. + */ +export function mdToHTML( + mdstr: string, + options?: { openInNewTab?: boolean; ignoreDivider?: boolean }, +) { + const md = Markdown(); + + if (options?.openInNewTab) { + const defaultRender = + md.renderer.rules.link_open || + function (tokens, idx, options, env, self) { + return self.renderToken(tokens, idx, options); + }; + // let the user open links in a new tab + md.renderer.rules.link_open = function (tokens, idx, options, env, self) { + tokens[idx].attrSet('target', '_blank'); + return defaultRender(tokens, idx, options, env, self); + }; } - return 0; -}; + + return md.render(mdstr); +} + +/** + * Convert a markdown string to HTML segments separated by '---'. + */ +export function mdToHTMLSegments(mdstr: string) { + const parts = mdstr.split('---'); + + return parts.map((v) => mdToHTML(v, { openInNewTab: true })); +} diff --git a/packages/secretnote-lite/tsconfig.json b/packages/secretnote-lite/tsconfig.json index 35e3dacb..25bd8459 100644 --- a/packages/secretnote-lite/tsconfig.json +++ b/packages/secretnote-lite/tsconfig.json @@ -6,7 +6,7 @@ "allowJs": true, "skipLibCheck": true, "moduleResolution": "bundler", - "noEmit": true, + // "noEmit": true, "jsx": "react-jsx", "esModuleInterop": true, "sourceMap": true, @@ -15,10 +15,10 @@ "allowSyntheticDefaultImports": true, "baseUrl": ".", "paths": { - "@/*": ["src/*"], + "@/*": ["src/*"] }, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "importHelpers": false, - }, + "importHelpers": false + } } diff --git a/packages/secretnote-lite/tsup.config.js b/packages/secretnote-lite/tsup.config.js index 2f42fb3d..3bfb4b83 100644 --- a/packages/secretnote-lite/tsup.config.js +++ b/packages/secretnote-lite/tsup.config.js @@ -1,5 +1,5 @@ const { spawn } = require('child_process'); - +const { writeFileSync } = require('fs'); const { yellow } = require('colorette'); const svgr = require('esbuild-plugin-svgr'); const { defineConfig } = require('tsup'); @@ -24,7 +24,7 @@ const emitDeclarations = (outDir) => '--declarationDir', outDir, ], - { stdio: ['ignore', 'ignore', 'ignore'] }, + { stdio: ['inherit', 'inherit', 'inherit'] }, ); proc.on('exit', () => { console.timeEnd(timer); @@ -33,16 +33,22 @@ const emitDeclarations = (outDir) => proc.on('error', reject); }); +const dtsIndex = `declare const App: () => JSX.Element; +export { App as default };`; + module.exports = defineConfig((overrides) => ({ outDir: 'dist', - format: ['esm', 'cjs'], - outExtension: ({ format }) => ({ js: `.${format}.js` }), + format: ['esm'], //, 'cjs'], + outExtension: () => ({ js: `.js` }), sourcemap: true, dts: false, loader: { '.less': 'copy', + '.md': 'text', }, esbuildPlugins: [svgr()], - onSuccess: () => emitDeclarations('./dist/typing'), + onSuccess() { + writeFileSync('./dist/index.d.ts', dtsIndex); + }, clean: overrides.clean || !overrides.watch, })); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9bf784cc..00fce882 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 2.27.7 '@commitlint/cli': specifier: ^17.8.1 - version: 17.8.1(@swc/core@1.7.2) + version: 17.8.1(@swc/core@1.7.2(@swc/helpers@0.5.1)) '@commitlint/config-conventional': specifier: ^17.8.1 version: 17.8.1 @@ -64,13 +64,13 @@ importers: version: 3.0.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + version: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) lint-staged: specifier: ^13.3.0 version: 13.3.0(enquirer@2.4.1) nx: specifier: ^17.2.0 - version: 17.3.2(@swc/core@1.7.2) + version: 17.3.2(@swc/core@1.7.2(@swc/helpers@0.5.1)) openapi-typescript-codegen: specifier: ^0.25.0 version: 0.25.0 @@ -118,10 +118,10 @@ importers: version: 6.0.4(stylelint@15.11.0(typescript@5.5.4)) ts-node: specifier: ^10.9.1 - version: 10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4) + version: 10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4) tsup: specifier: ^6.7.0 - version: 6.7.0(@swc/core@1.7.2)(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4))(typescript@5.5.4) + version: 6.7.0(@swc/core@1.7.2(@swc/helpers@0.5.1))(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4))(typescript@5.5.4) typescript: specifier: ^5.2.2 version: 5.5.4 @@ -274,7 +274,7 @@ importers: version: 0.8.10(@tiptap/core@2.5.7(@tiptap/pm@2.5.7)) umi: specifier: ^4.0.86 - version: 4.3.10(@babel/core@7.24.9)(@types/node@20.5.1)(@types/react@18.3.3)(@types/webpack@4.41.0)(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)))(lightningcss@1.22.1)(postcss-less@6.0.0(postcss@8.4.40))(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.29.4)(sass@1.77.8)(sockjs-client@1.4.0)(stylelint@15.11.0(typescript@4.2.3))(terser@5.31.3)(type-fest@2.19.0)(typescript@4.2.3)(webpack-dev-server@3.10.3(webpack@4.41.5))(webpack@4.41.5) + version: 4.3.10(@babel/core@7.24.9)(@types/node@20.5.1)(@types/react@18.3.3)(@types/webpack@4.41.0)(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)))(lightningcss@1.22.1)(postcss-less@6.0.0(postcss@8.4.40))(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.29.4)(sass@1.77.8)(sockjs-client@1.4.0)(stylelint@15.11.0(typescript@4.2.3))(terser@5.31.3)(type-fest@2.19.0)(typescript@4.2.3)(webpack-dev-server@3.10.3(webpack@4.41.5))(webpack@4.41.5) xterm: specifier: ^5.3.0 version: 5.3.0 @@ -319,23 +319,29 @@ importers: specifier: ^1.52.0 version: 1.55.8(@antv/g-base@0.5.16) '@difizen/libro-jupyter': - specifier: ^0.1.22 - version: 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(mapbox-gl@1.13.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^0.2.20 + version: 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(mapbox-gl@1.13.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-language-client': + specifier: ^0.2.20 + version: 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/mana-app': - specifier: ^0.1.10 + specifier: ^0.1.19 version: 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/mana-common': - specifier: ^0.1.10 + specifier: ^0.1.19 version: 0.1.19 '@difizen/mana-l10n': - specifier: ^0.1.10 + specifier: ^0.1.19 version: 0.1.19(react@18.3.1) '@difizen/mana-react': - specifier: ^0.1.10 + specifier: ^0.1.19 version: 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@kanaries/web-data-loader': specifier: ^0.1.7 version: 0.1.7 + '@lumino/polling': + specifier: ^2.1.3 + version: 2.1.3 '@tiptap/core': specifier: ^2.1.11 version: 2.5.7(@tiptap/pm@2.5.7) @@ -402,6 +408,9 @@ importers: lucide-react: specifier: ^0.284.0 version: 0.284.0(react@18.3.1) + markdown-it: + specifier: ^14.1.0 + version: 14.1.0 monaco-editor: specifier: ^0.45.0 version: 0.45.0 @@ -457,6 +466,12 @@ importers: esbuild-plugin-svgr: specifier: ^1.1.0 version: 1.1.0 + tsup: + specifier: ^8.2.4 + version: 8.2.4(@swc/core@1.7.2(@swc/helpers@0.5.1))(postcss@8.4.40)(typescript@5.5.4)(yaml@2.5.0) + typescript: + specifier: ^5.5.4 + version: 5.5.4 packages/secretnote-ui: dependencies: @@ -505,7 +520,7 @@ importers: version: 7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@storybook/react-vite': specifier: ^7.5.1 - version: 7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.29.4)(typescript@5.5.4)(vite@4.5.3(@types/node@20.5.1)(less@4.2.0)(lightningcss@1.22.1)(sass@1.77.8)(terser@5.31.3)) + version: 7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.1)(typescript@5.5.4)(vite@4.5.3(@types/node@20.5.1)(less@4.2.0)(lightningcss@1.22.1)(sass@1.77.8)(terser@5.31.3)) '@storybook/testing-library': specifier: ^0.2.2 version: 0.2.2 @@ -1987,136 +2002,271 @@ packages: peerDependencies: react: '>=16' + '@difizen/libro-code-cell@0.2.24': + resolution: {integrity: sha512-R3PaNHZ/o2GCy54kCHbZXoiubVOHQKPHvJmuYggaXi/UciYewuKypAeKETaS64RetE8vTglQdSjBqNRcuWELEw==} + peerDependencies: + react: '>=16' + '@difizen/libro-code-editor@0.1.37': resolution: {integrity: sha512-YGj8YVgUBiBrbSn/iUXG6m6frqi7QoRhYzK9v3MqbXdBg573xF2A38rz+WHNFbl+IaE9wuJzfqne5xG6WxnNTQ==} peerDependencies: react: '>=16' + '@difizen/libro-code-editor@0.2.24': + resolution: {integrity: sha512-WLUx5PnOZOP2B0mGv35lYf3ebWRjVLvrzXtRP6CSvZwH3KcXUpKrRwScBovSUHF4DnmX3g92vB+82rUEYVi5Vw==} + peerDependencies: + react: '>=16' + '@difizen/libro-codemirror@0.1.37': resolution: {integrity: sha512-BIw9aonrluLrx5fNHv1ilS8xADDXSys7ToK3J21dxTz1ep580TDUWHsOJJ5Vegh2ooBMlfixu8QgwenFaPXgQg==} + '@difizen/libro-codemirror@0.2.24': + resolution: {integrity: sha512-myRquLMPT3K1DMxogb1KCQRWWKnWnvPib/wzcJ/kgx+R8n/Zanj5016TEjhy87p69IRAC2lzZkIba1y+y2xMwg==} + '@difizen/libro-cofine-editor-contribution@0.1.37': resolution: {integrity: sha512-ONHQ5foeZOE6fQvkZFZUfQ0rxy1pGLlTVlXass0aETRPoHWQHW3Bm0r/eT9WtNP7BNFDqBEOiWQ9snrPKVSxQA==} + '@difizen/libro-cofine-editor-contribution@0.2.24': + resolution: {integrity: sha512-Y1KfbkPwfhFDK8XiXfpf1+KDlxvbyBoeMUUq4yE7meh0CTDTdCuLAxo9IMzj4iUPyyjpPvzWqo6xxbWisG0ZVA==} + '@difizen/libro-cofine-editor-core@0.1.37': resolution: {integrity: sha512-x0CBN1jYXG2UU+nPZFHGhqnsbYtdG+mk18w+LuoOlAnFfYFcrknuIq1Rf/cXk+PvGHj3FNaH57++g1t4zrH0Xw==} + '@difizen/libro-cofine-editor-core@0.2.24': + resolution: {integrity: sha512-44MSIF31LVorw29QoHAesWmVXTw3UuZ2oMBpSoWVhJdVMHc5zKHpurPjrsTWckT14YghS8GkVgAsKx9fgMk3vA==} + '@difizen/libro-cofine-editor@0.1.37': resolution: {integrity: sha512-Y3/ShBcedzoupygFjJOU71+5PuuDm4QCRunFm4gTdOz3bOqpMC4/Al/3IUybXMMmnSX9DQhO/UNkuz9tRi5ZAg==} peerDependencies: react: '>=16' + '@difizen/libro-cofine-editor@0.2.24': + resolution: {integrity: sha512-q44lk7wgk8YoUF0oWNqywDn4RRuPSxBTVc7f3YiDlA3MXmihvK8ku0Lb7if9HmfFpTzueh8O9U92dSTvu8+YqA==} + peerDependencies: + react: '>=16' + '@difizen/libro-cofine-textmate@0.1.37': resolution: {integrity: sha512-f6JPZ0e5z8LY5Z2zYKx3+X4TbBb0bMsM4hdyGC0YIjEcXYqHjJ0S7VhsG7cytOwmqrGrqoghJADje0fnvU0Sfw==} + '@difizen/libro-cofine-textmate@0.2.24': + resolution: {integrity: sha512-PINn1niT8HgT4EODjyYSO6iWMA4TVTzHPoq83cYtn6utFOdpmgOBNJy4ZR3sqa1EVXh5QuvLPMDyaWEJKEQN9A==} + '@difizen/libro-common@0.1.37': resolution: {integrity: sha512-RZUjqp2HKzoOXd5aKjZtcCJA4581QFWz2xOWHYg32YQm9Y4ynoFeVeP6SVjoWBzTSsAAQpRo8+g3VOoY3u6yoA==} peerDependencies: react: '>=16' + '@difizen/libro-common@0.2.24': + resolution: {integrity: sha512-PNJflwV09xfSfLrim6hbWaW9H/moi0+VF/8TWKjpvrBhXSnzDWI93nJmpLP5Z/3OjQMG+/g+gnhatTkK5FQ2iA==} + peerDependencies: + react: '>=16' + '@difizen/libro-core@0.1.37': resolution: {integrity: sha512-WtPm41uD9Erhy+iCsRx2BqGZcZnmGu0Jn8y/4m4s2LKqdGzfnk8u6TdDeJ/cFpTfBe7FKwPa6nAePPPJvA6+pA==} peerDependencies: antd: ^5.8.6 react: '>=16' + '@difizen/libro-core@0.2.24': + resolution: {integrity: sha512-0Ancmoz/bEXN9RNuhBtX+dZLDDC9NQPXBcBWoSeYJ2fvPzx6Vz8FCoEsICPq91jF7KZGtsvx6vbxPK9K5kZu7Q==} + peerDependencies: + antd: ^5.8.6 + react: '>=16' + '@difizen/libro-jupyter@0.1.37': resolution: {integrity: sha512-HW01kymN3SnFA/gSpGhZMN83eNOUKYcayXyqLnGXapXjnTEXVaXgeLSQnBuuqjOXt/Xsf7iqoDxr7csuJ5+lAw==} peerDependencies: antd: ^5.8.6 react: '>=16' + '@difizen/libro-jupyter@0.2.24': + resolution: {integrity: sha512-wjd0rlCrXVs4nxOgcO2K0fWBkxK3nVbnIenWZ2GZpB6LMtPIsv4UBFTOAnh86BEA067vM04IRkEs9lulgU0GFw==} + peerDependencies: + antd: ^5.8.6 + react: '>=16' + '@difizen/libro-kernel@0.1.37': resolution: {integrity: sha512-9JKWhi2yrbT4jjLvzHu8jv98/8V6eVpBoJwykMf2H7gc7yU6Y3jVFMHkKKLKG2G7ASGwDp4zWKsxWEs08hwYJw==} peerDependencies: react: '>=16' + '@difizen/libro-kernel@0.2.24': + resolution: {integrity: sha512-+UCg80HkidWZ8ppqItiAmuGYTYhT6Oc2qnssfzvEdZQtOOeJCUsoNec0uclk6WzG+ZhlQyyOMFIaYUwEtAQikg==} + peerDependencies: + react: '>=16' + '@difizen/libro-l10n@0.1.37': resolution: {integrity: sha512-O3BsMExwfdIFrlZnRTjUBR1UBN48pH0nXuFDSUBzDt00NLzD1T+hjnAeBx1bvssh7PZgQXZJO12vEWSNmtOjHw==} + '@difizen/libro-l10n@0.2.24': + resolution: {integrity: sha512-UDpgT/uK8AwfOg2FGFQ44AWp7uRN+QQlJUBYEssWfJxkeg9QdnPEcG5AAXkuamU8EC4bpP0ooGL5GZC/fDOOmg==} + '@difizen/libro-language-client@0.1.37': resolution: {integrity: sha512-kpwdCI5ShXSY04Dq1pHO5LBpyZFqFvIgdvphQEjryxaOMgAjLw1lHLpULbExt326hwru/rQI96EIsRZtaMeLJw==} peerDependencies: react: '>=16' + '@difizen/libro-language-client@0.2.24': + resolution: {integrity: sha512-hqY+5ZsQlmr68M+3SzoInmPPw60k8ngY7UIfmfw8ZNoBaSbNQgjHzvswlgnEFLtBjUD8Aw155weNwMsMBDDJXw==} + peerDependencies: + react: '>=16' + '@difizen/libro-lsp@0.1.37': resolution: {integrity: sha512-vS1db+I0OS1vfEW1lAtEKPVc3ZOT1MD/cTI8GB/T5WCaOHBTtkvjqspcUVsigdDErLsL9zXWbRkrg5qSIvqmLw==} peerDependencies: react: '>=16' + '@difizen/libro-lsp@0.2.24': + resolution: {integrity: sha512-n4ESi3/6bHsh1Kipfmm6tgQP0Dw9qIBuaPeDnv2uY/M47smEYhyvQMUX6jU5yJU8xyhbsdtz4Gh7VUaGJfL2NA==} + peerDependencies: + react: '>=16' + '@difizen/libro-markdown-cell@0.1.37': resolution: {integrity: sha512-PSmsMHpfU0RkzT1gdhRycXzdI1ri32Hv0ZPi68aYRtTPDvdjrNHl0Ii0UZd3+GRhYOPoTIYenzSSF+WJ1qG4pw==} peerDependencies: react: '>=16' + '@difizen/libro-markdown-cell@0.2.24': + resolution: {integrity: sha512-o9oDG2UxlTddEaC3SadNRUruW3y/Kyr7+3O3zb6wZXSweQBpud+4XoSiYMZvyDP/WDfLpTVVbMVOUhpSS01Kcg==} + peerDependencies: + react: '>=16' + '@difizen/libro-markdown@0.1.37': resolution: {integrity: sha512-8VPvY6epJ42Ueu7ape9I9Paz2hmMxJaO5+nXVRHZShDlrK7TMADGCD8Mk1dVB+nUYQLc2sMWw6PSB8S5XlPXNA==} + '@difizen/libro-markdown@0.2.24': + resolution: {integrity: sha512-GWGMwSbiH+Qq97NaMR6UkJZcqm3yVro6MWJqMysfMsUG3sG/KYrtjGhYJfO3DoxrFnkuoccdxZ2Ts3vKmz1IvA==} + '@difizen/libro-output@0.1.37': resolution: {integrity: sha512-DcvJk5xeSBwk/pzKMMDlYCCeJngSGQxEpskskQRPKmvzJGE2Z/OPfs/jqa0nqS2k6YvdwePSSCYwPvcF2Bw3Aw==} peerDependencies: antd: ^5.8.6 react: '>=16' + '@difizen/libro-output@0.2.24': + resolution: {integrity: sha512-kiL+RwoVlznrZx+dYYHjqx4vlb5FZSNQbphr3NT/e7LXhBpDL1UsTryzXlYfOQCLnLUnek+IwdS08tv18uQwEw==} + peerDependencies: + antd: ^5.8.6 + react: '>=16' + '@difizen/libro-raw-cell@0.1.37': resolution: {integrity: sha512-SJEvMtm8v3yaEMgjgXtjKlaGw+uz1cGEBYoTX/5weZubgzAxYlnrjAcgzAAWdGqq3OAqiO4Bzwmh6pMdreG0QA==} peerDependencies: react: '>=16' + '@difizen/libro-raw-cell@0.2.24': + resolution: {integrity: sha512-l7woaC0xkTVU/8cEaDPpYn8xc41gtZEp750QwMSO1UXVe/Ab+Oj6zxVbjsOxCIfeATaWoPQJdgej7KOOqxdZBg==} + peerDependencies: + react: '>=16' + '@difizen/libro-rendermime@0.1.37': resolution: {integrity: sha512-qcFBZJr8jmn8niJRKsGoDxJ5IQHoCdjXKj+ZJjQht7p7hludJ+kjK+co73uhyt6KXEGAHdnE3SEoGsnAJCK29Q==} peerDependencies: react: '>=16' + '@difizen/libro-rendermime@0.2.24': + resolution: {integrity: sha512-mxC/llAoWUswDI/Ti/eiKDtGpjjvrcIqXJlnPpmLEq+5jv8AMUhTxJP7kGPfLFQLJH2VA21wQzA6sFIGQvpm0A==} + peerDependencies: + react: '>=16' + '@difizen/libro-search-code-cell@0.1.37': resolution: {integrity: sha512-2HGBgNVoacnsb/cK1VZnEnG8UK+Uq2D6qjZ/TOqutSljml3HPmxCCfAQXVEaBzcG66n2OWQtuTK+G5LzxeThPQ==} + '@difizen/libro-search-code-cell@0.2.24': + resolution: {integrity: sha512-+kWTuL0pye1CEEhAEsNxhBJzmeio6SttfqKf7NNwP2ql9bLUppBCeIbtccDFhxWcF4x0Y/wfuSJBDZg66Ky5sg==} + '@difizen/libro-search@0.1.37': resolution: {integrity: sha512-WnmXnEKomaSeXYlHgSt3ZP0c3caHZBZdsGg2bSyVJDgo0+7jW+sC16zUHaTzGnzR1W+TOS/siktRGVOYiyAecg==} peerDependencies: antd: ^5.8.6 react: '>=16' + '@difizen/libro-search@0.2.24': + resolution: {integrity: sha512-RrjnF2HhBk9eNk//SZ9WXbBtppi5/p615b/qj7QoWh/9tN2M/fbTdgVby/Djy/qUdL+7WMilx6NHOxG9UiiYtQ==} + peerDependencies: + antd: ^5.8.6 + react: '>=16' + '@difizen/libro-shared-model@0.1.37': resolution: {integrity: sha512-C/UribdIZxj9xGd+KY/vvImVe1WqTkpGZAVAvhmm/XsJeE/UiZfYGJSqpIdnHotBUmKC2PauRoksOitJHiYs1g==} + '@difizen/libro-shared-model@0.2.24': + resolution: {integrity: sha512-g7yQz9cpbxdbBxJGkbMQ/j+IGbeAO+8bkN+ctpnEq/dA9jE66aMxQLH+xO5SJbUboMlJCiybxDjbUiwu3ZLIdA==} + '@difizen/libro-virtualized@0.1.37': resolution: {integrity: sha512-OAVnkpkOHegy4Sn/8UQbkUeXXcQOleJ0biHZN/ghJ55IfC9t4FgMiXy//ihu8Iofj5ddvty6WvnHkGBd4ZAoBQ==} peerDependencies: react: '>=16' react-dom: '>=16' + '@difizen/libro-virtualized@0.2.24': + resolution: {integrity: sha512-rAlC2C/VmRvUhDHvKbyX2Qv8PpgsX0KZ3Iu9iKLcSG3UL5kSqkSCFXBh2S1tXip91/i9dyAsUBEojvGoNzKgCQ==} + peerDependencies: + react: '>=16' + react-dom: '>=16' + '@difizen/mana-app@0.1.19': resolution: {integrity: sha512-Rve5NFRJ6M8+k5U+nsV4eOM0G8zjXfZk519AEt0vEOrQ8Rb0hRWWJxY5DwFBTwNjVSYDnIE+lxOss4EsVmmEOg==} peerDependencies: react: '>=16.8.6' react-dom: '>=16.8.6' + '@difizen/mana-app@0.1.23': + resolution: {integrity: sha512-aC07aHUmnBXNRqtt5blEI/Di6dlLRb0oz16aGbi5HgiSov6FJ3KCDwREUy9859EMQyIH2ar5wDl3wa6NTO6NYA==} + peerDependencies: + react: '>=16.8.6' + react-dom: '>=16.8.6' + '@difizen/mana-common@0.1.19': resolution: {integrity: sha512-woYjctDCD8Pm5D/gWVdOPJQrU1HNZK1M3bCeMNf+Tk+5h3N1CsbI1tU4nYlxpLmKOrU60ZqTJZcbHjRw5arF3Q==} + '@difizen/mana-common@0.1.23': + resolution: {integrity: sha512-fdlxh0RSTx39N8NYoS2+6aMnk2baDZB8sMeIQBW58psx+g6T1GUW+uaZLdjTFPK5qg5CuQY4oASYUBnw8XKGgw==} + '@difizen/mana-core@0.1.19': resolution: {integrity: sha512-yP89Ofd7d8SBhFoa2KV8X7E7OG7UV/iidS31CHLc6mVXhYt3n94uc4yIvp2AnmHBYiMi1G5GkAAhCt7YdX0BYw==} + '@difizen/mana-core@0.1.23': + resolution: {integrity: sha512-McGK86nxKmDnLVk1KSC+/Uqh8qMgf/C6hp8We0Tr/ObHQ2tYRzEE65cNeoVPv76G4d4qIh51kBW5l891jUJGZg==} + '@difizen/mana-l10n@0.1.19': resolution: {integrity: sha512-FF6SPKw9UlgFLL5+e5Kk9Bs4JqJ2u4kpWZ6D7kSQW32F8GgFafUsaIycWlV+9FnlU5YeHxxYmTzfcbDdQ84NGA==} peerDependencies: react: '>=16.8.6' + '@difizen/mana-l10n@0.1.23': + resolution: {integrity: sha512-De1UBJcbjv+C4nGT8HHRvCXJQQOdnx7LzjkoJ04ynwr3KkwkWE/SEXfynevnq8rVhNlJezXJGDLaZd1ircJ8NQ==} + peerDependencies: + react: '>=16.8.6' + '@difizen/mana-observable@0.1.19': resolution: {integrity: sha512-1RC3K53Hrk6udcRbsr2YVZ+SUH7Ar9ho1cc1XSicPTt/EqvA+Rny1cqPA8x7fAv33A484CaLi3qFHirco1AKxQ==} peerDependencies: react: '>=16.8.6' + '@difizen/mana-observable@0.1.23': + resolution: {integrity: sha512-yNqHGompo6CM1d1B0aIk3be948afx2DQk8VdWjgLhpeAYnFCQVCSR3FCqAiq283bUFnxvkDeJYixL5C9xXasGA==} + peerDependencies: + react: '>=16.8.6' + '@difizen/mana-react@0.1.19': resolution: {integrity: sha512-we5S1N1OghKOURBCW6nymdswm2VcCc/iknUc2ZcNY+Ry1bkHiZrZQdhELr4pp4CEFStIKnUQscgzFhPtxCOGqg==} peerDependencies: react: '>=16.8.6' react-dom: '>=16.8.6' + '@difizen/mana-react@0.1.23': + resolution: {integrity: sha512-DGNPxzTExs+CPoizInXKXUTX5o/VSBbPVvrVeht2ch6Q/IzA3Msk+wqg9aJDiHJXsSN8Kqa7s2LE1u47t9wlag==} + peerDependencies: + react: '>=16.8.6' + react-dom: '>=16.8.6' + '@difizen/mana-syringe@0.1.19': resolution: {integrity: sha512-VFdZrLIji76EG26ybGP9AMtra+BT3EaWpmbV5sH6xsJuG6/opnwL5xUtDukWwseF9Hq6CGK9FpUuYyH+zTQEzg==} + '@difizen/mana-syringe@0.1.23': + resolution: {integrity: sha512-YioGY8OEVXFK0+3pSLPgVA2Z1chSsybEuLTkqEM5h6X1V27yNR2vXepIhRwdWXzIvvhrH/VKfW6QuuLhxt6ckA==} + '@difizen/monaco-editor-core@0.39.4': resolution: {integrity: sha512-4aHhsaEJUOWOqxxHvV7r+UP/3f/wHHJvQdkwnMt28HIkP1KKjG/gEXoVDxsv7MWT31pSp9OhXl2K3BPy32P7yQ==} @@ -2165,6 +2315,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.17.19': resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -2183,6 +2339,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.17.19': resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} engines: {node: '>=12'} @@ -2201,6 +2363,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.17.19': resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} engines: {node: '>=12'} @@ -2219,6 +2387,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.17.19': resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} engines: {node: '>=12'} @@ -2237,6 +2411,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.17.19': resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} engines: {node: '>=12'} @@ -2255,6 +2435,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.17.19': resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} engines: {node: '>=12'} @@ -2273,6 +2459,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.17.19': resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} engines: {node: '>=12'} @@ -2291,6 +2483,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.17.19': resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} engines: {node: '>=12'} @@ -2309,6 +2507,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.17.19': resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} engines: {node: '>=12'} @@ -2327,6 +2531,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.17.19': resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} engines: {node: '>=12'} @@ -2345,6 +2555,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.17.19': resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} engines: {node: '>=12'} @@ -2363,6 +2579,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.17.19': resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} engines: {node: '>=12'} @@ -2381,6 +2603,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.17.19': resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} engines: {node: '>=12'} @@ -2399,6 +2627,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.17.19': resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} engines: {node: '>=12'} @@ -2417,6 +2651,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.17.19': resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} engines: {node: '>=12'} @@ -2435,6 +2675,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.17.19': resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} engines: {node: '>=12'} @@ -2453,6 +2699,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.17.19': resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} engines: {node: '>=12'} @@ -2471,6 +2723,18 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.17.19': resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} engines: {node: '>=12'} @@ -2489,6 +2753,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.17.19': resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} engines: {node: '>=12'} @@ -2507,6 +2777,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.17.19': resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} engines: {node: '>=12'} @@ -2525,6 +2801,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.17.19': resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} @@ -2543,6 +2825,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.17.19': resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} engines: {node: '>=12'} @@ -2561,6 +2849,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2883,23 +3177,38 @@ packages: '@lumino/algorithm@1.9.2': resolution: {integrity: sha512-Z06lp/yuhz8CtIir3PNTGnuk7909eXt4ukJsCzChsGuot2l5Fbs96RJ/FOHgwCedaX74CtxPjXHXoszFbUA+4A==} + '@lumino/algorithm@2.0.2': + resolution: {integrity: sha512-cI8yJ2+QK1yM5ZRU3Kuaw9fJ/64JEDZEwWWp7+U0cd/mvcZ44BGdJJ29w+tIet1QXxPAvnsUleWyQ5qm4qUouA==} + '@lumino/coreutils@1.12.1': resolution: {integrity: sha512-JLu3nTHzJk9N8ohZ85u75YxemMrmDzJdNgZztfP7F7T7mxND3YVNCkJG35a6aJ7edu1sIgCjBxOvV+hv27iYvQ==} peerDependencies: crypto: 1.0.1 + '@lumino/coreutils@2.2.0': + resolution: {integrity: sha512-x5wnQ/GjWBayJ6vXVaUi6+Q6ETDdcUiH9eSfpRZFbgMQyyM6pi6baKqJBK2CHkCc/YbAEl6ipApTgm3KOJ/I3g==} + '@lumino/disposable@1.10.4': resolution: {integrity: sha512-4ZxyYcyzUS+ZeB2KAH9oAH3w0DUUceiVr+FIZHZ2TAYGWZI/85WlqJtfm0xjwEpCwLLW1TDqJrISuZu3iMmVMA==} + '@lumino/disposable@2.1.3': + resolution: {integrity: sha512-k5KXy/+T3UItiWHY4WwQawnsJnGo3aNtP5CTRKqo4+tbTNuhc3rTSvygJlNKIbEfIZXW2EWYnwfFDozkYx95eA==} + '@lumino/polling@1.11.4': resolution: {integrity: sha512-yC7JLssj3mqVK6TsYj7dg4AG0rcsC42YtpoDLtz9yzO84Q5flQUfmjAPQB6oPA6wZOlISs3iasF+uO2w1ls5jg==} + '@lumino/polling@2.1.3': + resolution: {integrity: sha512-WEZk96ddK6eHEhdDkFUAAA40EOLit86QVbqQqnbPmhdGwFogek26Kq9b1U273LJeirv95zXCATOJAkjRyb7D+w==} + '@lumino/properties@1.8.2': resolution: {integrity: sha512-EkjI9Cw8R0U+xC9HxdFSu7X1tz1H1vKu20cGvJ2gU+CXlMB1DvoYJCYxCThByHZ+kURTAap4SE5x8HvKwNPbig==} '@lumino/signaling@1.11.1': resolution: {integrity: sha512-YCUmgw08VoyMN5KxzqPO3KMx+cwdPv28tAN06C0K7Q/dQf+oufb1XocuhZb5selTrTmmuXeizaYxgLIQGdS1fA==} + '@lumino/signaling@2.1.3': + resolution: {integrity: sha512-9Wd4iMk8F1i6pYjy65bqKuPlzQMicyL9xy1/ccS20kovPcfD074waneL/7BVe+3M8i+fGa3x2qjbWrBzOdTdNw==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -3665,6 +3974,95 @@ packages: rollup: optional: true + '@rollup/rollup-android-arm-eabi@4.21.1': + resolution: {integrity: sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.21.1': + resolution: {integrity: sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.21.1': + resolution: {integrity: sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.21.1': + resolution: {integrity: sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.21.1': + resolution: {integrity: sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.21.1': + resolution: {integrity: sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.21.1': + resolution: {integrity: sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.21.1': + resolution: {integrity: sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': + resolution: {integrity: sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-gnu@4.21.1': + resolution: {integrity: sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-s390x-gnu@4.21.1': + resolution: {integrity: sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.21.1': + resolution: {integrity: sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.21.1': + resolution: {integrity: sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-win32-arm64-msvc@4.21.1': + resolution: {integrity: sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.21.1': + resolution: {integrity: sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.21.1': + resolution: {integrity: sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==} + cpu: [x64] + os: [win32] + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -4222,6 +4620,9 @@ packages: '@tiptap/core': ^2.5.7 '@tiptap/pm': ^2.5.7 + '@traptitech/markdown-it-katex@3.6.0': + resolution: {integrity: sha512-CnJzTWxsgLGXFdSrWRaGz7GZ1kUUi8g3E9HzJmeveX1YwVJavrKYqysktfHZQsujdnRqV5O7g8FPKEA/aeTkOQ==} + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -6192,6 +6593,12 @@ packages: peerDependencies: esbuild: '>=0.17' + bundle-require@5.0.0: + resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + bytes@3.0.0: resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} engines: {node: '>= 0.8'} @@ -8116,6 +8523,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -11038,6 +11450,10 @@ packages: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -12951,6 +13367,24 @@ packages: ts-node: optional: true + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + postcss-logical@5.0.4: resolution: {integrity: sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==} engines: {node: ^12 || ^14 || >=16} @@ -14537,6 +14971,11 @@ packages: engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true + rollup@4.21.1: + resolution: {integrity: sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + rope-sequence@1.3.4: resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} @@ -15816,6 +16255,25 @@ packages: typescript: optional: true + tsup@8.2.4: + resolution: {integrity: sha512-akpCPePnBnC/CXgRrcy72ZSntgIEUa1jN0oJbbvpALWKNOz1B7aM+UVDWGRGIO/T/PZugAESWDJUAb5FD48o8Q==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + tsutils@3.21.0: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -19260,11 +19718,11 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@commitlint/cli@17.8.1(@swc/core@1.7.2)': + '@commitlint/cli@17.8.1(@swc/core@1.7.2(@swc/helpers@0.5.1))': dependencies: '@commitlint/format': 17.8.1 '@commitlint/lint': 17.8.1 - '@commitlint/load': 17.8.1(@swc/core@1.7.2) + '@commitlint/load': 17.8.1(@swc/core@1.7.2(@swc/helpers@0.5.1)) '@commitlint/read': 17.8.1 '@commitlint/types': 17.8.1 execa: 5.1.1 @@ -19349,7 +19807,7 @@ snapshots: babel-runtime: 6.26.0 lodash: 4.17.21 - '@commitlint/load@17.8.1(@swc/core@1.7.2)': + '@commitlint/load@17.8.1(@swc/core@1.7.2(@swc/helpers@0.5.1))': dependencies: '@commitlint/config-validator': 17.8.1 '@commitlint/execute-rule': 17.8.1 @@ -19358,12 +19816,12 @@ snapshots: '@types/node': 20.5.1 chalk: 4.1.2 cosmiconfig: 8.3.6(typescript@5.5.4) - cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.4))(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@20.5.1)(typescript@5.5.4))(typescript@5.5.4) + cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.4))(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@20.5.1)(typescript@5.5.4))(typescript@5.5.4) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 resolve-from: 5.0.0 - ts-node: 10.9.2(@swc/core@1.7.2)(@types/node@20.5.1)(typescript@5.5.4) + ts-node: 10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@20.5.1)(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - '@swc/core' @@ -19560,7 +20018,22 @@ snapshots: '@difizen/libro-code-editor': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-code-cell@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 transitivePeerDependencies: - '@types/hoist-non-react-statics' @@ -19573,8 +20046,19 @@ snapshots: '@difizen/libro-code-editor@0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-l10n': 0.1.19(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) + react: 18.3.1 + uuid: 9.0.1 + transitivePeerDependencies: + - react-dom + - supports-color + + '@difizen/libro-code-editor@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) react: 18.3.1 uuid: 9.0.1 transitivePeerDependencies: @@ -19596,7 +20080,38 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-lsp': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-rendermime': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@lezer/common': 1.2.1 + '@lezer/highlight': 1.2.0 + highlight.js: 11.10.0 + markdown-it: 13.0.2 + uuid: 9.0.1 + vscode-languageserver-protocol: 3.17.5 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react + - react-dom + - supports-color + + '@difizen/libro-codemirror@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@codemirror/autocomplete': 6.17.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.29.0)(@lezer/common@1.2.1) + '@codemirror/commands': 6.6.0 + '@codemirror/lang-markdown': 6.2.5 + '@codemirror/lang-python': 6.1.6(@codemirror/view@6.29.0) + '@codemirror/language': 6.10.2 + '@codemirror/lint': 6.8.1 + '@codemirror/search': 6.5.6 + '@codemirror/state': 6.4.1 + '@codemirror/view': 6.29.0 + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-lsp': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-rendermime': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@lezer/common': 1.2.1 '@lezer/highlight': 1.2.0 highlight.js: 11.10.0 @@ -19614,7 +20129,15 @@ snapshots: '@difizen/libro-cofine-editor-contribution@0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + transitivePeerDependencies: + - react + - react-dom + - supports-color + + '@difizen/libro-cofine-editor-contribution@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: - react - react-dom @@ -19623,7 +20146,19 @@ snapshots: '@difizen/libro-cofine-editor-core@0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@difizen/libro-cofine-editor-contribution': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/monaco-editor-core': 0.39.4 + debug: 4.3.5 + reflect-metadata: 0.1.14 + transitivePeerDependencies: + - react + - react-dom + - supports-color + + '@difizen/libro-cofine-editor-core@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-cofine-editor-contribution': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/monaco-editor-core': 0.39.4 debug: 4.3.5 reflect-metadata: 0.1.14 @@ -19640,7 +20175,29 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-lsp': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/monaco-editor-core': 0.39.4 + react: 18.3.1 + resize-observer-polyfill: 1.5.1 + uuid: 9.0.1 + vscode-languageserver-protocol: 3.17.5 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-cofine-editor@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-cofine-editor-core': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-cofine-textmate': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-lsp': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/monaco-editor-core': 0.39.4 react: 18.3.1 resize-observer-polyfill: 1.5.1 @@ -19657,7 +20214,19 @@ snapshots: '@difizen/libro-cofine-textmate@0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@difizen/libro-cofine-editor-core': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + fast-plist: 0.1.3 + vscode-oniguruma: 1.7.0 + vscode-textmate: 9.1.0 + transitivePeerDependencies: + - react + - react-dom + - supports-color + + '@difizen/libro-cofine-textmate@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-cofine-editor-core': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fast-plist: 0.1.3 vscode-oniguruma: 1.7.0 vscode-textmate: 9.1.0 @@ -19668,7 +20237,18 @@ snapshots: '@difizen/libro-common@0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + path-browserify: 1.0.1 + react: 18.3.1 + sanitize-html: 2.13.0 + url-parse: 1.5.10 + transitivePeerDependencies: + - react-dom + - supports-color + + '@difizen/libro-common@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) path-browserify: 1.0.1 react: 18.3.1 sanitize-html: 2.13.0 @@ -19684,9 +20264,35 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-shared-model': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-virtualized': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-l10n': 0.1.19(react@18.3.1) - '@difizen/mana-react': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) + '@difizen/mana-react': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + classnames: 2.5.1 + dayjs: 1.11.12 + dnd-core: 16.0.1 + react: 18.3.1 + react-dnd: 16.0.1(@types/node@20.5.1)(@types/react@18.3.3)(react@18.3.1) + react-dnd-html5-backend: 16.0.1 + resize-observer-polyfill: 1.5.1 + uuid: 9.0.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - react-dom + - supports-color + + '@difizen/libro-core@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-shared-model': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-virtualized': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) + '@difizen/mana-react': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 dayjs: 1.11.12 @@ -19723,8 +20329,43 @@ snapshots: '@difizen/libro-rendermime': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-search': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-search-code-cell': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-l10n': 0.1.19(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) + antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + classnames: 2.5.1 + moment: 2.30.1 + plotly.js: 2.34.0(mapbox-gl@1.13.3) + react: 18.3.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - mapbox-gl + - react-dom + - supports-color + + '@difizen/libro-jupyter@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(mapbox-gl@1.13.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@ant-design/colors': 7.1.0 + '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-code-cell': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-codemirror': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-cofine-editor': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-kernel': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-l10n': 0.2.24(react@18.3.1) + '@difizen/libro-language-client': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-lsp': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-markdown-cell': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-output': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-raw-cell': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-rendermime': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-search': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-search-code-cell': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 moment: 2.30.1 @@ -19742,7 +20383,24 @@ snapshots: dependencies: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + minimist: 1.2.8 + query-string: 8.2.0 + react: 18.3.1 + uuid: 9.0.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-kernel@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) minimist: 1.2.8 query-string: 8.2.0 react: 18.3.1 @@ -19757,7 +20415,13 @@ snapshots: '@difizen/libro-l10n@0.1.37(react@18.3.1)': dependencies: - '@difizen/mana-l10n': 0.1.19(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) + transitivePeerDependencies: + - react + + '@difizen/libro-l10n@0.2.24(react@18.3.1)': + dependencies: + '@difizen/mana-l10n': 0.1.23(react@18.3.1) transitivePeerDependencies: - react @@ -19768,8 +20432,32 @@ snapshots: '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-kernel': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-lsp': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-common': 0.1.19 + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-common': 0.1.23 + '@difizen/monaco-editor-core': 0.39.4 + '@difizen/vscode-languageserver-protocol': 3.17.6-next.2 + minimatch: 9.0.5 + react: 18.3.1 + uuid: 9.0.1 + vscode-uri: 3.0.8 + vscode-ws-jsonrpc: 3.3.2 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-language-client@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-kernel': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-lsp': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-common': 0.1.23 '@difizen/monaco-editor-core': 0.39.4 '@difizen/vscode-languageserver-protocol': 3.17.6-next.2 minimatch: 9.0.5 @@ -19791,7 +20479,28 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-kernel': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + lodash.mergewith: 4.6.2 + react: 18.3.1 + uuid: 9.0.1 + vscode-jsonrpc: 6.0.0 + vscode-languageserver-protocol: 3.17.5 + vscode-ws-jsonrpc: 1.0.2 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-lsp@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-kernel': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lodash.mergewith: 4.6.2 react: 18.3.1 uuid: 9.0.1 @@ -19812,7 +20521,26 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-markdown': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.2 + markdown-it-anchor: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.2) + react: 18.3.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-markdown-cell@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-markdown': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/markdown-it': 12.2.3 markdown-it: 13.0.2 markdown-it-anchor: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.2) @@ -19827,8 +20555,21 @@ snapshots: '@difizen/libro-markdown@0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/markdown-it': 12.2.3 + markdown-it: 13.0.2 + markdown-it-anchor: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.2) + transitivePeerDependencies: + - react + - react-dom + - supports-color + + '@difizen/libro-markdown@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@traptitech/markdown-it-katex': 3.6.0 '@types/markdown-it': 12.2.3 + katex: 0.16.11 markdown-it: 13.0.2 markdown-it-anchor: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@13.0.2) transitivePeerDependencies: @@ -19841,7 +20582,23 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-rendermime': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + markdown-it: 13.0.2 + react: 18.3.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - react-dom + - supports-color + + '@difizen/libro-output@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-rendermime': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) markdown-it: 13.0.2 react: 18.3.1 @@ -19857,7 +20614,22 @@ snapshots: '@difizen/libro-code-editor': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-raw-cell@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 transitivePeerDependencies: - '@types/hoist-non-react-statics' @@ -19872,7 +20644,23 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-markdown': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + lodash.escape: 4.0.1 + react: 18.3.1 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react-dom + - supports-color + + '@difizen/libro-rendermime@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-markdown': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lodash.escape: 4.0.1 react: 18.3.1 transitivePeerDependencies: @@ -19890,7 +20678,24 @@ snapshots: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-search': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - antd + - react + - react-dom + - supports-color + + '@difizen/libro-search-code-cell@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-code-cell': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-search': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: - '@types/hoist-non-react-statics' - '@types/node' @@ -19906,8 +20711,29 @@ snapshots: '@difizen/libro-code-editor': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@difizen/libro-core': 0.1.37(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-l10n': 0.1.19(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) + '@types/lodash.debounce': 4.0.9 + antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + classnames: 2.5.1 + lodash.debounce: 4.0.8 + react: 18.3.1 + reflect-metadata: 0.1.14 + transitivePeerDependencies: + - '@types/hoist-non-react-statics' + - '@types/node' + - '@types/react' + - react-dom + - supports-color + + '@difizen/libro-search@0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-code-editor': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/libro-core': 0.2.24(@types/node@20.5.1)(@types/react@18.3.3)(antd@5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) '@types/lodash.debounce': 4.0.9 antd: 5.19.3(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) classnames: 2.5.1 @@ -19924,7 +20750,19 @@ snapshots: '@difizen/libro-shared-model@0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@difizen/libro-common': 0.1.37(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@difizen/mana-app': 0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + uuid: 9.0.1 + y-protocols: 1.0.6(yjs@13.6.18) + yjs: 13.6.18 + transitivePeerDependencies: + - react + - react-dom + - supports-color + + '@difizen/libro-shared-model@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@difizen/libro-common': 0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-app': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) uuid: 9.0.1 y-protocols: 1.0.6(yjs@13.6.18) yjs: 13.6.18 @@ -19940,6 +20778,13 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + '@difizen/libro-virtualized@0.2.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + classnames: 2.5.1 + dom-helpers: 5.2.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@difizen/mana-app@0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -19966,10 +20811,40 @@ snapshots: transitivePeerDependencies: - supports-color + '@difizen/mana-app@0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-common': 0.1.23 + '@difizen/mana-core': 0.1.23(react@18.3.1) + '@difizen/mana-l10n': 0.1.23(react@18.3.1) + '@difizen/mana-observable': 0.1.23(react@18.3.1) + '@difizen/mana-react': 0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-syringe': 0.1.23 + '@types/lodash.debounce': 4.0.3 + '@types/react-virtualized': 9.21.30 + classnames: 2.5.1 + debug: 4.3.5 + file-icons-js: 1.0.3 + font-awesome: 4.7.0 + lodash.debounce: 4.0.8 + perfect-scrollbar: 1.5.5 + rc-tooltip: 5.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-virtualized: 9.22.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + uuid: 9.0.1 + vscode-uri: 2.1.2 + transitivePeerDependencies: + - supports-color + '@difizen/mana-common@0.1.19': dependencies: path-browserify: 1.0.1 + '@difizen/mana-common@0.1.23': + dependencies: + path-browserify: 1.0.1 + '@difizen/mana-core@0.1.19(react@18.3.1)': dependencies: '@difizen/mana-common': 0.1.19 @@ -19983,10 +20858,27 @@ snapshots: - react - supports-color + '@difizen/mana-core@0.1.23(react@18.3.1)': + dependencies: + '@difizen/mana-common': 0.1.23 + '@difizen/mana-observable': 0.1.23(react@18.3.1) + '@difizen/mana-syringe': 0.1.23 + ajv: 8.17.1 + debug: 4.3.5 + resize-observer-polyfill: 1.5.1 + vscode-uri: 2.1.2 + transitivePeerDependencies: + - react + - supports-color + '@difizen/mana-l10n@0.1.19(react@18.3.1)': dependencies: react: 18.3.1 + '@difizen/mana-l10n@0.1.23(react@18.3.1)': + dependencies: + react: 18.3.1 + '@difizen/mana-observable@0.1.19(react@18.3.1)': dependencies: '@difizen/mana-common': 0.1.19 @@ -19994,6 +20886,13 @@ snapshots: react: 18.3.1 reflect-metadata: 0.1.14 + '@difizen/mana-observable@0.1.23(react@18.3.1)': + dependencies: + '@difizen/mana-common': 0.1.23 + '@difizen/mana-syringe': 0.1.23 + react: 18.3.1 + reflect-metadata: 0.1.14 + '@difizen/mana-react@0.1.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -20005,12 +20904,31 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + '@difizen/mana-react@0.1.23(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@ant-design/icons': 5.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@difizen/mana-common': 0.1.23 + classnames: 2.5.1 + rc-dropdown: 3.6.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-motion: 2.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-notification: 5.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-tabs: 11.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rc-util: 4.21.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@difizen/mana-syringe@0.1.19': dependencies: '@difizen/mana-common': 0.1.19 inversify: 5.1.1 reflect-metadata: 0.1.14 + '@difizen/mana-syringe@0.1.23': + dependencies: + '@difizen/mana-common': 0.1.23 + inversify: 5.1.1 + reflect-metadata: 0.1.14 + '@difizen/monaco-editor-core@0.39.4': {} '@difizen/vscode-languageserver-protocol@3.17.6-next.2': @@ -20056,6 +20974,9 @@ snapshots: '@esbuild/aix-ppc64@0.21.4': optional: true + '@esbuild/aix-ppc64@0.23.1': + optional: true + '@esbuild/android-arm64@0.17.19': optional: true @@ -20065,6 +20986,9 @@ snapshots: '@esbuild/android-arm64@0.21.4': optional: true + '@esbuild/android-arm64@0.23.1': + optional: true + '@esbuild/android-arm@0.17.19': optional: true @@ -20074,6 +20998,9 @@ snapshots: '@esbuild/android-arm@0.21.4': optional: true + '@esbuild/android-arm@0.23.1': + optional: true + '@esbuild/android-x64@0.17.19': optional: true @@ -20083,6 +21010,9 @@ snapshots: '@esbuild/android-x64@0.21.4': optional: true + '@esbuild/android-x64@0.23.1': + optional: true + '@esbuild/darwin-arm64@0.17.19': optional: true @@ -20092,6 +21022,9 @@ snapshots: '@esbuild/darwin-arm64@0.21.4': optional: true + '@esbuild/darwin-arm64@0.23.1': + optional: true + '@esbuild/darwin-x64@0.17.19': optional: true @@ -20101,6 +21034,9 @@ snapshots: '@esbuild/darwin-x64@0.21.4': optional: true + '@esbuild/darwin-x64@0.23.1': + optional: true + '@esbuild/freebsd-arm64@0.17.19': optional: true @@ -20110,6 +21046,9 @@ snapshots: '@esbuild/freebsd-arm64@0.21.4': optional: true + '@esbuild/freebsd-arm64@0.23.1': + optional: true + '@esbuild/freebsd-x64@0.17.19': optional: true @@ -20119,6 +21058,9 @@ snapshots: '@esbuild/freebsd-x64@0.21.4': optional: true + '@esbuild/freebsd-x64@0.23.1': + optional: true + '@esbuild/linux-arm64@0.17.19': optional: true @@ -20128,6 +21070,9 @@ snapshots: '@esbuild/linux-arm64@0.21.4': optional: true + '@esbuild/linux-arm64@0.23.1': + optional: true + '@esbuild/linux-arm@0.17.19': optional: true @@ -20137,6 +21082,9 @@ snapshots: '@esbuild/linux-arm@0.21.4': optional: true + '@esbuild/linux-arm@0.23.1': + optional: true + '@esbuild/linux-ia32@0.17.19': optional: true @@ -20146,6 +21094,9 @@ snapshots: '@esbuild/linux-ia32@0.21.4': optional: true + '@esbuild/linux-ia32@0.23.1': + optional: true + '@esbuild/linux-loong64@0.17.19': optional: true @@ -20155,6 +21106,9 @@ snapshots: '@esbuild/linux-loong64@0.21.4': optional: true + '@esbuild/linux-loong64@0.23.1': + optional: true + '@esbuild/linux-mips64el@0.17.19': optional: true @@ -20164,6 +21118,9 @@ snapshots: '@esbuild/linux-mips64el@0.21.4': optional: true + '@esbuild/linux-mips64el@0.23.1': + optional: true + '@esbuild/linux-ppc64@0.17.19': optional: true @@ -20173,6 +21130,9 @@ snapshots: '@esbuild/linux-ppc64@0.21.4': optional: true + '@esbuild/linux-ppc64@0.23.1': + optional: true + '@esbuild/linux-riscv64@0.17.19': optional: true @@ -20182,6 +21142,9 @@ snapshots: '@esbuild/linux-riscv64@0.21.4': optional: true + '@esbuild/linux-riscv64@0.23.1': + optional: true + '@esbuild/linux-s390x@0.17.19': optional: true @@ -20191,6 +21154,9 @@ snapshots: '@esbuild/linux-s390x@0.21.4': optional: true + '@esbuild/linux-s390x@0.23.1': + optional: true + '@esbuild/linux-x64@0.17.19': optional: true @@ -20200,6 +21166,9 @@ snapshots: '@esbuild/linux-x64@0.21.4': optional: true + '@esbuild/linux-x64@0.23.1': + optional: true + '@esbuild/netbsd-x64@0.17.19': optional: true @@ -20209,6 +21178,12 @@ snapshots: '@esbuild/netbsd-x64@0.21.4': optional: true + '@esbuild/netbsd-x64@0.23.1': + optional: true + + '@esbuild/openbsd-arm64@0.23.1': + optional: true + '@esbuild/openbsd-x64@0.17.19': optional: true @@ -20218,6 +21193,9 @@ snapshots: '@esbuild/openbsd-x64@0.21.4': optional: true + '@esbuild/openbsd-x64@0.23.1': + optional: true + '@esbuild/sunos-x64@0.17.19': optional: true @@ -20227,6 +21205,9 @@ snapshots: '@esbuild/sunos-x64@0.21.4': optional: true + '@esbuild/sunos-x64@0.23.1': + optional: true + '@esbuild/win32-arm64@0.17.19': optional: true @@ -20236,6 +21217,9 @@ snapshots: '@esbuild/win32-arm64@0.21.4': optional: true + '@esbuild/win32-arm64@0.23.1': + optional: true + '@esbuild/win32-ia32@0.17.19': optional: true @@ -20245,6 +21229,9 @@ snapshots: '@esbuild/win32-ia32@0.21.4': optional: true + '@esbuild/win32-ia32@0.23.1': + optional: true + '@esbuild/win32-x64@0.17.19': optional: true @@ -20254,6 +21241,9 @@ snapshots: '@esbuild/win32-x64@0.21.4': optional: true + '@esbuild/win32-x64@0.23.1': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@7.18.0)': dependencies: eslint: 7.18.0 @@ -20464,7 +21454,7 @@ snapshots: - supports-color - utf-8-validate - '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4))': + '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -20478,7 +21468,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -20843,22 +21833,32 @@ snapshots: '@loadable/component@5.15.2(react@18.3.1)': dependencies: - '@babel/runtime': 7.23.6 + '@babel/runtime': 7.24.8 hoist-non-react-statics: 3.3.2 react: 18.3.1 react-is: 16.13.1 '@lumino/algorithm@1.9.2': {} + '@lumino/algorithm@2.0.2': {} + '@lumino/coreutils@1.12.1(crypto@1.0.1)': dependencies: crypto: 1.0.1 + '@lumino/coreutils@2.2.0': + dependencies: + '@lumino/algorithm': 2.0.2 + '@lumino/disposable@1.10.4': dependencies: '@lumino/algorithm': 1.9.2 '@lumino/signaling': 1.11.1 + '@lumino/disposable@2.1.3': + dependencies: + '@lumino/signaling': 2.1.3 + '@lumino/polling@1.11.4(crypto@1.0.1)': dependencies: '@lumino/coreutils': 1.12.1(crypto@1.0.1) @@ -20867,6 +21867,12 @@ snapshots: transitivePeerDependencies: - crypto + '@lumino/polling@2.1.3': + dependencies: + '@lumino/coreutils': 2.2.0 + '@lumino/disposable': 2.1.3 + '@lumino/signaling': 2.1.3 + '@lumino/properties@1.8.2': {} '@lumino/signaling@1.11.1': @@ -20874,6 +21880,11 @@ snapshots: '@lumino/algorithm': 1.9.2 '@lumino/properties': 1.8.2 + '@lumino/signaling@2.1.3': + dependencies: + '@lumino/algorithm': 2.0.2 + '@lumino/coreutils': 2.2.0 + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.24.8 @@ -20923,7 +21934,7 @@ snapshots: '@material-ui/core@4.7.1(@types/react@18.3.3)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 '@material-ui/styles': 4.11.5(@types/react@18.3.3)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) '@material-ui/system': 4.12.2(@types/react@18.3.3)(react-dom@16.14.0(react@16.14.0))(react@16.14.0) '@material-ui/types': 4.1.1 @@ -20944,7 +21955,7 @@ snapshots: '@material-ui/styles@4.11.5(@types/react@18.3.3)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 '@emotion/hash': 0.8.0 '@material-ui/types': 5.1.0(@types/react@18.3.3) '@material-ui/utils': 4.11.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) @@ -20967,7 +21978,7 @@ snapshots: '@material-ui/system@4.12.2(@types/react@18.3.3)(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 '@material-ui/utils': 4.11.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0) csstype: 2.6.21 prop-types: 15.8.1 @@ -20986,11 +21997,11 @@ snapshots: '@material-ui/utils@4.11.3(react-dom@16.14.0(react@16.14.0))(react@16.14.0)': dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 prop-types: 15.8.1 react: 16.14.0 react-dom: 16.14.0(react@16.14.0) - react-is: 16.13.1 + react-is: 17.0.2 '@mdx-js/loader@1.5.1(react@16.14.0)': dependencies: @@ -21079,9 +22090,9 @@ snapshots: '@npmcli/name-from-folder@2.0.0': {} - '@nrwl/tao@17.3.2(@swc/core@1.7.2)': + '@nrwl/tao@17.3.2(@swc/core@1.7.2(@swc/helpers@0.5.1))': dependencies: - nx: 17.3.2(@swc/core@1.7.2) + nx: 17.3.2(@swc/core@1.7.2(@swc/helpers@0.5.1)) tslib: 2.6.3 transitivePeerDependencies: - '@swc-node/register' @@ -21701,13 +22712,61 @@ snapshots: lodash: 4.17.21 lodash-es: 4.17.21 - '@rollup/pluginutils@5.1.0(rollup@3.29.4)': + '@rollup/pluginutils@5.1.0(rollup@4.21.1)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 3.29.4 + rollup: 4.21.1 + + '@rollup/rollup-android-arm-eabi@4.21.1': + optional: true + + '@rollup/rollup-android-arm64@4.21.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.21.1': + optional: true + + '@rollup/rollup-darwin-x64@4.21.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.21.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.21.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.21.1': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.21.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.21.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.21.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.21.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.21.1': + optional: true '@sinclair/typebox@0.27.8': {} @@ -22204,10 +23263,10 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/react-vite@7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.29.4)(typescript@5.5.4)(vite@4.5.3(@types/node@20.5.1)(less@4.2.0)(lightningcss@1.22.1)(sass@1.77.8)(terser@5.31.3))': + '@storybook/react-vite@7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.1)(typescript@5.5.4)(vite@4.5.3(@types/node@20.5.1)(less@4.2.0)(lightningcss@1.22.1)(sass@1.77.8)(terser@5.31.3))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.0(typescript@5.5.4)(vite@4.5.3(@types/node@20.5.1)(less@4.2.0)(lightningcss@1.22.1)(sass@1.77.8)(terser@5.31.3)) - '@rollup/pluginutils': 5.1.0(rollup@3.29.4) + '@rollup/pluginutils': 5.1.0(rollup@4.21.1) '@storybook/builder-vite': 7.6.20(encoding@0.1.13)(typescript@5.5.4)(vite@4.5.3(@types/node@20.5.1)(less@4.2.0)(lightningcss@1.22.1)(sass@1.77.8)(terser@5.31.3)) '@storybook/react': 7.6.20(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@vitejs/plugin-react': 3.1.0(vite@4.5.3(@types/node@20.5.1)(less@4.2.0)(lightningcss@1.22.1)(sass@1.77.8)(terser@5.31.3)) @@ -22411,23 +23470,6 @@ snapshots: '@swc/core-win32-x64-msvc@1.7.2': optional: true - '@swc/core@1.7.2': - dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.12 - optionalDependencies: - '@swc/core-darwin-arm64': 1.7.2 - '@swc/core-darwin-x64': 1.7.2 - '@swc/core-linux-arm-gnueabihf': 1.7.2 - '@swc/core-linux-arm64-gnu': 1.7.2 - '@swc/core-linux-arm64-musl': 1.7.2 - '@swc/core-linux-x64-gnu': 1.7.2 - '@swc/core-linux-x64-musl': 1.7.2 - '@swc/core-win32-arm64-msvc': 1.7.2 - '@swc/core-win32-ia32-msvc': 1.7.2 - '@swc/core-win32-x64-msvc': 1.7.2 - optional: true - '@swc/core@1.7.2(@swc/helpers@0.5.1)': dependencies: '@swc/counter': 0.1.3 @@ -22665,6 +23707,10 @@ snapshots: '@tiptap/core': 2.5.7(@tiptap/pm@2.5.7) '@tiptap/pm': 2.5.7 + '@traptitech/markdown-it-katex@3.6.0': + dependencies: + katex: 0.16.11 + '@trysound/sax@0.2.0': {} '@tsconfig/node10@1.0.11': {} @@ -23830,10 +24876,10 @@ snapshots: '@umijs/history@5.3.1': dependencies: - '@babel/runtime': 7.23.6 + '@babel/runtime': 7.24.8 query-string: 6.14.1 - '@umijs/lint@4.3.10(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)))(postcss-less@6.0.0(postcss@8.4.40))(stylelint@15.11.0(typescript@4.2.3))(typescript@4.2.3)': + '@umijs/lint@4.3.10(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)))(postcss-less@6.0.0(postcss@8.4.40))(stylelint@15.11.0(typescript@4.2.3))(typescript@4.2.3)': dependencies: '@babel/core': 7.23.6 '@babel/eslint-parser': 7.23.3(@babel/core@7.23.6)(eslint@7.18.0) @@ -23841,7 +24887,7 @@ snapshots: '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(typescript@4.2.3) '@typescript-eslint/parser': 5.62.0(eslint@7.18.0)(typescript@4.2.3) '@umijs/babel-preset-umi': 4.3.10 - eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)))(typescript@4.2.3) + eslint-plugin-jest: 27.2.3(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)))(typescript@4.2.3) eslint-plugin-react: 7.33.2(eslint@7.18.0) eslint-plugin-react-hooks: 4.6.0(eslint@7.18.0) postcss: 8.4.40 @@ -25390,6 +26436,11 @@ snapshots: esbuild: 0.17.19 load-tsconfig: 0.2.5 + bundle-require@5.0.0(esbuild@0.23.1): + dependencies: + esbuild: 0.23.1 + load-tsconfig: 0.2.5 + bytes@3.0.0: {} bytes@3.1.2: {} @@ -26296,11 +27347,11 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.4))(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@20.5.1)(typescript@5.5.4))(typescript@5.5.4): + cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@5.5.4))(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@20.5.1)(typescript@5.5.4))(typescript@5.5.4): dependencies: '@types/node': 20.5.1 cosmiconfig: 8.3.6(typescript@5.5.4) - ts-node: 10.9.2(@swc/core@1.7.2)(@types/node@20.5.1)(typescript@5.5.4) + ts-node: 10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@20.5.1)(typescript@5.5.4) typescript: 5.5.4 cosmiconfig@5.2.1: @@ -26368,13 +27419,13 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 - create-jest@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + create-jest@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -26383,13 +27434,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + create-jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -26582,7 +27633,7 @@ snapshots: css-vendor@2.0.8: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 is-in-browser: 1.1.3 css-what@3.4.2: {} @@ -27832,6 +28883,33 @@ snapshots: '@esbuild/win32-ia32': 0.21.4 '@esbuild/win32-x64': 0.21.4 + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + escalade@3.1.2: {} escape-html@1.0.3: {} @@ -27998,13 +29076,13 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)))(typescript@4.2.3): + eslint-plugin-jest@27.2.3(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)))(typescript@4.2.3): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@7.18.0)(typescript@4.2.3) eslint: 7.18.0 optionalDependencies: '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.18.0)(typescript@4.2.3))(eslint@7.18.0)(typescript@4.2.3) - jest: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) transitivePeerDependencies: - supports-color - typescript @@ -29797,7 +30875,7 @@ snapshots: history@4.10.1: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 loose-envify: 1.4.0 resolve-pathname: 3.0.0 tiny-invariant: 1.3.3 @@ -29806,7 +30884,7 @@ snapshots: history@5.3.0: dependencies: - '@babel/runtime': 7.23.6 + '@babel/runtime': 7.24.8 hmac-drbg@1.0.1: dependencies: @@ -30748,16 +31826,16 @@ snapshots: - supports-color - utf-8-validate - jest-cli@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + jest-cli@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + create-jest: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -30767,16 +31845,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + jest-cli@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + create-jest: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -30814,7 +31892,7 @@ snapshots: - supports-color - utf-8-validate - jest-config@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + jest-config@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: '@babel/core': 7.24.9 '@jest/test-sequencer': 29.7.0 @@ -30840,12 +31918,12 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 18.19.42 - ts-node: 10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4) + ts-node: 10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + jest-config@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: '@babel/core': 7.24.9 '@jest/test-sequencer': 29.7.0 @@ -30871,7 +31949,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 20.5.1 - ts-node: 10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4) + ts-node: 10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -31376,24 +32454,24 @@ snapshots: - supports-color - utf-8-validate - jest@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + jest@29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest-cli: 29.7.0(@types/node@18.19.42)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros - supports-color - ts-node - jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + jest-cli: 29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -31558,46 +32636,46 @@ snapshots: jss-plugin-camel-case@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 hyphenate-style-name: 1.1.0 jss: 10.10.0 jss-plugin-default-unit@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 jss: 10.10.0 jss-plugin-global@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 jss: 10.10.0 jss-plugin-nested@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 jss: 10.10.0 tiny-warning: 1.0.3 jss-plugin-props-sort@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 jss: 10.10.0 jss-plugin-rule-value-function@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 jss: 10.10.0 tiny-warning: 1.0.3 jss-plugin-vendor-prefixer@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 css-vendor: 2.0.8 jss: 10.10.0 jss@10.10.0: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 csstype: 3.1.3 is-in-browser: 1.1.3 tiny-warning: 1.0.3 @@ -31892,6 +32970,8 @@ snapshots: lilconfig@2.1.0: {} + lilconfig@3.1.2: {} + lines-and-columns@1.2.4: {} lines-and-columns@2.0.4: {} @@ -33023,7 +34103,7 @@ snapshots: mini-create-react-context@0.3.3(prop-types@15.8.1)(react@16.14.0): dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 prop-types: 15.8.1 react: 16.14.0 tiny-warning: 1.0.3 @@ -33479,9 +34559,9 @@ snapshots: nwsapi@2.2.12: {} - nx@17.3.2(@swc/core@1.7.2): + nx@17.3.2(@swc/core@1.7.2(@swc/helpers@0.5.1)): dependencies: - '@nrwl/tao': 17.3.2(@swc/core@1.7.2) + '@nrwl/tao': 17.3.2(@swc/core@1.7.2(@swc/helpers@0.5.1)) '@yarnpkg/lockfile': 1.1.0 '@yarnpkg/parsers': 3.0.0-rc.46 '@zkochan/js-yaml': 0.0.6 @@ -33526,7 +34606,7 @@ snapshots: '@nx/nx-linux-x64-musl': 17.3.2 '@nx/nx-win32-arm64-msvc': 17.3.2 '@nx/nx-win32-x64-msvc': 17.3.2 - '@swc/core': 1.7.2 + '@swc/core': 1.7.2(@swc/helpers@0.5.1) transitivePeerDependencies: - debug @@ -34413,13 +35493,20 @@ snapshots: dependencies: postcss: 8.4.40 - postcss-load-config@3.1.4(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)): + postcss-load-config@3.1.4(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: postcss: 8.4.40 - ts-node: 10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4) + ts-node: 10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4) + + postcss-load-config@6.0.1(postcss@8.4.40)(yaml@2.5.0): + dependencies: + lilconfig: 3.1.2 + optionalDependencies: + postcss: 8.4.40 + yaml: 2.5.0 postcss-logical@5.0.4(postcss@8.4.40): dependencies: @@ -35833,7 +36920,7 @@ snapshots: react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.23.6 + '@babel/runtime': 7.24.8 invariant: 2.2.4 prop-types: 15.8.1 react: 18.3.1 @@ -35892,7 +36979,7 @@ snapshots: react-router-dom@5.1.2(react@16.14.0): dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 history: 4.10.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -35910,7 +36997,7 @@ snapshots: react-router@5.1.2(react@16.14.0): dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 history: 4.10.1 hoist-non-react-statics: 3.3.2 loose-envify: 1.4.0 @@ -35946,7 +37033,7 @@ snapshots: react-transition-group@4.4.5(react-dom@16.14.0(react@16.14.0))(react@16.14.0): dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -36170,7 +37257,7 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.17.9 + '@babel/runtime': 7.24.8 regex-cache@0.4.4: dependencies: @@ -36621,6 +37708,28 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + rollup@4.21.1: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.21.1 + '@rollup/rollup-android-arm64': 4.21.1 + '@rollup/rollup-darwin-arm64': 4.21.1 + '@rollup/rollup-darwin-x64': 4.21.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.1 + '@rollup/rollup-linux-arm-musleabihf': 4.21.1 + '@rollup/rollup-linux-arm64-gnu': 4.21.1 + '@rollup/rollup-linux-arm64-musl': 4.21.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.1 + '@rollup/rollup-linux-riscv64-gnu': 4.21.1 + '@rollup/rollup-linux-s390x-gnu': 4.21.1 + '@rollup/rollup-linux-x64-gnu': 4.21.1 + '@rollup/rollup-linux-x64-musl': 4.21.1 + '@rollup/rollup-win32-arm64-msvc': 4.21.1 + '@rollup/rollup-win32-ia32-msvc': 4.21.1 + '@rollup/rollup-win32-x64-msvc': 4.21.1 + fsevents: 2.3.3 + rope-sequence@1.3.4: {} rst-selector-parser@2.2.3: @@ -36713,11 +37822,11 @@ snapshots: sass@1.22.10: dependencies: - chokidar: 3.3.0 + chokidar: 3.6.0 sass@1.77.8: dependencies: - chokidar: 3.3.0 + chokidar: 3.6.0 immutable: 4.3.7 source-map-js: 1.2.0 @@ -38195,7 +39304,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4): + ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -38213,9 +39322,9 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.7.2 + '@swc/core': 1.7.2(@swc/helpers@0.5.1) - ts-node@10.9.2(@swc/core@1.7.2)(@types/node@20.5.1)(typescript@5.5.4): + ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@20.5.1)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -38233,7 +39342,7 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.7.2 + '@swc/core': 1.7.2(@swc/helpers@0.5.1) tsconfig-paths@3.15.0: dependencies: @@ -38256,7 +39365,7 @@ snapshots: tsscmp@1.0.6: {} - tsup@6.7.0(@swc/core@1.7.2)(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4))(typescript@5.5.4): + tsup@6.7.0(@swc/core@1.7.2(@swc/helpers@0.5.1))(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4))(typescript@5.5.4): dependencies: bundle-require: 4.2.1(esbuild@0.17.19) cac: 6.7.14 @@ -38266,20 +39375,48 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 3.1.4(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)) + postcss-load-config: 3.1.4(postcss@8.4.40)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)) resolve-from: 5.0.0 rollup: 3.29.4 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: - '@swc/core': 1.7.2 + '@swc/core': 1.7.2(@swc/helpers@0.5.1) postcss: 8.4.40 typescript: 5.5.4 transitivePeerDependencies: - supports-color - ts-node + tsup@8.2.4(@swc/core@1.7.2(@swc/helpers@0.5.1))(postcss@8.4.40)(typescript@5.5.4)(yaml@2.5.0): + dependencies: + bundle-require: 5.0.0(esbuild@0.23.1) + cac: 6.7.14 + chokidar: 3.6.0 + consola: 3.2.3 + debug: 4.3.5 + esbuild: 0.23.1 + execa: 5.1.1 + globby: 11.1.0 + joycon: 3.1.1 + picocolors: 1.0.1 + postcss-load-config: 6.0.1(postcss@8.4.40)(yaml@2.5.0) + resolve-from: 5.0.0 + rollup: 4.21.1 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 + tree-kill: 1.2.2 + optionalDependencies: + '@swc/core': 1.7.2(@swc/helpers@0.5.1) + postcss: 8.4.40 + typescript: 5.5.4 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + tsutils@3.21.0(typescript@4.2.3): dependencies: tslib: 1.14.1 @@ -38416,13 +39553,13 @@ snapshots: uglify-to-browserify@1.0.2: optional: true - umi@4.3.10(@babel/core@7.24.9)(@types/node@20.5.1)(@types/react@18.3.3)(@types/webpack@4.41.0)(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)))(lightningcss@1.22.1)(postcss-less@6.0.0(postcss@8.4.40))(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.29.4)(sass@1.77.8)(sockjs-client@1.4.0)(stylelint@15.11.0(typescript@4.2.3))(terser@5.31.3)(type-fest@2.19.0)(typescript@4.2.3)(webpack-dev-server@3.10.3(webpack@4.41.5))(webpack@4.41.5): + umi@4.3.10(@babel/core@7.24.9)(@types/node@20.5.1)(@types/react@18.3.3)(@types/webpack@4.41.0)(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)))(lightningcss@1.22.1)(postcss-less@6.0.0(postcss@8.4.40))(prettier@3.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.29.4)(sass@1.77.8)(sockjs-client@1.4.0)(stylelint@15.11.0(typescript@4.2.3))(terser@5.31.3)(type-fest@2.19.0)(typescript@4.2.3)(webpack-dev-server@3.10.3(webpack@4.41.5))(webpack@4.41.5): dependencies: '@babel/runtime': 7.23.6 '@umijs/bundler-utils': 4.3.10 '@umijs/bundler-webpack': 4.3.10(@types/webpack@4.41.0)(sockjs-client@1.4.0)(type-fest@2.19.0)(typescript@4.2.3)(webpack-dev-server@3.10.3(webpack@4.41.5))(webpack@4.41.5) '@umijs/core': 4.3.10 - '@umijs/lint': 4.3.10(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2)(@types/node@18.19.42)(typescript@5.5.4)))(postcss-less@6.0.0(postcss@8.4.40))(stylelint@15.11.0(typescript@4.2.3))(typescript@4.2.3) + '@umijs/lint': 4.3.10(eslint@7.18.0)(jest@29.7.0(@types/node@20.5.1)(ts-node@10.9.2(@swc/core@1.7.2(@swc/helpers@0.5.1))(@types/node@18.19.42)(typescript@5.5.4)))(postcss-less@6.0.0(postcss@8.4.40))(stylelint@15.11.0(typescript@4.2.3))(typescript@4.2.3) '@umijs/preset-umi': 4.3.10(@types/node@20.5.1)(@types/react@18.3.3)(@types/webpack@4.41.0)(lightningcss@1.22.1)(rollup@3.29.4)(sass@1.77.8)(sockjs-client@1.4.0)(terser@5.31.3)(type-fest@2.19.0)(typescript@4.2.3)(webpack-dev-server@3.10.3(webpack@4.41.5))(webpack@4.41.5) '@umijs/renderer-react': 4.3.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@umijs/server': 4.3.10 diff --git a/pyprojects/secretnote/.jupyter/config_dev.py b/pyprojects/secretnote/.jupyter/config_dev.py index 666d8094..a96a6226 100644 --- a/pyprojects/secretnote/.jupyter/config_dev.py +++ b/pyprojects/secretnote/.jupyter/config_dev.py @@ -22,16 +22,20 @@ c.LanguageServerManager.autodetect = False c.LanguageServerManager.language_servers = { - "ruff-lsp": { - # if installed as a binary - "argv": [ - "ruff-lsp", - ], - "languages": ["python"], - "version": 2, - "mime_types": ["text/x-python"], - "display_name": "ruff-lsp", - }, + # `ruff` is only for linting, which is not necessary in personal style notebook. + # so we disbale it. + # "ruff-lsp": { + # # if installed as a binary + # "argv": [ + # "ruff-lsp", + # ], + # "languages": ["python"], + # "version": 2, + # "mime_types": ["text/x-python"], + # "display_name": "ruff-lsp", + # }, + # `libro-analyzer` is a derived version of pyright with virtual document enabled + # whole notebook LSP ability. "libro-analyzer": { # if installed as a binary "argv": [ @@ -45,3 +49,5 @@ "display_name": "libro-analyzer", }, } + +c.ResourceUseDisplay.track_cpu_percent = True