diff options
Diffstat (limited to 'vendor/mdbook/src/book/init.rs')
-rw-r--r-- | vendor/mdbook/src/book/init.rs | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/vendor/mdbook/src/book/init.rs b/vendor/mdbook/src/book/init.rs new file mode 100644 index 000000000..264c113d3 --- /dev/null +++ b/vendor/mdbook/src/book/init.rs @@ -0,0 +1,207 @@ +use std::fs::{self, File}; +use std::io::Write; +use std::path::PathBuf; + +use super::MDBook; +use crate::config::Config; +use crate::errors::*; +use crate::theme; + +/// A helper for setting up a new book and its directory structure. +#[derive(Debug, Clone, PartialEq)] +pub struct BookBuilder { + root: PathBuf, + create_gitignore: bool, + config: Config, + copy_theme: bool, +} + +impl BookBuilder { + /// Create a new `BookBuilder` which will generate a book in the provided + /// root directory. + pub fn new<P: Into<PathBuf>>(root: P) -> BookBuilder { + BookBuilder { + root: root.into(), + create_gitignore: false, + config: Config::default(), + copy_theme: false, + } + } + + /// Set the [`Config`] to be used. + pub fn with_config(&mut self, cfg: Config) -> &mut BookBuilder { + self.config = cfg; + self + } + + /// Get the config used by the `BookBuilder`. + pub fn config(&self) -> &Config { + &self.config + } + + /// Should the theme be copied into the generated book (so users can tweak + /// it)? + pub fn copy_theme(&mut self, copy: bool) -> &mut BookBuilder { + self.copy_theme = copy; + self + } + + /// Should we create a `.gitignore` file? + pub fn create_gitignore(&mut self, create: bool) -> &mut BookBuilder { + self.create_gitignore = create; + self + } + + /// Generate the actual book. This will: + /// + /// - Create the directory structure. + /// - Stub out some dummy chapters and the `SUMMARY.md`. + /// - Create a `.gitignore` (if applicable) + /// - Create a themes directory and populate it (if applicable) + /// - Generate a `book.toml` file, + /// - Then load the book so we can build it or run tests. + pub fn build(&self) -> Result<MDBook> { + info!("Creating a new book with stub content"); + + self.create_directory_structure() + .with_context(|| "Unable to create directory structure")?; + + self.create_stub_files() + .with_context(|| "Unable to create stub files")?; + + if self.create_gitignore { + self.build_gitignore() + .with_context(|| "Unable to create .gitignore")?; + } + + if self.copy_theme { + self.copy_across_theme() + .with_context(|| "Unable to copy across the theme")?; + } + + self.write_book_toml()?; + + match MDBook::load(&self.root) { + Ok(book) => Ok(book), + Err(e) => { + error!("{}", e); + + panic!( + "The BookBuilder should always create a valid book. If you are seeing this it \ + is a bug and should be reported." + ); + } + } + } + + fn write_book_toml(&self) -> Result<()> { + debug!("Writing book.toml"); + let book_toml = self.root.join("book.toml"); + let cfg = toml::to_vec(&self.config).with_context(|| "Unable to serialize the config")?; + + File::create(book_toml) + .with_context(|| "Couldn't create book.toml")? + .write_all(&cfg) + .with_context(|| "Unable to write config to book.toml")?; + Ok(()) + } + + fn copy_across_theme(&self) -> Result<()> { + debug!("Copying theme"); + + let html_config = self.config.html_config().unwrap_or_default(); + let themedir = html_config.theme_dir(&self.root); + + if !themedir.exists() { + debug!( + "{} does not exist, creating the directory", + themedir.display() + ); + fs::create_dir(&themedir)?; + } + + let mut index = File::create(themedir.join("index.hbs"))?; + index.write_all(theme::INDEX)?; + + let cssdir = themedir.join("css"); + if !cssdir.exists() { + fs::create_dir(&cssdir)?; + } + + let mut general_css = File::create(cssdir.join("general.css"))?; + general_css.write_all(theme::GENERAL_CSS)?; + + let mut chrome_css = File::create(cssdir.join("chrome.css"))?; + chrome_css.write_all(theme::CHROME_CSS)?; + + if html_config.print.enable { + let mut print_css = File::create(cssdir.join("print.css"))?; + print_css.write_all(theme::PRINT_CSS)?; + } + + let mut variables_css = File::create(cssdir.join("variables.css"))?; + variables_css.write_all(theme::VARIABLES_CSS)?; + + let mut favicon = File::create(themedir.join("favicon.png"))?; + favicon.write_all(theme::FAVICON_PNG)?; + + let mut favicon = File::create(themedir.join("favicon.svg"))?; + favicon.write_all(theme::FAVICON_SVG)?; + + let mut js = File::create(themedir.join("book.js"))?; + js.write_all(theme::JS)?; + + let mut highlight_css = File::create(themedir.join("highlight.css"))?; + highlight_css.write_all(theme::HIGHLIGHT_CSS)?; + + let mut highlight_js = File::create(themedir.join("highlight.js"))?; + highlight_js.write_all(theme::HIGHLIGHT_JS)?; + + Ok(()) + } + + fn build_gitignore(&self) -> Result<()> { + debug!("Creating .gitignore"); + + let mut f = File::create(self.root.join(".gitignore"))?; + + writeln!(f, "{}", self.config.build.build_dir.display())?; + + Ok(()) + } + + fn create_stub_files(&self) -> Result<()> { + debug!("Creating example book contents"); + let src_dir = self.root.join(&self.config.book.src); + + let summary = src_dir.join("SUMMARY.md"); + if !summary.exists() { + trace!("No summary found creating stub summary and chapter_1.md."); + let mut f = File::create(&summary).with_context(|| "Unable to create SUMMARY.md")?; + writeln!(f, "# Summary")?; + writeln!(f)?; + writeln!(f, "- [Chapter 1](./chapter_1.md)")?; + + let chapter_1 = src_dir.join("chapter_1.md"); + let mut f = + File::create(&chapter_1).with_context(|| "Unable to create chapter_1.md")?; + writeln!(f, "# Chapter 1")?; + } else { + trace!("Existing summary found, no need to create stub files."); + } + Ok(()) + } + + fn create_directory_structure(&self) -> Result<()> { + debug!("Creating directory tree"); + fs::create_dir_all(&self.root)?; + + let src = self.root.join(&self.config.book.src); + fs::create_dir_all(&src)?; + + let build = self.root.join(&self.config.build.build_dir); + fs::create_dir_all(&build)?; + + Ok(()) + } +} |