parse either book.toml or book.json
This commit is contained in:
parent
f67ae7c71a
commit
791487bc84
|
@ -1,8 +1,13 @@
|
||||||
use serde_json;
|
extern crate toml;
|
||||||
|
|
||||||
|
use std::process::exit;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
//use serde::{Serialize, Deserialize};
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BookConfig {
|
pub struct BookConfig {
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
|
@ -18,7 +23,6 @@ pub struct BookConfig {
|
||||||
multilingual: bool,
|
multilingual: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl BookConfig {
|
impl BookConfig {
|
||||||
pub fn new(root: &Path) -> Self {
|
pub fn new(root: &Path) -> Self {
|
||||||
BookConfig {
|
BookConfig {
|
||||||
|
@ -40,71 +44,154 @@ impl BookConfig {
|
||||||
|
|
||||||
debug!("[fn]: read_config");
|
debug!("[fn]: read_config");
|
||||||
|
|
||||||
// If the file does not exist, return early
|
let read_file = |path: PathBuf| -> String {
|
||||||
let mut config_file = match File::open(root.join("book.json")) {
|
let mut data = String::new();
|
||||||
Ok(f) => f,
|
let mut f: File = match File::open(&path) {
|
||||||
Err(_) => {
|
Ok(x) => x,
|
||||||
debug!("[*]: Failed to open {:?}", root.join("book.json"));
|
Err(_) => {
|
||||||
return self;
|
error!("[*]: Failed to open {:?}", &path);
|
||||||
},
|
exit(2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Err(_) = f.read_to_string(&mut data) {
|
||||||
|
error!("[*]: Failed to read {:?}", &path);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
data
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("[*]: Reading config");
|
// Read book.toml or book.json if exists
|
||||||
let mut data = String::new();
|
|
||||||
|
|
||||||
// Just return if an error occured.
|
if Path::new(root.join("book.toml").as_os_str()).exists() {
|
||||||
// I would like to propagate the error, but I have to return `&self`
|
|
||||||
if let Err(_) = config_file.read_to_string(&mut data) {
|
debug!("[*]: Reading config");
|
||||||
return self;
|
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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to JSON
|
self
|
||||||
if let Ok(config) = serde_json::from_str::<serde_json::Value>(&data) {
|
}
|
||||||
// Extract data
|
|
||||||
|
|
||||||
let config = config.as_object().unwrap();
|
pub fn parse_from_toml_string(&mut self, data: &String) -> &mut Self {
|
||||||
|
|
||||||
debug!("[*]: Extracting data from config");
|
let mut parser = toml::Parser::new(&data);
|
||||||
// Title, author, description
|
|
||||||
if let Some(a) = config.get("title") {
|
let config = match parser.parse() {
|
||||||
self.title = a.to_string().replace("\"", "")
|
Some(x) => {x},
|
||||||
}
|
None => {
|
||||||
if let Some(a) = config.get("author") {
|
error!("[*]: Toml parse errors in book.toml: {:?}", parser.errors);
|
||||||
self.author = a.to_string().replace("\"", "")
|
exit(2);
|
||||||
}
|
|
||||||
if let Some(a) = config.get("description") {
|
|
||||||
self.description = a.to_string().replace("\"", "")
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Destination folder
|
// TODO this is very similar to how the JSON is parsed. Combine somehow?
|
||||||
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
|
// Title, author, description
|
||||||
if dest.is_relative() {
|
if let Some(a) = config.get("title") {
|
||||||
dest = self.get_root().join(&dest);
|
self.title = a.to_string().replace("\"", "");
|
||||||
}
|
}
|
||||||
self.set_dest(&dest);
|
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
|
// Source folder
|
||||||
if let Some(a) = config.get("src") {
|
if let Some(a) = config.get("src") {
|
||||||
let mut src = PathBuf::from(&a.to_string().replace("\"", ""));
|
let mut src = PathBuf::from(&a.to_string().replace("\"", ""));
|
||||||
if src.is_relative() {
|
if src.is_relative() {
|
||||||
src = self.get_root().join(&src);
|
src = self.get_root().join(&src);
|
||||||
}
|
|
||||||
self.set_src(&src);
|
|
||||||
}
|
}
|
||||||
|
self.set_src(&src);
|
||||||
|
}
|
||||||
|
|
||||||
// Theme path folder
|
// Theme path folder
|
||||||
if let Some(a) = config.get("theme_path") {
|
if let Some(a) = config.get("theme_path") {
|
||||||
let mut theme_path = PathBuf::from(&a.to_string().replace("\"", ""));
|
let mut theme_path = PathBuf::from(&a.to_string().replace("\"", ""));
|
||||||
if theme_path.is_relative() {
|
if theme_path.is_relative() {
|
||||||
theme_path = self.get_root().join(&theme_path);
|
theme_path = self.get_root().join(&theme_path);
|
||||||
}
|
|
||||||
self.set_theme_path(&theme_path);
|
|
||||||
}
|
}
|
||||||
|
self.set_theme_path(&theme_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_from_json_string(&mut self, data: &String) -> &mut Self {
|
||||||
|
|
||||||
|
let config: serde_json::Value = match serde_json::from_str(&data) {
|
||||||
|
Ok(x) => {x},
|
||||||
|
Err(e) => {
|
||||||
|
error!("[*]: JSON parse errors in book.json: {:?}", e);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract data
|
||||||
|
|
||||||
|
let config = config.as_object().unwrap();
|
||||||
|
|
||||||
|
debug!("[*]: Extracting data from config");
|
||||||
|
|
||||||
|
// 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
|
self
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use book::bookconfig::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_parses_json_config() {
|
||||||
|
let text = r#"
|
||||||
|
{
|
||||||
|
"title": "mdBook Documentation",
|
||||||
|
"description": "Create book from markdown files. Like Gitbook but implemented in Rust",
|
||||||
|
"author": "Mathieu David"
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
// TODO don't require path argument, take pwd
|
||||||
|
let mut config = BookConfig::new(Path::new("."));
|
||||||
|
|
||||||
|
config.parse_from_json_string(&text.to_string());
|
||||||
|
|
||||||
|
let expected = r#"BookConfig {
|
||||||
|
root: ".",
|
||||||
|
dest: "./book",
|
||||||
|
src: "./src",
|
||||||
|
theme_path: "./theme",
|
||||||
|
title: "mdBook Documentation",
|
||||||
|
author: "Mathieu David",
|
||||||
|
description: "Create book from markdown files. Like Gitbook but implemented in Rust",
|
||||||
|
indent_spaces: 4,
|
||||||
|
multilingual: false
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
assert_eq!(format!("{:#?}", config), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_parses_toml_config() {
|
||||||
|
let text = r#"
|
||||||
|
title = "mdBook Documentation"
|
||||||
|
description = "Create book from markdown files. Like Gitbook but implemented in Rust"
|
||||||
|
author = "Mathieu David"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
// TODO don't require path argument, take pwd
|
||||||
|
let mut config = BookConfig::new(Path::new("."));
|
||||||
|
|
||||||
|
config.parse_from_toml_string(&text.to_string());
|
||||||
|
|
||||||
|
println!("{:#?}", config);
|
||||||
|
|
||||||
|
let expected = r#"BookConfig {
|
||||||
|
root: ".",
|
||||||
|
dest: "./book",
|
||||||
|
src: "./src",
|
||||||
|
theme_path: "./theme",
|
||||||
|
title: "mdBook Documentation",
|
||||||
|
author: "Mathieu David",
|
||||||
|
description: "Create book from markdown files. Like Gitbook but implemented in Rust",
|
||||||
|
indent_spaces: 4,
|
||||||
|
multilingual: false
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
assert_eq!(format!("{:#?}", config), expected);
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
pub mod bookitem;
|
pub mod bookitem;
|
||||||
pub mod bookconfig;
|
pub mod bookconfig;
|
||||||
|
|
||||||
|
pub mod bookconfig_test;
|
||||||
|
|
||||||
pub use self::bookitem::{BookItem, BookItems};
|
pub use self::bookitem::{BookItem, BookItems};
|
||||||
pub use self::bookconfig::BookConfig;
|
pub use self::bookconfig::BookConfig;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue