Skip to content

Commit

Permalink
Implement translation fallback of files included with preprocessing
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruin0x11 committed Sep 15, 2021
1 parent 5fed5e8 commit d6c27ab
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 20 deletions.
73 changes: 60 additions & 13 deletions src/preprocess/links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -76,9 +80,10 @@ impl Preprocessor for LinkPreprocessor {
fn replace_all<P1, P2>(
s: &str,
path: P1,
fallback: Option<P1>,
source: P2,
depth: usize,
chapter_title: &mut String,
chapter_title: &mut String
) -> String
where
P1: AsRef<Path>,
Expand All @@ -88,20 +93,22 @@ 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();

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,
Expand Down Expand Up @@ -323,14 +330,28 @@ impl<'a> Link<'a> {
fn render_with_path<P: AsRef<Path>>(
&self,
base: P,
fallback: Option<P2>,
chapter_title: &mut String,
) -> Result<String> {
let base = base.as_ref();
match self.link_type {
// 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 {
Expand All @@ -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 {
Expand All @@ -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!(
Expand Down Expand Up @@ -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]
Expand All @@ -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");
}

Expand Down
15 changes: 8 additions & 7 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand All @@ -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")),
Expand All @@ -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",
);
Expand Down
6 changes: 6 additions & 0 deletions tests/localized_book/src/en/example.rs
Original file line number Diff line number Diff line change
@@ -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");
}
5 changes: 5 additions & 0 deletions tests/localized_book/src/ja/inline-link-fallbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

0 comments on commit d6c27ab

Please sign in to comment.