Skip to content

Commit 035cb09

Browse files
committed
reveal: apply center class
1 parent 73a3d83 commit 035cb09

File tree

2 files changed

+113
-92
lines changed

2 files changed

+113
-92
lines changed

src/format/reveal/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const kSlideFooter = "footer";
1313
export const kHashType = "hash-type";
1414
export const kScrollable = "scrollable";
1515
export const kSmaller = "smaller";
16+
export const kCenter = "center";
1617
export const kCenterTitleSlide = "center-title-slide";
1718
export const kControlsAuto = "controlsAuto";
1819
export const kPreviewLinksAuto = "previewLinksAuto";

src/format/reveal/format-reveal.ts

Lines changed: 112 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
kAutoAnimateEasing,
5454
kAutoAnimateUnmatched,
5555
kAutoStretch,
56+
kCenter,
5657
kCenterTitleSlide,
5758
kControlsAuto,
5859
kHashType,
@@ -154,24 +155,32 @@ export function revealjsFormat() {
154155
// start with html format extras and our standard & plugin extras
155156
let extras = mergeConfigs(
156157
// extras for all html formats
157-
await htmlFormatExtras(input, flags, offset, format, temp, {
158-
tabby: true,
159-
anchors: false,
160-
copyCode: true,
161-
hoverCitations: true,
162-
hoverFootnotes: true,
163-
figResponsive: false,
164-
}, // tippy options
165-
{
166-
theme: "quarto-reveal",
167-
parent: "section.slide",
168-
config: {
169-
offset: [0, 0],
170-
maxWidth: 700,
158+
await htmlFormatExtras(
159+
input,
160+
flags,
161+
offset,
162+
format,
163+
temp,
164+
{
165+
tabby: true,
166+
anchors: false,
167+
copyCode: true,
168+
hoverCitations: true,
169+
hoverFootnotes: true,
170+
figResponsive: false,
171+
}, // tippy options
172+
{
173+
theme: "quarto-reveal",
174+
parent: "section.slide",
175+
config: {
176+
offset: [0, 0],
177+
maxWidth: 700,
178+
},
179+
},
180+
{
181+
quartoBase: false,
171182
},
172-
}, {
173-
quartoBase: false,
174-
}),
183+
),
175184
// default extras for reveal
176185
{
177186
args: [],
@@ -490,6 +499,14 @@ function revealHtmlPostprocessor(
490499
}
491500
}
492501

502+
// center other slides if requested
503+
if (format.metadata[kCenter] === true) {
504+
for (const slide of doc.querySelectorAll("section.slide")) {
505+
const slideEl = slide as Element;
506+
slideEl.classList.add("center");
507+
}
508+
}
509+
493510
// inject css to hide assistive mml in speaker notes (have to do it for each aside b/c the asides are
494511
// slurped into speaker mode one at a time using innerHTML) note that we can remvoe this hack when we begin
495512
// defaulting to MathJax 3 (after Pandoc updates their template to support Reveal 4.2 / MathJax 3)
@@ -651,97 +668,100 @@ function applyStretch(doc: Document, autoStretch: boolean) {
651668
const nodeEl = selNode;
652669

653670
// Do not apply stretch if this is an inline image among text
654-
if (!nodeEl || (nodeEl.nodeName === "P" && nodeEl.childNodes.length > 1)) {
671+
if (
672+
!nodeEl || (nodeEl.nodeName === "P" && nodeEl.childNodes.length > 1)
673+
) {
655674
continue;
656675
}
657676

658677
const hasStretchClass = function (el: Element): boolean {
659-
return el.classList.contains("stretch") || el.classList.contains("r-stretch");
678+
return el.classList.contains("stretch") ||
679+
el.classList.contains("r-stretch");
660680
};
661681

662682
// Only apply auto stretch on specific known structures
663683
// and avoid applying automatically on custom divs
664684
if (
665-
// on <p><img> (created by Pandoc)
666-
nodeEl.nodeName === "P" ||
667-
// on quarto figure divs
668-
nodeEl.nodeName === "DIV" && nodeEl.classList.contains("quarto-figure") ||
669-
// on computation output created image
670-
nodeEl.nodeName === "DIV" && nodeEl.classList.contains("cell") ||
671-
// on other divs (custom divs) when explicitly opt-in
672-
nodeEl.nodeName === "DIV" && hasStretchClass(nodeEl)
685+
// on <p><img> (created by Pandoc)
686+
nodeEl.nodeName === "P" ||
687+
// on quarto figure divs
688+
nodeEl.nodeName === "DIV" &&
689+
nodeEl.classList.contains("quarto-figure") ||
690+
// on computation output created image
691+
nodeEl.nodeName === "DIV" && nodeEl.classList.contains("cell") ||
692+
// on other divs (custom divs) when explicitly opt-in
693+
nodeEl.nodeName === "DIV" && hasStretchClass(nodeEl)
673694
) {
695+
// for custom divs, remove stretch class as it should only be present on img
696+
if (nodeEl.nodeName === "DIV" && hasStretchClass(nodeEl)) {
697+
nodeEl.classList.remove("r-stretch");
698+
nodeEl.classList.remove("stretch");
699+
}
674700

675-
// for custom divs, remove stretch class as it should only be present on img
676-
if (nodeEl.nodeName === "DIV" && hasStretchClass(nodeEl)) {
677-
nodeEl.classList.remove("r-stretch")
678-
nodeEl.classList.remove("stretch")
679-
}
680-
681-
// add stretch class if not already when auto-stretch is set
682-
if (
683-
autoStretch === true &&
684-
!hasStretchClass(imageEl) &&
685-
// if height is already set, we do nothing
686-
!imageEl.getAttribute("style")?.match("height:") &&
687-
!imageEl.hasAttribute("height")
688-
) {
689-
imageEl.classList.add("r-stretch");
690-
}
701+
// add stretch class if not already when auto-stretch is set
702+
if (
703+
autoStretch === true &&
704+
!hasStretchClass(imageEl) &&
705+
// if height is already set, we do nothing
706+
!imageEl.getAttribute("style")?.match("height:") &&
707+
!imageEl.hasAttribute("height")
708+
) {
709+
imageEl.classList.add("r-stretch");
710+
}
691711

692-
// If <img class="stetch"> is not a direct child of <section>, move it
693-
if (
694-
hasStretchClass(imageEl) &&
695-
imageEl.parentNode?.nodeName !== "SECTION"
696-
) {
697-
// Remove element then maybe remove its parents if empty
698-
const removeEmpty = function (el: Element) {
699-
const parentEl = el.parentElement;
700-
parentEl?.removeChild(el);
701-
if (
702-
parentEl?.innerText.trim() === "" &&
703-
// Stop at section leveal and do not remove empty slides
704-
parentEl?.nodeName !== "SECTION"
705-
) {
706-
removeEmpty(parentEl);
707-
}
708-
};
709-
710-
// Figure environment ? Get caption and alignment
711-
const quartoFig = slideEl.querySelector("div.quarto-figure");
712-
const caption = doc.createElement("p");
713-
if (quartoFig) {
714-
// Get alignment
715-
const align = quartoFig.className.match(
716-
"quarto-figure-(center|left|right)",
717-
);
718-
if (align) imageEl.classList.add(align[0]);
719-
// Get Caption
720-
const figCaption = nodeEl.querySelector("figcaption");
721-
if (figCaption) {
722-
caption.classList.add("caption");
723-
caption.innerHTML = figCaption.innerHTML;
724-
}
712+
// If <img class="stetch"> is not a direct child of <section>, move it
713+
if (
714+
hasStretchClass(imageEl) &&
715+
imageEl.parentNode?.nodeName !== "SECTION"
716+
) {
717+
// Remove element then maybe remove its parents if empty
718+
const removeEmpty = function (el: Element) {
719+
const parentEl = el.parentElement;
720+
parentEl?.removeChild(el);
721+
if (
722+
parentEl?.innerText.trim() === "" &&
723+
// Stop at section leveal and do not remove empty slides
724+
parentEl?.nodeName !== "SECTION"
725+
) {
726+
removeEmpty(parentEl);
725727
}
728+
};
726729

727-
// Target position of image
728-
// first level after the element
729-
const nextEl = nodeEl.nextElementSibling;
730-
// Remove image from its parent
731-
removeEmpty(imageEl);
732-
// insert at target position
733-
slideEl.insertBefore(image, nextEl);
734-
735-
// If there was a caption processed add it after
736-
if (caption.classList.contains("caption")) {
737-
slideEl.insertBefore(
738-
caption,
739-
imageEl.nextElementSibling,
740-
);
730+
// Figure environment ? Get caption and alignment
731+
const quartoFig = slideEl.querySelector("div.quarto-figure");
732+
const caption = doc.createElement("p");
733+
if (quartoFig) {
734+
// Get alignment
735+
const align = quartoFig.className.match(
736+
"quarto-figure-(center|left|right)",
737+
);
738+
if (align) imageEl.classList.add(align[0]);
739+
// Get Caption
740+
const figCaption = nodeEl.querySelector("figcaption");
741+
if (figCaption) {
742+
caption.classList.add("caption");
743+
caption.innerHTML = figCaption.innerHTML;
741744
}
742-
// Remove container if still there
743-
if (quartoFig) removeEmpty(quartoFig);
744745
}
746+
747+
// Target position of image
748+
// first level after the element
749+
const nextEl = nodeEl.nextElementSibling;
750+
// Remove image from its parent
751+
removeEmpty(imageEl);
752+
// insert at target position
753+
slideEl.insertBefore(image, nextEl);
754+
755+
// If there was a caption processed add it after
756+
if (caption.classList.contains("caption")) {
757+
slideEl.insertBefore(
758+
caption,
759+
imageEl.nextElementSibling,
760+
);
761+
}
762+
// Remove container if still there
763+
if (quartoFig) removeEmpty(quartoFig);
764+
}
745765
}
746766
}
747767
}

0 commit comments

Comments
 (0)