Compare commits
No commits in common. "e5a0ccdb53a5aad67152df3f8c16d8db571bdaf3" and "9660612724514aa6e8f78b719c36a1c943033b1f" have entirely different histories.
e5a0ccdb53
...
9660612724
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mdbook-last-changed"
|
name = "mdbook-last-changed"
|
||||||
version = "0.1.4"
|
version = "0.1.2"
|
||||||
description = "mdbook preprocessor to add the last modification date per page"
|
description = "mdbook preprocessor to add the last modification date per page"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
homepage = "https://github.com/badboy/mdbook-last-changed"
|
homepage = "https://github.com/badboy/mdbook-last-changed"
|
||||||
|
@ -8,12 +8,10 @@ repository = "https://github.com/badboy/mdbook-last-changed"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mdbook = "0.4.33"
|
mdbook = "0.4.21"
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
clap = { version = "4.0.29", features = ["cargo"] }
|
clap = { version = "4.0.29", features = ["cargo"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
toml = "0.5.11"
|
toml = "0.5.6"
|
||||||
xshell = "0.2.2"
|
xshell = "0.2.2"
|
||||||
chrono = "0.4.31"
|
|
||||||
concat-string = "1.0.1"
|
|
15
README.md
15
README.md
|
@ -10,6 +10,7 @@ It uses the configured `git-repository-url` as the base.
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* The `git` command line tool.
|
* The `git` command line tool.
|
||||||
|
* A configured git repository url in your `book.toml` configuration. See [Configuration](#configuration).
|
||||||
* Access to the git repository checkout while building your book.
|
* Access to the git repository checkout while building your book.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
@ -35,22 +36,10 @@ renderer = ["html"]
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[output.html]
|
[output.html]
|
||||||
# Optional: Your repository URL used in the link.
|
# Required: Your repository URL used in the link.
|
||||||
git-repository-url = "https://github.com/$user/$project"
|
git-repository-url = "https://github.com/$user/$project"
|
||||||
```
|
```
|
||||||
|
|
||||||
If `git-repository-url` is not configured the footer will not contain the commit and a link to it and instead only show the last changed date.
|
|
||||||
|
|
||||||
Without `git-repository-url` configured:
|
|
||||||
```HTML
|
|
||||||
<footer id="last-change">Last change: 2023-07-09</footer>
|
|
||||||
```
|
|
||||||
|
|
||||||
With `git-repository-url` configured:
|
|
||||||
```HTML
|
|
||||||
<footer id="last-change">Last change: 2023-07-09, commit: <a href="https://github.com/$user/$project/commit/$commit">0000000</a></footer>
|
|
||||||
```
|
|
||||||
|
|
||||||
To style the footer add a custom CSS file for your HTML output:
|
To style the footer add a custom CSS file for your HTML output:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
|
119
src/lib.rs
119
src/lib.rs
|
@ -1,9 +1,5 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::{Path, PathBuf};
|
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::book::{Book, BookItem, Chapter};
|
||||||
use mdbook::errors::Result;
|
use mdbook::errors::Result;
|
||||||
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
|
use mdbook::preprocess::{Preprocessor, PreprocessorContext};
|
||||||
|
@ -11,12 +7,6 @@ use xshell::{cmd, Shell};
|
||||||
|
|
||||||
pub struct LastChanged;
|
pub struct LastChanged;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
|
||||||
struct LiteLink {
|
|
||||||
name: String,
|
|
||||||
path: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Preprocessor for LastChanged {
|
impl Preprocessor for LastChanged {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"last-changed"
|
"last-changed"
|
||||||
|
@ -31,29 +21,27 @@ impl Preprocessor for LastChanged {
|
||||||
log::debug!("Src root: {}", src_root.display());
|
log::debug!("Src root: {}", src_root.display());
|
||||||
log::debug!("Git root: {}", git_root.display());
|
log::debug!("Git root: {}", git_root.display());
|
||||||
|
|
||||||
let repository_string: Option<&str> = match ctx.config.get("output.html.git-repository-url")
|
let repository_url = match ctx.config.get("output.html.git-repository-url") {
|
||||||
{
|
None => {
|
||||||
Some(val) => {
|
log::error!("mdbook-last-changed was called, but no `output.html.git-repository-url` configured. Book is left unchanged.");
|
||||||
let url = match val {
|
return Ok(book);
|
||||||
toml::Value::String(s) => s,
|
|
||||||
_ => {
|
|
||||||
log::trace!("git-repository-url is not a string: {val:?}");
|
|
||||||
return Ok(book);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
log::debug!("Repository URL: {}", url);
|
|
||||||
|
|
||||||
if !url.contains("github.com") {
|
|
||||||
log::trace!("git-repository-url is not a GitHub URL: {url:?}");
|
|
||||||
return Ok(book);
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(&url)
|
|
||||||
}
|
}
|
||||||
None => None,
|
Some(url) => url,
|
||||||
};
|
};
|
||||||
|
let repository_url = match repository_url {
|
||||||
|
toml::Value::String(s) => s,
|
||||||
|
_ => {
|
||||||
|
log::trace!("git-repository-url is not a string: {repository_url:?}");
|
||||||
|
return Ok(book);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
log::debug!("Repository URL: {}", repository_url);
|
||||||
|
|
||||||
|
if !repository_url.contains("github.com") {
|
||||||
|
log::trace!("git-repository-url is not a GitHub URL: {repository_url:?}");
|
||||||
|
return Ok(book);
|
||||||
|
}
|
||||||
|
|
||||||
let mut map: HashMap<LiteLink, String> = HashMap::new();
|
|
||||||
let mut res = None;
|
let mut res = None;
|
||||||
book.for_each_mut(|item: &mut BookItem| {
|
book.for_each_mut(|item: &mut BookItem| {
|
||||||
if let Some(Err(_)) = res {
|
if let Some(Err(_)) = res {
|
||||||
|
@ -63,53 +51,13 @@ impl Preprocessor for LastChanged {
|
||||||
|
|
||||||
if let BookItem::Chapter(ref mut chapter) = *item {
|
if let BookItem::Chapter(ref mut chapter) = *item {
|
||||||
res = Some(
|
res = Some(
|
||||||
last_changed(&git_root, &src_root, repository_string, chapter, &mut map).map(
|
last_changed(&git_root, &src_root, repository_url, chapter).map(|md| {
|
||||||
|md| {
|
chapter.content = 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!(
|
|
||||||
"<li><a href=\"{}\">{}</a></li>",
|
|
||||||
f.0.path.unwrap().display(),
|
|
||||||
f.0.name
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let text = concat_string!("## Recently Updated:\n", "<ul>", text, "</ul>");
|
|
||||||
|
|
||||||
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)
|
res.unwrap_or(Ok(())).map(|_| book)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,9 +65,8 @@ impl Preprocessor for LastChanged {
|
||||||
fn last_changed(
|
fn last_changed(
|
||||||
git_root: &Path,
|
git_root: &Path,
|
||||||
src_root: &Path,
|
src_root: &Path,
|
||||||
base_url: Option<&str>,
|
base_url: &str,
|
||||||
chapter: &mut Chapter,
|
chapter: &mut Chapter,
|
||||||
map: &mut HashMap<LiteLink, String>,
|
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let content = &chapter.content;
|
let content = &chapter.content;
|
||||||
|
|
||||||
|
@ -148,23 +95,11 @@ fn last_changed(
|
||||||
let modification = get_last_modification(git_root, &path);
|
let modification = get_last_modification(git_root, &path);
|
||||||
let text = match modification {
|
let text = match modification {
|
||||||
Ok((date, commit)) => {
|
Ok((date, commit)) => {
|
||||||
let lite_link = LiteLink {
|
let url = format!("{}/commit/{}", base_url, commit);
|
||||||
name: chapter.name.clone(),
|
format!(
|
||||||
path: chapter.path.clone(),
|
"Last change: {}, commit: <a href=\"{}\">{}</a>",
|
||||||
};
|
date, url, commit
|
||||||
map.insert(lite_link, date.clone());
|
)
|
||||||
match base_url {
|
|
||||||
Some(url) => {
|
|
||||||
let url = format!("{}/commit/{}", url, commit);
|
|
||||||
format!(
|
|
||||||
"Last change: {}, commit: <a href=\"{}\">{}</a>",
|
|
||||||
date, url, commit
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
format!("Last change: {}", date)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::trace!("No modification found for {path:?}. Error: {e:?}");
|
log::trace!("No modification found for {path:?}. Error: {e:?}");
|
||||||
|
|
Loading…
Reference in New Issue