SilverBullet 2.5 released

SilverBullet 2.5.0 brings a number of keyboard binding changes (due to CodeMirror dropping support for Alt-<letter> shortcuts, sorry about this...), significant sync reliability improvements ensuring your local state stays in sync with the server, and powerful new Lua Integrated Query features including group by and aggregator support. The Space Lua engine also saw significant improvements with a port of Lua's native pattern matching library, <close> attribute support, and various performance and compatibility improvements.

Changes

  • Changed keyboard bindings (sorry!). CodeMirror no longer directly allows Alt-<letter> and Alt-<special-character> Keyboard Shortcuts, meaning I had to remap a few key bindings. It's basically a mission impossible to pick great ones, but here are the new defaults:
    • Quick note is now bound to both Ctrl-q q (type Ctrl-q first, then hit q again) and Ctrl-q Ctrl-q (hit Ctrl-q twice)
    • Navigate: Home is now bound to Ctrl-g h
    • Text: Marker is now bound to Ctrl-Alt-m
    • Outlines commands generally now use a Mod-. (Cmd-. on mac, Ctrl-. on Linux/Windows) prefix:
      • Outline: Move Right: Mod-. l
      • Outline: Move Left: Mod-. h
      • Outline: Move Up: Alt-ArrowUp still works, but now also adds Mod-. k for consistency
      • Outline: Move Down: Alt-ArrowDow still works, but now also adds Mod-. j for consistency
      • Outline: Toggle Fold: Mod-. Mod-.
      • Outline: * Fold (other fold commands): keyboard disabled, readd yourself if you need them (see Keyboard Shortcuts)
      • Task: Cycle State: Mod-. t
    • Page: Rename keyboard shortcut removed
    • Page: Rename Linked Page keyboard shortcut removed
    • Sync: Space keyboard shortcut removed
    • As documented in Keyboard Shortcuts, it is now possible to specify multiple keyboard shortcuts to a commands.
  • Sync reliability work:
    • Better indication whether your page is synced to the server: "Dirty state" (slightly tinted color of page name) is now aligned with actual synced-to-server state unless the editor clearly indicates it is in offline mode (yellow top bar).
    • Sync snapshots are now persisted after every file sync, reducing (and hopefully eliminating) edge cases where the sync engine is killed mid-sync (for whatever reason) and the snapshot becomes of sync with "reality".
    • The index status progress indicator (blue circle) should now be more reliably reflect the actual indexing status.
    • HTTP status codes >= 500 are now treated as offline (better offline detection).
  • Lua Integrated Query improvements (courtesy of Matouš Jan Fialka):
    • group by and having clauses with aggregator support
    • filter(where <cond>) clause for per-row aggregate filtering
    • nulls first/nulls last in order by
    • Null/missing query cells now render as empty
  • Space Lua engine general improvements (most courtesey of Matouš Jan Fialka):
  • New experimental API: tag.define(spec), see linked page for docs and example uses. Brings back ability to define deadlines for tasks (see example). Another part of this is Schema support for tags. When a schema is defined for a tag, you get:
    • Frontmatter attribute completion and linting (in-editor error indicators) for attributes defined as part of the tag's schema.
    • Lua Integrated Query attribute code completion if you use the from v = index.tag("bla") style syntax (so explicitly bind your iterator variable).
    • Item-level linting (highlights the object in-line in case of validation errors).
  • Tag schema updates:
    • pos (present in link, item and some other tags) is now deprecated, use range instead
    • range is a tuple of two numbers: from and to (e.g. {0, 10}) identify where the object appears in the page
  • Editor improvements:
    • New Page: Create Under Cursor command, useful to pre-create an aspiring page link. Put your cursor in a wiki link to a non-existing page, and hit Cmd-Shift-Enter (Ctrl-Shift-Enter) to create it (empty) without navigating there.
    • Linked Mentions now list full page path rather than abbreviated version.
    • Hide vertical scrollbar overflow for long page names.
    • Upload file: prompt user before replacing files and no-clobber behavior for paste uploads (by Oliver Marriott).
    • Trim user input from prompts where appropriate (by rktjmp).
    • Consider empty string as invalid path (by rktjmp).
  • Styling changes:
    • Attribute names and values ([key: value] notation) now get different CSS classes in the editor: sb-attribute-name for names and sb-attribute-value for values.
    • The diff Fenced Code Block language now uses colors to indicate additions and removals (by Lajos Papp).
  • Configuration:
    • New shortWikiLinks config (defaulting to true) that decides whether a wiki link should be rendered in its short form (rendering just the last segment, e.g. Person/John would show as John). To always render the full name, put config.set("shortWikiLinks", false) in your CONFIG.
    • Authentication: how long "remember me" works is now configurable (by Metin Yazici) via Configuration and more reliably persisted.
  • Library Manager: SilverBullet now navigates to library page after installing one.
  • FreeBSD buids!
  • Now excluding .plug.js and .js.map files from the document list.
  • Fix: bring back Virtual Pages.

