From 6eccecf6d59681aed58f925019c4e548a4391293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A1=97=E8=A7=92=E5=B0=8F=E6=9E=97?= <1013335014@qq.com> Date: Wed, 21 Jan 2026 10:37:05 +0800 Subject: [PATCH] =?UTF-8?q?0.1.5=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 6148 -> 6148 bytes LICENSE | 674 ----- README.md | 13 +- README_en.md | 14 +- ShortcutKeySettingReference.md | 135 - ShortcutKeySettingReference_en.md | 135 - docs/changelog.md | 209 ++ docs/changelog_zh.md | 191 ++ Help.md => docs/help.md | 2 +- Help_zh.md => docs/help_zh.md | 0 docs/imageHosting.md | 63 + docs/imageHosting_zh.md | 63 + manifest.json | 2 +- plugin/.DS_Store | Bin 6148 -> 6148 bytes plugin/SmmEditView.js | 414 +-- plugin/locales/en.json | 115 +- plugin/locales/vi.json | 105 +- plugin/locales/zh.json | 113 +- plugin/locales/zhtw.json | 109 +- plugin/main.js | 93 +- plugin/ob/Commands.js | 450 +-- plugin/ob/ConfirmDialog.js | 64 + plugin/ob/MarkdownPostProcessor.js | 121 +- plugin/ob/Menus.js | 55 +- plugin/ob/ModifyFileName.js | 104 + plugin/ob/PreviewMindMap.js | 1 - plugin/ob/SmmSettingTab.js | 339 ++- plugin/ob/SuggestionModal.js | 3 +- plugin/ob/TextInfoDialog.js | 34 + plugin/ob/constant.js | 72 +- plugin/ob/metadataAndMarkdown.js | 41 +- plugin/ob/utils.js | 115 +- plugin/package-lock.json | 2507 +---------------- plugin/package.json | 3 +- plugin/src/assets/icon-font/iconfont.css | 78 +- plugin/src/assets/icon-font/iconfont.ttf | Bin 42416 -> 46012 bytes plugin/src/assets/icon-font/iconfont.woff | Bin 26624 -> 28660 bytes plugin/src/assets/icon-font/iconfont.woff2 | Bin 22620 -> 24220 bytes plugin/src/assets/img/.DS_Store | Bin 6148 -> 0 bytes plugin/src/assets/img/foramt/11.png | Bin 1817 -> 0 bytes plugin/src/assets/img/foramt/8.png | Bin 1946 -> 0 bytes plugin/src/assets/img/foramt/9.png | Bin 2080 -> 0 bytes .../src/assets/img/structures/fishbone2.jpg | Bin 9948 -> 0 bytes .../assets/img/structures/rightFishbone.jpg | Bin 6529 -> 0 bytes .../assets/img/structures/rightFishbone2.jpg | Bin 9709 -> 0 bytes plugin/src/components/ImgUpload/index.vue | 85 +- plugin/src/components/ImgUpload/utils.js | 40 + plugin/src/config/constant.js | 37 +- plugin/src/config/en.js | 251 +- plugin/src/config/icon.js | 24 +- plugin/src/config/image.js | 2 - plugin/src/config/index.js | 14 +- plugin/src/config/vi.js | 224 +- plugin/src/config/zh.js | 235 +- plugin/src/config/zhtw.js | 221 +- plugin/src/lang/en_us.js | 94 +- plugin/src/lang/vi_vn.js | 59 +- plugin/src/lang/zh_cn.js | 58 +- plugin/src/lang/zh_tw.js | 58 +- plugin/src/main.js | 12 +- plugin/src/mixins/fontFamily.js | 9 + plugin/src/mixins/imgHostingUpload.js | 63 + plugin/src/pages/.DS_Store | Bin 6148 -> 0 bytes plugin/src/pages/Edit/.DS_Store | Bin 6148 -> 0 bytes plugin/src/pages/Edit/Index.vue | 51 +- .../Edit/components/AssociativeLineStyle.vue | 7 +- .../src/pages/Edit/components/BaseStyle.vue | 200 +- plugin/src/pages/Edit/components/Color.vue | 3 - .../src/pages/Edit/components/Contextmenu.vue | 254 +- plugin/src/pages/Edit/components/Count.vue | 7 +- .../src/pages/Edit/components/Demonstrate.vue | 2 +- plugin/src/pages/Edit/components/Edit.vue | 545 ++-- plugin/src/pages/Edit/components/Export.vue | 55 +- .../pages/Edit/components/FileSelectList.vue | 221 ++ plugin/src/pages/Edit/components/Import.vue | 178 +- .../src/pages/Edit/components/MouseAction.vue | 1 - .../src/pages/Edit/components/Navigator.vue | 12 - .../Edit/components/NavigatorToolbar.vue | 5 +- .../pages/Edit/components/NodeHyperlink.vue | 9 +- plugin/src/pages/Edit/components/NodeIcon.vue | 6 +- .../pages/Edit/components/NodeIconSidebar.vue | 10 +- .../pages/Edit/components/NodeIconToolbar.vue | 5 - .../src/pages/Edit/components/NodeImage.vue | 116 +- .../pages/Edit/components/NodeImgPreview.vue | 2 +- plugin/src/pages/Edit/components/NodeNote.vue | 154 +- .../Edit/components/NodeNoteContentShow.vue | 7 - .../pages/Edit/components/NodeNoteSidebar.vue | 1 - .../pages/Edit/components/NodeOuterFrame.vue | 14 +- plugin/src/pages/Edit/components/NodeTag.vue | 4 +- .../pages/Edit/components/NodeTagStyle.vue | 2 - .../Edit/components/NodeTextInputObLink.vue | 202 ++ plugin/src/pages/Edit/components/Outline.vue | 103 +- .../src/pages/Edit/components/OutlineEdit.vue | 130 +- .../pages/Edit/components/OutlineSidebar.vue | 2 - .../pages/Edit/components/RichTextToolbar.vue | 8 +- plugin/src/pages/Edit/components/Scale.vue | 7 - .../src/pages/Edit/components/Scrollbar.vue | 9 - plugin/src/pages/Edit/components/Search.vue | 6 +- plugin/src/pages/Edit/components/Setting.vue | 83 +- .../src/pages/Edit/components/ShortcutKey.vue | 9 - plugin/src/pages/Edit/components/Sidebar.vue | 3 +- .../pages/Edit/components/SidebarTrigger.vue | 1 - .../src/pages/Edit/components/Structure.vue | 1 - plugin/src/pages/Edit/components/Style.vue | 96 +- plugin/src/pages/Edit/components/Theme.vue | 1 - plugin/src/pages/Edit/components/Toolbar.vue | 4 - .../Edit/components/ToolbarNodeBtnList.vue | 27 +- plugin/src/pages/PreviewMode/Index.vue | 11 +- .../pages/PreviewMode/components/Toolbar.vue | 2 +- plugin/src/store.js | 23 +- plugin/src/style/element-variables.scss | 2 +- plugin/src/utils/CursorTextHandler.js | 49 + plugin/src/utils/handleClipboardText.js | 10 +- plugin/src/utils/index.js | 204 +- plugin/style.css | 108 + plugin/webpack.config.js | 1 + 更新记录.md | 51 - 117 files changed, 4959 insertions(+), 5988 deletions(-) delete mode 100644 LICENSE delete mode 100644 ShortcutKeySettingReference.md delete mode 100644 ShortcutKeySettingReference_en.md create mode 100644 docs/changelog.md create mode 100644 docs/changelog_zh.md rename Help.md => docs/help.md (99%) rename Help_zh.md => docs/help_zh.md (100%) create mode 100644 docs/imageHosting.md create mode 100644 docs/imageHosting_zh.md create mode 100644 plugin/ob/ConfirmDialog.js create mode 100644 plugin/ob/ModifyFileName.js create mode 100644 plugin/ob/TextInfoDialog.js delete mode 100644 plugin/src/assets/img/.DS_Store delete mode 100644 plugin/src/assets/img/foramt/11.png delete mode 100644 plugin/src/assets/img/foramt/8.png delete mode 100644 plugin/src/assets/img/foramt/9.png delete mode 100644 plugin/src/assets/img/structures/fishbone2.jpg delete mode 100644 plugin/src/assets/img/structures/rightFishbone.jpg delete mode 100644 plugin/src/assets/img/structures/rightFishbone2.jpg create mode 100644 plugin/src/components/ImgUpload/utils.js create mode 100644 plugin/src/mixins/fontFamily.js create mode 100644 plugin/src/mixins/imgHostingUpload.js delete mode 100644 plugin/src/pages/.DS_Store delete mode 100644 plugin/src/pages/Edit/.DS_Store create mode 100644 plugin/src/pages/Edit/components/FileSelectList.vue create mode 100644 plugin/src/pages/Edit/components/NodeTextInputObLink.vue create mode 100644 plugin/src/utils/CursorTextHandler.js delete mode 100644 更新记录.md diff --git a/.DS_Store b/.DS_Store index ea1dbc89a99a5de13eefc214619059789ff4f1b8..f92e96bc238d1c9793cdbcb0375f30a7f2989ffb 100644 GIT binary patch delta 165 zcmZoMXfc@JFT}yXz`)4BAi$7PoSc)CpP$3Hc_Q;FMlp~$3quM+K0`7?FzN!lVX7D=-)E9x;o4API{81744d}EUy%idlNFie x)FI5{jzF{77z!A27)lw^88R923Nj3Xlk;;6fZ_~%iVrrYF&DFJX6N|J4*>t@EkOVP delta 139 zcmZoMXfc@JFUrQiz`)4BAi%(o$&i;+UR;orlb^IPaXBL++hj$i3BrcvIts?-hP65h z)s{vEItnIcCX_jP48!2${M-VN9w68}g}InzVu9Xfc8 - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md index 81dfb4f..30eb832 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,16 @@ mind-map 也提供了独立的思维导图客户端,可以点击[客户端](https://github.com/wanglin2/mind-map/releases)了解更多。 +独立客户端下载(Windows、macOS、Linux):[点击这里](https://github.com/wanglin2/mind-map/releases) + +更新记录:[中文](./docs/changelog_zh.md) | [English](./docs/changelog.md) + +使用帮助:[中文](./docs/help_zh.md) | [English](./docs/help.md) + +图床配置帮助:[中文](./docs/imageHosting_zh.md) | [English](./docs/imageHosting.md) + # 功能清单 -- 快捷键 - - 从`0.1.5+`开始,插件不再提供默认的快捷键,全部转为ob的命令,你可以自行设置命令对应的快捷键。该[文档](./ShortcutKeySettingReference.md)列出了原来的快捷键,可供参考。 - - 思维导图本身的功能可从[mind-map](https://github.com/wanglin2/mind-map)项目了解更多,也可以在这里查[看常见问题](./Help_zh.md)。 - 思维导图文件格式 @@ -183,4 +187,3 @@ mind-map 也提供了独立的思维导图客户端,可以点击[客户端](ht - diff --git a/README_en.md b/README_en.md index e806a80..452b449 100644 --- a/README_en.md +++ b/README_en.md @@ -8,12 +8,16 @@ The mind map functionality is built upon the [mind-map](https://github.com/wangl mind-map also provides a standalone mind map client. Learn more about the [Client](https://github.com/wanglin2/mind-map/releases). +Download standalone client(Windows、macOS、Linux): [Click here](https://github.com/wanglin2/mind-map/releases) + +Changelog: [中文](./docs/changelog_zh.md) | [English](./docs/changelog.md) + +Help: [中文](./docs/help_zh.md) | [English](./docs/help.md) + +Image Hosting Help: [中文](./docs/imageHosting_zh.md) | [English](./docs/imageHosting.md) + # Feature List -- Shortcuts - - Starting from '0.1.5+', the plugin no longer provides default shortcut keys, all are converted to ob commands, and you can set the corresponding shortcut keys for the commands yourself. This [document](./ShortcutKeySettingReference_en.md) lists the original shortcut keys for reference. - - For mind map features, refer to the [mind-map](https://github.com/wanglin2/mind-map) project. You can also check [Common Issues](./Help.md) here. - Mind Map File Format @@ -134,4 +138,4 @@ mind-map also provides a standalone mind map client. Learn more about the [Clien # Bugs/Suggestions/Requests -Submit via [Issues](https://github.com/wanglin2/obsidian-simplemindmap/issues). +Submit via [Issues](https://github.com/wanglin2/obsidian-simplemindmap/issues). \ No newline at end of file diff --git a/ShortcutKeySettingReference.md b/ShortcutKeySettingReference.md deleted file mode 100644 index 4f1f266..0000000 --- a/ShortcutKeySettingReference.md +++ /dev/null @@ -1,135 +0,0 @@ -# 自定义命令快捷键参考 - -从0.1.5+开始,插件不再提供默认的快捷键,全部转为ob的命令,你可以自行设置命令对应的快捷键。本文档给出原默认的快捷键,可供参考。 - -> 本文档中提到的Ctrl键,在Mac系统中,对应的是Command键 -> -> 快捷键中的`|`表示或、`+`表示与 -> -> Obsidian不支持设置单个键的快捷键,比如单独的Enter、Tab、Del等,建议使用组合键,比如`Ctrl + Enter`等 - -## 编辑操作 - -- 保存 - -`Ctrl + S` - -- 保存并更新图像数据 - -`Ctrl + Shfit + S` - -## 节点操作 - -- 插入下级节点 - -`Tab | Insert` - -- 插入同级节点 - -`Enter` - -- 插入父节点 - -`Shift + Tab` - -- 上移节点 - -`Ctrl + ↑` - -- 下移节点 - -`Ctrl + ↓` - -- 插入概要 - -`Ctrl + G` - -- 展开/收起节点 - -`/` - -- 删除节点 - -`Delete | Backspace` - -- 仅删除当前节点 - -`Shift + Backspace` - -- 复制节点 - -`Ctrl + C` - -- 剪切节点 - -`Ctrl + X` - -- 粘贴节点 - -`Ctrl + V` - -- 编辑节点 - -`F2` - -- 回退 - -`Ctrl + Z` - -- 前进 - -`Ctrl + Y` - -- 全选 - -`Ctrl + A` - -- 一键整理布局 - -`Ctrl + R` - -- 搜索和替换 - -`Ctrl + F` - -- 切换粗体 - -`Control + B` - -- 切换斜体 - -`Control + I` - -- 切换下划线 - -`Control + U` - -- 切换删除线 - -`Control + [` - -- 增大字号 - -`Control + Shift + =` - -- 减小字号 - -`Control + Shift + -` - -## 画布操作 - -- 放大 - -`Ctrl + +` - -- 缩小 - -`Ctrl + -` - -- 回到根节点 - -`Ctrl + Enter` - -- 适应画布 - -`Ctrl + Shift + I` \ No newline at end of file diff --git a/ShortcutKeySettingReference_en.md b/ShortcutKeySettingReference_en.md deleted file mode 100644 index a42ccfd..0000000 --- a/ShortcutKeySettingReference_en.md +++ /dev/null @@ -1,135 +0,0 @@ -# Custom Command Shortcut Reference - -Starting from version 0.1.5+, the plugin no longer provides default shortcuts. All commands have been converted to OB commands, allowing you to set custom shortcuts for each command. This document lists the original default shortcuts for reference. - -> In this document, the Ctrl key corresponds to the Command key on Mac systems. -> -> The `|` symbol in shortcuts indicates "or," while `+` indicates "and." -> -> Obsidian does not support setting individual keys as shortcuts, such as `Enter`, `Tab`, `Del`, etc. It is recommended to use composite keys, such as `Ctrl + Enter`. - -## Editing Operations - -- Save - -`Ctrl + S` - -- Save and Update Image Data - -`Ctrl + Shift + S` - -## Node Operations - -- Insert Child Node - -`Tab | Insert` - -- Insert Sibling Node - -`Enter` - -- Insert Parent Node - -`Shift + Tab` - -- Move Node Up - -`Ctrl + ↑` - -- Move Node Down - -`Ctrl + ↓` - -- Insert Summary - -`Ctrl + G` - -- Expand/Collapse Node - -`/` - -- Delete Node - -`Delete | Backspace` - -- Delete Current Node Only - -`Shift + Backspace` - -- Copy Node - -`Ctrl + C` - -- Cut Node - -`Ctrl + X` - -- Paste Node - -`Ctrl + V` - -- Edit Node - -`F2` - -- Undo - -`Ctrl + Z` - -- Redo - -`Ctrl + Y` - -- Select All - -`Ctrl + A` - -- Auto-arrange Layout - -`Ctrl + R` - -- Search and Replace - -`Ctrl + F` - -- Toggle Bold - -`Control + B` - -- Toggle Italic - -`Control + I` - -- Toggle Underline - -`Control + U` - -- Toggle Strikethrough - -`Control + [` - -- Increase Font Size - -`Control + Shift + =` - -- Decrease Font Size - -`Control + Shift + -` - -## Canvas Operations - -- Zoom In - -`Ctrl + +` - -- Zoom Out - -`Ctrl + -` - -- Return to Root Node - -`Ctrl + Enter` - -- Fit to Canvas - -`Ctrl + Shift + I` \ No newline at end of file diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..e68e955 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,209 @@ +# v0.0.0 + +1: +- Save files in Markdown format as `.smm.md`. The "More" menu in the top-right corner now supports switching to Markdown editing mode. +- Node hyperlinks now support linking to Obsidian (`.md`) files. +- Split-view mode now synchronizes the mind map’s core data (basic configurations and settings are not synchronized). +- Clicking the save button in the top-right stores the current preview image, which can then be embedded into Markdown documents using `![[.smm.md]]` to display as an image. The image updates in real time when the source file is modified, and double-clicking the image opens the mind map editor. +- Node statistics have been added to the bottom status bar. +- A basic multilingual setting has been implemented. + +2: +- Mind map and SVG data are now compressed and encoded before saving. +- Fixed duplicate entries for the **Open as Markdown Document** option in the top-right "More" menu. +- Mind map settings are now persisted across sessions. +- Added settings for specifying mind map file path, image file path, default structure, default theme, and auto-save interval. +- Theme mode can now be set to: Follow Obsidian, Dark, or Light. +- Files are automatically saved before closing a tab to prevent data loss. +- Uploaded node and background images are stored in the vault; only file paths are saved in the mind map data to reduce file size. +- Node images can now be selected directly from images already in the vault. +- Embedded previews now use PNG instead of SVG. This significantly reduces saved data size but sacrifices SVG’s high resolution. +- Added **Copy as Obsidian Internal Link** to the canvas right-click menu. +- Added a "Saving..." indicator next to the save button. +- Node text input now supports typing `[[` to trigger a popup listing Obsidian files for inserting internal links. +- Obsidian files in the hyperlink dialog now support search. +- Notification messages and tooltips have been migrated from Element UI to Obsidian’s native components. +- Theme colors now follow Obsidian’s theme; non-Element UI component colors dynamically adapt to Obsidian’s theme. +- Added a button in the top-right corner to switch to outline editing mode. + +3: +- **Multilingual support**: + - Automatically follows Obsidian’s language setting. + - Plugin code now fully supports Chinese, English, Vietnamese, and Traditional Chinese. +- Image upload dialog for node images now supports dragging images directly from the Obsidian file list. +- Pasted images are now automatically saved as files in the vault. +- Added **Copy as Obsidian Internal Link** to the node right-click menu; opening the link automatically focuses on that node. +- **Internal Links**: + - Improved editing of rich-text internal links within nodes: during editing, raw syntax like `[[xxx]]` is shown; after editing, it renders as a clickable link. Supports suffixes like `#`, `^`, and `|`. + - Unified handling of internal links in both node hyperlinks and node text; updates are synchronized to the Markdown document. + - Fixed ambiguity when inserting internal links to files with identical names in different directories. + - Deduplication of internal links. +- Support embedding SMM-language code blocks in Markdown documents: + - Simple mind map editing is possible within the code block; all keyboard shortcuts and rich-text toolbar functions are available. + - Initial height can be set and adjusted by dragging. + - Action buttons: Return to root node, Fit to canvas. + - Command: Insert a mind map code block into the current document. +- File selection popups for node text now support keyboard navigation (arrow keys and Enter). +- Fixed abnormal rendering in the minimap. +- Fixed errors in presentation mode. +- Outline view now supports displaying and adding internal links. +- Improved UI styling, layout, and dark mode compatibility. + +4: +- When importing `.smm`, `.json`, or `.xmind` files, base64-encoded node images are converted and stored in the vault. +- Hyperlink icons now visually distinguish between Obsidian files and web URLs. +- When exporting to `.smm`, `.json`, or `.xmind`, images using Obsidian paths are converted to base64. +- Added links in settings for submitting issues and downloading the desktop client. +- Double-clicking an embedded preview without an image still navigates to the mind map editor. +- Hyperlinks now support adding local files; selected files are uploaded to the vault, and the storage path can be customized in settings. +- Image compression for uploads is now supported; compression settings (enabled/disabled and parameters) are configurable. +- Added setting to control whether double-clicking an `![[]]` embedded preview opens in a new tab. +- Added setting to toggle transparent background for embedded previews. +- Mind map file storage directory can be set to: vault root, a specified folder, or the same folder as the current file. +- Image and general file storage directories support four options: vault root, specified folder, current file’s folder, or a subfolder under the current file’s folder. +- Added settings for prefix and datetime format in new mind map filenames. +- Added onboarding guidance for first-time plugin users. + +5: +- Added setting to extend the list of fonts available in mind maps. +- Directory inputs in settings now support selecting vault folders. +- Markdown documents can now be previewed as mind maps, with options to switch structure/theme and export as PNG, SVG, or PDF. +- Structure options in settings are now localized; single-type structures no longer show redundant index labels. +- Added a read-only mode toggle button in the top-right corner. +- If a mind map contains image data, embedded previews use PNG; otherwise, SVG is used. SVG previews support transparent backgrounds. +- Code block embedding now supports toggling transparent background. +- Code block embedding supports switching structure and theme. +- Components are now imported on-demand to reduce bundle size and fix interference with Obsidian’s table styles. + +# v0.1.1 +1. Added **Copy Current Node as Image to Clipboard** to the node right-click menu—can be pasted directly into Obsidian documents. +2. Fixed an issue where editing the same file in multiple tabs caused node text to disappear when switching tabs. +3. Fixed unresponsive Delete key during text editing when multiple tabs edit the same file. +4. Automatically clears active states (e.g., text editing, node activation) when switching tabs. +5. Fixed overlap between the bottom toolbar and Obsidian’s status bar. +6. Default theme settings now differentiate between light and dark modes. +7. Added **Show Bottom Toolbar** toggle in the mind map view’s sidebar settings. +8. Intercepted Obsidian’s `Ctrl+S` and `Ctrl+F` shortcuts: `Ctrl+S` now triggers mind map save, and `Ctrl+F` opens the mind map search box. +9. Added command to enter presentation mode. +10. Fixed failure to auto-update preview images when `![[]]` embeds lacked an initial preview. +11. Added a “File deleted” warning when an embedded file is removed. +12. Fixed repeated file creation and failures from rapid clicks on the new-file icon due to incorrect directory resolution. +13. Fixed ignored width/height settings for embedded previews in reading mode. +14. Centered Obsidian whiteboard embeds and limited max dimensions to prevent overflow. +15. Supported embedding mind maps as images in Excalidraw (display size issues remain). +16. Added **Save and Update Image** command with shortcut `Ctrl+Shift+S`. +17. Fixed empty content in the node notes sidebar. +18. Holding `Ctrl`/`Command` while clicking a node hyperlink opens it in a new tab. +19. Fixed hanging “loading” state when importing invalid Markdown files; added user feedback. + +# v0.1.2 +1. Added **Enable Search in Obsidian** setting. When enabled, all node text is saved to the file to support Obsidian search; clicking search results auto-focuses the relevant node. +2. Added **Check for Updates** setting; checks for new versions on plugin startup. +3. Filters out YAML frontmatter when previewing Markdown as a mind map. +4. Holding `Shift` enables horizontal panning with the mouse wheel. +5. Supports parsing online images in Markdown during import or preview. +6. Prioritizes mind map rendering before loading UI elements to improve open speed. +7. Preserves user-edited YAML data. +8. Supports converting mind map documents to Markdown. +9. Supports converting Markdown documents to mind map format. +10. Notes images are now uploaded to the vault, consistent with node images. +11. Mobile adaptation: + - Added right-click menu icon on the left. + - Added helper buttons in outline editing. + - Disabled Obsidian sidebar during horizontal canvas dragging. + - Hidden non-essential buttons. + - Disabled onboarding tips. +12. Supports dragging files from the vault or local system onto nodes: images are inserted as node images; others become hyperlinks. +13. Fixed hidden top-right search box obstructing canvas and node interactions. +14. Fixed unintended canvas/toolbox shifts when editing text near canvas edges. +15. Added **Save Canvas Position and Zoom** setting. +16. Improved Markdown import: if multiple root nodes are detected, a new root wraps them instead of discarding extras. +17. Changed UID symbol in **Copy Node as Obsidian Internal Link** from `#` to `#^`. +18. When **Enable Search in Obsidian** is on, saved UIDs use `^` instead of `#`. +19. Hover previews of `[[ ]]` embeds in reading mode now auto-resize images. + +# v0.1.3 +1. Fixed `undefined` errors during Markdown import. +2. Added **Max Heading Level for Node-to-Markdown Conversion**: nodes above this level become Markdown headings; others become list items. +3. Preview image data is now stored as separate files by default: + 3.1. Added **Store Preview Image as File** setting (enabled by default). When on, SVG preview files are saved in the vault and only paths are stored in the mind map file. When off, base64 data is embedded (increasing file size). + 3.2. Deleting a mind map file in Obsidian also deletes its preview file. Manual cleanup is needed if deleted via the OS. Auto-deletion may fail in some edge cases. +4. Fixed loss of searchable text data when saving in outline mode. +5. Optimized layout algorithm for **Logic Structure** diagrams: faster rendering, resolved position conflicts between summary and regular nodes, and fixed missing layout updates after summary node resizing. +6. Added confirmation dialogs for mind map ↔ Markdown conversions. +7. Import dialog now supports dragging files from the vault or local system. +8. File name can now be edited directly in the title bar. + +# v0.1.4 +1. Fixed ability to drag files onto nodes in read-only mode. +2. Node text editing now supports direct internal link input: + 2.1. Typing `[[` triggers Obsidian file list; navigate with arrow keys, press Enter or click to insert; search supported. + 2.2. After editing, `[[ ]]` renders as a clickable link; `Ctrl+Click` opens in a new tab. + 2.3. Supports `#`, `^`, and `|` suffixes in pasted or typed links. +3. Simplified new mind map filename format setting into a single field supporting variables. +4. Added **Image Paste Naming Format** setting with variable support. +5. Added **Open Node Links in New Tab** setting (enabled by default). +6. Removed close buttons from all dialogs and disabled closing by clicking outside. +7. Fixed canvas background turning into the preview image when double-clicking a node image with transparent background enabled. +8. Added "+" button next to the tag input field. +9. Added guidance text to the import dialog. +10. Added **Bracket** style to line connection options under Basic Styles. +11. Summary nodes now support connectors, formulas, and attachments. +12. SVG export now supports transparent background. +13. Added tooltips to clarify complex settings in the right-side configuration sidebar. + +# v0.1.5 +**New Features**: +1. Added support for free-floating nodes. +2. Enhanced internal link editing in node text: + - Parses aliases and block references. + - Fixed broken link opening. + - Typing `【【` auto-corrects to `[[` and triggers file selection. + - Creates new files if linked file doesn’t exist. +3. Upgraded math formula rendering library for better output. +4. Added support for importing `.txt` files. +5. Automatic math formula rendering during import of `.mm`, `.xmind`, `.txt`, `.md`, and `.xlsx` files. +6. Improved Markdown export: + - Preserves and renders bold, italic, and strikethrough. + - Preserves icons, tags, hyperlinks, and images. + - Wraps summary and note content in code blocks to avoid structural pollution; supports re-import. +7. Preserves raw math formula syntax in `.md` and `.txt` exports for reliable re-import. +8. Adds `$` delimiters around math formulas in `.xmind` exports for better recognition. +9. Node width resizing now snaps to sibling node widths. +10. Rainbow lines moved from instance options to theme settings for per-file customization. +11. Added node margin controls in the node style sidebar. +12. Added **Select All Nodes** to both node and canvas right-click menus. +13. Added **Copy as Plain Text** to the node right-click menu. +14. Grouped node creation and copy/paste actions into a submenu. +15. Added keyboard shortcuts for bold, italic, underline, strikethrough, and font size adjustment on active nodes (may conflict with Obsidian shortcuts). +16. Outline sidebar fixes: + - Fixed outdated outline after immediate node level changes post-editing. + - Fixed outline sync when promoting an already-active node. + - `Tab` key now demotes nodes (previously promoted). +17. Fullscreen outline editing fixes: + - Fixed node text reverting to default after promotion post-editing. + - `Tab` key now demotes nodes. +18. Added ability (and shortcut) to split text after cursor into a sibling node in outline mode (shortcut may conflict with Obsidian). +19. Pasting multi-line text supports preserving or flattening hierarchy. +20. With free-drag enabled, holding `Ctrl` ignores hierarchy during dragging. +21. Line arrow styling: + - **Basic Styles**: set arrow direction. + - **Node Styles**: toggle arrow visibility. +22. Switched node notes editor from modal to sidebar mode. +23. Added support for configuring image hosting services (image beds). + +**Fixes & Optimizations**: +1. Fixed failure when converting mind maps to Markdown. +2. Fixed duplicate file creation from **New Mind Map** in right-click menu. +3. Fixed failed Markdown conversion after duplicating an `.smm` file via **Duplicate** in file explorer. +4. Fixed save errors when editing a mind map with no preview file while it’s embedded via `![[]]` in another Markdown file. +5. Fixed mismatched preview SVG filenames after renaming mind map files or converting to Markdown. +6. Fixed delayed update of `path` metadata after renaming mind map files. +7. Fixed background images in SVG exports ignoring stretch settings from Basic Settings. +8. Resolved node collision in Directory Organization diagrams. +9. Fixed export failures (PNG/SVG/PDF) when node text contained illegal characters. +10. Fixed first background image upload failing after uploading a node image. +11. Optimized Fishbone diagram code and node outer spacing. +12. Improved text visibility in dark theme for level-3+ node text editors (fixed similar background/text colors). +13. Added filename length validation and warning for Excel exports. +14. Improved dark mode styling in file list dialogs. \ No newline at end of file diff --git a/docs/changelog_zh.md b/docs/changelog_zh.md new file mode 100644 index 0000000..ac62849 --- /dev/null +++ b/docs/changelog_zh.md @@ -0,0 +1,191 @@ +# v0.0.0 + +1: +保存为md格式的文件.smm.md,右上角更多菜单中支持切换为md格式编辑 +节点超链接支持添加ob文件 +拆分模式支持思维导图本身数据的同步,基本配置、设置之类的不能同步 +点击右上角的保存按钮时会存储当前的预览图像,然后可以通过![[.smm.md]]嵌入md文档显示为图片,原文件修改后会实时同步,双击图片跳转到思维导图编辑 +节点统计添加到底部状态栏 +设置简单做了一个多语言设置 + +2: +思维导图和svg数据压缩编码后进行保存 +修复右上角更多菜单中【打开为Markdown文档】菜单重复的问题 +支持持久化思维导图中的设置 +支持设置思维导图文件路径、图片文件路径、默认结构、默认主题、无操作自动保存时间 +支持设置主题模式为:跟随ob、深色、浅色 +标签页关闭前触发保存,避免数据丢失 +节点图片、背景图片上传后保存到vault中,只存储文件路径,减少数据体积 +节点图片支持选择vault中的图片 +嵌入预览的数据由svg格式改为png格式,优点是保存的数据会小很多,缺点是没有svg高清 +画布右键菜单中增加【复制为ob内链】菜单 +保存按钮旁边增加保存中的提示 +节点文本输入支持输入[[弹出选择ob文件的列表,支持插入链接 +节点超链接弹窗中的ob文件支持搜索 +提示信息由elementui切换为obsidian +tooltip由elementui切换为obsidian +主题色改为ob的主题色,非elementui组件的颜色支持随ob的主题色改变 +右上角新增切换大纲编辑模式的按钮 + +3: +多语言 + 跟随ob的设置 + 完善插件代码多语言,支持中文、英文、越南语、繁体 +节点图片上传弹窗支持直接从ob文件列表中拖拽图片 +直接粘贴的图片也创建为文件添加到vault中 +节点右键菜单新增【复制到ob内链】菜单,打开该内链时自动定位到该节点 +内链 + 修改节点富文本内链链接的编辑方式,编辑过程中显示源码[[xxx]],编辑完成后渲染为链接。支持带#、^、|后缀的内链 + 统一处理节点超链接和节点文本中出现的ob内链,更新到md文档中 + 修复节点文本中的内链插入时不同目录的同名文件无法区分的问题 + 内链去重 +支持在markdown文档嵌入smm语言的代码块: + 可简单编辑思维导图,快捷键功能都可用,支持富文本工具栏 + 支持设置初始高度,支持拖拽调整高度 + 操作按钮:回到根节点、适应画布 + 命令:插入思维导图代码块到当前文档 +节点文本选择文件弹窗支持键盘操作,上下方向键,回车键 +修复小地图图片渲染异常的问题 +修复演示模式报错的问题 +大纲支持显示和添加内链 +完善界面样式、布局、暗黑模式等 + +4. +导入smm、json、xmind文件转换base64格式的节点图片,存储到vault中 +节点超链接图标区分ob文件和网页 +导出为smm、json、xmind文件时转换ob路径的图片为base64 +设置里增加提交issue和下载客户端的链接信息 +没有可预览图片双击也可以跳转 +超链接支持添加本地文件,选择的文件会上传到Vault中,存储路径可以在设置中修改 +支持压缩上传的图片,是否开启压缩及压缩参数可在设置中修改 +支持设置![[]]嵌入预览时双击是否新标签页打开 +增加嵌入预览背景是否透明的设置 +思维导图文件存储目录支持设置三种方式:仓库根目录、指定文件夹、当前文件所在的文件夹 +图片文件存储目录、文件存储目录支持设置四种方式:仓库根目录、指定文件夹、当前文件所在的文件夹、当前文件所在文件夹下指定的子文件夹 +支持设置新建思维导图文件名的前缀和日期时间戳格式 +增加首次进入插件时的引导提示 + +5. +设置里支持扩展思维导图可用的字体列表 +设置里的目录输入支持选择仓库目录 +支持将md文档预览为思维导图,支持切换结构、主题,可导出为png、svg、pdf +设置里的结构选项列表适配多语言、只有一个的结构类型名称不用加索引 +右上角新增切换为只读模式的图标按钮 +如果思维导图中存在图片数据,那么嵌入的图形为png格式,否则为svg格式,svg嵌入图像支持背景透明 +代码块嵌入支持设置背景是否透明 +代码块嵌入支持切换结构、主题 +按需引入组件,减小打包体积,修复对ob文档表格样式影响的问题 + +# v0.1.1 +1.节点右键菜单新增【复制当前节点为图片到剪贴板】,可在ob文档里粘贴; +2.修复同时打开多个标签页编辑同一个文件时,在其中一个标签页中修改后,切换到其他标签页中会出现节点文字消失的问题; +3.修复同时打开多个标签页编辑同一个文件时,会出现文本编辑中删除键不生效的问题; +4.切换标签页时自动关闭思维导图界面上的一些状态,比如文本编辑状态、节点激活状态等等; +5.修复底部工具栏可能会和ob的状态栏重叠的问题; +6.默认主题设置区分浅色和深色模式; +7.思维导图视图的侧边栏设置中新增【是否显示底部工具栏】的设置; +8.拦截ob的Ctrl+S和Ctrl+F快捷键,修改为Ctrl+S触发思维导图保存,Ctrl+F触发显示思维导图搜索框; +9.增加进入演示模式的命令; +10.修复md文档![[]]嵌入时没有预览图像的情况下,此时更新图像预览图不会自动更新的问题; +11.![[]]嵌入后,如果文件被删除,增加文件已被删除的提示; +12.修复因获取文件新建目录错误导致会重复创建文件及快速点击新建图标会出现文件创建失败的问题; +13.修复嵌入预览在阅读模式下指定的宽高不生效的问题; +14.ob白板嵌入预览时居中显示,限制显示的最大宽高避免溢出; +15.支持excalidraw中以图像嵌入思维导图文件,但是显示尺寸目前存在问题; +16.新增【保存并更新图像】的命令和快捷键Ctrl+Shift+S; +17.修复节点备注侧边栏内容为空的问题; +18.按住Ctrl/Command键点击节点超链接,会在新标签页打开超链接; +19.修复导入解析不了的md文件时一直处于loading状态的问题,同时增加提示; + +# v0.1.2 +1.增加设置【是否允许在ob中搜索】。开启后会额外保存所有节点文本的内容到文件中用于搜索。点击搜索结果打开思维导图文件时会自动定位到该节点; +2.增加设置【检查新版本】。开启后会在插件启动时检查是否有新版本可用; +3.将Markdown文档【预览为思维导图】时过滤掉开头的YAML Frontmatter; +4.支持按住Shift键时鼠标滚轮左右移动画布; +5.导入Markdown及将Markdown文档【预览为思维导图】时支持解析Markdown中的网络图片; +6.优先渲染思维导图,然后加载页面UI,提升打开速度; +7.保留用户编辑的YAML数据; +8.支持把思维导图文档转换为Markdown文档; +9.支持把Markdown文档转换为思维导图文档; +10.备注的图片上传到Vault中,和节点图片保持一致; +11.适配手机端:1.左侧增加右键菜单图标;2.大纲编辑增加辅助按钮;3.左右拖动画布时禁止ob侧边栏显示;4.隐藏一些非必要的按钮;5.不显示新手引导; +12.支持从仓库或电脑本地拖拽文件到节点,如果是图片文件则以节点图片方式插入,否则为超链接; +13.修复右上角隐藏的搜索框会挡住画布和节点操作的问题; +14.修复在画布右侧或底部边缘编辑文本时,当文本编辑框范围超出边缘后整个画布及右边框、工具栏都会左移或上移的问题; +15.增加设置【存储画布位置和缩放数据】; +16.优化Markdown的导入和解析:如果解析出多个根节点,不是只返回第一个,而是再创建一个根节点来包裹; +17.将【复制节点为ob内链】操作中保存uid的符号由#改为#^; +18.开启【支持ob搜索】设置后保存节点uid的符号由#改为^; +19.在md中通过[[]]嵌入后在阅读模式下鼠标悬浮预览时图片自适应; + +# v0.1.3 +1.修复导入md时会出现undefined的问题; +2.增加设置【节点文字转markdown标题的最大层级】:小于该层级的节点文字会转为Markdown标题,其余的转为无序列表; +3.嵌入预览的图像数据默认改为以独立的文件存储: + 3.1.增加设置【预览图像数据是否以文件形式存储】,默认开启,即图像数据以svg文件形式存储在仓库中,思维导图文件中只存储路径。关闭则将图像数据以base64存储在文件中,文件体积会增大: + 3.2.在ob软件中删除思维导图文件时同步删除预览文件,如果是在电脑的文件系统中删除,则需要手动删除。其他一些情况下也可能无法自动删除; +4.修复大纲模式下保存会丢失用于搜索的文本数据的问题; +5.优化【逻辑结构图】结构的布局算法,加快渲染速度;优化【逻辑结构图】结构的概要节点和普通节点的位置冲突问题;修复概要节点尺寸改变后没有触发布局更新的问题; +6.思维导图文件和md文件的互相转换增加确认弹窗; +7.导入文件弹窗支持拖拽仓库或电脑本地文件进行导入; +8.支持在标题栏修改文件名; + +# v0.1.4 +1.修复只读模式下可以拖拽文件到节点上的问题; +2.节点文本编辑支持直接输入内链: + 2.1.编辑时连续输入[[会弹出ob文件列表,按键盘的上下键可切换选中的文件,按回车键可插入所选的文件,也可鼠标点击选择,支持搜索; + 2.2.文本编辑完成后[[]]格式会渲染为超链接样式,点击可打开链接的文件,ctrl+鼠标左键可新标签页打开; + 2.3.输入或粘贴的内链支持#、^、|三种格式; +3.新建思维导图文件命名格式设置修改,从两个设置选项改为一个,支持使用变量; +4.增加设置【粘贴图片的命名方式】,支持使用变量; +5.增加设置【新标签页打开节点链接】,默认开启; +6.所有弹窗隐藏掉右上角的关闭按钮,以及禁止点击弹窗外部关闭弹窗; +7.修复画布背景设置为透明时双击节点图片预览时画布背景会变为该图片的问题; +8.节点标签添加输入框右侧增加添加按钮; +9.导入弹窗增加提示信息; +10.基础样式-连线风格增加【括号】样式; +11.概要节点允许添加关联线、公式、附件; +12.导出为svg文件支持设置背景是否透明; +13.思维导图视图右侧设置侧边栏中对部分比较难以理解的设置选项增加提示信息; + +# v0.1.5 +新增: +1.支持创建自由节点; +2.节点文本内链编辑优化:1.支持解析别名、区块等;2.修复无法打开链接的问题;3.输入【【支持自动修改为[[并弹出文件选择列表;4.文件不存在则创建; +3.升级数学公式渲染库版本,提升渲染效果; +4.支持导入txt文件; +5.导入mm、xmind、txt、md、xlsx文件支持自动转换并渲染数学公式; +6.导出md文件优化:1.支持保留和解析加粗、斜体、删除线样式;2.支持保留和解析图标、标签、超链接、图片内容;3.优化概要和备注内容的保存,通过代码块包裹,导入支持解析,避免污染结构; +7.导出md、txt文件保留数学公式源码,便于导入识别; +8.导出为xmind文件时数学公式的前后增加$符号,便于导入识别; +9.拖拽调整节点宽度支持吸附到兄弟节点宽度; +10.彩虹线条由实例化选项改为主题配置中的字段,以支持不同的思维导图文件个性化; +11.节点样式侧边栏增加节点外边距的设置; +12.节点和画布右键菜单新增一键选择节点菜单; +13.节点右键菜单增加复制为纯文本菜单; +14.节点右键菜单中的创建节点、复制粘贴系列收起到二级菜单中; +15.新增对激活节点使用加粗、斜体、下划线、删除线、增大减小字体的快捷键(部分快捷键可能和ob快捷键冲突,导致不生效); +16.侧边栏大纲:1.修复编辑完某个节点再立即上移节点层级时思维导图树更新大纲未更新的问题;2.修复在大纲中点击已激活节点时进行上移操作思维导图树更新大纲未更新的问题;3.大纲Tab快捷键改为下移节点层级; +17.全屏大纲编辑:1.修复编辑已存在或新建节点文本后再提升该节点层级时会导致该节点文本恢复为默认文本的问题;2.大纲Tab快捷键改为下移节点层级; +18.大纲编辑新增将当前节点光标后面的内容拆分创建为同级节点的能力和快捷键(快捷键可能和ob快捷键冲突,导致不生效); +19.粘贴多行文本时支持保留层级和不保留层级两种方式创建节点; +20.开启自由拖拽后,支持按住Ctrl键忽略节点层级拖拽; +21.连线箭头样式设置:1.【基础样式】中支持设置箭头方向;2.【节点样式】中支持设置显示箭头; +22.节点备注编辑器由弹窗模式改为侧边模式; +23.支持配置图床; + +修复/优化: +1.修复转换思维导图为md文件时会失败的问题; +2.修复右键菜单中点击新建思维导图会创建两个文件的问题; +3.修复在文件列表中先将smm文件右键【创建副本】,然后在对创建的副本点击转换为markdown文件失败的问题; +4.修复在其他md文件中![[]]嵌入思维导图文件后,同时打开且思维导图没有预览文件的情况下,编辑思维导图文件保存时会报错的问题; +5.修复修改脑图文件名、将思维导图转换为md文件操作没有同步修改预览svg文件名的问题; +6.修复修改脑图文件名时,文件元数据中的path字段没有立即更新的问题; +7.修复导出svg文件,背景图片没有按基础设置中设置进行拉伸的问题; +8.修复目录组织图节点冲突的问题; +9.修复节点文本输入了非法字符时导出图片、svg、pdf会失败的问题; +10.修复先在节点图片弹窗中上传图片,然后在基础设置中的背景图片中上传图片第一次会不生效的问题; +11.鱼骨图结构代码优化;优化节点外间距; +12.优化深色主题下编辑三级及以下节点文本时编辑框背景色和文字颜色相近导致看不清的问题; +13.导出弹窗中增加对导出excel文件的名称长度的校验和提示; +14.优化文件列表弹窗暗黑模式的样式; diff --git a/Help.md b/docs/help.md similarity index 99% rename from Help.md rename to docs/help.md index ec88db4..3b9f1f0 100644 --- a/Help.md +++ b/docs/help.md @@ -115,4 +115,4 @@ - **Node Line Style Inheritance?** If enabled, descendant nodes inherit line styles (unless they have custom styles). - *Toggle:* Settings → *Node Line Style Inherits from Ancestor*. + *Toggle:* Settings → *Node Line Style Inherits from Ancestor*. \ No newline at end of file diff --git a/Help_zh.md b/docs/help_zh.md similarity index 100% rename from Help_zh.md rename to docs/help_zh.md diff --git a/docs/imageHosting.md b/docs/imageHosting.md new file mode 100644 index 0000000..0e42767 --- /dev/null +++ b/docs/imageHosting.md @@ -0,0 +1,63 @@ +# Image Hosting Feature Description + +Once the image hosting is configured and enabled, all images uploaded during the mind map editing process will be uploaded to the image hosting service. This significantly reduces the size of the mind map source file and speeds up both reading and saving operations. + +Currently, the default integration uses PicGo software to manage the image hosting and images. PicGo is a free, open-source tool for managing image hosting services, supporting various platforms such as Alibaba Cloud and Qiniu Cloud. You can download it here: [GitHub](https://github.com/Molunerfinn/PicGo/releases). + +After configuration and enabling the feature, ensure that the PicGo software is running during the mind map editing process; otherwise, uploads will fail. If you wish to use other image hosting tools, you will need to configure and test them on your own. + +If an image fails to open after a successful upload, it may be due to permission issues. Please check whether the image hosting service has public access enabled. + +## imgHostingResponseField Configuration Description + +The interface response structure configuration is used to extract the image URL after a successful upload. The default setting is `data.result[0]`, where `data` represents the root object of the interface response data and cannot be modified. Other fields should be configured according to the structure of the interface response data. Examples are as follows: + +If the image hosting interface response data structure is: + +```json +{ + "success": true, + "result": ["https://example.com/image.jpg" ] +} +``` + +Then the interface response structure configuration should be: `data.result[0]`. + +If the image hosting interface response data structure is: + +```json +{ + "success": true, + "data": { + "url": "https://example.com/image.jpg" + } +} +``` + +Then the interface response structure configuration should be: `data.data.url`. + +If the image hosting interface response data structure is: + +```json +{ + "url": "https://example.com/image.jpg" +} +``` + +Then the interface response structure configuration should be: `data.url`. + +If the image hosting interface response data structure is: + +```json +https://example.com/image.jpg +``` + +Then the interface response structure configuration should be: `data`. + +If the image hosting interface response data structure is: + +```json +["https://example.com/image.jpg"] +``` + +Then the interface response structure configuration should be: `data[0]`. \ No newline at end of file diff --git a/docs/imageHosting_zh.md b/docs/imageHosting_zh.md new file mode 100644 index 0000000..bd022b7 --- /dev/null +++ b/docs/imageHosting_zh.md @@ -0,0 +1,63 @@ +# 图床功能说明 + +设置了图床并开启后,在思维导图编辑过程中上传的所有图片都会上传到图床,可显著减小思维导图源文件体积,加快读取和保存的速度。 + +目前默认适配的是PicGo软件来管理图床和图片,PicGo是一个免费、开源的图床管理工具,支持多种图床,如阿里云、七牛云等。可点击这里进行下载:[GitHub](https://github.com/Molunerfinn/PicGo/releases)。 + +配置完成并开启使用后,在编辑思维导图的过程中需确保PicGo软件正在运行,否则无法上传。如果你想要使用其他图床工具,需要自行配置和测试。 + +上传成功后图片却打开,可能是权限问题,需检查图床是否开启了公开访问权限。 + +## imgHostingResponseField配置说明 + +接口响应结构配置用于提取上传成功后的图片URL,默认是`data.result[0]`,`data`代表接口响应数据的根对象,不可修改。其他字段需根据接口响应数据的结构进行配置。示例如下: + +如果图床接口响应数据的结构为: + +```json +{ + "success": true, + "result": ["https://example.com/image.jpg" ] +} +``` + +则接口响应结构配置为:`data.result[0]`。 + +如果图床接口响应数据的结构为: + +```json +{ + "success": true, + "data": { + "url": "https://example.com/image.jpg" + } +} +``` + +则接口响应结构配置为:`data.data.url`。 + +如果图床接口响应数据的结构为: + +```json +{ + "url": "https://example.com/image.jpg" +} +``` + +则接口响应结构配置为:`data.url`。 + +如果图床接口响应数据的结构为: + +```json +https://example.com/image.jpg +``` + +则接口响应结构配置为:`data`。 + +图床接口响应数据的结构为: + +```json +["https://example.com/image.jpg"] +``` + +则接口响应结构配置为:`data[0]`。 \ No newline at end of file diff --git a/manifest.json b/manifest.json index 5aba6f2..e110be1 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "simple-mind-map", "name": "Simple mind map", - "version": "0.1.3", + "version": "0.1.5", "minAppVersion": "1.8.3", "description": "A relatively powerful mind map.", "author": "wanglin", diff --git a/plugin/.DS_Store b/plugin/.DS_Store index 1b3624311855b17c5c575976da4219a5feeb6721..6edaf1c2164f8f73b44e1e2c48c869c3ebe034a6 100644 GIT binary patch delta 122 zcmZoMXfc=|#>CJzu~2NHo}vg70|Nsi1A_oVQht68kj=o%P&~0vW3qt=ivklvK0{JU zadHll977R9GE8W*A@ens%?`{>OqB)qu~2NHo}wr#0|Nsi1A_nqLk>eKLvc!Ra!ykI#*NDvWk53QK+$}L zWQIg!+58-ai9OQwN#(@_NjdpRKxI3V3UV@wOAHLIF)}f;u(GjpaBy&Q#0F>Nmj{<5 zmXsDdB^E`4cp>@uIY}^fVp3RUYI(eXh;x2kNn&PRY7tmNW=bkhNlbWVUP^wsQ+{b) zN-A@+R(_rLPx>E(xkSQlS5Ql-#REhJ0~|U zzZ>W}AYcS~5e#^tG>qy2GME{P8HyN^AzshV0V#zFl?4~&<>cq314S4&ZoJO2nVo~5 i0~mH2H-2ZH%rBxV0x|}qz5zmmZP^?mvVnPG0}BAI?OPK7 diff --git a/plugin/SmmEditView.js b/plugin/SmmEditView.js index 76920c0..f1e8ebf 100644 --- a/plugin/SmmEditView.js +++ b/plugin/SmmEditView.js @@ -7,7 +7,8 @@ import { SMM_TAG, OUTLINE_ICON, MINDMAP_ICON, - PRINT_ICON + PRINT_ICON, + getSmmEditViewCount } from './ob/constant.js' import { initApp } from './src/main.js' import { @@ -15,10 +16,15 @@ import { parseMarkdownText, createDefaultText } from './ob/metadataAndMarkdown.js' -import { hideTargetMenu, checkVersion } from './ob/utils.js' +import { + hideTargetMenu, + smmFilePathToFileName, + formatFileName +} from './ob/utils.js' import LZString from 'lz-string' +import { base64ToFile } from './src/utils' +import ModifyFileName from './ob/ModifyFileName.js' -// 自定义视图类 class SmmEditView extends TextFileView { constructor(leaf, plugin) { super(leaf) @@ -30,28 +36,17 @@ class SmmEditView extends TextFileView { height: 100%; overflow: hidden; ` - // 字符串类型的文件数据 this.mindMapData = '' - // 解析后的文件数据 this.parsedMindMapData = null - // Vue实例 this.mindMapAPP = null - // 当前视图是否处于激活状态 this.isActive = true - // 监听容器元素的尺寸变化 this.resizeObserver = null - // 当前文件是否存在未保存的内容 this.isUnSave = false - // 是否外部修改了当前文件 this.isOuterChange = false - // 是否不要触发data_change事件,当外部修改数据时进行同步使用 this.isNotTriggerDataChange = false - // 标签页是否处于隐藏状态 this.isHidden = false - // 标签页激活时是否需要通知思维导图刷新尺寸 this.needResize = false - // 按钮元素 this.isOutlineEditMode = false this.saveButton = null this.exportButton = null @@ -62,46 +57,39 @@ class SmmEditView extends TextFileView { this.savingTipEl = null this.isReadonlyMode = false this.toggleReadonlyButton = null + this.modifyFileName = new ModifyFileName(this) this.popScope = null + this.id = getSmmEditViewCount() } - // 获取视图类型 getViewType() { return SMM_VIEW_TYPE } - // 获取图标名称 getIcon() { return 'smm-icon' } - // 右上角更多菜单扩展 onPaneMenu(menu, source) { super.onPaneMenu(menu, source) - // 隐藏特定默认菜单项 hideTargetMenu(menu, '在新窗口中打开') hideTargetMenu(menu, '移动至新窗口') } - // 切换到Markdown视图 async switchToMarkdownView() { if (!this.file || !this.leaf) return - // 获取默认的Markdown视图类型 const mdViewType = this.app.viewRegistry.getTypeByExtension('md') - // 切换到Markdown视图 await this.leaf.setViewState({ type: mdViewType, state: { ...this.leaf.getViewState().state, isSwitchToMarkdownViewFromSmmView: true }, - popstate: true // 保持导航历史 + popstate: true }) } - // 打开视图 async onOpen() { - // 注册文件修改监听器 this.registerEvent( this.app.vault.on('modify', this._handleExternalChange.bind(this)) ) @@ -112,33 +100,22 @@ class SmmEditView extends TextFileView { this._handleActiveChange.bind(this) ) ) - // 注册窗口大小变化监听 this.registerEvent( this.app.workspace.on('resize', this._handleResize.bind(this)) ) - // 在视图头部右侧添加工具按钮 this._addActionBtns() - // 监听主题模式改变 this._initThemeMode() - // 检查更新 - if (this.plugin.settings.openVersionCheck) { - checkVersion(version => { - if (version) { - new Notice(this.plugin._t('tip.pluginNewVersion') + version) - } - }) - } + this.modifyFileName.setupTitleEditing() + this._registerHotkeyOverrides() } - // 获取视图数据(保存到文件) getViewData() { return this.mindMapData } - // 解析加载的数据 async setViewData(data, isClear) { if (this.isHidden) { return @@ -148,16 +125,25 @@ class SmmEditView extends TextFileView { } let rawData = data.trim() try { - // 空文件处理 if (!rawData) { - // 文件内容为空 throw new Error(this.plugin._t('tip.fileIsEmpty')) } else { this.parsedMindMapData = parseMarkdownText(rawData) const content = this.parsedMindMapData.metadata.content if (content) { - this.parsedMindMapData.metadata.content = - LZString.decompressFromBase64(content) + let passedContent = '' + try { + // 兼容未编码的老版数据 + const json = JSON.parse(content) + if (json && json.root) { + passedContent = content + } + } catch (error) {} + if (!passedContent) { + this.parsedMindMapData.metadata.content = LZString.decompressFromBase64( + content + ) + } } else { throw new Error('文件格式错误') } @@ -186,7 +172,6 @@ class SmmEditView extends TextFileView { } } - // 清理观察者 _clearObserver() { if (this.resizeObserver) { this.resizeObserver.disconnect() @@ -194,7 +179,6 @@ class SmmEditView extends TextFileView { } } - // 渲染思维导图 _renderMindMap() { this.warpEl.empty() const el = this.warpEl.createDiv('smmMindMapEdit') @@ -203,9 +187,7 @@ class SmmEditView extends TextFileView { height: 100%; overflow: hidden; ` - // 清理旧的观察者 this._clearObserver() - // 创建新的尺寸观察者 this.resizeObserver = new ResizeObserver(entries => { for (const entry of entries) { const { width, height } = entry.contentRect @@ -219,9 +201,7 @@ class SmmEditView extends TextFileView { this.resizeObserver.observe(el) } - // 实际初始化思维导图 _initializeMindMap(el) { - // 确保没有重复初始化 if (this.mindMapAPP) return const filePath = this.file?.path let initLocationNodeId = '' @@ -231,47 +211,64 @@ class SmmEditView extends TextFileView { delete fileToSubpathMap[filePath] } this.mindMapAPP = initApp(el, { - // 传递初始数据给思维导图渲染 getInitMindMapData: () => { return this.parsedMindMapData.metadata.content }, - // 获取思维导图初始化位置的节点ID getInitLocationNodeId: () => { return initLocationNodeId }, - // 从思维导图获取最新数据 getMindMapCurrentData: (content, linkData, textData) => { this.parsedMindMapData.metadata.content = content - const { metadata, svgdata, linkdata } = this.parsedMindMapData + const { + metadata, + svgdata, + svgdataUpdateAt, + linkdata + } = this.parsedMindMapData this.mindMapData = assembleMarkdownText({ metadata: { - path: `${filePath}`, + path: `${this.file?.path}`, tags: Array.from(new Set([SMM_TAG, ...metadata.tags])), content: LZString.compressToBase64(content), yaml: metadata.yaml }, svgdata, + svgdataUpdateAt, linkdata: linkData || linkdata || [], textdata: textData || [] }) }, - // 思维导图中触发保存 - saveMindMapData: (_, svgData) => { - if (svgData) { - this.parsedMindMapData.svgdata = LZString.compressToBase64(svgData) - } - this.forceSave() + saveMindMapData: async (_, svgData) => { + try { + this._showSavingTip() + const { embedImageIsSeparateFile } = this.plugin.settings + if (svgData) { + if (embedImageIsSeparateFile) { + const res = await this._getFileSvgData(svgData) + if (res) { + this.parsedMindMapData.svgdata = `![[${res}]]` + this.parsedMindMapData.svgdataUpdateAt = moment().format( + 'YYYY-MM-DD HH:mm:ss' + ) + } else { + new Notice(this.plugin._t('tip.imgCreateFail')) + } + } else { + this.parsedMindMapData.svgdata = LZString.compressToBase64( + svgData + ) + } + } + this.forceSave() + } catch (error) {} }, - // 获取思维导图配置 getMindMapConfig: () => { return this.plugin.settings.mindMapConfig || {} }, - // 设置思维导图配置 saveMindMapConfig: newConfig => { this.plugin.settings.mindMapConfig = newConfig this.plugin._saveSettings() }, - // 获取思维导图本地配置 getMindMapLocalConfig: () => { const { mindMapLocalConfig, themeMode } = this.plugin.settings const config = mindMapLocalConfig || {} @@ -281,12 +278,10 @@ class SmmEditView extends TextFileView { : themeMode === 'dark' return config }, - // 设置思维导图本地配置 saveMindMapLocalConfig: newConfig => { this.plugin.settings.mindMapLocalConfig = newConfig this.plugin._saveSettings() }, - // 获取设置 getSettings: () => { return this.plugin.settings || {} }, @@ -297,7 +292,6 @@ class SmmEditView extends TextFileView { } this.plugin._saveSettings() }, - // 获取所有文件 getObAllFiles: (extraSelf = true) => { const fileList = this.app.vault.getFiles() if (extraSelf && this.file) { @@ -307,140 +301,190 @@ class SmmEditView extends TextFileView { } return fileList }, - // 创建内链文件信息 - createLinkInfoFromFilePath: filePath => { - const file = this.app.vault.getFileByPath(filePath) + createLinkInfoFromFilePath: (filePath, subpath = '', alias = '') => { + const file = this.tryGetFileByPath(filePath) if (!file) { return null } const linkText = this.app.fileManager.generateMarkdownLink( file, - this.file?.path || '' + this.file?.path || '', + subpath, + alias ) return { link: file.path, linkText } }, - // 打开文件 - openFile: (filePath, isNewTab = false) => { + openFile: (filePath, isNewTab = false, createOnNoExist = false) => { if (!filePath) return - // [[xxx#xxx]]、[[xxx^xxx]]、[[xxx|xxx]] const arr = filePath.split(/(#|^|\|)/) filePath = arr[0] let postfix = '' if (arr.length > 1 && arr[1] !== '|') { postfix = arr.slice(1).join('') } - this.app.vault.getAbstractFileBy - let file = this.app.vault.getFileByPath(filePath) - if (!file) { - file = this.app.vault.getFileByPath(filePath + '.md') - } + const file = this.tryGetFileByPath(filePath) if (file && file instanceof TFile) { - this.app.workspace.openLinkText(file.path + postfix, '', isNewTab) + this.app.workspace.openLinkText( + file.path + postfix, + this.file?.path || '', + isNewTab + ) + } else if (createOnNoExist) { + this.app.workspace.openLinkText( + /\.md$/.test(filePath) ? filePath : filePath + '.md', + this.file?.path || '', + isNewTab + ) } }, - // 核心方法:打开网页链接 openWebLink: url => { if (this.app.openExternal) { this.app.openExternal(url) return } - // 兼容旧版 Obsidian 和移动端 try { - // 桌面端 Electron 环境 if (window.require) { const { shell } = window.require('electron') shell.openExternal(url) return } - } catch (e) { - console.error('Electron module not available', e) - } - // 通用回退方案 + } catch (e) {} window.open(url, '_blank', 'noopener,noreferrer') }, - // 保存文件到 vault - saveFileToVault: async (file, isImg = true) => { - try { - const folder = isImg - ? this._getFileSavePath( - 'imagePathType', - 'imagePath', - 'imageSubPath' - ) - : this._getFileSavePath( - 'attachmentPathType', - 'attachmentPath', - 'attachmentSubPath' - ) - await this.plugin._ensureDirectoryExists(folder) - // 处理文件名冲突 - let fileName = file.name - let counter = 1 - while ( - await this.app.vault.adapter.exists( - folder ? `${folder}/${fileName}` : fileName - ) - ) { - const parts = file.name.split('.') - const ext = parts.pop() - fileName = `${parts.join('.')}_${counter}.${ext}` - counter++ - } - // 读取文件内容 - const arrayBuffer = await file.arrayBuffer() - // 在vault中创建路径 - const vaultPath = folder ? `${folder}/${fileName}` : fileName - // 写入文件 - await this.app.vault.createBinary(vaultPath, arrayBuffer) - return vaultPath - } catch (error) { - return null - } + saveFileToVault: async (...args) => { + const res = await this.saveFileToVault(...args) + return res }, - // 获取资源路径 getResourcePath: vaultPath => { return this.app.vault.adapter.getResourcePath(vaultPath) }, - // 获取当前文件的链接信息 getObInternalLink: (...args) => { - return this.app.fileManager.generateMarkdownLink(this.file, ...args) + return this.app.fileManager.generateMarkdownLink(this.file, '', ...args) }, - // 显示ob提示 showTip: tip => { new Notice(tip) }, - // 从ob://协议的URI中获取文件信息 getFileFromUri: uri => { const params = new URLSearchParams(uri.split('?')[1]) const vault = decodeURIComponent(params.get('vault') || '') const filePath = decodeURIComponent(params.get('file') || '') if (!vault || !filePath) return null - // 检查当前vault是否匹配 if (this.app.vault.getName() !== vault) { - // 只允许添加当前仓库的文件 new Notice(this.plugin._t('tip.onlyEnableSelectCurrentVaultFile')) return null } - let res = this.app.vault.getFileByPath(filePath) - if (!res) { - res = this.app.vault.getFileByPath(filePath + '.md') - } - return res + return this.tryGetFileByPath(filePath) }, isMobile: () => { return Platform.isMobile + }, + getObsidianApp: () => { + return this.app + }, + getFormatFileName: (str, ignores = []) => { + return formatFileName(str, { + notename: this.file?.basename.split('.')[0], + ignores + }) } }) - setTimeout(() => { this._listenMindMapEvent() }, 100) } - // 根据uid定位到指定节点 + tryGetFileByPath(filePath) { + let res = this.app.vault.getFileByPath(filePath) + if (!res) { + res = this.app.vault.getFileByPath(filePath + '.md') + } + if (!res) { + res = this.app.metadataCache.getFirstLinkpathDest( + filePath, + this.file?.path + ) + } + return res + } + + async _getFileSvgData(svgData) { + const targetFileName = smmFilePathToFileName(this.file?.path, '.svg') + const { embedImageIsSeparateFileFolder } = this.plugin.settings + const originSvgData = this.parsedMindMapData.svgdata + if (originSvgData && /^!\[\[/.test(originSvgData)) { + const match = originSvgData.match(/!\[\[([^\]]+)\]\]/) + if (match && match[1]) { + const filePath = match[1] + const fileName = filePath.split('/').pop() + if (fileName !== targetFileName) { + const exist = await this.app.vault.exists(filePath) + if (exist) { + await this.app.vault.adapter.remove(filePath) + } + } + } + } + svgData = base64ToFile(svgData, targetFileName) + const res = await this.saveFileToVault( + svgData, + true, + embedImageIsSeparateFileFolder, + true + ) + return res + } + + async saveFileToVault(file, isImg = true, targetFolder = '', cover = false) { + try { + let folder = targetFolder || '' + if (!folder) { + folder = isImg + ? this._getFileSavePath('imagePathType', 'imagePath', 'imageSubPath') + : this._getFileSavePath( + 'attachmentPathType', + 'attachmentPath', + 'attachmentSubPath' + ) + } + await this.plugin._ensureDirectoryExists(folder) + let fileName = file.name + let fileExist = false + if (!cover) { + let counter = 1 + while ( + await this.app.vault.adapter.exists( + folder ? `${folder}/${fileName}` : fileName + ) + ) { + const parts = file.name.split('.') + const ext = parts.pop() + fileName = `${parts.join('.')}_${counter}.${ext}` + counter++ + } + } else { + fileExist = await this.app.vault.adapter.exists( + folder ? `${folder}/${fileName}` : fileName + ) + } + // 读取文件内容 + const arrayBuffer = await file.arrayBuffer() + // 在vault中创建路径 + const vaultPath = folder ? `${folder}/${fileName}` : fileName + // 写入文件 + if (fileExist) { + await app.vault.adapter.writeBinary(vaultPath, arrayBuffer) + } else { + await this.app.vault.createBinary(vaultPath, arrayBuffer) + } + return vaultPath + } catch (error) { + return null + } + } + jumpToNodeByUid(uid) { if (!this.mindMapAPP) { return @@ -448,13 +492,12 @@ class SmmEditView extends TextFileView { this.mindMapAPP.$bus.$emit('jumpToNodeByUid', uid) } - // 重写保存钩子(最直接的方式) - async save() { - if (!this.isActive) { + async save(ignoreActiveCheck = false) { + if (!ignoreActiveCheck && !this.isActive) { return } - // 获取一下最新数据 - // 取消本次自动保存 + if (this.app.noSaveOnClose) return + const t = Date.now() if (this.mindMapAPP) { this.mindMapAPP.$bus.$emit('getMindMapCurrentData') this.mindMapAPP.$bus.$emit('clearAutoSave') @@ -467,26 +510,21 @@ class SmmEditView extends TextFileView { this._hideSavingTip() } - // 强制保存 - forceSave() { + forceSave(ignoreActiveCheck = false) { this._showSavingTip() - this.save() + this.save(ignoreActiveCheck) } - // 强制保存并更新图像数据 forceSaveAndUpdateImage() { this._showSavingTip() this.mindMapAPP.$bus.$emit('saveToLocal', true, true) } - // 监听思维导图事件 _listenMindMapEvent() { this._onDataChange = this._onDataChange.bind(this) this.mindMapAPP.$bus.$on('data_change', this._onDataChange) - // this.mindMapAPP.$bus.$on('view_data_change', this._onDataChange) } - // 监听思维导图数据改变 _onDataChange() { if (this.isNotTriggerDataChange) { this.isNotTriggerDataChange = false @@ -495,7 +533,6 @@ class SmmEditView extends TextFileView { this._setIsUnSave(true) } - // 处理窗口大小变化 _handleResize() { if (!this.mindMapAPP || this.needResize) { return @@ -511,20 +548,15 @@ class SmmEditView extends TextFileView { this.mindMapAPP.$updateMindMapSize() } } - } catch (e) { - console.error('更新尺寸失败:', e) - } + } catch (e) {} } - // 处理标签激活状态变化 async _handleActiveChange(leaf) { const nowActive = leaf?.view === this if (nowActive && !this.isActive) { - // 标签被激活 + this._registerHotkeyOverrides() this.isActive = true - // 激活后刷新视图 if (this.mindMapAPP) { - // 更新外部修改 if (this.isHidden) { this.isHidden = false this._checkForExternalChanges() @@ -539,7 +571,7 @@ class SmmEditView extends TextFileView { } } } else if (!nowActive && this.isActive) { - // 标签失去激活 + this._clearPopScope() const rect = this.warpEl.getBoundingClientRect() this.isHidden = rect.width === 0 || rect.height === 0 if (this.mindMapAPP) { @@ -551,7 +583,6 @@ class SmmEditView extends TextFileView { } } - // 处理外部文件修改 async _handleExternalChange(file) { if (this.isActive) return if (file.path === this.file?.path) { @@ -559,29 +590,20 @@ class SmmEditView extends TextFileView { } } - // 检查外部修改并更新 async _checkForExternalChanges() { if (!this.file) return try { - // 重新加载文件数据 const data = await this.app.vault.read(this.file) await this.setViewData(data, false) - } catch (e) { - console.error('处理外部修改失败:', e) - } + } catch (e) {} } - // 清空视图数据 clear() { - // 清理观察者 this._clearObserver() - // 销毁应用实例 if (this.mindMapAPP) { try { this.mindMapAPP.$destroy() - } catch (e) { - console.error('销毁实例时出错:', e) - } + } catch (e) {} this.mindMapAPP = null } this.warpEl.empty() @@ -596,7 +618,9 @@ class SmmEditView extends TextFileView { } async onClose() { - await this.save() // 手动保存 + this._clearPopScope() + this.modifyFileName.unload() + await this.save() this.clear() this.saveButton = null this.exportButton = null @@ -607,7 +631,6 @@ class SmmEditView extends TextFileView { this.toggleReadonlyButton = null } - // 防抖函数实现 _debounce(func, wait) { let timeout return () => { @@ -618,12 +641,9 @@ class SmmEditView extends TextFileView { } } - // 在视图头部右侧添加工具按钮 _addActionBtns() { - // svg需添加class="svg-icon" const viewActions = this.headerEl.querySelector('.view-actions') - // 切换只读/编辑模式 this.toggleReadonlyButton = this._createActionBtn( this.plugin._t('action.changeToReadonly'), 'book-open', @@ -661,7 +681,6 @@ class SmmEditView extends TextFileView { true ) - // 切换为大纲模式 this.changeToOutlineButton = this._createActionBtn( this.plugin._t('action.changeToOutline'), OUTLINE_ICON, @@ -677,7 +696,6 @@ class SmmEditView extends TextFileView { } ) - // 切换为思维导图模式 this.changeToMindmapButton = this._createActionBtn( this.plugin._t('action.changeToMindMap'), MINDMAP_ICON, @@ -690,7 +708,6 @@ class SmmEditView extends TextFileView { ) this._hideButtons([this.changeToMindmapButton]) - // 打印大纲 this.printOutlineButton = this._createActionBtn( this.plugin._t('action.printOutline'), PRINT_ICON, @@ -701,7 +718,6 @@ class SmmEditView extends TextFileView { ) this._hideButtons([this.printOutlineButton]) - // 导入 this.importButton = this._createActionBtn( this.plugin._t('action.import'), IMPORT_ICON, @@ -711,7 +727,6 @@ class SmmEditView extends TextFileView { } ) - // 导出 if (!Platform.isMobile) { this.exportButton = this._createActionBtn( this.plugin._t('action.export'), @@ -733,7 +748,6 @@ class SmmEditView extends TextFileView { } ) - // 保存中的提示 this.savingTipEl = this.headerEl.createEl('div', { cls: 'smm-save-tip' }) @@ -742,7 +756,6 @@ class SmmEditView extends TextFileView { _showSavingTip() { if (!this.savingTipEl) return - // 保存中... this.savingTipEl.innerText = this.plugin._t('tip.saving') } @@ -751,7 +764,6 @@ class SmmEditView extends TextFileView { this.savingTipEl.innerText = '' } - // 创建工具按钮 _createActionBtn(label, icon, parentEl, onClick, isObIcon = false) { const el = this.headerEl.createEl('button', { cls: 'clickable-icon' @@ -767,7 +779,6 @@ class SmmEditView extends TextFileView { return el } - // 重置大纲编辑模式 _resetOnOutlineEditMode() { if (this.isOutlineEditMode) { this.saveButton.setAttribute( @@ -794,19 +805,14 @@ class SmmEditView extends TextFileView { }) } - // 设置是否存在未保存的内容 _setIsUnSave(isUnSave) { - if (!this.saveButton) return this.isUnSave = isUnSave this.saveButton.style.color = isUnSave ? '#ff6600' : 'var(--icon-color)' } - // 检测主题模式 _initThemeMode() { - // 初始检查 this._updateThemeMode() - // 监听主题变化事件 this.registerEvent( this.app.workspace.on('css-change', () => { this._updateThemeMode() @@ -814,7 +820,6 @@ class SmmEditView extends TextFileView { ) } - // 更新主题模式 _updateThemeMode() { if (this.plugin.settings.themeMode === 'follow') { const isDarkMode = this.plugin._getObIsDark() @@ -824,7 +829,6 @@ class SmmEditView extends TextFileView { } } - // 获取图片、文件存储路径 _getFileSavePath(typeKey, pathKey, subPathKey) { const type = this.plugin.settings[typeKey] const folder = this.plugin.settings[pathKey] || '' @@ -843,6 +847,36 @@ class SmmEditView extends TextFileView { return '' } } + + _clearPopScope() { + if (this.popScope) { + this.popScope() + this.popScope = null + } + } + + _registerHotkeyOverrides() { + this._clearPopScope() + const scope = this.app.keymap.getRootScope() + const ctrlFHandler = scope.register(['Mod'], 'f', evt => { + evt.preventDefault() + return true + }) + const ctrlSHandler = scope.register(['Mod'], 's', evt => { + evt.preventDefault() + const view = this.plugin._getActiveSmmView() + if (view) { + view.forceSave() + } + return true + }) + scope.keys.unshift(scope.keys.pop()) + scope.keys.unshift(scope.keys.pop()) + this.popScope = () => { + scope.unregister(ctrlFHandler) + scope.unregister(ctrlSHandler) + } + } } export default SmmEditView diff --git a/plugin/locales/en.json b/plugin/locales/en.json index 4de8e37..779bf57 100644 --- a/plugin/locales/en.json +++ b/plugin/locales/en.json @@ -3,7 +3,7 @@ "mindMap": "Mind map", "rootNodeDefaultText": "Root node", "secondNodeDefaultText": "Secondary node", - "branchNodeDefaultText": "Branch node" + "branchNodeDefaultText": "Branch topic" }, "action": { "createMindMap": "Create new mind map", @@ -23,9 +23,13 @@ "changeToMindMapFile": "Convert to mind map document" }, "tip": { + "tip": "Tip", + "confirm": "Confirm", + "cancel": "Cancel", + "close": "Close", "fileExist": "File already exists", "createMindMapFail": "Failed to create mind map", - "fileIsNotMd": "Current file is not a Markdown document", + "fileIsNotMd": "Current file is not a markdown document", "fileIsEmpty": "File content is empty", "fileFormatError": "File format error", "onlyEnableSelectCurrentVaultFile": "Only files from the current vault can be added", @@ -40,7 +44,14 @@ "pluginNoNewVersion": "The current version is already the latest version", "pluginVersionCheckError": "Check failed", "changeSuccess": "Change completed", - "mdToMindMapFail": "Conversion failed, unable to parse data that can be converted into a mind map" + "mdToMindMapFail": "Conversion failed, unable to parse data that can be converted into a mind map", + "imgCreateFail": "Image file creation failed", + "mdModifyTip": "Do not modify any information except YAML", + "fileNameEmpty": "The file name cannot be empty", + "fileNameIllegal": "The file name contains illegal characters", + "fileRenameFail": "File renaming failed", + "mindMapToMdTip": "After converting to a Markdown document, only some content will be retained, such as node text, summary text, notes, etc. Other content will be discarded and cannot be recovered. Please make a backup first.", + "mdToMindMapTip": "Only supports converting syntax such as titles and lists into mind maps. Other content will be discarded and cannot be recovered. Please make a backup first." }, "setting": { "title": { @@ -48,7 +59,8 @@ "title2": "File", "title3": "Image compression", "title4": "Embed", - "title5": "Other" + "title5": "Other", + "title6": "Image hosting" }, "themeMode": { "title": "Theme mode", @@ -61,7 +73,7 @@ "title": "Default theme (light color)", "desc": "Default theme for creating a mind map file in light color mode", "title2": "Default theme (dark color)", - "desc2": "Default theme for creating a mind map file in dark color mode" + "desc2": "Default theme for creating a mind map file in dark mode" }, "layout": { "title": "Default layout", @@ -89,7 +101,9 @@ "title8": "Support ob search", "desc8": "Mind map data is stored after encoding and compression, so it cannot be searched in OB. If you want to search for the node text content of the mind map in OB, you can turn on this option. After turning it on, the text content of all nodes will be saved in the file for search. The side effect is that it will cause the file size to increase, which may affect the speed of file opening and saving", "title9": "Store canvas position and scaling data", - "desc9": "After opening, the canvas position and zoom data will be saved in the file, so that the next time it is opened, it can be restored to the position and zoom state when it was closed last time. The disadvantage is that moving and scaling the canvas will cause file changes" + "desc9": "After opening, the canvas position and zoom data will be saved in the file, so that the next time it is opened, it can be restored to the position and zoom state when it was closed last time. The disadvantage is that moving and scaling the canvas will cause file changes", + "title10": "The maximum level for converting node text to Markdown titles", + "desc10": "Nodes with text less than or equal to this level will be converted to Markdown titles, while the rest will be converted to unordered lists" }, "compress": { "title1": "Compress images", @@ -109,7 +123,9 @@ }, "codeBlock": { "title": "Code block initial height", - "desc": "Initial height when embedding via smm code block (pixels)" + "desc": "Initial height when embedding via smm code block (pixels)", + "title2": "Code block background transparent", + "desc2": "Whether the background of the embedded smm code block is transparent, otherwise it will follow the selected mind map theme background color" }, "linkInfo": { "issues": "Bugs and feature requests", @@ -117,16 +133,32 @@ "community": "Community" }, "embed": { - "title1": "Embed preview double click to open a new window", - "desc1": "When embedding an MD document in format ![[]], double-click to preview the image and open the file in a new window", + "title1": "Embed preview double click to open a new tab", + "desc1": "When embedding an MD document in format ![[]], double-click to preview the image and open the file in a new tab", "title2": "Embed preview background transparent", - "desc2": "Set whether the background of the embedded preview image is transparent" + "desc2": "Is the background of the preview image embedded in the format of ![[]] transparent", + "title3": "Is the embedded image stored as a separate file", + "desc3": "By default, images used for embedding preview in ![[]] format will be stored separately in the repository as SVG files. This way, only the file path is stored in the mind map file, which can significantly reduce the file size and speed up file reading and saving. If closed, the image data will be stored in the mind map file, and the volume will significantly increase", + "title4": "Embedded image file storage directory", + "desc4": "The folder where the embedded preview image files are stored should not be empty relative to the repository root directory, and the directory should start with . as the hidden folder", + "title5": "New tab opens node link", + "desc5": "Does clicking on the inserted node link (excluding network links) open in a new tab. After closing, you can also open a new tab by pressing Ctrl+left mouse button" }, "file": { - "title1": "New mind map file name prefix", - "desc1": "Default naming format for new mind map files: Prefix + Space + Date Timestamp", - "title2": "Date timestamp format for new mind map files", - "desc2": "Default format: YYYY-MM-DD HH.mm.ss, Example: 2025-01-01 23.59.59. For details on format meaning and modification, refer to: https://day.js.org/docs/en/parse/string-format" + "title1": "File name format for creating a new mind map", + "desc1": "Naming format for creating a new mind map file name. Support variables other than notename", + "title3": "Naming format for pasting images", + "desc3": "Naming format for images pasted on nodes", + "filenameFormatDesc": "File name format description" + }, + "font": { + "title": "Font", + "desc": "Extended font list for mind maps", + "btn": "Manage", + "placeholder": "Search font. You can also press Enter to add input fonts directly", + "empty": "No font", + "noMatch": "No matching font", + "noFont": "No available font" }, "button": { "select": "Select" @@ -134,48 +166,21 @@ "other": { "title1": "Check for new versions", "desc1": "After activation, it will check if a new version is available when the plugin starts. If your network cannot access Github, it is recommended to disable this option" + }, + "imageHosting": { + "title1": "Open the picture bed", + "desc1": "After activation, all images will be uploaded to the image bed", + "tip1": "Please first improve the configuration information of the drawing bed", + "title2": "Picture bed URL", + "desc2": "Fill in the corresponding upload interface address based on the graphic tool you are using", + "title3": "Form field", + "desc3": "Name of the form field when uploading images", + "title4": "Response structure", + "desc4": "Response structure when uploading images. Please refer to the detailed description for more information:", + "desc5": "Image bed function description" } }, - "commands": { - "save": "Edit operation-Save", - "saveAndUpdateImage": "Edit operation-Save and update image", - "undo": "Edit operation-Undo", - "redo": "Edit operation-Redo", - "searchReplace": "Edit operation-Search and replace", - "insertChildNode": "Node operation-Insert child node", - "insertSiblingNode": "Node operation-Insert sibling node", - "insertParentNode": "Node operation-Insert parent node", - "moveUpNode": "Node operation-Move up node", - "moveDownNode": "Node operation-Move down node", - "insertSummary": "Node operation-Insert summary", - "toggleExpandNode": "Node operation-Expand/collapse node", - "deleteNode": "Node operation-Delete node", - "deleteNodeOnly": "Node operation-Delete current node only", - "copyNode": "Node operation-Copy node", - "cutNode": "Node operation-Cut node", - "pasteNode": "Node operation-Paste node", - "selectAllNode": "Node operation-Select all", - "organizeLayout": "Node operation-Organize layout with one click", - "toggleBoldNode": "Node operation-Toggle bold", - "toggleItalicNode": "Node operation-Toggle italic", - "toggleUnderlineNode": "Node operation-Toggle underline", - "toggleStrikethroughNode": "Node operation-Toggle strikethrough", - "increaseFontSizeNode": "Node operation-Increase font size", - "decreaseFontSizeNode": "Node operation-Decrease font size", - "zoomInCanvas": "Canvas operation-Zoom in", - "zoomOutCanvas": "Canvas operation-Zoom out", - "backToRootCanvas": "Canvas operation-Back to root node", - "activateLeftCanvas": "Canvas operation-Move focus left", - "activateTopCanvas": "Canvas operation-Move focus up", - "activateRightCanvas": "Canvas operation-Move focus right", - "activateBottomCanvas": "Canvas operation-Move focus down", - "zoomFitCanvas": "Canvas operation-Fit to canvas", - "enterDemonstrate": "Auxiliary operation-Enter demonstration mode", - "openImageEdit": "Interface operation-Open image edit dialog", - "openHyperlinkEdit": "Interface operation-Open hyperlink edit dialog", - "openRemarkEdit": "Interface operation-Open remark edit dialog", - "openTagEdit": "Interface operation-Open tag edit dialog", - "openImport": "Interface operation-Open import dialog", - "openExport": "Interface operation-Open export dialog" + "html": { + "filenameFormatDesc": "

In addition to fixed names, variables can also be used, enclosed in {}. Available variables are as follows:

1.{notename}: The current file name without extension;

2.{date}: Current date in YYYY-MM-DD format;

3.{time}: Current time in HH:mm:ss format;

4.{datatime}: Current date and time in YYYY-MM-DD HH:mm:ss format;

5.{date:Format}: Specify date/time format, e.g.: MM-DD HH:mm, reference: Format specification;

6.{random}: Random string with 6-character length;

" } } diff --git a/plugin/locales/vi.json b/plugin/locales/vi.json index 8827590..2f2ce77 100644 --- a/plugin/locales/vi.json +++ b/plugin/locales/vi.json @@ -23,6 +23,10 @@ "changeToMindMapFile": "Chuyển đổi sang tài liệu bản đồ tư duy" }, "tip": { + "tip": "Mẹo", + "confirm": "Xác nhận", + "cancel": "Hủy bỏ", + "close": "Đóng cửa", "fileExist": "Tệp đã tồn tại", "createMindMapFail": "Tạo sơ đồ tư duy thất bại", "fileIsNotMd": "Tệp hiện tại không phải tệp markdown", @@ -40,7 +44,14 @@ "pluginNoNewVersion": "Hiện tại là phiên bản mới nhất", "pluginVersionCheckError": "Kiểm tra thất bại", "changeSuccess": "Hoàn thành chuyển đổi", - "mdToMindMapFail": "Chuyển đổi thất bại, không có dữ liệu được phân tích để có thể được chuyển đổi thành Bản đồ tư duy" + "mdToMindMapFail": "Chuyển đổi thất bại, không có dữ liệu được phân tích để có thể được chuyển đổi thành Bản đồ tư duy", + "imgCreateFail": "Lỗi tạo tập tin ảnh", + "mdModifyTip": "Không thay đổi bất kỳ thông tin nào khác ngoài YAML", + "fileNameEmpty": "Tên tập tin không được để trống", + "fileNameIllegal": "Tên tập tin chứa ký tự không hợp lệ", + "fileRenameFail": "Lỗi đổi tên tập tin", + "mindMapToMdTip": "Sau khi chuyển đổi sang tài liệu Markdown, chỉ một số nội dung sẽ được giữ lại, chẳng hạn như văn bản nút, văn bản tóm tắt, ghi chú, v.v., những nội dung khác sẽ bị loại bỏ và không thể khôi phục, hãy sao lưu trước.", + "mdToMindMapTip": "Chỉ hỗ trợ chuyển đổi tiêu đề, danh sách và cú pháp khác thành bản đồ tư duy, các nội dung khác sẽ bị loại bỏ và không thể phục hồi, hãy sao lưu trước." }, "setting": { "title": { @@ -48,7 +59,8 @@ "title2": "Tệp", "title3": "Nén hình ảnh", "title4": "Hình ảnh", - "title5": "Khác" + "title5": "Khác", + "title6": "Hình ảnh hosting" }, "themeMode": { "title": "Chế độ chủ đề", @@ -89,7 +101,9 @@ "title8": "Hỗ trợ tìm kiếm OB", "desc8": "Tư duy bản đồ dữ liệu là mã hóa nén sau khi lưu trữ, vì vậy không thể tìm kiếm trong ob, nếu bạn muốn trong ob có thể tìm kiếm nội dung văn bản nút của bản đồ tư duy, bạn có thể mở tùy chọn này, sau khi mở sẽ lưu thêm tất cả các nút trong các tập tin nội dung văn bản để tìm kiếm, mang lại tác dụng phụ sẽ dẫn đến khối lượng tập tin lớn hơn, có thể ảnh hưởng đến tốc độ mở và lưu tập tin", "title9": "Lưu trữ vị trí canvas và dữ liệu thu phóng", - "desc9": "Vị trí khung và dữ liệu thu phóng được lưu trong tệp sau khi mở để bạn có thể khôi phục lại vị trí và trạng thái thu phóng của lần đóng cuối cùng khi mở tiếp theo. Nhược điểm là chỉ cần di chuyển và phóng to canvas sẽ làm thay đổi tập tin." + "desc9": "Vị trí khung và dữ liệu thu phóng được lưu trong tệp sau khi mở để bạn có thể khôi phục lại vị trí và trạng thái thu phóng của lần đóng cuối cùng khi mở tiếp theo. Nhược điểm là chỉ cần di chuyển và phóng to canvas sẽ làm thay đổi tập tin.", + "title10": "Mức tối đa của văn bản nút đến tiêu đề Markdown", + "desc10": "Văn bản nút nhỏ hơn hoặc bằng cấp này được chuyển thành tiêu đề Markdown và phần còn lại được chuyển thành danh sách không có thứ tự." }, "compress": { "title1": "Có nén ảnh không", @@ -109,7 +123,9 @@ }, "codeBlock": { "title": "Chiều cao ban đầu của khối mã nhúng", - "desc": "Chiều cao ban đầu khi nhúng bằng khối mã smm, đơn vị: px" + "desc": "Chiều cao ban đầu khi nhúng bằng khối mã smm, đơn vị: px", + "title2": "Nền nhúng khối mã có trong suốt hay không", + "desc2": "Nền có trong suốt khi nhúng khối mã smm hay không, nếu không nó sẽ theo màu nền của chủ đề bản đồ tư duy đã chọn" }, "linkInfo": { "issues": "Gửi bug hoặc gợi ý", @@ -120,13 +136,29 @@ "title1": "Nhúng xem thử Nhấp đúp vào cửa sổ mới để mở", "desc1": "![[]] Định dạng Nhấp đúp vào ô xem thử ảnh khi nhúng tài liệu md có cửa sổ mới Mở tập tin không", "title2": "Hình nền nhúng xem thử có trong suốt không", - "desc2": "Thiết lập hình nền nhúng xem thử có trong suốt không" + "desc2": "![[]] Định dạng Nền ảnh được nhúng trong ô xem thử có trong suốt không", + "title3": "Cho dù hình ảnh nhúng được lưu trữ dưới dạng tệp riêng biệt", + "desc3": "Hình ảnh được sử dụng mặc định để nhúng xem trước ở định dạng ![[]] được lưu trữ riêng biệt trong kho dưới dạng tệp svg để chỉ đường dẫn tệp được lưu trữ trong tệp Bản đồ Tư duy có thể làm giảm đáng kể khối lượng tệp và tăng tốc độ đọc và lưu tệp. Nếu tắt, dữ liệu hình ảnh sẽ được lưu trữ trong tệp Bản đồ Tư duy và khối lượng sẽ tăng lên đáng kể.", + "title4": "Nhúng thư mục lưu trữ tập tin ảnh", + "desc4": "Nhúng xem trước hình ảnh tập tin lưu trữ thư mục, liên quan đến thư mục gốc kho, không nên để trống và thư mục bắt đầu bằng . như một thư mục ẩn", + "title5": "Trang nhãn mới Mở liên kết nút", + "desc5": "Nhấp vào liên kết nút được chèn (không chứa liên kết mạng) để mở trên trang tab mới. Bạn cũng có thể mở tab mới bằng Ctrl+chuột trái sau khi đóng" }, "file": { - "title1": "Tiền tố tên tệp sơ đồ tư duy mới", - "desc1": "Định dạng đặt tên mặc định cho tên tệp sơ đồ tư duy mới là: Tiền tố + Dấu cách + Dấu thời gian ngày tháng", - "title2": "Định dạng dấu thời gian ngày tháng cho tên tệp sơ đồ tư duy mới", - "desc2": "Mặc định: YYYY-MM-DD HH.mm.ss, Ví dụ thực tế: 2025-01-01 23.59.59. Nếu không rõ ý nghĩa cụ thể của định dạng này và cách sửa đổi, vui lòng tham khảo: https://day.js.org/docs/en/parse/string-format" + "title1": "Định dạng tên tập tin cho bản đồ tư duy mới", + "desc1": "Dạng thức đặt tên cho tên tệp bản đồ tư duy mới. Hỗ trợ các biến khác ngoài notename", + "title3": "Định dạng có tên cho ảnh dán", + "desc3": "Định dạng có tên của ảnh được dán trên nút", + "filenameFormatDesc": "Mô tả định dạng tên tập tin" + }, + "font": { + "title": "Phông chữ", + "desc": "Phông chữ mặc định khi tạo bản đồ tư duy mới", + "btn": "Quản lý", + "placeholder": "Tìm kiếm phông chữ. Bạn cũng có thể nhấn Enter để thêm các phông chữ nhập trực tiếp", + "empty": "Không có phông chữ", + "noMatch": "Không tìm thấy phông chữ", + "noFont": "Không có phông chữ" }, "button": { "select": "Chọn" @@ -134,48 +166,21 @@ "other": { "title1": "Kiểm tra phiên bản mới", "desc1": "Khi plugin khởi động, bạn sẽ kiểm tra xem có phiên bản mới không và nếu mạng của bạn không truy cập được Github, bạn nên tắt tùy chọn này." + }, + "imageHosting": { + "title1": "Mở giường", + "desc1": "Sau khi mở, tất cả hình ảnh sẽ được tải lên giường.", + "tip1": "Vui lòng hoàn thiện thông tin cấu hình giường", + "title2": "Giường Url", + "desc2": "Điền địa chỉ giao diện tải lên tương ứng với công cụ giường chiếu mà bạn sử dụng", + "title3": "Trường mẫu", + "desc3": "Tên trường trong biểu mẫu khi tải lên hình ảnh", + "title4": "Cấu trúc phản hồi", + "desc4": "Cấu trúc phản hồi khi tải lên hình ảnh. Hãy tham khảo thêm tại:", + "desc5": "Hướng dẫn sử dụng giường" } }, - "commands": { - "save": "Thao tác chỉnh sửa - Lưu", - "saveAndUpdateImage": "Thao tác chỉnh sửa - Lưu và cập nhật hình ảnh", - "undo": "Thao tác chỉnh sửa - Quay lại", - "redo": "Thao tác chỉnh sửa - Tiến tới", - "searchReplace": "Thao tác chỉnh sửa - Tìm kiếm và thay thế", - "insertChildNode": "Thao tác nút - Chèn nút con", - "insertSiblingNode": "Thao tác nút - Chèn nút cùng cấp", - "insertParentNode": "Thao tác nút - Chèn nút cha", - "moveUpNode": "Thao tác nút - Di chuyển nút lên", - "moveDownNode": "Thao tác nút - Di chuyển nút xuống", - "insertSummary": "Thao tác nút - Chèn tóm tắt", - "toggleExpandNode": "Thao tác nút - Mở rộng/Thu gọn nút", - "deleteNode": "Thao tác nút - Xóa nút", - "deleteNodeOnly": "Thao tác nút - Chỉ xóa nút hiện tại", - "copyNode": "Thao tác nút - Sao chép nút", - "cutNode": "Thao tác nút - Cắt nút", - "pasteNode": "Thao tác nút - Dán nút", - "selectAllNode": "Thao tác nút - Chọn tất cả", - "organizeLayout": "Thao tác nút - Sắp xếp bố cục một lần", - "toggleBoldNode": "Thao tác nút - Chuyển đổi in đậm", - "toggleItalicNode": "Thao tác nút - Chuyển đổi in nghiêng", - "toggleUnderlineNode": "Thao tác nút - Chuyển đổi gạch chân", - "toggleStrikethroughNode": "Thao tác nút - Chuyển đổi gạch ngang", - "increaseFontSizeNode": "Thao tác nút - Tăng kích thước chữ", - "decreaseFontSizeNode": "Thao tác nút - Giảm kích thước chữ", - "zoomInCanvas": "Thao tác canvas - Phóng to", - "zoomOutCanvas": "Thao tác canvas - Thu nhỏ", - "backToRootCanvas": "Thao tác canvas - Quay về nút gốc", - "activateLeftCanvas": "Thao tác canvas - Di chuyển tiêu điểm sang trái", - "activateTopCanvas": "Thao tác canvas - Di chuyển tiêu điểm lên trên", - "activateRightCanvas": "Thao tác canvas - Di chuyển tiêu điểm sang phải", - "activateBottomCanvas": "Thao tác canvas - Di chuyển tiêu điểm xuống dưới", - "zoomFitCanvas": "Thao tác canvas - Vừa với canvas", - "enterDemonstrate": "Thao tác hỗ trợ - Vào chế độ trình diễn", - "openImageEdit": "Thao tác giao diện - Mở hộp thoại chỉnh sửa hình ảnh", - "openHyperlinkEdit": "Thao tác giao diện - Mở hộp thoại chỉnh sửa siêu liên kết", - "openRemarkEdit": "Thao tác giao diện - Mở hộp thoại chỉnh sửa ghi chú", - "openTagEdit": "Thao tác giao diện - Mở hộp thoại chỉnh sửa thẻ", - "openImport": "Thao tác giao diện - Mở hộp thoại nhập", - "openExport": "Thao tác giao diện - Mở hộp thoại xuất" + "html": { + "filenameFormatDesc": "

Ngoài các tên cố định, bạn cũng có thể sử dụng các biến, được đặt trong dấu ngoặc nhọn {}, các biến khả dụng như sau:

1.{notename}: Tên tệp hiện tại, không bao gồm phần mở rộng;

2.{date}: Ngày hiện tại, định dạng YYYY-MM-DD;

3.{time}: Thời gian hiện tại, định dạng HH:mm:ss;

4.{datatime}: Ngày giờ hiện tại, định dạng: YYYY-MM-DD HH:mm:ss;

5.{date:Format}: Chỉ định định dạng ngày giờ, ví dụ: MM-DD HH:mm, tham khảo thêm tại: hướng dẫn định dạng;

6.{random}: Chuỗi ngẫu nhiên, độ dài 6 ký tự;

" } } diff --git a/plugin/locales/zh.json b/plugin/locales/zh.json index 312a89a..65e4c90 100644 --- a/plugin/locales/zh.json +++ b/plugin/locales/zh.json @@ -23,6 +23,10 @@ "changeToMindMapFile": "转换为思维导图文档" }, "tip": { + "tip": "提示", + "confirm": "确认", + "cancel": "取消", + "close": "关闭", "fileExist": "文件已经存在", "createMindMapFail": "新建思维导图失败", "fileIsNotMd": "当前文件不是markdown文件", @@ -40,7 +44,14 @@ "pluginNoNewVersion": "当前已是最新版本", "pluginVersionCheckError": "检查失败", "changeSuccess": "转换完成", - "mdToMindMapFail": "转换失败,没有解析到可以转换为思维导图的数据" + "mdToMindMapFail": "转换失败,没有解析到可以转换为思维导图的数据", + "imgCreateFail": "图片文件创建失败", + "mdModifyTip": "请勿修改除YAML外的任何信息", + "fileNameEmpty": "文件名不能为空", + "fileNameIllegal": "文件名包含非法字符", + "fileRenameFail": "文件重命名失败", + "mindMapToMdTip": "转换为Markdown文档后,仅会保留部分内容,比如节点文本、概要文本、备注等,其他内容将丢弃且不可恢复,请先做好备份。", + "mdToMindMapTip": "仅支持将标题、列表等语法转换为思维导图,其他内容将丢弃且不可恢复,请先做好备份。" }, "setting": { "title": { @@ -48,12 +59,13 @@ "title2": "文件", "title3": "图片压缩", "title4": "嵌入", - "title5": "其他" + "title5": "其他", + "title6": "图床" }, "themeMode": { "title": "主题模式", "desc": "深色、浅色模式", - "option1": "跟随Obsidian", + "option1": "跟随obsidian", "option2": "浅色模式", "option3": "深色模式" }, @@ -89,10 +101,12 @@ "title8": "支持ob搜索", "desc8": "思维导图数据是编码压缩后存储的,所以无法在ob中搜索,如果你想在ob中能搜索到思维导图的节点文本内容,可以开启该选项,开启后会在文件中额外保存所有节点的文本内容用于搜索,带来的副作用是会导致文件体积变大,可能会影响文件打开和保存的速度", "title9": "存储画布位置和缩放数据", - "desc9": "开启后会在文件中保存画布位置和缩放数据,这样下次打开时能恢复到上次关闭时的位置和缩放状态。缺点是只要移动和缩放过画布就会造成文件改动" + "desc9": "开启后会在文件中保存画布位置和缩放数据,这样下次打开时能恢复到上次关闭时的位置和缩放状态。缺点是只要移动和缩放过画布就会造成文件改动", + "title10": "节点文字转Markdown标题的最大层级", + "desc10": "小于等于该层级的节点文字会转为Markdown标题,其余的转为无序列表" }, "compress": { - "title1": "是否压缩图片", + "title1": "压缩图片", "desc1": "是否压缩上传的节点图片(从本地选择的图片)", "title2": "最大压缩宽度", "desc2": "图片压缩后的最大宽度", @@ -109,7 +123,9 @@ }, "codeBlock": { "title": "代码块嵌入初始高度", - "desc": "smm代码块方式嵌入时初始高度,单位:px" + "desc": "smm代码块方式嵌入时初始高度,单位:px", + "title2": "代码块嵌入背景是否透明", + "desc2": "smm代码块嵌入时背景是否透明,否则会跟随所选的思维导图主题背景颜色" }, "linkInfo": { "issues": "提交bug或建议", @@ -117,16 +133,32 @@ "community": "社区" }, "embed": { - "title1": "嵌入预览双击是否新窗口打开", - "desc1": "![[]]格式嵌入md文档时双击预览图像是否新窗口打开文件", + "title1": "嵌入预览双击是否新标签页打开", + "desc1": "![[]]格式嵌入md文档时双击预览图像是否新标签页打开文件", "title2": "嵌入预览的图像背景是否透明", - "desc2": "![[]]格式嵌入预览的图像背景是否透明" + "desc2": "![[]]格式嵌入预览的图像背景是否透明", + "title3": "嵌入的图片是否以单独文件的形式存储", + "desc3": "默认用于![[]]格式嵌入预览的图片会以svg格式的文件单独存储到仓库里,这样思维导图文件中只存储文件路径,可以显著减小文件体积,加快文件的读取和保存速度。如果关闭,则会把图片数据存储到思维导图文件中,体积会显著增大", + "title4": "嵌入图片文件存储目录", + "desc4": "嵌入预览的图片文件存储的文件夹,相对于仓库根目录,建议不要为空,且目录以.开头作为隐藏文件夹", + "title5": "新标签页打开节点链接", + "desc5": "点击插入的节点链接(不包含网络链接)是否在新标签页打开。关闭后也可以通过Ctrl+鼠标左键在新标签页打开" }, "file": { - "title1": "新建思维导图的文件名前缀", - "desc1": "新建思维导图文件名默认的命名格式为:前缀 + 空格 + 日期时间戳", - "title2": "新建思维导图的文件名日期时间戳格式", - "desc2": "默认为:YYYY-MM-DD HH.mm.ss,实际示例:2025-01-01 23.59.59,如不清楚该格式的具体含义及如何修改,请参考:https://day.js.org/docs/en/parse/string-format" + "title1": "新建思维导图的文件名格式", + "desc1": "新建思维导图文件名的命名格式。支持除notename外的其他变量", + "title3": "粘贴图片的命名格式", + "desc3": "在节点上粘贴的图片的命名格式", + "filenameFormatDesc": "文件名格式说明" + }, + "font": { + "title": "字体", + "desc": "扩展思维导图的字体列表", + "btn": "管理", + "placeholder": "搜索字体。也可按回车键直接添加输入的字体", + "empty": "暂无已添加字体", + "noMatch": "无匹配字体", + "noFont": "没有可用字体" }, "button": { "select": "选择" @@ -134,48 +166,21 @@ "other": { "title1": "检查新版本", "desc1": "开启后会在插件启动时检查是否有新版本可用,如果你的网络访问不到Github,则建议关闭该选项" + }, + "imageHosting": { + "title1": "开启图床", + "desc1": "开启后,所有图片都将上传到图床", + "tip1": "请先完善图床配置信息", + "title2": "图床url", + "desc2": "根据你使用的图床工具填写对应的上传接口地址", + "title3": "表单字段", + "desc3": "上传图片时的表单字段名称", + "title4": "接口响应结构", + "desc4": "上传图片时的接口响应结构。详细说明请参考:", + "desc5": "图床功能说明" } }, - "commands": { - "save": "编辑操作-保存", - "saveAndUpdateImage": "编辑操作-保存并更新图像", - "undo": "编辑操作-回退", - "redo": "编辑操作-前进", - "searchReplace": "编辑操作-搜索和替换", - "insertChildNode": "节点操作-插入下级节点", - "insertSiblingNode": "节点操作-插入同级节点", - "insertParentNode": "节点操作-插入父节点", - "moveUpNode": "节点操作-上移节点", - "moveDownNode": "节点操作-下移节点", - "insertSummary": "节点操作-插入概要", - "toggleExpandNode": "节点操作-展开/收起节点", - "deleteNode": "节点操作-删除节点", - "deleteNodeOnly": "节点操作-仅删除当前节点", - "copyNode": "节点操作-复制节点", - "cutNode": "节点操作-剪切节点", - "pasteNode": "节点操作-粘贴节点", - "selectAllNode": "节点操作-全选", - "organizeLayout": "节点操作-一键整理布局", - "toggleBoldNode": "节点操作-切换粗体", - "toggleItalicNode": "节点操作-切换斜体", - "toggleUnderlineNode": "节点操作-切换下划线", - "toggleStrikethroughNode": "节点操作-切换删除线", - "increaseFontSizeNode": "节点操作-增大字号", - "decreaseFontSizeNode": "节点操作-减小字号", - "zoomInCanvas": "画布操作-放大", - "zoomOutCanvas": "画布操作-缩小", - "backToRootCanvas": "画布操作-回到根节点", - "activateLeftCanvas": "画布操作-向左移动焦点", - "activateTopCanvas": "画布操作-向上移动焦点", - "activateRightCanvas": "画布操作-向右移动焦点", - "activateBottomCanvas": "画布操作-向下移动焦点", - "zoomFitCanvas": "画布操作-适应画布", - "enterDemonstrate": "辅助操作-进入演示模式", - "openImageEdit": "界面操作-打开图片编辑弹窗", - "openHyperlinkEdit": "界面操作-打开超链接编辑弹窗", - "openRemarkEdit": "界面操作-打开备注编辑弹窗", - "openTagEdit": "界面操作-打开标签编辑弹窗", - "openImport": "界面操作-打开导入弹窗", - "openExport": "界面操作-打开导出弹窗" + "html": { + "filenameFormatDesc": "

除了固定名称外,也可以使用变量,用 {} 括起来,可用变量如下:

1.{notename}:当前文件的文件名,不包含扩展名;

2.{date}:当前日期,格式为 YYYY-MM-DD;

3.{time}:当前时间,格式为 HH:mm:ss;

4.{datatime}:当前日期时间,格式为:YYYY-MM-DD HH:mm:ss;

5.{date:Format}:指定日期时间格式,比如:MM-DD HH:mm,可参考:格式说明

6.{random}:随机字符串,长度为 6 位;

" } } diff --git a/plugin/locales/zhtw.json b/plugin/locales/zhtw.json index e2ada4f..b9cac2c 100644 --- a/plugin/locales/zhtw.json +++ b/plugin/locales/zhtw.json @@ -23,6 +23,10 @@ "changeToMindMapFile": "轉換為心智圖檔案" }, "tip": { + "tip": "提示", + "confirm": "確認", + "cancel": "取消", + "close": "關閉", "fileExist": "檔案已經存在", "createMindMapFail": "新建思維導圖失敗", "fileIsNotMd": "當前檔案不是 markdown 檔案", @@ -40,7 +44,14 @@ "pluginNoNewVersion": "當前已是最新版本", "pluginVersionCheckError": "檢查失敗", "changeSuccess": "轉換完成", - "mdToMindMapFail": "轉換失敗,沒有解析到可以轉換為心智圖的數據" + "mdToMindMapFail": "轉換失敗,沒有解析到可以轉換為心智圖的數據", + "imgCreateFail": "圖片檔案創建失敗", + "mdModifyTip": "請勿修改除YAML外的任何資訊", + "fileNameEmpty": "檔名不能為空", + "fileNameIllegal": "檔名包含非法字元", + "fileRenameFail": "檔案重命名失敗", + "mindMapToMdTip": "轉換為Markdown檔案後,僅會保留部分內容,比如節點文字、概要文字、備註等,其他內容將丟棄且不可恢復,請先做好備份。", + "mdToMindMapTip": "僅支持將標題、清單等語法轉換為心智圖,其他內容將丟棄且不可恢復,請先做好備份。" }, "setting": { "title": { @@ -48,7 +59,8 @@ "title2": "文件", "title3": "圖片壓縮", "title4": "嵌入", - "title5": "其他" + "title5": "其他", + "title6": "圖床主機" }, "themeMode": { "title": "主題模式", @@ -89,7 +101,9 @@ "title8": "支持ob蒐索", "desc8": "心智圖數據是編碼壓縮後存儲的,所以無法在ob中蒐索,如果你想在ob中能蒐索到心智圖的節點文字內容,可以開啟該選項,開啟後會在檔案中額外保存所有節點的文字內容用於蒐索,帶來的副作用是會導致檔案體積變大,可能會影響檔案打開和保存的速度", "title9": "存儲畫布位置和縮放數據", - "desc9": "開啟後會在檔案中保存畫布位置和縮放數據,這樣下次打開時能恢復到上次關閉時的位置和縮放狀態。缺點是只要移動和縮放過畫布就會造成檔案改動" + "desc9": "開啟後會在檔案中保存畫布位置和縮放數據,這樣下次打開時能恢復到上次關閉時的位置和縮放狀態。缺點是只要移動和縮放過畫布就會造成檔案改動", + "title10": "節點文字轉Markdown標題的最大層級", + "desc10": "小於等於該層級的節點文字會轉為Markdown標題,其餘的轉為無序清單" }, "compress": { "title1": "壓縮圖片", @@ -109,7 +123,9 @@ }, "codeBlock": { "title": "程式碼區塊嵌入初始高度", - "desc": "smm 程式碼區塊方式嵌入時初始高度,單位:px" + "desc": "smm 程式碼區塊方式嵌入時初始高度,單位:px", + "title2": "程式碼塊嵌入背景是否透明", + "desc2": "smm程式碼塊嵌入時背景是否透明,否則會跟隨所選的心智圖主題背景顏色" }, "linkInfo": { "issues": "提交bug或建議", @@ -117,16 +133,32 @@ "community": "社區" }, "embed": { - "title1": "嵌入預覽按兩下是否新窗口打開", - "desc1": "![[]]格式嵌入md檔案時按兩下預覽影像是否新窗口打開文件", + "title1": "嵌入預覽按兩下是否新標籤頁打開", + "desc1": "![[]]格式嵌入md檔案時按兩下預覽影像是否新標籤頁打開文件", "title2": "嵌入預覽的圖像背景是否透明", - "desc2": "設定![[]]格式嵌入預覽的圖像背景是否透明" + "desc2": "設定![[]]格式嵌入預覽的圖像背景是否透明", + "title3": "嵌入的圖片是否以單獨檔案的形式存儲", + "desc3": "默認用於![[]]格式嵌入預覽的圖片會以svg格式的檔案單獨存儲到倉庫裏,這樣心智圖檔案中只存儲檔案路徑,可以顯著减小檔案體積,加快檔案的讀取和保存速度。 如果關閉,則會把圖片資料存儲到心智圖檔案中,體積會顯著增大", + "title4": "嵌入圖片檔存儲目錄", + "desc4": "嵌入預覽的圖片檔存儲的資料夾,相對於倉庫根目錄,建議不要為空,且目錄以.開頭作為隱藏資料夾", + "title5": "新標籤頁打開節點連結", + "desc5": "點擊插入的節點連結(不包含網絡連結)是否在新標籤頁打開。 關閉後也可以通過Ctrl+滑鼠左鍵在新標籤頁打開" }, "file": { - "title1": "新建思維導圖的檔案名稱前綴", - "desc1": "新建思維導圖檔案名稱預設的命名格式為:前綴 + 空格 + 日期時間戳", - "title2": "新建思維導圖的檔案名稱日期時間戳格式", - "desc2": "預設為:YYYY-MM-DD HH.mm.ss,實際範例:2025-01-01 23.59.59,如不清楚該格式的具體含義及如何修改,請參考:https://day.js.org/docs/en/parse/string-format" + "title1": "新建心智圖的檔名格式", + "desc1": "新建心智圖檔名的命名格式。支持除notename外的其他變數", + "title3": "粘貼圖片的命名格式", + "desc3": "在節點上粘貼的圖片的命名格式", + "filenameFormatDesc": "檔名格式說明" + }, + "font": { + "title": "字體", + "desc": "擴展心智圖的字體清單", + "btn": "管理", + "placeholder": "蒐索字體。 也可按回車鍵直接添加輸入的字體", + "empty": "暫無已添加字體", + "noMatch": "無匹配字體", + "noFont": "沒有可用字體" }, "button": { "select": "選擇" @@ -134,48 +166,21 @@ "other": { "title1": "檢查新版本", "desc1": "開啟後會在挿件啟動時檢查是否有新版本可用,如果你的網絡訪問不到Github,則建議關閉該選項" + }, + "imageHosting": { + "title1": "開啟圖床", + "desc1": "開啟後,所有圖片都將上傳到圖床", + "tip1": "請先完善圖床配寘資訊", + "title2": "圖床url", + "desc2": "根據你使用的圖床工具填寫對應的上傳介面地址", + "title3": "表單欄位", + "desc3": "上傳圖片時的表單欄位名稱", + "title4": "接口響應結構", + "desc4": "上傳圖片時的接口響應結構。詳細說明請參考:", + "desc5": "圖床功能說明" } }, - "commands": { - "save": "編輯操作-儲存", - "saveAndUpdateImage": "編輯操作-儲存並更新圖像", - "undo": "編輯操作-復原", - "redo": "編輯操作-重做", - "searchReplace": "編輯操作-搜尋和取代", - "insertChildNode": "節點操作-插入下級節點", - "insertSiblingNode": "節點操作-插入同級節點", - "insertParentNode": "節點操作-插入父節點", - "moveUpNode": "節點操作-上移節點", - "moveDownNode": "節點操作-下移節點", - "insertSummary": "節點操作-插入概要", - "toggleExpandNode": "節點操作-展開/收起節點", - "deleteNode": "節點操作-刪除節點", - "deleteNodeOnly": "節點操作-僅刪除目前節點", - "copyNode": "節點操作-複製節點", - "cutNode": "節點操作-剪下節點", - "pasteNode": "節點操作-貼上節點", - "selectAllNode": "節點操作-全選", - "organizeLayout": "節點操作-一鍵整理版面配置", - "toggleBoldNode": "節點操作-切換粗體", - "toggleItalicNode": "節點操作-切換斜體", - "toggleUnderlineNode": "節點操作-切換底線", - "toggleStrikethroughNode": "節點操作-切換刪除線", - "increaseFontSizeNode": "節點操作-增大字型大小", - "decreaseFontSizeNode": "節點操作-減小字型大小", - "zoomInCanvas": "畫布操作-放大", - "zoomOutCanvas": "畫布操作-縮小", - "backToRootCanvas": "畫布操作-回到根節點", - "activateLeftCanvas": "畫布操作-向左移動焦點", - "activateTopCanvas": "畫布操作-向上移動焦點", - "activateRightCanvas": "畫布操作-向右移動焦點", - "activateBottomCanvas": "畫布操作-向下移動焦點", - "zoomFitCanvas": "畫布操作-適應畫布", - "enterDemonstrate": "輔助操作-進入演示模式", - "openImageEdit": "介面操作-開啟圖片編輯彈窗", - "openHyperlinkEdit": "介面操作-開啟超連結編輯彈窗", - "openRemarkEdit": "介面操作-開啟備註編輯彈窗", - "openTagEdit": "介面操作-開啟標籤編輯彈窗", - "openImport": "介面操作-開啟匯入彈窗", - "openExport": "介面操作-開啟匯出彈窗" + "html": { + "filenameFormatDesc": "

除了固定名稱外,也可以使用變數,用 {} 括起來,可用變數如下:

1.{notename}:目前檔案的檔名,不包含副檔名;

2.{date}:目前日期,格式為 YYYY-MM-DD;

3.{time}:目前時間,格式為 HH:mm:ss;

4.{datatime}:目前日期時間,格式為:YYYY-MM-DD HH:mm:ss;

5.{date:Format}:指定日期時間格式,例如:MM-DD HH:mm,可參考:格式說明

6.{random}:隨機字串,長度為 6 位;

" } } diff --git a/plugin/main.js b/plugin/main.js index d564cbf..1202dea 100644 --- a/plugin/main.js +++ b/plugin/main.js @@ -22,7 +22,7 @@ import { createDefaultMindMapData } from './ob/metadataAndMarkdown.js' import { around, dedupe } from 'monkey-around' -import { getUidFromSource } from './ob/utils.js' +import { getUidFromSource, formatFileName } from './ob/utils.js' import MarkdownPostProcessor from './ob/MarkdownPostProcessor.js' import SmmSettingTab from './ob/SmmSettingTab.js' import { langList } from './src/config/zh' @@ -37,12 +37,10 @@ import Menus from './ob/Menus.js' export default class SimpleMindMapPlugin extends Plugin { async onload() { - // 添加设置 await this._addSetting() - // 初始化多语言 i18n.init({ - lng: getLanguage() || 'en', // 自动检测用户语言 + lng: getLanguage() || 'en', fallbackLng: 'en', resources: { en: { translation: enTranslations }, @@ -54,66 +52,53 @@ export default class SimpleMindMapPlugin extends Plugin { addIcon('smm-icon', SIDE_BAR_ICON) - // 注册自定义视图 this.registerView(SMM_VIEW_TYPE, leaf => new SmmEditView(leaf, this)) - // 添加 Ribbon 图标 this._createSmmFile = this._createSmmFile.bind(this) this.addRibbonIcon( 'smm-icon', - this._t('action.createMindMap'), // 新建思维导图 + this._t('action.createMindMap'), this._createSmmFile ) - // 添加命令 this.commands = new Commands(this) - // 添加右键菜单 this.menus = new Menus(this) - // 打补丁,拦截默认的打开方法 this._registerMonkeyPatches() - // 切换到思维导图视图 this._switchToSmmAfterLoad() - // 创建状态栏子元素 this._initStatusBar() - // 处理嵌入的思维导图 this.markdownPostProcessor = new MarkdownPostProcessor(this) this.markdownPostProcessor.register() - // 记录打开文件的子路径,用于定位到指定节点 this.fileToSubpathMap = {} + this.noSaveOnClose = false } - // 创建思维导图文件 async _createSmmFile(folderPath = '', callback) { try { - if (typeof folderPath !== 'string') { + if (typeof folderPath !== 'string' || folderPath === '/') { folderPath = '' } - let { fileNamePrefix, fileNameDateFormat } = this.settings - fileNamePrefix = fileNamePrefix || 'MindMap' + const { fileNameFormat } = this.settings folderPath = this._getCreateFolderPath(folderPath) await this._ensureDirectoryExists(folderPath) const { vault } = this.app const filePath = `${ folderPath ? folderPath + '/' : '' - }${fileNamePrefix} ${moment().format(fileNameDateFormat)}.smm.md` + }${formatFileName(fileNameFormat, { ignores: ['notename'] })}.smm.md` const fileContent = createDefaultText( filePath, this._getCreateDefaultMindMapOptions() ) try { - // 检查文件是否已存在 const existingFile = vault.getFileByPath(filePath) if (existingFile) { - // 文件已经存在 new Notice(this._t('tip.fileExist')) } else { - // 创建新文件 await vault.create(filePath, fileContent) if (callback && typeof callback === 'function') { callback(filePath) @@ -122,18 +107,13 @@ export default class SimpleMindMapPlugin extends Plugin { } } } catch (error) { - // 新建思维导图失败 - console.error(error) new Notice(this._t('tip.createMindMapFail')) } } catch (error) { - console.error(error) - // 新建思维导图失败 new Notice(this._t('tip.createMindMapFail')) } } - // 获取创建文件夹路径 _getCreateFolderPath(folderPath) { if (folderPath) return folderPath const { filePathType, filePath } = this.settings @@ -149,7 +129,6 @@ export default class SimpleMindMapPlugin extends Plugin { } } - // 处理文件名重复问题 async _getAvailableFilaName(filePath, extCount = 1) { let counter = 1 while (await this.app.vault.adapter.exists(filePath)) { @@ -165,13 +144,11 @@ export default class SimpleMindMapPlugin extends Plugin { return filePath } - // 添加设置 async _addSetting() { await this._loadSettings() this.addSettingTab(new SmmSettingTab(this.app, this)) } - // 加载设置 async _loadSettings() { const data = await this.loadData() this.settings = Object.assign({}, DEFAULT_SETTINGS, data || {}) @@ -182,14 +159,11 @@ export default class SimpleMindMapPlugin extends Plugin { this.settings.lang = target ? target.value : 'en' } - // 保存设置 async _saveSettings() { await this.saveData(this.settings) } - // 打补丁,拦截默认的打开方法 _registerMonkeyPatches() { - // 防止其他插件或 Obsidian 核心代码通过 getActiveViewOfType 获取到 SmmEditView 时产生冲突(例如误判为 Markdown 视图) const key = 'https://github.com/wanglin2/mind-map' this.register( around(Workspace.prototype, { @@ -206,14 +180,6 @@ export default class SimpleMindMapPlugin extends Plugin { } }) ) - // 背景:Obsidian 的嵌套工作区(如拆分窗口或某些插件创建的容器)可能导致 WorkspaceLeaf 的根节点获取异常。原始 getRoot() 可能返回非最顶层的容器 - /* - 修复逻辑:1.先调用原始 getRoot() 获取当前层级的根节点 top - 2.检查 top.getRoot 方法是否与当前实例的 getRoot 相同: - 2.1:如果相同,说明 top 已是最顶层根节点,直接返回 - 2.2:如果不同,说明 top 仍是某个子容器,需递归调用 top.getRoot() 继续向上查找 - */ - // 如果该插件已存在,则跳过补丁(因为 hover-editor 已实现相同功能),避免冲突 if (!this.app.plugins?.plugins?.['obsidian-hover-editor']) { this.register( around(WorkspaceLeaf.prototype, { @@ -226,7 +192,6 @@ export default class SimpleMindMapPlugin extends Plugin { }) ) } - // 通过修改 Obsidian 核心的 WorkspaceLeaf.setViewState 方法,强制将特定文件定向到自定义视图 const self = this this.register( around(WorkspaceLeaf.prototype, { @@ -237,10 +202,10 @@ export default class SimpleMindMapPlugin extends Plugin { }, setViewState(next) { return function(state, ...rest) { - // 手动将smm视图切换为md视图不用拦截、md的预览和源码视图也不拦截 if ( - state.state?.isSwitchToMarkdownViewFromSmmView || - ['preview', 'source'].includes(state.state?.mode) + (state.state?.isSwitchToMarkdownViewFromSmmView || + ['preview', 'source'].includes(state.state?.mode)) && + !state.state?.isPreviewToMindMapViewFromMdView ) { return next.apply(this, [state, ...rest]) } @@ -261,7 +226,6 @@ export default class SimpleMindMapPlugin extends Plugin { ) { const uid = getUidFromSource(rest[0]) if (uid) { - // 从当前已经打开的视图中查找是否已存在 const existLeaf = this.app.workspace .getLeavesOfType(SMM_VIEW_TYPE) .find(leaf => { @@ -300,11 +264,9 @@ export default class SimpleMindMapPlugin extends Plugin { } }) ) - // 在md视图下的smm文件右上角菜单增加切换为思维导图菜单 this.menus.addMarkdownFileMenus() } - // 切换到思维导图视图 _switchToSmmAfterLoad() { this.app.workspace.onLayoutReady(async () => { let leaf @@ -321,7 +283,6 @@ export default class SimpleMindMapPlugin extends Plugin { }) } - // 设置思维导图视图状态 async _setSmmView(leaf) { await leaf.setViewState({ type: SMM_VIEW_TYPE, @@ -330,18 +291,15 @@ export default class SimpleMindMapPlugin extends Plugin { }) } - // 获取当前激活的思维导图视图 _getActiveSmmView() { return this.app.workspace.getActiveViewOfType(SmmEditView, IGNORE_CHECK_SMM) } - // 判断文件是否为思维导图 _isSmmFile(file) { if (!file) { return false } const isString = typeof file === 'string' - // 统一获取文件路径 const filePath = isString ? file : file.path if (filePath.endsWith('.smm.md')) { return true @@ -364,19 +322,15 @@ export default class SimpleMindMapPlugin extends Plugin { return false } - // 创建状态栏子元素 _initStatusBar() { - // 创建状态栏主元素 this.statusBarItem = this.addStatusBarItem() this.statusBarItem.empty() - this.statusBarItem.style.display = 'none' // 默认隐藏 + this.statusBarItem.style.display = 'none' - // 创建专门用于显示 smm 文件状态的子元素 this.smmFileStatus = this.statusBarItem.createEl('div', { cls: 'smm-file-status' }) - // 监听文件打开和视图变化 this.registerEvent( this.app.workspace.on('file-open', this._updateStatusBar.bind(this)) ) @@ -388,51 +342,38 @@ export default class SimpleMindMapPlugin extends Plugin { ) ) - // 初始更新 this._updateStatusBar() } - // 更新状态栏显示 _updateStatusBar() { const activeFile = this.app.workspace.getActiveFile() - // 检查是否是 smm 文件 const isSmmFile = activeFile && this._isSmmFile(activeFile) - // 获取状态栏容器 const statusBar = this.app.statusBar.containerEl - // 更新状态栏可见性 if (isSmmFile) { this.statusBarItem.style.display = 'block' - // 添加隐藏默认状态栏的类 statusBar.classList.add('smm-file-status-active') } else { this.statusBarItem.style.display = 'none' - // 移除隐藏类 statusBar.classList.remove('smm-file-status-active') } } - // 确保目录存在 async _ensureDirectoryExists(dirPath) { if (!dirPath) return const { vault } = this.app - // 检查目录是否存在 - // getFolderByPath无法检查到隐藏文件夹 const exist = await vault.exists(dirPath) if (!exist) { - // 递归创建目录 await vault.createFolder(dirPath) } } - // 多语言 _t(val) { return i18n.t(val) } - // 获取生成默认思维导图数据的配置 _getCreateDefaultMindMapOptions() { const { defaultTheme, defaultThemeDark, defaultLayout } = this.settings return { @@ -444,7 +385,6 @@ export default class SimpleMindMapPlugin extends Plugin { } } - // 根据参数生成默认思维导图数据 _createDefaultMindMapData() { return createDefaultMindMapData( this._getCreateDefaultMindMapOptions(), @@ -452,40 +392,31 @@ export default class SimpleMindMapPlugin extends Plugin { ) } - // 获取激活文件的目录 _getActiveFileDirectory() { - // 获取当前激活文件 const activeFile = this.app.workspace.getActiveFile() if (!activeFile) { return null } - // 检查是否为文件(排除文件夹) if (activeFile instanceof TFolder) { return null } - // 获取父目录路径 const parent = activeFile.parent if (!parent) { return null } - // 返回目录路径(Vault 相对路径) return parent.path.replace(/\/$/, '') } - // 获取ob是否是暗黑模式 _getObIsDark() { return document.body.classList.contains('theme-dark') } - // md 转思维导图数据 async _mdToMindmapData(md) { - // 过滤掉开头的 YAML front matter const frontMatterRegex = /^---\n[\s\S]*?\n---\n/ const cleanedMd = md.replace(frontMatterRegex, '') if (!cleanedMd.trim()) { return null } - // 解析 Markdown 数据 const data = await markdown.transformMarkdownTo(cleanedMd, false) if (!data) { return null @@ -501,11 +432,9 @@ export default class SimpleMindMapPlugin extends Plugin { } } - // 卸载时清理 onunload() { this.app.workspace.detachLeavesOfType(SMM_VIEW_TYPE) this.markdownPostProcessor.destroy() - // 清理状态栏 this.statusBarItem?.remove() this.commands.clear() } diff --git a/plugin/ob/Commands.js b/plugin/ob/Commands.js index 8016600..a32d9ac 100644 --- a/plugin/ob/Commands.js +++ b/plugin/ob/Commands.js @@ -20,7 +20,6 @@ export default class Commands { } _addCreatesCommand() { - // 新建思维导图 this.addCommand({ id: 'create-smm-mindmap', name: this._t('action.createMindMap'), @@ -28,7 +27,6 @@ export default class Commands { this.plugin._createSmmFile() } }) - // 新建思维导图并插入当前文档 this.addCommand({ id: 'create-smm-mindmap-insert-markdown', name: this._t('action.createMindMapInsertToMd'), @@ -61,437 +59,39 @@ export default class Commands { }) } - _commonCheckCallback(checking, run) { - const view = this.plugin._getActiveSmmView() - if (view) { - if (!checking) { - run(view) - } - return true - } - return false - } - _addActionsCommand() { - this._addMindMapEditActionCommands() - this._addMinMapNodeActionCommands() - this._addCanvasActionCommands() - this._addHelpActionCommands() - this._addUiActionCommands() - } - - _addMindMapEditActionCommands() { - // 编辑操作-保存 - this.addCommand({ - id: 'save-smm-mindmap', - name: this._t('commands.save'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.forceSave() - }) - } - }) - // 编辑操作-保存并更新图像 - this.addCommand({ - id: 'save-smm-mindmap-and-update-image', - name: this._t('commands.saveAndUpdateImage'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.forceSaveAndUpdateImage() - }) - } - }) - // 编辑操作-回退 - this.addCommand({ - id: 'undo-smm-mindmap-node', - name: this._t('commands.undo'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'BACK') - }) - } - }) - // 编辑操作-前进 - this.addCommand({ - id: 'redo-smm-mindmap-node', - name: this._t('commands.redo'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'FORWARD') - }) - } - }) - // 编辑操作-搜索和替换 - this.addCommand({ - id: 'show-smm-mindmap-search', - name: this._t('commands.searchReplace'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('show_search') - }) - } - }) - } - - _addMinMapNodeActionCommands() { - // 节点操作-插入下级节点 - this.addCommand({ - id: 'insert-smm-mindmap-child-node', - name: this._t('commands.insertChildNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'INSERT_CHILD_NODE') - }) - } - }) - // 节点操作-插入同级节点 - this.addCommand({ - id: 'insert-smm-mindmap-sibling-node', - name: this._t('commands.insertSiblingNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'INSERT_NODE') - }) - } - }) - // 节点操作-插入父节点 - this.addCommand({ - id: 'insert-smm-mindmap-parent-node', - name: this._t('commands.insertParentNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'INSERT_PARENT_NODE') - }) - } - }) - // 节点操作-上移节点 - this.addCommand({ - id: 'move-smm-mindmap-node-up', - name: this._t('commands.moveUpNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'UP_NODE') - }) - } - }) - // 节点操作-下移节点 - this.addCommand({ - id: 'move-smm-mindmap-node-down', - name: this._t('commands.moveDownNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'DOWN_NODE') - }) - } - }) - // 节点操作-插入概要 - this.addCommand({ - id: 'insert-smm-mindmap-summary', - name: this._t('commands.insertSummary'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'ADD_GENERALIZATION') - }) - } - }) - // 节点操作-展开/收起节点 - this.addCommand({ - id: 'toggle-expand-smm-mindmap-node', - name: this._t('commands.toggleExpandNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('toggleActiveExpand') - }) - } - }) - // 节点操作-删除节点 - this.addCommand({ - id: 'delete-smm-mindmap-node', - name: this._t('commands.deleteNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'REMOVE_NODE') - }) - } - }) - // 节点操作-仅删除当前节点 - this.addCommand({ - id: 'delete-smm-mindmap-node-only', - name: this._t('commands.deleteNodeOnly'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'REMOVE_CURRENT_NODE') - }) - } - }) - // 节点操作-复制节点 - this.addCommand({ - id: 'copy-smm-mindmap-node', - name: this._t('commands.copyNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('copyNode') - }) - } - }) - // 节点操作-剪切节点 - this.addCommand({ - id: 'cut-smm-mindmap-node', - name: this._t('commands.cutNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('cutNode') - }) - } - }) - // 节点操作-粘贴节点 - this.addCommand({ - id: 'paste-smm-mindmap-node', - name: this._t('commands.pasteNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('pasteNode') - }) - } - }) - // 节点操作-全选 - this.addCommand({ - id: 'select-all-smm-mindmap-node', - name: this._t('commands.selectAllNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'SELECT_ALL') - }) - } - }) - // 节点操作-一键整理布局 - this.addCommand({ - id: 'organize-smm-mindmap-layout', - name: this._t('commands.organizeLayout'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('execCommand', 'RESET_LAYOUT') - }) - } - }) - // 同级节点对齐,todo - // 节点操作-切换粗体 - this.addCommand({ - id: 'toggle-bold-smm-mindmap-node', - name: this._t('commands.toggleBoldNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('toggleBold') - }) - } - }) - // 节点操作-切换斜体 - this.addCommand({ - id: 'toggle-italic-smm-mindmap-node', - name: this._t('commands.toggleItalicNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('toggleItalic') - }) - } - }) - // 节点操作-切换下划线 - this.addCommand({ - id: 'toggle-underline-smm-mindmap-node', - name: this._t('commands.toggleUnderlineNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('toggleUnderline') - }) - } - }) - // 节点操作-切换删除线 - this.addCommand({ - id: 'toggle-strikethrough-smm-mindmap-node', - name: this._t('commands.toggleStrikethroughNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('toggleStrikethrough') - }) - } - }) - // 节点操作-增大字号 - this.addCommand({ - id: 'increase-font-size-smm-mindmap-node', - name: this._t('commands.increaseFontSizeNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('increaseFontSize') - }) - } - }) - // 节点操作-减小字号 - this.addCommand({ - id: 'decrease-font-size-smm-mindmap-node', - name: this._t('commands.decreaseFontSizeNode'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('decreaseFontSize') - }) - } - }) - } - - _addCanvasActionCommands() { - // 画布操作-放大 - this.addCommand({ - id: 'zoom-in-smm-mindmap', - name: this._t('commands.zoomInCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasZoomIn') - }) - } - }) - // 画布操作-缩小 - this.addCommand({ - id: 'zoom-out-smm-mindmap', - name: this._t('commands.zoomOutCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasZoomOut') - }) - } - }) - // 画布操作-回到根节点 - this.addCommand({ - id: 'back-to-root-smm-mindmap', - name: this._t('commands.backToRootCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasBackToRoot') - }) - } - }) - // 画布操作-向左移动焦点 - this.addCommand({ - id: 'activate-left-smm-mindmap', - name: this._t('commands.activateLeftCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasActivateLeftNode') - }) - } - }) - // 画布操作-向上移动焦点 - this.addCommand({ - id: 'activate-top-smm-mindmap', - name: this._t('commands.activateTopCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasActivateTopNode') - }) - } - }) - // 画布操作-向右移动焦点 - this.addCommand({ - id: 'activate-right-smm-mindmap', - name: this._t('commands.activateRightCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasActivateRightNode') - }) - } - }) - // 画布操作-向下移动焦点 - this.addCommand({ - id: 'activate-bottom-smm-mindmap', - name: this._t('commands.activateBottomCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasActivateBottomNode') - }) - } - }) - // 画布操作-适应画布 - this.addCommand({ - id: 'zoom-fit-smm-mindmap-node', - name: this._t('commands.zoomFitCanvas'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('canvasZoomFit') - }) - } - }) - } - - _addHelpActionCommands() { - // 进入演示模式 this.addCommand({ id: 'enter-smm-mindmap-demonstrate', - name: this._t('commands.enterDemonstrate'), + name: this._t('action.enterDemonstrate'), checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('enter_demonstrate') - }) + const view = this.plugin._getActiveSmmView() + if (view) { + if (!checking) { + view.mindMapAPP.$bus.$emit('enter_demonstrate') + } + return true + } + return false } }) - } - - _addUiActionCommands() { - // 打开图片编辑弹窗 this.addCommand({ - id: 'open-smm-mindmap-image-edit', - name: this._t('commands.openImageEdit'), + id: 'save-smm-mindmap-and-update-image', + name: this._t('action.saveAndUpdateImage'), + hotkeys: [ + { + modifiers: ['Mod', 'Shift'], + key: 's' + } + ], checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('showNodeImage') - }) - } - }) - // 打开超链接编辑弹窗 - this.addCommand({ - id: 'open-smm-mindmap-hyperlink-edit', - name: this._t('commands.openHyperlinkEdit'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('showNodeLink') - }) - } - }) - // 打开备注编辑弹窗 - this.addCommand({ - id: 'open-smm-mindmap-remark-edit', - name: this._t('commands.openRemarkEdit'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('showNodeNote') - }) - } - }) - // 打开标签编辑弹窗 - this.addCommand({ - id: 'open-smm-mindmap-tag-edit', - name: this._t('commands.openTagEdit'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('showNodeTag') - }) - } - }) - // 打开导入弹窗 - this.addCommand({ - id: 'open-smm-mindmap-import', - name: this._t('commands.openImport'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('showImport') - }) - } - }) - // 打开导出弹窗 - this.addCommand({ - id: 'open-smm-mindmap-export', - name: this._t('commands.openExport'), - checkCallback: checking => { - return this._commonCheckCallback(checking, view => { - view.mindMapAPP.$bus.$emit('showExport') - }) + const view = this.plugin._getActiveSmmView() + if (view) { + if (!checking) { + view.forceSaveAndUpdateImage() + } + return true + } + return false } }) } diff --git a/plugin/ob/ConfirmDialog.js b/plugin/ob/ConfirmDialog.js new file mode 100644 index 0000000..76f563f --- /dev/null +++ b/plugin/ob/ConfirmDialog.js @@ -0,0 +1,64 @@ +import { Modal } from 'obsidian' +import i18n from 'i18next' + +export class ConfirmDialog extends Modal { + constructor(app, params) { + super(app) + this.params = { + title: i18n.t('tip.tip'), + confirmText: i18n.t('tip.confirm'), + cancelText: i18n.t('tip.cancel'), + content: '', + danger: false, + ...params + } + this.resolvePromise = null + this.promise = new Promise(resolve => { + this.resolvePromise = resolve + }) + this.setTitle(this.params.title) + } + + onOpen() { + const { contentEl } = this + contentEl.empty() + const contentContainer = contentEl.createDiv('smm-confirm-dialog-content') + if (typeof this.params.content === 'string') { + contentContainer.createEl('p', { text: this.params.content }) + } else { + contentContainer.appendChild(this.params.content) + } + const buttonContainer = contentEl.createDiv('smm-confirm-dialog-buttons') + const cancelBtn = buttonContainer.createEl('button', { + text: this.params.cancelText + }) + cancelBtn.addEventListener('click', () => { + this.params.onCancel?.() + this.resolvePromise(false) + this.close() + }) + const confirmBtn = buttonContainer.createEl('button', { + text: this.params.confirmText, + cls: this.params.danger ? 'mod-warning' : 'mod-cta' + }) + confirmBtn.addEventListener('click', () => { + this.params.onConfirm?.() + this.resolvePromise(true) + this.close() + }) + } + + onClose() { + const { contentEl } = this + contentEl.empty() + if (this.resolvePromise) { + this.resolvePromise(false) + } + } +} + +export function showConfirmationDialog(app, params) { + const dialog = new ConfirmDialog(app, params) + dialog.open() + return dialog.promise +} diff --git a/plugin/ob/MarkdownPostProcessor.js b/plugin/ob/MarkdownPostProcessor.js index a717a69..fbb0c0f 100644 --- a/plugin/ob/MarkdownPostProcessor.js +++ b/plugin/ob/MarkdownPostProcessor.js @@ -1,31 +1,32 @@ import { TFile } from 'obsidian' import { parseMarkdownText } from './metadataAndMarkdown.js' -import { dataURItoBlob } from './utils.js' +import { dataURItoBlob, smmFilePathToFileName } from './utils.js' import LZString from 'lz-string' +import { SMM_VIEW_TYPE } from './constant.js' +import SmmEditView from '../SmmEditView.js' export default class MarkdownPostProcessor { constructor(plugin) { this.plugin = plugin - this.urlCache = new Map() // 文件路径 -> 图片URL的缓存 - this.imageElements = new Map() // 文件路径 -> 图片元素集合 - this.emptyMap = new Map() // 文件路径 -> 当前没有预览图像的集合 + this.urlCache = new Map() + this.imageElements = new Map() + this.emptyMap = new Map() - // 绑定事件处理器 this.handleFileModify = this.handleFileModify.bind(this) this.handleFileDelete = this.handleFileDelete.bind(this) + this.handleModifySvgName = this.handleModifySvgName.bind(this) - // 注册文件监听 plugin.app.vault.on('modify', this.handleFileModify) plugin.app.vault.on('delete', this.handleFileDelete) + plugin.app.vault.on('rename', this.handleModifySvgName) } destroy() { - // 清理事件监听 this.plugin.app.vault.off('modify', this.handleFileModify) this.plugin.app.vault.off('delete', this.handleFileDelete) + this.plugin.app.vault.off('rename', this.handleModifySvgName) - // 释放所有URL对象 this.urlCache.forEach(url => URL.revokeObjectURL(url)) this.urlCache.clear() this.imageElements.clear() @@ -42,15 +43,13 @@ export default class MarkdownPostProcessor { return } const curIsNoImage = noUrlCache && hasEmpty - // 重新生成图片URL const data = await this.plugin.app.vault.read(file) const parsedata = parseMarkdownText(data) - const svgBlob = dataURItoBlob( - LZString.decompressFromBase64(parsedata.svgdata) - ) - const newUrl = URL.createObjectURL(svgBlob) + const newUrl = this._getImgUrl(parsedata.svgdata) + if (!newUrl) { + return + } - // 更新缓存 const oldUrl = this.urlCache.get(file.path) if (oldUrl) URL.revokeObjectURL(oldUrl) this.urlCache.set(file.path, newUrl) @@ -60,7 +59,6 @@ export default class MarkdownPostProcessor { this.emptyMap.delete(file.path) } - // 更新所有关联的图片元素 const elements = this.imageElements.get(file.path) || new Set() elements.forEach(img => { img.src = newUrl @@ -74,10 +72,9 @@ export default class MarkdownPostProcessor { } } - handleFileDelete(file) { + async handleFileDelete(file) { if (!(file instanceof TFile)) return - // 清理被删除文件的资源 const url = this.urlCache.get(file.path) if (url) { URL.revokeObjectURL(url) @@ -95,13 +92,63 @@ export default class MarkdownPostProcessor { }) this.imageElements.delete(file.path) } - // 没有预览图像时修改提示信息 const emptyDiv = this.emptyMap.get(file.path) if (emptyDiv) { emptyDiv.textContent = this.plugin._t('tip.fileDeleted') emptyDiv.removeEventListener('dblclick', emptyDiv.dblclickHandler) this.emptyMap.delete(file.path) } + + this.deletePreviewSvgFile(file) + } + + async deletePreviewSvgFile(file) { + try { + const targetFileName = smmFilePathToFileName(file.path, '.svg') + const { embedImageIsSeparateFileFolder } = this.plugin.settings + const previewFilePath = embedImageIsSeparateFileFolder + ? `${embedImageIsSeparateFileFolder}/${targetFileName}` + : targetFileName + const exist = await this.plugin.app.vault.exists(previewFilePath) + console.log('删除预览图像文件:', previewFilePath, exist) + if (exist) { + await this.plugin.app.vault.adapter.remove(previewFilePath) + } + } catch (error) { + console.error('删除预览图像文件失败:', error) + } + } + + async handleModifySvgName(file, oldName) { + try { + oldName = smmFilePathToFileName(oldName, '.svg') + const { embedImageIsSeparateFileFolder } = this.plugin.settings + const oldPath = embedImageIsSeparateFileFolder + '/' + oldName + const exist = await this.plugin.app.vault.exists(oldPath) + if (exist) { + const newName = smmFilePathToFileName(file.name, '.svg') + const newPath = embedImageIsSeparateFileFolder + '/' + newName + await this.plugin.app.vault.adapter.rename(oldPath, newPath) + } + } catch (error) { + console.error('修改svg文件名失败:', error) + } + try { + const markdownLeafs = this.plugin.app.workspace.getLeavesOfType( + SMM_VIEW_TYPE + ) + for (const leaf of markdownLeafs) { + if ( + leaf.view instanceof SmmEditView && + leaf.view.file.path === file.path + ) { + leaf.view.forceSave(true) + break + } + } + } catch (error) { + console.error('保存失败:', error) + } } register() { @@ -112,12 +159,11 @@ export default class MarkdownPostProcessor { async _markdownPostProcessor(el, ctx) { try { - // 特殊卡片处理 if (this._isSpecialCard(el)) { + console.log('特殊卡片处理') return this._processSpecialCard(el) } - // 模式检测与处理 const embeddedItems = el.querySelectorAll('.internal-embed') if (embeddedItems.length === 0) { await this._processEditMode(el, ctx) @@ -141,7 +187,7 @@ export default class MarkdownPostProcessor { _processSpecialCard(el) { el.classList.add('smmMindCard') const svgdata = el.children[3].children[0].innerHTML - const url = URL.createObjectURL(dataURItoBlob(svgdata)) + const url = this._getImgUrl(svgdata) const img = this._createSvgImageElement(url) el.replaceChildren(img) @@ -178,8 +224,8 @@ export default class MarkdownPostProcessor { const img = await this._createImageFromFile(file, data) containerEl.empty() if (img) { - this._updateImgSize(containerEl, img) containerEl.appendChild(img) + this._updateImgSize(containerEl, img) } else { const emptyDiv = this._createEmptyDiv( containerEl, @@ -223,7 +269,6 @@ export default class MarkdownPostProcessor { } _updateImgSize(containerEl, img) { - // 悬浮预览弹窗 if ( containerEl.parentNode && containerEl.parentNode.classList.contains('popover') @@ -242,49 +287,55 @@ export default class MarkdownPostProcessor { } async _createImageFromFile(file, data) { - // 优先使用缓存 if (this.urlCache.has(file.path)) { const url = this.urlCache.get(file.path) return this._createSvgImageElement(url, file.path) } - // 生成新URL并缓存 const parsedata = parseMarkdownText(data) - if (!parsedata.svgdata) { + const svgdata = parsedata.svgdata + if (!svgdata) { return null } - const svgBlob = dataURItoBlob( - LZString.decompressFromBase64(parsedata.svgdata) - ) - const url = URL.createObjectURL(svgBlob) + const url = this._getImgUrl(svgdata) this.urlCache.set(file.path, url) - const img = this._createSvgImageElement(url, file.path) return img } + _getImgUrl(svgdata) { + if (!svgdata) return '' + let url = '' + if (/^!\[\[/.test(svgdata)) { + const match = svgdata.match(/!\[\[([^\]]+)\]\]/) + if (match && match[1]) { + url = this.plugin.app.vault.adapter.getResourcePath(match[1]) + } + } else { + const svgBlob = dataURItoBlob(LZString.decompressFromBase64(svgdata)) + url = URL.createObjectURL(svgBlob) + } + return url + } + _createSvgImageElement(url, filePath = '') { const img = document.createElement('img') img.src = url img.draggable = false if (filePath) { - // 添加文件路径标识 img.setAttribute('data-smm-file', filePath) - // 注册双击打开源文件 img.addEventListener('dblclick', () => { const newWindow = this.plugin.settings.embedDblClickNewWindow this.plugin.app.workspace.openLinkText(filePath, '', newWindow) }) - // 添加到元素追踪 if (!this.imageElements.has(filePath)) { this.imageElements.set(filePath, new Set()) } this.imageElements.get(filePath).add(img) - // 元素卸载时清理 const observer = new MutationObserver(() => { if (!document.contains(img)) { this.imageElements.get(filePath)?.delete(img) diff --git a/plugin/ob/Menus.js b/plugin/ob/Menus.js index 4dcb5b3..cf4af56 100644 --- a/plugin/ob/Menus.js +++ b/plugin/ob/Menus.js @@ -9,6 +9,7 @@ import LZString from 'lz-string' import { SMM_VIEW_TYPE, SMM_TAG } from './constant.js' import { around } from 'monkey-around' import markdown from 'simple-mind-map/src/parse/markdown.js' +import { showConfirmationDialog } from './ConfirmDialog.js' import SmmEditView from '../SmmEditView.js' export default class Menus { @@ -23,12 +24,10 @@ export default class Menus { return this.plugin._t(key) } - // 添加右键菜单 _addFileMenus() { this.plugin.registerEvent( this.app.workspace.on('file-menu', (menu, file) => { if (file instanceof TFolder) { - // 新建思维导图 menu.addItem(item => { item .setTitle(this._t('action.createMindMap')) @@ -41,7 +40,6 @@ export default class Menus { if (this.plugin._isSmmFile(file)) { hideTargetMenu(menu, '在新窗口中打开') hideTargetMenu(menu, '移动至新窗口') - // 打开为Markdown文档 menu.addItem(item => item .setTitle(this._t('action.openAsMd')) @@ -50,8 +48,9 @@ export default class Menus { .onClick(async () => { await this.app.workspace.openLinkText(file.path, '') const leaf = this.app.workspace.getLeaf(false) - const mdViewType = - this.app.viewRegistry.getTypeByExtension('md') + const mdViewType = this.app.viewRegistry.getTypeByExtension( + 'md' + ) await leaf.setViewState({ type: mdViewType, state: { @@ -63,13 +62,18 @@ export default class Menus { this.app.workspace.revealLeaf(leaf) }) ) - // 转换为md文档 menu.addItem(item => item .setTitle(this._t('action.changeToMdFile')) .setIcon('refresh-cw') .setSection('open') .onClick(async () => { + const confirmed = await showConfirmationDialog(this.app, { + content: this._t('tip.mindMapToMdTip') + }) + if (!confirmed) { + return + } const content = await this.app.vault.read(file) const result = parseMarkdownText(content) const mindMapData = LZString.decompressFromBase64( @@ -91,18 +95,24 @@ export default class Menus { if (mdStr) { mdStr = '---\n' + mdStr + '---\n' } + const { + nodeTextToMarkdownTitleMaxLevel + } = this.plugin.settings const mdMindMap = markdown.transformToMarkdown( - JSON.parse(mindMapData).root + JSON.parse(mindMapData).root, + nodeTextToMarkdownTitleMaxLevel ) mdStr += mdMindMap - let newPath = file.path.replace('.smm.md', '.md') + let newPath = file.path.replace(/\.smm.*\.md$/g, '.md') newPath = await this.plugin._getAvailableFilaName(newPath) await this.app.vault.rename(file, newPath) const renamedFile = this.app.vault.getFileByPath(newPath) if (renamedFile) { - // 关闭当前标签页 - const markdownLeafs = - this.app.workspace.getLeavesOfType(SMM_VIEW_TYPE) + this.plugin.markdownPostProcessor.deletePreviewSvgFile(file) + this.app.noSaveOnClose = true + const markdownLeafs = this.app.workspace.getLeavesOfType( + SMM_VIEW_TYPE + ) for (const leaf of markdownLeafs) { if ( leaf.view instanceof SmmEditView && @@ -112,9 +122,8 @@ export default class Menus { break } } - // 修改文件内容 await this.app.vault.modify(renamedFile, mdStr) - // 重新打开 + this.app.noSaveOnClose = false const ref = this.app.metadataCache.on( 'changed', changedFile => { @@ -140,15 +149,13 @@ export default class Menus { addMarkdownFileMenus() { const self = this - // 在md视图下的smm文件右上角菜单增加切换为思维导图菜单 this.plugin.register( around(MarkdownView.prototype, { onPaneMenu(next) { - return function (menu, source) { + return function(menu, source) { const res = next.apply(this, [menu, source]) if (self.plugin._isSmmFile(this.file)) { if (source === 'more-options') { - // 打开为思维导图文档 menu.addItem(item => item .setTitle(self._t('action.openAsMindMap')) @@ -161,7 +168,6 @@ export default class Menus { } } else { if (source === 'more-options') { - // 预览为思维导图 menu.addItem(item => item .setTitle(self._t('action.previewAsMindMap')) @@ -177,13 +183,18 @@ export default class Menus { }) }) ) - // 转换为思维导图文档 menu.addItem(item => item .setTitle(self._t('action.changeToMindMapFile')) .setIcon('refresh-cw') .setSection('pane') .onClick(async () => { + const confirmed = await showConfirmationDialog(this.app, { + content: self._t('tip.mdToMindMapTip') + }) + if (!confirmed) { + return + } let yaml = '' const tagList = [] await this.app.fileManager.processFrontMatter( @@ -229,9 +240,9 @@ export default class Menus { linkdata: [] }) if (renamedFile) { - // 关闭当前标签页 - const markdownLeafs = - this.app.workspace.getLeavesOfType('markdown') + const markdownLeafs = this.app.workspace.getLeavesOfType( + 'markdown' + ) for (const leaf of markdownLeafs) { if ( leaf.view instanceof MarkdownView && @@ -241,9 +252,7 @@ export default class Menus { break } } - // 修改文件内容 await this.app.vault.modify(renamedFile, str) - // 重新打开 const ref = this.app.metadataCache.on( 'changed', changedFile => { diff --git a/plugin/ob/ModifyFileName.js b/plugin/ob/ModifyFileName.js new file mode 100644 index 0000000..8408424 --- /dev/null +++ b/plugin/ob/ModifyFileName.js @@ -0,0 +1,104 @@ +export default class ModifyFileName { + constructor(view) { + this.view = view + this.plugin = view.plugin + this.app = view.app + this.titleEl = null + } + + setupTitleEditing() { + this.titleEl = this.getTitleElement() + if (!this.titleEl) return + this.titleEl.setAttribute('contenteditable', 'true') + this.onBlur = this.onBlur.bind(this) + this.titleEl.addEventListener('blur', this.onBlur) + this.onKeydown = this.onKeydown.bind(this) + this.titleEl.addEventListener('keydown', this.onKeydown) + } + + getTitleElement() { + return this.view.containerEl.querySelector('.view-header-title') + } + + async finishEditing(accept) { + if (!this.titleEl.isConnected) return + const file = this.view.file + if (!file) return + const originalName = file.basename + if (accept) { + const newName = this.titleEl.textContent.trim() + if (!newName) { + new Notice(this.plugin._t('tip.fileNameEmpty')) + return + } + this.titleEl.innerHTML = newName + if (newName === originalName) return + try { + const parentPath = file.parent.path + const extension = file.extension + const newPath = `${parentPath}${ + parentPath !== '/' ? '/' : '' + }${newName}${extension ? '.' + extension : ''}` + if (!/^[^<>:"/\\|?*]+$/.test(newName)) { + new Notice(this.plugin._t('tip.fileNameIllegal')) + return + } + const existingFile = + this.app.vault.getFileByPath(newPath) || + this.app.vault.getFileByPath(newPath.replace(/^\//, '')) + if (existingFile) { + new Notice(this.plugin._t('tip.fileExist')) + return + } + await this.app.fileManager.renameFile(file, newPath) + } catch (error) { + console.error('重命名文件失败:', error) + new Notice(this.plugin._t('tip.fileRenameFail')) + } + } else { + this.titleEl.innerHTML = originalName + const selection = window.getSelection() + const range = document.createRange() + let lastTextNode = null + const walker = document.createTreeWalker( + this.titleEl, + NodeFilter.SHOW_TEXT, + null, + false + ) + let node + while ((node = walker.nextNode())) { + lastTextNode = node + } + range.setStart( + lastTextNode, + /\.smm$/.test(lastTextNode.textContent) + ? lastTextNode.length - 4 + : lastTextNode.length + ) + range.collapse(true) + selection.removeAllRanges() + selection.addRange(range) + } + } + + onBlur() { + this.finishEditing(true) + } + + onKeydown(e) { + if (e.key === 'Enter') { + this.finishEditing(true) + } else if (e.key === 'Escape') { + this.finishEditing(false) + } + } + + unload() { + if (this.titleEl) { + this.titleEl.removeAttribute('contenteditable') + this.titleEl.removeEventListener('blur', this.onBlur) + this.titleEl.removeEventListener('keydown', this.onKeydown) + } + } +} diff --git a/plugin/ob/PreviewMindMap.js b/plugin/ob/PreviewMindMap.js index 3a350ec..54b729d 100644 --- a/plugin/ob/PreviewMindMap.js +++ b/plugin/ob/PreviewMindMap.js @@ -24,7 +24,6 @@ export class PreviewMindMap { this._renderView() } - // 渲染思维导图 async _renderView() { const content = await this.app.vault.read(this.file) const mindMapData = await this.plugin._mdToMindmapData(content) diff --git a/plugin/ob/SmmSettingTab.js b/plugin/ob/SmmSettingTab.js index 59c2c1d..9280c28 100644 --- a/plugin/ob/SmmSettingTab.js +++ b/plugin/ob/SmmSettingTab.js @@ -1,16 +1,17 @@ import { PluginSettingTab, Setting, Notice } from 'obsidian' import themeList from 'simple-mind-map-plugin-themes/themeList' import { layoutGroupList } from '../src/config' -import { GITHUB_ICON, DEFAULT_SETTINGS, COMMUNITY_ICON } from './constant' +import { GITHUB_ICON, COMMUNITY_ICON } from './constant' +import { DEFAULT_SETTINGS } from './constant' import { SuggestionModal } from './SuggestionModal' -import { checkVersion } from './utils' +import { TextInfoDialog } from './TextInfoDialog' +import { fragWithHTML } from './utils' const validateInteger = (value, defaultValue = 0, errorTip) => { value = Number(value) if (!Number.isNaN(value) && value > 0) { return value } else { - // 请输入大于0的数字 new Notice(errorTip) return defaultValue } @@ -28,6 +29,7 @@ export default class SmmSettingTab extends PluginSettingTab { this.compressImageOptionsMaxWidthSettings = null this.compressImageOptionsMaxHeightSettings = null this.compressImageOptionsQualitySettings = null + this.embedImageIsSeparateFileFolderSettings = null } display() { @@ -40,6 +42,8 @@ export default class SmmSettingTab extends PluginSettingTab { this._addCompressSetting() + this._addImageHostingSetting() + this._addEmbedSetting() this._addOtherSetting() @@ -47,16 +51,14 @@ export default class SmmSettingTab extends PluginSettingTab { this._addHelpInfo() } - // 基本设置 _addBaseSetting() { const { containerEl } = this containerEl.createEl('h2', { text: this.plugin._t('setting.title.title1') }) - // 自动保存时间设置 new Setting(containerEl) - .setName(this.plugin._t('setting.autoSave.title')) // 自动保存时间 - .setDesc(this.plugin._t('setting.autoSave.desc')) // 无操作自动保存时间,单位:秒 + .setName(this.plugin._t('setting.autoSave.title')) + .setDesc(this.plugin._t('setting.autoSave.desc')) .addText(text => { text .setValue(String(this.plugin.settings.autoSaveTime)) @@ -71,22 +73,21 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) - // 主题模式设置 new Setting(containerEl) - .setName(this.plugin._t('setting.themeMode.title')) // 主题模式 - .setDesc(this.plugin._t('setting.themeMode.desc')) // '设置深色、浅色模式' + .setName(this.plugin._t('setting.themeMode.title')) + .setDesc(this.plugin._t('setting.themeMode.desc')) .addDropdown(dropdown => { ;[ { - name: this.plugin._t('setting.themeMode.option1'), // 跟随obsidian + name: this.plugin._t('setting.themeMode.option1'), value: 'follow' }, { - name: this.plugin._t('setting.themeMode.option2'), // 浅色模式 + name: this.plugin._t('setting.themeMode.option2'), value: 'light' }, { - name: this.plugin._t('setting.themeMode.option3'), // 深色模式 + name: this.plugin._t('setting.themeMode.option3'), value: 'dark' } ].forEach(item => { @@ -100,19 +101,17 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) - // 默认主题设置 const allThemeList = [ { - name: this.plugin._t('setting.theme.title'), // 默认主题 + name: this.plugin._t('setting.theme.title'), value: 'default', dark: false }, ...themeList ].reverse() - // 浅色模式的默认主题 new Setting(containerEl) .setName(this.plugin._t('setting.theme.title')) - .setDesc(this.plugin._t('setting.theme.desc')) // '设置默认主题' + .setDesc(this.plugin._t('setting.theme.desc')) .addDropdown(dropdown => { allThemeList.forEach(item => { dropdown.addOption(item.value, item.name) @@ -124,10 +123,9 @@ export default class SmmSettingTab extends PluginSettingTab { await this.plugin._saveSettings() }) }) - // 深色模式的默认主题 new Setting(containerEl) .setName(this.plugin._t('setting.theme.title2')) - .setDesc(this.plugin._t('setting.theme.desc2')) // '设置默认主题' + .setDesc(this.plugin._t('setting.theme.desc2')) .addDropdown(dropdown => { allThemeList.forEach(item => { dropdown.addOption(item.value, item.name) @@ -140,7 +138,6 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) - // 默认结构设置 const allLayoutList = [] ;(layoutGroupList[this.plugin.settings.lang] || layoutGroupList.en).forEach( item => { @@ -154,10 +151,9 @@ export default class SmmSettingTab extends PluginSettingTab { ) } ) - // 默认结构 new Setting(containerEl) .setName(this.plugin._t('setting.layout.title')) - .setDesc(this.plugin._t('setting.layout.desc')) // '设置默认结构' + .setDesc(this.plugin._t('setting.layout.desc')) .addDropdown(dropdown => { allLayoutList.forEach(item => { dropdown.addOption(item.value, item.name) @@ -171,44 +167,64 @@ export default class SmmSettingTab extends PluginSettingTab { }) } - // 文件创建、保存相关设置 _addFileSaveSetting() { const { containerEl } = this containerEl.createEl('h2', { text: this.plugin._t('setting.title.title2') }) - // 新建文件名的前缀 new Setting(containerEl) - .setName(this.plugin._t('setting.file.title1')) // 新建思维导图的文件名前缀 - .setDesc(this.plugin._t('setting.file.desc1')) // 新建思维导图文件名默认的命名格式为:前缀 + 空格 + 日期时间戳 + .setName(this.plugin._t('setting.file.title1')) + .setDesc(this.plugin._t('setting.file.desc1')) .addText(text => { text - .setValue(this.plugin.settings.fileNamePrefix) + .setValue(this.plugin.settings.fileNameFormat) .onChange(async value => { - this.plugin.settings.fileNamePrefix = value + this.plugin.settings.fileNameFormat = value.trim() + ? value.trim() + : DEFAULT_SETTINGS.fileNameFormat await this.plugin._saveSettings() }) }) + .addExtraButton(button => + button + .setIcon('help') + .setTooltip(this.plugin._t('setting.file.filenameFormatDesc')) + .onClick(async () => { + new TextInfoDialog(this.app, { + title: this.plugin._t('setting.file.filenameFormatDesc'), + html: this.plugin._t('html.filenameFormatDesc') + }).open() + }) + ) - // 新建文件名的日期时间戳格式 - const fileNameDateFormatSetting = new Setting(containerEl) - .setName(this.plugin._t('setting.file.title2')) // 新建思维导图的文件名日期时间戳格式 - .setDesc(this.plugin._t('setting.file.desc2')) // 默认为:YYYY-MM-DD HH.mm.ss,实际示例:2025-01-01 23.59.59,如你不清楚该格式的具体含义及如何修改,请参考:https://day.js.org/docs/en/parse/string-format + new Setting(containerEl) + .setName(this.plugin._t('setting.file.title3')) + .setDesc(this.plugin._t('setting.file.desc3')) .addText(text => { text - .setValue(this.plugin.settings.fileNameDateFormat) + .setValue(this.plugin.settings.nodePasteImageNameFormat) .onChange(async value => { - this.plugin.settings.fileNameDateFormat = value + this.plugin.settings.nodePasteImageNameFormat = value.trim() + ? value.trim() + : DEFAULT_SETTINGS.nodePasteImageNameFormat await this.plugin._saveSettings() }) }) - fileNameDateFormatSetting.settingEl.className += - ' smm-setting-item-enable-select' + .addExtraButton(button => + button + .setIcon('help') + .setTooltip(this.plugin._t('setting.file.filenameFormatDesc')) + .onClick(async () => { + new TextInfoDialog(this.app, { + title: this.plugin._t('setting.file.filenameFormatDesc'), + html: this.plugin._t('html.filenameFormatDesc') + }).open() + }) + ) - // 文件存储位置 new Setting(containerEl) - .setName(this.plugin._t('setting.folder.title4')) // 文件存储位置 - .setDesc(this.plugin._t('setting.folder.desc4')) // 设置SimpleMindMap文件存储位置,默认为仓库根路径 + .setName(this.plugin._t('setting.folder.title4')) + .setDesc(this.plugin._t('setting.folder.desc4')) .addDropdown(dropdown => { this._getFilePathOptions().forEach(item => { dropdown.addOption(item.value, item.name) @@ -221,10 +237,9 @@ export default class SmmSettingTab extends PluginSettingTab { this._updateFilePathSettingsVisibility() }) }) - // 文件存储路径设置 this.filePathSettings = new Setting(containerEl) - .setName(this.plugin._t('setting.folder.title1')) // 文件存储路径 - .setDesc(this.plugin._t('setting.folder.desc1')) // 设置SimpleMindMap文件存储路径,默认为仓库根路径 + .setName(this.plugin._t('setting.folder.title1')) + .setDesc(this.plugin._t('setting.folder.desc1')) .addText(text => { text.setValue(this.plugin.settings.filePath).onChange(async value => { this.plugin.settings.filePath = value @@ -238,10 +253,9 @@ export default class SmmSettingTab extends PluginSettingTab { this.filePathSettings.settingEl.className += ' smm-setting-sub-item' this._updateFilePathSettingsVisibility() - // 图片存储位置 new Setting(containerEl) - .setName(this.plugin._t('setting.folder.title5')) // 图片存储位置 - .setDesc(this.plugin._t('setting.folder.desc5')) // 图片存储位置 + .setName(this.plugin._t('setting.folder.title5')) + .setDesc(this.plugin._t('setting.folder.desc5')) .addDropdown(dropdown => { this._getFilePathOptions(true).forEach(item => { dropdown.addOption(item.value, item.name) @@ -254,10 +268,9 @@ export default class SmmSettingTab extends PluginSettingTab { this._updateImagePathSettingsVisibility() }) }) - // 自定义图片存储目录 this.imagePathSettings = new Setting(containerEl) - .setName(this.plugin._t('setting.folder.title2')) // 图片存储路径 - .setDesc(this.plugin._t('setting.folder.desc2')) // 设置上传的图片文件(节点图片、背景图片)存储路径 + .setName(this.plugin._t('setting.folder.title2')) + .setDesc(this.plugin._t('setting.folder.desc2')) .addText(text => { text.setValue(this.plugin.settings.imagePath).onChange(async value => { this.plugin.settings.imagePath = value @@ -269,10 +282,9 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) this.imagePathSettings.settingEl.className += ' smm-setting-sub-item' - // 自定义子文件夹 this.imageSubPathSettings = new Setting(containerEl) - .setName(this.plugin._t('setting.folder.title6')) // 图片存储路径 - .setDesc(this.plugin._t('setting.folder.desc6')) // 设置上传的图片文件(节点图片、背景图片)存储路径 + .setName(this.plugin._t('setting.folder.title6')) + .setDesc(this.plugin._t('setting.folder.desc6')) .addText(text => { text .setValue(this.plugin.settings.imageSubPath) @@ -288,7 +300,6 @@ export default class SmmSettingTab extends PluginSettingTab { this.imageSubPathSettings.settingEl.className += ' smm-setting-sub-item' this._updateImagePathSettingsVisibility() - // 附件存储位置 new Setting(containerEl) .setName(this.plugin._t('setting.folder.title7')) .setDesc(this.plugin._t('setting.folder.desc7')) @@ -304,7 +315,6 @@ export default class SmmSettingTab extends PluginSettingTab { this._updateAttachmentPathSettingsVisibility() }) }) - // 附件存储路径设置 this.attachmentPathSettings = new Setting(containerEl) .setName(this.plugin._t('setting.folder.title3')) .setDesc(this.plugin._t('setting.folder.desc3')) @@ -321,7 +331,6 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) this.attachmentPathSettings.settingEl.className += ' smm-setting-sub-item' - // 自定义子文件夹 this.attachmentSubPathSettings = new Setting(containerEl) .setName(this.plugin._t('setting.folder.title6')) .setDesc(this.plugin._t('setting.folder.desc6')) @@ -341,7 +350,6 @@ export default class SmmSettingTab extends PluginSettingTab { ' smm-setting-sub-item' this._updateAttachmentPathSettingsVisibility() - // 是否支持ob搜索 new Setting(containerEl) .setName(this.plugin._t('setting.folder.title8')) .setDesc(this.plugin._t('setting.folder.desc8')) @@ -354,7 +362,6 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) - // 是否存储画布位置和缩放数据 new Setting(containerEl) .setName(this.plugin._t('setting.folder.title9')) .setDesc(this.plugin._t('setting.folder.desc9')) @@ -366,18 +373,31 @@ export default class SmmSettingTab extends PluginSettingTab { await this.plugin._saveSettings() }) }) + + new Setting(containerEl) + .setName(this.plugin._t('setting.folder.title10')) + .setDesc(this.plugin._t('setting.folder.desc10')) + .addDropdown(dropdown => { + new Array(6).fill(0).forEach((_, index) => { + dropdown.addOption(index + 1, index + 1) + }) + dropdown + .setValue(this.plugin.settings.nodeTextToMarkdownTitleMaxLevel) + .onChange(async value => { + this.plugin.settings.nodeTextToMarkdownTitleMaxLevel = value + await this.plugin._saveSettings() + }) + }) } - // 图片压缩设置 _addCompressSetting() { const { containerEl } = this containerEl.createEl('h2', { text: this.plugin._t('setting.title.title3') }) - // 是否压缩图片设置 new Setting(containerEl) - .setName(this.plugin._t('setting.compress.title1')) // 是否压缩图片 - .setDesc(this.plugin._t('setting.compress.desc1')) // 设置上传的图片文件(节点图片、背景图片)存储路径 + .setName(this.plugin._t('setting.compress.title1')) + .setDesc(this.plugin._t('setting.compress.desc1')) .addToggle(toggle => { toggle .setValue(this.plugin.settings.compressImage) @@ -388,10 +408,9 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) - // 压缩参数设置 this.compressImageOptionsMaxWidthSettings = new Setting(containerEl) - .setName(this.plugin._t('setting.compress.title2')) // 最大压缩宽度 - .setDesc(this.plugin._t('setting.compress.desc2')) // 设置图片压缩后的最大宽度 + .setName(this.plugin._t('setting.compress.title2')) + .setDesc(this.plugin._t('setting.compress.desc2')) .addText(text => { text .setValue(String(this.plugin.settings.compressImageOptionsMaxWidth)) @@ -408,8 +427,8 @@ export default class SmmSettingTab extends PluginSettingTab { this.compressImageOptionsMaxWidthSettings.settingEl.className += ' smm-setting-sub-item' this.compressImageOptionsMaxHeightSettings = new Setting(containerEl) - .setName(this.plugin._t('setting.compress.title3')) // 最大压缩高度 - .setDesc(this.plugin._t('setting.compress.desc3')) // 设置图片压缩后的最大高度 + .setName(this.plugin._t('setting.compress.title3')) + .setDesc(this.plugin._t('setting.compress.desc3')) .addText(text => { text .setValue(String(this.plugin.settings.compressImageOptionsMaxHeight)) @@ -426,15 +445,15 @@ export default class SmmSettingTab extends PluginSettingTab { this.compressImageOptionsMaxHeightSettings.settingEl.className += ' smm-setting-sub-item' this.compressImageOptionsQualitySettings = new Setting(containerEl) - .setName(this.plugin._t('setting.compress.title4')) // 图片质量 + .setName(this.plugin._t('setting.compress.title4')) .setDesc( `${this.plugin._t('setting.compress.desc4')},${this.plugin._t( 'setting.compress.curValue' )}: ${this.plugin.settings.compressImageOptionsQuality}` - ) // 显示当前值 + ) .addSlider(slider => slider - .setLimits(0, 1, 0.1) // 最小值0,最大值1,步长0.1 + .setLimits(0, 1, 0.1) .setValue(this.plugin.settings.compressImageOptionsQuality) .onChange(async value => { this.plugin.settings.compressImageOptionsQuality = value @@ -472,16 +491,46 @@ export default class SmmSettingTab extends PluginSettingTab { this._updateCompressImageSettingsVisibility() } - // 嵌入设置 _addEmbedSetting() { const { containerEl } = this containerEl.createEl('h2', { text: this.plugin._t('setting.title.title4') }) - // 嵌入预览的图像背景是否透明 new Setting(containerEl) - .setName(this.plugin._t('setting.embed.title2')) // 嵌入预览的图像背景是否透明 - .setDesc(this.plugin._t('setting.embed.desc2')) // 嵌入预览的图像背景是否透明 + .setName(this.plugin._t('setting.embed.title3')) + .setDesc(this.plugin._t('setting.embed.desc3')) + .addToggle(toggle => { + toggle + .setValue(this.plugin.settings.embedImageIsSeparateFile) + .onChange(async value => { + this.plugin.settings.embedImageIsSeparateFile = value + this._updateEmbedImageFileFolderSettingsVisibility() + await this.plugin._saveSettings() + }) + }) + + this.embedImageIsSeparateFileFolderSettings = new Setting(containerEl) + .setName(this.plugin._t('setting.embed.title4')) + .setDesc(this.plugin._t('setting.embed.desc4')) + .addText(text => { + text + .setValue(this.plugin.settings.embedImageIsSeparateFileFolder) + .onChange(async value => { + this.plugin.settings.embedImageIsSeparateFileFolder = value + await this.plugin._saveSettings() + }) + this._addFolderSelectBtn(text, selected => { + this.plugin.settings.embedImageIsSeparateFileFolder = selected + this.plugin._saveSettings() + }) + }) + this.embedImageIsSeparateFileFolderSettings.settingEl.className += + ' smm-setting-sub-item' + this._updateEmbedImageFileFolderSettingsVisibility() + + new Setting(containerEl) + .setName(this.plugin._t('setting.embed.title2')) + .setDesc(this.plugin._t('setting.embed.desc2')) .addToggle(toggle => { toggle .setValue(this.plugin.settings.compressImageIsTransparent) @@ -491,10 +540,9 @@ export default class SmmSettingTab extends PluginSettingTab { }) }) - // 嵌入预览双击是否新窗口打开 new Setting(containerEl) - .setName(this.plugin._t('setting.embed.title1')) // 嵌入预览双击是否新窗口打开 - .setDesc(this.plugin._t('setting.embed.desc1')) // ![[]]格式嵌入md文档时双击预览图像是否新窗口打开文件 + .setName(this.plugin._t('setting.embed.title1')) + .setDesc(this.plugin._t('setting.embed.desc1')) .addToggle(toggle => { toggle .setValue(this.plugin.settings.embedDblClickNewWindow) @@ -503,9 +551,20 @@ export default class SmmSettingTab extends PluginSettingTab { await this.plugin._saveSettings() }) }) + + new Setting(containerEl) + .setName(this.plugin._t('setting.embed.title5')) + .setDesc(this.plugin._t('setting.embed.desc5')) + .addToggle(toggle => { + toggle + .setValue(this.plugin.settings.embedLinkNewWindowOpen) + .onChange(async value => { + this.plugin.settings.embedLinkNewWindowOpen = value + await this.plugin._saveSettings() + }) + }) } - // 给目录输入框控件添加选择按钮 _addFolderSelectBtn(text, callback = () => {}) { const inputEl = text.inputEl const suggestionButton = inputEl.parentElement?.createEl('button', { @@ -526,32 +585,39 @@ export default class SmmSettingTab extends PluginSettingTab { }) } - // 获取文件路径选项 _getFilePathOptions(full = false) { const res = [ { - name: this.plugin._t('setting.folder.option1'), // 仓库的根目录 + name: this.plugin._t('setting.folder.option1'), value: 'root' }, { - name: this.plugin._t('setting.folder.option2'), // 指定文件夹 + name: this.plugin._t('setting.folder.option2'), value: 'custom' }, { - name: this.plugin._t('setting.folder.option3'), // 当前文件所在的文件夹 + name: this.plugin._t('setting.folder.option3'), value: 'currentFileFolder' } ] if (full) { res.push({ - name: this.plugin._t('setting.folder.option4'), // 当前文件所在的文件夹的子文件夹 + name: this.plugin._t('setting.folder.option4'), value: 'currentFileFolderSubFolder' }) } return res } - // 切换文件路径设置的显示状态 + _updateEmbedImageFileFolderSettingsVisibility() { + const isVisible = this.plugin.settings.embedImageIsSeparateFile + if (this.embedImageIsSeparateFileFolderSettings) { + this.embedImageIsSeparateFileFolderSettings.settingEl.style.display = isVisible + ? '' + : 'none' + } + } + _updateFilePathSettingsVisibility() { const isVisible = this.plugin.settings.filePathType === 'custom' if (this.filePathSettings) { @@ -559,7 +625,6 @@ export default class SmmSettingTab extends PluginSettingTab { } } - // 切换图片路径设置的显示状态 _updateImagePathSettingsVisibility() { const isVisible = this.plugin.settings.imagePathType === 'custom' if (this.imagePathSettings) { @@ -574,7 +639,6 @@ export default class SmmSettingTab extends PluginSettingTab { } } - // 切换附件路径设置的显示状态 _updateAttachmentPathSettingsVisibility() { const isVisible = this.plugin.settings.attachmentPathType === 'custom' if (this.attachmentPathSettings) { @@ -591,7 +655,6 @@ export default class SmmSettingTab extends PluginSettingTab { } } - // 切换压缩图片设置的显示状态 _updateCompressImageSettingsVisibility() { const isVisible = this.plugin.settings.compressImage if (this.compressImageOptionsMaxWidthSettings) { @@ -611,43 +674,87 @@ export default class SmmSettingTab extends PluginSettingTab { } } + _addImageHostingSetting() { + const { containerEl } = this + + containerEl.createEl('h2', { text: this.plugin._t('setting.title.title6') }) + + // 是否开启图床 + new Setting(containerEl) + .setName(this.plugin._t('setting.imageHosting.title1')) + .setDesc(this.plugin._t('setting.imageHosting.desc1')) + .addToggle(toggle => { + toggle + .setValue(this.plugin.settings.useImgHosting) + .onChange(async value => { + if ( + value && + (!this.plugin.settings.imgHostingUrl || + !this.plugin.settings.imgHostingFormField || + !this.plugin.settings.imgHostingResponseField) + ) { + toggle.setValue(false) + new Notice(this.plugin._t('setting.imageHosting.tip1')) + return + } + this.plugin.settings.useImgHosting = value + await this.plugin._saveSettings() + }) + }) + + // 图床url + new Setting(containerEl) + .setName(this.plugin._t('setting.imageHosting.title2')) + .setDesc(this.plugin._t('setting.imageHosting.desc2')) + .addText(text => { + text + .setValue(String(this.plugin.settings.imgHostingUrl)) + .onChange(async value => { + this.plugin.settings.imgHostingUrl = value + await this.plugin._saveSettings() + }) + }) + + // 表单字段 + new Setting(containerEl) + .setName(this.plugin._t('setting.imageHosting.title3')) + .setDesc(this.plugin._t('setting.imageHosting.desc3')) + .addText(text => { + text + .setValue(String(this.plugin.settings.imgHostingFormField)) + .onChange(async value => { + this.plugin.settings.imgHostingFormField = value + await this.plugin._saveSettings() + }) + }) + + // 接口响应结构 + new Setting(containerEl) + .setName(this.plugin._t('setting.imageHosting.title4')) + .setDesc( + fragWithHTML( + this.plugin._t('setting.imageHosting.desc4') + + '' + + this.plugin._t('setting.imageHosting.desc5') + + '。' + ) + ) + .addText(text => { + text + .setValue(String(this.plugin.settings.imgHostingResponseField)) + .onChange(async value => { + this.plugin.settings.imgHostingResponseField = value + await this.plugin._saveSettings() + }) + }) + } + _addOtherSetting() { const { containerEl } = this containerEl.createEl('h2', { text: this.plugin._t('setting.title.title5') }) - - // 是否开启版本检查 - new Setting(containerEl) - .setName(this.plugin._t('setting.other.title1')) // 是否开启版本检查 - .setDesc(this.plugin._t('setting.other.desc1')) // 是否开启版本检查 - .addToggle(toggle => { - toggle - .setValue(this.plugin.settings.openVersionCheck) - .onChange(async value => { - this.plugin.settings.openVersionCheck = value - await this.plugin._saveSettings() - }) - }) - .addExtraButton(button => { - button.setIcon('refresh-cw').onClick(async () => { - checkVersion( - version => { - if (version) { - new Notice(this.plugin._t('tip.pluginNewVersion') + version) - } else { - new Notice(this.plugin._t('tip.pluginNoNewVersion')) - } - }, - true, - () => { - new Notice(this.plugin._t('tip.pluginVersionCheckError')) - } - ) - }) - }) } - // 添加辅助信息 _addHelpInfo() { const { containerEl } = this const linkEl = containerEl.createDiv('setting-item smm-setting-link-list') diff --git a/plugin/ob/SuggestionModal.js b/plugin/ob/SuggestionModal.js index 3464d47..fe906d2 100644 --- a/plugin/ob/SuggestionModal.js +++ b/plugin/ob/SuggestionModal.js @@ -5,7 +5,7 @@ export class SuggestionModal extends SuggestModal { super(app) this.plugin = plugin this.emptyStateText = this.plugin._t('tip.noMatchResult') - this.type = type // folder(选择目录) + this.type = type if (this.type === 'folder') { this.getSuggestions = this._queryFolders.bind(this) } else { @@ -14,7 +14,6 @@ export class SuggestionModal extends SuggestModal { this.onSelect = onSelect } - // 查询目录 _queryFolders(query) { const list = this.app.vault.getAllFolders() return list diff --git a/plugin/ob/TextInfoDialog.js b/plugin/ob/TextInfoDialog.js new file mode 100644 index 0000000..4cbd4eb --- /dev/null +++ b/plugin/ob/TextInfoDialog.js @@ -0,0 +1,34 @@ +import { Modal } from 'obsidian' +import i18n from 'i18next' + +export class TextInfoDialog extends Modal { + constructor(app, params = {}) { + super(app) + this.params = { + title: '', + html: '', + closeText: i18n.t('tip.close'), + ...params + } + this.setTitle(this.params.title) + } + + onOpen() { + const { contentEl } = this + contentEl.empty() + const contentContainer = contentEl.createDiv('smm-text-info-dialog-content') + contentContainer.innerHTML = this.params.html + const buttonContainer = contentEl.createDiv('smm-text-info-dialog-buttons') + const closeBtn = buttonContainer.createEl('button', { + text: this.params.closeText + }) + closeBtn.addEventListener('click', () => { + this.close() + }) + } + + onClose() { + const { contentEl } = this + contentEl.empty() + } +} diff --git a/plugin/ob/constant.js b/plugin/ob/constant.js index 0a33caf..9e94c8a 100644 --- a/plugin/ob/constant.js +++ b/plugin/ob/constant.js @@ -5,9 +5,9 @@ export const SMM_TAG = 'simplemindmap' export const getDefaultSmmData = (options = {}) => { const theme = options.theme || 'classic13' const layout = options.layout || 'logicalStructure' - const rootNodeDefaultText = options.rootNodeDefaultText || 'Root Node' // 根节点 - const secondNodeDefaultText = options.secondNodeDefaultText || 'Second Node' // 二级节点 - const branchNodeDefaultText = options.branchNodeDefaultText || 'Branch Node' // 分支主题 + const rootNodeDefaultText = options.rootNodeDefaultText || 'Root node' // 根节点 + const secondNodeDefaultText = options.secondNodeDefaultText || 'Second node' // 二级节点 + const branchNodeDefaultText = options.branchNodeDefaultText || 'Branch node' // 分支主题 return { root: { data: { text: rootNodeDefaultText }, @@ -27,36 +27,46 @@ export const getDefaultSmmData = (options = {}) => { } export const DEFAULT_SETTINGS = { - isFirstUse: true, // 是否是第一次使用插件 - fileNamePrefix: 'MindMap', // 新建思维导图的文件名前缀 - fileNameDateFormat: 'YYYY-MM-DD HH.mm.ss', // 新建思维导图的文件名日期时间戳格式 - lang: 'zh', // 语言 - themeMode: 'follow', // 主题模式 - defaultLayout: 'logicalStructure', // 默认布局 - defaultTheme: 'classic13', // 浅色模式的默认主题 - defaultThemeDark: 'classic', // 深色模式的默认主题 - filePathType: 'root', // 文件存储位置 - filePath: '', // 文件存储路径 - imagePathType: 'currentFileFolder', // 图片存储位置 - imagePath: '', // 图片存储路径 - imageSubPath: '', // 自定义子文件夹 - attachmentPathType: 'currentFileFolder', // 附件存储位置 - attachmentPath: '', // 附件存储路径 - attachmentSubPath: '', // 自定义子文件夹 - compressImage: true, // 是否压缩图片 - compressImageOptionsMaxWidth: 1200, // 图片压缩后的最大宽度 - compressImageOptionsMaxHeight: 1200, // 图片压缩后的最大高度 - compressImageOptionsQuality: 0.8, // 图片质量 - attachmentPath: 'assets/files', // 附件存储路径 - compressImageIsTransparent: false, // 嵌入预览的图像背景是否透明 - embedDblClickNewWindow: true, // 嵌入预览双击是否新窗口打开 - autoSaveTime: 5, // 无操作自动保存时间,单位s + isFirstUse: true, + fileNameFormat: 'MindMap {date:YYYY-MM-DD HH.mm.ss}', + lang: 'zh', + themeMode: 'follow', + defaultLayout: 'logicalStructure', + defaultTheme: 'classic13', + defaultThemeDark: 'classic', + filePathType: 'root', + filePath: '', + imagePathType: 'currentFileFolder', + imagePath: '', + imageSubPath: '', + attachmentPathType: 'currentFileFolder', + attachmentPath: '', + attachmentSubPath: '', + compressImage: true, + compressImageOptionsMaxWidth: 1200, + compressImageOptionsMaxHeight: 1200, + compressImageOptionsQuality: 0.8, + compressImageIsTransparent: false, + embedDblClickNewWindow: true, + autoSaveTime: 5, mindMapConfig: null, mindMapLocalConfig: null, - codeBlockInitHeight: 300, // smm代码块方式嵌入时初始高度,单位:px - supportObSearch: false, // 是否支持ob搜索 - openVersionCheck: true, // 是否开启版本检查 - saveCanvasViewData: true // 是否存储画布位置和缩放数据 + supportObSearch: true, + saveCanvasViewData: true, + nodeTextToMarkdownTitleMaxLevel: 3, + embedImageIsSeparateFile: true, + embedImageIsSeparateFileFolder: '.smm-embed-image-files', + nodePasteImageNameFormat: '{notename}_pasteImage', + embedLinkNewWindowOpen: true, + useImgHosting: false, + imgHostingUrl: 'http://127.0.0.1:36677/upload', + imgHostingFormField: 'files', + imgHostingResponseField: 'data.result[0]' +} + +let smmEditViewCount = 0 +export const getSmmEditViewCount = () => { + return smmEditViewCount++ } export const IGNORE_CHECK_SMM = 'ignoreCheckSmm' diff --git a/plugin/ob/metadataAndMarkdown.js b/plugin/ob/metadataAndMarkdown.js index fc235e3..38b3197 100644 --- a/plugin/ob/metadataAndMarkdown.js +++ b/plugin/ob/metadataAndMarkdown.js @@ -1,14 +1,16 @@ import { getDefaultSmmData, SMM_TAG } from './constant' import LZString from 'lz-string' +import i18n from 'i18next' export const parseMarkdownText = text => { const result = { metadata: { path: '', tags: [], yaml: '', content: '' }, svgdata: '', - linkdata: [] + svgdataUpdateAt: '', + linkdata: [], + textdata: [] } - // Split text into lines const lines = text.split('\n') let currentSection = '' let inCodeBlock = false @@ -17,13 +19,11 @@ export const parseMarkdownText = text => { let codeBlockContent = [] for (const line of lines) { - // Handle YAML header if (line.trim() === '---') { inYamlHeader = !inYamlHeader continue } - // Check for section headers if (line.startsWith('# metadata')) { currentSection = 'metadata' continue @@ -34,11 +34,9 @@ export const parseMarkdownText = text => { currentSection = 'linkdata' continue } else if (line.startsWith('# textdata')) { - // 用于搜索的节点文本数据,遍历到这个即可结束 break } - // Handle code blocks if (line.trim() === '```metadata' || line.trim() === '```svgData') { inCodeBlock = true continue @@ -57,13 +55,17 @@ export const parseMarkdownText = text => { continue } - // Collect content if (inCodeBlock) { codeBlockContent.push(line) } else if (currentSection === 'linkdata' && line.startsWith('- ')) { result.linkdata.push(line.replace('- ', '').trim()) + } else if (currentSection === 'svgdata') { + if (line.startsWith('![[')) { + result.svgdata = line.trim() + } else if (line.startsWith('> updateAt:')) { + result.svgdataUpdateAt = line.match(/> updateAt:\s*(.*)/)[1] + } } else if (inYamlHeader) { - // 解析YAML if (line.startsWith('tags:')) { inTags = true } else if (inTags && line.startsWith(' -')) { @@ -85,7 +87,6 @@ export const parseMarkdownText = text => { export const assembleMarkdownText = obj => { let result = '---\n' - // Assemble YAML header result += `path: ${obj.metadata.path}\n` result += 'tags:\n' for (const tag of obj.metadata.tags) { @@ -96,30 +97,32 @@ export const assembleMarkdownText = obj => { } result += '---\n' - // Assemble metadata section + result += '> ' + i18n.t('tip.mdModifyTip') + '\n' + result += '# metadata\n' result += '```metadata\n' result += obj.metadata.content result += '\n```\n' - // Assemble svgdata section result += '# svgdata\n' - result += '```svgData\n' - result += obj.svgdata - result += '\n```\n' + if (obj.svgdata && /^!\[\[/.test(obj.svgdata)) { + result += obj.svgdata + '\n' + result += '> updateAt: ' + (obj.svgdataUpdateAt || '') + '\n' + } else { + result += '```svgData\n' + result += obj.svgdata + result += '\n```\n' + } - // Assemble linkdata section result += '# linkdata\n' for (const item of obj.linkdata) { result += `- ${item}\n` } - // Assemble textdata section result += '# textdata\n' if (obj.textdata && Array.isArray(obj.textdata)) { result += obj.textdata.join('\n\n') } - return result } @@ -137,6 +140,8 @@ export const createDefaultText = (filePath, options) => { content: createDefaultMindMapData(options) }, svgdata: '', - linkdata: [] + svgdataUpdateAt: '', + linkdata: [], + textdata: [] }) } diff --git a/plugin/ob/utils.js b/plugin/ob/utils.js index 815ad96..2548e91 100644 --- a/plugin/ob/utils.js +++ b/plugin/ob/utils.js @@ -1,6 +1,5 @@ -import manifestJson from '../../manifest.json' +import { createUid } from 'simple-mind-map/src/utils/index.js' -// 极简的深拷贝 export const simpleDeepClone = data => { try { return JSON.parse(JSON.stringify(data)) @@ -13,7 +12,6 @@ export const generateRandomString = ( length = 12, charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ) => { - // 参数验证 if (typeof length !== 'number' || length <= 0) { throw new Error('长度必须是正整数') } @@ -21,7 +19,6 @@ export const generateRandomString = ( throw new Error('字符集不能为空') } - // 使用加密安全的随机数生成器(如果可用) let randomValues if (typeof crypto !== 'undefined' && crypto.getRandomValues) { randomValues = new Uint32Array(length) @@ -32,7 +29,6 @@ export const generateRandomString = ( .map(() => Math.random() * 0x100000000) } - // 生成随机字符串 let result = '' for (let i = 0; i < length; i++) { const randomIndex = randomValues[i] % charSet.length @@ -43,9 +39,7 @@ export const generateRandomString = ( } export const hideTargetMenu = (menu, text = '在新窗口中打开') => { - // 隐藏特定默认菜单项 menu.items.forEach(item => { - // 通过菜单项标题或ID识别要隐藏的项 if (item.title === text || item.dom?.innerText?.includes(text)) { item.dom.hide() } @@ -72,8 +66,6 @@ export const getUidFromSource = data => { const last = matches[matches.length - 1] let index = last[1] let str = content[index] - // 当检测到^时,记录后面的字符 - // 当检测到换行符时,跳出循环 let uid = '' let isJoin = false while (true || index >= total) { @@ -92,73 +84,44 @@ export const getUidFromSource = data => { return uid } -export let versionUpdateCheckTimer = null -let versionUpdateChecked = false -export const checkVersion = async ( - callback = () => {}, - force = false, - err = () => {} -) => { - if (!force && versionUpdateChecked) { - return - } - versionUpdateChecked = true - try { - const gitAPIrequest = async () => { - return JSON.parse( - await request({ - url: `https://api.github.com/repos/wanglin2/obsidian-simplemindmap/releases?per_page=15&page=1` - }) - ) - } - const latestVersion = (await gitAPIrequest()) - .filter(el => !el.draft && !el.prerelease) - .map(el => { - return { - version: el.tag_name, - published: new Date(el.published_at) - } - }) - .filter(el => el.version.match(/^\d+\.\d+\.\d+$/)) - .sort((el1, el2) => el2.published - el1.published)[0].version - if (isVersionNewerThanOther(latestVersion, manifestJson.version)) { - callback(latestVersion) - } else { - callback() - } - } catch (e) { - console.error('检查更新失败', e) - err(e) - } - versionUpdateCheckTimer = window.setTimeout(() => { - versionUpdateChecked = false - versionUpdateCheckTimer = null - }, 28800000 * 3) // 24小时检查一次 +export const smmFilePathToFileName = (filePath, ext) => { + if (!filePath) return createUid() + ext + filePath = + filePath + .replace(/\//g, '_') + .replace(/.smm.md$/, '') + .replace(/.md$/, '') + ext + return filePath } -export const isVersionNewerThanOther = (version, otherVersion) => { - if (!version || !otherVersion) return true - const v = version.match(/(\d*)\.(\d*)\.(\d*)/) - const o = otherVersion.match(/(\d*)\.(\d*)\.(\d*)/) - return Boolean( - v && - v.length === 4 && - o && - o.length === 4 && - !( - isNaN(parseInt(v[1])) || - isNaN(parseInt(v[2])) || - isNaN(parseInt(v[3])) - ) && - !( - isNaN(parseInt(o[1])) || - isNaN(parseInt(o[2])) || - isNaN(parseInt(o[3])) - ) && - (parseInt(v[1]) > parseInt(o[1]) || - (parseInt(v[1]) >= parseInt(o[1]) && parseInt(v[2]) > parseInt(o[2])) || - (parseInt(v[1]) >= parseInt(o[1]) && - parseInt(v[2]) >= parseInt(o[2]) && - parseInt(v[3]) > parseInt(o[3]))) - ) +export const formatFileName = (str, { notename, ignores } = {}) => { + str = str.trim() + if (!str) return '' + str = str.replace(/{([^{}]+)}/g, (...args) => { + const match = args[1].trim() + if (ignores && ignores.includes(match)) { + return args[0] + } + if (match === 'notename' && notename) { + return notename + } else if (match === 'date') { + return moment().format('YYYY-MM-DD') + } else if (match === 'time') { + return moment().format('HH:mm:ss') + } else if (match === 'datetime') { + return moment().format('YYYY-MM-DD HH:mm:ss') + } else if (match === 'random') { + return Math.random() + .toString(36) + .substring(2, 8) + } else if (match.startsWith('date:') && match.slice(5).trim()) { + return moment().format(match.slice(5).trim()) + } + return args[0] + }) + return str } + +export const fragWithHTML = html => { + return createFragment(frag => (frag.createDiv().innerHTML = html)) +} \ No newline at end of file diff --git a/plugin/package-lock.json b/plugin/package-lock.json index 991e5bb..46adc5e 100644 --- a/plugin/package-lock.json +++ b/plugin/package-lock.json @@ -1,11 +1,11 @@ { - "name": "obsidian-simple-mind-map", + "name": "simple-mind-map", "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "obsidian-simple-mind-map", + "name": "simple-mind-map", "version": "0.1.0", "dependencies": { "@toast-ui/editor": "^3.1.5", @@ -14,7 +14,6 @@ "katex": "^0.16.9", "lz-string": "^1.5.0", "monkey-around": "^3.0.0", - "simple-mind-map": "^0.14.0-fix.1", "simple-mind-map-plugin-themes": "^1.0.0", "v-viewer": "^1.6.4", "vue": "^2.6.14", @@ -124,19 +123,6 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -162,19 +148,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.27.3", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", @@ -187,19 +160,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-annotate-as-pure/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", @@ -319,29 +279,19 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-member-expression-to-functions/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.0.0-beta.35", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz", - "integrity": "sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg==", - "dev": true, - "dependencies": { - "@babel/types": "7.0.0-beta.35", - "lodash": "^4.2.0" - } - }, "node_modules/@babel/helper-module-transforms": { "version": "7.27.3", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", @@ -359,32 +309,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", @@ -397,19 +321,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-optimise-call-expression/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-plugin-utils": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", @@ -466,19 +377,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -518,19 +416,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-wrap-function/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helpers": { "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", @@ -544,19 +429,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helpers/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/parser": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", @@ -571,18 +443,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/parser/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", @@ -769,32 +629,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-async-to-generator/node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", @@ -1658,19 +1492,6 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/preset-modules/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/runtime": { "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", @@ -1693,19 +1514,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/template/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/traverse": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", @@ -1724,11 +1532,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/types": { + "node_modules/@babel/types": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" @@ -1737,17 +1544,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/types": { - "version": "7.0.0-beta.35", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.35.tgz", - "integrity": "sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "lodash": "^4.2.0", - "to-fast-properties": "^2.0.0" - } - }, "node_modules/@codemirror/state": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", @@ -2487,37 +2283,12 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@pdf-lib/standard-fonts": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", - "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", - "dependencies": { - "pako": "^1.0.6" - } - }, - "node_modules/@pdf-lib/upng": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", - "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", - "dependencies": { - "pako": "^1.0.10" - } - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, - "node_modules/@svgdotjs/svg.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.0.tgz", - "integrity": "sha512-Tr8p+QVP7y+QT1GBlq1Tt57IvedVH8zCPoYxdHLX0Oof3a/PqnC/tXAkVufv1JQJfsDHlH/UrjcDfgxSofqSNA==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Fuzzyma" - } - }, "node_modules/@toast-ui/editor": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@toast-ui/editor/-/editor-3.2.2.tgz", @@ -2551,14 +2322,6 @@ "@types/tern": "*" } }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dependencies": { - "@types/ms": "*" - } - }, "node_modules/@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", @@ -2615,19 +2378,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" - }, "node_modules/@types/node": { "version": "16.18.126", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", @@ -2643,11 +2393,6 @@ "@types/estree": "*" } }, - "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -2918,36 +2663,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-loose": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-6.1.0.tgz", - "integrity": "sha512-FHhXoiF0Uch3IqsrnPpWwCtiv5PYvipTpT1k9lDMgQVVYc9iDuSl5zdJV358aI8twfHCYMFBRVYvAVki9wC/ng==", - "dependencies": { - "acorn": "^6.2.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-loose/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/adler-32": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", @@ -3155,6 +2870,27 @@ "@babel/helper-module-imports": "7.0.0-beta.35" } }, + "node_modules/babel-plugin-component/node_modules/@babel/helper-module-imports": { + "version": "7.0.0-beta.35", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz", + "integrity": "sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg==", + "dev": true, + "dependencies": { + "@babel/types": "7.0.0-beta.35", + "lodash": "^4.2.0" + } + }, + "node_modules/babel-plugin-component/node_modules/@babel/types": { + "version": "7.0.0-beta.35", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.35.tgz", + "integrity": "sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "lodash": "^4.2.0", + "to-fast-properties": "^2.0.0" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", @@ -3224,15 +2960,11 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, "funding": [ { "type": "github", @@ -3269,15 +3001,6 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -3327,6 +3050,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, "funding": [ { "type": "github", @@ -3483,15 +3207,6 @@ "node": ">=8" } }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -3592,11 +3307,6 @@ "node": ">= 10" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, "node_modules/consolidate": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", @@ -3641,11 +3351,6 @@ "url": "https://opencollective.com/core-js" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -4605,6 +4310,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, "dependencies": { "ms": "^2.1.3" }, @@ -4617,18 +4323,6 @@ } } }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/deepmerge": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", @@ -4654,14 +4348,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "engines": { - "node": ">=6" - } - }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -4675,14 +4361,6 @@ "node": ">=0.10" } }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -4788,28 +4466,6 @@ "node": ">= 4" } }, - "node_modules/enhanced-resolve": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz", - "integrity": "sha512-n6e4bsCpzsP0OB76X+vEWhySUQI8GHPVFVK+3QkX35tbryy2WoeGeK5kQ+oxzgDVHjIZyz5fyS60Mi3EpQLc0Q==", - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.3.0", - "object-assign": "^4.0.1", - "tapable": "^0.2.3" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/enhanced-resolve/node_modules/tapable": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", - "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -4834,15 +4490,12 @@ "node": ">=4" } }, - "node_modules/err-code": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", - "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" - }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, "dependencies": { "prr": "~1.0.1" }, @@ -4983,11 +4636,6 @@ "node": ">=0.10.0" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -5003,11 +4651,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -5117,11 +4760,6 @@ "node": ">=0.8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5140,11 +4778,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-browser-rtc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", - "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==" - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -5182,26 +4815,6 @@ "node": ">= 0.4" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -5223,7 +4836,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/has-flag": { "version": "4.0.0", @@ -5327,6 +4941,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, "funding": [ { "type": "github", @@ -5355,11 +4970,6 @@ "node": ">=0.10.0" } }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" - }, "node_modules/immutable": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", @@ -5385,20 +4995,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/interpret": { "version": "3.1.1", @@ -5554,11 +5155,6 @@ "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", "dev": true }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5574,15 +5170,6 @@ "node": ">=0.10.0" } }, - "node_modules/isomorphic.js": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", - "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -5656,17 +5243,6 @@ "node": ">=6" } }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, "node_modules/katex": { "version": "0.16.9", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz", @@ -5699,14 +5275,6 @@ "node": ">=0.10.0" } }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/klona": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", @@ -5787,33 +5355,11 @@ "semver": "bin/semver" } }, - "node_modules/lib0": { - "version": "0.2.114", - "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.114.tgz", - "integrity": "sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ==", - "dependencies": { - "isomorphic.js": "^0.2.4" - }, - "bin": { - "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", - "0gentesthtml": "bin/gentesthtml.js", - "0serve": "bin/0serve.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dependencies": { - "immediate": "~3.0.5" - } + "node_modules/less/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, "node_modules/lilconfig": { "version": "3.1.3", @@ -5882,23 +5428,12 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead." - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -5974,41 +5509,6 @@ "node": ">= 0.4" } }, - "node_modules/mdast-util-from-markdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "mdast-util-to-string": "^3.1.0", - "micromark": "^3.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -6021,15 +5521,6 @@ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", "dev": true }, - "node_modules/memory-fs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "integrity": "sha512-QTNXnl79X97kZ9jJk/meJrtDuvgvRakX5LU7HZW1L7MsXHuSTwoMIzN9tOLLH3Xfsj/gbsSqX/ovnsqz246zKQ==", - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, "node_modules/merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -6045,427 +5536,6 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "node_modules/micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-factory-destination": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -6587,17 +5657,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -6621,18 +5680,11 @@ "resolved": "https://registry.npmjs.org/monkey-around/-/monkey-around-3.0.0.tgz", "integrity": "sha512-jL6uY2lEAoaHxZep1cNRkCZjoIWY4g5VYCjriEWmcyHU7w8NU1+JH57xE251UVTohK0lCxMjv0ZV4ByDLIXEpw==" }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "engines": { - "node": ">=4" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/nanoid": { "version": "3.3.11", @@ -6694,14 +5746,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/obsidian": { "version": "1.8.7", "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.8.7.tgz", @@ -6716,14 +5760,6 @@ "@codemirror/view": "^6.0.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/orderedmap": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", @@ -6765,16 +5801,6 @@ "node": ">=6" } }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parchment": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", - "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==" - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -6784,14 +5810,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6807,17 +5825,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/pdf-lib": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", - "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==", - "dependencies": { - "@pdf-lib/standard-fonts": "^1.0.0", - "@pdf-lib/upng": "^1.0.1", - "pako": "^1.0.11", - "tslib": "^1.11.1" - } - }, "node_modules/picocolors": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", @@ -6915,11 +5922,6 @@ "node": ">=4" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, "node_modules/prosemirror-commands": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.5.2.tgz", @@ -6998,7 +6000,9 @@ "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==" + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true }, "node_modules/pseudomap": { "version": "1.0.2", @@ -7015,92 +6019,15 @@ "node": ">=6" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quill": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", - "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", - "dependencies": { - "eventemitter3": "^5.0.1", - "lodash-es": "^4.17.21", - "parchment": "^3.0.0", - "quill-delta": "^5.1.0" - }, - "engines": { - "npm": ">=8.2.3" - } - }, - "node_modules/quill-delta": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", - "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", - "dependencies": { - "fast-diff": "^1.3.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isequal": "^4.5.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/quill/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -7246,34 +6173,16 @@ "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/rope-sequence": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==" }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -7366,11 +6275,6 @@ } } }, - "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" - }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -7427,11 +6331,6 @@ "node": ">= 0.4" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -7465,27 +6364,6 @@ "node": ">=8" } }, - "node_modules/simple-mind-map": { - "version": "0.14.0-fix.1", - "resolved": "https://registry.npmjs.org/simple-mind-map/-/simple-mind-map-0.14.0-fix.1.tgz", - "integrity": "sha512-LuX2+32cS/lIB2AxmzkLZi5NHbrHuXBha3v0O376PE75K4ivAFoXYzJQ661/ls2E16ZOWwgvx9q4znt7jTBXxA==", - "dependencies": { - "@svgdotjs/svg.js": "3.2.0", - "deepmerge": "^1.5.2", - "eventemitter3": "^4.0.7", - "jszip": "^3.10.1", - "katex": "^0.16.8", - "mdast-util-from-markdown": "^1.3.0", - "pdf-lib": "^1.17.1", - "quill": "^2.0.3", - "tern": "^0.24.3", - "uuid": "^9.0.0", - "ws": "^7.5.9", - "xml-js": "^1.6.11", - "y-webrtc": "^10.2.5", - "yjs": "^13.6.8" - } - }, "node_modules/simple-mind-map-plugin-themes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/simple-mind-map-plugin-themes/-/simple-mind-map-plugin-themes-1.0.0.tgz", @@ -7494,47 +6372,6 @@ "esbuild": "^0.17.15" } }, - "node_modules/simple-peer": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", - "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "buffer": "^6.0.3", - "debug": "^4.3.2", - "err-code": "^3.0.1", - "get-browser-rtc": "^1.1.0", - "queue-microtask": "^1.2.3", - "randombytes": "^2.1.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/simple-peer/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7600,6 +6437,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -7678,34 +6516,6 @@ "node": ">=6" } }, - "node_modules/tern": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/tern/-/tern-0.24.3.tgz", - "integrity": "sha512-Z8uvtdWIlFn1GWy0HW5FhZ8VDryZwoJUdnjZU25C7/PBOltLIn1uv+WF3rVq6S1761YbsmbZYRP/l0ZJBCkvrw==", - "dependencies": { - "acorn": "^6.0.0", - "acorn-loose": "^6.0.0", - "acorn-walk": "^6.0.0", - "enhanced-resolve": "^2.2.2", - "glob": "^7.1.1", - "minimatch": "^3.0.3", - "resolve-from": "2.0.0" - }, - "bin": { - "tern": "bin/tern" - } - }, - "node_modules/tern/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/terser": { "version": "5.39.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", @@ -7847,11 +6657,6 @@ "node": ">=8.0" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -7918,18 +6723,6 @@ "node": ">=4" } }, - "node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -8018,36 +6811,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", - "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" - }, - "engines": { - "node": ">=8" - } + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "node_modules/v-viewer": { "version": "1.7.4", @@ -8521,31 +7286,6 @@ "node": ">=0.8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xlsx": { "version": "0.18.5", "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", @@ -8566,105 +7306,12 @@ "node": ">=0.8" } }, - "node_modules/xml-js": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", - "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", - "dependencies": { - "sax": "^1.2.4" - }, - "bin": { - "xml-js": "bin/cli.js" - } - }, - "node_modules/y-protocols": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz", - "integrity": "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==", - "dependencies": { - "lib0": "^0.2.85" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - }, - "peerDependencies": { - "yjs": "^13.0.0" - } - }, - "node_modules/y-webrtc": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/y-webrtc/-/y-webrtc-10.3.0.tgz", - "integrity": "sha512-KalJr7dCgUgyVFxoG3CQYbpS0O2qybegD0vI4bYnYHI0MOwoVbucED3RZ5f2o1a5HZb1qEssUKS0H/Upc6p1lA==", - "dependencies": { - "lib0": "^0.2.42", - "simple-peer": "^9.11.0", - "y-protocols": "^1.0.6" - }, - "bin": { - "y-webrtc-signaling": "bin/server.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - }, - "optionalDependencies": { - "ws": "^8.14.2" - }, - "peerDependencies": { - "yjs": "^13.6.8" - } - }, - "node_modules/y-webrtc/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "optional": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "node_modules/yjs": { - "version": "13.6.27", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.27.tgz", - "integrity": "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==", - "dependencies": { - "lib0": "^0.2.99" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -8737,16 +7384,6 @@ "semver": "^6.3.1" }, "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -8766,18 +7403,6 @@ "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/helper-annotate-as-pure": { @@ -8787,18 +7412,6 @@ "dev": true, "requires": { "@babel/types": "^7.27.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/helper-compilation-targets": { @@ -8891,28 +7504,16 @@ "requires": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/helper-module-imports": { - "version": "7.0.0-beta.35", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz", - "integrity": "sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "requires": { - "@babel/types": "7.0.0-beta.35", - "lodash": "^4.2.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" } }, "@babel/helper-module-transforms": { @@ -8924,28 +7525,6 @@ "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.27.3" - }, - "dependencies": { - "@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "requires": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - } - }, - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/helper-optimise-call-expression": { @@ -8955,18 +7534,6 @@ "dev": true, "requires": { "@babel/types": "^7.27.1" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/helper-plugin-utils": { @@ -9005,18 +7572,6 @@ "requires": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/helper-string-parser": { @@ -9044,18 +7599,6 @@ "@babel/template": "^7.27.1", "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/helpers": { @@ -9066,18 +7609,6 @@ "requires": { "@babel/template": "^7.27.2", "@babel/types": "^7.27.6" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/parser": { @@ -9086,17 +7617,6 @@ "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "requires": { "@babel/types": "^7.28.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { @@ -9212,28 +7732,6 @@ "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1" - }, - "dependencies": { - "@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "requires": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - } - }, - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/plugin-transform-block-scoped-functions": { @@ -9799,18 +8297,6 @@ "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", "esutils": "^2.0.2" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/runtime": { @@ -9827,18 +8313,6 @@ "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/traverse": { @@ -9854,29 +8328,15 @@ "@babel/template": "^7.27.2", "@babel/types": "^7.28.0", "debug": "^4.3.1" - }, - "dependencies": { - "@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - } - } } }, "@babel/types": { - "version": "7.0.0-beta.35", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.35.tgz", - "integrity": "sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w==", - "dev": true, + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", "requires": { - "esutils": "^2.0.2", - "lodash": "^4.2.0", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" } }, "@codemirror/state": { @@ -10229,33 +8689,12 @@ "dev": true, "optional": true }, - "@pdf-lib/standard-fonts": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", - "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", - "requires": { - "pako": "^1.0.6" - } - }, - "@pdf-lib/upng": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", - "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", - "requires": { - "pako": "^1.0.10" - } - }, "@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, - "@svgdotjs/svg.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.0.tgz", - "integrity": "sha512-Tr8p+QVP7y+QT1GBlq1Tt57IvedVH8zCPoYxdHLX0Oof3a/PqnC/tXAkVufv1JQJfsDHlH/UrjcDfgxSofqSNA==" - }, "@toast-ui/editor": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@toast-ui/editor/-/editor-3.2.2.tgz", @@ -10286,14 +8725,6 @@ "@types/tern": "*" } }, - "@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "requires": { - "@types/ms": "*" - } - }, "@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", @@ -10350,19 +8781,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "requires": { - "@types/unist": "^2" - } - }, - "@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" - }, "@types/node": { "version": "16.18.126", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", @@ -10378,11 +8796,6 @@ "@types/estree": "*" } }, - "@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, "@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -10624,26 +9037,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true }, - "acorn-loose": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-6.1.0.tgz", - "integrity": "sha512-FHhXoiF0Uch3IqsrnPpWwCtiv5PYvipTpT1k9lDMgQVVYc9iDuSl5zdJV358aI8twfHCYMFBRVYvAVki9wC/ng==", - "requires": { - "acorn": "^6.2.0" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" - } - } - }, - "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" - }, "adler-32": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", @@ -10789,6 +9182,29 @@ "dev": true, "requires": { "@babel/helper-module-imports": "7.0.0-beta.35" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.0.0-beta.35", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz", + "integrity": "sha512-vaC1KyIZSuyWb3Lj277fX0pxivyHwuDU4xZsofqgYAbkDxNieMg2vuhzP5AgMweMY7fCQUMTi+BgPqTLjkxXFg==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.35", + "lodash": "^4.2.0" + } + }, + "@babel/types": { + "version": "7.0.0-beta.35", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.35.tgz", + "integrity": "sha512-y9XT11CozHDgjWcTdxmhSj13rJVXpa5ZXwjjOiTedjaM0ba5ItqdS02t31EhPl7HtOWxsZkYCCUNrSfrOisA6w==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.2.0", + "to-fast-properties": "^2.0.0" + } + } } }, "babel-plugin-polyfill-corejs2": { @@ -10850,15 +9266,11 @@ } } }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true }, "big.js": { "version": "5.2.2", @@ -10878,15 +9290,6 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, - "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -10913,6 +9316,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -11010,11 +9414,6 @@ } } }, - "character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==" - }, "chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -11085,11 +9484,6 @@ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, "consolidate": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", @@ -11123,11 +9517,6 @@ "browserslist": "^4.25.0" } }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, "crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -11734,18 +10123,11 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, "requires": { "ms": "^2.1.3" } }, - "decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", - "requires": { - "character-entities": "^2.0.0" - } - }, "deepmerge": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", @@ -11762,11 +10144,6 @@ "gopd": "^1.0.1" } }, - "dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" - }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -11774,11 +10151,6 @@ "dev": true, "optional": true }, - "diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==" - }, "dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -11857,24 +10229,6 @@ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true }, - "enhanced-resolve": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz", - "integrity": "sha512-n6e4bsCpzsP0OB76X+vEWhySUQI8GHPVFVK+3QkX35tbryy2WoeGeK5kQ+oxzgDVHjIZyz5fyS60Mi3EpQLc0Q==", - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.3.0", - "object-assign": "^4.0.1", - "tapable": "^0.2.3" - }, - "dependencies": { - "tapable": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", - "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==" - } - } - }, "entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -11887,15 +10241,12 @@ "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", "dev": true }, - "err-code": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", - "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" - }, "errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, "requires": { "prr": "~1.0.1" } @@ -12001,11 +10352,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -12018,11 +10364,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" - }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -12091,11 +10432,6 @@ "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -12108,11 +10444,6 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, - "get-browser-rtc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", - "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==" - }, "get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -12141,19 +10472,6 @@ "es-object-atoms": "^1.0.0" } }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -12169,7 +10487,8 @@ "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "has-flag": { "version": "4.0.0", @@ -12226,7 +10545,8 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true }, "image-size": { "version": "0.5.5", @@ -12235,11 +10555,6 @@ "dev": true, "optional": true }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" - }, "immutable": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", @@ -12256,19 +10571,11 @@ "resolve-cwd": "^3.0.0" } }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "interpret": { "version": "3.1.1", @@ -12373,11 +10680,6 @@ "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", "dev": true }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -12390,11 +10692,6 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, - "isomorphic.js": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", - "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==" - }, "jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -12450,17 +10747,6 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, - "jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "requires": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, "katex": { "version": "0.16.9", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz", @@ -12482,11 +10768,6 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" - }, "klona": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", @@ -12527,6 +10808,12 @@ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "optional": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true } } }, @@ -12541,22 +10828,6 @@ "schema-utils": "^3.0.0" } }, - "lib0": { - "version": "0.2.114", - "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.114.tgz", - "integrity": "sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ==", - "requires": { - "isomorphic.js": "^0.2.4" - } - }, - "lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "requires": { - "immediate": "~3.0.5" - } - }, "lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", @@ -12609,22 +10880,12 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -12687,33 +10948,6 @@ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true }, - "mdast-util-from-markdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", - "requires": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "mdast-util-to-string": "^3.1.0", - "micromark": "^3.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "uvu": "^0.5.0" - } - }, - "mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "requires": { - "@types/mdast": "^3.0.0" - } - }, "mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -12726,15 +10960,6 @@ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", "dev": true }, - "memory-fs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", - "integrity": "sha512-QTNXnl79X97kZ9jJk/meJrtDuvgvRakX5LU7HZW1L7MsXHuSTwoMIzN9tOLLH3Xfsj/gbsSqX/ovnsqz246zKQ==", - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, "merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -12750,217 +10975,6 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", - "requires": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "micromark-core-commonmark": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", - "requires": { - "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "micromark-factory-destination": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", - "requires": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "micromark-factory-label": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", - "requires": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", - "requires": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "micromark-factory-title": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", - "requires": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "micromark-factory-whitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", - "requires": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "requires": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "micromark-util-chunked": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", - "requires": { - "micromark-util-symbol": "^1.0.0" - } - }, - "micromark-util-classify-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", - "requires": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "micromark-util-combine-extensions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", - "requires": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", - "requires": { - "micromark-util-symbol": "^1.0.0" - } - }, - "micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", - "requires": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "micromark-util-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==" - }, - "micromark-util-html-tag-name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==" - }, - "micromark-util-normalize-identifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", - "requires": { - "micromark-util-symbol": "^1.0.0" - } - }, - "micromark-util-resolve-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", - "requires": { - "micromark-util-types": "^1.0.0" - } - }, - "micromark-util-sanitize-uri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", - "requires": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "micromark-util-subtokenize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", - "requires": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==" - }, - "micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==" - }, "micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -13045,14 +11059,6 @@ } } }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -13070,15 +11076,11 @@ "resolved": "https://registry.npmjs.org/monkey-around/-/monkey-around-3.0.0.tgz", "integrity": "sha512-jL6uY2lEAoaHxZep1cNRkCZjoIWY4g5VYCjriEWmcyHU7w8NU1+JH57xE251UVTohK0lCxMjv0ZV4ByDLIXEpw==" }, - "mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==" - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "nanoid": { "version": "3.3.11", @@ -13125,11 +11127,6 @@ "boolbase": "^1.0.0" } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, "obsidian": { "version": "1.8.7", "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.8.7.tgz", @@ -13140,14 +11137,6 @@ "moment": "2.29.4" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, "orderedmap": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", @@ -13177,27 +11166,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "parchment": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", - "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==" - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -13210,17 +11184,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "pdf-lib": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", - "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==", - "requires": { - "@pdf-lib/standard-fonts": "^1.0.0", - "@pdf-lib/upng": "^1.0.1", - "pako": "^1.0.11", - "tslib": "^1.11.1" - } - }, "picocolors": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", @@ -13287,11 +11250,6 @@ "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", "optional": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, "prosemirror-commands": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.5.2.tgz", @@ -13370,7 +11328,9 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==" + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true }, "pseudomap": { "version": "1.0.2", @@ -13384,76 +11344,15 @@ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - }, - "quill": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", - "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", - "requires": { - "eventemitter3": "^5.0.1", - "lodash-es": "^4.17.21", - "parchment": "^3.0.0", - "quill-delta": "^5.1.0" - }, - "dependencies": { - "eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - } - } - }, - "quill-delta": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", - "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", - "requires": { - "fast-diff": "^1.3.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isequal": "^4.5.0" - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "requires": { "safe-buffer": "^5.1.0" } }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -13560,28 +11459,16 @@ } } }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" - }, "rope-sequence": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==" }, - "sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "requires": { - "mri": "^1.1.0" - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true }, "safe-regex-test": { "version": "1.1.0", @@ -13615,11 +11502,6 @@ "neo-async": "^2.6.2" } }, - "sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" - }, "schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -13660,11 +11542,6 @@ "has-property-descriptors": "^1.0.2" } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -13689,27 +11566,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "simple-mind-map": { - "version": "0.14.0-fix.1", - "resolved": "https://registry.npmjs.org/simple-mind-map/-/simple-mind-map-0.14.0-fix.1.tgz", - "integrity": "sha512-LuX2+32cS/lIB2AxmzkLZi5NHbrHuXBha3v0O376PE75K4ivAFoXYzJQ661/ls2E16ZOWwgvx9q4znt7jTBXxA==", - "requires": { - "@svgdotjs/svg.js": "3.2.0", - "deepmerge": "^1.5.2", - "eventemitter3": "^4.0.7", - "jszip": "^3.10.1", - "katex": "^0.16.8", - "mdast-util-from-markdown": "^1.3.0", - "pdf-lib": "^1.17.1", - "quill": "^2.0.3", - "tern": "^0.24.3", - "uuid": "^9.0.0", - "ws": "^7.5.9", - "xml-js": "^1.6.11", - "y-webrtc": "^10.2.5", - "yjs": "^13.6.8" - } - }, "simple-mind-map-plugin-themes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/simple-mind-map-plugin-themes/-/simple-mind-map-plugin-themes-1.0.0.tgz", @@ -13718,32 +11574,6 @@ "esbuild": "^0.17.15" } }, - "simple-peer": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", - "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", - "requires": { - "buffer": "^6.0.3", - "debug": "^4.3.2", - "err-code": "^3.0.1", - "get-browser-rtc": "^1.1.0", - "queue-microtask": "^1.2.3", - "randombytes": "^2.1.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -13799,6 +11629,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -13854,27 +11685,6 @@ "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true }, - "tern": { - "version": "0.24.3", - "resolved": "https://registry.npmjs.org/tern/-/tern-0.24.3.tgz", - "integrity": "sha512-Z8uvtdWIlFn1GWy0HW5FhZ8VDryZwoJUdnjZU25C7/PBOltLIn1uv+WF3rVq6S1761YbsmbZYRP/l0ZJBCkvrw==", - "requires": { - "acorn": "^6.0.0", - "acorn-loose": "^6.0.0", - "acorn-walk": "^6.0.0", - "enhanced-resolve": "^2.2.2", - "glob": "^7.1.1", - "minimatch": "^3.0.3", - "resolve-from": "2.0.0" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" - } - } - }, "terser": { "version": "5.39.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", @@ -13970,11 +11780,6 @@ "is-number": "^7.0.0" } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -14022,14 +11827,6 @@ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true }, - "unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "requires": { - "@types/unist": "^2.0.0" - } - }, "update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -14084,23 +11881,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", - "requires": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - } + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "v-viewer": { "version": "1.7.4", @@ -14448,17 +12230,6 @@ "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==" }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "requires": {} - }, "xlsx": { "version": "0.18.5", "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", @@ -14473,56 +12244,12 @@ "word": "~0.3.0" } }, - "xml-js": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", - "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", - "requires": { - "sax": "^1.2.4" - } - }, - "y-protocols": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz", - "integrity": "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==", - "requires": { - "lib0": "^0.2.85" - } - }, - "y-webrtc": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/y-webrtc/-/y-webrtc-10.3.0.tgz", - "integrity": "sha512-KalJr7dCgUgyVFxoG3CQYbpS0O2qybegD0vI4bYnYHI0MOwoVbucED3RZ5f2o1a5HZb1qEssUKS0H/Upc6p1lA==", - "requires": { - "lib0": "^0.2.42", - "simple-peer": "^9.11.0", - "ws": "^8.14.2", - "y-protocols": "^1.0.6" - }, - "dependencies": { - "ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "optional": true, - "requires": {} - } - } - }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "yjs": { - "version": "13.6.27", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.27.tgz", - "integrity": "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==", - "requires": { - "lib0": "^0.2.99" - } - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/plugin/package.json b/plugin/package.json index 4aa2a86..540a980 100644 --- a/plugin/package.json +++ b/plugin/package.json @@ -1,5 +1,5 @@ { - "name": "obsidian-simple-mind-map", + "name": "simple-mind-map", "version": "0.1.0", "private": true, "scripts": { @@ -45,7 +45,6 @@ "katex": "^0.16.9", "lz-string": "^1.5.0", "monkey-around": "^3.0.0", - "simple-mind-map": "^0.14.0-fix.1", "simple-mind-map-plugin-themes": "^1.0.0", "v-viewer": "^1.6.4", "vue": "^2.6.14", diff --git a/plugin/src/assets/icon-font/iconfont.css b/plugin/src/assets/icon-font/iconfont.css index 435e459..de81f0d 100644 --- a/plugin/src/assets/icon-font/iconfont.css +++ b/plugin/src/assets/icon-font/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 2479351 */ - src: url('iconfont.woff2?t=1753156289768') format('woff2'), - url('iconfont.woff?t=1753156289768') format('woff'), - url('iconfont.ttf?t=1753156289768') format('truetype'); + src: url('iconfont.woff2?t=1764835435069') format('woff2'), + url('iconfont.woff?t=1764835435069') format('woff'), + url('iconfont.ttf?t=1764835435069') format('truetype'); } .iconfont { @@ -13,6 +13,78 @@ -moz-osx-font-smoothing: grayscale; } +.iconfour-squares:before { + content: "\ea3e"; +} + +.iconyousuojin:before { + content: "\e6f0"; +} + +.icondaimakuai:before { + content: "\e65d"; +} + +.iconcharulianjie:before { + content: "\ec7f"; +} + +.iconcharutupian:before { + content: "\ec81"; +} + +.iconwuxupailie:before { + content: "\ec82"; +} + +.iconyinyong:before { + content: "\ec88"; +} + +.iconyouxupailie:before { + content: "\ec89"; +} + +.iconzitidaima:before { + content: "\ec8a"; +} + +.iconzitishangbiao:before { + content: "\ec8b"; +} + +.iconzitibiaoti:before { + content: "\ec8c"; +} + +.iconzitixiabiao:before { + content: "\ec8d"; +} + +.iconbeijingyanse1:before { + content: "\e645"; +} + +.icondocdocx:before { + content: "\e635"; +} + +.iconsousuo1:before { + content: "\e661"; +} + +.icondodechild:before { + content: "\e70e"; +} + +.iconbofang:before { + content: "\e8a3"; +} + +.iconkuangxuan:before { + content: "\e624"; +} + .iconcaidan:before { content: "\e630"; } diff --git a/plugin/src/assets/icon-font/iconfont.ttf b/plugin/src/assets/icon-font/iconfont.ttf index e63c2ad456a695a6395f6c5d8f6d79cca3e56c67..7c1923d13737d75c10d410f04450969ec3849760 100644 GIT binary patch delta 6421 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 delta 2848 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 Tm-S0@ddqjXvhpw8fK~y+FV%am delta 26319 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≥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 W^(0)YU#8PrKZ925AE#3SJOBVIHQG@C diff --git a/plugin/src/assets/icon-font/iconfont.woff2 b/plugin/src/assets/icon-font/iconfont.woff2 index b58d9bdd7da9b2ffa634b710a63eee85d7653f9d..61354d63093f6a57b75bc70d07402534f0e1e10f 100644 GIT binary patch literal 24220 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 D5%S%w literal 22620 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 diff --git a/plugin/src/assets/img/foramt/8.png b/plugin/src/assets/img/foramt/8.png deleted file mode 100644 index 8de0a046dec5e11653f8b7902480b2071678d5b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1946 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 diff --git a/plugin/src/assets/img/structures/rightFishbone2.jpg b/plugin/src/assets/img/structures/rightFishbone2.jpg deleted file mode 100644 index aa6eec580553f3d1c86a52d8db22f476ceb70b76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9709 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 O|KX(n9oFx7;C}!|UxJ(f diff --git a/plugin/src/components/ImgUpload/index.vue b/plugin/src/components/ImgUpload/index.vue index 049ca7d..db6d2bf 100644 --- a/plugin/src/components/ImgUpload/index.vue +++ b/plugin/src/components/ImgUpload/index.vue @@ -1,5 +1,9 @@ + + diff --git a/plugin/src/pages/Edit/components/Outline.vue b/plugin/src/pages/Edit/components/Outline.vue index d586ddf..6a4e82a 100644 --- a/plugin/src/pages/Edit/components/Outline.vue +++ b/plugin/src/pages/Edit/components/Outline.vue @@ -45,8 +45,9 @@ import { htmlEscape, handleInputPasteText } from 'simple-mind-map/src/utils' +import { linkRichToObUrlText, obUrlToLinkRich } from '@/utils' +import CursorTextHandler from '@/utils/CursorTextHandler' -// 大纲树 export default { props: { mindMap: { @@ -65,7 +66,8 @@ export default { beInsertNodeUid: '', insertType: '', isInTreArea: false, - isAfterCreateNewNode: false + isAfterCreateNewNode: false, + beingSplitNodeContent: '' } }, computed: { @@ -98,7 +100,6 @@ export default { }, handleDataChange() { - // 在大纲里操作节点时不要响应该事件,否则会重新刷新树 if (this.notHandleDataChange) { this.notHandleDataChange = false this.isAfterCreateNewNode = false @@ -112,13 +113,11 @@ export default { }, handleNodeTreeRenderEnd() { - // 当前存在未完成的节点插入操作 if (this.insertType) { this[this.insertType]() this.insertType = '' return } - // 插入了新节点后需要做一些操作 if (this.isHandleNodeTreeRenderEnd) { this.isHandleNodeTreeRenderEnd = false this.refresh() @@ -128,17 +127,17 @@ export default { } }, - // 刷新树数据 refresh() { + this.fileNameToPath = {} let data = this.mindMap.getData() - data.root = true // 标记根节点 + data.root = true let walk = root => { let text = root.data.richText - ? nodeRichTextToTextWithWrap(root.data.text) + ? nodeRichTextToTextWithWrap(linkRichToObUrlText(root.data.text)) : root.data.text text = htmlEscape(text) text = text.replace(/\n/g, '
') - root.textCache = text // 保存一份修改前的数据,用于对比是否修改了 + root.textCache = text root.label = text root.uid = root.data.uid if (root.children && root.children.length > 0) { @@ -148,23 +147,24 @@ export default { } } walk(data) - this.data = [data] + if (data.data.freeNodeTrees && data.data.freeNodeTrees.length > 0) { + data.data.freeNodeTrees.forEach(item => { + item.root = true + walk(item) + }) + } + this.data = [data, ...data.data.freeNodeTrees] }, - // 插入了新节点之后 afterCreateNewNode() { - // 如果是新插入节点,那么需要手动高亮该节点、定位该节点及聚焦 let id = this.beInsertNodeUid if (id && this.$refs.tree) { try { this.isAfterCreateNewNode = true - // 高亮树节点 this.$refs.tree.setCurrentKey(id) let node = this.$refs.tree.getNode(id) this.onCurrentChange(node.data) - // 定位该节点 this.onClick(node.data) - // 聚焦该树节点的编辑框 const el = document.querySelector( `.smmOutlineTreeCustomNode[data-id="${id}"] .smmOutlineTreeCustomNodeEdit` ) @@ -177,90 +177,113 @@ export default { let offsetTop = el.offsetTop this.$emit('scrollTo', offsetTop) } - } catch (error) { - console.log(error) - } + } catch (error) {} } this.beInsertNodeUid = '' }, - // 根节点不允许拖拽 checkAllowDrag(node) { return !node.data.root }, - // 失去焦点更新节点文本 onBlur(e, node) { - // 节点数据没有修改 if (node.data.textCache === e.target.innerHTML) { - // 如果存在未执行的插入新节点操作,那么直接执行 if (this.insertType) { this[this.insertType]() this.insertType = '' } return } - // 否则插入新节点操作需要等待当前修改事件渲染完成后再执行 const richText = node.data.data.richText let text = richText ? e.target.innerHTML : e.target.innerText const targetNode = this.mindMap.renderer.findNodeByUid(node.data.uid) if (!targetNode) return - this.notHandleDataChange = true + this.notHandleDataChange = !this.insertType if (richText) { - targetNode.setText(textToNodeRichTextWithWrap(text), true) + text = textToNodeRichTextWithWrap(text) + text = obUrlToLinkRich(text) + targetNode.setText(text, true) } else { targetNode.setText(text) } }, - // 拦截粘贴事件 onPaste(e) { handleInputPasteText(e) }, - // 生成唯一的key getKey() { return Math.random() }, - // 节点输入区域按键事件 onNodeInputKeydown(e) { if (e.keyCode === 13 && !e.shiftKey) { - // 插入兄弟节点 e.preventDefault() - this.insertType = 'insertNode' + this.insertType = e.ctrlKey ? 'splitInsertNode' : 'insertNode' + if (e.ctrlKey) { + const cursorTextHandler = new CursorTextHandler(e.target) + const afterText = cursorTextHandler.getTextAfterCursor() + if (!afterText) { + return + } + const beforeText = cursorTextHandler.getTextBeforeCursor() + e.target.innerHTML = beforeText + this.beingSplitNodeContent = afterText + } e.target.blur() } if (e.keyCode === 9) { e.preventDefault() if (e.shiftKey) { - // 节点上升一级 this.insertType = 'moveUp' e.target.blur() } else { - // 插入子节点 - this.insertType = 'insertChildNode' + this.insertType = 'moveDown' e.target.blur() } } }, - // 节点上移一个层级 moveUp() { this.mindMap.execCommand('MOVE_UP_ONE_LEVEL') }, - // 插入兄弟节点 - insertNode() { + moveDown() { + this.mindMap.execCommand('MOVE_DOWN_ONE_LEVEL') + }, + + splitInsertNode() { + if (!this.beingSplitNodeContent) { + return + } this.notHandleDataChange = true this.isHandleNodeTreeRenderEnd = true this.beInsertNodeUid = createUid() + const richText = !!this.mindMap.richText this.mindMap.execCommand('INSERT_NODE', false, [], { + uid: this.beInsertNodeUid, + text: richText + ? textToNodeRichTextWithWrap(this.beingSplitNodeContent) + : this.beingSplitNodeContent, + richText + }) + this.beingSplitNodeContent = '' + }, + + insertNode() { + const activeNode = this.mindMap.renderer.getActiveNodeList()[0] + let commandName = 'INSERT_NODE' + if (activeNode && activeNode.isRoot) { + commandName = 'INSERT_CHILD_NODE' + } + this.notHandleDataChange = true + this.isHandleNodeTreeRenderEnd = true + this.beInsertNodeUid = createUid() + this.mindMap.execCommand(commandName, false, [], { uid: this.beInsertNodeUid }) }, - // 插入下级节点 insertChildNode() { this.notHandleDataChange = true this.isHandleNodeTreeRenderEnd = true @@ -270,17 +293,15 @@ export default { }) }, - // 激活当前节点且移动当前节点到画布中间 onClick(data) { - this.notHandleDataChange = true const targetNode = this.mindMap.renderer.findNodeByUid(data.uid) if (targetNode && targetNode.nodeData.data.isActive) return + this.notHandleDataChange = true this.mindMap.execCommand('GO_TARGET_NODE', data.uid, () => { this.notHandleDataChange = false }) }, - // 拖拽结束事件 onNodeDrop(data, target, postion) { this.notHandleDataChange = true const node = this.mindMap.renderer.findNodeByUid(data.data.uid) @@ -303,12 +324,10 @@ export default { } }, - // 当前选中的树节点变化事件 onCurrentChange(data) { this.currentData = data }, - // 删除节点 onKeyDown(e) { if (!this.isInTreArea) return if ([46, 8].includes(e.keyCode) && this.currentData) { diff --git a/plugin/src/pages/Edit/components/OutlineEdit.vue b/plugin/src/pages/Edit/components/OutlineEdit.vue index f6f1fa5..27ad9b8 100644 --- a/plugin/src/pages/Edit/components/OutlineEdit.vue +++ b/plugin/src/pages/Edit/components/OutlineEdit.vue @@ -70,10 +70,15 @@ import { htmlEscape, handleInputPasteText } from 'simple-mind-map/src/utils' -import { printOutline } from '@/utils' +import { + printOutline, + linkRichToObUrlText, + obUrlToLinkRich, + parseInnerLinkAndText +} from '@/utils' import Import from './Import.vue' +import CursorTextHandler from '@/utils/CursorTextHandler' -// 大纲侧边栏 export default { components: { Import @@ -125,7 +130,6 @@ export default { this.$root.$bus.$off('printOutline', this.onPrint) }, methods: { - // 获取初始数据 getData() { this.mindMapData = JSON.parse( this.$root.$obsidianAPI.getInitMindMapData() @@ -134,20 +138,19 @@ export default { this.mindMapDataToTree(rootData) }, - // 思维导图数据转换为树结构 mindMapDataToTree(rootData, callback = () => {}) { this.currentData = null this.currentNode = null this.treeData = [] this.$nextTick(() => { - rootData.root = true // 标记根节点 + rootData.root = true let walk = root => { let text = root.data.richText - ? nodeRichTextToTextWithWrap(root.data.text) + ? nodeRichTextToTextWithWrap(linkRichToObUrlText(root.data.text)) : root.data.text text = htmlEscape(text) text = text.replace(/\n/g, '
') - root.textCache = text // 保存一份修改前的数据,用于对比是否修改了 + root.textCache = text root.label = text root.uid = root.data.uid if (root.children && root.children.length > 0) { @@ -157,54 +160,57 @@ export default { } } walk(rootData) - this.treeData = [rootData] + const freeNodeTrees = rootData.data.freeNodeTrees || [] + delete rootData.data.freeNodeTrees + if (freeNodeTrees && freeNodeTrees.length > 0) { + freeNodeTrees.forEach(item => { + item.root = true + walk(item) + }) + } + this.treeData = [rootData, ...freeNodeTrees] callback() }) }, - // 根节点不允许拖拽 checkAllowDrag(node) { return !node.data.root }, - // 拖拽结束事件 onNodeDrop() { this.autoSave() }, - // 当前选中的树节点变化事件 onCurrentChange(data, node) { this.currentData = data this.currentNode = node }, - // 失去焦点更新节点文本 onBlur(e, node) { - // 节点数据没有修改 if (node.data.textCache === e.target.innerHTML) { return } const richText = node.data.data.richText let text = richText ? e.target.innerHTML : e.target.innerText if (richText) { - text = textToNodeRichTextWithWrap(text) + let text2 = textToNodeRichTextWithWrap(text) + text2 = obUrlToLinkRich(text2) + node.data.data.text = text2 } - node.data.data.text = text + node.data.label = text node.data.textCache = e.target.innerHTML this.autoSave() }, - // 节点输入区域按键事件 onNodeInputKeydown(e, node) { const richText = !!node.data.data.richText const uid = createUid() - const text = this.$t('outline.nodeDefaultText') const data = { - textCache: text, uid, - label: text, + textCache: '', + label: '', data: { - text: richText ? textToNodeRichTextWithWrap(text) : text, + text: '', uid, richText }, @@ -212,20 +218,51 @@ export default { } if (e.keyCode === 13 && !e.shiftKey) { e.preventDefault() - if (node.data.root) { - return + if (e.ctrlKey) { + const cursorTextHandler = new CursorTextHandler(e.target) + const afterText = cursorTextHandler.getTextAfterCursor() + if (!afterText) { + return + } + const beforeText = cursorTextHandler.getTextBeforeCursor() + e.target.innerHTML = beforeText + data.label = afterText + data.textCache = afterText + data.data.text = richText + ? textToNodeRichTextWithWrap(afterText) + : afterText + this.$refs.tree.insertAfter(data, node) + } else { + const text = this.$t('outline.nodeDefaultText') + data.label = text + data.textCache = text + data.data.text = richText ? textToNodeRichTextWithWrap(text) : text + if (node.data.root) { + this.$refs.tree.append(data, node) + } else { + this.$refs.tree.insertAfter(data, node) + } } - this.$refs.tree.insertAfter(data, node) } if (e.keyCode === 9) { e.preventDefault() - if (e.shiftKey) { - // 上移一个层级 - this.$refs.tree.insertAfter(node.data, node.parent) - this.$refs.tree.remove(node) - } else { - this.$refs.tree.append(data, node) + if (node.data.root) { + return } + if (e.shiftKey) { + this.onBlur(e, node) + this.$refs.tree.insertAfter(node.data, node.parent) + } else { + const index = node.parent.childNodes.findIndex(item => { + return item === node + }) + if (index <= 0) return + const prevNode = node.parent.childNodes[index - 1] + if (prevNode) { + this.$refs.tree.append(node.data, prevNode) + } + } + this.$refs.tree.remove(node) } this.autoSave() this.$nextTick(() => { @@ -245,7 +282,6 @@ export default { }) }, - // 删除节点 onKeyDown(e) { if ([46, 8].includes(e.keyCode) && this.currentData) { e.stopPropagation() @@ -256,22 +292,18 @@ export default { } }, - // 拦截粘贴事件 onPaste(e) { handleInputPasteText(e) }, - // 生成唯一的key getKey() { return Math.random() }, - // 打印 onPrint() { printOutline(this.$refs.smmOutlineEditBox) }, - // 滚动 scrollTo(y) { let container = this.$refs.smmOutlineEditBox let height = container.offsetHeight @@ -282,7 +314,6 @@ export default { } }, - // 导入数据 onImportData(data) { let rootNodeData = null if (data.root) { @@ -295,7 +326,6 @@ export default { }) }, - // 获取当前编辑中的思维导图数据 getCurrentData() { let newNode = {} let node = this.treeData[0] @@ -309,23 +339,37 @@ export default { }) } walk(node, newNode) + const freeNodeTrees = [] + if (this.treeData.length > 1) { + this.treeData.slice(1).forEach(item => { + const newNode = {} + freeNodeTrees.push(newNode) + walk(item, newNode) + }) + newNode.data.freeNodeTrees = freeNodeTrees + } return simpleDeepClone(newNode) }, - // 发送最新数据给ob保存 emitMindMapCurrentData() { try { const curData = { ...this.mindMapData, root: this.getCurrentData() } - this.$root.$obsidianAPI.getMindMapCurrentData(JSON.stringify(curData)) + const { linkData, textData } = parseInnerLinkAndText( + curData, + this.$root.$obsidianAPI + ) + this.$root.$obsidianAPI.getMindMapCurrentData( + JSON.stringify(curData), + linkData, + textData + ) } catch (error) { - console.log(error) } }, - // 自动保存 autoSave() { this.$root.$bus.$emit('data_change') clearTimeout(this.autoSaveTimer) @@ -334,29 +378,24 @@ export default { }, this.autoSaveTime * 1000) }, - // 取消当前自动保存 clearAutoSave() { clearTimeout(this.autoSaveTimer) }, - // 手动触发保存 manuallySave() { clearTimeout(this.autoSaveTimer) this.saveToLocal() }, - // 保存 saveToLocal() { this.$root.$obsidianAPI.saveMindMapData() }, - // 从obsidian获取数据后更新思维导图数据 onUpdateMindMapDataFromOb(data) { try { data = JSON.parse(data) this.mindMapDataToTree(data.root) } catch (e) { - console.log(e) } }, @@ -495,7 +534,6 @@ export default { /deep/ .smmOutlineTreeCustomNode { .smmOutlineTreeCustomNodeEdit { - // max-width: 800px; } } } diff --git a/plugin/src/pages/Edit/components/OutlineSidebar.vue b/plugin/src/pages/Edit/components/OutlineSidebar.vue index 74f0513..cb5e241 100644 --- a/plugin/src/pages/Edit/components/OutlineSidebar.vue +++ b/plugin/src/pages/Edit/components/OutlineSidebar.vue @@ -26,7 +26,6 @@ import { mapState, mapMutations } from 'vuex' import Outline from './Outline.vue' import { printOutline } from '@/utils' -// 大纲侧边栏 export default { components: { Sidebar, @@ -64,7 +63,6 @@ export default { } }, - // 打印 onPrint() { printOutline(this.$refs.outlineRef.$el) } diff --git a/plugin/src/pages/Edit/components/RichTextToolbar.vue b/plugin/src/pages/Edit/components/RichTextToolbar.vue index 3d1b54c..a339c64 100644 --- a/plugin/src/pages/Edit/components/RichTextToolbar.vue +++ b/plugin/src/pages/Edit/components/RichTextToolbar.vue @@ -159,11 +159,13 @@