#!/usr/bin/env node "use strict"; const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const ROOT = process.cwd(); const blockMenuPath = path.join( ROOT, "rust/spikes/leptos-tiptap-spike/src/editor_runtime/block_handle_menu_view.rs", ); const routesPath = path.join(ROOT, "rust/crates/mnote-web/src/routes/mod.rs"); const stylePath = path.join( ROOT, "rust/spikes/leptos-tiptap-spike/src/editor_runtime/style.rs", ); const blockMenu = fs.readFileSync(blockMenuPath, "utf8"); const routes = fs.readFileSync(routesPath, "utf8"); const style = fs.readFileSync(stylePath, "utf8"); assert.match( blockMenu, /mnote:toast/, "复制链接必须触发全局可见 toast,而不是只改 command_feedback", ); assert.match( blockMenu, /已复制块链接/, "复制链接成功提示必须包含清晰的可见文案", ); ["move", "history", "comment"].forEach((id) => { assert.match( blockMenu, new RegExp('data-testid="block-' + id + '-panel"'), id + " 入口必须打开可见面板,避免点击后仅 active 无反馈", ); }); assert.doesNotMatch( blockMenu, /移动\/嵌入流程后续|块历史入口已记录|评论入口已打开|颜色子菜单后续/, "块菜单不能保留可点击但无真实 UI 的占位反馈", ); assert.match(blockMenu, /data-testid="block-color-panel"/, "颜色入口必须打开真实颜色面板"); assert.match(blockMenu, /apply_text_color\(editor, value\)/, "块菜单颜色面板必须能设置文字颜色"); assert.match(blockMenu, /apply_highlight_color\(editor, Some\(value\)\)/, "块菜单颜色面板必须能设置背景色"); assert.match( blockMenu, /data-testid="block-drag-menu-item-align-center"[\s\S]{0,240}selection_state\.get\(\)\.align_center/, "文字居中菜单项必须显示当前居中状态", ); assert.match( routes, /\/api\/documents\/buffer-state\/dirty:0/, "必须兼容旧浏览器误发的 /api/documents/buffer-state/dirty:0,避免控制台 404", ); assert.doesNotMatch( style, /@media \(max-width: 768px\)[\s\S]*?\.block-handle-shell,[\s\S]*?display: none;/, "移动端不能隐藏块手柄;点击正文后必须保留可触达的块菜单入口", ); assert.match( style, /@media \(max-width: 768px\)[\s\S]*?\.block-handle-trigger[\s\S]*?(?:width|height): (?:3[6-9]|4[0-9])px;/, "移动端块手柄触控目标至少应为 36px", ); console.log("task805 editor block menu static smoke passed");