#![cfg_attr(not(test), allow(dead_code))]
use serde_json::{Value, json};
use super::ast::{Align, Block, Inline, List, Table};
pub(crate) fn input_rich_message(blocks: &[Block]) -> Value {
json!({ "blocks": render_blocks(blocks) })
}
fn render_blocks(blocks: &[Block]) -> Vec<Value> {
blocks.iter().map(render_block).collect()
}
pub(crate) fn render_block(b: &Block) -> Value {
match b {
Block::Heading { level, content } => json!({
"type": "heading",
"level": level,
"content": render_inlines(content),
}),
Block::Paragraph(content) => json!({
"type": "paragraph",
"content": render_inlines(content),
}),
Block::List(list) => render_list(list),
Block::Table(table) => render_table(table),
Block::Code { lang, text } => json!({
"type": "code",
"language": lang,
"text": text,
}),
Block::Quote(blocks) => json!({
"type": "quote",
"blocks": render_blocks(blocks),
}),
Block::Math(text) => json!({
"type": "math",
"text": text,
}),
Block::Divider => json!({ "type": "divider" }),
Block::Details {
summary,
blocks,
open,
} => json!({
"type": "details",
"summary": render_inlines(summary),
"blocks": render_blocks(blocks),
"is_open": open,
}),
}
}
fn render_list(list: &List) -> Value {
let items: Vec<Value> = list
.items
.iter()
.map(|item| {
json!({
"task": item.task,
"content": render_inlines(&item.content),
"blocks": render_blocks(&item.children),
})
})
.collect();
json!({
"type": "list",
"ordered": list.ordered,
"items": items,
})
}
fn render_table(table: &Table) -> Value {
let cells = |row: &[Vec<Inline>]| -> Vec<Value> {
row.iter().map(|cell| json!(render_inlines(cell))).collect()
};
json!({
"type": "table",
"align": table.align.iter().map(|a| render_align(*a)).collect::<Vec<_>>(),
"header": cells(&table.header),
"rows": table.rows.iter().map(|r| json!(cells(r))).collect::<Vec<_>>(),
})
}
fn render_align(align: Align) -> &'static str {
match align {
Align::None => "none",
Align::Left => "left",
Align::Center => "center",
Align::Right => "right",
}
}
fn render_inlines(inlines: &[Inline]) -> Vec<Value> {
inlines.iter().map(render_inline).collect()
}
pub(crate) fn render_inline(inline: &Inline) -> Value {
match inline {
Inline::Text(text) => json!({ "type": "text", "text": text }),
Inline::Bold(content) => json!({ "type": "bold", "content": render_inlines(content) }),
Inline::Italic(content) => json!({ "type": "italic", "content": render_inlines(content) }),
Inline::Strike(content) => json!({
"type": "strikethrough",
"content": render_inlines(content),
}),
Inline::Code(text) => json!({ "type": "code", "text": text }),
Inline::Math(text) => json!({ "type": "math", "text": text }),
Inline::Link { content, url } => json!({
"type": "link",
"content": render_inlines(content),
"url": url,
}),
}
}