diff --git a/Cargo.lock b/Cargo.lock index 66ce6ec..2e2f32b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,14 +209,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", - "winapi", + "wasm-bindgen", + "windows-targets 0.48.1", ] [[package]] @@ -263,6 +265,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "concat-string" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7439becb5fafc780b6f4de382b1a7a3e70234afe783854a4702ee8adbb838609" + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -898,7 +906,9 @@ dependencies = [ name = "mdbook-last-changed" version = "0.1.4" dependencies = [ + "chrono", "clap", + "concat-string", "env_logger", "log", "mdbook", diff --git a/Cargo.toml b/Cargo.toml index 9500d5f..309ae19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,5 @@ clap = { version = "4.0.29", features = ["cargo"] } serde_json = "1.0" toml = "0.5.11" xshell = "0.2.2" +chrono = "0.4.31" +concat-string = "1.0.1" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6cd19c4..2d73995 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,9 @@ +use std::collections::HashMap; use std::path::{Path, PathBuf}; +use std::str::FromStr; +use chrono::NaiveDate; +use concat_string::concat_string; use mdbook::book::{Book, BookItem, Chapter}; use mdbook::errors::Result; use mdbook::preprocess::{Preprocessor, PreprocessorContext}; @@ -7,6 +11,12 @@ use xshell::{cmd, Shell}; pub struct LastChanged; +#[derive(Debug, Eq, PartialEq, Hash)] +struct LiteLink { + name: String, + path: Option, +} + impl Preprocessor for LastChanged { fn name(&self) -> &str { "last-changed" @@ -43,6 +53,7 @@ impl Preprocessor for LastChanged { None => None, }; + let mut map: HashMap = HashMap::new(); let mut res = None; book.for_each_mut(|item: &mut BookItem| { if let Some(Err(_)) = res { @@ -52,13 +63,53 @@ impl Preprocessor for LastChanged { if let BookItem::Chapter(ref mut chapter) = *item { res = Some( - last_changed(&git_root, &src_root, repository_string, chapter).map(|md| { - chapter.content = md; - }), + last_changed(&git_root, &src_root, repository_string, chapter, &mut map).map( + |md| { + chapter.content = md; + }, + ), ); } }); + let mut vec: Vec<(LiteLink, NaiveDate)> = map + .into_iter() + .map(|e| (e.0, NaiveDate::from_str(&e.1).unwrap())) + .collect(); + // Sorting alphabetically and then by date, this means same date entries will be sorted alphabetically, otherwise the end result will be randomized when truncating + vec.sort_by(|a, b| a.0.name.cmp(&b.0.name)); + vec.sort_by(|a, b| b.1.cmp(&a.1)); + vec.truncate(5); + + let text: String = vec + .into_iter() + .map(|f| { + format!( + "
  • {}
  • ", + f.0.path.unwrap().display(), + f.0.name + ) + }) + .collect(); + let text = concat_string!("## Recently Updated:\n", ""); + + book.for_each_mut(|item: &mut BookItem| { + if let Some(Err(_)) = res { + log::trace!("Error when changing the book. Last result: {res:?}"); + return; + } + + if let BookItem::Chapter(ref mut chapter) = *item { + if let Some(ch) = &chapter.number { + if ch.0[0] == 1 { + // let content = &chapter.content; + // chapter.content = format!("{}\n{}", text, content); + chapter.content = chapter.content.replace("⁂⁂⁂", &text); + } + } + } + }); + res.unwrap_or(Ok(())).map(|_| book) } } @@ -68,6 +119,7 @@ fn last_changed( src_root: &Path, base_url: Option<&str>, chapter: &mut Chapter, + map: &mut HashMap, ) -> Result { let content = &chapter.content; @@ -95,18 +147,25 @@ fn last_changed( let modification = get_last_modification(git_root, &path); let text = match modification { - Ok((date, commit)) => match base_url { - Some(url) => { - let url = format!("{}/commit/{}", url, commit); - format!( - "Last change: {}, commit: {}", - date, url, commit - ) + Ok((date, commit)) => { + let lite_link = LiteLink { + name: chapter.name.clone(), + path: chapter.path.clone(), + }; + map.insert(lite_link, date.clone()); + match base_url { + Some(url) => { + let url = format!("{}/commit/{}", url, commit); + format!( + "Last change: {}, commit: {}", + date, url, commit + ) + } + None => { + format!("Last change: {}", date) + } } - None => { - format!("Last change: {}", date) - } - }, + } Err(e) => { log::trace!("No modification found for {path:?}. Error: {e:?}"); return Ok(content.into());