dioxus-docs-kit 0.4.1

Reusable documentation site shell for Dioxus applications
Documentation
//! Builder for constructing a `DocsRegistry`.

use crate::registry::DocsRegistry;
use std::collections::HashMap;

/// Theme configuration for the documentation site.
///
/// Controls which DaisyUI theme(s) are applied and whether a toggle button is shown.
#[derive(Clone, Debug)]
pub struct ThemeConfig {
    /// The default theme name (must match a DaisyUI theme defined in `tailwind.css`).
    pub default_theme: String,
    /// If set, enables a light/dark toggle button. Tuple is `(light_theme, dark_theme)`.
    pub toggle_themes: Option<(String, String)>,
    /// localStorage key used to persist the user's theme preference.
    pub storage_key: String,
}

/// Builder for constructing a [`DocsRegistry`].
///
/// # Example
///
/// ```rust,ignore
/// let registry = DocsConfig::new(nav_json, content_map)
///     .with_openapi("api-reference", spec_yaml)
///     .with_default_path("getting-started/introduction")
///     .build();
/// ```
pub struct DocsConfig {
    nav_json: String,
    content_map: HashMap<&'static str, &'static str>,
    openapi_specs: Vec<(String, String)>,
    default_path: Option<String>,
    api_group_name: Option<String>,
    theme: Option<ThemeConfig>,
}

impl DocsConfig {
    /// Create a new builder from a `_nav.json` string and a content map.
    ///
    /// The content map is typically generated by `build.rs` using `include_str!()`.
    pub fn new(nav_json: &str, content_map: HashMap<&'static str, &'static str>) -> Self {
        Self {
            nav_json: nav_json.to_string(),
            content_map,
            openapi_specs: Vec::new(),
            default_path: None,
            api_group_name: None,
            theme: None,
        }
    }

    /// Add an OpenAPI specification.
    ///
    /// - `prefix`: The URL prefix for this spec's endpoints (e.g. "api-reference").
    /// - `yaml`: The raw YAML string of the OpenAPI spec.
    ///
    /// The `prefix` must correspond to a nav group in `_nav.json` whose `"group"` value
    /// matches [`Self::with_api_group_name`] (defaults to `"API Reference"`). The library
    /// dynamically injects API endpoints into that group's sidebar — do **not** list
    /// individual operation paths in the `"pages"` array of `_nav.json`.
    pub fn with_openapi(mut self, prefix: &str, yaml: &str) -> Self {
        self.openapi_specs
            .push((prefix.to_string(), yaml.to_string()));
        self
    }

    /// Set the default documentation path for redirects.
    ///
    /// Defaults to the first page in the first nav group if not set.
    pub fn with_default_path(mut self, path: &str) -> Self {
        self.default_path = Some(path.to_string());
        self
    }

    /// Set the display name for the API Reference sidebar group.
    ///
    /// Defaults to `"API Reference"`. The value must match a `"group"` in `_nav.json`
    /// so the library knows where to inject the API endpoint sidebar entries.
    /// See [`Self::with_openapi`] for details.
    pub fn with_api_group_name(mut self, name: &str) -> Self {
        self.api_group_name = Some(name.to_string());
        self
    }

    /// Set a single theme (no toggle button).
    ///
    /// The theme name must match a DaisyUI theme defined in the consumer's `tailwind.css`.
    pub fn with_theme(mut self, theme: &str) -> Self {
        self.theme = Some(ThemeConfig {
            default_theme: theme.to_string(),
            toggle_themes: None,
            storage_key: "docs-theme".to_string(),
        });
        self
    }

    /// Enable a light/dark theme toggle.
    ///
    /// - `light`: Name of the light DaisyUI theme.
    /// - `dark`: Name of the dark DaisyUI theme.
    /// - `default`: Which of the two to use on first visit (`light` or `dark`).
    pub fn with_theme_toggle(mut self, light: &str, dark: &str, default: &str) -> Self {
        self.theme = Some(ThemeConfig {
            default_theme: default.to_string(),
            toggle_themes: Some((light.to_string(), dark.to_string())),
            storage_key: "docs-theme".to_string(),
        });
        self
    }

    /// Build the [`DocsRegistry`].
    ///
    /// Parses all documents, builds the search index, and parses OpenAPI specs.
    pub fn build(self) -> DocsRegistry {
        DocsRegistry::from_config(self)
    }

    // Accessors for DocsRegistry::from_config
    pub(crate) fn nav_json(&self) -> &str {
        &self.nav_json
    }

    pub(crate) fn content_map(&self) -> &HashMap<&'static str, &'static str> {
        &self.content_map
    }

    pub(crate) fn openapi_specs(&self) -> &[(String, String)] {
        &self.openapi_specs
    }

    pub(crate) fn default_path_value(&self) -> Option<&str> {
        self.default_path.as_deref()
    }

    pub(crate) fn api_group_name_value(&self) -> Option<&str> {
        self.api_group_name.as_deref()
    }

    pub(crate) fn theme_config(&self) -> Option<&ThemeConfig> {
        self.theme.as_ref()
    }
}