rumdl_lib/utils/anchor_styles/
mod.rs1pub mod common;
16pub mod github;
17pub mod kramdown;
18pub mod kramdown_gfm; pub mod python_markdown;
20
21use serde::{Deserialize, Serialize};
22
23#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
25#[serde(rename_all = "kebab-case")]
26#[derive(Default)]
27pub enum AnchorStyle {
28 #[default]
30 #[serde(rename = "github")]
31 GitHub,
32 #[serde(rename = "kramdown-gfm", alias = "kramdown_gfm", alias = "jekyll")]
35 KramdownGfm,
36 #[serde(rename = "kramdown")]
38 Kramdown,
39 #[serde(rename = "python-markdown", alias = "python_markdown", alias = "mkdocs")]
41 PythonMarkdown,
42}
43
44impl AnchorStyle {
45 pub fn for_flavor(flavor: crate::config::MarkdownFlavor) -> Self {
52 match flavor {
53 crate::config::MarkdownFlavor::MkDocs => AnchorStyle::PythonMarkdown,
54 crate::config::MarkdownFlavor::Kramdown => AnchorStyle::KramdownGfm,
55 _ => AnchorStyle::GitHub,
56 }
57 }
58
59 pub fn generate_fragment(&self, heading: &str) -> String {
61 match self {
62 AnchorStyle::GitHub => github::heading_to_fragment(heading),
63 AnchorStyle::KramdownGfm => kramdown_gfm::heading_to_fragment(heading),
64 AnchorStyle::Kramdown => kramdown::heading_to_fragment(heading),
65 AnchorStyle::PythonMarkdown => python_markdown::heading_to_fragment(heading),
66 }
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn test_anchor_style_serde() {
76 assert_eq!(serde_json::to_string(&AnchorStyle::GitHub).unwrap(), "\"github\"");
78 assert_eq!(
79 serde_json::to_string(&AnchorStyle::KramdownGfm).unwrap(),
80 "\"kramdown-gfm\""
81 );
82 assert_eq!(serde_json::to_string(&AnchorStyle::Kramdown).unwrap(), "\"kramdown\"");
83 assert_eq!(
84 serde_json::to_string(&AnchorStyle::PythonMarkdown).unwrap(),
85 "\"python-markdown\""
86 );
87
88 assert_eq!(
90 serde_json::from_str::<AnchorStyle>("\"github\"").unwrap(),
91 AnchorStyle::GitHub
92 );
93 assert_eq!(
94 serde_json::from_str::<AnchorStyle>("\"kramdown-gfm\"").unwrap(),
95 AnchorStyle::KramdownGfm
96 );
97 assert_eq!(
98 serde_json::from_str::<AnchorStyle>("\"kramdown\"").unwrap(),
99 AnchorStyle::Kramdown
100 );
101 assert_eq!(
102 serde_json::from_str::<AnchorStyle>("\"python-markdown\"").unwrap(),
103 AnchorStyle::PythonMarkdown
104 );
105
106 assert_eq!(
108 serde_json::from_str::<AnchorStyle>("\"kramdown_gfm\"").unwrap(),
109 AnchorStyle::KramdownGfm
110 );
111 assert_eq!(
112 serde_json::from_str::<AnchorStyle>("\"python_markdown\"").unwrap(),
113 AnchorStyle::PythonMarkdown
114 );
115
116 assert_eq!(
118 serde_json::from_str::<AnchorStyle>("\"jekyll\"").unwrap(),
119 AnchorStyle::KramdownGfm
120 );
121 assert_eq!(
122 serde_json::from_str::<AnchorStyle>("\"mkdocs\"").unwrap(),
123 AnchorStyle::PythonMarkdown
124 );
125 }
126
127 #[test]
128 fn test_anchor_style_differences() {
129 let test_cases = [
130 "cbrown --> sbrown: --unsafe-paths",
131 "Update login_type",
132 "Test---with---multiple---hyphens",
133 "API::Response > Error--Handling",
134 ];
135
136 for case in test_cases {
137 let github = AnchorStyle::GitHub.generate_fragment(case);
138 let kramdown_gfm = AnchorStyle::KramdownGfm.generate_fragment(case);
139 let kramdown = AnchorStyle::Kramdown.generate_fragment(case);
140 let python_md = AnchorStyle::PythonMarkdown.generate_fragment(case);
141
142 assert!(!github.is_empty(), "GitHub style failed for: {case}");
144 assert!(!kramdown_gfm.is_empty(), "KramdownGfm style failed for: {case}");
145 assert!(!kramdown.is_empty(), "Kramdown style failed for: {case}");
146 assert!(!python_md.is_empty(), "PythonMarkdown style failed for: {case}");
147 }
148 }
149}