diff --git a/src/preprocess/links.rs b/src/preprocess/links.rs index 9dfdc651..94c91528 100644 --- a/src/preprocess/links.rs +++ b/src/preprocess/links.rs @@ -48,17 +48,21 @@ impl Preprocessor for LinkPreprocessor { .unwrap(); let src_dir = ctx.root.join(src_dir); + let fallback_src_dir = ctx + .config + .get_localized_src_path(ctx.config.default_language().as_ref()) + .unwrap(); + let fallback_src_dir = ctx.root.join(fallback_src_dir); + book.for_each_mut(|section: &mut BookItem| { if let BookItem::Chapter(ref mut ch) = *section { if let Some(ref chapter_path) = ch.path { - let base = chapter_path - .parent() - .map(|dir| src_dir.join(dir)) - .expect("All book items have a parent"); + let parent = chapter_path.parent().expect("All book items have a parent"); + let base = src_dir.join(parent); + let fallback = fallback_src_dir.join(parent); let mut chapter_title = ch.name.clone(); - let content = - replace_all(&ch.content, base, chapter_path, 0, &mut chapter_title); + let content = replace_all(&ch.content, base, Some(fallback), chapter_path, 0, &mut chapter_title); ch.content = content; if chapter_title != ch.name { ctx.chapter_titles @@ -76,9 +80,10 @@ impl Preprocessor for LinkPreprocessor { fn replace_all( s: &str, path: P1, + fallback: Option, source: P2, depth: usize, - chapter_title: &mut String, + chapter_title: &mut String ) -> String where P1: AsRef, @@ -88,6 +93,7 @@ where // the indices after that will not correspond, // we therefore have to store the difference to correct this let path = path.as_ref(); + let fallback = fallback.as_ref(); let source = source.as_ref(); let mut previous_end_index = 0; let mut replaced = String::new(); @@ -95,13 +101,14 @@ where for link in find_links(s) { replaced.push_str(&s[previous_end_index..link.start_index]); - match link.render_with_path(&path, chapter_title) { + match link.render_with_path(&path, fallback, chapter_title) { Ok(new_content) => { if depth < MAX_LINK_NESTED_DEPTH { if let Some(rel_path) = link.link_type.relative_path(path) { replaced.push_str(&replace_all( &new_content, rel_path, + None, source, depth + 1, chapter_title, @@ -323,6 +330,7 @@ impl<'a> Link<'a> { fn render_with_path>( &self, base: P, + fallback: Option, chapter_title: &mut String, ) -> Result { let base = base.as_ref(); @@ -330,7 +338,20 @@ impl<'a> Link<'a> { // omit the escape char LinkType::Escaped => Ok((&self.link_text[1..]).to_owned()), LinkType::Include(ref pat, ref range_or_anchor) => { - let target = base.join(pat); + let mut target = base.join(pat); + + if !target.exists() { + if let Some(fallback) = fallback { + let fallback_target = fallback.as_ref().join(pat); + if fallback_target.exists() { + debug!( + "Included file fallback: {:?} => {:?}", + target, fallback_target + ); + target = fallback_target; + } + } + } fs::read_to_string(&target) .map(|s| match range_or_anchor { @@ -346,7 +367,20 @@ impl<'a> Link<'a> { }) } LinkType::RustdocInclude(ref pat, ref range_or_anchor) => { - let target = base.join(pat); + let mut target = base.join(pat); + + if !target.exists() { + if let Some(fallback) = fallback { + let fallback_target = fallback.as_ref().join(pat); + if fallback_target.exists() { + debug!( + "Included file fallback: {:?} => {:?}", + target, fallback_target + ); + target = fallback_target; + } + } + } fs::read_to_string(&target) .map(|s| match range_or_anchor { @@ -366,7 +400,20 @@ impl<'a> Link<'a> { }) } LinkType::Playground(ref pat, ref attrs) => { - let target = base.join(pat); + let mut target = base.join(pat); + + if !target.exists() { + if let Some(fallback) = fallback { + let fallback_target = fallback.as_ref().join(pat); + if fallback_target.exists() { + debug!( + "Included file fallback: {:?} => {:?}", + target, fallback_target + ); + target = fallback_target; + } + } + } let mut contents = fs::read_to_string(&target).with_context(|| { format!( @@ -444,7 +491,7 @@ mod tests { {{#include file.rs}} << an escaped link! ```"; let mut chapter_title = "test_replace_all_escaped".to_owned(); - assert_eq!(replace_all(start, "", "", 0, &mut chapter_title), end); + assert_eq!(replace_all(start, "", None, "", 0, &mut chapter_title), end); } #[test] @@ -456,7 +503,7 @@ mod tests { # My Chapter "; let mut chapter_title = "test_set_chapter_title".to_owned(); - assert_eq!(replace_all(start, "", "", 0, &mut chapter_title), end); + assert_eq!(replace_all(start, "", None, "", 0, &mut chapter_title), end); assert_eq!(chapter_title, "My Title"); } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 7b9a7596..e71dabd2 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -518,10 +518,11 @@ more text with spaces let _ = env_logger::builder().is_test(true).try_init(); let test = |dest, path, exists, expected| { let src_dir = tempfile::tempdir().unwrap(); + let path = PathBuf::from(path); let ctx = if exists { Some(RenderMarkdownContext { - path: PathBuf::from(path), + path: path, src_dir: PathBuf::new(), language: None, fallback_language: None, @@ -534,7 +535,7 @@ more text with spaces let fallback_dir = src_dir.path().join("en"); fs::create_dir_all(&fallback_dir).unwrap(); - let chapter_path = fallback_dir.join(path).join(dest); + let chapter_path = fallback_dir.join(path.parent().unwrap()).join(dest); fs::create_dir_all(chapter_path.parent().unwrap()).unwrap(); debug!("Create: {}", chapter_path.display()); File::create(&chapter_path) @@ -543,7 +544,7 @@ more text with spaces .unwrap(); Some(RenderMarkdownContext { - path: PathBuf::from(path), + path: path, src_dir: PathBuf::from(src_dir.path()), language: Some(String::from("ja")), fallback_language: Some(String::from("en")), @@ -557,17 +558,17 @@ more text with spaces ); }; - test("../b/summary.md", "a.md", true, "../b/summary.html"); + test("../b/summary.md", "a/index.md", true, "../b/summary.html"); test( "../b/summary.md", - "a.md", + "a/index.md", false, "../../en/../b/summary.html", ); - test("../c/summary.md", "a/b.md", true, "../c/summary.html"); + test("../c/summary.md", "a/b/index.md", true, "../c/summary.html"); test( "../c/summary.md", - "a/b.md", + "a/b/index.md", false, "../../../en/../c/summary.html", ); diff --git a/tests/localized_book/src/en/example.rs b/tests/localized_book/src/en/example.rs new file mode 100644 index 00000000..6b49705c --- /dev/null +++ b/tests/localized_book/src/en/example.rs @@ -0,0 +1,6 @@ +fn main() { + println!("Hello World!"); +# +# // You can even hide lines! :D +# println!("I am hidden! Expand the code snippet to see me"); +} diff --git a/tests/localized_book/src/ja/inline-link-fallbacks.md b/tests/localized_book/src/ja/inline-link-fallbacks.md index 2da1d166..a295353c 100644 --- a/tests/localized_book/src/ja/inline-link-fallbacks.md +++ b/tests/localized_book/src/ja/inline-link-fallbacks.md @@ -12,4 +12,9 @@ Here is an [inline link](missing-summary-chapter.md) to a page missing from this Also, here is an [inline link](blah.md) to a page missing from both translations. It should point to this language's 404 page. +Here is a file included from the default language. +```rust +{{ #include example.rs }} +``` + The substitution won't work if you specify the `-l`/`--language` option, since it only builds a single translation in that case.