#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HeadingStyle {
Underlined,
#[default]
Atx,
AtxClosed,
}
impl HeadingStyle {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"atx" => Self::Atx,
"atxclosed" => Self::AtxClosed,
_ => Self::Underlined,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ListIndentType {
#[default]
Spaces,
Tabs,
}
impl ListIndentType {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"tabs" => Self::Tabs,
_ => Self::Spaces,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum WhitespaceMode {
#[default]
Normalized,
Strict,
}
impl WhitespaceMode {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"strict" => Self::Strict,
_ => Self::Normalized,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum NewlineStyle {
#[default]
Spaces,
Backslash,
}
impl NewlineStyle {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"backslash" => Self::Backslash,
_ => Self::Spaces,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CodeBlockStyle {
Indented,
#[default]
Backticks,
Tildes,
}
impl CodeBlockStyle {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"backticks" => Self::Backticks,
"tildes" => Self::Tildes,
_ => Self::Indented,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HighlightStyle {
#[default]
DoubleEqual,
Html,
Bold,
None,
}
impl HighlightStyle {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"doubleequal" => Self::DoubleEqual,
"html" => Self::Html,
"bold" => Self::Bold,
"none" => Self::None,
_ => Self::None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum LinkStyle {
#[default]
Inline,
Reference,
}
impl LinkStyle {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"reference" => Self::Reference,
_ => Self::Inline,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum OutputFormat {
#[default]
Markdown,
Djot,
Plain,
}
impl OutputFormat {
#[must_use]
pub fn parse(value: &str) -> Self {
match normalize_token(value).as_str() {
"djot" => Self::Djot,
"plain" | "plaintext" | "text" => Self::Plain,
_ => Self::Markdown,
}
}
}
pub(crate) fn normalize_token(value: &str) -> String {
let mut out = String::with_capacity(value.len());
for ch in value.chars() {
if ch.is_ascii_alphanumeric() {
out.push(ch.to_ascii_lowercase());
}
}
out
}
#[cfg(any(feature = "serde", feature = "metadata"))]
mod serde_impls {
use super::{
CodeBlockStyle, HeadingStyle, HighlightStyle, LinkStyle, ListIndentType, NewlineStyle, OutputFormat,
WhitespaceMode,
};
use serde::{Deserialize, Serialize, Serializer};
macro_rules! impl_deserialize_from_parse {
($ty:ty, $parser:expr) => {
impl<'de> Deserialize<'de> for $ty {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let value = String::deserialize(deserializer)?;
Ok($parser(&value))
}
}
};
}
impl_deserialize_from_parse!(HeadingStyle, HeadingStyle::parse);
impl_deserialize_from_parse!(ListIndentType, ListIndentType::parse);
impl_deserialize_from_parse!(WhitespaceMode, WhitespaceMode::parse);
impl_deserialize_from_parse!(NewlineStyle, NewlineStyle::parse);
impl_deserialize_from_parse!(CodeBlockStyle, CodeBlockStyle::parse);
impl_deserialize_from_parse!(HighlightStyle, HighlightStyle::parse);
impl_deserialize_from_parse!(LinkStyle, LinkStyle::parse);
impl_deserialize_from_parse!(OutputFormat, OutputFormat::parse);
impl Serialize for HeadingStyle {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::Underlined => "underlined",
Self::Atx => "atx",
Self::AtxClosed => "atxclosed",
};
serializer.serialize_str(s)
}
}
impl Serialize for ListIndentType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::Spaces => "spaces",
Self::Tabs => "tabs",
};
serializer.serialize_str(s)
}
}
impl Serialize for WhitespaceMode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::Normalized => "normalized",
Self::Strict => "strict",
};
serializer.serialize_str(s)
}
}
impl Serialize for NewlineStyle {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::Spaces => "spaces",
Self::Backslash => "backslash",
};
serializer.serialize_str(s)
}
}
impl Serialize for CodeBlockStyle {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::Indented => "indented",
Self::Backticks => "backticks",
Self::Tildes => "tildes",
};
serializer.serialize_str(s)
}
}
impl Serialize for HighlightStyle {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::DoubleEqual => "doubleequal",
Self::Html => "html",
Self::Bold => "bold",
Self::None => "none",
};
serializer.serialize_str(s)
}
}
impl Serialize for LinkStyle {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::Inline => "inline",
Self::Reference => "reference",
};
serializer.serialize_str(s)
}
}
impl Serialize for OutputFormat {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = match self {
Self::Markdown => "markdown",
Self::Djot => "djot",
Self::Plain => "plain",
};
serializer.serialize_str(s)
}
}
}
#[cfg(all(test, any(feature = "serde", feature = "metadata")))]
mod tests {
use super::*;
#[test]
fn test_enum_serialization() {
let heading = HeadingStyle::AtxClosed;
let json = serde_json::to_string(&heading).expect("Failed to serialize");
assert_eq!(json, r#""atxclosed""#);
let list_indent = ListIndentType::Tabs;
let json = serde_json::to_string(&list_indent).expect("Failed to serialize");
assert_eq!(json, r#""tabs""#);
let whitespace = WhitespaceMode::Strict;
let json = serde_json::to_string(&whitespace).expect("Failed to serialize");
assert_eq!(json, r#""strict""#);
}
#[test]
fn test_enum_deserialization() {
let heading: HeadingStyle = serde_json::from_str(r#""atxclosed""#).expect("Failed");
assert_eq!(heading, HeadingStyle::AtxClosed);
let heading: HeadingStyle = serde_json::from_str(r#""ATXCLOSED""#).expect("Failed");
assert_eq!(heading, HeadingStyle::AtxClosed);
let list_indent: ListIndentType = serde_json::from_str(r#""tabs""#).expect("Failed");
assert_eq!(list_indent, ListIndentType::Tabs);
}
}