cross-link by section number if TOC are structurally the same
This commit is contained in:
parent
badc921429
commit
aa54d95a23
|
@ -430,11 +430,11 @@ impl MDBook {
|
||||||
.map(|item| {
|
.map(|item| {
|
||||||
match *item {
|
match *item {
|
||||||
TocItem::Numbered(ref i) =>
|
TocItem::Numbered(ref i) =>
|
||||||
TocItem::Numbered(self.set_translation_links(i)),
|
TocItem::Numbered(self.set_translation_links(i, key.to_owned())),
|
||||||
TocItem::Unnumbered(ref i) =>
|
TocItem::Unnumbered(ref i) =>
|
||||||
TocItem::Unnumbered(self.set_translation_links(i)),
|
TocItem::Unnumbered(self.set_translation_links(i, key.to_owned())),
|
||||||
TocItem::Unlisted(ref i) =>
|
TocItem::Unlisted(ref i) =>
|
||||||
TocItem::Unlisted(self.set_translation_links(i)),
|
TocItem::Unlisted(self.set_translation_links(i, key.to_owned())),
|
||||||
TocItem::Spacer =>
|
TocItem::Spacer =>
|
||||||
TocItem::Spacer,
|
TocItem::Spacer,
|
||||||
}
|
}
|
||||||
|
@ -475,7 +475,7 @@ impl MDBook {
|
||||||
Some(default_links)
|
Some(default_links)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_translation_links(&mut self, content: &TocContent) -> TocContent {
|
fn set_translation_links(&mut self, content: &TocContent, key: String) -> TocContent {
|
||||||
let mut final_links: BTreeMap<String, TranslationLink> = BTreeMap::new();
|
let mut final_links: BTreeMap<String, TranslationLink> = BTreeMap::new();
|
||||||
let mut newcontent: TocContent = content.clone();
|
let mut newcontent: TocContent = content.clone();
|
||||||
|
|
||||||
|
@ -498,6 +498,9 @@ impl MDBook {
|
||||||
|
|
||||||
// Find a translation for the links that are still None
|
// Find a translation for the links that are still None
|
||||||
|
|
||||||
|
let orig_book: &Book = self.translations.get(&key).unwrap();
|
||||||
|
let orig_toc_id = toc::toc_node_count_id(&orig_book.toc);
|
||||||
|
|
||||||
for (key, trl) in final_links.clone().iter() {
|
for (key, trl) in final_links.clone().iter() {
|
||||||
match trl.link {
|
match trl.link {
|
||||||
Some(_) => { continue; },
|
Some(_) => { continue; },
|
||||||
|
@ -507,6 +510,8 @@ impl MDBook {
|
||||||
let b: &Book = self.translations.get(key).unwrap();
|
let b: &Book = self.translations.get(key).unwrap();
|
||||||
let flat_toc = toc::flat_toc(&b.toc);
|
let flat_toc = toc::flat_toc(&b.toc);
|
||||||
|
|
||||||
|
let by_section: bool = toc::toc_node_count_id(&b.toc) == orig_toc_id;
|
||||||
|
|
||||||
for item in flat_toc.iter() {
|
for item in flat_toc.iter() {
|
||||||
match *item {
|
match *item {
|
||||||
TocItem::Numbered(ref i) |
|
TocItem::Numbered(ref i) |
|
||||||
|
@ -515,7 +520,7 @@ impl MDBook {
|
||||||
|
|
||||||
// Note that this will also add a link to itself, which is good.
|
// Note that this will also add a link to itself, which is good.
|
||||||
|
|
||||||
if content.is_it_a_translation_of(i) {
|
if content.is_it_a_translation_of(i, true, true, by_section) {
|
||||||
if let Some(mut a) = i.chapter.get_dest_path() {
|
if let Some(mut a) = i.chapter.get_dest_path() {
|
||||||
// Join the path to the language code, i.e. en/tears.html
|
// Join the path to the language code, i.e. en/tears.html
|
||||||
a = PathBuf::from(key.to_string()).join(a);
|
a = PathBuf::from(key.to_string()).join(a);
|
||||||
|
|
|
@ -55,8 +55,14 @@ impl TocContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_it_a_translation_of(&self, checking: &TocContent) -> bool {
|
pub fn is_it_a_translation_of(&self,
|
||||||
|
checking: &TocContent,
|
||||||
|
by_tr_id: bool,
|
||||||
|
by_src_path: bool,
|
||||||
|
by_section: bool) -> bool {
|
||||||
|
|
||||||
// if the user has set the same translation_id on them
|
// if the user has set the same translation_id on them
|
||||||
|
if by_tr_id {
|
||||||
if let Some(ref a) = self.chapter.translation_id {
|
if let Some(ref a) = self.chapter.translation_id {
|
||||||
if let Some(ref b) = checking.chapter.translation_id {
|
if let Some(ref b) = checking.chapter.translation_id {
|
||||||
if a == b {
|
if a == b {
|
||||||
|
@ -64,8 +70,10 @@ impl TocContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if src_path matches
|
// if src_path matches
|
||||||
|
if by_src_path {
|
||||||
if let Some(ref a) = self.chapter.get_src_path() {
|
if let Some(ref a) = self.chapter.get_src_path() {
|
||||||
if let Some(ref b) = checking.chapter.get_src_path() {
|
if let Some(ref b) = checking.chapter.get_src_path() {
|
||||||
if a == b {
|
if a == b {
|
||||||
|
@ -73,6 +81,22 @@ impl TocContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if section string matches, useful when TOC structure matches but
|
||||||
|
// titles and paths are translated. Can test that with
|
||||||
|
// toc_node_count_id().
|
||||||
|
if by_section {
|
||||||
|
if let Some(_) = self.section {
|
||||||
|
let a = self.section_as_string();
|
||||||
|
if let Some(_) = checking.section {
|
||||||
|
let b = checking.section_as_string();
|
||||||
|
if a == b {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -115,3 +139,34 @@ pub fn flat_toc(toc: &Vec<TocItem>) -> Vec<TocItem> {
|
||||||
}
|
}
|
||||||
flattened
|
flattened
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Produces a String that can be used to check if two TOCs have the same
|
||||||
|
/// structure. It recursively counts the items at each level, ignoring Spacer
|
||||||
|
/// items.
|
||||||
|
pub fn toc_node_count_id(toc: &Vec<TocItem>) -> String {
|
||||||
|
let mut counters = String::new();
|
||||||
|
|
||||||
|
let c = toc.iter().filter(|x| {
|
||||||
|
match **x {
|
||||||
|
TocItem::Spacer => { false },
|
||||||
|
_ => { true },
|
||||||
|
}}).count();
|
||||||
|
|
||||||
|
counters.push_str(&format!("{}", c));
|
||||||
|
|
||||||
|
for i in toc.iter() {
|
||||||
|
match *i {
|
||||||
|
TocItem::Numbered(ref x) |
|
||||||
|
TocItem::Unnumbered(ref x) |
|
||||||
|
TocItem::Unlisted(ref x) => {
|
||||||
|
if let Some(ref subs) = x.sub_items {
|
||||||
|
let a = toc_node_count_id(subs);
|
||||||
|
counters.push_str(&a);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TocItem::Spacer => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
counters
|
||||||
|
}
|
||||||
|
|
|
@ -64,32 +64,28 @@ fn it_renders_multilanguage_book() {
|
||||||
assert!(s.contains("<a href=\"hu/index.html\">hu</a>"));
|
assert!(s.contains("<a href=\"hu/index.html\">hu</a>"));
|
||||||
assert!(s.contains("<a href=\"fr/index.html\">fr</a>"));
|
assert!(s.contains("<a href=\"fr/index.html\">fr</a>"));
|
||||||
|
|
||||||
// Test if translation links given in the TOML header were rendered
|
// Test if translation links are found
|
||||||
|
|
||||||
book_path = proj.translations.get("en").unwrap().config.get_dest();
|
book_path = proj.translations.get("en").unwrap().config.get_dest();
|
||||||
|
|
||||||
chapter_path = book_path.join("rabbit-hole.html");
|
chapter_path = book_path.join("rabbit-hole.html");
|
||||||
s = utils::fs::file_to_string(&chapter_path).unwrap();
|
s = utils::fs::file_to_string(&chapter_path).unwrap();
|
||||||
|
assert!(s.contains("<a href=\"en/rabbit-hole.html\">en</a>"));
|
||||||
assert!(s.contains("<a href=\"hu/nyuszi.html\">hu</a>"));
|
assert!(s.contains("<a href=\"hu/nyuszi.html\">hu</a>"));
|
||||||
assert!(s.contains("<a href=\"fr/terrier.html\">fr</a>"));
|
assert!(s.contains("<a href=\"fr/terrier.html\">fr</a>"));
|
||||||
|
|
||||||
// Test if translation links by translation_id were found
|
|
||||||
|
|
||||||
book_path = proj.translations.get("en").unwrap().config.get_dest();
|
|
||||||
chapter_path = book_path.join("long-tale.html");
|
|
||||||
s = utils::fs::file_to_string(&chapter_path).unwrap();
|
|
||||||
assert!(s.contains("<a href=\"en/long-tale.html\">en</a>"));
|
|
||||||
assert!(s.contains("<span>fr</span>"));
|
|
||||||
assert!(s.contains("<a href=\"hu/tarka-farka.html\">hu</a>"));
|
|
||||||
|
|
||||||
// Test if translation links by src_path were found
|
|
||||||
|
|
||||||
book_path = proj.translations.get("en").unwrap().config.get_dest();
|
|
||||||
chapter_path = book_path.join("tears.html");
|
chapter_path = book_path.join("tears.html");
|
||||||
s = utils::fs::file_to_string(&chapter_path).unwrap();
|
s = utils::fs::file_to_string(&chapter_path).unwrap();
|
||||||
assert!(s.contains("<a href=\"en/tears.html\">en</a>"));
|
assert!(s.contains("<a href=\"en/tears.html\">en</a>"));
|
||||||
assert!(s.contains("<a href=\"fr/tears.html\">fr</a>"));
|
assert!(s.contains("<a href=\"fr/tears.html\">fr</a>"));
|
||||||
assert!(s.contains("<a href=\"hu/tears.html\">hu</a>"));
|
assert!(s.contains("<a href=\"hu/tears.html\">hu</a>"));
|
||||||
|
|
||||||
|
chapter_path = book_path.join("long-tale.html");
|
||||||
|
s = utils::fs::file_to_string(&chapter_path).unwrap();
|
||||||
|
assert!(s.contains("<a href=\"en/long-tale.html\">en</a>"));
|
||||||
|
assert!(s.contains("<a href=\"fr/cocasse.html\">fr</a>"));
|
||||||
|
assert!(s.contains("<a href=\"hu/tarka-farka.html\">hu</a>"));
|
||||||
|
|
||||||
// Test if print.html is produced for each translations
|
// Test if print.html is produced for each translations
|
||||||
|
|
||||||
book_path = proj.translations.get("en").unwrap().config.get_dest();
|
book_path = proj.translations.get("en").unwrap().config.get_dest();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
||||||
use book::chapter::Chapter;
|
use book::chapter::Chapter;
|
||||||
use book::toc::{TocItem, TocContent, flat_toc};
|
use book::toc::{TocItem, TocContent, flat_toc, toc_node_count_id};
|
||||||
use parse::summary::parse_level;
|
use parse::summary::parse_level;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -77,3 +77,37 @@ fn it_flattens_toc() {
|
||||||
|
|
||||||
assert_eq!(format!("{:#?}", result), expected);
|
assert_eq!(format!("{:#?}", result), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_counts_toc_id_string() {
|
||||||
|
let text = r#"
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
[Introduction](misc/introduction.md)
|
||||||
|
|
||||||
|
- [mdBook](README.md)
|
||||||
|
- [Command Line Tool](cli/cli-tool.md)
|
||||||
|
- [init](cli/init.md)
|
||||||
|
- [build](cli/build.md)
|
||||||
|
- [watch](cli/watch.md)
|
||||||
|
- [serve](cli/serve.md)
|
||||||
|
- [test](cli/test.md)
|
||||||
|
- [Format](format/format.md)
|
||||||
|
- [SUMMARY.md](format/summary.md)
|
||||||
|
- [Configuration](format/config.md)
|
||||||
|
- [Theme](format/theme/theme.md)
|
||||||
|
- [index.hbs](format/theme/index-hbs.md)
|
||||||
|
- [Syntax highlighting](format/theme/syntax-highlighting.md)
|
||||||
|
- [MathJax Support](format/mathjax.md)
|
||||||
|
- [Rust code specific features](format/rust.md)
|
||||||
|
- [Rust Library](lib/lib.md)
|
||||||
|
-----------
|
||||||
|
[Contributors](misc/contributors.md)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let toc = parse_level(&mut text.split('\n').collect(), 0, vec![0], true).unwrap();
|
||||||
|
|
||||||
|
let counters = toc_node_count_id(&toc);
|
||||||
|
|
||||||
|
assert_eq!(counters, "6552".to_string());
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue