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
1 change: 1 addition & 0 deletions news/changelog-1.11.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ All changes included in 1.11:
- ([#14378](https://github.com/quarto-dev/quarto-cli/issues/14378)): Make scrollable code blocks and cell output keyboard-focusable in HTML output, so keyboard users can Tab to them and scroll with the arrow keys (axe rule `scrollable-region-focusable`, WCAG 2.1.1). While a region overflows it gets `tabindex="0"`, `role="group"`, and a localized `aria-label` (new `scrollable-code-label` and `scrollable-output-label` language keys, translated in all 34 built-in language files); when it fits again the attributes are removed. Chrome and Firefox already focus such regions natively; this adds Safari coverage and an accessible name.
- ([#14380](https://github.com/quarto-dev/quarto-cli/issues/14380)): Fix default listings rendering an empty, focusable subtitle link for posts without a subtitle, flagged by axe-core (`link-name`).
- ([#14795](https://github.com/quarto-dev/quarto-cli/issues/14795)): Fix keyboard focus in `revealjs` presentations reaching links and controls on nearby slides that are not shown. Tab now stays on the current slide, except in overview, scroll and print views where all slides are shown.
- ([#14844](https://github.com/quarto-dev/quarto-cli/issues/14844)): With `toc-location: left-body` or `right-body`, give the ids in the cloned body table of contents a `-body` suffix. The clone previously repeated every id from the sidebar copy, including the `toc-title` heading that `aria-labelledby` now points at.
- ([#14952](https://github.com/quarto-dev/quarto-cli/issues/14952)): Fix `revealjs` presentations disabling pinch-zoom on touch devices. The viewport `<meta>` tag no longer sets `maximum-scale=1.0` and `user-scalable=no`, which axe-core flagged (`meta-viewport`).
- ([#14968](https://github.com/quarto-dev/quarto-cli/issues/14968)): The header of notebook preview pages (back link, notebook title, download link) is now a navigation landmark named after the notebook, so it is reachable through landmark navigation and no longer flagged by axe-core (`region`).
- ([#14970](https://github.com/quarto-dev/quarto-cli/issues/14970)): Fix keyboard focus order of tabsets in `revealjs` presentations. Tab now follows the order of the slide: tabs and their panel content no longer come before other links on the slide, and two tabsets on the same slide are no longer mixed together.
Expand Down
33 changes: 33 additions & 0 deletions src/format/html/format-html-bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,11 +355,44 @@ function bootstrapHtmlPostprocessor(
// Leave it where it is in the document, and just mutate it
const clonedToc = toc.cloneNode(true) as Element;
clonedToc.id = "TOC-body";

const tocActionsEl = clonedToc.querySelector(".toc-actions");
if (tocActionsEl) {
tocActionsEl.remove();
}

// Ids must be unique, so the clone can't keep the originals: suffix
// every id it carries, and repoint its aria-labelledby at the renamed
// heading. Nothing outside the nav references these ids, and the
// originals stay on `toc`, so existing lookups resolve as before.
//
// A fixed suffix can still collide: headings "Setup" and "Setup Body"
// give `toc-setup` and `toc-setup-body`, so `toc-setup` + `-body` is
// already taken. Check each candidate against the document and the
// ids handed out so far, and append a counter until it is free.
const assignedIds = new Set<string>();
const uniqueBodyId = (id: string) => {
const base = `${id}-body`;
let candidate = base;
for (let n = 1; doc.getElementById(candidate) || assignedIds.has(candidate); n++) {
candidate = `${base}-${n}`;
}
assignedIds.add(candidate);
return candidate;
};
const renamedIds = new Map<string, string>();
const clonedIdEls = clonedToc.querySelectorAll("[id]");
for (let i = 0; i < clonedIdEls.length; i++) {
const clonedIdEl = clonedIdEls[i] as Element;
const newId = uniqueBodyId(clonedIdEl.id);
renamedIds.set(clonedIdEl.id, newId);
clonedIdEl.id = newId;
}
const clonedLabelId = clonedToc.getAttribute("aria-labelledby");
if (clonedLabelId && renamedIds.has(clonedLabelId)) {
clonedToc.setAttribute("aria-labelledby", renamedIds.get(clonedLabelId)!);
}

toc.parentElement?.insertBefore(clonedToc, toc);
}

Expand Down
5 changes: 4 additions & 1 deletion src/project/types/website/website-navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,10 @@ function makeBreadCrumbs(
navEl.classList.add(cls);
});
}
navEl.setAttribute("aria-label", language[kNavigationBreadcrumbsLabel]!);
navEl.setAttribute(
"aria-label",
language[kNavigationBreadcrumbsLabel] || "Breadcrumbs",
);

const olEl = doc.createElement("ol");
olEl.classList.add("breadcrumb");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,3 @@ if (nav.layout === "article" || nav.layout === "full") {




Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: 3473-toc-left-body-id-collision
format:
html:
toc: true
toc-location: left-body
toc-title: Contents
_quarto:
tests:
html:
ensureHtmlElements:
-
- "nav#TOC a#toc-setup"
- "nav#TOC a#toc-setup-body"
- "nav#TOC-body a#toc-setup-body-1"
- "nav#TOC-body a#toc-setup-body-body"
- []
ensureFileRegexMatches:
- []
- ['id="toc-setup-body"[\s\S]*id="toc-setup-body"']
---

The heading pair below slugs to `toc-setup` and `toc-setup-body`. A fixed
`-body` suffix on the cloned body TOC would hand `toc-setup` the id
`toc-setup-body`, which the sidebar TOC already holds (#14844).

# Setup

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

# Setup Body

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
9 changes: 9 additions & 0 deletions tests/docs/smoke-all/issues/3473-toc-side-body/left-body.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@ _quarto:
ensureHtmlElements:
-
- "nav#TOC.toc-active"
- "nav#TOC h2#toc-title"
- 'nav#TOC[aria-labelledby="toc-title"]'
- "nav#TOC-body"
- "nav#TOC-body h2#toc-title-body"
- 'nav#TOC-body[aria-labelledby="toc-title-body"]'
- "nav#TOC-body a#toc-section-1-body"
-
- "nav#TOC-body h2#toc-title"
- 'nav#TOC-body[aria-labelledby="toc-title"]'
- "nav#TOC-body a#toc-section-1"
---

# Section 1
Expand Down
9 changes: 9 additions & 0 deletions tests/docs/smoke-all/issues/3473-toc-side-body/right-body.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@ _quarto:
ensureHtmlElements:
-
- "nav#TOC.toc-active"
- "nav#TOC h2#toc-title"
- 'nav#TOC[aria-labelledby="toc-title"]'
- "nav#TOC-body"
- "nav#TOC-body h2#toc-title-body"
- 'nav#TOC-body[aria-labelledby="toc-title-body"]'
- "nav#TOC-body a#toc-section-1-body"
-
- "nav#TOC-body h2#toc-title"
- 'nav#TOC-body[aria-labelledby="toc-title"]'
- "nav#TOC-body a#toc-section-1"
---

# Section 1
Expand Down
Loading