Skip to content

Commit d847388

Browse files
authored
Merge pull request #10800 from quarto-dev/bugfix/issue-10340
dashboard - build card title correctly in the presence of math and other markup
2 parents db9b5be + 4cda934 commit d847388

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

news/changelog-1.6.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ All changes included in 1.6:
1212
- ([#10328](https://github.com/quarto-dev/quarto-cli/issues/10328)): Interpret subcells as subfloats when subcap count matches subcell count.
1313
- ([#10624](https://github.com/quarto-dev/quarto-cli/issues/10624)): Don't crash when proof environments are empty in `pdf`.
1414

15+
## `dashboard` Format
16+
17+
- ([#10340](https://github.com/quarto-dev/quarto-cli/issues/10340)): Build card title correctly in the presence of equations and other markup.
18+
1519
## `html` Format
1620

1721
- Fix `kbd` element styling on dark themes.

src/format/dashboard/format-dashboard-card.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ const kCardHeaderClass = "card-header";
4040
const kCardFooterClass = "card-footer";
4141
const kCardTitleClass = "card-title";
4242
const kCardToolbarClass = "card-toolbar";
43-
const kCardTitleToolbarClass = "card-title-toolbar";
4443

4544
const kCardSidebarClass = "card-sidebar";
4645

@@ -152,17 +151,27 @@ export function processCards(doc: Document, dashboardMeta: DashboardMeta) {
152151
if (cardHeaderEl) {
153152
// Loose text gets grouped into a div for alignment purposes
154153
// Always place this element first no matter what else is going on
155-
const looseText: string[] = [];
154+
const looseText: Node[] = [];
156155

157156
// See if there is a toolbar in the header
158157
const cardToolbarEl = cardHeaderEl.querySelector(`.${kCardToolbarClass}`);
159158

160-
for (const headerChildNode of cardHeaderEl.childNodes) {
159+
const isText = (node: Node) => node.nodeType === Node.TEXT_NODE;
160+
const isEmphasis = (node: Node) => node.nodeName === "EM";
161+
const isBold = (node: Node) => node.nodeName === "STRONG";
162+
const isMath = (node: Node) =>
163+
node.nodeName === "SPAN" &&
164+
(node as Element).classList.contains("math") &&
165+
(node as Element).classList.contains("inline");
166+
167+
for (const headerChildNode of Array.from(cardHeaderEl.childNodes)) {
161168
if (
162-
headerChildNode.nodeType === Node.TEXT_NODE &&
163-
headerChildNode.textContent.trim() !== ""
169+
isText(headerChildNode) ||
170+
isEmphasis(headerChildNode) ||
171+
isBold(headerChildNode) ||
172+
isMath(headerChildNode)
164173
) {
165-
looseText.push(headerChildNode.textContent.trim());
174+
looseText.push(headerChildNode);
166175
headerChildNode.parentNode?.removeChild(headerChildNode);
167176
}
168177
}
@@ -172,7 +181,13 @@ export function processCards(doc: Document, dashboardMeta: DashboardMeta) {
172181
const classes = [kCardTitleClass];
173182

174183
const titleTextDiv = makeEl("DIV", { classes }, doc);
175-
titleTextDiv.innerText = looseText.join(" ");
184+
const innerSpan = makeEl("SPAN", {
185+
attributes: { style: "display: inline" },
186+
}, doc);
187+
titleTextDiv.appendChild(innerSpan);
188+
for (const node of looseText) {
189+
innerSpan.appendChild(node);
190+
}
176191
if (cardToolbarEl) {
177192
cardToolbarEl.insertBefore(titleTextDiv, cardToolbarEl.firstChild);
178193
} else {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: "Test Dashboard"
3+
format: dashboard
4+
_quarto:
5+
tests:
6+
dashboard:
7+
ensureHtmlElements:
8+
- []
9+
-
10+
- "div.card-header > span.math.inline"
11+
- "div.card-header > em"
12+
- "div.card-header > strong"
13+
---
14+
15+
##
16+
::: {.card title="Math $y=mx+b$ between *emphasized* and **bold** words"}
17+
18+
Math $y=mx+b$ between words
19+
20+
:::

0 commit comments

Comments
 (0)