refactor: externalize editor upload context

This commit is contained in:
lix-2026
2026-05-24 23:43:22 +08:00
parent 5a96ea9eba
commit 437c690a39
4 changed files with 182 additions and 1 deletions
@@ -20,6 +20,110 @@ function currentRootUri() {
: '';
}
function editorUploadRootFromElementWithDeps(target, deps) {
if (deps && typeof deps.editorUploadRootFromElement === 'function') {
return deps.editorUploadRootFromElement(target);
}
if (!(target instanceof Element)) return null;
var selector = String(deps && deps.rootSelector || '[data-editor-host-kind="leptos_tiptap_island"], [data-editor-host-kind="leptos_tiptap_resource"]');
var root = target.closest(selector);
return root instanceof HTMLElement ? root : null;
}
function resolveEditorUploadContext(detail, deps) {
var root = null;
var selector = detail && detail.editorRootSelector ? String(detail.editorRootSelector) : '';
if (selector) {
try {
var selected = document.querySelector(selector);
if (selected instanceof HTMLElement) root = selected;
} catch (_) {}
}
if (!root && window.__mnoteIntendedSlashRoot instanceof HTMLElement && window.__mnoteIntendedSlashRoot.isConnected) {
root = window.__mnoteIntendedSlashRoot;
}
if (!root && window.__mnoteLastEditorUploadRoot instanceof HTMLElement && window.__mnoteLastEditorUploadRoot.isConnected) {
root = window.__mnoteLastEditorUploadRoot;
}
if (!root && document.activeElement instanceof Element) {
root = editorUploadRootFromElementWithDeps(document.activeElement, deps);
}
if (!root) {
var rootSelector = String(deps && deps.rootSelector || '[data-editor-host-kind="leptos_tiptap_island"], [data-editor-host-kind="leptos_tiptap_resource"]');
var focused = document.querySelector(rootSelector + ' .ProseMirror:focus-within');
root = editorUploadRootFromElementWithDeps(focused, deps);
}
if (!root) {
root = document.querySelector('[data-editor-host-kind="leptos_tiptap_island"][data-pane-role="primary"]');
}
var pane = root instanceof Element ? root.closest('.document-pane[data-pane-role]') : null;
var shell = root instanceof Element ? root.closest('.document-shell[data-document-id]') : null;
var currentDocumentId = deps && typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId : function() { return ''; };
var resolveWorkspaceId = deps && typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; };
return {
root: root instanceof HTMLElement ? root : null,
documentId: String(
detail && detail.documentId
|| (root instanceof HTMLElement && root.getAttribute('data-document-id'))
|| (pane instanceof HTMLElement && pane.getAttribute('data-pane-document-id'))
|| (shell instanceof HTMLElement && shell.getAttribute('data-document-id'))
|| currentDocumentId()
|| ''
).trim(),
workspaceId: String(
detail && detail.workspaceId
|| (root instanceof HTMLElement && root.getAttribute('data-workspace-id'))
|| (pane instanceof HTMLElement && pane.getAttribute('data-pane-workspace-id'))
|| (shell instanceof HTMLElement && shell.getAttribute('data-workspace-id'))
|| resolveWorkspaceId(document.body)
|| ''
).trim()
};
}
function editorRootFromUploadOptions(options, deps) {
if (options && options.editorRoot instanceof HTMLElement) return options.editorRoot;
if (window.__mnoteIntendedSlashRoot instanceof HTMLElement && window.__mnoteIntendedSlashRoot.isConnected) {
return window.__mnoteIntendedSlashRoot;
}
if (window.__mnoteLastEditorUploadRoot instanceof HTMLElement && window.__mnoteLastEditorUploadRoot.isConnected) {
return window.__mnoteLastEditorUploadRoot;
}
var rootSelector = String(deps && deps.rootSelector || '[data-editor-host-kind="leptos_tiptap_island"], [data-editor-host-kind="leptos_tiptap_resource"]');
var focused = document.querySelector(rootSelector + ' .ProseMirror:focus-within');
return editorUploadRootFromElementWithDeps(focused, deps);
}
function openEditorUploadFilePicker(detail, deps) {
var uploadContext = resolveEditorUploadContext(detail || {}, deps || {});
var input = document.createElement('input');
input.type = 'file';
input.multiple = detail && detail.multiple !== false;
if (detail && detail.accept) input.accept = String(detail.accept);
input.style.position = 'fixed';
input.style.left = '-9999px';
input.style.top = '-9999px';
document.body.appendChild(input);
input.addEventListener('change', function() {
var files = Array.from(input.files || []);
input.remove();
var resolveWorkspaceId = deps && typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; };
var currentDocumentId = deps && typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId : function() { return ''; };
var uploadFilesWithResolvedTarget = deps && typeof deps.uploadFilesWithResolvedTarget === 'function' ? deps.uploadFilesWithResolvedTarget : null;
if (!uploadFilesWithResolvedTarget) return;
void uploadFilesWithResolvedTarget(files, {
workspaceId: uploadContext.workspaceId || resolveWorkspaceId(document.body),
documentId: uploadContext.documentId || currentDocumentId(),
targetRowId: null,
uploadIntent: 'editor.markdown.attach'
}, {
insertIntoEditor: detail && detail.insertIntoEditor !== false,
editorRoot: uploadContext.root
});
}, { once: true });
input.click();
}
function localAssetOpenUrl(asset, download, context) {
if (!isLocalUploadedAsset(asset)) return '';
var rootUri = String(context && context.rootUri || asset && (asset.rootUri || asset.root_uri) || '').trim() || currentRootUri();
@@ -145,6 +249,9 @@ function uploadedFileSize(asset) {
window.__mnoteLocalUploadRuntime = {
uploadedAssetTitle: uploadedAssetTitle,
uploadedAssetUrl: uploadedAssetUrl,
resolveEditorUploadContext: resolveEditorUploadContext,
editorRootFromUploadOptions: editorRootFromUploadOptions,
openEditorUploadFilePicker: openEditorUploadFilePicker,
localAssetOpenUrl: localAssetOpenUrl,
uploadedAssetType: uploadedAssetType,
fileTreeIconKindForFileName: fileTreeIconKindForFileName,
@@ -3775,6 +3775,15 @@ const SIDEBAR_TREE_JS: &str = r##"
}
function resolveEditorUploadContext(detail) {
var runtimeFn = localUploadRuntimeFunction('resolveEditorUploadContext');
if (runtimeFn) {
return runtimeFn(detail || {}, {
rootSelector: EDITOR_UPLOAD_ROOT_SELECTOR,
editorUploadRootFromElement: editorUploadRootFromElement,
currentDocumentId: currentDocumentId,
resolveWorkspaceId: resolveWorkspaceId
});
}
var root = null;
var selector = detail && detail.editorRootSelector ? String(detail.editorRootSelector) : '';
if (selector) {
@@ -3823,6 +3832,13 @@ const SIDEBAR_TREE_JS: &str = r##"
}
function editorRootFromUploadOptions(options) {
var runtimeFn = localUploadRuntimeFunction('editorRootFromUploadOptions');
if (runtimeFn) {
return runtimeFn(options || {}, {
rootSelector: EDITOR_UPLOAD_ROOT_SELECTOR,
editorUploadRootFromElement: editorUploadRootFromElement
});
}
if (options && options.editorRoot instanceof HTMLElement) return options.editorRoot;
if (window.__mnoteIntendedSlashRoot instanceof HTMLElement && window.__mnoteIntendedSlashRoot.isConnected) {
return window.__mnoteIntendedSlashRoot;
@@ -4029,6 +4045,16 @@ const SIDEBAR_TREE_JS: &str = r##"
}
function openEditorUploadFilePicker(detail) {
var runtimeFn = localUploadRuntimeFunction('openEditorUploadFilePicker');
if (runtimeFn) {
return runtimeFn(detail || {}, {
rootSelector: EDITOR_UPLOAD_ROOT_SELECTOR,
editorUploadRootFromElement: editorUploadRootFromElement,
currentDocumentId: currentDocumentId,
resolveWorkspaceId: resolveWorkspaceId,
uploadFilesWithResolvedTarget: uploadFilesWithResolvedTarget
});
}
var uploadContext = resolveEditorUploadContext(detail || {});
var input = document.createElement('input');
input.type = 'file';
@@ -10795,12 +10821,29 @@ mod tests {
assert!(SIDEBAR_TREE_JS.contains("refreshLocalFolderSidebarSnapshot"));
assert!(SIDEBAR_TREE_JS.contains("wolai:local-assets-changed"));
assert!(SIDEBAR_TREE_JS.contains("function resolveEditorUploadContext"));
assert!(
SIDEBAR_TREE_JS.contains("localUploadRuntimeFunction('resolveEditorUploadContext')")
);
assert!(
SIDEBAR_TREE_JS.contains("localUploadRuntimeFunction('openEditorUploadFilePicker')")
);
assert!(SIDEBAR_TREE_JS.contains("__mnoteLastEditorUploadRoot"));
assert!(SIDEBAR_TREE_JS.contains("data-pane-role=\"primary\""));
assert!(SIDEBAR_TREE_JS.contains("insertUploadedAssetIntoEditor(localPayload.asset, editorRootFromUploadOptions(options))"));
assert!(SIDEBAR_TREE_JS.contains("editorRoot: uploadContext.root"));
}
#[test]
fn local_upload_runtime_contains_editor_upload_context_helpers() {
const LOCAL_UPLOAD_RUNTIME_JS: &str =
include_str!("../../../browser/local-upload-runtime.js");
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function resolveEditorUploadContext"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function editorRootFromUploadOptions"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function openEditorUploadFilePicker"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("uploadFilesWithResolvedTarget"));
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("__mnoteLastEditorUploadRoot"));
}
#[test]
fn sidebar_tree_runtime_focuses_restored_local_folder_row() {
assert!(SIDEBAR_TREE_JS.contains("applyPendingLocalFolderRestoreFocusOnce"));