pulldown_cmark_toc/
render.rs1use std::borrow::Borrow;
4use std::fmt;
5use std::fmt::Write;
6use std::ops::RangeInclusive;
7
8use pulldown_cmark::{Event, HeadingLevel, Tag, TagEnd};
9
10use crate::slug::{GitHubSlugifier, Slugify};
11
12pub enum ItemSymbol {
14 Hyphen,
16 Asterisk,
18}
19
20pub struct Options {
34 pub(crate) item_symbol: ItemSymbol,
35 pub(crate) levels: RangeInclusive<HeadingLevel>,
36 pub(crate) indent: usize,
37 pub(crate) slugifier: Box<dyn Slugify>,
38}
39
40pub(crate) fn to_cmark<'a, I, E>(events: I) -> String
41where
42 I: Iterator<Item = E>,
43 E: Borrow<Event<'a>>,
44{
45 let mut buf = String::new();
46 for event in events {
47 let event = event.borrow();
48 match event {
49 Event::Start(Tag::Emphasis) | Event::End(TagEnd::Emphasis) => buf.push('*'),
50 Event::Start(Tag::Strong) | Event::End(TagEnd::Strong) => buf.push_str("**"),
51 Event::Text(s) => buf.push_str(s),
52 Event::Code(s) => {
53 buf.push('`');
54 buf.push_str(s);
55 buf.push('`');
56 }
57 Event::Html(s) => buf.push_str(s),
58 _ => {} }
60 }
61 buf
62}
63
64impl fmt::Display for ItemSymbol {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 Self::Hyphen => f.write_char('-'),
68 Self::Asterisk => f.write_char('*'),
69 }
70 }
71}
72
73impl Default for Options {
74 fn default() -> Self {
75 Self {
76 item_symbol: ItemSymbol::Hyphen,
77 levels: (HeadingLevel::H1..=HeadingLevel::H6),
78 indent: 2,
79 slugifier: Box::<GitHubSlugifier>::default(),
80 }
81 }
82}
83
84impl Options {
85 #[must_use]
87 pub fn item_symbol(mut self, item_symbol: ItemSymbol) -> Self {
88 self.item_symbol = item_symbol;
89 self
90 }
91
92 #[must_use]
94 pub fn levels(mut self, levels: RangeInclusive<HeadingLevel>) -> Self {
95 self.levels = levels;
96 self
97 }
98
99 #[must_use]
101 pub fn indent(mut self, indent: usize) -> Self {
102 self.indent = indent;
103 self
104 }
105
106 #[must_use]
108 pub fn slugifier(mut self, slugifier: Box<dyn Slugify>) -> Self {
109 self.slugifier = slugifier;
110 self
111 }
112}