Skip to content

Instantly share code, notes, and snippets.

@danieltomasz
Last active August 21, 2024 08:55
Show Gist options
  • Save danieltomasz/87b1321e23c045309d2571f525f856cf to your computer and use it in GitHub Desktop.
Save danieltomasz/87b1321e23c045309d2571f525f856cf to your computer and use it in GitHub Desktop.

Quarto callouts

About callouts

Callouts are a great way to add more attention ot certain details of the text (in the form of a box). Quarto provides 5 different types of callouts:

  • note
  • warning
  • important
  • tip
  • caution.

The color and icon will be different depending upon the type that you select. You could preview them in the official documentation - Quarto - Callout Blocks. If you want to check the end effect jump directly to it here.

The problem:

When writing your text directly in markdown compiled in Quarto you need to use pandoc div syntax

::: {.callout-note}
Note that there are five types of callouts, including:
`note`, `warning`, `important`, `tip`, and `caution`.
:::

When you want to edit your text in Obsidian obisidian doesnt pick the pandoc div syntax, instead it will have:

> [!note] My note
>
> Note content

There is no easy way to have nice formatted callouts in qmd/md files in Obsidian before compiling them to pdf/html

Lua filters come as a solution

Pandoc can be supplemented by filters written by Lua that might some complex operations with source text.

I found a nice pandoc filter on the Obsidian forum, which I modified, so it support the default callouts in Quarto. You need to save it as a pandoc filter and put inro your project folder and point to it when running quarto command (either via commandline or by putting it into you _quart.yml project settings.

In my case the file is called obsidian-callouts.lua and I point to it in the _quarto,yml in the root of the folder in the following section (I excluded irrelevant details):

project:
  output-dir: _output
  
filters:
- filters/obsidian-callouts.lua

Content of the file obsidian-callouts.lua :

local stringify = (require "pandoc.utils").stringify

function BlockQuote (el)
    start = el.content[1]
    if (start.t == "Para" and start.content[1].t == "Str" and
        start.content[1].text:match("^%[!%w+%][-+]?$")) then
        _, _, ctype = start.content[1].text:find("%[!(%w+)%]")
        el.content:remove(1)
        start.content:remove(1)
        local class = "callout-" .. ctype:lower()
        div = pandoc.Div(el.content, {class = class})
        div.attributes["data-callout"] = ctype:lower()
        div.attributes["title"] = stringify(start.content):gsub("^ ", "")
        return div
    else
        return el
    end
end

As a source I used this thread https://forum.obsidian.md/t/rendering-callouts-similarly-in-pandoc/40020/6

Tweaks to obsidian CSS

By default Obsidian recognize only note and warning callouts, to have the other 3 callouts the same icons and colors as in Quarto add the following CSS snippet quarto-callout-styllling to hidden .snippets folder and turn it on in the Obsidian appearance section of settings

/* See https://lucide.dev for icon codes */

/* annotation */
.callout[data-callout="important"] {
  --callout-color: 251, 70, 76;
  --callout-icon: lucide-alert-circle
}

.callout[data-callout="tip"] {
  --callout-color: 28, 207, 110;
  --callout-icon: lucide-lightbulb
}

.callout[data-callout="caution"] {
  --callout-color: 255,153,102;
  --callout-icon: lucide-flame
}

Comparison

After applying the css could see the difference between callouts in Live Preview in Obsidian

Image

and PDF generated via Quarto

Image

Below is the markdown used to generate it

> [!note] My note
>
> Note content

> [!warning] My note
>
> Note content

> [!important] My note
>
> Note content

> [!tip] My note
>
> Note content

> [!caution] My note
>
> Note content

Attention

While those snippets will ensure that your notes will render nicely in Obsidian, it may cause other editors that support Quarto to offer the same (altough) it will nice compile to pdf/html.

I didnt extensively test this Lua filter, so it might easily go broke in more complex cases and if you will try to use the callouts outside the one defined in Quarto by default.

More about how to use Quarto in Obsidian

In general I enabled Obsidian to see quarto files as md files via plugin, and then use obsidian-shellcomands with quarto render {{file_path:absolute}} --to pdf to render the file inside Obsidian (quarto is installed via homebrew on mac, this might work for linux, I am not sure about windows).

I also assigned this shellcomand to a button in my GUI via commander plugin (so I dont need to invoke it every time via command switcher when I want to re-run it on a file.

I created rudimentary plugin to support QMD files in Obsidian, in the Readme.md you could find more advices how to streamline work with your qmd files in Quarto:

danieltomasz/qmd-as-md-obsidian: A plugin for Obsidian which allows editing of qmd Quarto files.

@danieltomasz
Copy link
Author

danieltomasz commented Aug 19, 2023

@jadebarclay which different things from Obsidian you want to map to pandoc divs? it should be possible to write another filter that use different regex but works not so different from this one

@jadebarclay
Copy link

Thanks @danieltomasz. Nothing specific comes to mind right now. Quarto is my data science and sharing/publishing haven, and Obsidian is my writing/thinking workbench. I'm delighted with both, and they're both brilliant for different use cases. Just trying to keep them as interoperable as I can, and not have to swap between Markdown syntaxes.

I end up finding and tweaking extensions and filters for almost every one-off project.

Here are some of the things that I'd love to be more interoperable, not urgent just simmering at the back of my mind as examples/curiosity/inspiration...
I've recently combined and tweaked many of these extensions/filters for bibliography wrangling in my thesis and cv:

And lots of these packages/extensions are amazing in Quarto, but don't really render (yet) in Obsidian:

  • https://psyteachr.github.io/ (esp webexercises, booktem, glossary, etc. using in-built pandoc markdown features, like definition-lists notation for the glossary)

@jadebarclay
Copy link

@danieltomasz Having the Quarto columns, cross-references, asides and marginnotes would be brilliant. I tinkered with some fancy Tufte extensions, but they introduced problems. I can get the same effect just by setting the font and margins in yaml. It renders to pdf/html well. Not sure if there's a way to get Obsidian to render nicely as well.

eg, Interchangable column syntax would be great https://github.com/tnichols217/obsidian-columns

eg, in yaml

---
reference-location: margin
citation-location: margin
---

or in-line columns, in-line margins or asides

::: {.column-margin}

:::

[in-line span to put notes in the margins]{.aside}

@danieltomasz
Copy link
Author

@jadebarclay I don't have personal experience with columns in Obsidian or Quarto, but in theory it seems like it should be feasible to translate Obsidian's column syntax into Bootstrap's grid system for Quarto HTML output. This StackOverflow link looks helpful for that approach.

It might get trickier for LaTeX output, since I'm not sure if LaTeX recognizes Bootstrap grids out of the box. But for HTML/CSS, mapping Obsidian columns to Bootstrap should work nicely.

And you're right - it seems like a simple tweak to my filter could handle translating custom callout CSS (like the aside callout in some Obsidian themes https://willemstad.cc/Theme+Extensions/Callouts) into Pandoc divs. I might investigate it further (especially Tufte style annotation) but not very soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment