Merge pull request #2893 from ehuss/fix-fold-sub-chapter
Fix heading nav with folded chapters
This commit is contained in:
commit
7b7dee4a4e
20 changed files with 212 additions and 127 deletions
|
|
@ -571,17 +571,18 @@ html:not(.sidebar-resizing) .sidebar {
|
||||||
line-height: 2.2em;
|
line-height: 2.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapter ol {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chapter li {
|
.chapter li {
|
||||||
display: flex;
|
|
||||||
color: var(--sidebar-non-existant);
|
color: var(--sidebar-non-existant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is a span wrapping the chapter link and the fold chevron. */
|
||||||
|
.chapter-link-wrapper {
|
||||||
|
/* Used to position the chevron to the right, allowing the text to wrap before it. */
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.chapter li a {
|
.chapter li a {
|
||||||
display: block;
|
/* Remove underlines. */
|
||||||
padding: 0;
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--sidebar-fg);
|
color: var(--sidebar-fg);
|
||||||
}
|
}
|
||||||
|
|
@ -594,21 +595,22 @@ html:not(.sidebar-resizing) .sidebar {
|
||||||
color: var(--sidebar-active);
|
color: var(--sidebar-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapter li > a.toggle {
|
/* This is the toggle chevron. */
|
||||||
|
.chapter-fold-toggle {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: block;
|
/* Positions the chevron to the side. */
|
||||||
margin-inline-start: auto;
|
margin-inline-start: auto;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
opacity: 0.68;
|
opacity: 0.68;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapter li > a.toggle div {
|
.chapter-fold-toggle div {
|
||||||
transition: transform 0.5s;
|
transition: transform 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* collapse the section */
|
/* collapse the section */
|
||||||
.chapter li:not(.expanded) + li > ol {
|
.chapter li:not(.expanded) > ol {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -617,10 +619,12 @@ html:not(.sidebar-resizing) .sidebar {
|
||||||
margin-block-start: 0.6em;
|
margin-block-start: 0.6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapter li.expanded > a.toggle div {
|
/* When expanded, rotate the chevron to point down. */
|
||||||
|
.chapter li.expanded > span > .chapter-fold-toggle div {
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Horizontal line in chapter list. */
|
||||||
.spacer {
|
.spacer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
|
|
@ -630,6 +634,7 @@ html:not(.sidebar-resizing) .sidebar {
|
||||||
background-color: var(--sidebar-spacer);
|
background-color: var(--sidebar-spacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* On touch devices, add more vertical spacing to make it easier to tap links. */
|
||||||
@media (-moz-touch-enabled: 1), (pointer: coarse) {
|
@media (-moz-touch-enabled: 1), (pointer: coarse) {
|
||||||
.chapter li a { padding: 5px 0; }
|
.chapter li a { padding: 5px 0; }
|
||||||
.spacer { margin: 10px 0; }
|
.spacer { margin: 10px 0; }
|
||||||
|
|
@ -741,7 +746,6 @@ html:not(.sidebar-resizing) .sidebar {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -16px;
|
left: -16px;
|
||||||
top: 0;
|
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,9 @@ class MDBookSidebarScrollbox extends HTMLElement {
|
||||||
&& current_page.endsWith('/index.html')) {
|
&& current_page.endsWith('/index.html')) {
|
||||||
link.classList.add('active');
|
link.classList.add('active');
|
||||||
let parent = link.parentElement;
|
let parent = link.parentElement;
|
||||||
if (parent && parent.classList.contains('chapter-item')) {
|
|
||||||
parent.classList.add('expanded');
|
|
||||||
}
|
|
||||||
while (parent) {
|
while (parent) {
|
||||||
if (parent.tagName === 'LI' && parent.previousElementSibling) {
|
if (parent.tagName === 'LI' && parent.classList.contains('chapter-item')) {
|
||||||
if (parent.previousElementSibling.classList.contains('chapter-item')) {
|
parent.classList.add('expanded');
|
||||||
parent.previousElementSibling.classList.add('expanded');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
parent = parent.parentElement;
|
parent = parent.parentElement;
|
||||||
}
|
}
|
||||||
|
|
@ -62,9 +57,9 @@ class MDBookSidebarScrollbox extends HTMLElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Toggle buttons
|
// Toggle buttons
|
||||||
const sidebarAnchorToggles = document.querySelectorAll('#mdbook-sidebar a.toggle');
|
const sidebarAnchorToggles = document.querySelectorAll('.chapter-fold-toggle');
|
||||||
function toggleSection(ev) {
|
function toggleSection(ev) {
|
||||||
ev.currentTarget.parentElement.classList.toggle('expanded');
|
ev.currentTarget.parentElement.parentElement.classList.toggle('expanded');
|
||||||
}
|
}
|
||||||
Array.from(sidebarAnchorToggles).forEach(el => {
|
Array.from(sidebarAnchorToggles).forEach(el => {
|
||||||
el.addEventListener('click', toggleSection);
|
el.addEventListener('click', toggleSection);
|
||||||
|
|
@ -237,17 +232,12 @@ window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox)
|
||||||
// be expanded.
|
// be expanded.
|
||||||
function updateHeaderExpanded(currentA) {
|
function updateHeaderExpanded(currentA) {
|
||||||
// Add expanded to all header-item li ancestors.
|
// Add expanded to all header-item li ancestors.
|
||||||
let current = currentA.parentElement.parentElement.parentElement;
|
let current = currentA.parentElement;
|
||||||
while (current.tagName === 'LI') {
|
while (current) {
|
||||||
const prevSibling = current.previousElementSibling;
|
if (current.tagName === 'LI' && current.classList.contains('header-item')) {
|
||||||
if (prevSibling !== null
|
current.classList.add('expanded');
|
||||||
&& prevSibling.tagName === 'LI'
|
|
||||||
&& prevSibling.classList.contains('header-item')) {
|
|
||||||
prevSibling.classList.add('expanded');
|
|
||||||
current = prevSibling.parentElement.parentElement;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
current = current.parentElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,19 +333,6 @@ window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox)
|
||||||
if (activeSection === null) {
|
if (activeSection === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const activeItem = activeSection.parentElement;
|
|
||||||
const activeList = activeItem.parentElement;
|
|
||||||
|
|
||||||
// Build a tree of headers in the sidebar.
|
|
||||||
const rootLi = document.createElement('li');
|
|
||||||
rootLi.classList.add('header-item');
|
|
||||||
rootLi.classList.add('expanded');
|
|
||||||
const rootOl = document.createElement('ol');
|
|
||||||
rootOl.classList.add('section');
|
|
||||||
rootLi.appendChild(rootOl);
|
|
||||||
const stack = [{ level: 0, ol: rootOl }];
|
|
||||||
// The level where it will start folding deeply nested headers.
|
|
||||||
const foldLevel = 3;
|
|
||||||
|
|
||||||
const main = document.getElementsByTagName('main')[0];
|
const main = document.getElementsByTagName('main')[0];
|
||||||
headers = Array.from(main.querySelectorAll('h2, h3, h4, h5, h6'))
|
headers = Array.from(main.querySelectorAll('h2, h3, h4, h5, h6'))
|
||||||
|
|
@ -365,57 +342,90 @@ window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build a tree of headers in the sidebar.
|
||||||
|
|
||||||
|
const stack = [];
|
||||||
|
|
||||||
|
const firstLevel = parseInt(headers[0].tagName.charAt(1));
|
||||||
|
for (let i = 1; i < firstLevel; i++) {
|
||||||
|
const ol = document.createElement('ol');
|
||||||
|
ol.classList.add('section');
|
||||||
|
if (stack.length > 0) {
|
||||||
|
stack[stack.length - 1].ol.appendChild(ol);
|
||||||
|
}
|
||||||
|
stack.push({level: i + 1, ol: ol});
|
||||||
|
}
|
||||||
|
|
||||||
|
// The level where it will start folding deeply nested headers.
|
||||||
|
const foldLevel = 3;
|
||||||
|
|
||||||
for (let i = 0; i < headers.length; i++) {
|
for (let i = 0; i < headers.length; i++) {
|
||||||
const header = headers[i];
|
const header = headers[i];
|
||||||
const level = parseInt(header.tagName.charAt(1));
|
const level = parseInt(header.tagName.charAt(1));
|
||||||
|
|
||||||
|
const currentLevel = stack[stack.length - 1].level;
|
||||||
|
if (level > currentLevel) {
|
||||||
|
// Begin nesting to this level.
|
||||||
|
for (let nextLevel = currentLevel + 1; nextLevel <= level; nextLevel++) {
|
||||||
|
const ol = document.createElement('ol');
|
||||||
|
ol.classList.add('section');
|
||||||
|
const last = stack[stack.length - 1];
|
||||||
|
const lastChild = last.ol.lastChild;
|
||||||
|
// Handle the case where jumping more than one nesting
|
||||||
|
// level, which doesn't have a list item to place this new
|
||||||
|
// list inside of.
|
||||||
|
if (lastChild) {
|
||||||
|
lastChild.appendChild(ol);
|
||||||
|
} else {
|
||||||
|
last.ol.appendChild(ol);
|
||||||
|
}
|
||||||
|
stack.push({level: nextLevel, ol: ol});
|
||||||
|
}
|
||||||
|
} else if (level < currentLevel) {
|
||||||
|
while (stack.length > 1 && stack[stack.length - 1].level >= level) {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
li.classList.add('header-item');
|
li.classList.add('header-item');
|
||||||
li.classList.add('expanded');
|
li.classList.add('expanded');
|
||||||
if (level < foldLevel) {
|
if (level < foldLevel) {
|
||||||
li.classList.add('expanded');
|
li.classList.add('expanded');
|
||||||
}
|
}
|
||||||
|
const span = document.createElement('span');
|
||||||
|
span.classList.add('chapter-link-wrapper');
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
|
span.appendChild(a);
|
||||||
a.href = '#' + header.id;
|
a.href = '#' + header.id;
|
||||||
a.classList.add('header-in-summary');
|
a.classList.add('header-in-summary');
|
||||||
a.innerHTML = header.children[0].innerHTML;
|
a.innerHTML = header.children[0].innerHTML;
|
||||||
a.addEventListener('click', headerThresholdClick);
|
a.addEventListener('click', headerThresholdClick);
|
||||||
li.appendChild(a);
|
|
||||||
const nextHeader = headers[i + 1];
|
const nextHeader = headers[i + 1];
|
||||||
if (nextHeader !== undefined) {
|
if (nextHeader !== undefined) {
|
||||||
const nextLevel = parseInt(nextHeader.tagName.charAt(1));
|
const nextLevel = parseInt(nextHeader.tagName.charAt(1));
|
||||||
if (nextLevel > level && level >= foldLevel) {
|
if (nextLevel > level && level >= foldLevel) {
|
||||||
const div = document.createElement('div');
|
|
||||||
div.textContent = '❱';
|
|
||||||
const toggle = document.createElement('a');
|
const toggle = document.createElement('a');
|
||||||
toggle.classList.add('toggle');
|
toggle.classList.add('chapter-fold-toggle');
|
||||||
toggle.classList.add('header-toggle');
|
toggle.classList.add('header-toggle');
|
||||||
toggle.appendChild(div);
|
|
||||||
toggle.addEventListener('click', () => {
|
toggle.addEventListener('click', () => {
|
||||||
li.classList.toggle('expanded');
|
li.classList.toggle('expanded');
|
||||||
});
|
});
|
||||||
li.appendChild(toggle);
|
const toggleDiv = document.createElement('div');
|
||||||
|
toggleDiv.textContent = '❱';
|
||||||
|
toggle.appendChild(toggleDiv);
|
||||||
|
span.appendChild(toggle);
|
||||||
headerToggles.push(li);
|
headerToggles.push(li);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
li.appendChild(span);
|
||||||
// Find the appropriate parent level.
|
|
||||||
while (stack.length > 1 && stack[stack.length - 1].level >= level) {
|
|
||||||
stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentParent = stack[stack.length - 1];
|
const currentParent = stack[stack.length - 1];
|
||||||
currentParent.ol.appendChild(li);
|
currentParent.ol.appendChild(li);
|
||||||
|
|
||||||
// Create new nested ol for potential children.
|
|
||||||
const nestedOl = document.createElement('ol');
|
|
||||||
nestedOl.classList.add('section');
|
|
||||||
const nestedLi = document.createElement('li');
|
|
||||||
nestedLi.appendChild(nestedOl);
|
|
||||||
currentParent.ol.appendChild(nestedLi);
|
|
||||||
stack.push({ level: level, ol: nestedOl });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activeList.insertBefore(rootLi, activeItem.nextSibling);
|
const activeItemSpan = activeSection.parentElement;
|
||||||
|
activeItemSpan.after(stack[0].ol);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', reloadCurrentHeader);
|
document.addEventListener('DOMContentLoaded', reloadCurrentHeader);
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,13 @@ impl HelperDef for RenderToc {
|
||||||
out.write("<ol class=\"chapter\">")?;
|
out.write("<ol class=\"chapter\">")?;
|
||||||
|
|
||||||
let mut current_level = 1;
|
let mut current_level = 1;
|
||||||
|
let mut first = true;
|
||||||
|
|
||||||
for item in chapters {
|
for item in chapters {
|
||||||
let (_section, level) = if let Some(s) = item.get("section") {
|
let level = item
|
||||||
(s.as_str(), s.matches('.').count())
|
.get("section")
|
||||||
} else {
|
.map(|s| s.matches('.').count())
|
||||||
("", 1)
|
.unwrap_or(1);
|
||||||
};
|
|
||||||
|
|
||||||
// Expand if folding is disabled, or if levels that are larger than this would not
|
// Expand if folding is disabled, or if levels that are larger than this would not
|
||||||
// be folded.
|
// be folded.
|
||||||
|
|
@ -71,25 +71,31 @@ impl HelperDef for RenderToc {
|
||||||
|
|
||||||
match level.cmp(¤t_level) {
|
match level.cmp(¤t_level) {
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
while level > current_level {
|
// There is an assumption that when descending, it can
|
||||||
out.write("<li>")?;
|
// only go one level down at a time. This should be
|
||||||
out.write("<ol class=\"section\">")?;
|
// enforced by the nature of markdown lists and the
|
||||||
current_level += 1;
|
// summary parser.
|
||||||
}
|
assert_eq!(level, current_level + 1);
|
||||||
write_li_open_tag(out, is_expanded, false)?;
|
current_level += 1;
|
||||||
|
out.write("<ol class=\"section\">")?;
|
||||||
|
write_li_open_tag(out, is_expanded)?;
|
||||||
}
|
}
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
while level < current_level {
|
while level < current_level {
|
||||||
out.write("</ol>")?;
|
|
||||||
out.write("</li>")?;
|
out.write("</li>")?;
|
||||||
|
out.write("</ol>")?;
|
||||||
current_level -= 1;
|
current_level -= 1;
|
||||||
}
|
}
|
||||||
write_li_open_tag(out, is_expanded, false)?;
|
write_li_open_tag(out, is_expanded)?;
|
||||||
}
|
}
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
write_li_open_tag(out, is_expanded, !item.contains_key("section"))?;
|
if !first {
|
||||||
|
out.write("</li>")?;
|
||||||
|
}
|
||||||
|
write_li_open_tag(out, is_expanded)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
first = false;
|
||||||
|
|
||||||
// Spacer
|
// Spacer
|
||||||
if item.contains_key("spacer") {
|
if item.contains_key("spacer") {
|
||||||
|
|
@ -105,6 +111,8 @@ impl HelperDef for RenderToc {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.write("<span class=\"chapter-link-wrapper\">")?;
|
||||||
|
|
||||||
// Link
|
// Link
|
||||||
let path_exists = match item.get("path") {
|
let path_exists = match item.get("path") {
|
||||||
Some(path) if !path.is_empty() => {
|
Some(path) if !path.is_empty() => {
|
||||||
|
|
@ -121,7 +129,7 @@ impl HelperDef for RenderToc {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
out.write("<div>")?;
|
out.write("<span>")?;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -142,41 +150,35 @@ impl HelperDef for RenderToc {
|
||||||
if path_exists {
|
if path_exists {
|
||||||
out.write("</a>")?;
|
out.write("</a>")?;
|
||||||
} else {
|
} else {
|
||||||
out.write("</div>")?;
|
out.write("</span>")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render expand/collapse toggle
|
// Render expand/collapse toggle
|
||||||
if let Some(flag) = item.get("has_sub_items") {
|
if let Some(flag) = item.get("has_sub_items") {
|
||||||
let has_sub_items = flag.parse::<bool>().unwrap_or_default();
|
let has_sub_items = flag.parse::<bool>().unwrap_or_default();
|
||||||
if fold_enable && has_sub_items {
|
if fold_enable && has_sub_items {
|
||||||
out.write("<a class=\"toggle\"><div>❱</div></a>")?;
|
// The <div> here is to manage rotating the element when
|
||||||
|
// the chapter title is long and word-wraps.
|
||||||
|
out.write("<a class=\"chapter-fold-toggle\"><div>❱</div></a>")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.write("</li>")?;
|
out.write("</span>")?;
|
||||||
}
|
}
|
||||||
while current_level > 1 {
|
while current_level > 0 {
|
||||||
out.write("</ol>")?;
|
|
||||||
out.write("</li>")?;
|
out.write("</li>")?;
|
||||||
|
out.write("</ol>")?;
|
||||||
current_level -= 1;
|
current_level -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write("</ol>")?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_li_open_tag(
|
fn write_li_open_tag(out: &mut dyn Output, is_expanded: bool) -> Result<(), std::io::Error> {
|
||||||
out: &mut dyn Output,
|
|
||||||
is_expanded: bool,
|
|
||||||
is_affix: bool,
|
|
||||||
) -> Result<(), std::io::Error> {
|
|
||||||
let mut li = String::from("<li class=\"chapter-item ");
|
let mut li = String::from("<li class=\"chapter-item ");
|
||||||
if is_expanded {
|
if is_expanded {
|
||||||
li.push_str("expanded ");
|
li.push_str("expanded ");
|
||||||
}
|
}
|
||||||
if is_affix {
|
|
||||||
li.push_str("affix ");
|
|
||||||
}
|
|
||||||
li.push_str("\">");
|
li.push_str("\">");
|
||||||
out.write(&li)
|
out.write(&li)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
tests/gui/books/heading-nav-folded/book.toml
Normal file
6
tests/gui/books/heading-nav-folded/book.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
[book]
|
||||||
|
title = "heading-nav-folded"
|
||||||
|
|
||||||
|
[output.html.fold]
|
||||||
|
enable = true
|
||||||
|
level = 0
|
||||||
7
tests/gui/books/heading-nav-folded/src/SUMMARY.md
Normal file
7
tests/gui/books/heading-nav-folded/src/SUMMARY.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
- [Introduction](./intro.md)
|
||||||
|
- [Sub chapter](./sub/index.md)
|
||||||
|
- [Sub inner](./sub/inner/index.md)
|
||||||
|
- [Sub second chapter](./sub/second.md)
|
||||||
|
- [Next main chapter](./next-main.md)
|
||||||
9
tests/gui/books/heading-nav-folded/src/intro.md
Normal file
9
tests/gui/books/heading-nav-folded/src/intro.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
## Heading A
|
||||||
|
|
||||||
|
### Heading A2
|
||||||
|
|
||||||
|
### Heading A3
|
||||||
|
|
||||||
|
## Heading B
|
||||||
1
tests/gui/books/heading-nav-folded/src/next-main.md
Normal file
1
tests/gui/books/heading-nav-folded/src/next-main.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
# Next main chapter
|
||||||
3
tests/gui/books/heading-nav-folded/src/sub/index.md
Normal file
3
tests/gui/books/heading-nav-folded/src/sub/index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Sub chapter
|
||||||
|
|
||||||
|
## Sub-chapter heading
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Sub inner
|
||||||
|
|
||||||
|
## Inner chapter heading
|
||||||
3
tests/gui/books/heading-nav-folded/src/sub/second.md
Normal file
3
tests/gui/books/heading-nav-folded/src/sub/second.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Sub second chapter
|
||||||
|
|
||||||
|
## Second chapter heading
|
||||||
|
|
@ -6,3 +6,4 @@
|
||||||
- [Collapsed headings](collapsed.md)
|
- [Collapsed headings](collapsed.md)
|
||||||
- [Headings with markup](markup.md)
|
- [Headings with markup](markup.md)
|
||||||
- [Current scrolls to bottom](current-to-bottom.md)
|
- [Current scrolls to bottom](current-to-bottom.md)
|
||||||
|
- [Unusual heading levels](unusual-heading-levels.md)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Unusual heading levels
|
||||||
|
|
||||||
|
### Heading 3
|
||||||
|
|
||||||
|
## Heading 2
|
||||||
|
|
||||||
|
#### Heading 5
|
||||||
|
|
||||||
|
#### Heading 5.1
|
||||||
|
|
@ -3,49 +3,54 @@
|
||||||
set-window-size: (1400, 800)
|
set-window-size: (1400, 800)
|
||||||
go-to: |DOC_PATH| + "heading-nav/collapsed.html"
|
go-to: |DOC_PATH| + "heading-nav/collapsed.html"
|
||||||
|
|
||||||
assert-count: (".header-item", 12)
|
assert-count: (".header-item", 11)
|
||||||
assert-count: (".current-header", 1)
|
assert-count: (".current-header", 1)
|
||||||
assert-text: (".current-header", "Heading 1")
|
assert-text: (".current-header", "Heading 1")
|
||||||
// Collapsed elements do not have "expanded" class.
|
// Collapsed elements do not have "expanded" class.
|
||||||
assert-attribute: ("li:has(> a[href='#heading-12'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-12'])", {"class": "header-item"})
|
||||||
assert-attribute: ("li:has(> a[href='#heading-21'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-21'])", {"class": "header-item"})
|
||||||
|
|
||||||
// Click 1.2, doesn't change expanded.
|
// Click 1.2, expands it.
|
||||||
click: "a.header-in-summary[href='#heading-12']"
|
click: "a.header-in-summary[href='#heading-12']"
|
||||||
assert-attribute: ("li:has(> a[href='#heading-12'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-12'])", {"class": "header-item expanded"})
|
||||||
assert-attribute: ("li:has(> a[href='#heading-21'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-21'])", {"class": "header-item"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-12']]]/ol", {"display": "none"})
|
assert-css: ("//a[@href='#heading-12']/../following-sibling::ol", {"display": "block"})
|
||||||
// Click expand chevron.
|
|
||||||
// 1.2.1 and 1.2.2 should be visible
|
// Click 1.1, should collapse it.
|
||||||
|
click: "a.header-in-summary[href='#heading-11']"
|
||||||
|
assert-attribute: ("li:has(> span > a[href='#heading-12'])", {"class": "header-item"})
|
||||||
|
assert-attribute: ("li:has(> span > a[href='#heading-21'])", {"class": "header-item"})
|
||||||
|
assert-css: ("//a[@href='#heading-12']/../following-sibling::ol", {"display": "none"})
|
||||||
|
|
||||||
|
// Click the chevron, should expand it.
|
||||||
click: "a.header-in-summary[href='#heading-12'] ~ a.header-toggle"
|
click: "a.header-in-summary[href='#heading-12'] ~ a.header-toggle"
|
||||||
assert-attribute: ("li:has(> a[href='#heading-12'])", {"class": "header-item expanded"})
|
assert-attribute: ("li:has(> span > a[href='#heading-12'])", {"class": "header-item expanded"})
|
||||||
assert-attribute: ("li:has(> a[href='#heading-21'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-21'])", {"class": "header-item"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-12']]]/ol", {"display": "block"})
|
assert-css: ("//a[@href='#heading-12']/../following-sibling::ol", {"display": "block"})
|
||||||
|
|
||||||
// Click 1.3
|
// Click 1.3
|
||||||
click: "a.header-in-summary[href='#heading-13']"
|
click: "a.header-in-summary[href='#heading-13']"
|
||||||
// Everything should be collapsed
|
// Everything should be collapsed
|
||||||
assert-attribute: ("li:has(> a[href='#heading-12'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-12'])", {"class": "header-item"})
|
||||||
assert-attribute: ("li:has(> a[href='#heading-21'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-21'])", {"class": "header-item"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-12']]]/ol", {"display": "none"})
|
assert-css: ("//a[@href='#heading-12']/../following-sibling::ol", {"display": "none"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-21']]]/ol", {"display": "none"})
|
assert-css: ("//a[@href='#heading-21']/../following-sibling::ol", {"display": "none"})
|
||||||
|
assert-attribute: ("li:has(> span > a[href='#heading-12'])", {"class": "header-item"})
|
||||||
|
assert-attribute: ("li:has(> span > a[href='#heading-21'])", {"class": "header-item"})
|
||||||
|
assert-attribute: ("li:has(> span > a[href='#heading-211'])", {"class": "header-item"})
|
||||||
|
assert-attribute: ("li:has(> span > a[href='#heading-2111'])", {"class": "header-item"})
|
||||||
|
|
||||||
|
|
||||||
assert-attribute: ("li:has(> a[href='#heading-12'])", {"class": "header-item"})
|
|
||||||
assert-attribute: ("li:has(> a[href='#heading-21'])", {"class": "header-item"})
|
|
||||||
assert-attribute: ("li:has(> a[href='#heading-211'])", {"class": "header-item"})
|
|
||||||
assert-attribute: ("li:has(> a[href='#heading-2111'])", {"class": "header-item"})
|
|
||||||
// Scroll to bottom of page
|
// Scroll to bottom of page
|
||||||
press-key: 'PageDown'
|
press-key: 'PageDown'
|
||||||
press-key: 'PageDown'
|
press-key: 'PageDown'
|
||||||
press-key: 'PageDown'
|
press-key: 'PageDown'
|
||||||
press-key: 'PageDown'
|
press-key: 'PageDown'
|
||||||
// 2.1.1.1.1 should be visible, and all the chevrons should be open, and expanded should be on each one
|
// 2.1.1.1.1 should be visible, and all the chevrons should be open, and expanded should be on each one
|
||||||
assert-attribute: ("li:has(> a[href='#heading-12'])", {"class": "header-item"})
|
assert-attribute: ("li:has(> span > a[href='#heading-12'])", {"class": "header-item"})
|
||||||
assert-attribute: ("li:has(> a[href='#heading-21'])", {"class": "header-item expanded"})
|
assert-attribute: ("li:has(> span > a[href='#heading-21'])", {"class": "header-item expanded"})
|
||||||
assert-attribute: ("li:has(> a[href='#heading-211'])", {"class": "header-item expanded"})
|
assert-attribute: ("li:has(> span > a[href='#heading-211'])", {"class": "header-item expanded"})
|
||||||
assert-attribute: ("li:has(> a[href='#heading-2111'])", {"class": "header-item expanded"})
|
assert-attribute: ("li:has(> span > a[href='#heading-2111'])", {"class": "header-item expanded"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-12']]]/ol", {"display": "none"})
|
assert-css: ("//a[@href='#heading-12']/../following-sibling::ol", {"display": "none"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-21']]]/ol", {"display": "block"})
|
assert-css: ("//a[@href='#heading-21']/../following-sibling::ol", {"display": "block"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-211']]]/ol", {"display": "block"})
|
assert-css: ("//a[@href='#heading-211']/../following-sibling::ol", {"display": "block"})
|
||||||
assert-css: ("//li[preceding-sibling::li[1][a[@href='#heading-2111']]]/ol", {"display": "block"})
|
assert-css: ("//a[@href='#heading-2111']/../following-sibling::ol", {"display": "block"})
|
||||||
|
|
|
||||||
3
tests/gui/heading-nav-folded.goml
Normal file
3
tests/gui/heading-nav-folded.goml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
// Tests when chapter folding is enabled.
|
||||||
|
|
||||||
|
go-to: |DOC_PATH| + "heading-nav-folded/index.html"
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
set-window-size: (1400, 800)
|
set-window-size: (1400, 800)
|
||||||
go-to: |DOC_PATH| + "heading-nav/large-intro.html"
|
go-to: |DOC_PATH| + "heading-nav/large-intro.html"
|
||||||
assert-count: (".header-item", 2)
|
assert-count: (".header-item", 1)
|
||||||
assert-count: (".current-header", 0)
|
assert-count: (".current-header", 0)
|
||||||
|
|
||||||
scroll-to: "#first-header"
|
scroll-to: "#first-header"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set-window-size: (1400, 800)
|
set-window-size: (1400, 800)
|
||||||
go-to: |DOC_PATH| + "heading-nav/markup.html"
|
go-to: |DOC_PATH| + "heading-nav/markup.html"
|
||||||
|
|
||||||
assert-count: (".header-item", 5)
|
assert-count: (".header-item", 4)
|
||||||
assert-count: (".current-header", 1)
|
assert-count: (".current-header", 1)
|
||||||
assert-text: (".current-header", "Heading with code or italic or bold or strike")
|
assert-text: (".current-header", "Heading with code or italic or bold or strike")
|
||||||
assert-property: (".current-header", {"innerHTML": "Heading with <code>code</code> or <em>italic</em> or <strong>bold</strong> or <del>strike</del>"})
|
assert-property: (".current-header", {"innerHTML": "Heading with <code>code</code> or <em>italic</em> or <strong>bold</strong> or <del>strike</del>"})
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
set-window-size: (1400, 800)
|
set-window-size: (1400, 800)
|
||||||
go-to: |DOC_PATH| + "heading-nav/normal-intro.html"
|
go-to: |DOC_PATH| + "heading-nav/normal-intro.html"
|
||||||
assert-count: (".header-item", 4)
|
assert-count: (".header-item", 3)
|
||||||
assert-count: (".current-header", 1)
|
assert-count: (".current-header", 1)
|
||||||
assert-text: (".current-header", "The first heading")
|
assert-text: (".current-header", "The first heading")
|
||||||
|
|
||||||
|
|
|
||||||
7
tests/gui/heading-nav-unusual-levels.goml
Normal file
7
tests/gui/heading-nav-unusual-levels.goml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Tests for unusual heading levels
|
||||||
|
|
||||||
|
set-window-size: (1400, 800)
|
||||||
|
go-to: |DOC_PATH| + "heading-nav/unusual-heading-levels.html"
|
||||||
|
|
||||||
|
assert-property: ("//a[@href='unusual-heading-levels.html']/../following-sibling::ol", {"innerHTML": '<ol class="section"><li class="header-item expanded"><span class="chapter-link-wrapper"><a href="#heading-3" class="header-in-summary current-header">Heading 3</a></span></li></ol><li class="header-item expanded"><span class="chapter-link-wrapper"><a href="#heading-2" class="header-in-summary">Heading 2</a></span><ol class="section"><ol class="section"><li class="header-item expanded"><span class="chapter-link-wrapper"><a href="#heading-5" class="header-in-summary">Heading 5</a></span></li><li class="header-item expanded"><span class="chapter-link-wrapper"><a href="#heading-51" class="header-in-summary">Heading 5.1</a></span></li></ol></ol></li>'})
|
||||||
|
|
||||||
|
|
@ -20,16 +20,22 @@ fn readme_to_index() {
|
||||||
)
|
)
|
||||||
.check_toc_js(str![[r#"
|
.check_toc_js(str![[r#"
|
||||||
<ol class="chapter">
|
<ol class="chapter">
|
||||||
<li class="chapter-item expanded affix ">
|
<li class="chapter-item expanded ">
|
||||||
|
<span class="chapter-link-wrapper">
|
||||||
<a href="index.html">Intro</a>
|
<a href="index.html">Intro</a>
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="chapter-item expanded ">
|
<li class="chapter-item expanded ">
|
||||||
|
<span class="chapter-link-wrapper">
|
||||||
<a href="first/index.html">
|
<a href="first/index.html">
|
||||||
<strong aria-hidden="true">1.</strong> First</a>
|
<strong aria-hidden="true">1.</strong> First</a>
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="chapter-item expanded ">
|
<li class="chapter-item expanded ">
|
||||||
|
<span class="chapter-link-wrapper">
|
||||||
<a href="second/index.html">
|
<a href="second/index.html">
|
||||||
<strong aria-hidden="true">2.</strong> Second</a>
|
<strong aria-hidden="true">2.</strong> Second</a>
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
"#]]);
|
"#]]);
|
||||||
|
|
|
||||||
|
|
@ -148,16 +148,22 @@ fn summary_with_markdown_formatting() {
|
||||||
.check_toc_js(str![[r#"
|
.check_toc_js(str![[r#"
|
||||||
<ol class="chapter">
|
<ol class="chapter">
|
||||||
<li class="chapter-item expanded ">
|
<li class="chapter-item expanded ">
|
||||||
|
<span class="chapter-link-wrapper">
|
||||||
<a href="formatted-summary.html">
|
<a href="formatted-summary.html">
|
||||||
<strong aria-hidden="true">1.</strong> Italic code *escape* `escape2`</a>
|
<strong aria-hidden="true">1.</strong> Italic code *escape* `escape2`</a>
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="chapter-item expanded ">
|
<li class="chapter-item expanded ">
|
||||||
|
<span class="chapter-link-wrapper">
|
||||||
<a href="soft.html">
|
<a href="soft.html">
|
||||||
<strong aria-hidden="true">2.</strong> Soft line break</a>
|
<strong aria-hidden="true">2.</strong> Soft line break</a>
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="chapter-item expanded ">
|
<li class="chapter-item expanded ">
|
||||||
|
<span class="chapter-link-wrapper">
|
||||||
<a href="escaped-tag.html">
|
<a href="escaped-tag.html">
|
||||||
<strong aria-hidden="true">3.</strong> <escaped tag></a>
|
<strong aria-hidden="true">3.</strong> <escaped tag></a>
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
"#]])
|
"#]])
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue