fml 0.5.0

Friendly Markup Language
Documentation
//! This module contains implementations of From<FmlTypes> for dioxus_core::Element
//! for easy conversions between fml and dioxus.
use dioxus::prelude::*;

use crate::ast::{Content, FmlCodeBlockValue, FmlValue, FmlValues, Section};

impl From<Content> for Element {
	fn from(content: Content) -> Self {
		Self::from(&content)
	}
}
impl From<&mut Content> for Element {
	fn from(content: &mut Content) -> Self {
		Self::from(&*content)
	}
}
impl From<&Content> for Element {
	fn from(content: &Content) -> Self {
		rsx! {
			article {
				for section in content.iter() {
					{Self::from(section)}
				}
			}
		}
	}
}

impl From<Section> for Element {
	fn from(section: Section) -> Self {
		Self::from(&section)
	}
}
impl From<&mut Section> for Element {
	fn from(section: &mut Section) -> Self {
		Self::from(&*section)
	}
}
impl From<&Section> for Element {
	fn from(section: &Section) -> Self {
		rsx! {
			p { {Self::from(&section.0)} }
		}
	}
}

impl From<FmlValues> for Element {
	fn from(values: FmlValues) -> Self {
		Self::from(&values)
	}
}
impl From<&mut FmlValues> for Element {
	fn from(values: &mut FmlValues) -> Self {
		Self::from(&*values)
	}
}
impl From<&FmlValues> for Element {
	fn from(values: &FmlValues) -> Self {
		rsx! {
			for v in values.iter() {
				{Self::from(v)}
			}
		}
	}
}

impl From<FmlValue> for Element {
	fn from(value: FmlValue) -> Self {
		Self::from(&value)
	}
}
impl From<&mut FmlValue> for Element {
	fn from(value: &mut FmlValue) -> Self {
		Self::from(&*value)
	}
}
impl From<&FmlValue> for Element {
	fn from(value: &FmlValue) -> Self {
		match value {
			FmlValue::Linebreak => rsx! {
				br {}
			},
			FmlValue::Heading1(vals) => rsx! {
				h1 { {Self::from(vals)} }
			},
			FmlValue::Heading2(vals) => rsx! {
				h2 { {Self::from(vals)} }
			},
			FmlValue::Heading3(vals) => rsx! {
				h3 { {Self::from(vals)} }
			},
			FmlValue::Superline(vals) => rsx! {
				sup { style: "display:block", {Self::from(vals)} }
			},
			FmlValue::Subline(vals) => rsx! {
				sub { style: "display:block", {Self::from(vals)} }
			},
			FmlValue::Bold(vals) => rsx! {
				strong { {Self::from(vals)} }
			},
			FmlValue::Italic(vals) => rsx! {
				i { {Self::from(vals)} }
			},
			FmlValue::Strikethrough(vals) => rsx! {
				s { {Self::from(vals)} }
			},
			FmlValue::Quote(vals) => rsx! {
				blockquote { {Self::from(vals)} }
			},
			FmlValue::ListItem(vals) => rsx! {
				// wrapping every li with ul to allow nesting
				ul {
					li { {Self::from(vals)} }
				}
			},
			// Plaintext print of an unknown function
			FmlValue::Function(function) => {
				let mut lead = String::from("#");
				lead.push_str(&function.name);
				if let Some(params) = &function.params {
					lead.push('<');
					lead.push_str(params);
					lead.push('>');
				}
				lead.push('{');

				rsx! {
					"{lead}"
					{Self::from(&function.body)}
					"}}"
				}
			}
			FmlValue::Superscript(vals) => rsx! {
				sup { {Self::from(vals)} }
			},
			FmlValue::Subscript(vals) => rsx! {
				sub { {Self::from(vals)} }
			},
			FmlValue::Underline(vals) => rsx! {
				span { style: "text-decoration-line: underline;", {Self::from(vals)} }
			},
			FmlValue::ColorFg(fml_color) => {
				let color = &fml_color.color;
				rsx! {
					span { style: "color: {color};", {Self::from(&fml_color.body)} }
				}
			}
			FmlValue::ColorBg(fml_color) => {
				let color = &fml_color.color;
				rsx! {
					span { style: "background-color: {color};", {Self::from(&fml_color.body)} }
				}
			}
			FmlValue::ContentWarning { reason, body } => rsx! {
				details {
					summary { "{reason}" }
					{Self::from(body)}
				}
			},
			FmlValue::CodeBlock { lang, body } => rsx! {
				pre {
					code { class: if let Some(lang) = lang { format!("language-{lang}") } else { "" },
						for v in body {
							{Self::from(v)}
						}
					}
				}
			},
			FmlValue::Hyperlink { fml, uri } => rsx! {
				a { href: uri, {Self::from(fml)} }
			},
			FmlValue::CodeInline(txt) => rsx! {
				code { "{txt}" }
			},
			FmlValue::Typst(typst) => rsx! { "{typst}" },
			FmlValue::Text(txt) => rsx! { "{txt}" },
		}
	}
}

impl From<FmlCodeBlockValue> for Element {
	fn from(value: FmlCodeBlockValue) -> Self {
		Self::from(&value)
	}
}
impl From<&mut FmlCodeBlockValue> for Element {
	fn from(value: &mut FmlCodeBlockValue) -> Self {
		Self::from(&*value)
	}
}
impl From<&FmlCodeBlockValue> for Element {
	fn from(value: &FmlCodeBlockValue) -> Self {
		match value {
			FmlCodeBlockValue::Str(txt) => rsx! { "{txt}" },
			FmlCodeBlockValue::Linebreak => rsx! {
				br {}
			},
		}
	}
}