主编辑区改造准备
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
use core_protocol::editor::{
|
||||
BlockProps, ContentNode, ContentNodePayload, EditorBlock, EditorBlockDocument,
|
||||
EditorBlockDocumentTiptapBridge, EditorBlockType, TextMark, TiptapCodeBlockAttrs,
|
||||
TiptapHeadingAttrs, TiptapNode, TiptapParagraphAttrs, TiptapTaskItemAttrs,
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[test]
|
||||
fn p05_blocks_round_trip_through_tiptap_doc() {
|
||||
let document = EditorBlockDocument {
|
||||
document_id: "doc_1".into(),
|
||||
root_block_ids: vec![
|
||||
"p1".into(),
|
||||
"h1".into(),
|
||||
"b1".into(),
|
||||
"n1".into(),
|
||||
"t1".into(),
|
||||
"q1".into(),
|
||||
"c1".into(),
|
||||
],
|
||||
blocks: vec![
|
||||
EditorBlock {
|
||||
block_id: "p1".into(),
|
||||
block_type: EditorBlockType::Paragraph,
|
||||
props: BlockProps::default(),
|
||||
content_nodes: vec![ContentNode {
|
||||
payload: ContentNodePayload::Text {
|
||||
text: "段落".into(),
|
||||
marks: vec![TextMark::Bold],
|
||||
},
|
||||
attrs: BTreeMap::new(),
|
||||
}],
|
||||
child_block_ids: vec![],
|
||||
},
|
||||
EditorBlock {
|
||||
block_id: "h1".into(),
|
||||
block_type: EditorBlockType::Heading,
|
||||
props: BlockProps {
|
||||
heading_level: Some(2),
|
||||
..BlockProps::default()
|
||||
},
|
||||
content_nodes: vec![ContentNode {
|
||||
payload: ContentNodePayload::Text {
|
||||
text: "标题".into(),
|
||||
marks: vec![],
|
||||
},
|
||||
attrs: BTreeMap::new(),
|
||||
}],
|
||||
child_block_ids: vec![],
|
||||
},
|
||||
EditorBlock {
|
||||
block_id: "b1".into(),
|
||||
block_type: EditorBlockType::BulletListItem,
|
||||
props: BlockProps::default(),
|
||||
content_nodes: vec![ContentNode {
|
||||
payload: ContentNodePayload::Text {
|
||||
text: "项目".into(),
|
||||
marks: vec![],
|
||||
},
|
||||
attrs: BTreeMap::new(),
|
||||
}],
|
||||
child_block_ids: vec![],
|
||||
},
|
||||
EditorBlock {
|
||||
block_id: "n1".into(),
|
||||
block_type: EditorBlockType::NumberedListItem,
|
||||
props: BlockProps::default(),
|
||||
content_nodes: vec![ContentNode {
|
||||
payload: ContentNodePayload::Text {
|
||||
text: "序号".into(),
|
||||
marks: vec![],
|
||||
},
|
||||
attrs: BTreeMap::new(),
|
||||
}],
|
||||
child_block_ids: vec![],
|
||||
},
|
||||
EditorBlock {
|
||||
block_id: "t1".into(),
|
||||
block_type: EditorBlockType::Todo,
|
||||
props: BlockProps {
|
||||
checked: Some(true),
|
||||
..BlockProps::default()
|
||||
},
|
||||
content_nodes: vec![ContentNode {
|
||||
payload: ContentNodePayload::Text {
|
||||
text: "待办".into(),
|
||||
marks: vec![],
|
||||
},
|
||||
attrs: BTreeMap::new(),
|
||||
}],
|
||||
child_block_ids: vec![],
|
||||
},
|
||||
EditorBlock {
|
||||
block_id: "q1".into(),
|
||||
block_type: EditorBlockType::Quote,
|
||||
props: BlockProps::default(),
|
||||
content_nodes: vec![ContentNode {
|
||||
payload: ContentNodePayload::Text {
|
||||
text: "引用".into(),
|
||||
marks: vec![],
|
||||
},
|
||||
attrs: BTreeMap::new(),
|
||||
}],
|
||||
child_block_ids: vec![],
|
||||
},
|
||||
EditorBlock {
|
||||
block_id: "c1".into(),
|
||||
block_type: EditorBlockType::CodeBlock,
|
||||
props: BlockProps {
|
||||
language: Some("rust".into()),
|
||||
..BlockProps::default()
|
||||
},
|
||||
content_nodes: vec![ContentNode {
|
||||
payload: ContentNodePayload::Text {
|
||||
text: "fn main() {}".into(),
|
||||
marks: vec![TextMark::Code],
|
||||
},
|
||||
attrs: BTreeMap::new(),
|
||||
}],
|
||||
child_block_ids: vec![],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let doc =
|
||||
EditorBlockDocumentTiptapBridge::to_tiptap_doc(&document).expect("export should work");
|
||||
let round_trip = EditorBlockDocumentTiptapBridge::from_tiptap_doc("doc_2", &doc)
|
||||
.expect("import should work");
|
||||
|
||||
assert_eq!(
|
||||
round_trip.root_block_ids,
|
||||
vec!["p1", "h1", "b1", "n1", "t1", "q1", "c1"]
|
||||
);
|
||||
assert_eq!(round_trip.blocks[0].block_id, "p1");
|
||||
assert_eq!(round_trip.blocks[0].content_nodes.len(), 1);
|
||||
match &round_trip.blocks[0].content_nodes[0].payload {
|
||||
ContentNodePayload::Text { marks, .. } => assert_eq!(marks, &vec![TextMark::Bold]),
|
||||
other => panic!("unexpected payload: {other:?}"),
|
||||
}
|
||||
assert_eq!(round_trip.blocks[1].props.heading_level, Some(2));
|
||||
assert_eq!(round_trip.blocks[4].props.checked, Some(true));
|
||||
assert_eq!(round_trip.blocks[6].props.language.as_deref(), Some("rust"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tiptap_import_preserves_explicit_block_ids_and_marks() {
|
||||
let doc = TiptapNode::Doc {
|
||||
content: vec![
|
||||
TiptapNode::Paragraph {
|
||||
attrs: TiptapParagraphAttrs {
|
||||
block_id: Some("p-1".into()),
|
||||
},
|
||||
content: vec![TiptapNode::Text {
|
||||
text: "Hello".into(),
|
||||
marks: vec![core_protocol::editor::TiptapMark {
|
||||
r#type: "italic".into(),
|
||||
}],
|
||||
}],
|
||||
},
|
||||
TiptapNode::Heading {
|
||||
attrs: TiptapHeadingAttrs {
|
||||
level: 3,
|
||||
block_id: Some("h-1".into()),
|
||||
},
|
||||
content: vec![TiptapNode::Text {
|
||||
text: "H".into(),
|
||||
marks: vec![],
|
||||
}],
|
||||
},
|
||||
TiptapNode::TaskList {
|
||||
attrs: core_protocol::editor::TiptapListAttrs {
|
||||
block_id: Some("t-1".into()),
|
||||
},
|
||||
content: vec![TiptapNode::TaskItem {
|
||||
attrs: TiptapTaskItemAttrs {
|
||||
checked: true,
|
||||
block_id: Some("t-1".into()),
|
||||
},
|
||||
content: vec![TiptapNode::Paragraph {
|
||||
attrs: TiptapParagraphAttrs {
|
||||
block_id: Some("t-1".into()),
|
||||
},
|
||||
content: vec![TiptapNode::Text {
|
||||
text: "todo".into(),
|
||||
marks: vec![],
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
TiptapNode::CodeBlock {
|
||||
attrs: TiptapCodeBlockAttrs {
|
||||
language: Some("ts".into()),
|
||||
block_id: Some("c-1".into()),
|
||||
},
|
||||
content: vec![TiptapNode::Text {
|
||||
text: "let x = 1;".into(),
|
||||
marks: vec![core_protocol::editor::TiptapMark {
|
||||
r#type: "code".into(),
|
||||
}],
|
||||
}],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let imported = EditorBlockDocumentTiptapBridge::from_tiptap_doc("doc_3", &doc).unwrap();
|
||||
assert_eq!(imported.root_block_ids, vec!["p-1", "h-1", "t-1", "c-1"]);
|
||||
assert_eq!(imported.blocks[0].block_id, "p-1");
|
||||
assert_eq!(imported.blocks[1].props.heading_level, Some(3));
|
||||
assert_eq!(imported.blocks[2].props.checked, Some(true));
|
||||
assert_eq!(imported.blocks[3].props.language.as_deref(), Some("ts"));
|
||||
|
||||
match &imported.blocks[0].content_nodes[0].payload {
|
||||
ContentNodePayload::Text { marks, .. } => assert_eq!(marks, &vec![TextMark::Italic]),
|
||||
other => panic!("unexpected payload: {other:?}"),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user