From e815b118c39e041e0db4dfa6a86dd2a2b7cea703 Mon Sep 17 00:00:00 2001 From: DryHeeHuang Date: Sun, 8 Mar 2026 01:10:17 +0800 Subject: [PATCH] feat(windows): support displaying and opening .lnk shortcut files Show .lnk shortcut files in the sidebar only when they point to file types natively supported by MarkText (e.g., .md, .txt). When such a shortcut is clicked, its target file is opened directly. Shortcuts pointing to unsupported file types are filtered out and do not appear in the sidebar. --- src/common/filesystem/paths.js | 20 +++++++++++++++++++- src/main/filesystem/markdown.js | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/common/filesystem/paths.js b/src/common/filesystem/paths.js index 9961466fd..4b9ef0203 100644 --- a/src/common/filesystem/paths.js +++ b/src/common/filesystem/paths.js @@ -2,8 +2,10 @@ import fs from 'fs' import path from 'path' import { isFile, isFile2, isSymbolicLink } from './index' import { minimatch } from 'minimatch' +import { shell } from 'electron' const isOsx = process.platform === 'darwin' +const isWindows = process.platform === 'win32' export const MARKDOWN_EXTENSIONS = Object.freeze([ 'markdown', @@ -30,7 +32,7 @@ export const IMAGE_EXTENSIONS = Object.freeze(['jpeg', 'jpg', 'png', 'gif', 'svg */ export const hasMarkdownExtension = (filename) => { if (!filename || typeof filename !== 'string') return false - return MARKDOWN_EXTENSIONS.some((ext) => filename.toLowerCase().endsWith(`.${ext}`)) + return MARKDOWN_EXTENSIONS.some((ext) => resolveShortcut(filename).toLowerCase().endsWith(`.${ext}`)) } /** @@ -133,3 +135,19 @@ export const checkPathExcludePattern = (pathname, patterns) => { } return false } + +/** + * Returns the actual path pointed to by a shortcut file, or the original path if resolution fails. + * @param {string} The absolute path of the shortcut file. + */ +export const resolveShortcut = (shortcutPath) => { + try { + if (isWindows) { + return shell.readShortcutLink(shortcutPath)?.target || shortcutPath + } else { + return shortcutPath + } + } catch { + return shortcutPath + } +} diff --git a/src/main/filesystem/markdown.js b/src/main/filesystem/markdown.js index c0ebc69c8..602a566ee 100644 --- a/src/main/filesystem/markdown.js +++ b/src/main/filesystem/markdown.js @@ -4,7 +4,7 @@ import log from 'electron-log' import iconv from 'iconv-lite' import { LINE_ENDING_REG, LF_LINE_ENDING_REG, CRLF_LINE_ENDING_REG } from '../config' import { isDirectory2 } from 'common/filesystem' -import { isMarkdownFile } from 'common/filesystem/paths' +import { isMarkdownFile, resolveShortcut } from 'common/filesystem/paths' import { normalizeAndResolvePath, writeFile } from '../filesystem' import { guessEncoding } from './encoding' @@ -87,7 +87,7 @@ export const loadMarkdownFile = async ( // TODO: Use streams to not buffer the file multiple times and only guess // encoding on the first 256/512 bytes. - let buffer = await fsPromises.readFile(path.resolve(pathname)) + let buffer = await fsPromises.readFile(path.resolve(resolveShortcut(pathname))) const encoding = guessEncoding(buffer, autoGuessEncoding) const supported = iconv.encodingExists(encoding.encoding)