export const createSidebarAttachmentOpenRuntime = (dependencies = {}) => { const { attachmentClassForFileName, buildLocalFileOpenUrl, buildLocalOnlyOfficeOpenUrl, buildOnlyOfficeOpenPath, buildOnlyOfficeOpenUrl, closestAction: injectedClosestAction, currentDocumentId, currentRootUri, currentWorkspaceSourcePayload, fileTreeIconKindForFileName, healLegacyOfficeAttachmentParagraphs, inferCodeAttachmentLanguage, inferOnlyOfficeFileType, isCodeAttachmentFileName, isPdfAttachmentFileName, localFilePathFromAssetId, openLocalOfficeFileInActiveTab, openLocalResourceInActiveTab, openTreeContextMenu, resolveWorkspaceId, triggerBrowserDownload, uploadedFileSize, } = dependencies; const closestAction = typeof injectedClosestAction === 'function' ? injectedClosestAction : function(target, selector) { var node = target && target.nodeType === Node.TEXT_NODE ? target.parentElement : target; return node && typeof node.closest === 'function' ? node.closest(selector) : null; }; var activeEditorAttachmentLink = null; var attachmentActionsHideTimer = 0; function attachmentQueryParams(href) { try { return new URL(String(href || ''), window.location.origin).searchParams; } catch (_) { return new URLSearchParams(); } } function localFileOpenPathFromHref(href) { try { var 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 ''; } } function localFileOpenRootUriFromHref(href) { try { var url = new URL(String(href || ''), window.location.origin); if (url.pathname !== '/api/local-folder/files/open') return ''; return String(url.searchParams.get('rootUri') || '').trim(); } catch (_) { return ''; } } function buildLocalFileStatusUrl(relativePath, rootUri) { var effectiveRootUri = String(rootUri || currentRootUri() || '').trim(); if (!effectiveRootUri || !relativePath) return ''; var url = new URL('/api/local-folder/files/stat', window.location.origin); url.searchParams.set('rootUri', effectiveRootUri); url.searchParams.set('path', relativePath); return url.toString(); } function setEditorAttachmentMissingState(link, missing) { if (!(link instanceof HTMLAnchorElement)) return; var value = Boolean(missing); if (value) { link.setAttribute('data-mnote-attachment-missing', 'true'); link.classList.add('mnote-uploaded-attachment-missing'); link.setAttribute('aria-label', (link.textContent || '附件') + '(文件不存在)'); } else { if (link.getAttribute('data-mnote-attachment-missing') !== 'true') return; link.removeAttribute('data-mnote-attachment-missing'); link.classList.remove('mnote-uploaded-attachment-missing'); link.removeAttribute('aria-label'); } } async function refreshLocalAttachmentExistence(link) { if (!(link instanceof HTMLAnchorElement)) return; var href = link.getAttribute('href') || link.href || ''; var localFilePath = localFileOpenPathFromHref(href); if (!localFilePath) return; var statusUrl = buildLocalFileStatusUrl(localFilePath, localFileOpenRootUriFromHref(href)); if (!statusUrl) return; try { var response = await fetch(statusUrl, { headers: { accept: 'application/json' }, cache: 'no-store' }); var payload = await response.json().catch(function() { return null; }); var exists = Boolean(response.ok && payload && payload.ok === true && payload.result && payload.result.exists === true); setEditorAttachmentMissingState(link, !exists); } catch (_) {} } function refreshEditorLocalAttachmentExistence() { document.querySelectorAll('.editor-surface .ProseMirror a[href*="/api/local-folder/files/open"]').forEach(function(link) { if (link instanceof HTMLAnchorElement) void refreshLocalAttachmentExistence(link); }); } window.__mnoteRefreshEditorLocalAttachmentExistence = refreshEditorLocalAttachmentExistence; function fileNameFromPath(path) { var value = String(path || '').trim(); return value.indexOf('/') >= 0 ? value.split('/').pop() : value; } function isOnlyOfficeAttachmentHref(href) { try { var url = new URL(String(href || ''), window.location.origin); return url.pathname === '/onlyoffice' && (url.searchParams.has('assetId') || url.searchParams.has('fileName')); } catch (_) { return false; } } function normalizeOnlyOfficeAttachmentHref(href) { try { var url = new URL(String(href || ''), window.location.origin); if (url.pathname !== '/onlyoffice') return String(href || ''); return buildOnlyOfficeOpenUrl({ fileUrl: url.searchParams.get('fileUrl') || '', fileName: url.searchParams.get('fileName') || '未命名附件', fileType: url.searchParams.get('fileType') || inferOnlyOfficeFileType(url.searchParams.get('fileName') || '', ''), assetId: url.searchParams.get('assetId') || '', documentId: url.searchParams.get('documentId') || currentDocumentId() || '', userId: url.searchParams.get('userId') || '', mode: url.searchParams.get('mode') || 'view' }); } catch (_) { return String(href || ''); } } function isOfficeFileName(fileName) { return Boolean(inferOnlyOfficeFileType(fileName, '')); } function editorAttachmentPaneContext(link) { var pane = link && typeof link.closest === 'function' ? link.closest('[data-document-pane="true"]') : null; var roleHost = link && typeof link.closest === 'function' ? link.closest('[data-pane-role]') : null; var paneRole = ( pane instanceof HTMLElement && pane.getAttribute('data-pane-role') === 'secondary' ) || ( roleHost instanceof HTMLElement && roleHost.getAttribute('data-pane-role') === 'secondary' ) ? 'secondary' : 'primary'; var paneDocumentId = ''; var paneWorkspaceId = ''; if (pane instanceof HTMLElement) { paneDocumentId = (pane.getAttribute('data-pane-document-id') || '').trim(); paneWorkspaceId = (pane.getAttribute('data-pane-workspace-id') || '').trim(); var shell = pane.querySelector('.document-shell[data-document-id]'); if (!paneDocumentId && shell instanceof HTMLElement) paneDocumentId = (shell.getAttribute('data-document-id') || '').trim(); if (!paneWorkspaceId && shell instanceof HTMLElement) paneWorkspaceId = (shell.getAttribute('data-workspace-id') || '').trim(); } if (roleHost instanceof HTMLElement) { if (!paneDocumentId) paneDocumentId = (roleHost.getAttribute('data-document-id') || '').trim(); if (!paneWorkspaceId) paneWorkspaceId = (roleHost.getAttribute('data-workspace-id') || '').trim(); var roleHostShell = roleHost.matches('.document-shell') ? roleHost : roleHost.querySelector?.('.document-shell[data-document-id]'); if (!paneDocumentId && roleHostShell instanceof HTMLElement) paneDocumentId = (roleHostShell.getAttribute('data-document-id') || '').trim(); if (!paneWorkspaceId && roleHostShell instanceof HTMLElement) paneWorkspaceId = (roleHostShell.getAttribute('data-workspace-id') || '').trim(); } return { paneRole: paneRole, documentId: paneDocumentId || currentDocumentId() || '', workspaceId: paneWorkspaceId || resolveWorkspaceId(document.body) || '' }; } function detailFromEditorAttachmentLink(link) { var rawHref = link instanceof HTMLAnchorElement ? link.href : ''; var params = attachmentQueryParams(rawHref); var paneContext = editorAttachmentPaneContext(link); var localFilePath = localFileOpenPathFromHref(rawHref); var fileName = params.get('fileName') || fileNameFromPath(localFilePath) || (link ? link.textContent : '') || '未命名附件'; var fileType = params.get('fileType') || inferOnlyOfficeFileType(fileName, ''); var assetId = params.get('assetId') || (link ? link.getAttribute('data-asset-id') : '') || (localFilePath ? 'local-file:' + localFilePath : ''); var fileUrl = params.get('fileUrl') || ''; var documentId = params.get('documentId') || paneContext.documentId || ''; var href = rawHref; if (!isOnlyOfficeAttachmentHref(rawHref) && fileType) { fileUrl = rawHref; href = buildOnlyOfficeOpenUrl({ fileUrl: fileUrl, fileName: fileName, fileType: fileType, assetId: assetId, documentId: documentId, userId: '', mode: 'view' }); } else if (isOnlyOfficeAttachmentHref(rawHref)) { href = normalizeOnlyOfficeAttachmentHref(rawHref); } return { href: href, fileUrl: fileUrl, fileName: fileName, title: fileName, fileType: fileType, assetId: assetId, documentId: documentId, workspaceId: paneContext.workspaceId, paneRole: paneContext.paneRole, fileSize: (link ? link.getAttribute('data-file-size') : '') || '' }; } function enhanceEditorAttachmentLink(link) { if (!(link instanceof HTMLAnchorElement)) return; var href = link.getAttribute('href') || ''; var params = attachmentQueryParams(href); var localFilePath = localFileOpenPathFromHref(href); var paneContext = editorAttachmentPaneContext(link); var fileName = params.get('fileName') || fileNameFromPath(localFilePath) || link.textContent || ''; var className = link.getAttribute('class') || ''; var shouldEnhance = isOnlyOfficeAttachmentHref(href) || className.indexOf('mnote-uploaded-attachment-row') >= 0 || isOfficeFileName(fileName) || Boolean(localFilePath); if (!shouldEnhance) return; link.setAttribute('data-mnote-attachment-link', 'true'); var assetId = params.get('assetId') || link.getAttribute('data-asset-id') || (localFilePath ? 'local-file:' + localFilePath : ''); if (assetId) link.setAttribute('data-asset-id', assetId); attachmentClassForFileName(fileName).split(/\s+/).forEach(function(name) { if (name) link.classList.add(name); }); link.setAttribute('target', '_blank'); link.setAttribute('rel', 'noopener noreferrer nofollow'); if (localFilePath && !isOnlyOfficeAttachmentHref(href)) { void refreshLocalAttachmentExistence(link); return; } if (isOnlyOfficeAttachmentHref(href)) { link.setAttribute('href', buildOnlyOfficeOpenPath({ fileUrl: params.get('fileUrl') || '', fileName: fileName || '未命名附件', fileType: params.get('fileType') || inferOnlyOfficeFileType(fileName, ''), assetId: assetId, documentId: params.get('documentId') || paneContext.documentId || '', userId: params.get('userId') || '', mode: params.get('mode') || 'view' })); } void hydrateEditorAttachmentMeta(link); } function enhanceEditorAttachmentLinks() { document.querySelectorAll('.editor-surface .ProseMirror a[href]').forEach(enhanceEditorAttachmentLink); void healLegacyOfficeAttachmentParagraphs(); } window.__mnoteEnhanceEditorAttachmentLinks = function() { observeEditorAttachmentRoots(); enhanceEditorAttachmentLinks(); }; var attachmentInitialEnhanceAttempts = 0; var attachmentInitialEnhanceTimer = window.setInterval(function() { attachmentInitialEnhanceAttempts += 1; enhanceEditorAttachmentLinks(); if (attachmentInitialEnhanceAttempts >= 120) window.clearInterval(attachmentInitialEnhanceTimer); }, 500); function ensureAttachmentActions() { var existing = document.querySelector('[data-testid="mnote-attachment-actions"]'); if (existing instanceof HTMLElement) return existing; var actions = document.createElement('div'); actions.className = 'mnote-attachment-actions'; actions.setAttribute('data-testid', 'mnote-attachment-actions'); actions.hidden = true; actions.innerHTML = '' + '' + ''; actions.addEventListener('mouseenter', function() { if (attachmentActionsHideTimer) window.clearTimeout(attachmentActionsHideTimer); }); actions.addEventListener('mouseleave', scheduleHideAttachmentActions); document.body.appendChild(actions); return actions; } function positionAttachmentActions(link) { if (!(link instanceof HTMLElement)) return; var actions = ensureAttachmentActions(); var rect = link.getBoundingClientRect(); actions.hidden = false; actions.style.left = Math.min(window.innerWidth - 76, Math.max(8, rect.right + 6)) + 'px'; actions.style.top = Math.max(8, rect.top + (rect.height - 28) / 2) + 'px'; activeEditorAttachmentLink = link; } function scheduleHideAttachmentActions() { if (attachmentActionsHideTimer) window.clearTimeout(attachmentActionsHideTimer); attachmentActionsHideTimer = window.setTimeout(function() { var actions = document.querySelector('[data-testid="mnote-attachment-actions"]'); if (actions instanceof HTMLElement) actions.hidden = true; activeEditorAttachmentLink = null; }, 220); } async function openEditorAttachmentDetail(detail) { if (!detail || !detail.href) return; var localFilePath = localFilePathFromAssetId(detail.assetId); if (localFilePath) { if (await openLocalOfficeFileInActiveTab(detail, 'view')) return; // 非 Office 本地文件:用对应图标类型打开 active tab,失败则新窗口 void openLocalResourceInActiveTab({ path: localFilePath, title: detail.fileName || localFilePath.split('/').pop() || localFilePath, kind: fileTreeIconKindForFileName(detail.fileName || localFilePath.split('/').pop() || localFilePath), assetId: detail.assetId, documentId: detail.documentId || currentDocumentId() || '', workspaceId: detail.workspaceId || resolveWorkspaceId(document.body) || '', href: buildLocalFileOpenUrl(localFilePath, false), paneRole: detail.paneRole || 'primary' }).then(function(opened) { if (!opened) window.open(buildLocalFileOpenUrl(localFilePath, false) || detail.href, '_blank', 'noopener,noreferrer'); }); return; } if (isPdfAttachmentFileName(detail.fileName)) { void openPdfEditorAttachment(detail); return; } if (isCodeAttachmentFileName(detail.fileName)) { void openCodeEditorAttachment(detail); return; } var fileType = String(detail.fileType || '').trim(); if (fileType && typeof window.__mnoteDocumentPaneRuntime?.openResourceInActiveTab === 'function') { void window.__mnoteDocumentPaneRuntime.openResourceInActiveTab({ objectIdentity: 'resource:onlyoffice:' + (detail.documentId || '') + ':' + (detail.assetId || ''), assetId: detail.assetId || '', title: detail.fileName || '附件', fileName: detail.fileName || '附件', kind: 'office', officeUrl: detail.href, documentId: detail.documentId || '', workspaceId: detail.workspaceId || '', paneRole: detail.paneRole || 'primary' }); return; } window.open(detail.href, '_blank', 'noopener,noreferrer'); } function openEditorAttachmentNewWindow(detail, mode) { if (!detail) return; var requestedMode = mode === 'edit' ? 'edit' : 'view'; var localFilePath = localFilePathFromAssetId(detail.assetId); if (localFilePath) { var localFileName = localFilePath.split('/').pop() || localFilePath; var localOfficeUrl = buildLocalOnlyOfficeOpenUrl(localFilePath, localFileName, String(detail.documentId || currentDocumentId() || '').trim(), detail.assetId, requestedMode); var localFileUrl = buildLocalFileOpenUrl(localFilePath, false); window.open(localOfficeUrl || localFileUrl || detail.href, '_blank', 'noopener,noreferrer'); return; } var href = detail.href || detail.fileUrl; if (detail.fileType && isOnlyOfficeAttachmentHref(href)) { try { var url = new URL(href, window.location.origin); url.searchParams.set('mode', requestedMode); href = url.toString(); } catch (_) {} } else if (detail.fileType) { href = buildOnlyOfficeOpenUrl({ fileUrl: detail.fileUrl || href || '', fileName: detail.fileName || '未命名附件', fileType: detail.fileType, assetId: detail.assetId || '', documentId: detail.documentId || currentDocumentId() || '', userId: '', mode: requestedMode }); } window.open(href, '_blank', 'noopener,noreferrer'); } async function openEditorAttachmentEditTab(detail) { if (!detail) return false; var localFilePath = localFilePathFromAssetId(detail.assetId); if (localFilePath) { if (await openLocalOfficeFileInActiveTab(detail, 'edit')) return true; } var href = detail.href || detail.fileUrl; if (detail.fileType && isOnlyOfficeAttachmentHref(href)) { try { var url = new URL(href, window.location.origin); url.searchParams.set('mode', 'edit'); href = url.toString(); } catch (_) {} } else if (detail.fileType) { href = buildOnlyOfficeOpenUrl({ fileUrl: detail.fileUrl || href || '', fileName: detail.fileName || '未命名附件', fileType: detail.fileType, assetId: detail.assetId || '', documentId: detail.documentId || currentDocumentId() || '', userId: '', mode: 'edit' }); } if (detail.fileType && typeof window.__mnoteDocumentPaneRuntime?.openResourceInActiveTab === 'function') { var didOpenEditTab = await window.__mnoteDocumentPaneRuntime.openResourceInActiveTab({ objectIdentity: 'resource:onlyoffice:' + (detail.documentId || '') + ':' + (detail.assetId || ''), assetId: detail.assetId || '', title: detail.fileName || '附件', fileName: detail.fileName || '附件', kind: 'office', officeUrl: href, documentId: detail.documentId || '', workspaceId: detail.workspaceId || '', paneRole: detail.paneRole || 'primary' }); if (!didOpenEditTab && href) window.open(href, '_blank', 'noopener,noreferrer'); return didOpenEditTab; } if (href) window.open(href, '_blank', 'noopener,noreferrer'); return false; } async function resolveEditorAttachmentUrl(detail) { var assetId = String(detail && detail.assetId || '').trim(); var localFilePath = localFilePathFromAssetId(assetId); if (localFilePath) { var localUrl = buildLocalFileOpenUrl(localFilePath, false); if (localUrl) { return { url: localUrl, asset: { file_name: String(detail && detail.fileName || '').trim(), fileSize: String(detail && detail.fileSize || '').trim() } }; } } if (assetId) { var response = await fetch('/api/media/sign?assetId=' + encodeURIComponent(assetId), { method: 'GET', credentials: 'include', cache: 'no-store' }); var payload = await response.json().catch(function() { return null; }); if (!response.ok || !payload) { throw new Error(payload && payload.error ? payload.error : '生成签名链接失败'); } var signedUrl = String(payload && payload.signedUrl || '').trim(); if (!signedUrl) throw new Error('附件链接不可用'); return { url: signedUrl, asset: payload.asset && typeof payload.asset === 'object' ? payload.asset : {} }; } var url = String(detail && (detail.fileUrl || detail.href) || '').trim(); if (!url) throw new Error('附件链接不可用'); return { url: url, asset: {} }; } async function openPdfEditorAttachment(detail) { try { var resolved = await resolveEditorAttachmentUrl(detail); window.open(resolved.url, '_blank', 'noopener,noreferrer'); } catch (error) { window.alert(error && error.message ? error.message : '打开 PDF 失败'); } } async function openCodeEditorAttachment(detail) { var resolved = null; try { resolved = await resolveEditorAttachmentUrl(detail); var size = Number(resolved.asset && (resolved.asset.file_size || resolved.asset.fileSize) || 0); if (Number.isFinite(size) && size > 1024 * 1024) { window.open(resolved.url, '_blank', 'noopener,noreferrer'); return; } var response = await fetch(resolved.url, { method: 'GET', credentials: 'include', cache: 'no-store' }); if (!response.ok) throw new Error('读取附件内容失败'); var text = await response.text(); if (text.length > 1024 * 1024) { window.open(resolved.url, '_blank', 'noopener,noreferrer'); return; } var editorRoot = document.querySelector('.editor-surface .ProseMirror'); var editor = editorRoot && editorRoot.editor; if (!editor || !editor.chain) { window.open(resolved.url, '_blank', 'noopener,noreferrer'); return; } var title = String(detail.fileName || resolved.asset.file_name || '附件').trim() || '附件'; var language = inferCodeAttachmentLanguage(title); editor.chain().focus().insertContent([ { type: 'paragraph', content: [{ type: 'text', text: title }] }, { type: 'codeBlock', attrs: { language: language }, content: text ? [{ type: 'text', text: text.replace(/\r\n?/g, '\n') }] : [] } ]).run(); } catch (error) { console.warn('[mnote attachment] open code attachment failed', error); if (resolved && resolved.url) { window.open(resolved.url, '_blank', 'noopener,noreferrer'); return; } window.alert(error && error.message ? error.message : '打开代码附件失败'); } } async function openEditorAttachmentDownload(detail) { if (!detail) return; var localFilePath = localFilePathFromAssetId(detail.assetId); if (localFilePath) { var localDownloadUrl = buildLocalFileOpenUrl(localFilePath, true); if (localDownloadUrl) { triggerBrowserDownload(localDownloadUrl); return; } } if (detail.assetId) { try { var response = await fetch('/api/media/sign?assetId=' + encodeURIComponent(detail.assetId), { method: 'GET', credentials: 'include' }); var payload = await response.json().catch(function() { return null; }); var signedUrl = String(payload && payload.signedUrl || '').trim(); if (response.ok && signedUrl) { window.open(signedUrl, '_blank', 'noopener,noreferrer'); return; } } catch (_) {} } var localRelativePath = String(detail.localRelativePath || '').trim(); if (localRelativePath) { var localPathDownloadUrl = buildLocalFileOpenUrl(localRelativePath, true); if (localPathDownloadUrl) { triggerBrowserDownload(localPathDownloadUrl); return; } } var target = detail.fileUrl || detail.href; if (!target) return; window.open(target, '_blank', 'noopener,noreferrer'); } function openEditorAttachmentMenu(link, trigger, point) { var detail = detailFromEditorAttachmentLink(link); var rect = trigger && trigger.getBoundingClientRect ? trigger.getBoundingClientRect() : link.getBoundingClientRect(); var x = point && typeof point.x === 'number' ? point.x : rect.right; var y = point && typeof point.y === 'number' ? point.y : rect.bottom + 4; openTreeContextMenu('attachment', detail, x, y, trigger || link); } function openEditorAttachmentLink(link) { enhanceEditorAttachmentLink(link); openEditorAttachmentDetail(detailFromEditorAttachmentLink(link)); } enhanceEditorAttachmentLinks(); var attachmentEnhanceFrame = 0; var attachmentEditorObserver = null; var attachmentObservedEditors = typeof WeakSet === 'function' ? new WeakSet() : null; function scheduleEditorAttachmentEnhance() { if (attachmentEnhanceFrame) return; attachmentEnhanceFrame = window.requestAnimationFrame(function() { attachmentEnhanceFrame = 0; enhanceEditorAttachmentLinks(); observeEditorAttachmentRoots(); }); } function addedNodeMayContainEditorAttachmentLink(node) { return node instanceof HTMLElement && ( node.matches('.editor-surface .ProseMirror, .editor-surface .ProseMirror a[href], .editor-surface .ProseMirror p, .editor-surface .ProseMirror span, .editor-surface .ProseMirror div') || node.querySelector?.('.editor-surface .ProseMirror, .editor-surface .ProseMirror a[href]') ); } function observeEditorAttachmentRoots() { if (!attachmentEditorObserver) return; document.querySelectorAll('.editor-surface .ProseMirror').forEach(function(editor) { if (!(editor instanceof HTMLElement)) return; if (attachmentObservedEditors && attachmentObservedEditors.has(editor)) return; if (attachmentObservedEditors) attachmentObservedEditors.add(editor); attachmentEditorObserver.observe(editor, { childList: true, subtree: true }); }); } attachmentEditorObserver = new MutationObserver(function(records) { var shouldEnhance = Array.isArray(records) && records.some(function(record) { if (!record || record.type !== 'childList') return false; return Array.from(record.addedNodes || []).some(function(node) { return addedNodeMayContainEditorAttachmentLink(node); }); }); if (!shouldEnhance) return; scheduleEditorAttachmentEnhance(); }); attachmentEditorObserver.observe(document.documentElement, { childList: true, subtree: true }); observeEditorAttachmentRoots(); window.addEventListener('mnote:editor-attachment-links-changed', function() { window.__mnoteEnhanceEditorAttachmentLinks(); scheduleEditorAttachmentEnhance(); }); [ 'mnote:leptos-tiptap-spike:ready', 'mnote:leptos-tiptap-spike:change', 'mnote:leptos-tiptap-spike:state' ].forEach(function(eventName) { window.addEventListener(eventName, function() { enhanceEditorAttachmentLinks(); observeEditorAttachmentRoots(); window.setTimeout(function() { enhanceEditorAttachmentLinks(); observeEditorAttachmentRoots(); }, 120); }, true); }); [120, 500, 1200, 2500].forEach(function(delayMs) { window.setTimeout(function() { enhanceEditorAttachmentLinks(); observeEditorAttachmentRoots(); }, delayMs); }); function interceptEditorAttachmentLink(event) { var editorAttachmentLink = closestAction(event.target, '.editor-surface .ProseMirror a[data-mnote-attachment-link="true"], .editor-surface .ProseMirror a.mnote-uploaded-attachment-row, .editor-surface .ProseMirror a[href*="/api/local-folder/files/open"]'); if (!(editorAttachmentLink instanceof HTMLAnchorElement)) return; event.preventDefault(); event.stopPropagation(); if (typeof event.stopImmediatePropagation === 'function') event.stopImmediatePropagation(); openEditorAttachmentLink(editorAttachmentLink); } function suppressEditorAttachmentLinkDefault(event) { var editorAttachmentLink = closestAction(event.target, '.editor-surface .ProseMirror a[data-mnote-attachment-link="true"], .editor-surface .ProseMirror a.mnote-uploaded-attachment-row, .editor-surface .ProseMirror a[href*="/api/local-folder/files/open"]'); if (!(editorAttachmentLink instanceof HTMLAnchorElement)) return; event.preventDefault(); event.stopPropagation(); if (typeof event.stopImmediatePropagation === 'function') event.stopImmediatePropagation(); } window.addEventListener('mousedown', suppressEditorAttachmentLinkDefault, true); window.addEventListener('click', interceptEditorAttachmentLink, true); document.addEventListener('mouseover', function(event) { var link = closestAction(event.target, '.editor-surface .ProseMirror a[data-mnote-attachment-link="true"], .editor-surface .ProseMirror a.mnote-uploaded-attachment-row, .editor-surface .ProseMirror a[href*="/api/local-folder/files/open"]'); if (!(link instanceof HTMLAnchorElement)) return; if (attachmentActionsHideTimer) window.clearTimeout(attachmentActionsHideTimer); enhanceEditorAttachmentLink(link); positionAttachmentActions(link); }); document.addEventListener('mouseout', function(event) { var link = closestAction(event.target, '.editor-surface .ProseMirror a[data-mnote-attachment-link="true"], .editor-surface .ProseMirror a.mnote-uploaded-attachment-row, .editor-surface .ProseMirror a[href*="/api/local-folder/files/open"]'); if (!(link instanceof HTMLAnchorElement)) return; var next = event.relatedTarget; var actions = document.querySelector('[data-testid="mnote-attachment-actions"]'); if (next && (link.contains(next) || (actions && actions.contains(next)))) return; scheduleHideAttachmentActions(); }); return { detailFromEditorAttachmentLink, enhanceEditorAttachmentLink, enhanceEditorAttachmentLinks, openCodeEditorAttachment, openEditorAttachmentDetail, openEditorAttachmentDownload, openEditorAttachmentEditTab, openEditorAttachmentNewWindow, refreshEditorLocalAttachmentExistence, }; };