514 lines
25 KiB
JavaScript
514 lines
25 KiB
JavaScript
// 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') || '').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(/~2F/g, '/');
|
|
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 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,
|
|
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, '"')
|
|
.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 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 targetDocumentId = String(documentId || asset.document_id || asset.documentId || currentDocumentId() || '').trim();
|
|
var 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
|
|
};
|
|
li.setAttribute('data-node-id', 'asset:' + assetId);
|
|
var title = uploadedAssetTitle(asset);
|
|
var iconKind = fileTreeIconKindForFileName(title) || uploadedAssetType(asset) || 'file';
|
|
if (objectKind === 'mindmap') iconKind = 'mindmap';
|
|
li.innerHTML =
|
|
'<div class="tree-row" role="treeitem" aria-level="' + (parentRow ? '2' : '1') + '" aria-expanded="false" data-rust-rendered-row="filetree" data-testid="filetree-asset-row" data-row-id="' + escapeHtml('asset:' + assetId) + '" data-row-kind="asset" data-node-id="' + escapeHtml('asset:' + assetId) + '" data-document-id="' + escapeHtml(targetDocumentId) + '" data-doc-id="' + escapeHtml(targetDocumentId) + '" data-asset-id="' + escapeHtml(assetId) + '" data-object-identity="' + escapeHtml(objectIdentityAttr(objectIdentity)) + '" data-object-kind="' + escapeHtml(objectKind || 'attachment') + '" data-shell-mode="filetree" data-selected="false" data-active="false" draggable="true">' +
|
|
'<span class="tree-spacer" aria-hidden="true"></span><span class="tree-kind-badge" data-kind="' + escapeHtml(iconKind) + '" aria-hidden="true"></span>' +
|
|
'<button type="button" class="tree-link" data-rust-action="open" data-row-id="' + escapeHtml('asset:' + assetId) + '" data-document-id="' + escapeHtml(targetDocumentId) + '" data-asset-id="' + escapeHtml(assetId) + '"><span class="tree-link-title">' + escapeHtml(title) + '</span></button>' +
|
|
'<div class="tree-actions"><button type="button" class="tree-action" data-testid="filetree-action-menu" data-rust-action="menu" data-row-id="' + escapeHtml('asset:' + assetId) + '" aria-label="更多操作">…</button></div></div>';
|
|
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) });
|
|
});
|
|
}
|
|
|
|
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,
|
|
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
|
|
};
|