refactor: renderer.js拆分为6个模块(core/tabs/editor/search/sidebar/markdown)

This commit is contained in:
thzxx
2026-05-21 13:34:49 +08:00
parent b185771c41
commit e071a26db6
8 changed files with 1232 additions and 1664 deletions
+156
View File
@@ -0,0 +1,156 @@
// MarkLite — Tabs Module
(function () {
'use strict';
var ML = window.MarkLite;
// ===== Tab State =====
ML.tabs = [];
ML.activeTabId = null;
var tabIdCounter = 0;
ML.mruTabStack = [];
ML.createTab = function (filePath, content) {
var id = ++tabIdCounter;
return { id: id, filePath: filePath || null, content: content || '', isModified: false, scrollTop: 0, scrollLeft: 0, selectionStart: 0, selectionEnd: 0, previewScrollTop: 0 };
};
ML.getActiveTab = function () { return ML.tabs.find(function (t) { return t.id === ML.activeTabId; }) || null; };
ML.getTabIndex = function (tabId) { return ML.tabs.findIndex(function (t) { return t.id === tabId; }); };
ML.saveCurrentTabState = function () {
var tab = ML.getActiveTab();
if (!tab) return;
tab.content = ML.editor.value;
tab.scrollTop = ML.editor.scrollTop;
tab.scrollLeft = ML.editor.scrollLeft;
tab.selectionStart = ML.editor.selectionStart;
tab.selectionEnd = ML.editor.selectionEnd;
tab.previewScrollTop = ML.previewPanel.scrollTop;
};
ML.loadTabState = function (tab) {
ML.editor.focus(); ML.editor.select();
var inserted = document.execCommand('insertText', false, tab.content);
if (!inserted) ML.editor.value = tab.content;
ML.lineCountCache = 0;
ML.updateLineNumbers();
ML.renderMarkdown(tab.content);
ML.updateFileSize();
ML.cachePreviewPositions();
requestAnimationFrame(function () {
ML.editor.scrollTop = tab.scrollTop;
ML.editor.scrollLeft = tab.scrollLeft;
ML.lineNumbers.scrollTop = tab.scrollTop;
ML.editor.setSelectionRange(tab.selectionStart, tab.selectionEnd);
ML.previewPanel.scrollTop = tab.previewScrollTop;
ML.updateCursorPosition();
});
ML.setModified(tab.isModified);
if (typeof window.electronAPI !== 'undefined') window.electronAPI.tabSwitched(tab.filePath);
};
ML.setModified = function (modified) {
var tab = ML.getActiveTab();
if (tab) {
tab.isModified = modified;
var tabEl = ML.tabList.querySelector('.tab-item[data-tab-id="' + tab.id + '"]');
if (tabEl) tabEl.classList.toggle('modified', modified);
}
ML.updateTitle();
};
ML.createNewTab = function (filePath, content) {
if (filePath) {
var existing = ML.tabs.find(function (t) { return t.filePath === filePath; });
if (existing) { ML.switchToTab(existing.id); return existing; }
}
var tab = ML.createTab(filePath, content);
ML.tabs.push(tab);
ML.switchToTab(tab.id);
return tab;
};
ML.switchToTab = function (tabId) {
if (tabId === ML.activeTabId) return;
ML.saveCurrentTabState();
if (ML.activeTabId) {
ML.mruTabStack = ML.mruTabStack.filter(function (id) { return id !== ML.activeTabId; });
ML.mruTabStack.unshift(ML.activeTabId);
}
ML.activeTabId = tabId;
var tab = ML.getActiveTab();
if (!tab) return;
ML.loadTabState(tab);
ML.renderTabBar();
ML.updateTitle();
ML.updateSidebarHighlight();
ML.welcomeScreen.classList.add('hidden');
};
ML.closeTab = function (tabId) {
var index = ML.getTabIndex(tabId);
if (index === -1) return;
var tab = ML.tabs[index];
if (tab.isModified) {
var name = tab.filePath ? ML.getFileName(tab.filePath) : '未命名';
if (!confirm('"' + name + '" 尚未保存,确定要关闭吗?')) return;
}
ML.tabs.splice(index, 1);
ML.mruTabStack = ML.mruTabStack.filter(function (id) { return id !== tabId; });
if (tabId === ML.activeTabId) {
if (ML.tabs.length === 0) {
ML.activeTabId = null;
ML.editor.value = '';
ML.preview.innerHTML = '';
ML.lineNumbers.innerHTML = '';
ML.lineCountCache = 0;
ML.statusSize.textContent = '';
ML.statusSizeDivider.classList.remove('visible');
ML.welcomeScreen.classList.remove('hidden');
document.title = 'MarkLite';
ML.statusText.textContent = '就绪';
if (typeof window.electronAPI !== 'undefined') window.electronAPI.tabSwitched(null);
} else {
var newIndex = Math.min(index, ML.tabs.length - 1);
ML.activeTabId = ML.tabs[newIndex].id;
ML.loadTabState(ML.tabs[newIndex]);
}
}
ML.renderTabBar();
ML.updateTitle();
ML.updateSidebarHighlight();
};
ML.renderTabBar = function () {
ML.tabList.innerHTML = '';
ML.tabs.forEach(function (tab) {
var el = document.createElement('div');
el.className = 'tab-item' + (tab.id === ML.activeTabId ? ' active' : '') + (tab.isModified ? ' modified' : '');
el.dataset.tabId = tab.id;
var name = document.createElement('span');
name.className = 'tab-name';
name.textContent = tab.filePath ? ML.getFileName(tab.filePath) : '未命名';
el.appendChild(name);
var close = document.createElement('button');
close.className = 'tab-close';
close.innerHTML = '<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
close.addEventListener('click', function (e) { e.stopPropagation(); ML.closeTab(tab.id); });
el.appendChild(close);
el.addEventListener('click', function () { ML.switchToTab(tab.id); });
ML.tabList.appendChild(el);
});
};
ML.updateTitle = function () {
var tab = ML.getActiveTab();
if (tab) {
var name = tab.filePath ? ML.getFileName(tab.filePath) : '未命名';
var mod = tab.isModified ? ' *' : '';
document.title = 'MarkLite - ' + name + mod;
ML.statusText.textContent = name;
} else {
document.title = 'MarkLite';
ML.statusText.textContent = '就绪';
}
};
})();