Make link to first chapter active in index page

Makes both pages more consistent, and also the previous test pass

Co-authored-by: Eric Huss <eric@huss.org>
This commit is contained in:
ISSOtm 2022-06-22 23:40:36 +02:00
parent a91e888575
commit fa5f32c7fd
3 changed files with 13 additions and 20 deletions

View File

@ -116,7 +116,7 @@ impl HtmlHandlebars {
if ctx.is_index { if ctx.is_index {
ctx.data.insert("path".to_owned(), json!("index.md")); ctx.data.insert("path".to_owned(), json!("index.md"));
ctx.data.insert("path_to_root".to_owned(), json!("")); ctx.data.insert("path_to_root".to_owned(), json!(""));
ctx.data.insert("is_index".to_owned(), json!("true")); ctx.data.insert("is_index".to_owned(), json!(true));
let rendered_index = ctx.handlebars.render("index", &ctx.data)?; let rendered_index = ctx.handlebars.render("index", &ctx.data)?;
let rendered_index = let rendered_index =
self.post_process(rendered_index, &ctx.html_config.playground, ctx.edition); self.post_process(rendered_index, &ctx.html_config.playground, ctx.edition);

View File

@ -57,6 +57,11 @@ impl HelperDef for RenderToc {
out.write("<ol class=\"chapter\">")?; out.write("<ol class=\"chapter\">")?;
let mut current_level = 1; let mut current_level = 1;
// The "index" page, which has this attribute set, is supposed to alias the first chapter in
// the book, i.e. the first link. There seems to be no easy way to determine which chapter
// the "index" is aliasing from within the renderer, so this is used instead to force the
// first link to be active. See further below.
let mut is_first_chapter = ctx.data().get("is_index").is_some();
for item in chapters { for item in chapters {
// Spacer // Spacer
@ -130,7 +135,8 @@ impl HelperDef for RenderToc {
out.write(&tmp)?; out.write(&tmp)?;
out.write("\"")?; out.write("\"")?;
if path == &current_path { if path == &current_path || is_first_chapter {
is_first_chapter = false;
out.write(" class=\"active\"")?; out.write(" class=\"active\"")?;
} }

View File

@ -15,7 +15,7 @@ use select::predicate::{Class, Name, Predicate};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::io::{Read, Write}; use std::io::Write;
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use tempfile::Builder as TempFileBuilder; use tempfile::Builder as TempFileBuilder;
@ -476,23 +476,10 @@ fn first_chapter_is_copied_as_index_even_if_not_first_elem() {
let md = MDBook::load_with_config(temp.path(), cfg).unwrap(); let md = MDBook::load_with_config(temp.path(), cfg).unwrap();
md.build().unwrap(); md.build().unwrap();
// In theory, just reading the entire files into memory and comparing is sufficient for *testing*, let root = temp.path().join("book");
// but since the files are temporary and get deleted when the test completes, we'll want to print let chapter = fs::read_to_string(root.join("chapter_1.html")).expect("read chapter 1");
// the differences on failure. let index = fs::read_to_string(root.join("index.html")).expect("read index");
// We could invoke `diff` on the files on failure, but that may not be portable (hi, Windows...) pretty_assertions::assert_eq!(chapter, index);
// so we'll do the job ourselves—potentially a bit sloppily, but that can always be piped into
// `diff` manually afterwards.
let book_path = temp.path().join("book");
let read_file = |path: &str| {
let mut buf = String::new();
fs::File::open(book_path.join(path))
.with_context(|| format!("Failed to read {}", path))
.unwrap()
.read_to_string(&mut buf)
.unwrap();
buf
};
pretty_assertions::assert_eq!(read_file("chapter_1.html"), read_file("index.html"));
} }
#[test] #[test]