fix: resolve critical issues found in code review

- Fix marked.js v12 code highlighting (removed deprecated highlight option, use custom renderer.code)
- Fix open-file race condition (handle file association before window ready)
- Fix Tab key undo history (use execCommand/setRangeText instead of direct value assignment)
- Fix drag-drop file path tracking (use IPC readFile instead of FileReader)
- Fix CSP security (remove unsafe-inline from script-src)
- Improve scroll sync (line-based instead of percentage-based)
- Deduplicate file open dialog logic
- Fix .gitignore duplicate entry
This commit is contained in:
thzxx
2026-05-18 10:46:22 +08:00
parent fda3e5987d
commit 76e1699ee7
4 changed files with 105 additions and 64 deletions
+39 -26
View File
@@ -4,6 +4,7 @@ const fs = require('fs');
let mainWindow = null;
let currentFilePath = null;
let pendingFilePath = null; // For file association race condition
function createWindow() {
// Create the browser window
@@ -120,7 +121,7 @@ function buildMenu() {
Menu.setApplicationMenu(menu);
}
async function handleOpenFile() {
async function showOpenDialog() {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
@@ -128,9 +129,16 @@ async function handleOpenFile() {
{ name: '所有文件', extensions: ['*'] }
]
});
if (!result.canceled && result.filePaths.length > 0) {
openFile(result.filePaths[0]);
return result.filePaths[0];
}
return null;
}
async function handleOpenFile() {
const filePath = await showOpenDialog();
if (filePath) {
openFile(filePath);
}
}
@@ -147,16 +155,8 @@ function openFile(filePath) {
// IPC Handlers
ipcMain.handle('dialog:openFile', async () => {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [
{ name: 'Markdown 文件', extensions: ['md', 'markdown', 'txt'] },
{ name: '所有文件', extensions: ['*'] }
]
});
if (!result.canceled && result.filePaths.length > 0) {
const filePath = result.filePaths[0];
const filePath = await showOpenDialog();
if (filePath) {
const content = fs.readFileSync(filePath, 'utf-8');
currentFilePath = filePath;
mainWindow.setTitle(`MarkLite - ${path.basename(filePath)}`);
@@ -227,7 +227,7 @@ ipcMain.handle('file:getCurrentPath', () => {
});
// Handle file open from command line or file association
function handleFileOpen() {
function getCommandLineFile() {
const args = process.argv.slice(1);
if (args.length > 0 && !args[0].startsWith('--')) {
const filePath = args[0];
@@ -240,24 +240,37 @@ function handleFileOpen() {
// App lifecycle
app.whenReady().then(() => {
// Register open-file handler BEFORE creating window (fixes race condition)
app.on('open-file', (event, filePath) => {
event.preventDefault();
if (mainWindow && mainWindow.webContents.isLoading()) {
// Window is still loading, queue the file
pendingFilePath = filePath;
} else if (mainWindow) {
openFile(filePath);
} else {
// Window not created yet, store for later
pendingFilePath = filePath;
}
});
createWindow();
// Check for file passed via command line
const fileToOpen = handleFileOpen();
const fileToOpen = getCommandLineFile();
if (fileToOpen) {
// Wait for window to be ready
mainWindow.webContents.on('did-finish-load', () => {
openFile(fileToOpen);
});
pendingFilePath = fileToOpen;
}
// Handle macOS open-file event
app.on('open-file', (event, filePath) => {
event.preventDefault();
if (mainWindow) {
openFile(filePath);
}
});
// Open pending file once window is fully ready
if (pendingFilePath) {
mainWindow.webContents.on('did-finish-load', () => {
if (pendingFilePath) {
openFile(pendingFilePath);
pendingFilePath = null;
}
});
}
});
app.on('window-all-closed', () => {