mdbook/src/renderer/html_handlebars/helpers/toc.rs

145 lines
5 KiB
Rust
Raw Normal View History

2017-06-13 20:53:25 +08:00
use std::collections::BTreeMap;
2018-07-23 12:45:01 -05:00
use std::path::Path;
use utils;
use handlebars::{Handlebars, Helper, HelperDef, RenderContext, RenderError};
use pulldown_cmark::{html, Event, Parser, Tag};
2018-07-23 12:45:01 -05:00
use serde_json;
// Handlebars helper to construct TOC
#[derive(Clone, Copy)]
pub struct RenderToc {
pub no_section_label: bool,
}
impl HelperDef for RenderToc {
fn call(&self, _h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
// get value from context data
// rc.get_path() is current json parent path, you should always use it like this
// param is the key of value you want to display
let chapters = rc.evaluate_absolute("chapters", true).and_then(|c| {
serde_json::value::from_value::<Vec<BTreeMap<String, String>>>(c.clone())
.map_err(|_| RenderError::new("Could not decode the JSON data"))
})?;
let current = rc.evaluate_absolute("path", true)?
.as_str()
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))?
.replace("\"", "");
Improve accessibility (#535) * fix(theme/index): Use nav element for Table of Content * fix(renderer/html_handlebars/helpers/toc): Use ol instead of ul Chapters and sections are ordered, so we should use the appropriate HTML tag. * fix(renderer/html_handlebars/helpers/toc): Hide section number from screen readers Screen readers have this functionality build-in, no need to present this. Ideally, this should not even be in the DOM tree, since the numbers can be shown by using CSS. * fix(theme/index): Remove tabIndex="-1" from .page Divs are not focusable by default * fix(theme): Make sidebar accessible Using aria-hidden (together with tabIndex) takes the links out of the tab order. http://heydonworks.com/practical_aria_examples/#progressive-collapsibles * fix(theme/index): Wrap content inside main tag The main tag helps users skip additional content on the page. * fix(theme/book): Don't focus .page on page load The main content is identified by the main tag, not by auto-focusing it on page load. * fix(theme/index): Make page controls accessible * fix: Make theme selector accessible - Use ul and li (since it is a list) - Add aria-expanded and aria-haspopup to the toggle button - Use button instead of div (buttons are accessible by default) - Handle Esc key (close popup) - Adjust CSS to keep same visual style * fix(theme/stylus/sidebar): Make link clickable area wider Links now expand to fill the entire row. * fix(theme): Wrap header buttons and improve animation performance Previously, the header had a fixed height, which meant that sometimes the print button was not visible. Animating the left property is expensive, which lead to laggy animations - transform is much cheaper and has the same effect. * fix(theme/stylus/theme-popup): Theme button inherits color Bug introduced while making the popup accessible * fix(theme/book): Handle edge case when toggling sidebar Bug introduced when switching from animating left to using transform.
2018-01-15 14:26:53 +01:00
rc.writer.write_all(b"<ol class=\"chapter\">")?;
let mut current_level = 1;
2017-06-13 20:53:25 +08:00
for item in chapters {
// Spacer
if item.get("spacer").is_some() {
rc.writer.write_all(b"<li class=\"spacer\"></li>")?;
continue;
}
let level = if let Some(s) = item.get("section") {
2017-06-27 09:08:58 +02:00
s.matches('.').count()
} else {
1
};
if level > current_level {
while level > current_level {
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"<li>")?;
Improve accessibility (#535) * fix(theme/index): Use nav element for Table of Content * fix(renderer/html_handlebars/helpers/toc): Use ol instead of ul Chapters and sections are ordered, so we should use the appropriate HTML tag. * fix(renderer/html_handlebars/helpers/toc): Hide section number from screen readers Screen readers have this functionality build-in, no need to present this. Ideally, this should not even be in the DOM tree, since the numbers can be shown by using CSS. * fix(theme/index): Remove tabIndex="-1" from .page Divs are not focusable by default * fix(theme): Make sidebar accessible Using aria-hidden (together with tabIndex) takes the links out of the tab order. http://heydonworks.com/practical_aria_examples/#progressive-collapsibles * fix(theme/index): Wrap content inside main tag The main tag helps users skip additional content on the page. * fix(theme/book): Don't focus .page on page load The main content is identified by the main tag, not by auto-focusing it on page load. * fix(theme/index): Make page controls accessible * fix: Make theme selector accessible - Use ul and li (since it is a list) - Add aria-expanded and aria-haspopup to the toggle button - Use button instead of div (buttons are accessible by default) - Handle Esc key (close popup) - Adjust CSS to keep same visual style * fix(theme/stylus/sidebar): Make link clickable area wider Links now expand to fill the entire row. * fix(theme): Wrap header buttons and improve animation performance Previously, the header had a fixed height, which meant that sometimes the print button was not visible. Animating the left property is expensive, which lead to laggy animations - transform is much cheaper and has the same effect. * fix(theme/stylus/theme-popup): Theme button inherits color Bug introduced while making the popup accessible * fix(theme/book): Handle edge case when toggling sidebar Bug introduced when switching from animating left to using transform.
2018-01-15 14:26:53 +01:00
rc.writer.write_all(b"<ol class=\"section\">")?;
current_level += 1;
}
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"<li>")?;
} else if level < current_level {
while level < current_level {
Improve accessibility (#535) * fix(theme/index): Use nav element for Table of Content * fix(renderer/html_handlebars/helpers/toc): Use ol instead of ul Chapters and sections are ordered, so we should use the appropriate HTML tag. * fix(renderer/html_handlebars/helpers/toc): Hide section number from screen readers Screen readers have this functionality build-in, no need to present this. Ideally, this should not even be in the DOM tree, since the numbers can be shown by using CSS. * fix(theme/index): Remove tabIndex="-1" from .page Divs are not focusable by default * fix(theme): Make sidebar accessible Using aria-hidden (together with tabIndex) takes the links out of the tab order. http://heydonworks.com/practical_aria_examples/#progressive-collapsibles * fix(theme/index): Wrap content inside main tag The main tag helps users skip additional content on the page. * fix(theme/book): Don't focus .page on page load The main content is identified by the main tag, not by auto-focusing it on page load. * fix(theme/index): Make page controls accessible * fix: Make theme selector accessible - Use ul and li (since it is a list) - Add aria-expanded and aria-haspopup to the toggle button - Use button instead of div (buttons are accessible by default) - Handle Esc key (close popup) - Adjust CSS to keep same visual style * fix(theme/stylus/sidebar): Make link clickable area wider Links now expand to fill the entire row. * fix(theme): Wrap header buttons and improve animation performance Previously, the header had a fixed height, which meant that sometimes the print button was not visible. Animating the left property is expensive, which lead to laggy animations - transform is much cheaper and has the same effect. * fix(theme/stylus/theme-popup): Theme button inherits color Bug introduced while making the popup accessible * fix(theme/book): Handle edge case when toggling sidebar Bug introduced when switching from animating left to using transform.
2018-01-15 14:26:53 +01:00
rc.writer.write_all(b"</ol>")?;
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"</li>")?;
current_level -= 1;
}
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"<li>")?;
} else {
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"<li")?;
if item.get("section").is_none() {
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b" class=\"affix\"")?;
}
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b">")?;
}
// Link
let path_exists = if let Some(path) = item.get("path") {
if !path.is_empty() {
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"<a href=\"")?;
let tmp = Path::new(item.get("path").expect("Error: path should be Some(_)"))
.with_extension("html")
.to_str()
.unwrap()
// Hack for windows who tends to use `\` as separator instead of `/`
.replace("\\", "/");
// Add link
2018-07-23 12:45:01 -05:00
rc.writer
.write_all(&utils::fs::path_to_root(&current).as_bytes())?;
rc.writer.write_all(tmp.as_bytes())?;
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"\"")?;
if path == &current {
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b" class=\"active\"")?;
}
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b">")?;
true
} else {
false
}
} else {
false
};
if !self.no_section_label {
// Section does not necessarily exist
if let Some(section) = item.get("section") {
Improve accessibility (#535) * fix(theme/index): Use nav element for Table of Content * fix(renderer/html_handlebars/helpers/toc): Use ol instead of ul Chapters and sections are ordered, so we should use the appropriate HTML tag. * fix(renderer/html_handlebars/helpers/toc): Hide section number from screen readers Screen readers have this functionality build-in, no need to present this. Ideally, this should not even be in the DOM tree, since the numbers can be shown by using CSS. * fix(theme/index): Remove tabIndex="-1" from .page Divs are not focusable by default * fix(theme): Make sidebar accessible Using aria-hidden (together with tabIndex) takes the links out of the tab order. http://heydonworks.com/practical_aria_examples/#progressive-collapsibles * fix(theme/index): Wrap content inside main tag The main tag helps users skip additional content on the page. * fix(theme/book): Don't focus .page on page load The main content is identified by the main tag, not by auto-focusing it on page load. * fix(theme/index): Make page controls accessible * fix: Make theme selector accessible - Use ul and li (since it is a list) - Add aria-expanded and aria-haspopup to the toggle button - Use button instead of div (buttons are accessible by default) - Handle Esc key (close popup) - Adjust CSS to keep same visual style * fix(theme/stylus/sidebar): Make link clickable area wider Links now expand to fill the entire row. * fix(theme): Wrap header buttons and improve animation performance Previously, the header had a fixed height, which meant that sometimes the print button was not visible. Animating the left property is expensive, which lead to laggy animations - transform is much cheaper and has the same effect. * fix(theme/stylus/theme-popup): Theme button inherits color Bug introduced while making the popup accessible * fix(theme/book): Handle edge case when toggling sidebar Bug introduced when switching from animating left to using transform.
2018-01-15 14:26:53 +01:00
rc.writer.write_all(b"<strong aria-hidden=\"true\">")?;
rc.writer.write_all(section.as_bytes())?;
rc.writer.write_all(b"</strong> ")?;
}
}
if let Some(name) = item.get("name") {
// Render only inline code blocks
// filter all events that are not inline code blocks
let parser = Parser::new(name).filter(|event| match *event {
Event::Start(Tag::Code)
| Event::End(Tag::Code)
| Event::InlineHtml(_)
| Event::Text(_) => true,
_ => false,
});
// render markdown to html
let mut markdown_parsed_name = String::with_capacity(name.len() * 3 / 2);
html::push_html(&mut markdown_parsed_name, parser);
// write to the handlebars template
rc.writer.write_all(markdown_parsed_name.as_bytes())?;
}
if path_exists {
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"</a>")?;
}
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"</li>")?;
}
while current_level > 1 {
Improve accessibility (#535) * fix(theme/index): Use nav element for Table of Content * fix(renderer/html_handlebars/helpers/toc): Use ol instead of ul Chapters and sections are ordered, so we should use the appropriate HTML tag. * fix(renderer/html_handlebars/helpers/toc): Hide section number from screen readers Screen readers have this functionality build-in, no need to present this. Ideally, this should not even be in the DOM tree, since the numbers can be shown by using CSS. * fix(theme/index): Remove tabIndex="-1" from .page Divs are not focusable by default * fix(theme): Make sidebar accessible Using aria-hidden (together with tabIndex) takes the links out of the tab order. http://heydonworks.com/practical_aria_examples/#progressive-collapsibles * fix(theme/index): Wrap content inside main tag The main tag helps users skip additional content on the page. * fix(theme/book): Don't focus .page on page load The main content is identified by the main tag, not by auto-focusing it on page load. * fix(theme/index): Make page controls accessible * fix: Make theme selector accessible - Use ul and li (since it is a list) - Add aria-expanded and aria-haspopup to the toggle button - Use button instead of div (buttons are accessible by default) - Handle Esc key (close popup) - Adjust CSS to keep same visual style * fix(theme/stylus/sidebar): Make link clickable area wider Links now expand to fill the entire row. * fix(theme): Wrap header buttons and improve animation performance Previously, the header had a fixed height, which meant that sometimes the print button was not visible. Animating the left property is expensive, which lead to laggy animations - transform is much cheaper and has the same effect. * fix(theme/stylus/theme-popup): Theme button inherits color Bug introduced while making the popup accessible * fix(theme/book): Handle edge case when toggling sidebar Bug introduced when switching from animating left to using transform.
2018-01-15 14:26:53 +01:00
rc.writer.write_all(b"</ol>")?;
2017-06-27 09:08:58 +02:00
rc.writer.write_all(b"</li>")?;
current_level -= 1;
}
Improve accessibility (#535) * fix(theme/index): Use nav element for Table of Content * fix(renderer/html_handlebars/helpers/toc): Use ol instead of ul Chapters and sections are ordered, so we should use the appropriate HTML tag. * fix(renderer/html_handlebars/helpers/toc): Hide section number from screen readers Screen readers have this functionality build-in, no need to present this. Ideally, this should not even be in the DOM tree, since the numbers can be shown by using CSS. * fix(theme/index): Remove tabIndex="-1" from .page Divs are not focusable by default * fix(theme): Make sidebar accessible Using aria-hidden (together with tabIndex) takes the links out of the tab order. http://heydonworks.com/practical_aria_examples/#progressive-collapsibles * fix(theme/index): Wrap content inside main tag The main tag helps users skip additional content on the page. * fix(theme/book): Don't focus .page on page load The main content is identified by the main tag, not by auto-focusing it on page load. * fix(theme/index): Make page controls accessible * fix: Make theme selector accessible - Use ul and li (since it is a list) - Add aria-expanded and aria-haspopup to the toggle button - Use button instead of div (buttons are accessible by default) - Handle Esc key (close popup) - Adjust CSS to keep same visual style * fix(theme/stylus/sidebar): Make link clickable area wider Links now expand to fill the entire row. * fix(theme): Wrap header buttons and improve animation performance Previously, the header had a fixed height, which meant that sometimes the print button was not visible. Animating the left property is expensive, which lead to laggy animations - transform is much cheaper and has the same effect. * fix(theme/stylus/theme-popup): Theme button inherits color Bug introduced while making the popup accessible * fix(theme/book): Handle edge case when toggling sidebar Bug introduced when switching from animating left to using transform.
2018-01-15 14:26:53 +01:00
rc.writer.write_all(b"</ol>")?;
Ok(())
}
}