mdbook/src/book/bookconfig.rs
2016-12-24 13:22:01 +00:00

228 lines
6.4 KiB
Rust

extern crate toml;
use std::process::exit;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::collections::BTreeMap;
use std::str::FromStr;
use serde_json;
#[derive(Debug, Clone)]
pub struct BookConfig {
root: PathBuf,
pub dest: PathBuf,
pub src: PathBuf,
pub theme_path: PathBuf,
pub title: String,
pub author: String,
pub description: String,
pub indent_spaces: i32,
multilingual: bool,
}
impl BookConfig {
pub fn new(root: &Path) -> Self {
BookConfig {
root: root.to_owned(),
dest: root.join("book"),
src: root.join("src"),
theme_path: root.join("theme"),
title: String::new(),
author: String::new(),
description: String::new(),
indent_spaces: 4, // indentation used for SUMMARY.md
multilingual: false,
}
}
pub fn read_config(&mut self, root: &Path) -> &mut Self {
debug!("[fn]: read_config");
let read_file = |path: PathBuf| -> String {
let mut data = String::new();
let mut f: File = match File::open(&path) {
Ok(x) => x,
Err(_) => {
error!("[*]: Failed to open {:?}", &path);
exit(2);
}
};
if let Err(_) = f.read_to_string(&mut data) {
error!("[*]: Failed to read {:?}", &path);
exit(2);
}
data
};
// Read book.toml or book.json if exists
if Path::new(root.join("book.toml").as_os_str()).exists() {
debug!("[*]: Reading config");
let data = read_file(root.join("book.toml"));
self.parse_from_toml_string(&data);
} else if Path::new(root.join("book.json").as_os_str()).exists() {
debug!("[*]: Reading config");
let data = read_file(root.join("book.json"));
self.parse_from_json_string(&data);
} else {
debug!("[*]: No book.toml or book.json was found, using defaults.");
}
self
}
pub fn parse_from_toml_string(&mut self, data: &String) -> &mut Self {
let mut parser = toml::Parser::new(&data);
let config = match parser.parse() {
Some(x) => {x},
None => {
error!("[*]: Toml parse errors in book.toml: {:?}", parser.errors);
exit(2);
}
};
self.parse_from_btreemap(&config);
self
}
/// Parses the string to JSON and converts it to BTreeMap<String, toml::Value>.
pub fn parse_from_json_string(&mut self, data: &String) -> &mut Self {
let c: serde_json::Value = match serde_json::from_str(&data) {
Ok(x) => x,
Err(e) => {
error!("[*]: JSON parse errors in book.json: {:?}", e);
exit(2);
}
};
let config = json_object_to_btreemap(&c.as_object().unwrap());
self.parse_from_btreemap(&config);
self
}
pub fn parse_from_btreemap(&mut self, config: &BTreeMap<String, toml::Value>) -> &mut Self {
// Title, author, description
if let Some(a) = config.get("title") {
self.title = a.to_string().replace("\"", "");
}
if let Some(a) = config.get("author") {
self.author = a.to_string().replace("\"", "");
}
if let Some(a) = config.get("description") {
self.description = a.to_string().replace("\"", "");
}
// Destination folder
if let Some(a) = config.get("dest") {
let mut dest = PathBuf::from(&a.to_string().replace("\"", ""));
// If path is relative make it absolute from the parent directory of src
if dest.is_relative() {
dest = self.get_root().join(&dest);
}
self.set_dest(&dest);
}
// Source folder
if let Some(a) = config.get("src") {
let mut src = PathBuf::from(&a.to_string().replace("\"", ""));
if src.is_relative() {
src = self.get_root().join(&src);
}
self.set_src(&src);
}
// Theme path folder
if let Some(a) = config.get("theme_path") {
let mut theme_path = PathBuf::from(&a.to_string().replace("\"", ""));
if theme_path.is_relative() {
theme_path = self.get_root().join(&theme_path);
}
self.set_theme_path(&theme_path);
}
self
}
pub fn get_root(&self) -> &Path {
&self.root
}
pub fn set_root(&mut self, root: &Path) -> &mut Self {
self.root = root.to_owned();
self
}
pub fn get_dest(&self) -> &Path {
&self.dest
}
pub fn set_dest(&mut self, dest: &Path) -> &mut Self {
self.dest = dest.to_owned();
self
}
pub fn get_src(&self) -> &Path {
&self.src
}
pub fn set_src(&mut self, src: &Path) -> &mut Self {
self.src = src.to_owned();
self
}
pub fn get_theme_path(&self) -> &Path {
&self.theme_path
}
pub fn set_theme_path(&mut self, theme_path: &Path) -> &mut Self {
self.theme_path = theme_path.to_owned();
self
}
}
pub fn json_object_to_btreemap(json: &serde_json::Map<String, serde_json::Value>) -> BTreeMap<String, toml::Value> {
let mut config: BTreeMap<String, toml::Value> = BTreeMap::new();
for (key, value) in json.iter() {
config.insert(
String::from_str(key).unwrap(),
json_value_to_toml_value(value.to_owned())
);
}
config
}
pub fn json_value_to_toml_value(json: serde_json::Value) -> toml::Value {
match json {
serde_json::Value::Null => toml::Value::String("".to_string()),
serde_json::Value::Bool(x) => toml::Value::Boolean(x),
serde_json::Value::I64(x) => toml::Value::Integer(x),
serde_json::Value::U64(x) => toml::Value::Integer(x as i64),
serde_json::Value::F64(x) => toml::Value::Float(x),
serde_json::Value::String(x) => toml::Value::String(x),
serde_json::Value::Array(x) => {
toml::Value::Array(x.iter().map(|v| json_value_to_toml_value(v.to_owned())).collect())
},
serde_json::Value::Object(x) => {
toml::Value::Table(json_object_to_btreemap(&x))
},
}
}