Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 32 additions & 9 deletions crates/mdbook-core/src/utils/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ pub fn copy_files_except_ext(
avoid_dir
);

copy_files_when(from, to, recursive, &|path| {
if let Some(avoid) = avoid_dir {
if path == avoid {
return false;
}
}

if let Some(ext) = path.extension() {
if ext_blacklist.contains(&ext.to_str().unwrap()) {
return false;
}
}

true
})
}

/// Copies all files of a directory to another one
/// when the copy logic returns true. It should be
/// noted that the predicate is required by reference
/// should it be called recursively.
pub fn copy_files_when<T>(from: &Path, to: &Path, recursive: bool, predicate: &T) -> Result<()>
where
T: Fn(&PathBuf) -> bool,
{
// Check that from and to are different
if from == to {
return Ok(());
Expand All @@ -125,24 +150,22 @@ pub fn copy_files_except_ext(
continue;
}

if let Some(avoid) = avoid_dir {
if entry == *avoid {
continue;
}
if !predicate(&entry) {
debug!("Skipping copy {entry:?}");
continue;
}

// check if output dir already exists
if !target_file_path.exists() {
fs::create_dir(&target_file_path)?;
}

copy_files_except_ext(&entry, &target_file_path, true, avoid_dir, ext_blacklist)?;
copy_files_when(&entry, &target_file_path, true, predicate)?;
} else if metadata.is_file() {
// Check if it is in the blacklist
if let Some(ext) = entry.extension() {
if ext_blacklist.contains(&ext.to_str().unwrap()) {
continue;
}
if !predicate(&entry) {
debug!("Skipping copy {entry:?}");
continue;
}
debug!("Copying {entry:?} to {target_file_path:?}");
copy(&entry, &target_file_path)?;
Expand Down
2 changes: 2 additions & 0 deletions crates/mdbook-html/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ elasticlunr-rs = { workspace = true, optional = true }
font-awesome-as-a-crate.workspace = true
handlebars.workspace = true
hex.workspace = true
ignore.workspace = true
pathdiff.workspace = true
html5ever.workspace = true
indexmap.workspace = true
mdbook-core.workspace = true
Expand Down
51 changes: 50 additions & 1 deletion crates/mdbook-html/src/html_handlebars/hbs_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ use crate::theme::Theme;
use crate::utils::ToUrlPath;
use anyhow::{Context, Result, bail};
use handlebars::Handlebars;
use ignore::gitignore::Gitignore;
use mdbook_core::book::{Book, BookItem, Chapter};
use mdbook_core::config::{BookConfig, Config, HtmlConfig};
use mdbook_core::utils::fs;
use mdbook_renderer::{RenderContext, Renderer};
use pathdiff::diff_paths;
use serde_json::json;
use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -443,8 +445,55 @@ impl Renderer for HtmlHandlebars {
self.emit_redirects(&ctx.destination, &handlebars, &html_config.redirect)
.context("Unable to emit redirects")?;

let ignore = src_dir
.ancestors()
.map(|p| p.join(".gitignore"))
.find(|p| p.exists())
.and_then(|gitignore_path| {
let (ignore, err) = Gitignore::new(&gitignore_path);
if let Some(err) = err {
warn!(
"error reading gitignore `{}`: {err}",
gitignore_path.display()
);
}

match ignore.path().canonicalize() {
Err(error) => {
warn!("unable to canonicalize path for ignore: {error:?}");
None
}
Ok(path) => Some((path, ignore)),
}
});

// Copy all remaining files, avoid a recursive copy from/to the book build dir
fs::copy_files_except_ext(&src_dir, destination, true, Some(&build_dir), &["md"])?;
// and also honor the .gitignore file found in the project if any
fs::copy_files_when(&src_dir, destination, true, &|path| {
if *path == build_dir {
return false;
}

if let Some(ext) = path.extension() {
if ext.to_str().unwrap() == "md" {
return false;
}
}

if let Some((ignore_path, ignore)) = &ignore {
let path = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
let relative_path = diff_paths(&path, &ignore_path)
.expect("One of the paths should be an absolute");
if ignore
.matched_path_or_any_parents(&relative_path, relative_path.is_dir())
.is_ignore()
{
return false;
}
}

true
})?;

info!("HTML book written to `{}`", destination.display());

Expand Down