// MNote 主壳文件树运行时外置模块。 // 当前先承接 SIDEBAR_TREE_JS 中低风险的行数据解析 helper; // inline script 保留 fallback,避免模块加载顺序影响首屏行为。 function fileTreeRowKind(row) { if (!(row instanceof HTMLElement)) return ''; return String(row.getAttribute('data-row-kind') || '').trim(); } function fileTreeRowDocumentId(row) { if (!(row instanceof HTMLElement)) return ''; return String( row.getAttribute('data-document-id') || row.getAttribute('data-doc-id') || row.getAttribute('data-owner-document-id') || '', ).trim(); } function fileTreeRowAssetId(row, deps) { if (!(row instanceof HTMLElement)) return ''; var assetId = String(row.getAttribute('data-asset-id') || '').trim(); if (assetId) return assetId; var currentSourceKind = deps && typeof deps.currentSourceKind === 'function' ? deps.currentSourceKind : function() { return ''; }; if (currentSourceKind() === 'local_folder' && fileTreeRowKind(row) === 'asset') { return String(row.getAttribute('data-row-id') || '').trim(); } return ''; } function decodeLocalEncodedPath(value) { var path = String(value || '').trim().replace(/~([0-9A-Fa-f]{2})/g, '%$1'); if (!path) return ''; try { return decodeURIComponent(path); } catch (_) { return path; } } function fileTreeRowLocalRelativePath(row, deps) { if (!(row instanceof HTMLElement)) return ''; var direct = String(row.getAttribute('data-local-relative-path') || '').trim(); if (direct) return direct; var localFilePathFromAssetId = deps && typeof deps.localFilePathFromAssetId === 'function' ? deps.localFilePathFromAssetId : function() { return ''; }; var assetPath = localFilePathFromAssetId(fileTreeRowAssetId(row, deps)); if (assetPath) return assetPath; var rowId = String(row.getAttribute('data-row-id') || '').trim(); var nodeId = String(row.getAttribute('data-node-id') || '').trim(); var documentId = fileTreeRowDocumentId(row); var kind = fileTreeRowKind(row); if (rowId.indexOf('local:asset:') === 0) return rowId.slice('local:asset:'.length); if (rowId.indexOf('local:markdown:') === 0) return rowId.slice('local:markdown:'.length); if (rowId.indexOf('local:folder:') === 0) return rowId.slice('local:folder:'.length); if (rowId.indexOf('local:node:') === 0) return rowId.slice('local:node:'.length); if (nodeId.indexOf('local:node:') === 0) return nodeId.slice('local:node:'.length); if ((kind === 'document' || kind === 'doc' || kind === 'markdown') && documentId.indexOf('local-md:') === 0) { return decodeLocalEncodedPath(documentId.slice('local-md:'.length)); } if ((kind === 'folder' || kind === 'directory' || kind === 'index') && documentId.indexOf('local-dir:') === 0) { return decodeLocalEncodedPath(documentId.slice('local-dir:'.length)); } return ''; } function fileTreeRowLocalUploadTargetRelativePath(row, deps) { if (!(row instanceof HTMLElement)) return ''; var kind = fileTreeRowKind(row); var relativePath = fileTreeRowLocalRelativePath(row, deps); if (!relativePath) return ''; if (kind === 'folder' || kind === 'directory') return relativePath; var lastSlash = relativePath.lastIndexOf('/'); return lastSlash >= 0 ? relativePath.slice(0, lastSlash) : ''; } function parseObjectIdentityAttr(value) { var raw = String(value || '').trim(); if (!raw) return null; try { var parsed = JSON.parse(raw); return parsed && typeof parsed === 'object' ? parsed : { raw: raw }; } catch (_) { return { raw: raw }; } } function readWorkspacePathFromRow(row, deps) { if (!(row instanceof HTMLElement)) return null; deps = deps || {}; var currentSourceKind = typeof deps.currentSourceKind === 'function' ? deps.currentSourceKind : function() { return ''; }; var currentRootUri = typeof deps.currentRootUri === 'function' ? deps.currentRootUri : function() { return ''; }; var resolveWorkspaceId = typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; }; var rowTitle = typeof deps.rowTitle === 'function' ? deps.rowTitle : function(target) { return String(target && target.textContent || '').trim(); }; var objectIdentityRaw = String(row.getAttribute('data-object-identity') || '').trim(); var objectIdentity = parseObjectIdentityAttr(objectIdentityRaw); var objectKind = String(row.getAttribute('data-object-kind') || (objectIdentity && objectIdentity.objectKind) || '').trim(); var relativePath = fileTreeRowLocalRelativePath(row, deps); var assetId = fileTreeRowAssetId(row, deps); var documentId = fileTreeRowDocumentId(row); var rowId = String(row.getAttribute('data-row-id') || '').trim(); var rowKind = fileTreeRowKind(row); if (!documentId && (rowKind === 'folder' || objectKind === 'index') && relativePath) { documentId = 'local-dir:' + relativePath.replace(/^\/+/, '').split('/').map(function(segment) { return encodeURIComponent(segment).replace(/%20/g, '~20'); }).join('~2F'); } var sourceKind = String(row.getAttribute('data-source-kind') || currentSourceKind() || '').trim(); var rootUri = String(row.getAttribute('data-root-uri') || currentRootUri() || '').trim(); return { schema: 'mnote.workspace_path.v1', workspaceId: String(row.getAttribute('data-workspace-id') || resolveWorkspaceId(row) || '').trim(), sourceKind: sourceKind, rootUri: rootUri, relativePath: relativePath, localRelativePath: relativePath, objectIdentity: objectIdentity, objectIdentityRaw: objectIdentityRaw, objectKind: objectKind, resourceKind: objectKind || rowKind, rowId: rowId, rowKind: rowKind, documentId: documentId, assetId: assetId, title: rowTitle(row), href: String(row.querySelector?.('.tree-link')?.getAttribute?.('href') || '').trim(), isLocalFolder: sourceKind === 'local_folder' || (!sourceKind && (rowId.indexOf('local:') === 0 || documentId.indexOf('local-md:') === 0 || documentId.indexOf('local-dir:') === 0)) }; } function isFileTreeDownloadableAssetRow(row, deps) { if (!(row instanceof HTMLElement)) return false; var kind = fileTreeRowKind(row); if (kind === 'document' || kind === 'doc' || kind === 'index' || kind === 'markdown' || kind === 'folder' || kind === 'directory') return false; return Boolean(fileTreeRowAssetId(row, deps)); } function isFileTreeDownloadableRow(row, deps) { if (!(row instanceof HTMLElement)) return false; var currentSourceKind = deps && typeof deps.currentSourceKind === 'function' ? deps.currentSourceKind : function() { return ''; }; if (currentSourceKind() !== 'local_folder') return isFileTreeDownloadableAssetRow(row, deps); return Boolean(fileTreeRowLocalRelativePath(row, deps) || isFileTreeDownloadableAssetRow(row, deps)); } function fileTreeAssetDownloadDetail(row, deps) { if (!isFileTreeDownloadableRow(row, deps)) return null; var rowTitle = deps && typeof deps.rowTitle === 'function' ? deps.rowTitle : function() { return ''; }; var resolveWorkspaceId = deps && typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; }; var title = rowTitle(row); var relativePath = fileTreeRowLocalRelativePath(row, deps); var assetId = fileTreeRowAssetId(row, deps) || (relativePath ? 'local-file:' + relativePath : ''); return { contextKind: 'filetree', documentId: fileTreeRowDocumentId(row), rowId: row.getAttribute('data-row-id') || '', rowKind: fileTreeRowKind(row), assetId: assetId, localRelativePath: relativePath, workspacePath: readWorkspacePathFromRow(row, deps), title: title, fileName: title, workspaceId: resolveWorkspaceId(row) }; } function fileTreeRowsByRowIds(rowIds, deps) { var cssEscape = deps && typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); }; return (rowIds || []).map(function(rowId) { return document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape(rowId) + '"]'); }).filter(function(row) { return row instanceof HTMLElement; }); } function fileTreeChildCount(documentId, deps) { if (!documentId) return 0; var cssEscape = deps && typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); }; var row = document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape('doc:' + documentId) + '"]'); var node = row ? row.closest('.tree-node') : null; var children = node ? node.querySelectorAll(':scope > .tree-children > .tree-node > .tree-row[data-shell-mode="filetree"][data-row-kind="document"], :scope > .tree-children > .tree-node > .tree-row[data-shell-mode="filetree"][data-row-kind="doc"]') : []; return children.length; } function defaultEscapeHtml(value) { return String(value == null ? '' : value) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function defaultObjectIdentityAttr(identity) { try { return JSON.stringify(identity || {}); } catch (_) { return ''; } } function readProjection(value) { if (!value || typeof value !== 'object') return null; if (value.result && typeof value.result === 'object') return value.result; if (value.snapshot && value.snapshot.tree) return value.snapshot.tree; if (value.data && value.data.tree) return value.data.tree; if (value.tree && typeof value.tree === 'object') return value.tree; return value; } function readSidebarDataset(value) { if (!value || typeof value !== 'object') return null; if (value.snapshot && value.snapshot.dataset && typeof value.snapshot.dataset === 'object') return value.snapshot.dataset; if (value.data && value.data.dataset && typeof value.data.dataset === 'object') return value.data.dataset; if (value.dataset && typeof value.dataset === 'object') return value.dataset; if (value.sidebar && typeof value.sidebar === 'object') return value.sidebar; return null; } function readDatasetProjection(value, snakeCaseKey, camelCaseKey) { var dataset = readSidebarDataset(value); if (!dataset || typeof dataset !== 'object') return null; if (dataset[snakeCaseKey] && typeof dataset[snakeCaseKey] === 'object') return dataset[snakeCaseKey]; if (dataset[camelCaseKey] && typeof dataset[camelCaseKey] === 'object') return dataset[camelCaseKey]; return null; } function projectionItems(projection) { var resolved = readProjection(projection); return resolved && Array.isArray(resolved.items) ? resolved.items : []; } function hasProjectionItems(projection) { var resolved = readProjection(projection); return Boolean(resolved && Array.isArray(resolved.items)); } function nodeIdOf(item) { return String(item && (item.nodeId || item.id || item.documentId) || '').trim(); } function rowIdOf(item) { return String(item && (item.rowId || item.nodeId || item.id) || '').trim(); } function parentIdOf(item) { return String(item && (item.parentNodeId || item.parentId || '') || '').trim(); } function titleOf(item) { return String(item && item.title || '无标题').trim() || '无标题'; } function fileWorkspaceRelativePath(item) { var meta = item && item.resourceMeta && typeof item.resourceMeta === 'object' ? item.resourceMeta : {}; var workspacePath = meta.workspacePath && typeof meta.workspacePath === 'object' ? meta.workspacePath : {}; var fromWorkspacePath = String(workspacePath.relativePath || '').trim(); if (fromWorkspacePath) return fromWorkspacePath; var extra = meta.extra && typeof meta.extra === 'object' ? meta.extra : {}; var source = extra.source && typeof extra.source === 'object' ? extra.source : {}; var fromSource = String(source.relativePath || '').trim(); if (fromSource) return fromSource; return String(item && (item.relativePath || item.rootRelativePath) || '').trim(); } function groupRowsByParent(rows) { rows = Array.isArray(rows) ? rows : []; var ids = new Set(rows.map(nodeIdOf).filter(Boolean)); var grouped = new Map(); rows.forEach(function(item) { var parentId = parentIdOf(item); if (!ids.has(parentId)) parentId = ''; if (!grouped.has(parentId)) grouped.set(parentId, []); grouped.get(parentId).push(item); }); return grouped; } function replaceSidebarTreeFromDocument(nextDocument, rootId) { var current = document.getElementById(rootId); var next = nextDocument ? nextDocument.getElementById(rootId) : null; if (!(current instanceof HTMLElement) || !(next instanceof HTMLElement)) return false; current.innerHTML = next.innerHTML; Array.from(next.attributes || []).forEach(function(attr) { current.setAttribute(attr.name, attr.value); }); return true; } function applyLocalFolderSidebarSnapshot(nextDocument, options) { options = options || {}; var pageRootId = String(options.pageRootId || 'sidebar-tree-root'); var fileRootId = String(options.fileRootId || 'sidebar-file-tree-root'); var appliedPage = replaceSidebarTreeFromDocument(nextDocument, pageRootId); var appliedFile = replaceSidebarTreeFromDocument(nextDocument, fileRootId); var applied = appliedPage || appliedFile; if (applied && typeof options.onApplied === 'function') options.onApplied({ pageRootApplied: appliedPage, fileRootApplied: appliedFile }); return applied; } function markLocalFolderWatchApplied(value) { var appliedValue = String(value || 'projection'); if (!document || !document.documentElement) return false; document.documentElement.setAttribute('data-mnote-local-folder-watch-applied', appliedValue); return true; } function revealFileTreeRow(row) { if (!(row instanceof HTMLElement)) return; var node = row.closest('.tree-node'); while (node && node.parentElement) { if (node.parentElement.classList && node.parentElement.classList.contains('tree-children')) { node.parentElement.classList.remove('tree-children--collapsed'); var parentNode = node.parentElement.closest('.tree-node'); var parentRow = parentNode ? parentNode.querySelector(':scope > .tree-row') : null; if (parentRow instanceof HTMLElement) { parentRow.setAttribute('aria-expanded', 'true'); var toggle = parentRow.querySelector('[data-rust-action="toggle"]'); if (toggle) toggle.setAttribute('aria-expanded', 'true'); } } node = node.parentElement.closest('.tree-node'); } try { row.scrollIntoView({ block: 'nearest' }); } catch (_) {} } function revealFileTreeAssetRow(assetId, deps) { if (!assetId) return false; var cssEscape = deps && typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); }; var row = document.querySelector('.tree-row[data-shell-mode="filetree"][data-asset-id="' + cssEscape(assetId) + '"]'); if (!(row instanceof HTMLElement)) return false; revealFileTreeRow(row); return true; } function localUploadedAssetRelativePath(asset, deps) { deps = deps || {}; var direct = String(asset && (asset.rootRelativePath || asset.root_relative_path || asset.relativePath || asset.relative_path) || '').trim(); if (direct) return direct; var localFilePathFromAssetId = typeof deps.localFilePathFromAssetId === 'function' ? deps.localFilePathFromAssetId : function(assetId) { var value = String(assetId || '').trim(); return value.indexOf('local-file:') === 0 ? value.slice('local-file:'.length) : value.indexOf('local:asset:') === 0 ? value.slice('local:asset:'.length) : ''; }; return localFilePathFromAssetId(String(asset && asset.id || '').trim()); } function parentRelativePathForUploadedAsset(asset, relativePath) { var target = String(asset && (asset.targetRelativePath || asset.target_relative_path) || '').trim(); if (target || Object.prototype.hasOwnProperty.call(asset || {}, 'targetRelativePath')) return target; var normalized = String(relativePath || '').trim().replace(/^\/+|\/+$/g, ''); var lastSlash = normalized.lastIndexOf('/'); return lastSlash >= 0 ? normalized.slice(0, lastSlash) : ''; } function findLocalFileTreeParentRowForAsset(asset, relativePath, deps) { deps = deps || {}; var cssEscape = typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); }; var currentSourceKind = typeof deps.currentSourceKind === 'function' ? deps.currentSourceKind : function() { return ''; }; if (currentSourceKind() !== 'local_folder') return null; var parentRelativePath = parentRelativePathForUploadedAsset(asset, relativePath); var selector = '#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-local-relative-path="' + cssEscape(parentRelativePath) + '"]'; if (parentRelativePath) { var parentRow = document.querySelector(selector); if (parentRow instanceof HTMLElement) return parentRow; } if (!parentRelativePath) { var root = document.querySelector('#sidebar-file-tree-root .tree-root'); return root instanceof HTMLElement ? null : null; } return null; } function appendUploadedAssetRow(asset, documentId, deps) { deps = deps || {}; var cssEscape = typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); }; var escapeHtml = typeof deps.escapeHtml === 'function' ? deps.escapeHtml : defaultEscapeHtml; var objectIdentityAttr = typeof deps.objectIdentityAttr === 'function' ? deps.objectIdentityAttr : defaultObjectIdentityAttr; var uploadedAssetTitle = typeof deps.uploadedAssetTitle === 'function' ? deps.uploadedAssetTitle : function(nextAsset) { return String(nextAsset && (nextAsset.file_name || nextAsset.title || nextAsset.name) || '未命名附件').trim() || '未命名附件'; }; var uploadedAssetType = typeof deps.uploadedAssetType === 'function' ? deps.uploadedAssetType : function(nextAsset) { return String(nextAsset && (nextAsset.asset_type || nextAsset.assetType || nextAsset.mime_type || '') || '').trim(); }; var fileTreeIconKindForFileName = typeof deps.fileTreeIconKindForFileName === 'function' ? deps.fileTreeIconKindForFileName : function() { return ''; }; var currentDocumentId = typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId : function() { return ''; }; var currentSourceKind = typeof deps.currentSourceKind === 'function' ? deps.currentSourceKind : function() { return ''; }; var assetId = String(asset && asset.id || '').trim(); if (!assetId) return false; if (revealFileTreeAssetRow(assetId, { cssEscape: cssEscape })) return true; var objectKind = String(asset && (asset.objectKind || asset.resourceKind || '') || '').trim(); if (!objectKind && (String(asset && (asset.asset_type || asset.assetType) || '').trim() === 'mindmap' || /\.mindmap\.json$/i.test(assetId))) { objectKind = 'mindmap'; } var localRelativePath = localUploadedAssetRelativePath(asset, deps); var targetDocumentId = String(documentId || asset.document_id || asset.documentId || asset.ownerDocumentId || currentDocumentId() || '').trim(); var parentRow = findLocalFileTreeParentRowForAsset(asset, localRelativePath, deps); if (!parentRow) parentRow = targetDocumentId ? document.querySelector('.tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape('doc:' + targetDocumentId) + '"]') : null; if (!parentRow && currentSourceKind() === 'local_folder' && objectKind === 'mindmap') return false; if (!parentRow) parentRow = document.querySelector('.tree-row[data-shell-mode="filetree"][data-row-kind="document"]'); var root = document.querySelector('#sidebar-file-tree-root .tree-root'); if (!root && !parentRow) return false; var parentLi = parentRow ? parentRow.closest('.tree-node') : null; var children = parentLi ? parentLi.querySelector(':scope > .tree-children') : null; if (parentLi && !children) { children = document.createElement('ul'); children.className = 'tree-children'; parentLi.appendChild(children); } if (children) { children.classList.remove('tree-children--collapsed'); if (parentRow) { parentRow.setAttribute('aria-expanded', 'true'); var toggle = parentRow.querySelector('[data-rust-action="toggle"]'); if (toggle) toggle.setAttribute('aria-expanded', 'true'); } } var container = children || root; var li = document.createElement('li'); li.className = 'tree-node'; var objectIdentity = { objectKind: objectKind || 'attachment', documentId: targetDocumentId || null, blockId: null, assetId: assetId, rootUri: String(asset && (asset.rootUri || asset.root_uri) || '').trim() || null, relativePath: localRelativePath || null }; li.setAttribute('data-node-id', 'asset:' + assetId); var title = uploadedAssetTitle(asset); var iconKind = fileTreeIconKindForFileName(title) || uploadedAssetType(asset) || 'file'; if (objectKind === 'mindmap') iconKind = 'mindmap'; var ownerDocumentId = String(asset && (asset.ownerDocumentId || asset.owner_document_id) || targetDocumentId || '').trim(); var rootUri = String(asset && (asset.rootUri || asset.root_uri) || '').trim(); li.innerHTML = ''; container.appendChild(li); revealFileTreeRow(li.querySelector('.tree-row')); document.documentElement.setAttribute('data-mnote-last-upload-asset-id', assetId); return true; } function fileTreeUploadTargetFallback(detail, deps) { detail = detail || {}; deps = deps || {}; var resolveWorkspaceId = typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; }; var currentDocumentId = typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId : function() { return ''; }; var workspaceId = String(detail.workspaceId || resolveWorkspaceId(document.body) || '').trim(); var documentId = String(detail.documentId || currentDocumentId() || '').trim(); if (Object.prototype.hasOwnProperty.call(detail, 'targetRelativePath')) { return { workspaceId: workspaceId, targetDocumentId: documentId, targetMindmapId: null, targetSubPath: null, targetRelativePath: String(detail.targetRelativePath || ''), uploadIntent: String(detail.uploadIntent || 'filetree.folder.drop') }; } if (!workspaceId || !documentId) { throw new Error('请选择一个目标页面后再拖入文件'); } return { workspaceId: workspaceId, targetDocumentId: documentId, targetMindmapId: null, targetSubPath: null, uploadIntent: String(detail.uploadIntent || 'editor.markdown.attach') }; } function normalizeFileTreeUploadTargetPlan(detail, plan) { detail = detail || {}; plan = plan && typeof plan === 'object' ? Object.assign({}, plan) : {}; if (Object.prototype.hasOwnProperty.call(detail, 'targetRelativePath')) { plan.targetRelativePath = String(detail.targetRelativePath || ''); } if (detail.uploadIntent) { plan.uploadIntent = String(detail.uploadIntent); } else if (Object.prototype.hasOwnProperty.call(detail, 'targetRelativePath')) { plan.uploadIntent = 'filetree.folder.drop'; } else if (!plan.uploadIntent) { plan.uploadIntent = 'editor.markdown.attach'; } return plan; } function fileTreeRowsForUploadPreflight(deps) { deps = deps || {}; var fileTreeRowKind = typeof deps.fileTreeRowKind === 'function' ? deps.fileTreeRowKind : function(row) { return row instanceof HTMLElement ? String(row.getAttribute('data-row-kind') || '').trim() : ''; }; var fileTreeRowDocumentId = typeof deps.fileTreeRowDocumentId === 'function' ? deps.fileTreeRowDocumentId : function(row) { return row instanceof HTMLElement ? String(row.getAttribute('data-document-id') || row.getAttribute('data-doc-id') || '').trim() : ''; }; var fileTreeRowAssetId = typeof deps.fileTreeRowAssetId === 'function' ? deps.fileTreeRowAssetId : function(row) { return row instanceof HTMLElement ? String(row.getAttribute('data-asset-id') || '').trim() : ''; }; return Array.from(document.querySelectorAll('.tree-row[data-shell-mode="filetree"]')).map(function(row) { var documentId = fileTreeRowDocumentId(row); var assetId = fileTreeRowAssetId(row) || null; var badge = row.querySelector('.tree-kind-badge'); return { rowId: row.getAttribute('data-row-id') || '', rowKind: fileTreeRowKind(row), documentId: documentId || null, assetId: assetId, assetDocumentId: documentId || null, assetType: badge ? badge.getAttribute('data-kind') : null, storagePath: null }; }).filter(function(row) { return row.rowId || row.documentId || row.assetId; }); } function fileTreeDocumentParentsForPreflight(deps) { deps = deps || {}; var fileTreeRowDocumentId = typeof deps.fileTreeRowDocumentId === 'function' ? deps.fileTreeRowDocumentId : function(row) { return row instanceof HTMLElement ? String(row.getAttribute('data-document-id') || row.getAttribute('data-doc-id') || '').trim() : ''; }; return Array.from(document.querySelectorAll('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"]')).map(function(row) { var documentId = fileTreeRowDocumentId(row); if (!documentId) return null; var parentRowId = row.getAttribute('data-parent-id') || ''; var parentDocumentId = parentRowId.indexOf('doc:') === 0 ? parentRowId.slice(4) : parentRowId || null; return { documentId: documentId, parentId: parentDocumentId }; }).filter(Boolean); } function fileTreeTargetChildrenForPreflight(targetRow, deps) { deps = deps || {}; var fileTreeRowKind = typeof deps.fileTreeRowKind === 'function' ? deps.fileTreeRowKind : function(row) { return row instanceof HTMLElement ? String(row.getAttribute('data-row-kind') || '').trim() : ''; }; var fileTreeRowDocumentId = typeof deps.fileTreeRowDocumentId === 'function' ? deps.fileTreeRowDocumentId : function(row) { return row instanceof HTMLElement ? String(row.getAttribute('data-document-id') || row.getAttribute('data-doc-id') || '').trim() : ''; }; var fileTreeRowAssetId = typeof deps.fileTreeRowAssetId === 'function' ? deps.fileTreeRowAssetId : function(row) { return row instanceof HTMLElement ? String(row.getAttribute('data-asset-id') || '').trim() : ''; }; var rowTitle = typeof deps.rowTitle === 'function' ? deps.rowTitle : function(row) { if (!(row instanceof HTMLElement)) return ''; var titleNode = row.querySelector('.tree-link-title'); return String(titleNode && titleNode.textContent || row.getAttribute('title') || '').trim(); }; var node = targetRow instanceof HTMLElement ? targetRow.closest('.tree-node') : null; if (!node) return []; return Array.from(node.querySelectorAll(':scope > .tree-children > .tree-node > .tree-row[data-shell-mode="filetree"]')).map(function(row) { return { rowKind: fileTreeRowKind(row), documentId: fileTreeRowDocumentId(row) || null, assetId: fileTreeRowAssetId(row) || null, title: rowTitle(row) }; }); } function fileTreeDropPreflightRows(deps) { deps = deps || {}; var cssEscape = typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); }; var rowTitle = typeof deps.rowTitle === 'function' ? deps.rowTitle : function(row) { if (!(row instanceof HTMLElement)) return ''; var titleNode = row.querySelector('.tree-link-title'); return String(titleNode && titleNode.textContent || row.getAttribute('title') || '').trim(); }; var rows = typeof deps.fileTreeRowsForUploadPreflight === 'function' ? deps.fileTreeRowsForUploadPreflight() : fileTreeRowsForUploadPreflight(deps); return rows.map(function(row) { var domRow = document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape(row.rowId) + '"]'); return Object.assign({}, row, { title: rowTitle(domRow) }); }); } function fileTreeDocumentWorkspacesForUploadPreflight(workspaceId, deps) { deps = deps || {}; var rows = typeof deps.fileTreeRowsForUploadPreflight === 'function' ? deps.fileTreeRowsForUploadPreflight() : fileTreeRowsForUploadPreflight(deps); var seen = new Set(); return rows.filter(function(row) { if (!row.documentId || seen.has(row.documentId)) return false; seen.add(row.documentId); return true; }).map(function(row) { return { documentId: row.documentId, workspaceId: workspaceId || null }; }); } function fileTreeUploadTargetPreflightBody(detail, deps) { detail = detail || {}; deps = deps || {}; var resolveWorkspaceId = typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; }; var currentDocumentId = typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId : function() { return ''; }; var workspaceId = String(detail.workspaceId || resolveWorkspaceId(document.body) || '').trim(); var rows = typeof deps.fileTreeRowsForUploadPreflight === 'function' ? deps.fileTreeRowsForUploadPreflight() : fileTreeRowsForUploadPreflight(deps); var documentWorkspaces = fileTreeDocumentWorkspacesForUploadPreflight(workspaceId, Object.assign({}, deps, { fileTreeRowsForUploadPreflight: function() { return rows; } })); return { workspaceId: workspaceId || null, targetDocumentId: detail.documentId ? String(detail.documentId) : null, targetRowId: detail.targetRowId ? String(detail.targetRowId) : null, focusedRowId: deps.focusedRowId || null, activeDocumentId: currentDocumentId() || null, rows: rows, documentWorkspaces: documentWorkspaces }; } function shortMindmapFileName(mindmapId) { var raw = String(mindmapId || '').trim(); var pathName = raw.indexOf('/') >= 0 ? raw.split('/').pop() : raw; if (/\.json$/i.test(pathName)) return pathName; var digits = raw.match(/(\d{4,})$/); var suffix = digits ? digits[1].slice(-6) : ''; return suffix ? '思维导图' + suffix + '.json' : '思维导图.json'; } function parseMindmapApiTarget(input) { try { var rawUrl = typeof input === 'string' ? input : input && typeof input.url === 'string' ? input.url : ''; if (!rawUrl) return null; var url = new URL(rawUrl, window.location.origin); var match = /^\/api\/mindmap\/([^/]+)\/([^/]+)$/.exec(url.pathname); if (!match) return null; return { documentId: decodeURIComponent(match[1]), mindmapId: decodeURIComponent(match[2]) }; } catch (_) { return null; } } function requestMethod(input, init) { return String( init && init.method ? init.method : input && typeof input.method === 'string' ? input.method : 'GET' ).toUpperCase(); } function requestBodyHasMindmapCreateOnly(init) { var body = init && typeof init.body === 'string' ? init.body : ''; if (!body) return false; try { var payload = JSON.parse(body); return payload && payload.createOnly === true; } catch (_) { return false; } } window.__mnoteFileTreeRuntime = { readProjection: readProjection, readSidebarDataset: readSidebarDataset, readDatasetProjection: readDatasetProjection, projectionItems: projectionItems, hasProjectionItems: hasProjectionItems, nodeIdOf: nodeIdOf, rowIdOf: rowIdOf, parentIdOf: parentIdOf, titleOf: titleOf, fileWorkspaceRelativePath: fileWorkspaceRelativePath, groupRowsByParent: groupRowsByParent, replaceSidebarTreeFromDocument: replaceSidebarTreeFromDocument, applyLocalFolderSidebarSnapshot: applyLocalFolderSidebarSnapshot, markLocalFolderWatchApplied: markLocalFolderWatchApplied, fileTreeRowKind: fileTreeRowKind, fileTreeRowDocumentId: fileTreeRowDocumentId, fileTreeRowAssetId: fileTreeRowAssetId, decodeLocalEncodedPath: decodeLocalEncodedPath, fileTreeRowLocalRelativePath: fileTreeRowLocalRelativePath, fileTreeRowLocalUploadTargetRelativePath: fileTreeRowLocalUploadTargetRelativePath, readWorkspacePathFromRow: readWorkspacePathFromRow, isFileTreeDownloadableAssetRow: isFileTreeDownloadableAssetRow, isFileTreeDownloadableRow: isFileTreeDownloadableRow, fileTreeAssetDownloadDetail: fileTreeAssetDownloadDetail, fileTreeRowsByRowIds: fileTreeRowsByRowIds, fileTreeChildCount: fileTreeChildCount, revealFileTreeRow: revealFileTreeRow, revealFileTreeAssetRow: revealFileTreeAssetRow, appendUploadedAssetRow: appendUploadedAssetRow, fileTreeUploadTargetFallback: fileTreeUploadTargetFallback, normalizeFileTreeUploadTargetPlan: normalizeFileTreeUploadTargetPlan, fileTreeRowsForUploadPreflight: fileTreeRowsForUploadPreflight, fileTreeDocumentParentsForPreflight: fileTreeDocumentParentsForPreflight, fileTreeTargetChildrenForPreflight: fileTreeTargetChildrenForPreflight, fileTreeDropPreflightRows: fileTreeDropPreflightRows, fileTreeDocumentWorkspacesForUploadPreflight: fileTreeDocumentWorkspacesForUploadPreflight, fileTreeUploadTargetPreflightBody: fileTreeUploadTargetPreflightBody, shortMindmapFileName: shortMindmapFileName, parseMindmapApiTarget: parseMindmapApiTarget, requestMethod: requestMethod, requestBodyHasMindmapCreateOnly: requestBodyHasMindmapCreateOnly };