收口 MNote P0 P1 P2 审查尾项

- 归档 OnlyOffice live bridge、Page AI、mindmap、design governance 与相关 bug 条目
- 补齐 MinerU OCR 后端 runtime 合同与 smoke/test 基线
- 收口 ChatOnly/Doubao、ObjectIdentity、Page Aggregate compat 与 runtime owner 文档口径

验证:
- cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1
- cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_bridge -- --test-threads=1
- git diff --check
- git diff --cached --check
- codegraph index . --force && codegraph status .
- codegraph sync . && codegraph status .
This commit is contained in:
lix-2026
2026-06-01 09:29:12 +08:00
parent 49a0545148
commit 1882db7681
143 changed files with 29810 additions and 3228 deletions
+120 -1
View File
@@ -1623,6 +1623,104 @@ pub async fn sidebar_page_ai_runtime_asset() -> Response {
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_ai_markdown_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-ai-markdown-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, runtime_asset_cache_control())
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(browser_runtime_js_body(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_ai_render_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-ai-render-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, runtime_asset_cache_control())
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(browser_runtime_js_body(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_ai_permission_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-ai-permission-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, runtime_asset_cache_control())
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(browser_runtime_js_body(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_ai_profile_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-ai-profile-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, runtime_asset_cache_control())
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(browser_runtime_js_body(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_ai_session_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-ai-session-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, runtime_asset_cache_control())
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(browser_runtime_js_body(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_ai_skill_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-ai-skill-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, runtime_asset_cache_control())
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(browser_runtime_js_body(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_ai_target_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-ai-target-runtime.js");
Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
"application/javascript; charset=utf-8",
)
.header(header::CACHE_CONTROL, runtime_asset_cache_control())
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
.body(browser_runtime_js_body(JS))
.unwrap_or_else(|_| Response::new(Body::empty()))
}
pub async fn sidebar_page_settings_runtime_asset() -> Response {
const JS: &str = include_str!("../../browser/sidebar-page-settings-runtime.js");
Response::builder()
@@ -3151,8 +3249,18 @@ mod tests {
"const pageBodyTiptapDocument = (body, fallbackText = '', context = null) => {"
));
assert!(conversion_runtime.contains("body?.blockDocument || body?.block_document"));
let block_document_source_index = conversion_runtime
.find("if (blockDocument) return 'page_aggregate.block_document';")
.expect("blockDocument source should be explicit");
let local_markdown_source_index = conversion_runtime
.find("return 'local_markdown.content';")
.expect("local markdown legacy fallback should remain explicit");
assert!(
conversion_runtime.contains("localizeTiptapAssetUrls(toTiptapDocument(body.content")
block_document_source_index < local_markdown_source_index,
"local-first 浏览器转换应优先消费 blockDocument,再降级到 body.content"
);
assert!(
conversion_runtime.contains("localizeTiptapAssetUrls(toTiptapDocument(body?.content")
);
assert!(conversion_runtime.contains("localAttachmentClassForTiptapHref"));
assert!(conversion_runtime.contains("mnote-uploaded-attachment-code"));
@@ -4428,4 +4536,15 @@ mod tests {
"block.contentNodes.map((node) => typeof node?.text === 'string' ? node.text : '').join('')"
));
}
#[test]
fn mindmap_resize_runtime_contract_includes_dimension_attrs() {
let runtime = DOCUMENT_TIPTAP_CONVERSION_RUNTIME_JS;
assert!(runtime.contains("mindmapWidth"));
assert!(runtime.contains("mindmapHeight"));
assert!(runtime.contains("data?.mindmap_width"));
assert!(runtime.contains("dataset.mnoteMindmapWidth"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("--mnote-mindmap-block-max-width"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("currentPageWidthPreferences().mindmap"));
}
}