diff --git a/src/book/book.rs b/src/book/book.rs index e4c631ef..b69e98ab 100644 --- a/src/book/book.rs +++ b/src/book/book.rs @@ -167,9 +167,9 @@ impl Chapter { ) -> Chapter { Chapter { name: name.to_string(), - content: content, + content, path: path.into(), - parent_names: parent_names, + parent_names, ..Default::default() } } @@ -210,7 +210,7 @@ fn load_summary_item>( match *item { SummaryItem::Separator => Ok(BookItem::Separator), SummaryItem::Link(ref link) => { - load_chapter(link, src_dir, parent_names).map(|c| BookItem::Chapter(c)) + load_chapter(link, src_dir, parent_names).map(BookItem::Chapter) } } } diff --git a/src/book/init.rs b/src/book/init.rs index 202b3ec5..4acf4b52 100644 --- a/src/book/init.rs +++ b/src/book/init.rs @@ -175,7 +175,7 @@ impl BookBuilder { let summary = src_dir.join("SUMMARY.md"); let mut f = File::create(&summary).chain_err(|| "Unable to create SUMMARY.md")?; writeln!(f, "# Summary")?; - writeln!(f, "")?; + writeln!(f)?; writeln!(f, "- [Chapter 1](./chapter_1.md)")?; let chapter_1 = src_dir.join("chapter_1.md"); diff --git a/src/book/mod.rs b/src/book/mod.rs index 3ffbde6f..48537a37 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -20,8 +20,9 @@ use tempfile::Builder as TempFileBuilder; use toml::Value; use errors::*; -use preprocess::{IndexPreprocessor, LinkPreprocessor, Preprocessor, - PreprocessorContext, CmdPreprocessor}; +use preprocess::{ + CmdPreprocessor, IndexPreprocessor, LinkPreprocessor, Preprocessor, PreprocessorContext, +}; use renderer::{CmdRenderer, HtmlHandlebars, RenderContext, Renderer}; use utils; @@ -160,15 +161,16 @@ impl MDBook { /// Run the entire build process for a particular `Renderer`. fn execute_build_process(&self, renderer: &Renderer) -> Result<()> { let mut preprocessed_book = self.book.clone(); - let preprocess_ctx = PreprocessorContext::new(self.root.clone(), - self.config.clone(), - renderer.name().to_string()); + let preprocess_ctx = PreprocessorContext::new( + self.root.clone(), + self.config.clone(), + renderer.name().to_string(), + ); for preprocessor in &self.preprocessors { if preprocessor_should_run(&**preprocessor, renderer, &self.config) { debug!("Running the {} preprocessor.", preprocessor.name()); - preprocessed_book = - preprocessor.run(&preprocess_ctx, preprocessed_book)?; + preprocessed_book = preprocessor.run(&preprocess_ctx, preprocessed_book)?; } } @@ -178,11 +180,7 @@ impl MDBook { Ok(()) } - fn render( - &self, - preprocessed_book: &Book, - renderer: &Renderer, - ) -> Result<()> { + fn render(&self, preprocessed_book: &Book, renderer: &Renderer) -> Result<()> { let name = renderer.name(); let build_dir = self.build_dir_for(name); if build_dir.exists() { @@ -233,9 +231,8 @@ impl MDBook { let temp_dir = TempFileBuilder::new().prefix("mdbook-").tempdir()?; // FIXME: Is "test" the proper renderer name to use here? - let preprocess_context = PreprocessorContext::new(self.root.clone(), - self.config.clone(), - "test".to_string()); + let preprocess_context = + PreprocessorContext::new(self.root.clone(), self.config.clone(), "test".to_string()); let book = LinkPreprocessor::new().run(&preprocess_context, self.book.clone())?; // Index Preprocessor is disabled so that chapter paths continue to point to the @@ -363,17 +360,11 @@ fn determine_preprocessors(config: &Config) -> Result>> { preprocessors.extend(default_preprocessors()); } - if let Some(preprocessor_table) = - config.get("preprocessor").and_then(|v| v.as_table()) - { + if let Some(preprocessor_table) = config.get("preprocessor").and_then(|v| v.as_table()) { for key in preprocessor_table.keys() { match key.as_ref() { - "links" => { - preprocessors.push(Box::new(LinkPreprocessor::new())) - } - "index" => { - preprocessors.push(Box::new(IndexPreprocessor::new())) - } + "links" => preprocessors.push(Box::new(LinkPreprocessor::new())), + "index" => preprocessors.push(Box::new(IndexPreprocessor::new())), name => preprocessors.push(interpret_custom_preprocessor( name, &preprocessor_table[name], @@ -385,10 +376,7 @@ fn determine_preprocessors(config: &Config) -> Result>> { Ok(preprocessors) } -fn interpret_custom_preprocessor( - key: &str, - table: &Value, -) -> Box { +fn interpret_custom_preprocessor(key: &str, table: &Value) -> Box { let command = table .get("command") .and_then(|c| c.as_str()) @@ -406,8 +394,7 @@ fn interpret_custom_renderer(key: &str, table: &Value) -> Box { .and_then(|c| c.as_str()) .map(|s| s.to_string()); - let command = - table_dot_command.unwrap_or_else(|| format!("mdbook-{}", key)); + let command = table_dot_command.unwrap_or_else(|| format!("mdbook-{}", key)); Box::new(CmdRenderer::new(key.to_string(), command.to_string())) } @@ -428,7 +415,8 @@ fn preprocessor_should_run(preprocessor: &Preprocessor, renderer: &Renderer, cfg let renderer_name = renderer.name(); if let Some(Value::Array(ref explicit_renderers)) = cfg.get(&key) { - return explicit_renderers.into_iter() + return explicit_renderers + .iter() .filter_map(|val| val.as_str()) .any(|name| name == renderer_name); } @@ -436,7 +424,6 @@ fn preprocessor_should_run(preprocessor: &Preprocessor, renderer: &Renderer, cfg preprocessor.supports_renderer(renderer_name) } - #[cfg(test)] mod tests { use super::*; @@ -539,10 +526,7 @@ mod tests { // make sure the `preprocessor.random` table exists let random = cfg.get_preprocessor("random").unwrap(); - let random = interpret_custom_preprocessor( - "random", - &Value::Table(random.clone()), - ); + let random = interpret_custom_preprocessor("random", &Value::Table(random.clone())); assert_eq!(random.cmd(), "python random.py"); } @@ -557,7 +541,8 @@ mod tests { let cfg = Config::from_str(cfg_str).unwrap(); // double-check that we can access preprocessor.links.renderers[0] - let html = cfg.get_preprocessor("links") + let html = cfg + .get_preprocessor("links") .and_then(|links| links.get("renderers")) .and_then(|renderers| renderers.as_array()) .and_then(|renderers| renderers.get(0)) diff --git a/src/book/summary.rs b/src/book/summary.rs index a7f73358..31bf0b9b 100644 --- a/src/book/summary.rs +++ b/src/book/summary.rs @@ -280,7 +280,7 @@ impl<'a> SummaryParser<'a> { Err(self.parse_error("You can't have an empty link.")) } else { Ok(Link { - name: name, + name, location: PathBuf::from(href.to_string()), number: None, nested_items: Vec::new(), @@ -313,7 +313,6 @@ impl<'a> SummaryParser<'a> { root_items += bunch_of_items.len() as u32; items.extend(bunch_of_items); - match self.next_event() { Some(Event::Start(Tag::Paragraph)) => { // we're starting the suffix chapters @@ -732,7 +731,8 @@ mod tests { /// Ensure section numbers are correctly incremented after a horizontal separator. #[test] fn keep_numbering_after_separator() { - let src = "- [First](./first.md)\n---\n- [Second](./second.md)\n---\n- [Third](./third.md)\n"; + let src = + "- [First](./first.md)\n---\n- [Second](./second.md)\n---\n- [Third](./third.md)\n"; let should_be = vec![ SummaryItem::Link(Link { name: String::from("First"), diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs index ba89c587..0fd88c3a 100644 --- a/src/cmd/serve.rs +++ b/src/cmd/serve.rs @@ -115,7 +115,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> { } #[cfg(feature = "watch")] - watch::trigger_on_change(&mut book, move |path, book_dir| { + watch::trigger_on_change(&book, move |path, book_dir| { info!("File changed: {:?}", path); info!("Building book..."); diff --git a/src/config.rs b/src/config.rs index 71591ace..c6b37094 100644 --- a/src/config.rs +++ b/src/config.rs @@ -301,8 +301,8 @@ impl<'de> Deserialize<'de> for Config { .unwrap_or_default(); Ok(Config { - book: book, - build: build, + book, + build, rest: Value::Table(table), }) } @@ -444,7 +444,7 @@ pub struct HtmlConfig { pub search: Option, /// Git repository url. If `None`, the git button will not be shown. pub git_repository_url: Option, - /// FontAwesome icon class to use for the Git repository link. + /// FontAwesome icon class to use for the Git repository link. /// Defaults to `fa-github` if `None`. pub git_repository_icon: Option, } diff --git a/src/main.rs b/src/main.rs index 86147532..dec89cf3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,8 +20,8 @@ use std::path::{Path, PathBuf}; mod cmd; -const NAME: &'static str = "mdBook"; -const VERSION: &'static str = concat!("v", crate_version!()); +const NAME: &str = "mdBook"; +const VERSION: &str = concat!("v", crate_version!()); fn main() { init_logger(); diff --git a/src/preprocess/index.rs b/src/preprocess/index.rs index 5560db54..a8818518 100644 --- a/src/preprocess/index.rs +++ b/src/preprocess/index.rs @@ -7,7 +7,7 @@ use super::{Preprocessor, PreprocessorContext}; use book::{Book, BookItem}; /// A preprocessor for converting file name `README.md` to `index.md` since -/// `README.md` is the de facto index file in a markdown-based documentation. +/// `README.md` is the de facto index file in markdown-based documentation. pub struct IndexPreprocessor; impl IndexPreprocessor { diff --git a/src/preprocess/links.rs b/src/preprocess/links.rs index 3403891a..90a057b0 100644 --- a/src/preprocess/links.rs +++ b/src/preprocess/links.rs @@ -69,12 +69,7 @@ where Ok(new_content) => { if depth < MAX_LINK_NESTED_DEPTH { if let Some(rel_path) = playpen.link.relative_path(path) { - replaced.push_str(&replace_all( - &new_content, - rel_path, - source, - depth + 1, - )); + replaced.push_str(&replace_all(&new_content, rel_path, source, depth + 1)); } else { replaced.push_str(&new_content); } @@ -118,18 +113,10 @@ impl<'a> LinkType<'a> { let base = base.as_ref(); match self { LinkType::Escaped => None, - LinkType::IncludeRange(p, _) => { - Some(return_relative_path(base, &p)) - } - LinkType::IncludeRangeFrom(p, _) => { - Some(return_relative_path(base, &p)) - } - LinkType::IncludeRangeTo(p, _) => { - Some(return_relative_path(base, &p)) - } - LinkType::IncludeRangeFull(p, _) => { - Some(return_relative_path(base, &p)) - } + LinkType::IncludeRange(p, _) => Some(return_relative_path(base, &p)), + LinkType::IncludeRangeFrom(p, _) => Some(return_relative_path(base, &p)), + LinkType::IncludeRangeTo(p, _) => Some(return_relative_path(base, &p)), + LinkType::IncludeRangeFull(p, _) => Some(return_relative_path(base, &p)), LinkType::Playpen(p, _) => Some(return_relative_path(base, &p)), } } @@ -155,27 +142,21 @@ fn parse_include_path(path: &str) -> LinkType<'static> { let end = end.and_then(|s| s.parse::().ok()); match start { Some(start) => match end { - Some(end) => LinkType::IncludeRange( - path, - Range { - start: start, - end: end, - }, - ), + Some(end) => LinkType::IncludeRange(path, Range { start, end }), None => if has_end { - LinkType::IncludeRangeFrom(path, RangeFrom { start: start }) + LinkType::IncludeRangeFrom(path, RangeFrom { start }) } else { LinkType::IncludeRange( path, Range { - start: start, + start, end: start + 1, }, ) }, }, None => match end { - Some(end) => LinkType::IncludeRangeTo(path, RangeTo { end: end }), + Some(end) => LinkType::IncludeRangeTo(path, RangeTo { end }), None => LinkType::IncludeRangeFull(path, RangeFull), }, } @@ -199,15 +180,11 @@ impl<'a> Link<'a> { match (typ.as_str(), file_arg) { ("include", Some(pth)) => Some(parse_include_path(pth)), - ("playpen", Some(pth)) => { - Some(LinkType::Playpen(pth.into(), props)) - } + ("playpen", Some(pth)) => Some(LinkType::Playpen(pth.into(), props)), _ => None, } } - (Some(mat), None, None) - if mat.as_str().starts_with(ESCAPE_CHAR) => - { + (Some(mat), None, None) if mat.as_str().starts_with(ESCAPE_CHAR) => { Some(LinkType::Escaped) } _ => None, @@ -258,7 +235,7 @@ impl<'a> Link<'a> { let target = base.join(pat); file_to_string(&target) - .map(|s| take_lines(&s, range.clone())) + .map(|s| take_lines(&s, *range)) .chain_err(|| { format!( "Could not read file for link {} ({})", @@ -271,22 +248,23 @@ impl<'a> Link<'a> { let target = base.join(pat); file_to_string(&target).chain_err(|| { - format!("Could not read file for link {} ({})", - self.link_text, - target.display()) + format!( + "Could not read file for link {} ({})", + self.link_text, + target.display() + ) }) } LinkType::Playpen(ref pat, ref attrs) => { let target = base.join(pat); - let contents = - file_to_string(&target).chain_err(|| { - format!( - "Could not read file for link {} ({})", - self.link_text, - target.display() - ) - })?; + let contents = file_to_string(&target).chain_err(|| { + format!( + "Could not read file for link {} ({})", + self.link_text, + target.display() + ) + })?; let ftype = if !attrs.is_empty() { "rust," } else { "rust" }; Ok(format!( "```{}{}\n{}\n```\n", @@ -531,10 +509,7 @@ mod tests { Link { start_index: 38, end_index: 68, - link: LinkType::Playpen( - PathBuf::from("file.rs"), - vec!["editable"] - ), + link: LinkType::Playpen(PathBuf::from("file.rs"), vec!["editable"]), link_text: "{{#playpen file.rs editable }}", }, Link { @@ -544,8 +519,7 @@ mod tests { PathBuf::from("my.rs"), vec!["editable", "no_run", "should_panic"], ), - link_text: - "{{#playpen my.rs editable no_run should_panic}}", + link_text: "{{#playpen my.rs editable no_run should_panic}}", }, ] ); diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 6ef12f3c..f12fd168 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -30,75 +30,67 @@ impl HtmlHandlebars { print_content: &mut String, ) -> Result<()> { // FIXME: This should be made DRY-er and rely less on mutable state - match *item { - BookItem::Chapter(ref ch) => { - let content = ch.content.clone(); - let content = utils::render_markdown(&content, ctx.html_config.curly_quotes); - print_content.push_str(&content); + if let BookItem::Chapter(ref ch) = *item { + let content = ch.content.clone(); + let content = utils::render_markdown(&content, ctx.html_config.curly_quotes); + print_content.push_str(&content); - // Update the context with data for this file - let path = ch - .path - .to_str() - .chain_err(|| "Could not convert path to str")?; - let filepath = Path::new(&ch.path).with_extension("html"); + // Update the context with data for this file + let path = ch + .path + .to_str() + .chain_err(|| "Could not convert path to str")?; + let filepath = Path::new(&ch.path).with_extension("html"); - // "print.html" is used for the print page. - if ch.path == Path::new("print.md") { - bail!(ErrorKind::ReservedFilenameError(ch.path.clone())); - }; + // "print.html" is used for the print page. + if ch.path == Path::new("print.md") { + bail!(ErrorKind::ReservedFilenameError(ch.path.clone())); + }; - // Non-lexical lifetimes needed :'( - let title: String; - { - let book_title = ctx - .data - .get("book_title") - .and_then(serde_json::Value::as_str) - .unwrap_or(""); - title = ch.name.clone() + " - " + book_title; - } - - ctx.data.insert("path".to_owned(), json!(path)); - ctx.data.insert("content".to_owned(), json!(content)); - ctx.data.insert("chapter_title".to_owned(), json!(ch.name)); - ctx.data.insert("title".to_owned(), json!(title)); - ctx.data.insert( - "path_to_root".to_owned(), - json!(utils::fs::path_to_root(&ch.path)), - ); - - // Render the handlebars template with the data - debug!("Render template"); - let rendered = ctx.handlebars.render("index", &ctx.data)?; - - let rendered = self.post_process(rendered, &ctx.html_config.playpen); - - // Write to file - debug!("Creating {}", filepath.display()); - utils::fs::write_file(&ctx.destination, &filepath, rendered.as_bytes())?; - - if ctx.is_index { - ctx.data.insert("path".to_owned(), json!("index.html")); - ctx.data.insert("path_to_root".to_owned(), json!("")); - let rendered_index = ctx.handlebars.render("index", &ctx.data)?; - let rendered_index = - self.post_process(rendered_index, &ctx.html_config.playpen); - debug!("Creating index.html from {}", path); - utils::fs::write_file( - &ctx.destination, - "index.html", - rendered_index.as_bytes(), - )?; - } + // Non-lexical lifetimes needed :'( + let title: String; + { + let book_title = ctx + .data + .get("book_title") + .and_then(serde_json::Value::as_str) + .unwrap_or(""); + title = ch.name.clone() + " - " + book_title; + } + + ctx.data.insert("path".to_owned(), json!(path)); + ctx.data.insert("content".to_owned(), json!(content)); + ctx.data.insert("chapter_title".to_owned(), json!(ch.name)); + ctx.data.insert("title".to_owned(), json!(title)); + ctx.data.insert( + "path_to_root".to_owned(), + json!(utils::fs::path_to_root(&ch.path)), + ); + + // Render the handlebars template with the data + debug!("Render template"); + let rendered = ctx.handlebars.render("index", &ctx.data)?; + + let rendered = self.post_process(rendered, &ctx.html_config.playpen); + + // Write to file + debug!("Creating {}", filepath.display()); + utils::fs::write_file(&ctx.destination, &filepath, rendered.as_bytes())?; + + if ctx.is_index { + ctx.data.insert("path".to_owned(), json!("index.html")); + ctx.data.insert("path_to_root".to_owned(), json!("")); + let rendered_index = ctx.handlebars.render("index", &ctx.data)?; + let rendered_index = self.post_process(rendered_index, &ctx.html_config.playpen); + debug!("Creating index.html from {}", path); + utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?; } - _ => {} } Ok(()) } - #[cfg_attr(feature = "cargo-clippy", allow(let_and_return))] + #[cfg_attr(feature = "cargo-clippy", allow(clippy::let_and_return))] fn post_process(&self, rendered: String, playpen_config: &Playpen) -> String { let rendered = build_header_links(&rendered); let rendered = fix_code_blocks(&rendered); @@ -328,7 +320,7 @@ impl Renderer for HtmlHandlebars { handlebars: &handlebars, destination: destination.to_path_buf(), data: data.clone(), - is_index: is_index, + is_index, html_config: html_config.clone(), }; self.render_item(item, ctx, &mut print_content)?; diff --git a/src/renderer/html_handlebars/helpers/navigation.rs b/src/renderer/html_handlebars/helpers/navigation.rs index dc84d0da..0e551004 100644 --- a/src/renderer/html_handlebars/helpers/navigation.rs +++ b/src/renderer/html_handlebars/helpers/navigation.rs @@ -18,13 +18,13 @@ impl Target { /// Returns target if found. fn find( &self, - base_path: &String, - current_path: &String, + base_path: &str, + current_path: &str, current_item: &StringMap, previous_item: &StringMap, ) -> Result, RenderError> { - match self { - &Target::Next => { + match *self { + Target::Next => { let previous_path = previous_item .get("path") .ok_or_else(|| RenderError::new("No path found for chapter in JSON data"))?; @@ -34,7 +34,7 @@ impl Target { } } - &Target::Previous => { + Target::Previous => { if current_path == base_path { return Ok(Some(previous_item.clone())); } diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs index fd055f38..c27977e1 100644 --- a/src/renderer/html_handlebars/search.rs +++ b/src/renderer/html_handlebars/search.rs @@ -54,7 +54,7 @@ fn add_doc( section_id: &Option, items: &[&str], ) { - let url = if let &Some(ref id) = section_id { + let url = if let Some(ref id) = *section_id { Cow::Owned(format!("{}#{}", anchor_base, id)) } else { Cow::Borrowed(anchor_base) @@ -74,8 +74,8 @@ fn render_item( doc_urls: &mut Vec, item: &BookItem, ) -> Result<()> { - let chapter = match item { - &BookItem::Chapter(ref ch) => ch, + let chapter = match *item { + BookItem::Chapter(ref ch) => ch, _ => return Ok(()), }; @@ -101,7 +101,7 @@ fn render_item( for event in p { match event { Event::Start(Tag::Header(i)) if i <= max_section_depth => { - if heading.len() > 0 { + if !heading.is_empty() { // Section finished, the next header is following now // Write the data to the index, and clear it for the next section add_doc( @@ -155,7 +155,7 @@ fn render_item( } } - if heading.len() > 0 { + if !heading.is_empty() { // Make sure the last section is added to the index add_doc( index, diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index bf5f59c5..ae26c6ac 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -76,8 +76,8 @@ impl RenderContext { Q: Into, { RenderContext { - book: book, - config: config, + book, + config, version: ::MDBOOK_VERSION.to_string(), root: root.into(), destination: destination.into(), diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 73015f5a..31abe98c 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -119,7 +119,7 @@ struct EventQuoteConverter { impl EventQuoteConverter { fn new(enabled: bool) -> Self { EventQuoteConverter { - enabled: enabled, + enabled, convert_text: true, } } @@ -324,14 +324,8 @@ more text with spaces id_from_content("## Method-call expressions"), "method-call-expressions" ); - assert_eq!( - id_from_content("## **Bold** title"), - "bold-title" - ); - assert_eq!( - id_from_content("## `Code` title"), - "code-title" - ); + assert_eq!(id_from_content("## **Bold** title"), "bold-title"); + assert_eq!(id_from_content("## `Code` title"), "code-title"); } #[test] @@ -344,10 +338,7 @@ more text with spaces id_from_content("## 中文標題 CJK title"), "中文標題-cjk-title" ); - assert_eq!( - id_from_content("## Über"), - "Über" - ); + assert_eq!(id_from_content("## Über"), "Über"); } #[test]