Last active
June 20, 2026 02:14
-
-
Save danieltomasz/31d298aca2969adaf60d8841b68005e2 to your computer and use it in GitHub Desktop.
Lua filter that allows passing obsidian/github callouts as quarto native in quarto >1.3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- obsidian-callouts.lua | |
| -- Render Obsidian / GitHub-style callouts as native Quarto callouts. | |
| -- | |
| -- > [!note] Optional title | |
| -- > body... | |
| -- > [!warning]- <- trailing - / + sets collapsed / expanded | |
| -- | |
| -- Works whether or not there is a blank `>` line between the title line | |
| -- and the body. Requires Quarto >= 1.3 (uses the quarto.Callout API). | |
| -- Put it in your project's _quarto.yml under `filters:`. | |
| local stringify = pandoc.utils.stringify | |
| local type_map = { | |
| note = "note", info = "note", todo = "note", abstract = "note", | |
| summary = "note", tldr = "note", example = "note", quote = "note", | |
| tip = "tip", hint = "tip", success = "tip", check = "tip", | |
| done = "tip", question = "tip", help = "tip", faq = "tip", | |
| warning = "warning", attention = "warning", | |
| caution = "caution", fail = "caution", missing = "caution", | |
| danger = "caution", error = "caution", bug = "caution", | |
| important = "important", | |
| } | |
| function BlockQuote(el) | |
| local first = el.content[1] | |
| if not first or first.t ~= "Para" then return el end | |
| local marker = first.content[1] | |
| if not marker or marker.t ~= "Str" then return el end | |
| -- marker token: [!type] with optional trailing - or + (fold state) | |
| local ctype, fold = marker.text:match("^%[!(%w+)%]([-+]?)$") | |
| if not ctype then return el end | |
| -- inlines of the marker paragraph, minus the "[!type]" token | |
| local inlines = first.content:clone() | |
| table.remove(inlines, 1) | |
| -- With no blank `>` line, Pandoc folds the title line and the body into | |
| -- one paragraph joined by a SoftBreak. Split at the first line break: | |
| -- before it is the title, after it is the first body paragraph. | |
| local title_inlines, rest_inlines = pandoc.List({}), pandoc.List({}) | |
| local seen_break = false | |
| for _, inl in ipairs(inlines) do | |
| if not seen_break and (inl.t == "SoftBreak" or inl.t == "LineBreak") then | |
| seen_break = true | |
| elseif seen_break then | |
| rest_inlines:insert(inl) | |
| else | |
| title_inlines:insert(inl) | |
| end | |
| end | |
| local title = stringify(title_inlines):gsub("^%s+", ""):gsub("%s+$", "") | |
| -- rebuild the callout body | |
| if #rest_inlines > 0 then | |
| el.content[1] = pandoc.Para(rest_inlines) -- trailing text on marker line | |
| else | |
| table.remove(el.content, 1) -- marker line had only the title | |
| end | |
| return quarto.Callout({ | |
| type = type_map[ctype:lower()] or "note", | |
| title = (title ~= "" and title) or nil, | |
| collapse = (fold == "-" and true) or (fold == "+" and false) or nil, | |
| content = el.content, | |
| }) | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
got this error
lua:24: <eof> expected near 'end'which went away after removing the last two lines with the two extraends