98 lines
2.7 KiB
Rust
98 lines
2.7 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use uuid::Uuid;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct RichTextBlock {
|
|
pub block_type: BlockType,
|
|
pub content: String,
|
|
pub attributes: Option<serde_json::Value>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum BlockType {
|
|
Text,
|
|
Code,
|
|
Quote,
|
|
Link,
|
|
Mention,
|
|
Emoji,
|
|
Image,
|
|
}
|
|
|
|
pub struct RichTextRenderer {}
|
|
|
|
impl RichTextRenderer {
|
|
pub fn new() -> Self {
|
|
Self {}
|
|
}
|
|
|
|
pub fn parse_markdown(&self, content: &str) -> Vec<RichTextBlock> {
|
|
let mut blocks = Vec::new();
|
|
|
|
blocks.push(RichTextBlock {
|
|
block_type: BlockType::Text,
|
|
content: content.to_string(),
|
|
attributes: None,
|
|
});
|
|
|
|
blocks
|
|
}
|
|
|
|
pub fn parse_mentions(&self, content: &str) -> Vec<Uuid> {
|
|
let mut mentions = Vec::new();
|
|
|
|
for word in content.split_whitespace() {
|
|
if word.starts_with('@') {
|
|
if let Ok(uuid) = Uuid::parse_str(&word[1..]) {
|
|
mentions.push(uuid);
|
|
}
|
|
}
|
|
}
|
|
|
|
mentions
|
|
}
|
|
|
|
pub fn highlight_code(&self, code: &str, language: &str) -> String {
|
|
format!("```{}\n{}\n```", language, code)
|
|
}
|
|
|
|
pub fn render_to_html(&self, blocks: &[RichTextBlock]) -> String {
|
|
blocks
|
|
.iter()
|
|
.map(|block| match block.block_type {
|
|
BlockType::Text => format!("<p>{}</p>", html_escape(&block.content)),
|
|
BlockType::Code => {
|
|
format!("<pre><code>{}</code></pre>", html_escape(&block.content))
|
|
}
|
|
BlockType::Quote => {
|
|
format!("<blockquote>{}</blockquote>", html_escape(&block.content))
|
|
}
|
|
BlockType::Link => format!(
|
|
"<a href=\"{}\">{}</a>",
|
|
html_escape(&block.content),
|
|
html_escape(&block.content)
|
|
),
|
|
BlockType::Mention => format!(
|
|
"<span class=\"mention\">@{}</span>",
|
|
html_escape(&block.content)
|
|
),
|
|
BlockType::Emoji => format!(
|
|
"<span class=\"emoji\">{}</span>",
|
|
html_escape(&block.content)
|
|
),
|
|
BlockType::Image => format!("<img src=\"{}\" />", html_escape(&block.content)),
|
|
})
|
|
.collect::<Vec<_>>()
|
|
.join("\n")
|
|
}
|
|
}
|
|
|
|
fn html_escape(s: &str) -> String {
|
|
s.replace('&', "&")
|
|
.replace('<', "<")
|
|
.replace('>', ">")
|
|
.replace('"', """)
|
|
.replace('\'', "'")
|
|
}
|