diff --git a/src/errors.rs b/src/errors.rs index 97972ffab..f741cd862 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,5 +1,5 @@ -use thiserror::Error; use std::path::PathBuf; +use thiserror::Error; #[derive(Error, Debug)] pub enum Error { @@ -42,6 +42,9 @@ pub enum Error { #[error(transparent)] Io(#[from] std::io::Error), + #[error(transparent)] + AssetOutsideSrcDir(#[from] std::path::StripPrefixError), + #[error(transparent)] Book(#[from] mdbook::errors::Error), #[error(transparent)] diff --git a/src/resources/asset.rs b/src/resources/asset.rs index 57e9c5879..7f981860d 100644 --- a/src/resources/asset.rs +++ b/src/resources/asset.rs @@ -82,14 +82,7 @@ impl Asset { return Err(Error::AssetFile(absolute_location)); } // Use filename as embedded file path with content from absolute_location. - let binding = utils::normalize_path(Path::new(link)); - debug!("Extracting file name from = {:?}, binding = '{binding:?}'", &full_filename.display()); - let filename = if cfg!(target_os = "windows") { - binding.as_os_str().to_os_string() - .into_string().expect("Error getting filename for Local Asset").replace('\\', "/") - } else { - String::from(binding.as_path().to_str().unwrap()) - }; + let filename = full_filename.strip_prefix(src_dir)?; let asset = Asset::new( filename, @@ -112,7 +105,13 @@ impl Asset { pub(crate) fn compute_asset_path_by_src_and_link(link: &str, chapter_dir: &PathBuf) -> PathBuf { let mut reassigned_asset_root: PathBuf = PathBuf::from(chapter_dir); let link_string = String::from(link); - // if chapter is a MD file, remove if from path + // mdbook built-in link preprocessor have `README.md` renamed and `index.md` is not exist + // strip the converted filename in the path + if chapter_dir.ends_with("index.md") && !chapter_dir.exists() { + debug!("It seems a `README.md` chapter, adjust the chapter root."); + reassigned_asset_root.pop(); + } + // if chapter is a MD file or not exist, remove if from path if chapter_dir.is_file() { reassigned_asset_root.pop(); } diff --git a/src/resources/resource.rs b/src/resources/resource.rs index 9735fcaaf..743f97fc4 100644 --- a/src/resources/resource.rs +++ b/src/resources/resource.rs @@ -48,9 +48,15 @@ pub(crate) fn find(ctx: &RenderContext) -> Result, Error> continue; } for link in find_assets_in_markdown(&ch.content)? { - let asset = match Url::parse(&link) { - Ok(url) => Asset::from_url(url, &ctx.destination), - Err(_) => Asset::from_local(&link, &src_dir, ch.path.as_ref().unwrap()), + let asset = if let Ok(url) = Url::parse(&link) { + Asset::from_url(url, &ctx.destination) + } else { + let result = Asset::from_local(&link, &src_dir, ch.path.as_ref().unwrap()); + if let Err(Error::AssetOutsideSrcDir(_)) = result { + warn!("Asset '{link}' is outside source dir '{src_dir:?}' and ignored"); + continue; + }; + result }?; // that is CORRECT generation way diff --git a/tests/dummy/src/02_advanced/Epub_logo.svg b/tests/dummy/src/02_advanced/Epub_logo.svg new file mode 100644 index 000000000..d53b002d8 --- /dev/null +++ b/tests/dummy/src/02_advanced/Epub_logo.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/tests/dummy/src/02_advanced/README.md b/tests/dummy/src/02_advanced/README.md new file mode 100644 index 000000000..5d5a566b8 --- /dev/null +++ b/tests/dummy/src/02_advanced/README.md @@ -0,0 +1,5 @@ +# README.md tests + +## image link + +![Awesome image in the same folder](Epub_logo.svg "Awesome") diff --git a/tests/dummy/src/SUMMARY.md b/tests/dummy/src/SUMMARY.md index dd840d0f7..2d62376e5 100644 --- a/tests/dummy/src/SUMMARY.md +++ b/tests/dummy/src/SUMMARY.md @@ -2,3 +2,7 @@ - [Chapter 1](./chapter_1.md) - [Getting started](01_getting_started/02_article.md) + +# Advanced + +- [README.md tests](./02_advanced/README.md) diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index dd1283c48..5ebad41e2 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -125,17 +125,38 @@ fn look_for_chapter_1_heading() { assert!(content.contains("

Chapter 1

")); } +#[test] +#[serial] +fn look_for_chapter_2_image_link_in_readme() { + init_logging(); + let mut doc = generate_epub().unwrap(); + + let path = if cfg!(target_os = "linux") { + Path::new("OEBPS").join("02_advanced").join("README.html") // linux + } else { + Path::new("OEBPS/02_advanced/README.html").to_path_buf() // windows with 'forward slash' / + }; + let content = doc.0.get_resource_str_by_path(path).unwrap(); + + assert!(content.contains("