Skip to content

Commit

Permalink
Merge pull request #10800 from quarto-dev/bugfix/issue-10340
Browse files Browse the repository at this point in the history
dashboard - build card title correctly in the presence of math and other markup
  • Loading branch information
cscheid authored Sep 20, 2024
2 parents db9b5be + 4cda934 commit d847388
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 7 deletions.
4 changes: 4 additions & 0 deletions news/changelog-1.6.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ All changes included in 1.6:
- ([#10328](https://github.com/quarto-dev/quarto-cli/issues/10328)): Interpret subcells as subfloats when subcap count matches subcell count.
- ([#10624](https://github.com/quarto-dev/quarto-cli/issues/10624)): Don't crash when proof environments are empty in `pdf`.

## `dashboard` Format

- ([#10340](https://github.com/quarto-dev/quarto-cli/issues/10340)): Build card title correctly in the presence of equations and other markup.

## `html` Format

- Fix `kbd` element styling on dark themes.
Expand Down
29 changes: 22 additions & 7 deletions src/format/dashboard/format-dashboard-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const kCardHeaderClass = "card-header";
const kCardFooterClass = "card-footer";
const kCardTitleClass = "card-title";
const kCardToolbarClass = "card-toolbar";
const kCardTitleToolbarClass = "card-title-toolbar";

const kCardSidebarClass = "card-sidebar";

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

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

for (const headerChildNode of cardHeaderEl.childNodes) {
const isText = (node: Node) => node.nodeType === Node.TEXT_NODE;
const isEmphasis = (node: Node) => node.nodeName === "EM";
const isBold = (node: Node) => node.nodeName === "STRONG";
const isMath = (node: Node) =>
node.nodeName === "SPAN" &&
(node as Element).classList.contains("math") &&
(node as Element).classList.contains("inline");

for (const headerChildNode of Array.from(cardHeaderEl.childNodes)) {
if (
headerChildNode.nodeType === Node.TEXT_NODE &&
headerChildNode.textContent.trim() !== ""
isText(headerChildNode) ||
isEmphasis(headerChildNode) ||
isBold(headerChildNode) ||
isMath(headerChildNode)
) {
looseText.push(headerChildNode.textContent.trim());
looseText.push(headerChildNode);
headerChildNode.parentNode?.removeChild(headerChildNode);
}
}
Expand All @@ -172,7 +181,13 @@ export function processCards(doc: Document, dashboardMeta: DashboardMeta) {
const classes = [kCardTitleClass];

const titleTextDiv = makeEl("DIV", { classes }, doc);
titleTextDiv.innerText = looseText.join(" ");
const innerSpan = makeEl("SPAN", {
attributes: { style: "display: inline" },
}, doc);
titleTextDiv.appendChild(innerSpan);
for (const node of looseText) {
innerSpan.appendChild(node);
}
if (cardToolbarEl) {
cardToolbarEl.insertBefore(titleTextDiv, cardToolbarEl.firstChild);
} else {
Expand Down
20 changes: 20 additions & 0 deletions tests/docs/smoke-all/2024/09/13/issue-10340.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: "Test Dashboard"
format: dashboard
_quarto:
tests:
dashboard:
ensureHtmlElements:
- []
-
- "div.card-header > span.math.inline"
- "div.card-header > em"
- "div.card-header > strong"
---

##
::: {.card title="Math $y=mx+b$ between *emphasized* and **bold** words"}

Math $y=mx+b$ between words

:::

0 comments on commit d847388

Please sign in to comment.