feat: updated to newest notion-client version
This commit is contained in:
parent
0966a27e99
commit
5b4ab0302c
236
src/lib.rs
236
src/lib.rs
|
@ -1,109 +1,114 @@
|
||||||
|
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {}
|
||||||
}
|
|
||||||
|
|
||||||
use notion;
|
use notion;
|
||||||
use notion::BlockType;
|
use notion::BlockType;
|
||||||
|
|
||||||
pub fn convert_rich_text(text: ¬ion::RichText) -> String {
|
pub fn convert_rich_text(text: ¬ion::RichText) -> String {
|
||||||
match text {
|
match text {
|
||||||
notion::RichText::Text(text, _) => {
|
notion::RichText::Text {
|
||||||
|
text, annotations, ..
|
||||||
|
} => {
|
||||||
let mut string = text.content.to_owned();
|
let mut string = text.content.to_owned();
|
||||||
|
|
||||||
if text.annotations.bold {
|
if annotations.bold {
|
||||||
string = format!("**{string}**");
|
string = format!("**{string}**");
|
||||||
}
|
}
|
||||||
|
|
||||||
if text.annotations.italic {
|
if annotations.italic {
|
||||||
string = format!("*{string}*");
|
string = format!("*{string}*");
|
||||||
}
|
}
|
||||||
|
|
||||||
if text.annotations.code {
|
if annotations.code {
|
||||||
string = format!("`{string}`");
|
string = format!("`{string}`");
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
},
|
}
|
||||||
_ => "".to_string()
|
_ => "".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion]
|
#[async_recursion]
|
||||||
pub async fn convert_blocks(notion: ¬ion::Client, blocks: &Vec<notion::Block>) -> Result<String, Error> {
|
pub async fn convert_blocks(
|
||||||
|
notion: ¬ion::Client,
|
||||||
|
blocks: &Vec<notion::Block>,
|
||||||
|
) -> Result<String, Error> {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
for block in blocks.iter() {
|
for block in blocks.iter() {
|
||||||
let string = match &block.value {
|
let string = match &block.block {
|
||||||
BlockType::Heading1(heading) |
|
BlockType::Heading1 { heading }
|
||||||
BlockType::Heading2(heading) |
|
| BlockType::Heading2 { heading }
|
||||||
BlockType::Heading3(heading) => {
|
| BlockType::Heading3 { heading } => {
|
||||||
let content = heading.rich_text
|
let content = heading
|
||||||
|
.rich_text
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
let markdown_heading = match &block.value {
|
let markdown_heading = match &block.block {
|
||||||
BlockType::Heading1(_) => "#",
|
BlockType::Heading1 { .. } => "#",
|
||||||
BlockType::Heading2(_) => "##",
|
BlockType::Heading2 { .. } => "##",
|
||||||
BlockType::Heading3(_) | _ => "###",
|
BlockType::Heading3 { .. } | _ => "###",
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(format!("{markdown_heading} {content}"))
|
Some(format!("{markdown_heading} {content}"))
|
||||||
},
|
}
|
||||||
BlockType::Paragraph(paragraph) => {
|
BlockType::Paragraph { paragraph, .. } => Some(
|
||||||
Some(
|
paragraph
|
||||||
paragraph.rich_text
|
.rich_text
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>()
|
.collect::<String>(),
|
||||||
)
|
),
|
||||||
},
|
BlockType::Code { code, .. } => {
|
||||||
BlockType::Code(code) => {
|
|
||||||
let language = serde_variant::to_variant_name(&code.language).unwrap();
|
let language = serde_variant::to_variant_name(&code.language).unwrap();
|
||||||
let content = code.rich_text
|
let content = code
|
||||||
|
.rich_text
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
Some(
|
Some(format!("```{language}\n{content}\n```"))
|
||||||
format!("```{language}\n{content}\n```")
|
}
|
||||||
)
|
BlockType::BulletedListItem {
|
||||||
},
|
bulleted_list_item, ..
|
||||||
BlockType::BulletedListItem(list_item) => {
|
} => {
|
||||||
let content = list_item.rich_text
|
let content = bulleted_list_item
|
||||||
|
.rich_text
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
// TODO: Recurse down to `children`
|
// TODO: Recurse down to `children`
|
||||||
|
|
||||||
Some(
|
Some(format!("* {content}"))
|
||||||
format!("* {content}")
|
}
|
||||||
)
|
BlockType::NumberedListItem {
|
||||||
},
|
numbered_list_item, ..
|
||||||
BlockType::NumberedListItem(list_item) => {
|
} => {
|
||||||
// TODO: Hold state for numbering
|
// TODO: Hold state for numbering
|
||||||
let content = list_item.rich_text
|
let content = numbered_list_item
|
||||||
|
.rich_text
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
// TODO: Recurse down to `children`
|
// TODO: Recurse down to `children`
|
||||||
|
|
||||||
Some(
|
Some(format!("1. {content}"))
|
||||||
format!("1. {content}")
|
}
|
||||||
)
|
BlockType::ToDo { to_do, .. } => {
|
||||||
},
|
let content = to_do
|
||||||
BlockType::ToDo(todo_item) => {
|
.rich_text
|
||||||
let content = todo_item.rich_text
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
let checked = if todo_item.checked.unwrap_or(false) {
|
let checked = if to_do.checked.unwrap_or(false) {
|
||||||
"x"
|
"x"
|
||||||
} else {
|
} else {
|
||||||
" "
|
" "
|
||||||
|
@ -111,32 +116,30 @@ pub async fn convert_blocks(notion: ¬ion::Client, blocks: &Vec<notion::Block>
|
||||||
|
|
||||||
// TODO: Recurse down to `children`
|
// TODO: Recurse down to `children`
|
||||||
|
|
||||||
Some(
|
Some(format!("[{checked}] {content}"))
|
||||||
format!("[{checked}] {content}")
|
}
|
||||||
)
|
BlockType::Quote { quote, .. } => {
|
||||||
},
|
let content = quote
|
||||||
BlockType::Quote(quote) => {
|
.rich_text
|
||||||
let content = quote.rich_text
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
// TODO: Recurse down to `children`
|
// TODO: Recurse down to `children`
|
||||||
|
|
||||||
Some(
|
Some(format!("> {content}"))
|
||||||
format!("> {content}")
|
}
|
||||||
)
|
BlockType::Callout { callout, .. } => {
|
||||||
},
|
let content = callout
|
||||||
BlockType::Callout(callout) => {
|
.rich_text
|
||||||
let content = callout.rich_text
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|text| convert_rich_text(text))
|
.map(|text| convert_rich_text(text))
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
let icon = if let Some(value) = &callout.icon {
|
let icon = if let Some(value) = &callout.icon {
|
||||||
match value {
|
match value {
|
||||||
notion::Icon::Emoji(emoji) => emoji,
|
notion::Icon::Emoji { emoji, .. } => emoji,
|
||||||
_ => ""
|
_ => "",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
|
@ -144,42 +147,53 @@ pub async fn convert_blocks(notion: ¬ion::Client, blocks: &Vec<notion::Block>
|
||||||
|
|
||||||
// TODO: Recurse down to `children`
|
// TODO: Recurse down to `children`
|
||||||
|
|
||||||
Some(
|
Some(format!("> {icon} {content}"))
|
||||||
format!("> {icon} {content}")
|
}
|
||||||
)
|
BlockType::Image { image, .. } => {
|
||||||
},
|
match &image {
|
||||||
BlockType::Image(image) => {
|
notion::File::External { external, .. } => {
|
||||||
match &image.image {
|
let url = &external.url;
|
||||||
notion::File::External(url) => Some(format!(r#"<img style="margin: 0 auto" src="{url}">"#)),
|
Some(format!(r#"<img style="margin: 0 auto" src="{url}">"#))
|
||||||
|
}
|
||||||
// TODO: Implement reupload of Notion file type
|
// TODO: Implement reupload of Notion file type
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
BlockType::Video(video) => {
|
BlockType::Video { video, .. } => {
|
||||||
match &video.video {
|
match &video {
|
||||||
notion::File::External(url) => Some(format!(r#"<video controls src="{url}" />"#)),
|
notion::File::External { external, .. } => {
|
||||||
|
let url = &external.url;
|
||||||
|
Some(format!(r#"<video controls src="{url}" />"#))
|
||||||
|
}
|
||||||
// TODO: Implement reupload of Notion file type
|
// TODO: Implement reupload of Notion file type
|
||||||
_ => None
|
_ => None,
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
BlockType::Divider => Some("---".to_string()),
|
BlockType::Divider => Some("---".to_string()),
|
||||||
BlockType::Unsupported(string) => {
|
BlockType::Unsupported => {
|
||||||
println!("Did not catch {string}");
|
// println!("Did not catch {string}");
|
||||||
None
|
None
|
||||||
},
|
}
|
||||||
BlockType::ColumnList(_) => {
|
BlockType::ColumnList { .. } => {
|
||||||
if block.has_children {
|
if block.has_children {
|
||||||
let columns = notion
|
let columns = notion
|
||||||
.blocks()
|
.blocks
|
||||||
.children()
|
.children()
|
||||||
.list(notion::BlockChildrenListOptions { block_id: &block.id })
|
.list(notion::BlockChildrenListOptions {
|
||||||
|
block_id: &block.id,
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.results;
|
.results;
|
||||||
|
|
||||||
let mut content = vec![];
|
let mut content = vec![];
|
||||||
for column in columns.iter() {
|
for column in columns.iter() {
|
||||||
let children = notion.blocks().children().list(notion::BlockChildrenListOptions { block_id: &column.id })
|
let children = notion
|
||||||
|
.blocks
|
||||||
|
.children()
|
||||||
|
.list(notion::BlockChildrenListOptions {
|
||||||
|
block_id: &column.id,
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.results;
|
.results;
|
||||||
|
@ -187,35 +201,36 @@ pub async fn convert_blocks(notion: ¬ion::Client, blocks: &Vec<notion::Block>
|
||||||
content.push(convert_blocks(¬ion, &children).await.unwrap());
|
content.push(convert_blocks(¬ion, &children).await.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(
|
Some(format!(
|
||||||
format!(
|
r#"<div style="display: flex;">{content}</div>"#,
|
||||||
r#"<div style="display: flex;">{content}</div>"#,
|
content = content
|
||||||
content = content
|
.iter()
|
||||||
.iter()
|
.map(|column| format!(r#"<div style="margin: 0 16px">{column}</div>"#))
|
||||||
.map(
|
.collect::<Vec<String>>()
|
||||||
|column| format!(r#"<div style="margin: 0 16px">{column}</div>"#)
|
.join("\n")
|
||||||
)
|
))
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("\n")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
BlockType::Column(_) |
|
BlockType::Column { .. }
|
||||||
BlockType::Table |
|
| BlockType::Table
|
||||||
BlockType::Bookmark |
|
| BlockType::Bookmark { .. }
|
||||||
BlockType::File(_) | BlockType::PDF(_) |
|
| BlockType::File { .. }
|
||||||
|
| BlockType::Pdf { .. }
|
||||||
BlockType::TableOfContents |
|
| BlockType::TableOfContents
|
||||||
BlockType::ChildPage(_) |
|
| BlockType::ChildPage { .. }
|
||||||
BlockType::ChildDatabase(_) |
|
| BlockType::ChildDatabase { .. }
|
||||||
BlockType::SyncedBlock |
|
| BlockType::SyncedBlock
|
||||||
BlockType::Template |
|
| BlockType::Template
|
||||||
BlockType::Toggle => None
|
| BlockType::Toggle
|
||||||
|
| BlockType::Breadcrumb
|
||||||
|
| BlockType::Embed { .. }
|
||||||
|
| BlockType::Equation { .. }
|
||||||
|
| BlockType::LinkPreview { .. }
|
||||||
|
| BlockType::TableRow
|
||||||
|
| BlockType::LinkToPage { .. } => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(string) = string {
|
if let Some(string) = string {
|
||||||
|
@ -225,4 +240,3 @@ pub async fn convert_blocks(notion: ¬ion::Client, blocks: &Vec<notion::Block>
|
||||||
|
|
||||||
Ok(output.join("\n\n"))
|
Ok(output.join("\n\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue