refactor: crates (#4258)

* chore: rename flowy-folder2 to flowy-folder

* chore: rename flowy-document2 to flowy-document

* chore: fix test

* chore: move lib-infra crate

* chore: remove shared-lib

* chore: fix clippy
This commit is contained in:
Nathan.fooo
2023-12-31 07:29:40 +08:00
committed by GitHub
parent 2f6a4f8c7b
commit 5facb61e23
460 changed files with 498 additions and 11141 deletions

View File

@ -0,0 +1,105 @@
use collab_document::blocks::DocumentData;
use flowy_document::parser::document_data_parser::DocumentDataParser;
use flowy_document::parser::json::parser::JsonToDocumentParser;
use flowy_document::parser::parser_entities::{NestedBlock, Range, Selection};
use std::sync::Arc;
#[tokio::test]
async fn document_data_parse_json_test() {
let initial_json_str = include_str!("../assets/json/initial_document.json");
let document_data = JsonToDocumentParser::json_str_to_document(initial_json_str)
.unwrap()
.into();
let parser = DocumentDataParser::new(Arc::new(document_data), None);
let read_me_json = serde_json::from_str::<NestedBlock>(initial_json_str).unwrap();
let json = parser.to_json().unwrap();
assert_eq!(read_me_json, json);
}
// range_1 is a range from the 2nd block to the 8th block
#[tokio::test]
async fn document_data_to_json_with_range_1_test() {
let initial_json_str = include_str!("../assets/json/initial_document.json");
let document_data: DocumentData = JsonToDocumentParser::json_str_to_document(initial_json_str)
.unwrap()
.into();
let children_map = &document_data.meta.children_map;
let page_block_id = &document_data.page_id;
let blocks = &document_data.blocks;
let page_block = blocks.get(page_block_id).unwrap();
let children = children_map.get(page_block.children.as_str()).unwrap();
let range = Range {
start: Selection {
block_id: children.get(1).unwrap().to_string(),
index: 4,
length: 15,
},
end: Selection {
block_id: children.get(7).unwrap().to_string(),
index: 0,
length: 11,
},
};
let parser = DocumentDataParser::new(Arc::new(document_data), Some(range));
let json = parser.to_json().unwrap();
let part_1 = include_str!("../assets/json/range_1.json");
let part_1_json = serde_json::from_str::<NestedBlock>(part_1).unwrap();
assert_eq!(part_1_json, json);
}
// range_2 is a range from the 4th block's first child to the 18th block's first child
#[tokio::test]
async fn document_data_to_json_with_range_2_test() {
let initial_json_str = include_str!("../assets/json/initial_document.json");
let document_data: DocumentData = JsonToDocumentParser::json_str_to_document(initial_json_str)
.unwrap()
.into();
let children_map = &document_data.meta.children_map;
let page_block_id = &document_data.page_id;
let blocks = &document_data.blocks;
let page_block = blocks.get(page_block_id).unwrap();
let start_block_parent_id = children_map
.get(page_block.children.as_str())
.unwrap()
.get(3)
.unwrap();
let start_block_parent = blocks.get(start_block_parent_id).unwrap();
let start_block_id = children_map
.get(start_block_parent.children.as_str())
.unwrap()
.first()
.unwrap();
let start = Selection {
block_id: start_block_id.to_string(),
index: 6,
length: 27,
};
let end_block_parent_id = children_map
.get(page_block.children.as_str())
.unwrap()
.get(17)
.unwrap();
let end_block_parent = blocks.get(end_block_parent_id).unwrap();
let end_block_children = children_map
.get(end_block_parent.children.as_str())
.unwrap();
let end_block_id = end_block_children.first().unwrap();
let end = Selection {
block_id: end_block_id.to_string(),
index: 0,
length: 11,
};
let range = Range { start, end };
let parser = DocumentDataParser::new(Arc::new(document_data), Some(range));
let json = parser.to_json().unwrap();
let part_2 = include_str!("../assets/json/range_2.json");
let part_2_json = serde_json::from_str::<NestedBlock>(part_2).unwrap();
assert_eq!(part_2_json, json);
}

View File

@ -0,0 +1 @@
mod parser_test;

View File

@ -0,0 +1,45 @@
use flowy_document::parser::external::parser::ExternalDataToNestedJSONParser;
use flowy_document::parser::parser_entities::{InputType, NestedBlock};
macro_rules! generate_test_cases {
($($ty:ident),*) => {
[
$(
(
include_str!(concat!("../../assets/json/", stringify!($ty), ".json")),
include_str!(concat!("../../assets/html/", stringify!($ty), ".html")),
)
),*
]
};
}
/// test convert data to json
/// - input html: <p>Hello</p><p> World!</p>
#[tokio::test]
async fn html_to_document_test() {
let test_cases = generate_test_cases!(notion, google_docs, simple);
for (json, html) in test_cases.iter() {
let parser = ExternalDataToNestedJSONParser::new(html.to_string(), InputType::Html);
let block = parser.to_nested_block();
assert!(block.is_some());
let block = block.unwrap();
let expect_block = serde_json::from_str::<NestedBlock>(json).unwrap();
assert_eq!(block, expect_block);
}
}
/// test convert data to json
/// - input plain text: Hello World!
#[tokio::test]
async fn plain_text_to_document_test() {
let plain_text = include_str!("../../assets/text/plain_text.txt");
let parser = ExternalDataToNestedJSONParser::new(plain_text.to_string(), InputType::PlainText);
let block = parser.to_nested_block();
assert!(block.is_some());
let block = block.unwrap();
let expect_json = include_str!("../../assets/json/plain_text.json");
let expect_block = serde_json::from_str::<NestedBlock>(expect_json).unwrap();
assert_eq!(block, expect_block);
}

View File

@ -0,0 +1,103 @@
use serde_json::json;
use flowy_document::parser::json::block::SerdeBlock;
#[test]
fn test_empty_data_and_children() {
let json = json!({
"type": "page",
});
let block = serde_json::from_value::<SerdeBlock>(json).unwrap();
assert_eq!(block.ty, "page");
assert!(block.data.is_empty());
assert!(block.children.is_empty());
}
#[test]
fn test_data() {
let json = json!({
"type": "todo_list",
"data": {
"delta": [{ "insert": "Click anywhere and just start typing." }],
"checked": false
}
});
let block = serde_json::from_value::<SerdeBlock>(json).unwrap();
assert_eq!(block.ty, "todo_list");
assert_eq!(block.data.len(), 2);
assert_eq!(block.data.get("checked").unwrap(), false);
assert_eq!(
block.data.get("delta").unwrap().to_owned(),
json!([{ "insert": "Click anywhere and just start typing." }])
);
assert!(block.children.is_empty());
}
#[test]
fn test_children() {
let json = json!({
"type": "page",
"children": [
{
"type": "heading",
"data": {
"delta": [{ "insert": "Welcome to AppFlowy!" }],
"level": 1
}
},
{
"type": "todo_list",
"data": {
"delta": [{ "insert": "Welcome to AppFlowy!" }],
"checked": false
}
}
]});
let block = serde_json::from_value::<SerdeBlock>(json).unwrap();
assert!(block.data.is_empty());
assert_eq!(block.ty, "page");
assert_eq!(block.children.len(), 2);
// heading
let heading = &block.children[0];
assert_eq!(heading.ty, "heading");
assert_eq!(heading.data.len(), 2);
// todo_list
let todo_list = &block.children[1];
assert_eq!(todo_list.ty, "todo_list");
assert_eq!(todo_list.data.len(), 2);
}
#[test]
fn test_nested_children() {
let json = json!({
"type": "page",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "paragraph"
}
]
}
]
}
]
}
]
});
let block = serde_json::from_value::<SerdeBlock>(json).unwrap();
assert!(block.data.is_empty());
assert_eq!(block.ty, "page");
assert_eq!(
block.children[0].children[0].children[0].children[0].ty,
"paragraph"
);
}

View File

@ -0,0 +1,2 @@
mod block_test;
mod parser_test;

View File

@ -0,0 +1,123 @@
use collab_document::blocks::json_str_to_hashmap;
use flowy_document::parser::json::parser::JsonToDocumentParser;
use serde_json::json;
#[test]
fn test_parser_children_in_order() {
let json = json!({
"type": "page",
"children": [
{
"type": "paragraph1",
},
{
"type": "paragraph2",
},
{
"type": "paragraph3",
},
{
"type": "paragraph4",
}
]
});
let document = JsonToDocumentParser::json_str_to_document(json.to_string().as_str()).unwrap();
// root + 4 paragraphs
assert_eq!(document.blocks.len(), 5);
// root + 4 paragraphs
assert_eq!(document.meta.children_map.len(), 5);
let (page_id, page_block) = document
.blocks
.iter()
.find(|(_, block)| block.ty == "page")
.unwrap();
// the children should be in order
let page_children = document
.meta
.children_map
.get(page_block.children_id.as_str())
.unwrap();
assert_eq!(page_children.children.len(), 4);
for (i, child_id) in page_children.children.iter().enumerate() {
let child = document.blocks.get(child_id).unwrap();
assert_eq!(child.ty, format!("paragraph{}", i + 1));
assert_eq!(child.parent_id, page_id.to_owned());
}
}
#[test]
fn test_parser_nested_children() {
let json = json!({
"type": "page",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "paragraph",
"children": [
{
"type": "paragraph"
}
]
}
]
}
]
}
]
});
let document = JsonToDocumentParser::json_str_to_document(json.to_string().as_str()).unwrap();
// root + 4 paragraphs
assert_eq!(document.blocks.len(), 5);
// root + 4 paragraphs
assert_eq!(document.meta.children_map.len(), 5);
let (page_id, page_block) = document
.blocks
.iter()
.find(|(_, block)| block.ty == "page")
.unwrap();
// first child of root is a paragraph
let page_children = document
.meta
.children_map
.get(page_block.children_id.as_str())
.unwrap();
assert_eq!(page_children.children.len(), 1);
let page_first_child_id = page_children.children.first().unwrap();
let page_first_child = document.blocks.get(page_first_child_id).unwrap();
assert_eq!(page_first_child.ty, "paragraph");
assert_eq!(page_first_child.parent_id, page_id.to_owned());
}
#[tokio::test]
async fn parse_readme_test() {
let json = include_str!("../../../../flowy-core/assets/read_me.json");
let document = JsonToDocumentParser::json_str_to_document(json).unwrap();
document.blocks.iter().for_each(|(_, block)| {
let data = json_str_to_hashmap(&block.data).ok();
assert!(data.is_some());
if let Some(data) = data {
assert!(data.get("delta").is_none());
}
if let Some(external_id) = &block.external_id {
let text = document.meta.text_map.get(external_id);
assert!(text.is_some());
}
});
}

