Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions crates/mdbook-html/front-end/templates/toc.js.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -336,10 +336,17 @@ window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox)
});
}

// Takes the nodes from the given head and copies them over to the
// destination, along with some filtering.
// Takes the rendered content of the given heading and copies it over to
// the destination, along with some filtering.
function filterHeader(source, dest) {
const clone = source.cloneNode(true);
// Unwrap the injected permalink anchor (`<a class="header">`), keeping
// its children. When the heading itself is a link, the browser hoists
// that link out as a sibling of the (now empty) permalink anchor, so
// unwrapping here lets the actual heading text come through.
clone.querySelectorAll('a.header').forEach(headerLink => {
headerLink.replaceWith(...headerLink.childNodes);
});
clone.querySelectorAll('mark').forEach(mark => {
mark.replaceWith(...mark.childNodes);
});
Expand Down Expand Up @@ -418,7 +425,7 @@ window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox)
span.appendChild(a);
a.href = '#' + header.id;
a.classList.add('header-in-summary');
filterHeader(header.children[0], a);
filterHeader(header, a);
a.addEventListener('click', headerThresholdClick);
const nextHeader = headers[i + 1];
if (nextHeader !== undefined) {
Expand Down
4 changes: 4 additions & 0 deletions tests/gui/books/heading-nav/src/markup.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Basic markup should be copied.

Probably not super-wise to have headings with links, but at least they shouldn't explode.

## [link-only](../index.html)

A heading whose entire content is a link should still show its text in the sidebar.

## Heading with a custom id { #custom-id .custom-class }

Make sure navigation works on a custom id.
Expand Down
9 changes: 8 additions & 1 deletion tests/gui/heading-nav-markup.goml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
set-window-size: (1400, 800)
go-to: |DOC_PATH| + "heading-nav/markup.html"

assert-count: (".header-item", 4)
assert-count: (".header-item", 5)
assert-count: (".current-header", 1)
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>"})

// A heading that contains a link should keep its text (and the link) in the sidebar.
assert-text: ("a.header-in-summary[href='#heading-with-a-link']", "Heading with a link")
assert-property: ("a.header-in-summary[href='#heading-with-a-link']", {"innerHTML": "Heading with a <a href=\"../index.html\">link</a>"})

// A heading whose entire content is a link should still show its text.
assert-text: ("a.header-in-summary[href='#link-only']", "link-only")

// Clicking the custom one should work and should make it current.
click: "a.header-in-summary[href='#custom-id']"
assert-count: (".current-header", 1)
Expand Down
Loading