diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index f12fd16875..b5ef228d34 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -33,7 +33,11 @@ impl HtmlHandlebars { if let BookItem::Chapter(ref ch) = *item { let content = ch.content.clone(); let content = utils::render_markdown(&content, ctx.html_config.curly_quotes); - print_content.push_str(&content); + + let string_path = ch.path.parent().unwrap().display().to_string(); + + let fixed_content = utils::render_markdown_with_base(&ch.content, ctx.html_config.curly_quotes, &string_path); + print_content.push_str(&fixed_content); // Update the context with data for this file let path = ch diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 31abe98cae..df997d5eb3 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -66,15 +66,21 @@ pub fn id_from_content(content: &str) -> String { normalize_id(trimmed) } -fn adjust_links(event: Event) -> Event { +fn adjust_links<'a>(event: Event<'a>, with_base: &str) -> Event<'a> { lazy_static! { static ref HTTP_LINK: Regex = Regex::new("^https?://").unwrap(); - static ref MD_LINK: Regex = Regex::new("(?P.*).md(?P#.*)?").unwrap(); + static ref MD_LINK: Regex = Regex::new(r"(?P.*)\.md(?P#.*)?").unwrap(); } match event { Event::Start(Tag::Link(dest, title)) => { if !HTTP_LINK.is_match(&dest) { + let dest = if !with_base.is_empty() { + format!("{}/{}", with_base, dest) + } else { + dest.clone().into_owned() + }; + if let Some(caps) = MD_LINK.captures(&dest) { let mut html_link = [&caps["link"], ".html"].concat(); @@ -94,6 +100,10 @@ fn adjust_links(event: Event) -> Event { /// Wrapper around the pulldown-cmark parser for rendering markdown to HTML. pub fn render_markdown(text: &str, curly_quotes: bool) -> String { + render_markdown_with_base(text, curly_quotes, "") +} + +pub fn render_markdown_with_base(text: &str, curly_quotes: bool, base: &str) -> String { let mut s = String::with_capacity(text.len() * 3 / 2); let mut opts = Options::empty(); @@ -104,7 +114,7 @@ pub fn render_markdown(text: &str, curly_quotes: bool) -> String { let mut converter = EventQuoteConverter::new(curly_quotes); let events = p .map(clean_codeblock_headers) - .map(adjust_links) + .map(|event| adjust_links(event, base)) .map(|event| converter.convert(event)); html::push_html(&mut s, events); @@ -220,6 +230,12 @@ mod tests { render_markdown("[example_anchor](example.md#anchor)", false), "

example_anchor

\n" ); + + // this anchor contains 'md' inside of it + assert_eq!( + render_markdown("[phantom data](foo.html#phantomdata)", false), + "

phantom data

\n" + ); } #[test] diff --git a/tests/dummy_book/src/SUMMARY.md b/tests/dummy_book/src/SUMMARY.md index 0536e5c297..ee2426e4a8 100644 --- a/tests/dummy_book/src/SUMMARY.md +++ b/tests/dummy_book/src/SUMMARY.md @@ -8,6 +8,7 @@ - [Includes](first/includes.md) - [Recursive](first/recursive.md) - [Second Chapter](second.md) + - [Nested Chapter](second/nested.md) --- diff --git a/tests/dummy_book/src/second/nested.md b/tests/dummy_book/src/second/nested.md new file mode 100644 index 0000000000..c3eb3c8fbb --- /dev/null +++ b/tests/dummy_book/src/second/nested.md @@ -0,0 +1,4 @@ +# Testing relative links for the print page + +When we link to [the first section](../first/nested.md), it should work on +both the print page and the non-print page. \ No newline at end of file diff --git a/tests/rendered_output.rs b/tests/rendered_output.rs index 44aed62b0d..b7777ee7c5 100644 --- a/tests/rendered_output.rs +++ b/tests/rendered_output.rs @@ -31,7 +31,7 @@ const TOC_TOP_LEVEL: &[&'static str] = &[ "Introduction", ]; const TOC_SECOND_LEVEL: &[&'static str] = - &["1.1. Nested Chapter", "1.2. Includes", "1.3. Recursive"]; + &["1.1. Nested Chapter", "1.2. Includes", "2.1. Nested Chapter", "1.3. Recursive"]; /// Make sure you can load the dummy book and build it without panicking. #[test] @@ -109,6 +109,20 @@ fn check_correct_cross_links_in_nested_dir() { ); } +#[test] +fn check_correct_relative_links_in_print_page() { + let temp = DummyBook::new().build().unwrap(); + let md = MDBook::load(temp.path()).unwrap(); + md.build().unwrap(); + + let first = temp.path().join("book"); + + assert_contains_strings( + first.join("print.html"), + &[r##"the first section,"##], + ); +} + #[test] fn rendered_code_has_playpen_stuff() { let temp = DummyBook::new().build().unwrap(); @@ -443,7 +457,7 @@ mod search { assert_eq!(docs[&some_section]["body"], ""); assert_eq!( docs[&summary]["body"], - "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Conclusion" + "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Nested Chapter Conclusion" ); assert_eq!(docs[&summary]["breadcrumbs"], "First Chapter » Summary"); assert_eq!(docs[&conclusion]["body"], "I put <HTML> in here!"); diff --git a/tests/searchindex_fixture.json b/tests/searchindex_fixture.json index 330bc648a5..78a3915368 100644 --- a/tests/searchindex_fixture.json +++ b/tests/searchindex_fixture.json @@ -9,6 +9,7 @@ "first/includes.html#includes", "first/includes.html#summary", "second.html#second-chapter", + "second/nested.html#testing-relative-links-for-the-print-page", "conclusion.html#conclusion" ], "index": { @@ -24,6 +25,11 @@ "breadcrumbs": 1, "title": 1 }, + "10": { + "body": 3, + "breadcrumbs": 1, + "title": 1 + }, "2": { "body": 2, "breadcrumbs": 2, @@ -50,7 +56,7 @@ "title": 1 }, "7": { - "body": 12, + "body": 14, "breadcrumbs": 3, "title": 1 }, @@ -60,9 +66,9 @@ "title": 2 }, "9": { - "body": 3, - "breadcrumbs": 1, - "title": 1 + "body": 10, + "breadcrumbs": 7, + "title": 5 } }, "docs": { @@ -78,6 +84,12 @@ "id": "1", "title": "Introduction" }, + "10": { + "body": "I put <HTML> in here!", + "breadcrumbs": "Conclusion", + "id": "10", + "title": "Conclusion" + }, "2": { "body": "more text.", "breadcrumbs": "First Chapter", @@ -109,7 +121,7 @@ "title": "Includes" }, "7": { - "body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Conclusion", + "body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Nested Chapter Conclusion", "breadcrumbs": "First Chapter » Summary", "id": "7", "title": "Summary" @@ -121,13 +133,13 @@ "title": "Second Chapter" }, "9": { - "body": "I put <HTML> in here!", - "breadcrumbs": "Conclusion", + "body": "When we link to the first section , it should work on both the print page and the non-print page.", + "breadcrumbs": "Second Chapter » Testing relative links for the print page", "id": "9", - "title": "Conclusion" + "title": "Testing relative links for the print page" } }, - "length": 10, + "length": 11, "save": true }, "fields": [ @@ -206,6 +218,18 @@ } } } + }, + "t": { + "df": 0, + "docs": {}, + "h": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } } } }, @@ -251,7 +275,7 @@ "tf": 1.0 }, "7": { - "tf": 1.7320508075688773 + "tf": 2.0 }, "8": { "tf": 1.0 @@ -296,10 +320,10 @@ "s": { "df": 2, "docs": { - "7": { + "10": { "tf": 1.0 }, - "9": { + "7": { "tf": 1.0 } } @@ -420,13 +444,16 @@ "df": 0, "docs": {}, "t": { - "df": 2, + "df": 3, "docs": { "2": { "tf": 1.0 }, "7": { "tf": 1.0 + }, + "9": { + "tf": 1.0 } } } @@ -485,7 +512,7 @@ "0": { "tf": 1.0 }, - "9": { + "10": { "tf": 1.0 } } @@ -683,6 +710,14 @@ "tf": 1.0 } } + }, + "k": { + "df": 1, + "docs": { + "9": { + "tf": 1.4142135623730951 + } + } } } }, @@ -709,7 +744,7 @@ "t": { "df": 1, "docs": { - "9": { + "10": { "tf": 1.0 } } @@ -791,14 +826,42 @@ "tf": 1.0 }, "7": { - "tf": 1.0 + "tf": 1.4142135623730951 } } } } + }, + "o": { + "df": 0, + "docs": {}, + "n": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } } }, "p": { + "a": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "e": { + "df": 1, + "docs": { + "9": { + "tf": 1.7320508075688772 + } + } + } + } + }, "df": 0, "docs": {}, "r": { @@ -871,8 +934,12 @@ "df": 0, "docs": {}, "t": { - "df": 0, - "docs": {}, + "df": 1, + "docs": { + "9": { + "tf": 1.7320508075688772 + } + }, "l": { "df": 0, "docs": {}, @@ -935,7 +1002,7 @@ "t": { "df": 1, "docs": { - "9": { + "10": { "tf": 1.0 } } @@ -967,7 +1034,15 @@ } }, "df": 0, - "docs": {} + "docs": {}, + "l": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } }, "u": { "df": 0, @@ -1050,13 +1125,16 @@ "df": 0, "docs": {}, "n": { - "df": 2, + "df": 3, "docs": { "3": { "tf": 1.0 }, "5": { "tf": 1.0 + }, + "9": { + "tf": 1.0 } } } @@ -1170,8 +1248,12 @@ "df": 0, "docs": {} }, - "df": 0, - "docs": {} + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } } }, "x": { @@ -1200,6 +1282,14 @@ "r": { "df": 0, "docs": {}, + "k": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + }, "l": { "d": { "df": 1, @@ -1280,13 +1370,25 @@ "df": 2, "docs": { "0": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "7": { "tf": 1.0 } } } + }, + "t": { + "df": 0, + "docs": {}, + "h": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } } } }, @@ -1323,13 +1425,13 @@ "df": 0, "docs": {}, "r": { - "df": 6, + "df": 7, "docs": { "2": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "4": { - "tf": 1.7320508075688773 + "tf": 1.7320508075688772 }, "5": { "tf": 1.0 @@ -1338,10 +1440,13 @@ "tf": 1.0 }, "7": { - "tf": 2.0 + "tf": 2.23606797749979 }, "8": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 + }, + "9": { + "tf": 1.0 } } } @@ -1383,11 +1488,11 @@ "s": { "df": 2, "docs": { + "10": { + "tf": 1.4142135623730951 + }, "7": { "tf": 1.0 - }, - "9": { - "tf": 1.4142135623730952 } } } @@ -1419,7 +1524,7 @@ "df": 2, "docs": { "0": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "7": { "tf": 1.0 @@ -1507,10 +1612,10 @@ "df": 0, "docs": {}, "t": { - "df": 5, + "df": 6, "docs": { "2": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "4": { "tf": 1.0 @@ -1522,7 +1627,10 @@ "tf": 1.0 }, "7": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 + }, + "9": { + "tf": 1.0 } } } @@ -1581,7 +1689,7 @@ "0": { "tf": 1.0 }, - "9": { + "10": { "tf": 1.0 } } @@ -1636,7 +1744,7 @@ "df": 2, "docs": { "6": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "7": { "tf": 1.0 @@ -1728,7 +1836,7 @@ "df": 2, "docs": { "1": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "7": { "tf": 1.0 @@ -1779,6 +1887,14 @@ "tf": 1.0 } } + }, + "k": { + "df": 1, + "docs": { + "9": { + "tf": 1.7320508075688772 + } + } } } }, @@ -1805,7 +1921,7 @@ "t": { "df": 1, "docs": { - "9": { + "10": { "tf": 1.0 } } @@ -1884,17 +2000,45 @@ "df": 2, "docs": { "4": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "7": { - "tf": 1.0 + "tf": 1.4142135623730951 } } } } + }, + "o": { + "df": 0, + "docs": {}, + "n": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } } }, "p": { + "a": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "e": { + "df": 1, + "docs": { + "9": { + "tf": 2.0 + } + } + } + } + }, "df": 0, "docs": {}, "r": { @@ -1967,8 +2111,12 @@ "df": 0, "docs": {}, "t": { - "df": 0, - "docs": {}, + "df": 1, + "docs": { + "9": { + "tf": 2.0 + } + }, "l": { "df": 0, "docs": {}, @@ -2031,7 +2179,7 @@ "t": { "df": 1, "docs": { - "9": { + "10": { "tf": 1.0 } } @@ -2063,7 +2211,15 @@ } }, "df": 0, - "docs": {} + "docs": {}, + "l": { + "df": 1, + "docs": { + "9": { + "tf": 1.4142135623730951 + } + } + } }, "u": { "df": 0, @@ -2122,13 +2278,16 @@ "docs": {}, "n": { "d": { - "df": 2, + "df": 3, "docs": { "7": { "tf": 1.0 }, "8": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 + }, + "9": { + "tf": 1.0 } } }, @@ -2146,13 +2305,16 @@ "df": 0, "docs": {}, "n": { - "df": 2, + "df": 3, "docs": { "3": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 }, "5": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 + }, + "9": { + "tf": 1.0 } } } @@ -2216,7 +2378,7 @@ "df": 1, "docs": { "7": { - "tf": 1.4142135623730952 + "tf": 1.4142135623730951 } } } @@ -2266,8 +2428,12 @@ "df": 0, "docs": {} }, - "df": 0, - "docs": {} + "df": 1, + "docs": { + "9": { + "tf": 1.4142135623730951 + } + } } }, "x": { @@ -2296,6 +2462,14 @@ "r": { "df": 0, "docs": {}, + "k": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + }, "l": { "d": { "df": 1, @@ -2388,7 +2562,7 @@ "s": { "df": 1, "docs": { - "9": { + "10": { "tf": 1.0 } } @@ -2511,6 +2685,26 @@ } } }, + "l": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "n": { + "df": 0, + "docs": {}, + "k": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + } + } + }, "n": { "df": 0, "docs": {}, @@ -2531,6 +2725,62 @@ } } }, + "p": { + "a": { + "df": 0, + "docs": {}, + "g": { + "df": 0, + "docs": {}, + "e": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + } + }, + "df": 0, + "docs": {}, + "r": { + "df": 0, + "docs": {}, + "i": { + "df": 0, + "docs": {}, + "n": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + } + } + } + }, + "r": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "l": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + } + }, "s": { "df": 0, "docs": {}, @@ -2609,6 +2859,26 @@ } } } + }, + "t": { + "df": 0, + "docs": {}, + "e": { + "df": 0, + "docs": {}, + "s": { + "df": 0, + "docs": {}, + "t": { + "df": 1, + "docs": { + "9": { + "tf": 1.0 + } + } + } + } + } } } }