View File

@ -0,0 +1,4 @@
mod document_data_parser_test;
mod html;
mod json;
mod parse_to_html_text;

View File

@ -0,0 +1,2 @@
mod test;
mod utils;

View File

@ -0,0 +1,37 @@
use crate::parser::parse_to_html_text::utils::{assert_document_html_eq, assert_document_text_eq};
macro_rules! generate_test_cases {
($($block_ty:ident),*) => {
[
$(
(
include_str!(concat!("../../assets/json/", stringify!($block_ty), ".json")),
include_str!(concat!("../../assets/html/", stringify!($block_ty), ".html")),
include_str!(concat!("../../assets/text/", stringify!($block_ty), ".txt")),
)
),*
]
};
}
#[tokio::test]
async fn block_tests() {
let test_cases = generate_test_cases!(
heading,
callout,
paragraph,
divider,
image,
math_equation,
code,
bulleted_list,
numbered_list,
todo_list,
toggle_list,
quote
);
for (json_data, expect_html, expect_text) in test_cases.iter() {
assert_document_html_eq(json_data, expect_html);
assert_document_text_eq(json_data, expect_text);
}
}

View File

@ -0,0 +1,21 @@
use flowy_document::parser::document_data_parser::DocumentDataParser;
use flowy_document::parser::json::parser::JsonToDocumentParser;
use std::sync::Arc;
pub fn assert_document_html_eq(source: &str, expect: &str) {
let document_data = JsonToDocumentParser::json_str_to_document(source)
.unwrap()
.into();
let parser = DocumentDataParser::new(Arc::new(document_data), None);
let html = parser.to_html();
assert_eq!(expect, html);
}
pub fn assert_document_text_eq(source: &str, expect: &str) {
let document_data = JsonToDocumentParser::json_str_to_document(source)
.unwrap()
.into();
let parser = DocumentDataParser::new(Arc::new(document_data), None);
let text = parser.to_text();
assert_eq!(expect, text);
}