Skip to content

Commit bd614a0

Browse files
committed
Add support for margin elements in HTML tabsets
Fixes #3280
1 parent 27258e4 commit bd614a0

File tree

3 files changed

+160
-2
lines changed

3 files changed

+160
-2
lines changed

src/format/html/format-html-bootstrap.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,9 @@ function processColumnElements(
676676
// Process margin elements that may appear in callouts
677677
processMarginElsInCallouts(doc);
678678

679+
// Process margin elements that may appear in tabsets
680+
processMarginElsInTabsets(doc);
681+
679682
// Group margin elements by their parents and wrap them in a container
680683
// Be sure to ignore containers which are already processed
681684
// and should be left alone
@@ -954,6 +957,53 @@ const processMarginElsInCallouts = (doc: Document) => {
954957
});
955958
};
956959

960+
const processMarginElsInTabsets = (doc: Document) => {
961+
// Move margin elements inside tabsets into a separate container that appears
962+
// before the tabset- this will hold the margin content
963+
// quarto.js will detect tab changed events and propery show and hide elements
964+
// by marking them with a collapse class.
965+
966+
const tabSetNodes = doc.querySelectorAll("div.panel-tabset");
967+
tabSetNodes.forEach((tabsetNode) => {
968+
const tabSetEl = tabsetNode as Element;
969+
const tabNodes = tabSetEl.querySelectorAll("div.tab-pane");
970+
971+
const marginEls: Element[] = [];
972+
let count = 0;
973+
tabNodes.forEach((tabNode) => {
974+
const tabEl = tabNode as Element;
975+
const tabId = tabEl.id;
976+
977+
const marginNodes = tabEl.querySelectorAll(
978+
".column-margin, aside, .aside",
979+
);
980+
981+
if (tabId && marginNodes.length > 0) {
982+
const marginArr = Array.from(marginNodes);
983+
marginArr.forEach((marginNode) => {
984+
const marginEl = marginNode as Element;
985+
marginEl.classList.add("tabset-margin-content");
986+
marginEl.classList.add(`${tabId}-tab-margin-content`);
987+
if (count > 0) {
988+
marginEl.classList.add("collapse");
989+
}
990+
marginEls.push(marginEl);
991+
});
992+
}
993+
count++;
994+
});
995+
996+
if (marginEls) {
997+
const containerEl = doc.createElement("div");
998+
containerEl.classList.add("tabset-margin-container");
999+
marginEls.forEach((marginEl) => {
1000+
containerEl.appendChild(marginEl);
1001+
});
1002+
tabSetEl.before(containerEl);
1003+
}
1004+
});
1005+
};
1006+
9571007
interface MarginNodeProcessor {
9581008
selector: string;
9591009
canProcess(el: Element): boolean;

src/resources/formats/html/quarto.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,44 @@ window.document.addEventListener("DOMContentLoaded", function (_event) {
461461
for (const tabEl of tabEls) {
462462
const id = tabEl.getAttribute("data-bs-target");
463463
if (id) {
464-
const columnEl = document.querySelector(`${id} .column-margin`);
464+
const columnEl = document.querySelector(
465+
`${id} .column-margin, .tabset-margin-content`
466+
);
465467
if (columnEl)
466-
tabEl.addEventListener("shown.bs.tab", function (_event) {
468+
tabEl.addEventListener("shown.bs.tab", function (event) {
469+
470+
const el = event.srcElement;
471+
if (el) {
472+
const visibleCls = `${el.id}-margin-content`;
473+
// walk up until we find a parent tabset
474+
let panelTabsetEl = el.parentElement;
475+
while (panelTabsetEl) {
476+
if (panelTabsetEl.classList.contains("panel-tabset")) {
477+
break;
478+
}
479+
panelTabsetEl = panelTabsetEl.parentElement;
480+
}
481+
482+
if (panelTabsetEl) {
483+
const prevSib = panelTabsetEl.previousElementSibling;
484+
if (
485+
prevSib &&
486+
prevSib.classList.contains("tabset-margin-container")
487+
) {
488+
const childNodes = prevSib.querySelectorAll(
489+
".tabset-margin-content"
490+
);
491+
for (const childEl of childNodes) {
492+
if (childEl.classList.contains(visibleCls)) {
493+
childEl.classList.remove("collapse");
494+
} else {
495+
childEl.classList.add("collapse");
496+
}
497+
}
498+
}
499+
}
500+
}
501+
467502
layoutMarginEls();
468503
});
469504
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
title: "column-margin Misplacement in panel-tabset Reproducible Example"
3+
format: html
4+
_quarto:
5+
tests:
6+
html:
7+
ensureHtmlElements:
8+
- [".tabset-margin-container .tabset-margin-content", ".tabset-margin-container .tabset-margin-content.collapse", ".column-container .callout-collapse"]
9+
---
10+
11+
## Header 1
12+
13+
::: {.panel-tabset}
14+
15+
### Subheader 1
16+
17+
::: {.column-margin}
18+
Margin Text 1
19+
:::
20+
21+
<!-- ![](https://quarto.org/docs/gallery/articles/advanced-layout-pdf.png) -->
22+
23+
### Subheader 2
24+
25+
::: {.column-margin}
26+
Margin Text 2
27+
:::
28+
29+
::: {.column-margin}
30+
Margin Text 3
31+
:::
32+
33+
34+
:::
35+
36+
37+
:::{.callout-note collapse=true}
38+
39+
## hi
40+
41+
This is a callout what is up bro
42+
43+
:::{.column-margin}
44+
This is margin content
45+
:::
46+
47+
48+
:::
49+
50+
51+
## Header 2
52+
53+
::: {.panel-tabset}
54+
55+
### Subheader 1
56+
57+
::: {.column-margin}
58+
Margin Text 1
59+
:::
60+
61+
<!-- ![](https://quarto.org/docs/gallery/articles/advanced-layout-pdf.png) -->
62+
63+
### Subheader 2
64+
65+
::: {.column-margin}
66+
Margin Text 2
67+
:::
68+
69+
::: {.column-margin}
70+
Margin Text 3
71+
:::
72+
73+
:::

0 commit comments

Comments
 (0)