Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 84 additions & 3 deletions crates/mdbook-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,10 @@ pub struct HtmlConfig {
/// The theme directory, if specified.
pub theme: Option<PathBuf>,
/// The default theme to use, defaults to 'light'
pub default_theme: Option<String>,
pub default_theme: Option<BuiltinTheme>,
/// The theme to use if the browser requests the dark version of the site.
/// Defaults to 'navy'.
pub preferred_dark_theme: Option<String>,
pub preferred_dark_theme: Option<BuiltinTheme>,
/// Supports smart quotes, apostrophes, ellipsis, en-dash, and em-dash.
pub smart_punctuation: bool,
/// Support for definition lists.
Expand Down Expand Up @@ -728,6 +728,40 @@ trait Updateable<'de>: Serialize + Deserialize<'de> {

impl<'de, T> Updateable<'de> for T where T: Serialize + Deserialize<'de> {}

/// A built-in HTML theme supported by mdBook.
///
/// These themes are defined in `crates/mdbook-html/front-end/css/variables.css`.
///
/// The enum variants correspond to the theme names accepted by the
/// `[output.html]` configuration keys `default-theme` and
/// `preferred-dark-theme`.
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase", deny_unknown_fields)]
#[non_exhaustive]
pub enum BuiltinTheme {
/// A dark theme with a balanced color palette.
Ayu,
/// A dark theme with a gray-on-gray aesthetic.
Coal,
/// A light theme optimized for readability.
Light,
/// A dark navy-themed variant.
Navy,
/// A rust-colored theme.
Rust,
}

impl BuiltinTheme {
/// An array of all built-in themes, in the order they should be displayed in the theme selector.
pub const ALL: [BuiltinTheme; 5] = [
BuiltinTheme::Light,
BuiltinTheme::Rust,
BuiltinTheme::Coal,
BuiltinTheme::Navy,
BuiltinTheme::Ayu,
];
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -795,7 +829,7 @@ mod tests {
smart_punctuation: true,
additional_css: vec![PathBuf::from("./foo/bar/baz.css")],
theme: Some(PathBuf::from("./themedir")),
default_theme: Some(String::from("rust")),
default_theme: Some(BuiltinTheme::Rust),
playground: playground_should_be,
git_repository_url: Some(String::from("https://foo.com/")),
git_repository_icon: Some(String::from("fa-code-fork")),
Expand All @@ -819,6 +853,53 @@ mod tests {
assert_eq!(got.html_config().unwrap(), html_should_be);
}

#[test]
fn parse_builtin_html_themes() {
let src = r#"
[output.html]
default-theme = "rust"
preferred-dark-theme = "coal"
"#;

let got = Config::from_str(src).unwrap();
let html_config = got.html_config().unwrap();

assert_eq!(html_config.default_theme, Some(BuiltinTheme::Rust));
assert_eq!(html_config.preferred_dark_theme, Some(BuiltinTheme::Coal));
assert_eq!(
BuiltinTheme::ALL,
[
BuiltinTheme::Light,
BuiltinTheme::Rust,
BuiltinTheme::Coal,
BuiltinTheme::Navy,
BuiltinTheme::Ayu,
]
);
}

#[test]
fn invalid_default_theme() {
let src = r#"
[output.html]
default-theme = "does-not-exist"
"#;

let got = Config::from_str(src).unwrap();
assert_eq!(got.html_config(), None);
}

#[test]
fn invalid_preferred_dark_theme() {
let src = r#"
[output.html]
preferred-dark-theme = "does-not-exist"
"#;

let got = Config::from_str(src).unwrap();
assert_eq!(got.html_config(), None);
}

#[test]
fn disable_runnable() {
let src = r#"
Expand Down
1 change: 1 addition & 0 deletions crates/mdbook-html/front-end/css/chrome.css
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ html:not(.js) .sidebar-resize-handle {
color: inherit;
background: inherit;
font-size: inherit;
text-transform: capitalize;
}
.theme-popup .theme:hover {
background-color: var(--theme-hover);
Expand Down
8 changes: 3 additions & 5 deletions crates/mdbook-html/front-end/templates/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,9 @@
</button>
<ul id="mdbook-theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-ayu">Ayu</button></li>
{{#each builtin_themes}}
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-{{this}}">{{this}}</button></li>
{{/each}}
</ul>
{{#if search_enabled}}
<button id="mdbook-search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="mdbook-searchbar">
Expand Down
16 changes: 7 additions & 9 deletions crates/mdbook-html/src/html_handlebars/hbs_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::utils::ToUrlPath;
use anyhow::{Context, Result, bail};
use handlebars::Handlebars;
use mdbook_core::book::{Book, BookItem, Chapter};
use mdbook_core::config::{BookConfig, Config, HtmlConfig};
use mdbook_core::config::{BookConfig, BuiltinTheme, Config, HtmlConfig};
use mdbook_core::utils::fs;
use mdbook_renderer::{RenderContext, Renderer};
use serde_json::json;
Expand Down Expand Up @@ -491,16 +491,14 @@ fn make_data(
);
}

let default_theme = match html_config.default_theme {
Some(ref theme) => theme.to_lowercase(),
None => "light".to_string(),
};
data.insert("builtin_themes".to_owned(), json!(BuiltinTheme::ALL));

let default_theme = html_config.default_theme.unwrap_or(BuiltinTheme::Light);
data.insert("default_theme".to_owned(), json!(default_theme));

let preferred_dark_theme = match html_config.preferred_dark_theme {
Some(ref theme) => theme.to_lowercase(),
None => "navy".to_string(),
};
let preferred_dark_theme = html_config
.preferred_dark_theme
.unwrap_or(BuiltinTheme::Navy);
data.insert(
"preferred_dark_theme".to_owned(),
json!(preferred_dark_theme),
Expand Down
12 changes: 7 additions & 5 deletions guide/src/format/configuration/renderers.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,14 @@ The following configuration options are available:
- **theme:** mdBook comes with a default theme and all the resource files needed
for it. But if this option is set, mdBook will selectively overwrite the theme
files with the ones found in the specified folder.
- **default-theme:** The theme color scheme to select by default in the
'Change Theme' dropdown. Defaults to `light`.
- **preferred-dark-theme:** The default dark theme. This theme will be used if
the browser requests the dark version of the site via the
- **default-theme:** The built-in theme to select by default in the
'Change Theme' dropdown. Accepted values are `light`, `rust`, `coal`, `navy`,
and `ayu`. Defaults to `light`.
- **preferred-dark-theme:** The built-in theme to use when the browser requests
the dark version of the site via the
[`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme)
CSS media query. Defaults to `navy`.
CSS media query. Accepted values are `light`, `rust`, `coal`, `navy`, and
`ayu`. Defaults to `navy`.
- **smart-punctuation:** Converts quotes to curly quotes, `...` to `…`, `--` to en-dash, and `---` to em-dash.
See [Smart Punctuation](../markdown.md#smart-punctuation).
Defaults to `true`.
Expand Down