Moving My Website to Quarto

quarto
Author

Jihong Zhang

Published

June 25, 2023

Since June 25, 2023, I start to move my website from hugo/rmarkdown/blogdown/wowchemy to quarto website. It is difficult to explain why I spend so much time on that. Perhaps because some reasons same as other bloggers:

(1) Quarto is the next generation of rmarkdown.

(2) Quarto is independent with R or Rstudio.

(3) Quarto has a clean file tree for website building.

(4) Quarto has cleaner command than hugo (i.e., `quarto publish netlify` for publishing website etc.).

This blog serves as a note how I customize quarto website bit by bit. It will not be a comprehensive tutorial (much online resources exists) but contain be some tricks.

2 Tricks of Quarto

2.1 Code highlighting

The very first trick is using format > html > code-fold: true settings in YAML metadata in _quarto.yml (global) or .qmd (local) to hide the code block as |> Code, like:

library(kableExtra)
Warning: package 'kableExtra' was built under R version 4.2.3
kbl(head(iris)) |> 
  kable_styling(
    html_font = "Ysabeau Office",
    font_size = 11, full_width = TRUE)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
4.6 3.1 1.5 0.2 setosa
5.0 3.6 1.4 0.2 setosa
5.4 3.9 1.7 0.4 setosa

Note that the code block can be numbered and added with a left border using code-block-bg: true and code-block-border-left: "#31BAE9"

Code block now also can be shown with language #| echo: fenced. As the code chunk shown below, {r} is explicitly presented. I don’t hate #| as the new way of chuck option setup but when I test the code chuck, I found there is a space between #| and option keys. For example, it should be #| echo: fenced rather than #|echo:fenced. Otherwise, quarto will ignore chunk options.

```{r}
#| eval: false
#| code-fold: false
kableExtra::kbl(head(iris)) |> 
  kableExtra::kable_styling(
    html_font = "Ysabeau Office",
    bootstrap_options = c('striped', 'hover'),
    font_size = 10, full_width = TRUE)
```
⌘+C
```{python}
#| eval: false
#| code-fold: show
import numpy as np
iris = np.array(iris)
```

2.2 Visual model

Visual model is one of the most appealing feature for Quarto but I am far from a expert in that. It looks like a visual model version of markdown editor (so called WYSIWYM editing, What you see is What you mean) but slightly different. The shortcut of switching between source and visual model is Cmd + Shift + F4 (Thanks to Yihui’s JS for pretty keyboard styling).

I list some most frequently used keyboard for visual mode editing:

  1. Insert Hyperlink: Cmd + K

  2. Add footnote1: Shift+Cmd+F7

  3. Insert picture: Shift +Cmd +I

  4. Insert code chunk2: Alt +Cmd +I

  5. Edit attribute3: F4

1 Like this.

2 By default, it will insert R code chunk. If another language is frequently, use Tools > Modify keyboard shortcuts > filter 'Insert'. There should be a place for setting shortcut for other language.

3 Click `F4` in any place in the div works.

Please also refer to the official document for more shortcuts and features. One thing I found very interesting is single quote mark ` . First, I’m not sure how to escape this in visual model. Second, if you close quote before typing content, like ``, visual mode will escape both quote marks. However, if you type in left quote mark then content and then close quote (i.e., type in`something first, and type closing quote mark), it can quote content correctly.

Last but not least, perhaps just type / in rstudio is a better choice as it will pop up a list of elements to choose.

2.3 giscus comments box theme toggle (not work any more for Quarto 1.5.23)

giscus comments box needs some tweaks to switch light/dark based on the toggle switcher of quarto. Please find Ella’s post and Ella’s giscus issue discussion and original Javascript.

giscus-mode-toggle.html
<script>
function getGiscusTheme() {
  const quartoTheme = localStorage.getItem("quarto-color-scheme");
  const giscusTheme = quartoTheme === "alternate" ? "dark" : "light";
  return giscusTheme;
}

function setGiscusTheme() {
  function sendMessage(message) {
    const iframe = document.querySelector('iframe.giscus-frame');
    if (!iframe) return;
    iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
  }
  sendMessage({
    setConfig: {
      theme: getGiscusTheme(),
    },
  });
}

document.addEventListener('DOMContentLoaded', function () {
  const giscusAttributes = {
    "src": "https://giscus.app/client.js",
    "data-repo": "[ENTER REPO HERE]",
    "data-repo-id": "[ENTER REPO ID HERE]",
    "data-category": "[ENTER CATEGORY NAME HERE]",
    "data-category-id": "[ENTER CATEGORY ID HERE]",
    "data-mapping": "pathname",
    "data-strict": "0",
    "data-reactions-enabled": "1",
    "data-emit-metadata": "0",
    "data-input-position": "top",
    "data-theme": getGiscusTheme(),
    "data-lang": "en",
    "crossorigin": "anonymous",
    "async": "",
  };

  // Dynamically create script tag
  const giscusScript = document.createElement("script");
  Object.entries(giscusAttributes).forEach(([key, value]) => giscusScript.setAttribute(key, value));
  document.body.appendChild(giscusScript);

  // Update giscus theme when theme switcher is clicked
  const toggle = document.querySelector('.quarto-color-scheme-toggle');
  if (toggle) {
    toggle.addEventListener('click', setGiscusTheme);
  }
});
</script>
div-giscus.html
<div class="giscus">
_metadata.yml
include-in-header: giscus-mode-toggle.html
include-after-body: div-giscus.html
Note

Remember comment out giscus setting in _quarto.yml

_quarto.yml
#comments:
#  giscus:
#    repo: JihongZ/quarto-academic-jihong
Back to top