Upgrading

  • For docker-based install, pull the new image, stop the container and start a new one. For binary-based installs run silverbullet --upgrade and restart.
  • After upgrading the server, make sure you reload all your SilverBullet tabs a few times, just to make sure the cache is flushed.

Dedication

As mentioned earlier, I decided to reduce my regular day job to fewer days and spend this time on SilverBullet. This allows for deeper focus and more ambitious work. If you like this, consider sponsoring to make this a little bit more financially viable for me.

14 Likes

Quick patch release with 2.5.1: there was a latent caching bug in some environments, that resulted in built-in plugs and libraries not being updated (somehow they were stuck with an old timestamp). Should be fixed after updating to 2.5.1.

2 Likes

My plugin MdTableSheet is not working anymore after 2.5.1 migration. Is there a breaking change list somewhere? (something related to table management or signature of function changes?)

Thank you Zef and dev team. Group by is a tremendous feature.

Regarding to my issues after upgrade, the only that I notice was with a function (pixel_tracker_map_section) from the thepaperpilot CBT library. Changing from 100% to 100%% solved the issue.

--from this:
local offset_expr = string.format("calc(100% - (%d * 1lh) + var(--gap))", week_index)
--to this:
local offset_expr = string.format("calc(100%% - (%d * 1lh) + var(--gap))", week_index)

There's a list in the announcement, although nothing should be breaking. Since on the Lua end some things have been reimplemented to be more Lua compatible, it's possible that somewhere your code depends on non-standard or not valid previous behavior?

Right, this an example of what I just mentioned. In string.format % has special meaning, to insert an actual % you have to use %%. This was always the case, but previously not doing this also (sometimes) worked.

Just released 2.5.2:

  • Fixed table indexer shifting columns when cells are empty
  • Fixed transclusions not working in widgets
  • Fixed renaming page with ) in the name
2 Likes

before
${string.find("space-lua","space-lua")} => 1
After:2.5.0
${string.find("space-lua","space-lua")} => nil
${string.find("space-lua","space")} => 1

My breaking change or regression?

This is the case with format, gsub, find, ...
Use % with special caracteres.
${string.find("space-lua","space%-lua")} => 1

it worked fine before and in my case, every parameter are variables . It will be a nightmare to escape everything.
Is there a method to auto escape strings?

On another issue: "Error: invalid use of '%' in replacement string".
I'm sure that i will detect more regression. Is there a list of "breaking change" for space-lua language in 2.5.x?

You can even override the Lua functions...
But this is the Lua default.
I changed all the occurrences I had. The main problem was with dates (2026-03-06).
Below is one possibility...

--priority 99
sfind = string.find
string.find = function(s,p)
  local p = string.gsub(p,'%-','%%-')
  return sfind(s,p)
end

Another option...
The 4th parameter defines an exact search, escaping special characters.

string.find("space-lua","space-lua",1,true) => 1

Thanks. It's an idea.
Step by step, I will identify the full impact of this new behavior.
In function, I will rewrite or eliminate some of scripts to not have to migrate them too often.

Remember... these are the special characters:
( ) . % + - * ? [ ^ $
I think these are the Lua functions impacted:
find, gmatch, match, gsub
format

Cc @mjf for awareness

Acked.