Commit Graph
291 Commits
Author SHA1 Message Date
Zef Hemel ec40aa0838 Add action buttons to flashNotification
Used by upgrade notification
2026-03-10 16:07:25 +01:00
Zef Hemel d9f4b93795 Eliminate (most) uses of the client global
Also an opportunity to refactor the transclusion code, which had become
very messy
2026-03-10 14:02:05 +01:00
Zef Hemel fd1a81b8d8 Client refactor: move UI related APIs to editor_ui.ts 2026-03-10 12:42:26 +01:00
Zef Hemel 6d33d3d8ac Refactor: extract page/document manager into separate class 2026-03-10 12:33:34 +01:00
Zef Hemel cb9f954bc7 Refactor: extract widget cache from Client class 2026-03-10 12:17:02 +01:00
Zef Hemel 822997fd5e Client available upgrade notification
If the server is updated, but the client doesn't match the server
version, a notification will appear instructing the user to reload.
2026-03-10 12:05:33 +01:00
Zef Hemel c2d42849a9 A few more format and type fixes 2026-03-10 09:42:48 +01:00
Zef Hemel 799e27a9b4 Enable biome based formatter and reformat 2026-03-10 09:38:59 +01:00
Zef Hemel cce5b669f6 Merge branch 'main' into to-node 2026-03-10 08:57:58 +01:00
Matouš Jan Fialka 9c9ca047f0 Fix: Handle tagged floats before plain object check in renderCellContent
Tagged floats (`{value: N, isFloat: true}`) were matched by
`isPlainObject` and rendered as a two-column table with "value" and
"isFloat" headers instead of as a formatted number. This is now fixed.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-09 12:57:53 +01:00
Matouš Jan Fialka 2aaa797bda Improve Lua Widget Rendering
Lua `${...}` expression results are rendered using two parallel paths:

- **HTML path** (display path) for visual display in the editor and
- **Markdown path** (copy path) for the *copy button* output.

Every Lua value is classified as one of:

- **Scalar:** number, string, boolean, or `nil`
- **Empty table:** `{}`
- **Array:** a `LuaTable` with only sequential integer keys (no string keys)
- **Array of tables:** an array where every element is a `LuaTable`
- **Record:** a `LuaTable` with any string key (may also have integer keys)

Scalars are rendered as inline Markdown - wiki links, tags, bold, and
other inline syntax are resolved, `nil` renders as `<span data-empty>`.

Empty tables render as `<table data-table-empty>`.

An array of tables renders as a multi-row `<table>`. Column headers
are the union of all element keys. Each cell value recurses through
the same classification.

An array of scalars (or a mix of scalars and tables) renders as `<ul>`
with one `<li>` per element. Each item value recurses.

A record renders as a single-row `<table>` with one column per key.
Cell values recurse.

Every `<td>` carries `data-table-cell-type` and optionally
`data-table-cell-empty`.  Every `<li>` carries `data-list-item-type` and
optionally `data-list-item-empty`.  The outermost element carries
`data-type`.  These attributes allow CSS styling of rendered widgets.

Nesting is **unlimited**. Tables inside cells, lists inside cells,
tables inside list items all render correctly in HTML.

Scalars render as plain text. Lua `nil` renders as `nil`. Empty tables
render as `*(empty table)*`.

An array of tables renders as a pipe-delimited Markdown table. Nested
values in cells are rendered as Lua literals via `toStringAsync()`
(e.g. `{1, 2, 3}` or `{a = 1}`), since Markdown table cells cannot
contain block-level content.

An array of scalars renders as a Markdown list (`- item`). When a list
item is itself multi-line (a sublist) it uses an empty bullet with
two-space indented content on the next line:

```
- 1
- 2
-
  - nested 1
  - nested 2
```

Nested tables or arrays **beyond the first list nesting** level are
rendered as Lua literals.

A record renders as a single-row Markdown table.

Column headers follow the order returned by `LuaTable.keys`: string keys
in their insertion order, followed by integer keys in ascending order.
For example, `{a = 1, b = 2, 3, d = 4}` produces columns `a
| b | d | 1`. This is consequence of `LuaTable` storing string keys
and the array part separately (for performance).

Arrays mixing plain scalars and record-like tables (e.g.  `{1, 2, 3,
{a=3}}`) were previously rendered as a single flat table due to an
internal JS conversion (`toJS`). They now render as a list, with record
elements shown as nested tables - which more accurately reflects their
Lua structure. This is the only divergence from the original
presentation.

To restore the old tabular layout, wrap all elements as records with
a consistent key:

