gitdataai/libs/transport/richtext.rs

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('&', "&amp;")
.replace('<', "&lt;")
.replace('>', "&gt;")
.replace('"', "&quot;")
.replace('\'', "&#x27;")
}