Louis/scripts/wikilinks.lua
2026-06-09 14:45:18 +02:00

112 lines
3.8 KiB
Lua

--- Shamelessly stolen from https://github.com/rmgpanw/quarto-obsidian-template thanks rmgpanw
--- Pandoc Lua filter for Obsidian-Quarto compatibility.
--- 1. Converts [[wikilinks]] to standard markdown links.
--- 2. Merges Obsidian `tags` into Quarto `categories` for the listing page.
--- Runs at render time inside Pandoc; source files are never mutated.
--- Merge tags into categories so Obsidian tags appear on Quarto listing pages.
function Meta(meta)
if meta.tags then
local cats = meta.categories or pandoc.MetaList({})
-- Collect existing categories for deduplication
local seen = {}
for _, c in ipairs(cats) do
seen[pandoc.utils.stringify(c)] = true
end
for _, t in ipairs(meta.tags) do
local val = pandoc.utils.stringify(t)
if not seen[val] then
cats[#cats + 1] = t
seen[val] = true
end
end
meta.categories = cats
return meta
end
end
function Str(el)
-- Match wikilinks with alias: [[target|display]]
local target, display = el.text:match("^%[%[(.-)%|(.-)%]%]$")
if target and display then
local url = resolve_target(target)
return pandoc.Link(display, url)
end
-- Match plain wikilinks: [[target]]
target = el.text:match("^%[%[(.-)%]%]$")
if target then
local url = resolve_target(target)
return pandoc.Link(target, url)
end
return nil
end
function Inlines(inlines)
local result = pandoc.List()
local i = 1
while i <= #inlines do
-- Look for a sequence starting with Str("[[")
if inlines[i].t == "Str" and inlines[i].text:match("^%[%[") then
-- Collect all elements until we find one ending with "]]"
local parts = { inlines[i].text }
local j = i + 1
local found_end = inlines[i].text:match("%]%]$") ~= nil
if not found_end then
while j <= #inlines do
if inlines[j].t == "Str" then
parts[#parts + 1] = inlines[j].text
if inlines[j].text:match("%]%]$") then
found_end = true
j = j + 1
break
end
elseif inlines[j].t == "Space" or inlines[j].t == "SoftBreak" then
parts[#parts + 1] = " "
else
-- Non-text element breaks the wikilink sequence
break
end
j = j + 1
end
end
if found_end then
local combined = table.concat(parts)
-- Try alias syntax first
local target, display = combined:match("^%[%[(.-)%|(.-)%]%]$")
if target and display then
result:insert(pandoc.Link(display, resolve_target(target)))
i = j
else
target = combined:match("^%[%[(.-)%]%]$")
if target then
result:insert(pandoc.Link(target, resolve_target(target)))
i = j
else
result:insert(inlines[i])
i = i + 1
end
end
else
result:insert(inlines[i])
i = i + 1
end
else
result:insert(inlines[i])
i = i + 1
end
end
return result
end
function resolve_target(target)
-- If target already has an extension, use it as-is
if target:match("%.[%a]+$") then
return target
end
-- Append .html so links work regardless of source extension (.md or .qmd)
return target .. ".html"
end