gdnative_doc/backend/
callbacks.rs

1use std::collections::HashMap;
2
3use super::{Generator, Resolver};
4use crate::documentation::{Method, Property};
5use pulldown_cmark::{CowStr, Event, HeadingLevel, Tag};
6
7/// Callbacks to encode markdown input in a given format.
8///
9/// This trait should be implemented if you want to make your own backend.
10pub trait Callbacks {
11    /// File extension for the files generated by this callback.
12    fn extension(&self) -> &'static str;
13    /// Drive the generation process.
14    ///
15    /// This returns a map from file names (relative to the output directory) to
16    /// their contents.
17    ///
18    /// You can find inspiration about how to implement this in the source code, for
19    /// example in `src/backend/html.rs`.
20    fn generate_files(&mut self, generator: Generator) -> HashMap<String, String>;
21    /// Called before encoding each method.
22    ///
23    /// **Default**: does nothing
24    fn start_method(&mut self, _s: &mut String, _resolver: &Resolver, _method: &Method) {}
25    /// Called before encoding each property.
26    ///
27    /// **Default**: does nothing
28    fn start_property(&mut self, _s: &mut String, _resolver: &Resolver, _property: &Property) {}
29    /// Encode the stream of `events` in `s`.
30    fn encode(&mut self, s: &mut String, events: Vec<Event<'_>>);
31}
32
33impl dyn Callbacks {
34    /// Default start_method implementation, implemented on `dyn Callbacks` to avoid
35    /// code duplication.
36    ///
37    /// This will create a level 3 header that looks like (in markdown):
38    /// ```markdown
39    /// ### <a id="func-name"></a>func name(arg1: [type](link), ...) -> [type](link)
40    /// ________
41    /// ```
42    ///
43    /// With appropriate linking.
44    pub fn start_method_default(&mut self, s: &mut String, property: &Resolver, method: &Method) {
45        let link = &format!("<a id=\"func-{}\"></a>", method.name);
46        self.encode(
47            s,
48            vec![
49                Event::Start(Tag::Heading(HeadingLevel::H3, None, Vec::new())),
50                Event::Html(CowStr::Borrowed(link)),
51            ],
52        );
53        let mut method_header = String::from("func ");
54        method_header.push_str(&method.name);
55        method_header.push('(');
56        for (index, (name, typ, _)) in method.parameters.iter().enumerate() {
57            method_header.push_str(name);
58            method_header.push_str(": ");
59            self.encode(s, vec![Event::Text(CowStr::Borrowed(&method_header))]);
60            method_header.clear();
61            self.encode(s, property.encode_type(typ));
62            if index + 1 != method.parameters.len() {
63                method_header.push_str(", ");
64            }
65        }
66        method_header.push_str(") -> ");
67        let mut last_events = vec![Event::Text(CowStr::Borrowed(&method_header))];
68        last_events.extend(property.encode_type(&method.return_type));
69        last_events.push(Event::End(Tag::Heading(HeadingLevel::H3, None, Vec::new())));
70        last_events.push(Event::Rule);
71        self.encode(s, last_events);
72    }
73
74    /// Default start_property implementation, implemented on `dyn Callbacks` to avoid
75    /// code duplication.
76    ///
77    /// This will create a level 3 header that looks like (in markdown):
78    /// ```markdown
79    /// ### <a id="property-name"></a> name: [type](link)
80    /// ________
81    /// ```
82    ///
83    /// With appropriate linking.
84    pub fn start_property_default(
85        &mut self,
86        s: &mut String,
87        resolver: &Resolver,
88        property: &Property,
89    ) {
90        let link = &format!(
91            "<a id=\"property-{}\"></a> {}: ",
92            property.name, property.name
93        );
94        self.encode(
95            s,
96            vec![
97                Event::Start(Tag::Heading(HeadingLevel::H3, None, Vec::new())),
98                Event::Html(CowStr::Borrowed(link)),
99            ],
100        );
101        let mut last_events = resolver.encode_type(&property.typ);
102        last_events.push(Event::End(Tag::Heading(HeadingLevel::H3, None, Vec::new())));
103        last_events.push(Event::Rule);
104        self.encode(s, last_events);
105    }
106}
107
108impl std::fmt::Debug for dyn Callbacks {
109    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110        formatter.write_str("Callbacks")
111    }
112}