From 5a56fbc532436cff445cb65daf0a283ba82c7966 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: Sun, 25 Jan 2026 13:20:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dob=E5=AE=A1=E6=A0=B8=E6=8F=90?= =?UTF-8?q?=E5=87=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin/SmmEditView.js | 39 ++++++-------- plugin/main.js | 1 - plugin/ob/MarkdownPostProcessor.js | 8 +-- plugin/ob/Menus.js | 8 ++- plugin/ob/PreviewMindMap.js | 10 +--- plugin/ob/SmmSettingTab.js | 87 ++++++++++++++++-------------- plugin/src/utils/index.js | 5 +- plugin/style.css | 57 ++++++++++++++++++-- 8 files changed, 129 insertions(+), 86 deletions(-) diff --git a/plugin/SmmEditView.js b/plugin/SmmEditView.js index f1e8ebf..16db89e 100644 --- a/plugin/SmmEditView.js +++ b/plugin/SmmEditView.js @@ -31,11 +31,7 @@ class SmmEditView extends TextFileView { this.plugin = plugin this.contentEl.style.padding = 0 this.warpEl = this.contentEl.createDiv('smmMindmapEditContainer') - this.warpEl.style.cssText = ` - width: 100%; - height: 100%; - overflow: hidden; - ` + this.warpEl.classList.add('smm-common-full-size') this.mindMapData = '' this.parsedMindMapData = null this.mindMapAPP = null @@ -182,11 +178,7 @@ class SmmEditView extends TextFileView { _renderMindMap() { this.warpEl.empty() const el = this.warpEl.createDiv('smmMindMapEdit') - el.style.cssText = ` - width: 100%; - height: 100%; - overflow: hidden; - ` + el.classList.add('smm-common-full-size') this._clearObserver() this.resizeObserver = new ResizeObserver(entries => { for (const entry of entries) { @@ -455,7 +447,7 @@ class SmmEditView extends TextFileView { if (!cover) { let counter = 1 while ( - await this.app.vault.adapter.exists( + this.app.vault.getFileByPath( folder ? `${folder}/${fileName}` : fileName ) ) { @@ -631,16 +623,6 @@ class SmmEditView extends TextFileView { this.toggleReadonlyButton = null } - _debounce(func, wait) { - let timeout - return () => { - clearTimeout(timeout) - timeout = setTimeout(() => { - func.call(this) - }, wait) - } - } - _addActionBtns() { const viewActions = this.headerEl.querySelector('.view-actions') @@ -747,6 +729,7 @@ class SmmEditView extends TextFileView { this.forceSaveAndUpdateImage() } ) + this.saveButton.classList.add('smm-save-button-default') this.savingTipEl = this.headerEl.createEl('div', { cls: 'smm-save-tip' @@ -794,20 +777,28 @@ class SmmEditView extends TextFileView { _showButtons(list) { list.forEach(el => { if (!el) return - el.style.display = 'flex' + el.classList.remove('smm-common-hide') + el.classList.add('smm-common-flex') }) } _hideButtons(list) { list.forEach(el => { if (!el) return - el.style.display = 'none' + el.classList.remove('smm-common-flex') + el.classList.add('smm-common-hide') }) } _setIsUnSave(isUnSave) { this.isUnSave = isUnSave - this.saveButton.style.color = isUnSave ? '#ff6600' : 'var(--icon-color)' + if (isUnSave) { + this.saveButton.classList.remove('smm-save-button-default') + this.saveButton.classList.add('smm-save-button-un-save') + } else { + this.saveButton.classList.remove('smm-save-button-un-save') + this.saveButton.classList.add('smm-save-button-default') + } } _initThemeMode() { diff --git a/plugin/main.js b/plugin/main.js index 1202dea..987ffa6 100644 --- a/plugin/main.js +++ b/plugin/main.js @@ -433,7 +433,6 @@ 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/MarkdownPostProcessor.js b/plugin/ob/MarkdownPostProcessor.js index fbb0c0f..444d6fd 100644 --- a/plugin/ob/MarkdownPostProcessor.js +++ b/plugin/ob/MarkdownPostProcessor.js @@ -17,9 +17,11 @@ export default class MarkdownPostProcessor { 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) + plugin.registerEvent(plugin.app.vault.on('modify', this.handleFileModify)) + plugin.registerEvent(plugin.app.vault.on('delete', this.handleFileDelete)) + plugin.registerEvent( + plugin.app.vault.on('rename', this.handleModifySvgName) + ) } destroy() { diff --git a/plugin/ob/Menus.js b/plugin/ob/Menus.js index cf4af56..fab3541 100644 --- a/plugin/ob/Menus.js +++ b/plugin/ob/Menus.js @@ -122,7 +122,9 @@ export default class Menus { break } } - await this.app.vault.modify(renamedFile, mdStr) + await this.app.vault.process(renamedFile, () => { + return mdStr + }) this.app.noSaveOnClose = false const ref = this.app.metadataCache.on( 'changed', @@ -252,7 +254,9 @@ export default class Menus { break } } - await this.app.vault.modify(renamedFile, str) + await this.app.vault.process(renamedFile, () => { + return str + }) const ref = this.app.metadataCache.on( 'changed', changedFile => { diff --git a/plugin/ob/PreviewMindMap.js b/plugin/ob/PreviewMindMap.js index 54b729d..f9effa6 100644 --- a/plugin/ob/PreviewMindMap.js +++ b/plugin/ob/PreviewMindMap.js @@ -11,15 +11,7 @@ export class PreviewMindMap { this.container = document.createElement('div') this.wrap = document.createElement('div') this.container.appendChild(this.wrap) - this.container.style.cssText = ` - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 50; - background: rgba(0, 0, 0, 0.5); - ` + this.container.classList.add('smm-preview-md-to-mindmap-container') document.body.appendChild(this.container) this._renderView() } diff --git a/plugin/ob/SmmSettingTab.js b/plugin/ob/SmmSettingTab.js index 9280c28..61e1794 100644 --- a/plugin/ob/SmmSettingTab.js +++ b/plugin/ob/SmmSettingTab.js @@ -1,4 +1,4 @@ -import { PluginSettingTab, Setting, Notice } from 'obsidian' +import { PluginSettingTab, Setting, Notice, normalizePath } from 'obsidian' import themeList from 'simple-mind-map-plugin-themes/themeList' import { layoutGroupList } from '../src/config' import { GITHUB_ICON, COMMUNITY_ICON } from './constant' @@ -46,16 +46,12 @@ export default class SmmSettingTab extends PluginSettingTab { this._addEmbedSetting() - this._addOtherSetting() - 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')) @@ -170,7 +166,7 @@ export default class SmmSettingTab extends PluginSettingTab { _addFileSaveSetting() { const { containerEl } = this - containerEl.createEl('h2', { text: this.plugin._t('setting.title.title2') }) + this._setHeader(containerEl, this.plugin._t('setting.title.title2')) new Setting(containerEl) .setName(this.plugin._t('setting.file.title1')) @@ -242,11 +238,11 @@ export default class SmmSettingTab extends PluginSettingTab { .setDesc(this.plugin._t('setting.folder.desc1')) .addText(text => { text.setValue(this.plugin.settings.filePath).onChange(async value => { - this.plugin.settings.filePath = value + this.plugin.settings.filePath = normalizePath(value) await this.plugin._saveSettings() }) this._addFolderSelectBtn(text, selected => { - this.plugin.settings.filePath = selected + this.plugin.settings.filePath = normalizePath(selected) this.plugin._saveSettings() }) }) @@ -273,11 +269,11 @@ export default class SmmSettingTab extends PluginSettingTab { .setDesc(this.plugin._t('setting.folder.desc2')) .addText(text => { text.setValue(this.plugin.settings.imagePath).onChange(async value => { - this.plugin.settings.imagePath = value + this.plugin.settings.imagePath = normalizePath(value) await this.plugin._saveSettings() }) this._addFolderSelectBtn(text, selected => { - this.plugin.settings.imagePath = selected + this.plugin.settings.imagePath = normalizePath(selected) this.plugin._saveSettings() }) }) @@ -289,11 +285,11 @@ export default class SmmSettingTab extends PluginSettingTab { text .setValue(this.plugin.settings.imageSubPath) .onChange(async value => { - this.plugin.settings.imageSubPath = value + this.plugin.settings.imageSubPath = normalizePath(value) await this.plugin._saveSettings() }) this._addFolderSelectBtn(text, selected => { - this.plugin.settings.imageSubPath = selected + this.plugin.settings.imageSubPath = normalizePath(selected) this.plugin._saveSettings() }) }) @@ -322,11 +318,11 @@ export default class SmmSettingTab extends PluginSettingTab { text .setValue(this.plugin.settings.attachmentPath) .onChange(async value => { - this.plugin.settings.attachmentPath = value + this.plugin.settings.attachmentPath = normalizePath(value) await this.plugin._saveSettings() }) this._addFolderSelectBtn(text, selected => { - this.plugin.settings.attachmentPath = selected + this.plugin.settings.attachmentPath = normalizePath(selected) this.plugin._saveSettings() }) }) @@ -393,7 +389,7 @@ export default class SmmSettingTab extends PluginSettingTab { _addCompressSetting() { const { containerEl } = this - containerEl.createEl('h2', { text: this.plugin._t('setting.title.title3') }) + this._setHeader(containerEl, this.plugin._t('setting.title.title3')) new Setting(containerEl) .setName(this.plugin._t('setting.compress.title1')) @@ -494,7 +490,7 @@ export default class SmmSettingTab extends PluginSettingTab { _addEmbedSetting() { const { containerEl } = this - containerEl.createEl('h2', { text: this.plugin._t('setting.title.title4') }) + this._setHeader(containerEl, this.plugin._t('setting.title.title4')) new Setting(containerEl) .setName(this.plugin._t('setting.embed.title3')) @@ -612,72 +608,76 @@ export default class SmmSettingTab extends PluginSettingTab { _updateEmbedImageFileFolderSettingsVisibility() { const isVisible = this.plugin.settings.embedImageIsSeparateFile if (this.embedImageIsSeparateFileFolderSettings) { - this.embedImageIsSeparateFileFolderSettings.settingEl.style.display = isVisible - ? '' - : 'none' + this.embedImageIsSeparateFileFolderSettings.settingEl.classList[ + isVisible ? 'remove' : 'add' + ]('smm-setting-item-hide') } } _updateFilePathSettingsVisibility() { const isVisible = this.plugin.settings.filePathType === 'custom' if (this.filePathSettings) { - this.filePathSettings.settingEl.style.display = isVisible ? '' : 'none' + this.filePathSettings.settingEl.classList[isVisible ? 'remove' : 'add']( + 'smm-setting-item-hide' + ) } } _updateImagePathSettingsVisibility() { const isVisible = this.plugin.settings.imagePathType === 'custom' if (this.imagePathSettings) { - this.imagePathSettings.settingEl.style.display = isVisible ? '' : 'none' + this.imagePathSettings.settingEl.classList[isVisible ? 'remove' : 'add']( + 'smm-setting-item-hide' + ) } const isVisibleSub = this.plugin.settings.imagePathType === 'currentFileFolderSubFolder' if (this.imageSubPathSettings) { - this.imageSubPathSettings.settingEl.style.display = isVisibleSub - ? '' - : 'none' + this.imageSubPathSettings.settingEl.classList[ + isVisibleSub ? 'remove' : 'add' + ]('smm-setting-item-hide') } } _updateAttachmentPathSettingsVisibility() { const isVisible = this.plugin.settings.attachmentPathType === 'custom' if (this.attachmentPathSettings) { - this.attachmentPathSettings.settingEl.style.display = isVisible - ? '' - : 'none' + this.attachmentPathSettings.settingEl.classList[ + isVisible ? 'remove' : 'add' + ]('smm-setting-item-hide') } const isVisibleSub = this.plugin.settings.attachmentPathType === 'currentFileFolderSubFolder' if (this.attachmentSubPathSettings) { - this.attachmentSubPathSettings.settingEl.style.display = isVisibleSub - ? '' - : 'none' + this.attachmentSubPathSettings.settingEl.classList[ + isVisibleSub ? 'remove' : 'add' + ]('smm-setting-item-hide') } } _updateCompressImageSettingsVisibility() { const isVisible = this.plugin.settings.compressImage if (this.compressImageOptionsMaxWidthSettings) { - this.compressImageOptionsMaxWidthSettings.settingEl.style.display = isVisible - ? '' - : 'none' + this.compressImageOptionsMaxWidthSettings.settingEl.classList[ + isVisible ? 'remove' : 'add' + ]('smm-setting-item-hide') } if (this.compressImageOptionsMaxHeightSettings) { - this.compressImageOptionsMaxHeightSettings.settingEl.style.display = isVisible - ? '' - : 'none' + this.compressImageOptionsMaxHeightSettings.settingEl.classList[ + isVisible ? 'remove' : 'add' + ]('smm-setting-item-hide') } if (this.compressImageOptionsQualitySettings) { - this.compressImageOptionsQualitySettings.settingEl.style.display = isVisible - ? '' - : 'none' + this.compressImageOptionsQualitySettings.settingEl.classList[ + isVisible ? 'remove' : 'add' + ]('smm-setting-item-hide') } } _addImageHostingSetting() { const { containerEl } = this - containerEl.createEl('h2', { text: this.plugin._t('setting.title.title6') }) + this._setHeader(containerEl, this.plugin._t('setting.title.title6')) // 是否开启图床 new Setting(containerEl) @@ -752,7 +752,12 @@ export default class SmmSettingTab extends PluginSettingTab { _addOtherSetting() { const { containerEl } = this - containerEl.createEl('h2', { text: this.plugin._t('setting.title.title5') }) + this._setHeader(containerEl, this.plugin._t('setting.title.title5')) + } + + // 设置标题 + _setHeader(containerEl, title) { + new Setting(containerEl).setName(title).setHeading() } _addHelpInfo() { diff --git a/plugin/src/utils/index.js b/plugin/src/utils/index.js index 0d0e7c5..08123f1 100644 --- a/plugin/src/utils/index.js +++ b/plugin/src/utils/index.js @@ -1,4 +1,5 @@ import { nodeRichTextToTextWithWrap } from 'simple-mind-map/src/utils/index.js' +import { Platform } from 'obsidian' const getOnfullscreEnevt = () => { if (document.documentElement.requestFullScreen) { @@ -36,7 +37,7 @@ export const fileToBuffer = file => { export const copy = text => { const input = document.createElement('textarea') - input.innerHTML = text + input.value = text document.body.appendChild(input) input.select() document.execCommand('copy') @@ -409,5 +410,5 @@ export const tFileToFile = async function(tfile, app, mimeTypes = {}) { } export const checkIsMac = () => { - return navigator.platform.toUpperCase().indexOf('MAC') >= 0 + return Platform.isMacOS } diff --git a/plugin/style.css b/plugin/style.css index bd846aa..be50555 100644 --- a/plugin/style.css +++ b/plugin/style.css @@ -1,3 +1,27 @@ +/* 通用 */ +.smm-common-full-size { + width: 100%; + height: 100%; + overflow: hidden; +} + +.smm-common-flex { + display: flex; +} + +.smm-common-hide { + display: none; +} + +/* 编辑 */ +.smm-save-button-default { + color: var(--icon-color); +} + +.smm-save-button-un-save { + color: #ff6600; +} + .smm-save-tip { font-size: 12px; margin-right: 10px; @@ -27,6 +51,28 @@ user-select: text; } +.smm-setting-item-hide { + display: none; +} + +.smm-embed-img-empty { + color: var(--text-muted); + border: 1px dashed var(--text-muted); + padding: 10px; + border-radius: 4px; + text-align: center; +} + +.smm-preview-md-to-mindmap-container { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 50; + background: rgba(0, 0, 0, 0.5); +} + /* 字体管理弹窗样式 */ .smm-font-manager-modal { } @@ -130,7 +176,8 @@ } /* 确认弹窗样式 */ -.smm-confirm-dialog-content, .smm-text-info-dialog-content { +.smm-confirm-dialog-content, +.smm-text-info-dialog-content { padding: 16px 0; line-height: 1.6; margin-bottom: 16px; @@ -138,11 +185,13 @@ color: var(--text-normal); } -.smm-confirm-dialog-content p, .smm-text-info-dialog-content p { +.smm-confirm-dialog-content p, +.smm-text-info-dialog-content p { margin: 0; } -.smm-confirm-dialog-buttons, .smm-text-info-dialog-buttons { +.smm-confirm-dialog-buttons, +.smm-text-info-dialog-buttons { display: flex; justify-content: flex-end; gap: 8px; @@ -152,4 +201,4 @@ /* 文字信息弹窗 */ .smm-text-info-dialog-content p a { color: var(--text-accent); -} \ No newline at end of file +}