The workbench is where you shape and understand your space: look through your data, build queries over it, try out Space Lua, and see how your scripts and styles loaded.
You can open the panel via ${widgets.commandButton("Workbench: Toggle")}.
Ultimately it will contain many things, but for now it covers the following:
space-lua block in your space, and how loading it went.space-style block in your space, and whether the browser could make sense of it.The workbench is a panel that opens at the bottom of the window. Like other panels, you can drag its top edge to resize it, and move it to the left or right sidebar, or open it as a large modal window, with its dock menu. On a phone it takes the full height of the screen instead, apart from a strip of your page. These commands open it:
/Query… slash command, typed in a page: opens the #Query tab with its query editor showing, to build a query that goes where you typed it.The tabs are, in order: Overview, Query, Console, Scripts, Styles, Libraries and Health. It opens on Overview the first time, and after that on the tab you last picked. Switching tabs keeps each tab’s state, such as a half-typed line in the REPL.
The Overview tab is the default, and shows your space at a glance. It is quick to open: the counts show first, and the revision-based cards fill in as they arrive. Counts update as your space changes; activity and Git sync update when the tab becomes visible and every minute while it is. Cards:
Library/ and Repositories/ are not counted.Library/ and Repositories/.Library/ and Repositories/ pages are excluded here too. System meta/ tags are not counted.Everything on the Overview leads to where you would act on it. Pages, Links and Documents open the Query tab on that tag, and the open and done task counts open it on tasks, filtered. A top tag pill opens that tag's page in the editor (its configured tag page, or the built-in tag: page), while "all tags" opens the Query tab on tags. Activity, the heatmap and the Most edited and Edits by person titles open the space-wide revision log, while a Most edited row opens that page. The Git sync title opens the Git status, and its conflicts count goes to Health. The Scripts and Styles rows switch to their tabs; the version is plain text.
Activity, Most edited and Edits by person come from your space's revision history, so they only show when Revisions are enabled and you have write access. They don't count Git sync merges as edits.
Stats: Show is unchanged: it still shows its toast about the current page.
A mix of logs (Lua, JavaScript, Plugs, Service Worker) and a Lua REPL. Enter Lua expressions, and they will be evaluated and render their results inline. Each line has a context menu with relevant actions.
The log collects, from the moment SilverBullet starts:
print in your scripts, with a link to the line that printed it, plus everything you run in the REPL.The log keeps the most recent 1000 entries. Use the filter field to search them (a plug’s name matches too), and the All, Lua, JS, Plug, SW and Error buttons to show one source, or only errors. Clear empties the log.
Lua errors show their message, a hint when there is one, and the offending line with the failing part marked. Stack lists where the error passed through. Each location is a link: it jumps the editor to that spot in your page, or, when it points into earlier REPL input, scrolls the log to that input.
Type Lua at the › prompt at the bottom and press Enter to run it.
1 + 2 shows 3, and "a", "b" shows both values. A statement, like an assignment or a loop, shows nothing unless it ends with return.local you define stays available to later input, until you reload the page. Everything else resolves against your space’s environment, so the functions your space-lua blocks define are available, and keep working after you edit and reload them.function f() or an open {, Enter starts a new line instead of running it. Shift-Enter always starts a new line.Results that are tables, lists or records render the way a ${…} expression would render them on a page: query results as tables, widgets as widgets. Use the Rendered and Lua toggle on a result to switch to the underlying Lua value instead.
Hover a log entry and click ⋯ for actions that fit it:
Copy as ${…} (for a single expression, so you can paste it into a page), Copy code, and Run again.${…} widget.The Scripts tab lists every space-lua block in your space, in the order SilverBullet loads them: by priority, highest first (see Space Lua#Definition loading). Each row shows:
@66.Scripts that failed to load show their error right below the row, with the same message, marked line and clickable stack as in the console. To narrow the list, use the filter field and two sets of buttons, each showing counts:
Library/Std pages. Everything else is custom, including libraries you installed. The list starts on Custom.The footer shows how many scripts there are, how long loading them took in total, and when they last loaded.
Click a row to jump to the script. Its ⋯ menu offers:
A script is quarantined when you stop it for running too long while it loads. It’s then skipped on later loads until you re-enable it, or until you edit it. A script you stopped during the current load also shows as quarantined. See Space Lua#Runaway scripts.
Reload runs all your space-lua blocks again, and the list updates when they’re done.
The Styles tab lists every space-style block in your space (see Space Style), in the order they’re applied: by priority, highest first, after the blocks that set no priority. Each row shows:
Browsers drop CSS they can’t parse without reporting it, so an amber row almost always means a syntax error, like a missing {. A block that only holds comments isn’t flagged. A typo that breaks just one rule in a block shows up only as that block’s rule count being one lower than you’d expect.
The filter field and the All, Custom and Built-in buttons narrow the list, the same as on the #Scripts tab, and it starts on Custom too. The footer shows how many styles there are, how many rules they add up to, and when they last loaded.
Click a row to jump to the style. Its ⋯ menu offers Open source and Copy CSS. Reload applies all styles again and updates the list.
The Query tab shows the objects in your space: your pages, tasks, and everything you tagged. Pick a tag to look through its objects, and use the query editor beside them to narrow them down, sort or group them, or pick what to show: it builds a query without you knowing the query syntax. Close the editor with its ✕ to give the objects the whole tab, and bring it back with Edit query. The result updates as you go; when you like what you see, put the query on a page. Either way, the bar at the bottom shows the query it takes, so you can learn the syntax as you click.
The tab has three parts:
page and task (with the root tags your data blocks define), then edge and index tags, then the User tags used in your space. Type in the box at the top to narrow the list; Enter picks the first match and Escape clears it. Picking one starts a query on it. The tab first opens on pages.index.*() helper, such as index.pages() or index.data("contact"). Next to it, narrow it down: a root tag to the objects that carry one of the user tags used on it (index.pages("project"); a relation to one kind), or a user tag to one root tag it's used on (index.tasks("project"), where on its own it reads index.objects("project")). For pages, pick All, Content or Meta to read every page, only content pages (index.contentPages(), the default) or only meta pages (index.metaPages()). Narrowing keeps the query you built. Schema lists every field of its objects (see #Fields).count or avg, including your own aggregates.templates (such as tasks with their checkbox), or a Custom template… you write with the fields as ${name}. Each template shows the description from the --- comment above it, and the ones whose @param takes this tag’s objects come first.Fields come from the tag’s Schema when it has one, and from looking at up to 500 of its objects, which also finds fields a schema leaves out. For each field, Schema shows its type, where it came from (built-in, declared or inferred), how many objects have it, and some of its values.
For a tag without a schema, the type is worked out from the values: dates, page links and numbers are recognized, and a field with a few repeating values becomes one of those values, with a dropdown in filters. A field with values of different kinds is marked mixed. You can change a field’s type for this session; that only changes which filters are offered. Copy as tag.define copies the fields as a tag.define you can paste into a space-lua block to give the tag a declared schema.
Changing the tag, or a change that leaves a filter or column without its field, offers to undo it.
The bar at the bottom shows the query; Show expands it.
${query[…](<…>)} in the page you’re editing, or where you typed /Query…. For a query you opened from a page, it’s Update page, which replaces that query, and keeps doing so as you change it further.To change a ${query[…](<…>)} already on a page, choose Edit in query builder from its widget’s ⋯ menu, or put the cursor in it and run ${widgets.commandButton("Workbench: Edit Query")}. The query editor opens with the query taken apart into its rows: a filter the builder could have written becomes that filter again, and any other condition, order or column stays as Lua, in an Expression. The query keeps its own variable name, or none.
Some queries don’t fit the builder, and say why instead of opening: a query over something other than one index.*() collection (such as index.pages(), or the older index.tag "page", which is rewritten as index.pages()), an offset, a having, grouping by anything but fields, an order by with using, or a select other than a table with named columns or a template.
The Libraries tab manages the libraries in your space. In a read-only space it only shows what's there: installing, updating, removing and checking for updates are hidden, with a note saying why (a read-only server doesn't reach other servers, so there is nothing to check against). It reloads every time you show the tab, so what you see matches your space. The toolbar has:
https://… or github:…) and installs it. For a plug (a URI ending in .plug.js) it also asks where to save it.Below it are three sections, each with its own error and info banner:
Library/Std/ pages, or without a share URI) are marked built-in and can’t be updated or removed. Libraries in dev mode are marked dev mode and are left alone, too. Click a row to open its page.An installed library or repository row shows its share URI. Its ⋯ menu offers:
Plugs only offer Remove.
Check for updates reads the source of every library you installed (not built-in or dev-mode ones) and every repository you added, and labels each one:
The footer counts libraries, repositories and available libraries, and shows when you last checked. A label stays until you update or remove that row, or check again; labels of rows that are gone disappear when the list reloads.
${widgets.commandButton("Libraries: Manager")} (also the Libraries... menu item) and ${widgets.commandButton("Library: Manager")} open the workbench on this tab. ${widgets.commandButton("Library: Install")}, ${widgets.commandButton("Library: Add Repository")}, ${widgets.commandButton("Library: Update All")} and ${widgets.commandButton("Library: Update All Repositories")} open it too, and then start that action. They work while the workbench is closed.
The Health tab lists problems in your space in one place. The tab's label shows a count of errors, so you notice a real problem from any tab. It counts failed scripts, Git conflicts and Git sync errors, plus each error from a finished space-wide lint once per page and line. Space-wide lint errors on a page whose script already failed aren't counted again, and neither are conflict markers on a page that already has a Git conflict. Click a problem to open its page.
The checks below are instant, and refresh as your space changes:
A group with no problems shows up as a single line with a check mark.
The space-wide lint runs API/space#space.lint over every page outside Library/. This reads each page, runs every lint rule and renders its ${…} expressions and Lua widgets, so on a large space it can take a while. That's why it never runs by itself: press Run space-wide lint when you want it. It shows progress and the problems found so far as it goes, and Cancel stops it. When it's done, Run again repeats it. Results are kept until you reload.
Narrow the list with the severity filter (All, Errors, Warnings, Info, each with a count) and the text filter, which matches page names and messages. The ⋯ menu in the toolbar has Reindex space, which rebuilds the index.