PageSourceSearch

https://soci231-w11.netlify.app/index_files/libs/revealjs/plugin/quarto-support/support.js

js soci231-w11.netlify.app collected 2026-10-03 11:26:06 UTC 11,430 bytes, 338 lines download raw bytes

1// catch all plugin for various quarto features
2window.QuartoSupport = function () {
3  function isPrintView() {
4    return /print-pdf/gi.test(window.location.search);
5  }
6
7  // helper for theme toggling
8  function toggleBackgroundTheme(el, onDarkBackground, onLightBackground) {
9    if (onDarkBackground) {
10      el.classList.add('has-dark-background')
11    } else {
12      el.classList.remove('has-dark-background')
13    }
14    if (onLightBackground) {
15      el.classList.add('has-light-background')
16    } else {
17      el.classList.remove('has-light-background')
18    }
19  }
20
21  // implement controlsAudo
22  function controlsAuto(deck) {
23    const config = deck.getConfig();
24    if (config.controlsAuto === true) {
25      const iframe = window.location !== window.parent.location;
26      const localhost =
27        window.location.hostname === "localhost" ||
28        window.location.hostname === "127.0.0.1";
29      deck.configure({
30        controls:
31          (iframe && !localhost) ||
32          (deck.hasVerticalSlides() && config.navigationMode !== "linear"),
33      });
34    }
35  }
36
37  // helper to provide event handlers for all links in a container
38  function handleLinkClickEvents(deck, container) {
39    Array.from(container.querySelectorAll("a")).forEach((el) => {
40      const url = el.getAttribute("href");
41      if (/^(http|www)/gi.test(url)) {
42        el.addEventListener(
43          "click",
44          (ev) => {
45            const fullscreen = !!window.document.fullscreen;
46            const dataPreviewLink = el.getAttribute("data-preview-link");
47
48            // if there is a local specifcation then use that
49            if (dataPreviewLink) {
50              if (
51                dataPreviewLink === "true" ||
52                (dataPreviewLink === "auto" && fullscreen)
53              ) {
54                ev.preventDefault();
55                deck.showPreview(url);
56                return false;
57              }
58            } else {
59              const previewLinks = !!deck.getConfig().previewLinks;
60              const previewLinksAuto =
61                deck.getConfig().previewLinksAuto === true;
62              if (previewLinks == true || (previewLinksAuto && fullscreen)) {
63                ev.preventDefault();
64                deck.showPreview(url);
65                return false;
66              }
67            }
68
69            // if the deck is in an iframe we want to open it externally
70            // (don't do this when in vscode though as it has its own
71            // handler for opening links externally that will be play)
72            const iframe = window.location !== window.parent.location;
73            if (
74              iframe &&
75              !window.location.search.includes("quartoPreviewReqId=")
76            ) {
77              ev.preventDefault();
78              ev.stopImmediatePropagation();
79              window.open(url, "_blank");
80              return false;
81            }
82
83            // if the user has set data-preview-link to "auto" we need to handle the event
84            // (because reveal will interpret "auto" as true)
85            if (dataPreviewLink === "auto") {
86              ev.preventDefault();
87              ev.stopImmediatePropagation();
88              const target =
89                el.getAttribute("target") ||
90                (ev.ctrlKey || ev.metaKey ? "_blank" : "");
91              if (target) {
92                window.open(url, target);
93              } else {
94                window.location.href = url;
95              }
96              return false;
97            }
98          },
99          false
100        );
101      }
102    });
103  }
104
105  // implement previewLinksAuto
106  function previewLinksAuto(deck) {
107    handleLinkClickEvents(deck, deck.getRevealElement());
108  }
109
110  // apply styles
111  function applyGlobalStyles(deck) {
112    if (deck.getConfig()["smaller"] === true) {
113      const revealParent = deck.getRevealElement();
114      revealParent.classList.add("smaller");
115    }
116  }
117
118  // add logo image
119  function addLogoImage(deck) {
120    const revealParent = deck.getRevealElement();
121    const logoImg = document.querySelector(".slide-logo");
122    if (logoImg) {
123      revealParent.appendChild(logoImg);
124      revealParent.classList.add("has-logo");
125    }
126  }
127
128  // tweak slide-number element
129  function tweakSlideNumber(deck) {
130    deck.on("slidechanged", function (ev) {
131      const revealParent = deck.getRevealElement();
132      const slideNumberEl = revealParent.querySelector(".slide-number");
133      const onDarkBackground = Reveal.getSlideBackground(ev.indexh, ev.indexv).classList.contains('has-dark-background');
134      const onLightBackground = Reveal.getSlideBackground(ev.indexh, ev.indexv).classList.contains('has-light-background');
135      toggleBackgroundTheme(slideNumberEl, onDarkBackground, onLightBackground);
136    })
137  }
138
139   // add footer text
140   function addFooter(deck) {
141    const revealParent = deck.getRevealElement();
142    const defaultFooterDiv = document.querySelector(".footer-default");
143    if (defaultFooterDiv) {
144      revealParent.appendChild(defaultFooterDiv);
145      handleLinkClickEvents(deck, defaultFooterDiv);
146      if (!isPrintView()) {
147        deck.on("slidechanged", function (ev) {
148          const prevSlideFooter = document.querySelector(
149            ".reveal > .footer:not(.footer-default)"
150          );
151          if (prevSlideFooter) {
152            prevSlideFooter.remove();
153          }
154          const currentSlideFooter = ev.currentSlide.querySelector(".footer");
155          const onDarkBackground = Reveal.getSlideBackground(ev.indexh, ev.indexv).classList.contains('has-dark-background')
156          const onLightBackground = Reveal.getSlideBackground(ev.indexh, ev.indexv).classList.contains('has-light-background')
157          if (currentSlideFooter) {
158            defaultFooterDiv.style.display = "none";
159            const slideFooter = currentSlideFooter.cloneNode(true);
160            handleLinkClickEvents(deck, slideFooter);
161            deck.getRevealElement().appendChild(slideFooter);
162            toggleBackgroundTheme(slideFooter, onDarkBackground, onLightBackground)
163          } else {
164            defaultFooterDiv.style.display = "block";
165            toggleBackgroundTheme(defaultFooterDiv, onDarkBackground, onLightBackground)
166          }
167        });
168      }
169    }
170  }
171
172  // add chalkboard buttons
173  function addChalkboardButtons(deck) {
174    const chalkboard = deck.getPlugin("RevealChalkboard");
175    if (chalkboard && !isPrintView()) {
176      const revealParent = deck.getRevealElement();
177      const chalkboardDiv = document.createElement("div");
178      chalkboardDiv.classList.add("slide-chalkboard-buttons");
179      if (document.querySelector(".slide-menu-button")) {
180        chalkboardDiv.classList.add("slide-menu-offset");
181      }
182      // add buttons
183      const buttons = [
184        {
185          icon: "easel2",
186          title: "Toggle Chalkboard (b)",
187          onclick: chalkboard.toggleChalkboard,
188        },
189        {
190          icon: "brush",
191          title: "Toggle Notes Canvas (c)",
192          onclick: chalkboard.toggleNotesCanvas,
193        },
194      ];
195      buttons.forEach(function (button) {
196        const span = document.createElement("span");
197        span.title = button.title;
198        const icon = document.createElement("i");
199        icon.classList.add("fas");
200        icon.classList.add("fa-" + button.icon);
201        span.appendChild(icon);
202        span.onclick = function (event) {
203          event.preventDefault();
204          button.onclick();
205        };
206        chalkboardDiv.appendChild(span);
207      });
208      revealParent.appendChild(chalkboardDiv);
209      const config = deck.getConfig();
210      if (!config.chalkboard.buttons) {
211        chalkboardDiv.classList.add("hidden");
212      }
213
214      // show and hide chalkboard buttons on slidechange
215      deck.on("slidechanged", function (ev) {
216        const config = deck.getConfig();
217        let buttons = !!config.chalkboard.buttons;
218        const slideButtons = ev.currentSlide.getAttribute(
219          "data-chalkboard-buttons"
220        );
221        if (slideButtons) {
222          if (slideButtons === "true" || slideButtons === "1") {
223            buttons = true;
224          } else if (slideButtons === "false" || slideButtons === "0") {
225            buttons = false;
226          }
227        }
228        if (buttons) {
229          chalkboardDiv.classList.remove("hidden");
230        } else {
231          chalkboardDiv.classList.add("hidden");
232        }
233      });
234    }
235  }
236
237  function handleTabbyClicks() {
238    const tabs = document.querySelectorAll(".panel-tabset-tabby > li > a");
239    for (let i = 0; i < tabs.length; i++) {
240      const tab = tabs[i];
241      tab.onclick = function (ev) {
242        ev.preventDefault();
243        ev.stopPropagation();
244        return false;
245      };
246    }
247  }
248
249  function fixupForPrint(deck) {
250    if (isPrintView()) {
251      const slides = deck.getSlides();
252      slides.forEach(function (slide) {
253        slide.removeAttribute("data-auto-animate");
254      });
255      window.document.querySelectorAll(".hljs").forEach(function (el) {
256        el.classList.remove("hljs");
257      });
258      window.document.querySelectorAll(".hljs-ln-code").forEach(function (el) {
259        el.classList.remove("hljs-ln-code");
260      });
261    }
262  }
263
264  function handleSlideChanges(deck) {
265    // dispatch for htmlwidgets
266    const fireSlideEnter = () => {
267      const event = window.document.createEvent("Event");
268      event.initEvent("slideenter", true, true);
269      window.document.dispatchEvent(event);
270    };
271
272    const fireSlideChanged = (previousSlide, currentSlide) => {
273      fireSlideEnter();
274
275      // dispatch for shiny
276      if (window.jQuery) {
277        if (previousSlide) {
278          window.jQuery(previousSlide).trigger("hidden");
279        }
280        if (currentSlide) {
281          window.jQuery(currentSlide).trigger("shown");
282        }
283      }
284    };
285
286    // fire slideEnter for tabby tab activations (for htmlwidget resize behavior)
287    document.addEventListener("tabby", fireSlideEnter, false);
288
289    deck.on("slidechanged", function (event) {
290      fireSlideChanged(event.previousSlide, event.currentSlide);
291    });
292  }
293
294  function workaroundMermaidDistance(deck) {
295    if (window.document.querySelector("pre.mermaid-js")) {
296      const slideCount = deck.getTotalSlides();
297      deck.configure({
298        mobileViewDistance: slideCount,
299        viewDistance: slideCount,
300      });
301    }
302  }
303
304  function handleWhiteSpaceInColumns(deck) {
305    for (const outerDiv of window.document.querySelectorAll("div.columns")) {
306      // remove all whitespace text nodes
307      // whitespace nodes cause the columns to be misaligned
308      // since they have inline-block layout
309      // 
310      // Quarto emits no whitespace nodes, but third-party tooling
311      // has bugs that can cause whitespace nodes to be emitted.
312      // See https://github.com/quarto-dev/quarto-cli/issues/8382
313      for (const node of outerDiv.childNodes) {
314        if (node.nodeType === 3 && node.nodeValue.trim() === "") {
315          outerDiv.removeChild(node);
316        }
317      }
318    }
319  }
320
321  return {
322    id: "quarto-support",
323    init: function (deck) {
324      controlsAuto(deck);
325      previewLinksAuto(deck);
326      fixupForPrint(deck);
327      applyGlobalStyles(deck);
328      addLogoImage(deck);
329      tweakSlideNumber(deck);
330      addFooter(deck);
331      addChalkboardButtons(deck);
332      handleTabbyClicks();
333      handleSlideChanges(deck);
334      workaroundMermaidDistance(deck);
335      handleWhiteSpaceInColumns(deck);
336    },
337  };
338};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.