New configuration struct + tests #285
This commit is contained in:
parent
272022621d
commit
170bf8b1eb
|
@ -18,6 +18,7 @@ exclude = [
|
||||||
clap = "2.24"
|
clap = "2.24"
|
||||||
handlebars = "0.26"
|
handlebars = "0.26"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
pulldown-cmark = "0.0.14"
|
pulldown-cmark = "0.0.14"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
use std::path::{PathBuf, Path};
|
||||||
|
|
||||||
|
use super::HtmlConfig;
|
||||||
|
use super::tomlconfig::TomlConfig;
|
||||||
|
|
||||||
|
/// Configuration struct containing all the configuration options available in mdBook.
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct BookConfig {
|
||||||
|
root: PathBuf,
|
||||||
|
source: PathBuf,
|
||||||
|
|
||||||
|
title: String,
|
||||||
|
authors: Vec<String>,
|
||||||
|
description: String,
|
||||||
|
|
||||||
|
multilingual: bool,
|
||||||
|
indent_spaces: i32,
|
||||||
|
|
||||||
|
html_config: Option<HtmlConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BookConfig {
|
||||||
|
/// Creates a new `BookConfig` struct with as root path the path given as parameter.
|
||||||
|
/// The source directory is `root/src` and the destination for the rendered book is `root/book`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::path::PathBuf;
|
||||||
|
/// # use mdbook::config::{BookConfig, HtmlConfig};
|
||||||
|
/// #
|
||||||
|
/// let root = PathBuf::from("directory/to/my/book");
|
||||||
|
/// let config = BookConfig::new(&root);
|
||||||
|
///
|
||||||
|
/// assert_eq!(config.get_root(), &root);
|
||||||
|
/// assert_eq!(config.get_source(), PathBuf::from("directory/to/my/book/src"));
|
||||||
|
/// assert_eq!(config.get_html_config(), Some(&HtmlConfig::new(PathBuf::from("directory/to/my/book"))));
|
||||||
|
/// ```
|
||||||
|
pub fn new<T: Into<PathBuf>>(root: T) -> Self {
|
||||||
|
let root: PathBuf = root.into();
|
||||||
|
let htmlconfig = HtmlConfig::new(&root);
|
||||||
|
|
||||||
|
BookConfig {
|
||||||
|
root: root.clone(),
|
||||||
|
source: root.join("src"),
|
||||||
|
|
||||||
|
title: String::new(),
|
||||||
|
authors: Vec::new(),
|
||||||
|
description: String::new(),
|
||||||
|
|
||||||
|
multilingual: false,
|
||||||
|
indent_spaces: 4,
|
||||||
|
|
||||||
|
html_config: Some(htmlconfig),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder method to set the source directory
|
||||||
|
pub fn with_source<T: Into<PathBuf>>(mut self, source: T) -> Self {
|
||||||
|
self.source = source.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder method to set the book's title
|
||||||
|
pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
|
||||||
|
self.title = title.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder method to set the book's description
|
||||||
|
pub fn with_description<T: Into<String>>(mut self, description: T) -> Self {
|
||||||
|
self.description = description.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builder method to set the book's authors
|
||||||
|
pub fn with_authors<T: Into<Vec<String>>>(mut self, authors: T) -> Self {
|
||||||
|
self.authors = authors.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_tomlconfig<T: Into<PathBuf>>(root: T, tomlconfig: TomlConfig) -> Self {
|
||||||
|
let root = root.into();
|
||||||
|
let mut config = BookConfig::new(&root);
|
||||||
|
|
||||||
|
if let Some(s) = tomlconfig.source {
|
||||||
|
config.set_source(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(t) = tomlconfig.title {
|
||||||
|
config.set_title(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(d) = tomlconfig.description {
|
||||||
|
config.set_description(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(a) = tomlconfig.authors {
|
||||||
|
config.set_authors(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(a) = tomlconfig.author {
|
||||||
|
config.set_authors(vec![a]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(tomlhtmlconfig) = tomlconfig.output.and_then(|o| o.html) {
|
||||||
|
let source = config.get_source().to_owned();
|
||||||
|
let mut htmlconfig = config.get_mut_html_config().expect("We just created a new config and it creates a default HtmlConfig");
|
||||||
|
htmlconfig.fill_from_tomlconfig(&root, &source, tomlhtmlconfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_root<T: Into<PathBuf>>(&mut self, root: T) -> &mut Self {
|
||||||
|
self.root = root.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_root(&self) -> &Path {
|
||||||
|
&self.root
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_source<T: Into<PathBuf>>(&mut self, source: T) -> &mut Self {
|
||||||
|
let mut source = source.into();
|
||||||
|
|
||||||
|
// If the source path is relative, start with the root path
|
||||||
|
if source.is_relative() {
|
||||||
|
source = self.root.join(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.source = source;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_source(&self) -> &Path {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title<T: Into<String>>(&mut self, title: T) -> &mut Self {
|
||||||
|
self.title = title.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_title(&self) -> &str {
|
||||||
|
&self.title
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_description<T: Into<String>>(&mut self, description: T) -> &mut Self {
|
||||||
|
self.description = description.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_description(&self) -> &str {
|
||||||
|
&self.description
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_authors<T: Into<Vec<String>>>(&mut self, authors: T) -> &mut Self {
|
||||||
|
self.authors = authors.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the authors of the book as specified in the configuration file
|
||||||
|
pub fn get_authors(&self) -> &[String] {
|
||||||
|
self.authors.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_html_config(&mut self, htmlconfig: HtmlConfig) -> &mut Self {
|
||||||
|
self.html_config = Some(htmlconfig);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the configuration for the HTML renderer or None of there isn't any
|
||||||
|
pub fn get_html_config(&self) -> Option<&HtmlConfig> {
|
||||||
|
self.html_config.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mut_html_config(&mut self) -> Option<&mut HtmlConfig> {
|
||||||
|
self.html_config.as_mut()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
use std::path::{PathBuf, Path};
|
||||||
|
|
||||||
|
use super::tomlconfig::TomlHtmlConfig;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct HtmlConfig {
|
||||||
|
destination: PathBuf,
|
||||||
|
theme: Option<PathBuf>,
|
||||||
|
google_analytics: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HtmlConfig {
|
||||||
|
/// Creates a new `HtmlConfig` struct containing the configuration parameters for the HTML renderer.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::path::PathBuf;
|
||||||
|
/// # use mdbook::config::HtmlConfig;
|
||||||
|
/// #
|
||||||
|
/// let output = PathBuf::from("root/book");
|
||||||
|
/// let config = HtmlConfig::new(PathBuf::from("root"));
|
||||||
|
///
|
||||||
|
/// assert_eq!(config.get_destination(), &output);
|
||||||
|
/// ```
|
||||||
|
pub fn new<T: Into<PathBuf>>(root: T) -> Self {
|
||||||
|
HtmlConfig {
|
||||||
|
destination: root.into().join("book"),
|
||||||
|
theme: None,
|
||||||
|
google_analytics: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill_from_tomlconfig<T: Into<PathBuf>>(&mut self, root: T, source: T, tomlconfig: TomlHtmlConfig) -> &mut Self {
|
||||||
|
if let Some(d) = tomlconfig.destination {
|
||||||
|
if d.is_relative() {
|
||||||
|
self.destination = root.into().join(d);
|
||||||
|
} else {
|
||||||
|
self.destination = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(t) = tomlconfig.theme {
|
||||||
|
if t.is_relative() {
|
||||||
|
self.theme = Some(source.into().join(t));
|
||||||
|
} else {
|
||||||
|
self.theme = Some(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tomlconfig.google_analytics.is_some() {
|
||||||
|
self.google_analytics = tomlconfig.google_analytics;
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_destination(&self) -> &Path {
|
||||||
|
&self.destination
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: How to get a `Option<&Path>` ?
|
||||||
|
pub fn get_theme(&self) -> Option<&PathBuf> {
|
||||||
|
self.theme.as_ref()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
pub mod bookconfig;
|
||||||
|
pub mod htmlconfig;
|
||||||
|
pub mod tomlconfig;
|
||||||
|
|
||||||
|
// Re-export the config structs
|
||||||
|
pub use self::bookconfig::BookConfig;
|
||||||
|
pub use self::htmlconfig::HtmlConfig;
|
|
@ -0,0 +1,50 @@
|
||||||
|
extern crate toml;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct TomlConfig {
|
||||||
|
pub source: Option<PathBuf>,
|
||||||
|
|
||||||
|
pub title: Option<String>,
|
||||||
|
pub author: Option<String>,
|
||||||
|
pub authors: Option<Vec<String>>,
|
||||||
|
pub description: Option<String>,
|
||||||
|
|
||||||
|
pub output: Option<TomlOutputConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct TomlOutputConfig {
|
||||||
|
pub html: Option<TomlHtmlConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
pub struct TomlHtmlConfig {
|
||||||
|
pub destination: Option<PathBuf>,
|
||||||
|
pub theme: Option<PathBuf>,
|
||||||
|
pub google_analytics: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a TomlConfig from a TOML string
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use mdbook::config::tomlconfig::TomlConfig;
|
||||||
|
/// # use std::path::PathBuf;
|
||||||
|
/// let toml = r#"title="Some title"
|
||||||
|
/// [output.html]
|
||||||
|
/// destination = "htmlbook" "#;
|
||||||
|
///
|
||||||
|
/// let config = TomlConfig::from_toml(&toml).expect("Should parse correctly");
|
||||||
|
/// assert_eq!(config.title, Some(String::from("Some title")));
|
||||||
|
/// assert_eq!(config.output.unwrap().html.unwrap().destination, Some(PathBuf::from("htmlbook")));
|
||||||
|
/// ```
|
||||||
|
impl TomlConfig {
|
||||||
|
pub fn from_toml(input: &str) -> Result<Self, String> {
|
||||||
|
let config: TomlConfig = toml::from_str(input)
|
||||||
|
.map_err(|e| format!("Could not parse TOML: {}", e))?;
|
||||||
|
|
||||||
|
return Ok(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,9 +69,11 @@
|
||||||
//!
|
//!
|
||||||
//! Make sure to take a look at it.
|
//! Make sure to take a look at it.
|
||||||
|
|
||||||
extern crate serde;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_json;
|
extern crate serde_derive;
|
||||||
|
extern crate serde;
|
||||||
|
#[macro_use] extern crate serde_json;
|
||||||
|
|
||||||
extern crate handlebars;
|
extern crate handlebars;
|
||||||
extern crate pulldown_cmark;
|
extern crate pulldown_cmark;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
@ -79,6 +81,7 @@ extern crate regex;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
pub mod book;
|
pub mod book;
|
||||||
|
pub mod config;
|
||||||
mod parse;
|
mod parse;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
extern crate mdbook;
|
||||||
|
use mdbook::config::BookConfig;
|
||||||
|
use mdbook::config::tomlconfig::TomlConfig;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
// Tests that the `title` key is correcly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_source() {
|
||||||
|
let toml = r#"source = "source""#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
assert_eq!(config.get_source(), PathBuf::from("root/source"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the `title` key is correcly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_title() {
|
||||||
|
let toml = r#"title = "Some title""#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
assert_eq!(config.get_title(), "Some title");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the `description` key is correcly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_description() {
|
||||||
|
let toml = r#"description = "This is a description""#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
assert_eq!(config.get_description(), "This is a description");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the `author` key is correcly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_author() {
|
||||||
|
let toml = r#"author = "John Doe""#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
assert_eq!(config.get_authors(), &[String::from("John Doe")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the `authors` key is correcly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_authors() {
|
||||||
|
let toml = r#"authors = ["John Doe", "Jane Doe"]"#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
assert_eq!(config.get_authors(), &[String::from("John Doe"), String::from("Jane Doe")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the `output.html.destination` key is correcly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_output_html_destination() {
|
||||||
|
let toml = r#"[output.html]
|
||||||
|
destination = "htmlbook""#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig");
|
||||||
|
|
||||||
|
assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the `output.html.theme` key is correcly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_output_html_theme() {
|
||||||
|
let toml = r#"[output.html]
|
||||||
|
theme = "theme""#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig");
|
||||||
|
|
||||||
|
assert_eq!(htmlconfig.get_theme().expect("the theme key was provided"), &PathBuf::from("root/src/theme"));
|
||||||
|
}
|
Loading…
Reference in New Issue