```lua
-- Before (was a flat table, now a list with nested table):
${{1, 2, 3, {a=3}}}

-- After (explicit records, renders as a table):
${{{value=1}, {value=2}, {value=3}, {a=3}}}
```

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-09 11:45:04 +01:00
Zef Hemel a5c9227499 deno fmt 2026-03-08 16:11:29 +01:00
Zef Hemel 0452910b0b Fixes #1777 2026-03-08 16:00:18 +01:00
Zef Hemel bbcd9ac6aa Introduce new noFloatingPromises lint rule and fix violiations 2026-03-08 15:49:45 +01:00
Zef Hemel 5c9dba30de Merge branch 'main' into to-node 2026-03-06 14:37:03 +01:00
Zef Hemel 82f1c9dd74 Cleaned up imports/exports 2026-03-06 14:36:23 +01:00
Matouš Jan Fialka 81f5ec7f67 Fix table cell alignment for missing and misaligned cells
The table style is determined by the header row. After normalizing the
header (filling empty cells between consecutive delimiters), extract
two properties: the column count and whether the header starts with
a delimiter.

For each data row, normalization proceeds in three steps. First, fill in
empty cells between consecutive delimiters (this handles empty cells in
the middle of a row). Second, if the header has no leading delimiter but
the row does, insert an empty cell after the row's leading delimiter (this
corrects the one-position shift caused by the row having a leading pipe
that the header lacks. Third, if the row has fewer cells than the header
column count, pad with empty cells at the end (this handles rows that
are shorter than the header because trailing pipes or cells were
omitted).

The same normalization is applied both in the renderer and the indexer.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-06 14:20:48 +01:00
Zef Hemel 947edf52c8 Remove redundant type argument 2026-03-06 13:59:37 +01:00
Zef Hemel 3859af0260 Remove redundant Deno global vars 2026-03-06 13:57:28 +01:00
Zef Hemel adfa5e5596 Bring autofocus back in auth 2026-03-06 13:53:57 +01:00
Zef Hemel 8a2424f27f Fix mini editor regressions 2026-03-06 13:50:29 +01:00
Zef Hemel d6424b714a Merge branch 'main' into to-node 2026-03-06 13:38:23 +01:00
Zef HemelandGitHub c75f48d8a3 Merge pull request #1819 from onespaceman/panels
Panels - strings to elements
2026-03-06 13:30:03 +01:00
Matouš Jan FialkaandGitHub b5fadf4dc2 Merge branch 'silverbulletmd:main' into fix-table-indexer-empty-cells 2026-03-06 08:58:08 +01:00
Matouš Jan Fialka 9b37060d9f Extract normalizer to helper shared by both parser and renderer
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-06 08:45:16 +01:00
Zef Hemel 06e4a4c7ed Fixes #1869 2026-03-06 08:20:45 +01:00
Zef Hemel dbf275d75b Introduce biome as linter with lint fixes 2026-03-06 08:05:13 +01:00
Zef Hemel de32dfb0f5 Auto discover lua test files 2026-03-05 16:39:19 +01:00
Zef Hemel 873fa7e4f5 Further simplification of runtime loading 2026-03-05 16:38:05 +01:00
Zef Hemel 9d39c8b1b8 Merge branch 'main' into to-node 2026-03-05 16:26:16 +01:00
Zef Hemel 856b176ce7 Fixes #1864 by making ordering stable 2026-03-05 08:12:19 +01:00
Zef Hemel 444349c3f3 Cleanup plug runtime loading during compilation
Note: drops custom worker URL support (which I doubt anybody used)
2026-03-04 16:07:38 +01:00
Zef Hemel e218433f52 Merge remote-tracking branch 'origin/main' into to-node
# Conflicts:
#	client/space_lua/query_collection.test.ts
2026-03-04 15:47:09 +01:00
Zef Hemel 1178f7bc92 Fix: ordering of space-lua scripts
No priority defined now means priority 0
2026-03-04 15:40:59 +01:00
Matouš Jan Fialka 879bfb811a [LIQ] group by: Convert plain JS objects to LuaTable in results
Items from `index.tag` are stored as plain JS objects when no metatable
is defined. The `group by` clause wraps rows in `LuaTable` (`key`,
`group`) but leaves the individual `group` items as plain JS objects.
This causes `t.keys is not a function` errors when passing `row.group`
to APIs like `template.each` that expect `LuaTable` instances.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-04 11:47:28 +01:00
Matouš Jan Fialka df998ebc68 [LIQ] order by: Pre-compute sort keys before merge sort (Schwartzian transform)
Evaluate all `order by` expressions once per item in a decorate pass,
then compare cached keys during sort. Reduces Lua eval calls from
*O(kn log n)* to *O(kn)* where *k* is the number of sort keys.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-04 09:58:43 +01:00
Matouš Jan Fialka a1024212ee [LIQ] order by: Replace Quicksort with merge sort with SWO violation detection
- Add iterative async stable merge sort (*O(n log n)*).
- Replace Quicksort with the new merge sort (kept Quicksort for tables).
- Update documentation (reorganize for logical flow, add SWO section
  with invalid comparator example that really throws).

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-04 09:06:11 +01:00
Matouš Jan Fialka 01dd7c1db4 [Space Lua] LIQ: Add using ... support to order by
* support for custom comparators in LIQ `order by` clauses via the
  `using` keyword.

