refactor: delegate uploaded asset insertion runtime
This commit is contained in:
@@ -83,3 +83,7 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
|
|||||||
- `reasonix-2026-05-24T17-07-59-638Z-29274a46` 产生 handoff,但内容串到 Worker B 的 block menu 任务,worktree 无 diff,拒绝采纳。
|
- `reasonix-2026-05-24T17-07-59-638Z-29274a46` 产生 handoff,但内容串到 Worker B 的 block menu 任务,worktree 无 diff,拒绝采纳。
|
||||||
- `reasonix-2026-05-24T17-12-41-044Z-25b9d5d7` 仅产生 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,无 `final.md`、`result.json`、`process-handoff.md/json`,worktree 无 diff,拒绝采纳。
|
- `reasonix-2026-05-24T17-12-41-044Z-25b9d5d7` 仅产生 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,无 `final.md`、`result.json`、`process-handoff.md/json`,worktree 无 diff,拒绝采纳。
|
||||||
- 该项保持未完成;下一刀应进一步缩窄为只迁 editor 插入 DOM 拼接中的一个纯 helper,或由 Codex 本地实现后再交 Reasonix 做浏览器 smoke。
|
- 该项保持未完成;下一刀应进一步缩窄为只迁 editor 插入 DOM 拼接中的一个纯 helper,或由 Codex 本地实现后再交 Reasonix 做浏览器 smoke。
|
||||||
|
- 2026-05-25:Codex 主控完成 `insertUploadedAssetIntoEditor` 外置切片:`local-upload-runtime.js` 新增并导出 `insertUploadedAssetIntoEditor(asset, targetRoot, deps)`,`layout.rs` 优先委托 runtime,保留完整 inline fallback。
|
||||||
|
- 修改:`rust/crates/mnote-web/browser/local-upload-runtime.js`、`rust/crates/mnote-web/src/ssr/pages/layout.rs`。
|
||||||
|
- 已验证:`node --check rust/crates/mnote-web/browser/local-upload-runtime.js`、`cargo fmt --manifest-path rust/Cargo.toml --all --check`、`cargo check --manifest-path rust/Cargo.toml -p mnote-web`、`cargo test --manifest-path rust/Cargo.toml -p mnote-web local_upload_runtime_contains_editor_upload_context_helpers -- --test-threads=1`、`cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_upload_runtime_routes_local_markdown_assets_to_local_folder -- --test-threads=1`、`node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`。
|
||||||
|
- 未完成:`uploadFileToMediaAsset` 编排壳、`uploadFilesWithResolvedTarget`、conflict merge / accept / keep 业务逻辑、secondary pane conflict smoke 仍未迁出。
|
||||||
|
|||||||
@@ -183,6 +183,101 @@ async function uploadLocalFolderAsset(file, plan, context) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function insertUploadedAssetIntoEditor(asset, targetRoot, deps) {
|
||||||
|
deps = deps || {};
|
||||||
|
var editorRoot = targetRoot instanceof HTMLElement
|
||||||
|
? targetRoot.querySelector('.editor-surface .ProseMirror')
|
||||||
|
: document.querySelector('.editor-surface .ProseMirror');
|
||||||
|
if (targetRoot instanceof HTMLElement) window.__mnoteLastEditorUploadRoot = targetRoot;
|
||||||
|
var editor = editorRoot && editorRoot.editor;
|
||||||
|
if (!editor || !editor.chain) {
|
||||||
|
document.documentElement.setAttribute('data-mnote-last-upload-inserted', 'false');
|
||||||
|
document.documentElement.setAttribute('data-mnote-last-upload-insert-error', 'editor_unavailable');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var title = typeof deps.uploadedAssetTitle === 'function' ? deps.uploadedAssetTitle(asset) : uploadedAssetTitle(asset);
|
||||||
|
var localOpenUrl = typeof deps.localAssetOpenUrl === 'function' ? deps.localAssetOpenUrl(asset, false) : localAssetOpenUrl(asset, false);
|
||||||
|
var fallbackUrl = typeof deps.uploadedAssetUrl === 'function' ? deps.uploadedAssetUrl(asset) : uploadedAssetUrl(asset);
|
||||||
|
var url = localOpenUrl || fallbackUrl;
|
||||||
|
var type = typeof deps.uploadedAssetType === 'function' ? deps.uploadedAssetType(asset) : uploadedAssetType(asset);
|
||||||
|
var assetId = String(asset && asset.id || '').trim();
|
||||||
|
var sizeLabel = typeof deps.uploadedFileSize === 'function' ? deps.uploadedFileSize(asset) : uploadedFileSize(asset);
|
||||||
|
try {
|
||||||
|
if (type === 'image' && url) {
|
||||||
|
return editor.chain().focus().setImage({ src: url, alt: title, title: title }).run() === true;
|
||||||
|
}
|
||||||
|
var isLocalAsset = typeof deps.isLocalUploadedAsset === 'function' ? deps.isLocalUploadedAsset(asset) : isLocalUploadedAsset(asset);
|
||||||
|
var userId = '';
|
||||||
|
var buildOnlyOfficeAssetOpenUrl = typeof deps.buildOnlyOfficeAssetOpenUrl === 'function' ? deps.buildOnlyOfficeAssetOpenUrl : function() { return ''; };
|
||||||
|
var onlyOfficeUrl = buildOnlyOfficeAssetOpenUrl(asset, userId);
|
||||||
|
if (onlyOfficeUrl && assetId) {
|
||||||
|
userId = typeof deps.fetchCurrentOnlyOfficeUserId === 'function' ? await deps.fetchCurrentOnlyOfficeUserId() : '';
|
||||||
|
onlyOfficeUrl = buildOnlyOfficeAssetOpenUrl(asset, userId);
|
||||||
|
}
|
||||||
|
var href = onlyOfficeUrl || url;
|
||||||
|
if (href) {
|
||||||
|
var storedHref = onlyOfficeUrl
|
||||||
|
? (isLocalAsset ? onlyOfficeUrl : deps.buildOnlyOfficeOpenPath({
|
||||||
|
fileUrl: '',
|
||||||
|
fileName: title,
|
||||||
|
fileType: deps.inferOnlyOfficeFileType(title, asset && asset.mime_type) || 'docx',
|
||||||
|
assetId: assetId,
|
||||||
|
documentId: String(asset && (asset.document_id || asset.documentId) || deps.currentDocumentId() || '').trim(),
|
||||||
|
userId: userId || '',
|
||||||
|
mode: 'view'
|
||||||
|
}))
|
||||||
|
: href;
|
||||||
|
var inserted = editor.chain().focus().insertContent([
|
||||||
|
{
|
||||||
|
type: 'paragraph',
|
||||||
|
content: [{
|
||||||
|
type: 'text',
|
||||||
|
text: title,
|
||||||
|
marks: [{
|
||||||
|
type: 'link',
|
||||||
|
attrs: {
|
||||||
|
href: storedHref,
|
||||||
|
target: '_blank',
|
||||||
|
rel: 'noopener noreferrer nofollow',
|
||||||
|
class: typeof deps.uploadedAttachmentClass === 'function' ? deps.uploadedAttachmentClass(asset) : uploadedAttachmentClass(asset)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{ type: 'paragraph' }
|
||||||
|
]).focus('end').run() === true;
|
||||||
|
if (inserted) {
|
||||||
|
document.documentElement.setAttribute('data-mnote-last-upload-inserted', 'true');
|
||||||
|
document.documentElement.setAttribute('data-mnote-last-upload-asset-id', assetId || '');
|
||||||
|
document.documentElement.removeAttribute('data-mnote-last-upload-insert-error');
|
||||||
|
} else {
|
||||||
|
document.documentElement.setAttribute('data-mnote-last-upload-inserted', 'false');
|
||||||
|
document.documentElement.setAttribute('data-mnote-last-upload-insert-error', 'insert_content_failed');
|
||||||
|
}
|
||||||
|
window.setTimeout(function() {
|
||||||
|
if (targetRoot instanceof HTMLElement) window.__mnoteLastEditorUploadRoot = targetRoot;
|
||||||
|
if (typeof deps.enhanceEditorAttachmentLinks === 'function') deps.enhanceEditorAttachmentLinks();
|
||||||
|
var cssEscape = typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value || '').replace(/"/g, '\\"'); };
|
||||||
|
var selector = assetId
|
||||||
|
? '.editor-surface .ProseMirror a[href*="' + cssEscape(assetId) + '"]'
|
||||||
|
: '.editor-surface .ProseMirror a';
|
||||||
|
var link = targetRoot instanceof HTMLElement
|
||||||
|
? targetRoot.querySelector(selector)
|
||||||
|
: document.querySelector(selector);
|
||||||
|
if (link instanceof HTMLElement) {
|
||||||
|
link.setAttribute('data-mnote-attachment-link', 'true');
|
||||||
|
if (assetId) link.setAttribute('data-asset-id', assetId);
|
||||||
|
if (sizeLabel) link.setAttribute('data-file-size', sizeLabel);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
return inserted;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('[mnote upload] insert uploaded asset failed', error);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function localAssetOpenUrl(asset, download, context) {
|
function localAssetOpenUrl(asset, download, context) {
|
||||||
if (!isLocalUploadedAsset(asset)) return '';
|
if (!isLocalUploadedAsset(asset)) return '';
|
||||||
var rootUri = String(context && context.rootUri || asset && (asset.rootUri || asset.root_uri) || '').trim() || currentRootUri();
|
var rootUri = String(context && context.rootUri || asset && (asset.rootUri || asset.root_uri) || '').trim() || currentRootUri();
|
||||||
@@ -313,6 +408,7 @@ window.__mnoteLocalUploadRuntime = {
|
|||||||
openEditorUploadFilePicker: openEditorUploadFilePicker,
|
openEditorUploadFilePicker: openEditorUploadFilePicker,
|
||||||
fetchWithTimeout: fetchWithTimeout,
|
fetchWithTimeout: fetchWithTimeout,
|
||||||
uploadLocalFolderAsset: uploadLocalFolderAsset,
|
uploadLocalFolderAsset: uploadLocalFolderAsset,
|
||||||
|
insertUploadedAssetIntoEditor: insertUploadedAssetIntoEditor,
|
||||||
localAssetOpenUrl: localAssetOpenUrl,
|
localAssetOpenUrl: localAssetOpenUrl,
|
||||||
uploadedAssetType: uploadedAssetType,
|
uploadedAssetType: uploadedAssetType,
|
||||||
fileTreeIconKindForFileName: fileTreeIconKindForFileName,
|
fileTreeIconKindForFileName: fileTreeIconKindForFileName,
|
||||||
|
|||||||
@@ -3905,6 +3905,25 @@ const SIDEBAR_TREE_JS: &str = r##"
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function insertUploadedAssetIntoEditor(asset, targetRoot) {
|
async function insertUploadedAssetIntoEditor(asset, targetRoot) {
|
||||||
|
var runtimeFn = localUploadRuntimeFunction('insertUploadedAssetIntoEditor');
|
||||||
|
if (runtimeFn) {
|
||||||
|
return await runtimeFn(asset, targetRoot, {
|
||||||
|
uploadedAssetTitle: uploadedAssetTitle,
|
||||||
|
localAssetOpenUrl: localAssetOpenUrl,
|
||||||
|
uploadedAssetUrl: uploadedAssetUrl,
|
||||||
|
uploadedAssetType: uploadedAssetType,
|
||||||
|
isLocalUploadedAsset: isLocalUploadedAsset,
|
||||||
|
buildOnlyOfficeAssetOpenUrl: buildOnlyOfficeAssetOpenUrl,
|
||||||
|
fetchCurrentOnlyOfficeUserId: fetchCurrentOnlyOfficeUserId,
|
||||||
|
buildOnlyOfficeOpenPath: buildOnlyOfficeOpenPath,
|
||||||
|
inferOnlyOfficeFileType: inferOnlyOfficeFileType,
|
||||||
|
currentDocumentId: currentDocumentId,
|
||||||
|
uploadedAttachmentClass: uploadedAttachmentClass,
|
||||||
|
uploadedFileSize: uploadedFileSize,
|
||||||
|
cssEscape: cssEscape,
|
||||||
|
enhanceEditorAttachmentLinks: enhanceEditorAttachmentLinks
|
||||||
|
});
|
||||||
|
}
|
||||||
var editorRoot = targetRoot instanceof HTMLElement
|
var editorRoot = targetRoot instanceof HTMLElement
|
||||||
? targetRoot.querySelector('.editor-surface .ProseMirror')
|
? targetRoot.querySelector('.editor-surface .ProseMirror')
|
||||||
: document.querySelector('.editor-surface .ProseMirror');
|
: document.querySelector('.editor-surface .ProseMirror');
|
||||||
@@ -10932,6 +10951,9 @@ mod tests {
|
|||||||
assert!(
|
assert!(
|
||||||
SIDEBAR_TREE_JS.contains("localUploadRuntimeFunction('openEditorUploadFilePicker')")
|
SIDEBAR_TREE_JS.contains("localUploadRuntimeFunction('openEditorUploadFilePicker')")
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
SIDEBAR_TREE_JS.contains("localUploadRuntimeFunction('insertUploadedAssetIntoEditor')")
|
||||||
|
);
|
||||||
assert!(SIDEBAR_TREE_JS.contains("__mnoteLastEditorUploadRoot"));
|
assert!(SIDEBAR_TREE_JS.contains("__mnoteLastEditorUploadRoot"));
|
||||||
assert!(SIDEBAR_TREE_JS.contains("data-pane-role=\"primary\""));
|
assert!(SIDEBAR_TREE_JS.contains("data-pane-role=\"primary\""));
|
||||||
assert!(SIDEBAR_TREE_JS.contains("insertUploadedAssetIntoEditor(localPayload.asset, editorRootFromUploadOptions(options))"));
|
assert!(SIDEBAR_TREE_JS.contains("insertUploadedAssetIntoEditor(localPayload.asset, editorRootFromUploadOptions(options))"));
|
||||||
@@ -10947,6 +10969,8 @@ mod tests {
|
|||||||
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function openEditorUploadFilePicker"));
|
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function openEditorUploadFilePicker"));
|
||||||
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function fetchWithTimeout"));
|
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function fetchWithTimeout"));
|
||||||
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function uploadLocalFolderAsset"));
|
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function uploadLocalFolderAsset"));
|
||||||
|
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("function insertUploadedAssetIntoEditor"));
|
||||||
|
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("data-mnote-last-upload-inserted"));
|
||||||
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("uploadFilesWithResolvedTarget"));
|
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("uploadFilesWithResolvedTarget"));
|
||||||
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("__mnoteLastEditorUploadRoot"));
|
assert!(LOCAL_UPLOAD_RUNTIME_JS.contains("__mnoteLastEditorUploadRoot"));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user