Skip to main content

dioxus_tw_components/components/
markdown.rs

1use dioxus::prelude::*;
2
3#[derive(Clone, PartialEq, Props)]
4pub struct MarkdownProps {
5    #[props(extends = div, extends = GlobalAttributes)]
6    attributes: Vec<Attribute>,
7    /// The markdown content to render
8    /// Example: "# Hello World"
9    /// Default: ""
10    #[props(into, default = String::new())]
11    content: String,
12}
13
14/// Uses `dangerous_inner_html` to render markdown content as HTML
15#[component]
16pub fn Markdown(props: MarkdownProps) -> Element {
17    let content = string_to_html(props.content.clone());
18
19    rsx! {
20        div {
21            class: "prose dark:prose-invert max-w-none",
22            dangerous_inner_html: "{content}",
23            ..props.attributes
24        }
25    }
26}
27
28/// Convert a markdown string to HTML
29/// Uses pulldown-cmark crate
30/// Supports tables, footnotes, strikethrough, tasklists, and smart punctuation
31/// # Example
32/// ```
33/// let html = string_to_html("# Hello World");
34/// assert_eq!(html, "<h1>Hello World</h1>");
35/// ```
36fn string_to_html(content: String) -> String {
37    use pulldown_cmark::{Options, Parser, html};
38
39    let mut options = Options::empty();
40    options.insert(Options::ENABLE_TABLES);
41    options.insert(Options::ENABLE_FOOTNOTES);
42    options.insert(Options::ENABLE_STRIKETHROUGH);
43    options.insert(Options::ENABLE_TASKLISTS);
44    options.insert(Options::ENABLE_SMART_PUNCTUATION);
45
46    let parser = Parser::new_ext(&content, options);
47
48    let mut html_output = String::new();
49    html::push_html(&mut html_output, parser);
50
51    html_output
52}