refactor: extract mindmap fetch helpers

This commit is contained in:
lix-2026
2026-05-25 09:38:50 +08:00
parent 812504924f
commit 863e68b126
3 changed files with 141 additions and 24 deletions
@@ -6,7 +6,7 @@
## 1. 目标
`3-19` 已归档的基础上,继续把仍留在 Rust inline / 主壳大 runtime 中的浏览器行为切成可审计模块。Codex 维护本文件作为事实源,Reasonix 只承接短批次审计、窄范围实现或浏览器 smoke;当前 goal 下每批最多 2 个 worker。
`3-19` 已归档的基础上,继续把仍留在 Rust inline / 主壳大 runtime 中的浏览器行为切成可审计模块。Codex 维护本文件作为事实源,Reasonix 只承接短批次审计、窄范围实现或浏览器 smoke;当前 goal 下每批最多 4 个 worker。
## 2. 本轮边界
@@ -185,17 +185,17 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 修改:`filetree-runtime.js` 新增并导出 `markLocalFolderWatchApplied(value)``layout.rs` 的同名 wrapper 优先委托 runtimeinline fallback 保留 `data-mnote-local-folder-watch-applied="projection"` 行为。
- 边界:未改 projection fetch URL、JSON 渲染、selection/focus/sidebar shell 副作用、附件存在性刷新、tree live SSE consumer;本批只外置刷新完成证据标记。
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-runtime.js``git diff --check``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 filetree_runtime -- --test-threads=1`
- 2026-05-25Batch AC 按用户纠正继续采用独立 worktree 流程;本轮实际 3 个 worker,符合当前 goal 每批最多 4 个 worker 的上限;任务书均写入各 worktree `tmp/`,未新增主工作区 `.codex/reasonix-tasks`
- 2026-05-25Batch AC 按当前 4-worker 口径继续采用独立 worktree 流程;本轮实际 3 个 worker,符合当前 goal 上限;任务书均写入各 worktree `tmp/`,未新增主工作区 `.codex/reasonix-tasks`
- Worker C `/mnt/Data1T/mnote-worktrees/0525-ac-worker-c-3-20-conflict-action-boundary`Reasonix run `reasonix-2026-05-24T22-52-30-772Z-464df4b4`Codex 已读取 Hindsight recall、`process-handoff.md/json``result.json`,并核对 worktree `git status --short` / `git diff --stat` 为空。
- 审计结论经 Codex 复核后采纳:`acceptDiskVersion``keepCurrentEditorVersion``writeMergedConflictResult` 仍强依赖 fetch、persist、session views、Tiptap hydrate、conflict key 计算和 `setSessionStatus`,不应整体迁入 `document-conflict-panel-runtime.js`;共享的 session 状态字段重置块暂不外置,以保持 runtime=DOM/promise wrapper、shell=业务编排的边界。
- Worker D `/mnt/Data1T/mnote-worktrees/0525-ac-worker-d-smoke-regression`Reasonix run `reasonix-2026-05-24T22-52-30-854Z-dfad6786`,源码零 diff`task489``task488``task487``task451` 在 3001 均通过,其中 `task451` 覆盖 accept-disk、keep-current、merge-save、agent-conflict-source。
- 未完成:conflict action 业务逻辑仍留在 `web_shell.rs`secondary pane conflict 专项 smoke 仍可后续单独补强。
- 2026-05-25Batch AD 采用 3 个独立 worktree workerB/C/D),符合当前 goal 每批最多 4 个 worker 的上限;任务书均写入各 worktree `tmp/`,未新增主工作区 `.codex/reasonix-tasks`
- 2026-05-25Batch AD 采用 3 个独立 worktree workerB/C/D),符合当前 4-worker 口径;任务书均写入各 worktree `tmp/`,未新增主工作区 `.codex/reasonix-tasks`
- 涉及 worktree`/mnt/Data1T/mnote-worktrees/0525-ad-worker-b-5-29-drop-indicator-block-rect``/mnt/Data1T/mnote-worktrees/0525-ad-worker-c-3-20-upload-target-readonly``/mnt/Data1T/mnote-worktrees/0525-ad-worker-d-regression-smoke`
- Worker C run `reasonix-2026-05-24T23-05-57-201Z-41882fef` 仅产出 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,无 `final.md``result.json``process-handoff.md/json`worktree 零 diff3-20 输出拒收。
- Worker D run `reasonix-2026-05-24T23-05-57-257Z-c917f1ef` 有完整 `process-handoff.md/json``result.json``final.md`,源码零 diff`task489``task488``task487``task451` 在 3001 均通过,其中 `task487` 覆盖 local-folder tree live consumer、`task451` 覆盖 conflict UI actions。Codex 已读取 Hindsight recall 与 handoff/result,并独立复跑 `task487` / `task451` / `task489` / `task488` 主控验收,全部通过。
- 后续如需继续 upload target 审计,必须重新按最多 4 worker 的受控批次派发。
- 2026-05-25Batch AE 的 3-20 侧记录 2 个独立 worktree worker;同批跨 3-20 / 5-29 总 worker 数为 4 个,符合当前 goal 每批最多 4 个 worker 上限。任务书均写入各 worktree `tmp/`,未写主工作区 `.codex/reasonix-tasks`
- 2026-05-25Batch AE 的 3-20 侧记录 2 个独立 worktree worker;同批跨 3-20 / 5-29 总 worker 数为 4 个,符合当前 4-worker 口径;任务书均写入各 worktree `tmp/`,未写主工作区 `.codex/reasonix-tasks`
- Worker C `/mnt/Data1T/mnote-worktrees/0525-ae-worker-c-3-20-upload-target-readonly`run `reasonix-2026-05-24T23-18-29-419Z-3e999c4d` 有完整 `process-handoff.md/json``result.json``final.md`,源码零 diff;审计结论经主控复核后采纳:`resolveFileTreeUploadTarget` 暂不宜迁入 browser runtime,核心依赖 `preflightFileTreeUploadTarget``sidebarFileTreeSelection`、fetch 与 DOM 查询;`refreshLocalFolderSidebarSnapshot` 仍是 shell 编排,append/reveal 系列 helper 已足够外置。
- Worker D `/mnt/Data1T/mnote-worktrees/0525-ae-worker-d-regression-smoke`run `reasonix-2026-05-24T23-18-29-435Z-3225d16e` 串线执行成 5-29 overlay 只读审计,未运行 `task489` / `task488` / `task487` / `task451` smoke;本轮 3-20 smoke 输出拒收。
- 后续 3-20 推荐下一刀:只读审计 `syncSidebarFileTreeSelection` 是否可迁入 `filetree-runtime.js`,或在明确降级兼容策略后评估 inline fallback 瘦身;不要继续盲迁 `refreshLocalFolderSidebarSnapshot` 整体。
@@ -268,16 +268,19 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据
- 边界:未迁 `preflightFileTreeUploadTarget` 的 API 请求、`fallbackFileTreeUploadTarget` 的 workspace/document 语义、preflight 失败降级策略、sidebar refresh 或上传编排。
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-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 filetree_runtime_contains_row_accessor_helpers -- --test-threads=1`、临时当前源码服务 `MNOTE_WEB_BIND=127.0.0.1:3022 MNOTE_WEB_PUBLIC_BIND=127.0.0.1:3022 cargo run --manifest-path rust/Cargo.toml -p mnote-web``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3022 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 结果:`task479``editor-upload-to-page-resource-dir``filetree-folder-drop-to-target``ok:true`,说明本刀未破坏本地 Markdown 附件上传目标与文件树文件夹拖入目标路径。
- 2026-05-25:等待 Batch BF 只读审计期间,发现未批准 residual runner 自动启动了旧 Batch BE 的 4 个 worker`0525-be-worker-a/b/c/d-*`),违反当前 goal 的“每批最多 2 个 worker”约束
- 处置:主控已统一终止相关 `reasonix-coding-runner` / `reasonix acp` / `reasonix/dist/cli/index.js acp` 进程;不读取、不采纳这些未授权 run 的 handoff、transcript 或 smoke 结果。
- 影响:本文件中所有关于 Batch BE“按当前 goal 派发 4 worker”的口径均视为错误历史噪音,不作为事实源;后续 3-20 侧继续以已提交主线和受控 1-worker/2-worker 短批次为准。
- 2026-05-25Codex 主控继续收口 filetree upload preflight 的 document/workspace 数据采集层。
- 修改:`rust/crates/mnote-web/browser/filetree-runtime.js` 新增并导出 `fileTreeDocumentWorkspacesForUploadPreflight(workspaceId, deps)``layout.rs` 的同名壳层优先委托 runtime helper,并保留原 inline fallback。
- 边界:未迁 `preflightFileTreeUploadTarget` fetch、`ensureFileTreeWritableTarget``fallbackFileTreeUploadTarget`、upload/drop 编排或 sidebar refresh;本批只外置“从当前 filetree row 快照推导 documentId -> workspaceId 列表”的纯 DOM 数据采集。
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-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 filetree_runtime_contains_row_accessor_helpers -- --test-threads=1`、临时当前源码服务 `MNOTE_WEB_BIND=127.0.0.1:3027 MNOTE_WEB_PUBLIC_BIND=127.0.0.1:3027 cargo run --manifest-path rust/Cargo.toml -p mnote-web``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3027 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 结果:`task479``editor-upload-to-page-resource-dir``filetree-folder-drop-to-target``ok:true`,说明该 preflight helper 外置未破坏本地 Markdown 附件上传或文件树文件夹拖入目标。
- 2026-05-25:等待后续只读审计期间,发现不属于当前手动批次的 residual Reasonix runner。主控按进程面核对后,只保留当前 goal 明确允许的“每批最多 4 个独立 worktree worker”口径;不完整 handoff / result / final 的自动 run 继续按合同拒收
- 2026-05-25Codex 主控完成 filetree upload preflight 的 `documentWorkspaces` 低风险数据采样切片。
- 修改:`rust/crates/mnote-web/browser/filetree-runtime.js` 新增并导出 `fileTreeDocumentWorkspacesForUploadPreflight(workspaceId, deps)``rust/crates/mnote-web/src/ssr/pages/layout.rs::fileTreeDocumentWorkspacesForUploadPreflight` 优先委托 runtime helper,保留完整 inline fallback。
- 边界:未迁 `preflightFileTreeUploadTarget` 的 fetch/API 请求、`sidebarFileTreeSelection``currentDocumentId()``resolveWorkspaceId()`、fallback 降级或上传编排;本批只外置基于 `fileTreeRowsForUploadPreflight()` 的 documentId 去重与 workspaceId 映射。
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-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 filetree_runtime_contains_row_accessor_helpers -- --test-threads=1`、临时当前源码服务 `MNOTE_WEB_BIND=127.0.0.1:3035 MNOTE_WEB_PUBLIC_BIND=127.0.0.1:3035 cargo run --manifest-path rust/Cargo.toml -p mnote-web``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3035 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 结果:`task479` `editor-upload-to-page-resource-dir``filetree-folder-drop-to-target``ok:true`,说明本刀未破坏本地 Markdown 附件上传目标与文件树文件夹拖入目标路径
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-runtime.js``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo test --manifest-path rust/Cargo.toml -p mnote-web filetree -- --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`、临时当前源码服务 `MNOTE_WEB_BIND=127.0.0.1:3036 MNOTE_WEB_PUBLIC_BIND=127.0.0.1:3036 cargo run --manifest-path rust/Cargo.toml -p mnote-web``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3036 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 结果:`task479` 全部检查 `ok:true`,覆盖 editor 上传到页面资源目录、文件树 folder drop 到目标目录、真实附件删除后缺失链接、无 active md 时附件 tab 打开、文件树滚动、文件名页头、删除单个附件引用等回归链路;运行时仍有系统 inotify watch limit fallback 与若干 500 日志,但 smoke 最终通过,属于既有环境限制/接口噪声,不作为本刀失败
- 2026-05-25Codex 主控继续收口 upload-target preflight request body 的纯数据组装层。
- 修改:`rust/crates/mnote-web/browser/filetree-runtime.js` 新增并导出 `fileTreeUploadTargetPreflightBody(detail, deps)``rust/crates/mnote-web/src/ssr/pages/layout.rs::preflightFileTreeUploadTarget` 优先委托该 helper 构造 POST bodyfetch、response 解析、错误处理与 fallback 仍留在 inline 壳层。
- 边界:未迁 `/api/tree/filetree/upload-target-preflight` 请求、`sidebarFileTreeSelection` 来源、`currentDocumentId()` / `resolveWorkspaceId()` 的壳层语义、`resolveFileTreeUploadTarget` 降级策略或上传编排;本批只外置 `workspaceId / targetDocumentId / targetRowId / focusedRowId / activeDocumentId / rows / documentWorkspaces` 的 body 对象构造。
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-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 filetree_runtime_contains_row_accessor_helpers -- --test-threads=1`、临时当前源码服务 `MNOTE_WEB_BIND=127.0.0.1:3038 MNOTE_WEB_PUBLIC_BIND=127.0.0.1:3038 cargo run --manifest-path rust/Cargo.toml -p mnote-web``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3038 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`
- 结果:`task479` 全部检查 `ok:true`,其中 `editor-upload-to-page-resource-dir``filetree-folder-drop-to-target` 继续确认本地 Markdown 附件上传目标与文件树文件夹拖入目标路径未回归。
- 2026-05-25Codex 主控继续收口 local mindmap asset fetch observer 的纯 helper 层。
- 修改:`rust/crates/mnote-web/browser/filetree-runtime.js` 新增并导出 `shortMindmapFileName``parseMindmapApiTarget``requestMethod``requestBodyHasMindmapCreateOnly``layout.rs` 中同名壳层优先委托 runtime helper,保留完整 inline fallback。
- 边界:未迁 `installMindmapAssetFetchObserver``withLocalMindmapSourceParams``mindmapAssetFromTarget``applyMindmapApiMutationToFileTree`、fetch hook、`currentSourceKind/currentRootUri/currentDocumentId``appendUploadedAssetRow``refreshLocalFolderSidebarSnapshot`;本批只迁纯 URL/方法/body/fileName 解析。
- 已验证:`node --check rust/crates/mnote-web/browser/filetree-runtime.js``cargo fmt --manifest-path rust/Cargo.toml --all --check``cargo test --manifest-path rust/Cargo.toml -p mnote-web filetree_runtime_contains_row_accessor_helpers -- --test-threads=1``cargo check --manifest-path rust/Cargo.toml -p mnote-web`、临时当前源码服务 `MNOTE_WEB_BIND=127.0.0.1:3038 MNOTE_WEB_PUBLIC_BIND=127.0.0.1:3038 cargo run --manifest-path rust/Cargo.toml -p mnote-web``MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3038 NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task455-local-folder-mindmap-clean-smoke.js`
- 结果:`task455` 通过,`mindmapId=思维导图093352.json`,磁盘中 `CleanPage.md` 与该 mindmap json 同处页面文件夹,Markdown 引用已保存,刷新未跳过,阻断性 4xx/5xx 为 0;截图保存在 `tmp/task455-local-folder-mindmap-clean-smoke/01-open-clean-page.png``04-after-refresh.png`。另试跑 `task169-mindmap-realtime-smoke.js` 时因 legacy tree command 依赖返回 `convex_unavailable`,不作为本刀失败证据。
@@ -490,6 +490,79 @@ function fileTreeDocumentWorkspacesForUploadPreflight(workspaceId, deps) {
});
}
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,
@@ -525,5 +598,10 @@ window.__mnoteFileTreeRuntime = {
fileTreeDocumentParentsForPreflight: fileTreeDocumentParentsForPreflight,
fileTreeTargetChildrenForPreflight: fileTreeTargetChildrenForPreflight,
fileTreeDropPreflightRows: fileTreeDropPreflightRows,
fileTreeDocumentWorkspacesForUploadPreflight: fileTreeDocumentWorkspacesForUploadPreflight
fileTreeDocumentWorkspacesForUploadPreflight: fileTreeDocumentWorkspacesForUploadPreflight,
fileTreeUploadTargetPreflightBody: fileTreeUploadTargetPreflightBody,
shortMindmapFileName: shortMindmapFileName,
parseMindmapApiTarget: parseMindmapApiTarget,
requestMethod: requestMethod,
requestBodyHasMindmapCreateOnly: requestBodyHasMindmapCreateOnly
};
+37 -1
View File
@@ -3133,8 +3133,15 @@ const SIDEBAR_TREE_JS: &str = r##"
}
async function preflightFileTreeUploadTarget(detail) {
var bodyRuntime = fileTreeRuntimeFunction('fileTreeUploadTargetPreflightBody');
var body = bodyRuntime ? bodyRuntime(detail || {}, Object.assign({}, fileTreeRuntimeDeps(), {
focusedRowId: sidebarFileTreeSelection.focusedRowId || null,
fileTreeRowsForUploadPreflight: fileTreeRowsForUploadPreflight,
currentDocumentId: currentDocumentId,
resolveWorkspaceId: resolveWorkspaceId
})) : (function() {
var workspaceId = String(detail && detail.workspaceId || resolveWorkspaceId(document.body) || '').trim();
var body = {
return {
workspaceId: workspaceId || null,
targetDocumentId: detail && detail.documentId ? String(detail.documentId) : null,
targetRowId: detail && detail.targetRowId ? String(detail.targetRowId) : null,
@@ -3143,6 +3150,7 @@ const SIDEBAR_TREE_JS: &str = r##"
rows: fileTreeRowsForUploadPreflight(),
documentWorkspaces: fileTreeDocumentWorkspacesForUploadPreflight(workspaceId)
};
})();
var response = await fetch('/api/tree/filetree/upload-target-preflight', {
method: 'POST',
credentials: 'include',
@@ -3743,6 +3751,8 @@ const SIDEBAR_TREE_JS: &str = r##"
}
function shortMindmapFileName(mindmapId) {
var runtimeFn = fileTreeRuntimeFunction('shortMindmapFileName');
if (runtimeFn) return runtimeFn(mindmapId);
var raw = String(mindmapId || '').trim();
var pathName = raw.indexOf('/') >= 0 ? raw.split('/').pop() : raw;
if (/\.json$/i.test(pathName)) return pathName;
@@ -3752,6 +3762,8 @@ const SIDEBAR_TREE_JS: &str = r##"
}
function parseMindmapApiTarget(input) {
var runtimeFn = fileTreeRuntimeFunction('parseMindmapApiTarget');
if (runtimeFn) return runtimeFn(input);
try {
var rawUrl = typeof input === 'string'
? input
@@ -3793,6 +3805,8 @@ const SIDEBAR_TREE_JS: &str = r##"
}
function requestMethod(input, init) {
var runtimeFn = fileTreeRuntimeFunction('requestMethod');
if (runtimeFn) return runtimeFn(input, init);
return String(
init && init.method
? init.method
@@ -3803,6 +3817,8 @@ const SIDEBAR_TREE_JS: &str = r##"
}
function requestBodyHasMindmapCreateOnly(init) {
var runtimeFn = fileTreeRuntimeFunction('requestBodyHasMindmapCreateOnly');
if (runtimeFn) return runtimeFn(init);
var body = init && typeof init.body === 'string' ? init.body : '';
if (!body) return false;
try {
@@ -11195,6 +11211,11 @@ mod tests {
assert!(
FILETREE_RUNTIME_JS.contains("function fileTreeDocumentWorkspacesForUploadPreflight")
);
assert!(FILETREE_RUNTIME_JS.contains("function fileTreeUploadTargetPreflightBody"));
assert!(FILETREE_RUNTIME_JS.contains("function shortMindmapFileName"));
assert!(FILETREE_RUNTIME_JS.contains("function parseMindmapApiTarget"));
assert!(FILETREE_RUNTIME_JS.contains("function requestMethod"));
assert!(FILETREE_RUNTIME_JS.contains("function requestBodyHasMindmapCreateOnly"));
assert!(FILETREE_RUNTIME_JS.contains("function readProjection"));
assert!(FILETREE_RUNTIME_JS.contains("function readSidebarDataset"));
assert!(FILETREE_RUNTIME_JS.contains("function readDatasetProjection"));
@@ -11229,10 +11250,25 @@ mod tests {
assert!(FILETREE_RUNTIME_JS.contains(
"fileTreeDocumentWorkspacesForUploadPreflight: fileTreeDocumentWorkspacesForUploadPreflight"
));
assert!(FILETREE_RUNTIME_JS
.contains("fileTreeUploadTargetPreflightBody: fileTreeUploadTargetPreflightBody"));
assert!(FILETREE_RUNTIME_JS.contains("shortMindmapFileName: shortMindmapFileName"));
assert!(FILETREE_RUNTIME_JS.contains("parseMindmapApiTarget: parseMindmapApiTarget"));
assert!(FILETREE_RUNTIME_JS.contains("requestMethod: requestMethod"));
assert!(FILETREE_RUNTIME_JS
.contains("requestBodyHasMindmapCreateOnly: requestBodyHasMindmapCreateOnly"));
assert!(SIDEBAR_TREE_JS
.contains("fileTreeRuntimeFunction('fileTreeDocumentWorkspacesForUploadPreflight')"));
assert!(SIDEBAR_TREE_JS
.contains("fileTreeRuntimeFunction('fileTreeUploadTargetPreflightBody')"));
assert!(SIDEBAR_TREE_JS
.contains("fileTreeRowsForUploadPreflight: fileTreeRowsForUploadPreflight"));
assert!(SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('shortMindmapFileName')"));
assert!(SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('parseMindmapApiTarget')"));
assert!(SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('requestMethod')"));
assert!(
SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('requestBodyHasMindmapCreateOnly')")
);
assert!(FILETREE_RUNTIME_JS
.contains("uploadIntent: String(detail.uploadIntent || 'filetree.folder.drop')"));
assert!(FILETREE_RUNTIME_JS