refactor: activate tiptap runtime modules
This commit is contained in:
+9
-24
@@ -314,10 +314,6 @@ function __wbg_get_imports() {
|
||||
const ret = arg0.anchorNode;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
},
|
||||
__wbg_appendChild_e95c8b3b936d250a: function() { return handleError(function (arg0, arg1) {
|
||||
const ret = arg0.appendChild(arg1);
|
||||
return ret;
|
||||
}, arguments); },
|
||||
__wbg_assign_d4fed0f8abb71719: function() { return handleError(function (arg0, arg1, arg2) {
|
||||
arg0.assign(getStringFromWasm0(arg1, arg2));
|
||||
}, arguments); },
|
||||
@@ -608,13 +604,6 @@ function __wbg_get_imports() {
|
||||
__wbg_init_bridge_runtime_777169bfaa015be2: function() { return handleError(function () {
|
||||
init_bridge_runtime();
|
||||
}, arguments); },
|
||||
__wbg_innerHTML_df4703c8599a85c4: function(arg0, arg1) {
|
||||
const ret = arg1.innerHTML;
|
||||
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||
},
|
||||
__wbg_innerHeight_72e7bb88c4b9ede8: function() { return handleError(function (arg0) {
|
||||
const ret = arg0.innerHeight;
|
||||
return ret;
|
||||
@@ -1029,10 +1018,6 @@ function __wbg_get_imports() {
|
||||
__wbg_removeAttribute_c75ac657c944b3f1: function() { return handleError(function (arg0, arg1, arg2) {
|
||||
arg0.removeAttribute(getStringFromWasm0(arg1, arg2));
|
||||
}, arguments); },
|
||||
__wbg_removeChild_172df530ec85cc8a: function() { return handleError(function (arg0, arg1) {
|
||||
const ret = arg0.removeChild(arg1);
|
||||
return ret;
|
||||
}, arguments); },
|
||||
__wbg_removeEventListener_0069d57d090a1674: function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||
arg0.removeEventListener(getStringFromWasm0(arg1, arg2), arg3, arg4 !== 0);
|
||||
}, arguments); },
|
||||
@@ -1259,47 +1244,47 @@ function __wbg_get_imports() {
|
||||
}
|
||||
}, arguments); },
|
||||
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 1145, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 1144, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h396914cf76a9e7a5);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000002: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 1197, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 1196, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h3a3182d847094e12);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000003: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 973, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 972, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`.
|
||||
const ret = makeClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__had771ddc65647798);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000004: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 1095, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 1094, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h0abd2b2fe4652e2a);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000005: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 1145, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 1144, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h396914cf76a9e7a5_4);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000006: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 294, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("KeyboardEvent")], shim_idx: 598, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__hd90af689bc3e71bf);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000007: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 1097, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 1096, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h794babeffd4f821f);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000008: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 1112, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 1111, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`.
|
||||
const ret = makeClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h2b648e7ac8ec1fb5);
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_cast_0000000000000009: function(arg0, arg1) {
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 1148, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [], shim_idx: 1147, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||
const ret = makeMutClosure(arg0, arg1, wasm_bindgen__convert__closures_____invoke__h0b7fb40a8610550c);
|
||||
return ret;
|
||||
},
|
||||
|
||||
BIN
Binary file not shown.
@@ -1,120 +0,0 @@
|
||||
//! 基于 HTML 字符串的 block menu legacy helper。
|
||||
//!
|
||||
//! 这些函数通过浏览器 DOM API 操作编辑器完整 HTML 字符串:
|
||||
//! `window.document.createElement("div") + innerHTML 解析 -> DOM 修改 ->
|
||||
//! innerHTML 回读`。这是 history-safe Tiptap command 之前的过渡路径,
|
||||
//! 新代码应优先使用 command-based mutation,不要继续扩展整文 HTML 替换。
|
||||
//!
|
||||
//! # History 风险
|
||||
//!
|
||||
//! HTML 字符串往返会丢失 ProseMirror 内部状态,包括 marks、decorations、
|
||||
//! selection 和 undo history。调用方随后必须通过 `apply_html_update` 用原始
|
||||
//! HTML 重置编辑器,因此也会破坏撤销历史。本模块只用于隔离待替换的 legacy
|
||||
//! helper。
|
||||
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::{window, Element};
|
||||
|
||||
use crate::editor_runtime::block_hover_state::DropPlacement;
|
||||
|
||||
/// 复制第 `index` 个顶层 HTML 块并插入其后。
|
||||
///
|
||||
/// 纯 DOM 操作:解析 `current_html` 为 `<div>` 子元素,克隆目标块,
|
||||
/// 插入到下一个同级节点前(或末尾),返回序列化 HTML。
|
||||
pub(crate) fn duplicate_top_level_block_html(
|
||||
current_html: &str,
|
||||
index: usize,
|
||||
) -> Result<String, String> {
|
||||
let document = window()
|
||||
.and_then(|win| win.document())
|
||||
.ok_or_else(|| "浏览器 document 不可用".to_string())?;
|
||||
let container = document
|
||||
.create_element("div")
|
||||
.map_err(|err| format!("创建 HTML 容器失败:{err:?}"))?;
|
||||
container.set_inner_html(current_html);
|
||||
|
||||
let children = container.children();
|
||||
let current = children
|
||||
.item(index as u32)
|
||||
.ok_or_else(|| format!("找不到第 {index} 个 HTML 顶层块"))?;
|
||||
let cloned = current
|
||||
.clone_node_with_deep(true)
|
||||
.map_err(|err| format!("复制 HTML 块失败:{err:?}"))?
|
||||
.dyn_into::<Element>()
|
||||
.map_err(|_| "复制出的节点不是 Element".to_string())?;
|
||||
|
||||
if let Some(next_sibling) = children.item(index as u32 + 1) {
|
||||
container
|
||||
.insert_before(&cloned, Some(&next_sibling))
|
||||
.map_err(|err| format!("插入复制块失败:{err:?}"))?;
|
||||
} else {
|
||||
container
|
||||
.append_child(&cloned)
|
||||
.map_err(|err| format!("追加复制块失败:{err:?}"))?;
|
||||
}
|
||||
|
||||
Ok(container.inner_html())
|
||||
}
|
||||
|
||||
/// 在 HTML 层将第 `source` 个顶层块移动到第 `target` 个块的前/后。
|
||||
///
|
||||
/// 纯 DOM 操作:解析 `current_html`,克隆拖拽块,移除原始块,
|
||||
/// 在调整后的位置插入克隆,返回序列化 HTML。
|
||||
pub(crate) fn reorder_top_level_block_html(
|
||||
current_html: &str,
|
||||
source: usize,
|
||||
target: usize,
|
||||
placement: DropPlacement,
|
||||
) -> Result<String, String> {
|
||||
let document = window()
|
||||
.and_then(|win| win.document())
|
||||
.ok_or_else(|| "浏览器 document 不可用".to_string())?;
|
||||
let container = document
|
||||
.create_element("div")
|
||||
.map_err(|err| format!("创建 HTML 容器失败:{err:?}"))?;
|
||||
container.set_inner_html(current_html);
|
||||
|
||||
let initial_children = container.children();
|
||||
let block_count = initial_children.length() as usize;
|
||||
if source >= block_count || target >= block_count {
|
||||
return Err("拖拽目标超出当前顶层块范围".to_string());
|
||||
}
|
||||
|
||||
let current = initial_children
|
||||
.item(source as u32)
|
||||
.ok_or_else(|| format!("找不到第 {source} 个 HTML 顶层块"))?;
|
||||
let moving = current
|
||||
.clone_node_with_deep(true)
|
||||
.map_err(|err| format!("复制拖拽块失败:{err:?}"))?
|
||||
.dyn_into::<Element>()
|
||||
.map_err(|_| "复制出的拖拽块不是 Element".to_string())?;
|
||||
|
||||
container
|
||||
.remove_child(¤t)
|
||||
.map_err(|err| format!("移除原始拖拽块失败:{err:?}"))?;
|
||||
|
||||
let mut insert_at = match placement {
|
||||
DropPlacement::Before => target,
|
||||
DropPlacement::After => target + 1,
|
||||
};
|
||||
if source < insert_at {
|
||||
insert_at = insert_at.saturating_sub(1);
|
||||
}
|
||||
|
||||
let current_children = container.children();
|
||||
let current_len = current_children.length() as usize;
|
||||
if insert_at >= current_len {
|
||||
container
|
||||
.append_child(&moving)
|
||||
.map_err(|err| format!("追加拖拽块失败:{err:?}"))?;
|
||||
} else {
|
||||
let next_sibling = current_children
|
||||
.item(insert_at as u32)
|
||||
.ok_or_else(|| format!("找不到第 {insert_at} 个 HTML 插入位置"))?;
|
||||
container
|
||||
.insert_before(&moving, Some(&next_sibling))
|
||||
.map_err(|err| format!("插入拖拽块失败:{err:?}"))?;
|
||||
}
|
||||
|
||||
Ok(container.inner_html())
|
||||
}
|
||||
@@ -122,7 +122,6 @@ pub(crate) fn move_top_level_block_with_history(
|
||||
target_index: usize,
|
||||
placement: DropPlacement,
|
||||
) -> Result<(), String> {
|
||||
// 读取并克隆源块内容
|
||||
let document = editor
|
||||
.get_json()
|
||||
.map_err(|err| format!("读取当前 JSON 失败:{err}"))?;
|
||||
@@ -135,32 +134,47 @@ pub(crate) fn move_top_level_block_with_history(
|
||||
}
|
||||
let source_block = content[source_index].clone();
|
||||
|
||||
// 删除源块
|
||||
let mut insert_at = match placement {
|
||||
DropPlacement::Before => target_index,
|
||||
DropPlacement::After => target_index + 1,
|
||||
};
|
||||
if source_index < insert_at {
|
||||
insert_at = insert_at.saturating_sub(1);
|
||||
}
|
||||
|
||||
if insert_at == source_index {
|
||||
return editor
|
||||
.focus()
|
||||
.map_err(|err| format!("聚焦编辑器失败:{err}"));
|
||||
}
|
||||
|
||||
delete_top_level_block_with_history(editor, source_index)?;
|
||||
|
||||
// 重新计算目标位置(删除后索引可能偏移)
|
||||
let adjusted_target =
|
||||
if source_index < target_index {
|
||||
target_index - 1
|
||||
} else {
|
||||
target_index
|
||||
};
|
||||
let document = editor
|
||||
.get_json()
|
||||
.map_err(|err| format!("重新读取 JSON 失败:{err}"))?;
|
||||
let range = top_level_block_full_range(&document, adjusted_target)
|
||||
.ok_or_else(|| format!("无法计算第 {adjusted_target} 个块的插入位置"))?;
|
||||
|
||||
let insert_at = match placement {
|
||||
DropPlacement::Before => range.from,
|
||||
DropPlacement::After => range.to,
|
||||
let content_len_after_move = document
|
||||
.get("content")
|
||||
.and_then(Value::as_array)
|
||||
.map(Vec::len)
|
||||
.unwrap_or(0);
|
||||
let insert_position = if content_len_after_move == 0 {
|
||||
0
|
||||
} else if insert_at >= content_len_after_move {
|
||||
top_level_block_full_range(&document, content_len_after_move - 1)
|
||||
.map(|range| range.to)
|
||||
.ok_or_else(|| "无法计算文档末尾插入位置".to_string())?
|
||||
} else {
|
||||
top_level_block_full_range(&document, insert_at)
|
||||
.map(|range| range.from)
|
||||
.ok_or_else(|| format!("无法计算第 {insert_at} 个块的插入位置"))?
|
||||
};
|
||||
|
||||
editor
|
||||
.insert_content_at(
|
||||
TiptapRange {
|
||||
from: insert_at,
|
||||
to: insert_at,
|
||||
from: insert_position,
|
||||
to: insert_position,
|
||||
},
|
||||
TiptapContent::json(source_block),
|
||||
Some(TiptapInsertContentOptions {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
use leptos::prelude::*;
|
||||
use leptos::ev;
|
||||
use leptos::mount::{mount_to, UnmountHandle};
|
||||
use leptos::mount::mount_to;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use serde_wasm_bindgen;
|
||||
|
||||
@@ -4,12 +4,13 @@ pub(crate) mod block_dnd;
|
||||
pub(crate) mod block_hover_state;
|
||||
pub(crate) mod block_menu_document;
|
||||
pub(crate) mod block_menu_overlay;
|
||||
pub(crate) mod block_menu_legacy_html;
|
||||
pub(crate) mod bridge_events;
|
||||
pub(crate) mod command_sync;
|
||||
pub(crate) mod content_layout;
|
||||
pub(crate) mod dom_events;
|
||||
pub(crate) mod dom_selection;
|
||||
pub(crate) mod editor_focus;
|
||||
pub(crate) mod history_safe_commands;
|
||||
pub(crate) mod mindmap_node_view;
|
||||
pub(crate) mod overlays;
|
||||
pub(crate) mod persistence;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user