Skip to content

Commit 09a8b66

Browse files
committed
Improve robustness of link rewriting
1 parent 8d1c086 commit 09a8b66

File tree

6 files changed

+266
-196
lines changed

6 files changed

+266
-196
lines changed

src/config.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -877,8 +877,6 @@ pub struct Language {
877877
pub description: Option<String>,
878878
}
879879

880-
impl LanguageConfig {}
881-
882880
/// Allows you to "update" any arbitrary field in a struct by round-tripping via
883881
/// a `toml::Value`.
884882
///

src/preprocess/cmd.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ mod tests {
193193
let md = guide();
194194
let ctx = PreprocessorContext::new(
195195
md.root.clone(),
196+
None,
196197
BuildOpts::default(),
197198
md.config.clone(),
198199
"some-renderer".to_string(),

src/renderer/html_handlebars/hbs_renderer.rs

Lines changed: 57 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::errors::*;
44
use crate::renderer::html_handlebars::helpers;
55
use crate::renderer::{RenderContext, Renderer};
66
use crate::theme::{self, playground_editor, Theme};
7-
use crate::utils;
7+
use crate::utils::{self, RenderMarkdownContext};
88

99
use std::borrow::Cow;
1010
use std::collections::BTreeMap;
@@ -35,14 +35,12 @@ impl HtmlHandlebars {
3535
match ctx.book {
3636
LoadedBook::Localized(ref books) => {
3737
for (lang_ident, book) in books.0.iter() {
38-
let localized_src_dir = src_dir.join(lang_ident);
3938
let localized_destination = ctx.destination.join(lang_ident);
4039
let localized_build_dir = ctx.config.build.build_dir.join(lang_ident);
4140
self.render_book(
4241
ctx,
4342
&book,
44-
&localized_src_dir,
45-
&localized_src_dir,
43+
src_dir,
4644
&localized_destination,
4745
&localized_build_dir,
4846
&Some(lang_ident.to_string()),
@@ -53,27 +51,10 @@ impl HtmlHandlebars {
5351
}
5452
}
5553
LoadedBook::Single(ref book) => {
56-
// `src_dir` points to the root source directory. If this book
57-
// is actually multilingual and we specified a single language
58-
// to build on the command line, then `src_dir` will not be
59-
// pointing at the subdirectory with the specified translation's
60-
// index/summary files. We have to append the language
61-
// identifier to prevent the files from the other translations
62-
// from being copied in the final step.
63-
let extra_file_dir = match &ctx.build_opts.language_ident {
64-
Some(lang_ident) => {
65-
let mut path = src_dir.clone();
66-
path.push(lang_ident);
67-
path
68-
}
69-
None => src_dir.clone(),
70-
};
71-
7254
self.render_book(
7355
ctx,
7456
&book,
7557
src_dir,
76-
&extra_file_dir,
7758
&ctx.destination,
7859
&ctx.config.build.build_dir,
7960
&ctx.build_opts.language_ident,
@@ -92,10 +73,9 @@ impl HtmlHandlebars {
9273
ctx: &RenderContext,
9374
book: &Book,
9475
src_dir: &PathBuf,
95-
extra_file_dir: &PathBuf,
9676
destination: &PathBuf,
9777
build_dir: &PathBuf,
98-
language_ident: &Option<String>,
78+
language: &Option<String>,
9979
html_config: &HtmlConfig,
10080
handlebars: &mut Handlebars<'a>,
10181
theme: &Theme,
@@ -106,7 +86,7 @@ impl HtmlHandlebars {
10686
&book,
10787
&ctx.book,
10888
&ctx.config,
109-
language_ident,
89+
language,
11090
&html_config,
11191
&theme,
11292
)?;
@@ -127,7 +107,14 @@ impl HtmlHandlebars {
127107
html_config: html_config.clone(),
128108
edition: ctx.config.rust.edition,
129109
};
130-
self.render_item(item, item_ctx, src_dir, &ctx.config, &mut print_content)?;
110+
self.render_item(
111+
item,
112+
item_ctx,
113+
&src_dir,
114+
language,
115+
&ctx.config,
116+
&mut print_content,
117+
)?;
131118
is_index = false;
132119
}
133120

@@ -136,9 +123,9 @@ impl HtmlHandlebars {
136123
self.render_404(
137124
ctx,
138125
&html_config,
139-
src_dir,
126+
&src_dir,
140127
destination,
141-
language_ident,
128+
language,
142129
handlebars,
143130
&mut data,
144131
)?;
@@ -178,6 +165,28 @@ impl HtmlHandlebars {
178165
self.emit_redirects(&ctx.destination, handlebars, &html_config.redirect)
179166
.context("Unable to emit redirects")?;
180167

168+
// `src_dir` points to the root source directory. If this book
169+
// is actually multilingual and we specified a single language
170+
// to build on the command line, then `src_dir` will not be
171+
// pointing at the subdirectory with the specified translation's
172+
// index/summary files. We have to append the language
173+
// identifier to prevent the files from the other translations
174+
// from being copied in the final step.
175+
let extra_file_dir = match language {
176+
Some(lang_ident) => {
177+
// my_book/src/ja/
178+
let mut path = src_dir.clone();
179+
path.push(lang_ident);
180+
path
181+
}
182+
// my_book/src/
183+
None => src_dir.clone(),
184+
};
185+
debug!(
186+
"extra file dir {:?} {:?} {:?}",
187+
extra_file_dir, language, ctx.config
188+
);
189+
181190
// Copy all remaining files, avoid a recursive copy from/to the book build dir
182191
utils::fs::copy_files_except_ext(
183192
&extra_file_dir,
@@ -195,6 +204,7 @@ impl HtmlHandlebars {
195204
item: &BookItem,
196205
mut ctx: RenderItemContext<'_>,
197206
src_dir: &PathBuf,
207+
language: &Option<String>,
198208
cfg: &Config,
199209
print_content: &mut String,
200210
) -> Result<()> {
@@ -219,28 +229,32 @@ impl HtmlHandlebars {
219229
.insert("git_repository_edit_url".to_owned(), json!(edit_url));
220230
}
221231

222-
let fallback_path = cfg.default_language().map(|lang_ident| {
223-
let mut fallback = PathBuf::from(utils::fs::path_to_root(&path));
224-
fallback.push("../");
225-
fallback.push(lang_ident.clone());
226-
fallback
227-
});
232+
let mut md_ctx = match language {
233+
Some(lang_ident) => RenderMarkdownContext {
234+
path: path.clone(),
235+
src_dir: src_dir.clone(),
236+
language: Some(lang_ident.clone()),
237+
fallback_language: cfg.default_language(),
238+
prepend_parent: false,
239+
},
240+
None => RenderMarkdownContext {
241+
path: path.clone(),
242+
src_dir: src_dir.clone(),
243+
language: None,
244+
fallback_language: None,
245+
prepend_parent: false,
246+
},
247+
};
228248

229249
let content = ch.content.clone();
230-
let content = utils::render_markdown_with_path(
231-
&content,
232-
ctx.html_config.curly_quotes,
233-
Some(&path),
234-
Some(&src_dir),
235-
&fallback_path,
236-
);
250+
let content =
251+
utils::render_markdown_with_path(&content, ctx.html_config.curly_quotes, Some(&md_ctx));
237252

253+
md_ctx.prepend_parent = true;
238254
let fixed_content = utils::render_markdown_with_path(
239255
&ch.content,
240256
ctx.html_config.curly_quotes,
241-
Some(&path),
242-
Some(&src_dir),
243-
&fallback_path,
257+
Some(&md_ctx),
244258
);
245259
if !ctx.is_index {
246260
// Add page break between chapters

src/utils/fs.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ pub fn path_to_root<P: Into<PathBuf>>(path: P) -> String {
4747
.fold(String::new(), |mut s, c| {
4848
match c {
4949
Component::Normal(_) => s.push_str("../"),
50+
Component::ParentDir => {
51+
s.truncate(s.len() - 3);
52+
}
5053
_ => {
5154
debug!("Other path component... {:?}", c);
5255
}
@@ -189,7 +192,7 @@ pub fn get_404_output_file(input_404: &Option<String>) -> String {
189192

190193
#[cfg(test)]
191194
mod tests {
192-
use super::copy_files_except_ext;
195+
use super::{copy_files_except_ext, path_to_root};
193196
use std::{fs, io::Result, path::Path};
194197

195198
#[cfg(target_os = "windows")]
@@ -272,4 +275,10 @@ mod tests {
272275
panic!("output/symlink.png should exist")
273276
}
274277
}
278+
279+
#[test]
280+
fn test_path_to_root() {
281+
assert_eq!(path_to_root("some/relative/path"), "../../");
282+
assert_eq!(path_to_root("some/relative/other/../path"), "../../");
283+
}
275284
}

0 commit comments

Comments
 (0)