Emit redirects towards the end of the rendering process
This commit is contained in:
parent
a5086a1e58
commit
b2d50392ea
|
@ -539,6 +539,7 @@ impl Default for HtmlConfig {
|
||||||
git_repository_url: None,
|
git_repository_url: None,
|
||||||
git_repository_icon: None,
|
git_repository_icon: None,
|
||||||
livereload_url: None,
|
livereload_url: None,
|
||||||
|
redirect: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::utils;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs::{self, File};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use handlebars::Handlebars;
|
use handlebars::Handlebars;
|
||||||
|
@ -279,6 +279,46 @@ impl HtmlHandlebars {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_redirects(
|
||||||
|
&self,
|
||||||
|
root: &Path,
|
||||||
|
handlebars: &Handlebars<'_>,
|
||||||
|
redirects: &HashMap<PathBuf, String>,
|
||||||
|
) -> Result<()> {
|
||||||
|
if redirects.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
log::debug!("Emitting redirects");
|
||||||
|
|
||||||
|
for (original, new) in redirects {
|
||||||
|
log::debug!("Redirecting \"{}\" → \"{}\"", original.display(), new);
|
||||||
|
let filename = root.join(original);
|
||||||
|
self.emit_redirect(handlebars, &filename, new)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_redirect(
|
||||||
|
&self,
|
||||||
|
handlebars: &Handlebars<'_>,
|
||||||
|
original: &Path,
|
||||||
|
destination: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
if let Some(parent) = original.parent() {
|
||||||
|
std::fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ctx = json!({
|
||||||
|
"url": destination,
|
||||||
|
});
|
||||||
|
let f = File::create(original)?;
|
||||||
|
handlebars.render_to_write("redirect", &ctx, f)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mattico): Remove some time after the 0.1.8 release
|
// TODO(mattico): Remove some time after the 0.1.8 release
|
||||||
|
@ -343,6 +383,10 @@ impl Renderer for HtmlHandlebars {
|
||||||
debug!("Register the head handlebars template");
|
debug!("Register the head handlebars template");
|
||||||
handlebars.register_partial("head", String::from_utf8(theme.head.clone())?)?;
|
handlebars.register_partial("head", String::from_utf8(theme.head.clone())?)?;
|
||||||
|
|
||||||
|
debug!("Register the redirect handlebars template");
|
||||||
|
handlebars
|
||||||
|
.register_template_string("redirect", String::from_utf8(theme.redirect.clone())?)?;
|
||||||
|
|
||||||
debug!("Register the header handlebars template");
|
debug!("Register the header handlebars template");
|
||||||
handlebars.register_partial("header", String::from_utf8(theme.header.clone())?)?;
|
handlebars.register_partial("header", String::from_utf8(theme.header.clone())?)?;
|
||||||
|
|
||||||
|
@ -401,6 +445,8 @@ impl Renderer for HtmlHandlebars {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.emit_redirects(&ctx.destination, &handlebars, &html_config.redirect)?;
|
||||||
|
|
||||||
// Copy all remaining files, avoid a recursive copy from/to the book build dir
|
// Copy all remaining files, avoid a recursive copy from/to the book build dir
|
||||||
utils::fs::copy_files_except_ext(&src_dir, &destination, true, Some(&build_dir), &["md"])?;
|
utils::fs::copy_files_except_ext(&src_dir, &destination, true, Some(&build_dir), &["md"])?;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ use crate::errors::*;
|
||||||
|
|
||||||
pub static INDEX: &[u8] = include_bytes!("index.hbs");
|
pub static INDEX: &[u8] = include_bytes!("index.hbs");
|
||||||
pub static HEAD: &[u8] = include_bytes!("head.hbs");
|
pub static HEAD: &[u8] = include_bytes!("head.hbs");
|
||||||
|
pub static REDIRECT: &[u8] = include_bytes!("redirect.hbs");
|
||||||
pub static HEADER: &[u8] = include_bytes!("header.hbs");
|
pub static HEADER: &[u8] = include_bytes!("header.hbs");
|
||||||
pub static CHROME_CSS: &[u8] = include_bytes!("css/chrome.css");
|
pub static CHROME_CSS: &[u8] = include_bytes!("css/chrome.css");
|
||||||
pub static GENERAL_CSS: &[u8] = include_bytes!("css/general.css");
|
pub static GENERAL_CSS: &[u8] = include_bytes!("css/general.css");
|
||||||
|
@ -46,6 +47,7 @@ pub static FONT_AWESOME_OTF: &[u8] = include_bytes!("FontAwesome/fonts/FontAweso
|
||||||
pub struct Theme {
|
pub struct Theme {
|
||||||
pub index: Vec<u8>,
|
pub index: Vec<u8>,
|
||||||
pub head: Vec<u8>,
|
pub head: Vec<u8>,
|
||||||
|
pub redirect: Vec<u8>,
|
||||||
pub header: Vec<u8>,
|
pub header: Vec<u8>,
|
||||||
pub chrome_css: Vec<u8>,
|
pub chrome_css: Vec<u8>,
|
||||||
pub general_css: Vec<u8>,
|
pub general_css: Vec<u8>,
|
||||||
|
@ -77,6 +79,7 @@ impl Theme {
|
||||||
let files = vec![
|
let files = vec![
|
||||||
(theme_dir.join("index.hbs"), &mut theme.index),
|
(theme_dir.join("index.hbs"), &mut theme.index),
|
||||||
(theme_dir.join("head.hbs"), &mut theme.head),
|
(theme_dir.join("head.hbs"), &mut theme.head),
|
||||||
|
(theme_dir.join("redirect.hbs"), &mut theme.redirect),
|
||||||
(theme_dir.join("header.hbs"), &mut theme.header),
|
(theme_dir.join("header.hbs"), &mut theme.header),
|
||||||
(theme_dir.join("book.js"), &mut theme.js),
|
(theme_dir.join("book.js"), &mut theme.js),
|
||||||
(theme_dir.join("css/chrome.css"), &mut theme.chrome_css),
|
(theme_dir.join("css/chrome.css"), &mut theme.chrome_css),
|
||||||
|
@ -120,6 +123,7 @@ impl Default for Theme {
|
||||||
Theme {
|
Theme {
|
||||||
index: INDEX.to_owned(),
|
index: INDEX.to_owned(),
|
||||||
head: HEAD.to_owned(),
|
head: HEAD.to_owned(),
|
||||||
|
redirect: REDIRECT.to_owned(),
|
||||||
header: HEADER.to_owned(),
|
header: HEADER.to_owned(),
|
||||||
chrome_css: CHROME_CSS.to_owned(),
|
chrome_css: CHROME_CSS.to_owned(),
|
||||||
general_css: GENERAL_CSS.to_owned(),
|
general_css: GENERAL_CSS.to_owned(),
|
||||||
|
@ -175,6 +179,7 @@ mod tests {
|
||||||
let files = [
|
let files = [
|
||||||
"index.hbs",
|
"index.hbs",
|
||||||
"head.hbs",
|
"head.hbs",
|
||||||
|
"redirect.hbs",
|
||||||
"header.hbs",
|
"header.hbs",
|
||||||
"favicon.png",
|
"favicon.png",
|
||||||
"css/chrome.css",
|
"css/chrome.css",
|
||||||
|
@ -203,6 +208,7 @@ mod tests {
|
||||||
let empty = Theme {
|
let empty = Theme {
|
||||||
index: Vec::new(),
|
index: Vec::new(),
|
||||||
head: Vec::new(),
|
head: Vec::new(),
|
||||||
|
redirect: Vec::new(),
|
||||||
header: Vec::new(),
|
header: Vec::new(),
|
||||||
chrome_css: Vec::new(),
|
chrome_css: Vec::new(),
|
||||||
general_css: Vec::new(),
|
general_css: Vec::new(),
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Redirecting...</title>
|
||||||
|
<meta http-equiv="refresh" content="0;URL='{{url}}'">
|
||||||
|
<meta rel="canonical" href="{{url}}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Redirecting to... <a href="{{url}}">{{url}}</a>.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue