ddoc/config/
mod.rs

1mod attribute;
2mod before_0_11;
3mod element;
4mod element_key;
5mod element_list;
6mod menu;
7mod nav_link;
8mod page_list;
9mod text;
10mod toc;
11
12pub use {
13    attribute::*,
14    element::*,
15    element_key::*,
16    element_list::*,
17    menu::*,
18    nav_link::*,
19    page_list::*,
20    text::*,
21    toc::*,
22};
23
24use {
25    crate::*,
26    before_0_11::NavComponents,
27    serde::{
28        Deserialize,
29        Serialize,
30    },
31    std::path::{
32        Path,
33        PathBuf,
34    },
35};
36
37pub static CONFIG_FILE_NAME: &str = "ddoc.hjson";
38
39pub type ClassName = String;
40
41#[derive(Debug, Clone, Deserialize)]
42#[serde(rename_all = "kebab-case")]
43pub struct Config {
44    pub title: String,
45    pub description: Option<String>,
46    pub ddoc_version: Option<String>,
47    #[serde(alias = "pages", alias = "menu")]
48    pub site_map: PageList,
49    pub favicon: Option<String>,
50    /// for compatibility with ddoc (0.11-), this is loaded but only used
51    /// through conversion to the new `body` field
52    #[serde(flatten)]
53    old: NavComponents,
54    #[serde(default)]
55    pub body: ElementList,
56}
57
58impl Config {
59    /// Read the ddoc.hjson configuration file at the root of a ddoc project
60    ///
61    /// Return both the config and the path where it was found
62    ///
63    /// # Errors
64    /// Return `DdError::ConfigNotFound` if no ddoc.hjson is found at the specified path
65    /// or other `DdError` variants on read/parse errors
66    pub fn at_root(path: &Path) -> DdResult<(Self, PathBuf)> {
67        let config_path = path.join(CONFIG_FILE_NAME);
68        if !config_path.exists() {
69            return Err(DdError::ConfigNotFound);
70        }
71        let config: Config = read_file(&config_path)?;
72        Ok((config, config_path))
73    }
74    pub fn description(&self) -> Option<&str> {
75        self.description.as_deref().filter(|s| !s.is_empty())
76    }
77    pub fn favicon(&self) -> Option<&str> {
78        self.favicon.as_deref().filter(|s| !s.is_empty())
79    }
80    pub fn needs_search_script(&self) -> bool {
81        self.body.has_href("--search")
82    }
83    pub fn needs_toc_activate_script(&self) -> bool {
84        self.body.has(|element: &Element| {
85            if let ElementContent::Toc(toc) = &element.content {
86                return toc.activate_visible_item;
87            }
88            false
89        })
90    }
91    /// For support of old ddoc versions (<= 0.11), convert old nav components
92    /// if the new `body` field is empty
93    pub fn fix_old(&mut self) {
94        if self.body.children.is_empty() {
95            self.body = self.old.to_body_composite();
96        }
97    }
98}
99
100#[derive(Debug, Clone, Deserialize, Serialize)]
101pub struct UiOptions {
102    /// If true, a hamburger checkbox is added to the UI for toggling
103    /// the menu on small screens.
104    ///
105    /// When it's true (default), CSS becomes necessary
106    #[serde(default = "bool_true")]
107    hamburger_checkbox: bool,
108}
109
110impl Default for UiOptions {
111    fn default() -> Self {
112        Self {
113            hamburger_checkbox: true,
114        }
115    }
116}
117
118pub fn bool_true() -> bool {
119    true
120}