* `using` is mutually exclusive with `asc`/`desc` and accepts either
  a *named function* or an *inline anonymous function*. The comparator
  receives two values and returns true if the first should come before the
  second.

* `nulls first`/ `nulls last` works independently of `using`.

* `using` is now a reserved keyword (`kw`; this cannot be avoided but
  the chance to collide with user scripts is negligable),

* documentation updated + polished a little

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-03 14:47:28 +01:00
Matouš Jan Fialka 7cc39ce62f Show null/missing query cells as empty instead of *(null)*
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-03 09:25:45 +01:00
Matouš Jan Fialka b786d65307 [LIQ] Add filter(where <cond>) clause for per-row aggregate filtering
Implements `filter(where <cond>)` for aggregate functions in LIQ
queries which allows per-row conditional filtering within grouped
aggregates. Also extends test suite and documentation.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-03 08:29:18 +01:00
Matouš Jan Fialka e35b61d050 Rename LUA_SQL_NULL to LIQ_NULL
Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-02 14:07:07 +01:00
Matouš Jan Fialka 0d49a7b0de [Space Lua] Load scripts without priority last during reload
The new null-aware ordering in `orderByCompare` changed the default
placement of undefined values for descending sorts to `nulls first` (SQL
standard). This caused Space Lua scripts without a `-- priority:`
comment to load before the `Std` library scripts and breaking the boot
sequence for user scripts ran before `schema`, `config`, `widget` and
other core definitions were available.

Add explicit `nulls: "last"` to the reload query so scripts without
priority always load last, matching the documented behavior.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-02 13:44:28 +01:00
Matouš Jan Fialka ff6854f6ee [LIQ] Add nulls first / nulls last to order by
Extend the `order by` clause with optional `nulls first` and `nulls
last` modifiers following standard SQL semantics. Each sort key can
independently specify where `nil` values should appear in the result. By
default, ascending sorts place nulls last and descending sorts place
nulls first. An explicit nulls first or nulls last overrides this
default. The `asc` keyword is also now accepted as an explicit
alternative to the default ascending direction. Documentation and tests
were updated accordingly.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-03-02 12:34:25 +01:00
Zef Hemel 380b5d90ca More Deno cleanup 2026-02-27 16:25:34 +01:00
Zef Hemel 9e49794ac8 Remove file:// Deno-ism from plug compiler
- Drop file:// URL prefix from generated plug imports; use plain
  absolute paths instead (esbuild resolves these natively)
- Remove the file-url-resolver esbuild plugin that was only needed
  to strip that prefix
2026-02-27 16:08:31 +01:00
Zef Hemel 42ff234801 Cleanup test 2026-02-27 15:47:25 +01:00
Matouš Jan Fialka 8f193dc402 [LIQ] Fix: preserve queryable collections in query evaluation
Check for already-queryable objects (e.g. `DataStoreQueryCollection`)
before `LuaTable` extraction or `luaValueToJS` conversion, preventing
them from being destroyed by the collection normalization pipeline.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-02-27 15:44:26 +01:00
Zef Hemel efc0d24e11 Fixes 2026-02-27 15:35:34 +01:00
Matouš Jan Fialka cad71aa586 [LIQ] Fix: group by keys and collection handling
- Fix `group by` key building: populate array indices from
  `keyParts` instead of only from `keyRecord`, which was empty for
  some expressions (e.g. `tags[1]`).

- Fix collection handling: treat record-like `LuaTables` (no array part)
  as items instead of extracting zero items.

- Update test suite.

Signed-off-by: Matouš Jan Fialka <mjf@mjf.cz>
2026-02-27 15:30:40 +01:00
Zef Hemel 803c5c478d Merge remote-tracking branch 'origin/main' into to-node 2026-02-27 15:05:49 +01:00