fix: stabilize local attachment icons and office proxy urls

This commit is contained in:
lix-2026
2026-05-26 09:44:35 +08:00
parent 0a15595066
commit 8cd8b44db3
11 changed files with 564 additions and 14 deletions
@@ -321,6 +321,51 @@ export const localFileOpenUrlForTiptap = (value, context) => {
return url.toString();
};
export const localFileOpenPathFromTiptapHref = (href) => {
try {
const url = new URL(String(href || ''), window.location.origin);
if (url.pathname !== '/api/local-folder/files/open') return '';
return String(url.searchParams.get('path') || '').trim();
} catch (_) {
return '';
}
};
export const fileNameFromPath = (path) => {
const value = String(path || '').trim();
return value.includes('/') ? value.split('/').pop() : value;
};
export const attachmentClassForFileName = (fileName) => {
const name = String(fileName || '').trim().toLowerCase();
const ext = name.includes('.') ? name.split('.').pop() : '';
if (['doc', 'docx', 'odt', 'rtf'].includes(ext)) return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-word';
if (['ppt', 'pptx', 'odp'].includes(ext)) return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-ppt';
if (['xls', 'xlsx', 'ods', 'csv'].includes(ext)) return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-sheet';
if (ext === 'pdf') return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-pdf';
if (['md', 'markdown', 'txt', 'json', 'js', 'ts', 'tsx', 'jsx', 'rs', 'py', 'go', 'java', 'kt', 'swift', 'c', 'cpp', 'h', 'hpp', 'css', 'scss', 'html', 'xml', 'yaml', 'yml', 'toml', 'ini', 'sh', 'bash', 'zsh', 'sql', 'vue', 'svelte'].includes(ext)) {
return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-code';
}
return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-file';
};
export const mergeClassNames = (...values) => {
const seen = new Set();
return values
.flatMap((value) => String(value || '').split(/\s+/))
.filter((name) => {
if (!name || seen.has(name)) return false;
seen.add(name);
return true;
})
.join(' ');
};
export const localAttachmentClassForTiptapHref = (href) => {
const localFilePath = localFileOpenPathFromTiptapHref(href);
return localFilePath ? attachmentClassForFileName(fileNameFromPath(localFilePath)) : '';
};
export const localizeTiptapAssetUrls = (node, context) => {
if (!node || typeof node !== 'object') return node;
if (node.type === 'image' && node.attrs && typeof node.attrs.src === 'string') {
@@ -329,7 +374,18 @@ export const localizeTiptapAssetUrls = (node, context) => {
if (Array.isArray(node.marks)) {
node.marks = node.marks.map((mark) => {
if (!mark || mark.type !== 'link' || !mark.attrs || typeof mark.attrs.href !== 'string') return mark;
return { ...mark, attrs: { ...mark.attrs, href: localFileOpenUrlForTiptap(mark.attrs.href, context) } };
const href = localFileOpenUrlForTiptap(mark.attrs.href, context);
const attachmentClass = localAttachmentClassForTiptapHref(href);
const attrs = attachmentClass
? {
...mark.attrs,
href,
class: mergeClassNames(mark.attrs.class, attachmentClass),
target: mark.attrs.target || '_blank',
rel: mark.attrs.rel || 'noopener noreferrer nofollow',
}
: { ...mark.attrs, href };
return { ...mark, attrs };
});
}
if (Array.isArray(node.content)) {