Customizable [[Wiki Link]] Resolution

What if we had the possibility to customize how wiki links resolve to a page link? :thinking:

Right now, a link like [[My Page]] typically resolves directly to My Page.md. Imagine if we could define rules or patterns for this resolution.

For example:

Skipping Sub-directory Prefixes: Maybe [[My Post]] could automatically look for blog/My Post.md.

Aliasing/Shortcuts: What if [[alpha:task123]] could resolve to a page like Projects/Project Alpha/Task 123.md based on a predefined mapping?

If users can write their resolver function, I think this could offer a lot more flexibility in how we organize our notes and create more semantic links within Silverbullet. It could also make it easier to maintain a consistent structure, especially for larger knowledge bases.

What are your initial thoughts on this? Do you see any benefits or potential challenges? Are there any specific use cases where you think this would be incredibly helpful?

3 Likes

:+1:

I like the idea of customizable “resolvers” in general. This is one of the integeresting use cases!

Technically this could be solved similar to the pageCreating event.
When resolving a link SB would fire an event, then waits for anyone to return a path and if no listener returns or they return null, it just falls back to the default resolving. Only problem could be with async loaders, but I guess that also applies to pageCreating.

2 Likes

I see there’s page:click event, which might be useful…

page:click - Fired when a user clicks somehwere in the page.
API/event

That’s actually a good point. SB itself does “all” the navigation inside a plug. Sadly I don’t think there is an easy way to overwrite that event listener. Maybe that’s something to think about.

Oh, that means you can write a Plug that override the default event:

Could you tho, I don’t know the load order and all that stuff of the top of my head, but I think it would be very hard to overwrite the default listener without some quirky hacks.

Not sure, I will try that when I start migrating from LogSeq because LogSeq stores markdowns in this format:

  • pages/xxx.md
  • journals/xxxx-xx-xx.md

I want to make them work without breaking all the links

1 Like

Zef said in the chat channel that a plugin cannot override a handler but can only extend.

Related Camel Case as link or tag

Tried the editor:pageCreating event, to change how wikilink is resolved.

E.g., Upon clicking [[March]]

  1. Search all pages matching March
  2. Navigate to matching page if one found (e.g., 2025/March)
  3. Show filter box if many are found (e.g., 2024/March, 2024/March)

I hit a problem, where silverbullet navigates to March which is not existent. This needs change in silverbullet, I guess, right?

event.listen {
  name = "editor:pageCreating",
  run = function(e)
    local wikiName = e.data.name
    local pages = space.listPages()
    local resolvedPaths = {}

    -- Collect all matching pages by filename
    for _, page in ipairs(pages) do
      local filename = page.name:match("([^/]+)$")
      if filename == wikiName then
        table.insert(resolvedPaths, {
          name = page.name .. ".md"
        })
      end
    end

    -- Handle multiple or single matches
    if #resolvedPaths > 1 then
      local result = editor.filterBox("Navigate To:", resolvedPaths, "")
      if result then
        editor.navigate(result.name, false, true) -- open in new tab as workaround to automatic navigation
      end
    elseif #resolvedPaths == 1 then
      editor.navigate(resolvedPaths[1].name, false, true) -- open in new tab as workaround to automatic navigation
    else
      print("No matching pages found for: " .. wikiName)
    end

    return nil -- Needs change in SilverBullet to prevent automatic navigation
  end
}