@svelterm/core 0.1.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +465 -0
- package/README.md +42 -29
- package/dist/src/cli/build.d.ts +13 -0
- package/dist/src/cli/build.js +119 -0
- package/dist/src/cli/bundle.d.ts +25 -0
- package/dist/src/cli/bundle.js +61 -0
- package/dist/src/cli/dev.d.ts +10 -0
- package/dist/src/cli/dev.js +152 -0
- package/dist/src/cli/devtools.d.ts +9 -0
- package/dist/src/cli/devtools.js +47 -0
- package/dist/src/cli/init.d.ts +8 -0
- package/dist/src/cli/init.js +153 -0
- package/dist/src/cli/main.d.ts +9 -0
- package/dist/src/cli/main.js +52 -0
- package/dist/src/cli/svt-bin.d.ts +2 -0
- package/dist/src/cli/svt-bin.js +6 -0
- package/dist/src/cli/svt.d.ts +14 -0
- package/dist/src/cli/svt.js +76 -0
- package/dist/src/components/text-buffer.js +8 -5
- package/dist/src/css/animation-runner.d.ts +15 -6
- package/dist/src/css/animation-runner.js +80 -29
- package/dist/src/css/animation.d.ts +12 -0
- package/dist/src/css/animation.js +21 -0
- package/dist/src/css/calc.js +4 -3
- package/dist/src/css/color.d.ts +19 -0
- package/dist/src/css/color.js +371 -62
- package/dist/src/css/compute.d.ts +31 -4
- package/dist/src/css/compute.js +273 -34
- package/dist/src/css/defaults.d.ts +1 -1
- package/dist/src/css/defaults.js +9 -0
- package/dist/src/css/easing.d.ts +9 -0
- package/dist/src/css/easing.js +95 -0
- package/dist/src/css/incremental.d.ts +1 -1
- package/dist/src/css/incremental.js +2 -2
- package/dist/src/css/interpolate.d.ts +13 -0
- package/dist/src/css/interpolate.js +41 -0
- package/dist/src/css/parser.js +59 -3
- package/dist/src/css/pseudo-elements.d.ts +9 -0
- package/dist/src/css/pseudo-elements.js +97 -0
- package/dist/src/css/selector.d.ts +17 -2
- package/dist/src/css/selector.js +128 -13
- package/dist/src/css/specificity.js +17 -6
- package/dist/src/css/values.d.ts +6 -1
- package/dist/src/css/values.js +13 -6
- package/dist/src/debug/context.d.ts +13 -0
- package/dist/src/debug/context.js +11 -0
- package/dist/src/debug/css.d.ts +12 -0
- package/dist/src/debug/css.js +28 -0
- package/dist/src/debug/dom.d.ts +17 -0
- package/dist/src/debug/dom.js +92 -0
- package/dist/src/devtools/DevTools.compiled.js +327 -0
- package/dist/src/devtools/DevTools.css.js +1 -0
- package/dist/src/devtools/client.d.ts +36 -0
- package/dist/src/devtools/client.js +76 -0
- package/dist/src/framelog.d.ts +54 -0
- package/dist/src/framelog.js +99 -0
- package/dist/src/headless.js +12 -4
- package/dist/src/index.d.ts +66 -3
- package/dist/src/index.js +610 -81
- package/dist/src/input/checkable.d.ts +8 -0
- package/dist/src/input/checkable.js +66 -0
- package/dist/src/input/details.d.ts +6 -0
- package/dist/src/input/details.js +34 -0
- package/dist/src/input/focus.d.ts +6 -0
- package/dist/src/input/focus.js +27 -9
- package/dist/src/input/keyboard.d.ts +2 -2
- package/dist/src/input/keyboard.js +32 -5
- package/dist/src/input/label.d.ts +8 -0
- package/dist/src/input/label.js +53 -0
- package/dist/src/input/modal.d.ts +9 -0
- package/dist/src/input/modal.js +28 -0
- package/dist/src/input/mouse.d.ts +2 -2
- package/dist/src/input/mouse.js +15 -2
- package/dist/src/input/select.d.ts +12 -0
- package/dist/src/input/select.js +63 -0
- package/dist/src/input/selection.d.ts +48 -0
- package/dist/src/input/selection.js +150 -0
- package/dist/src/layout/engine.d.ts +2 -0
- package/dist/src/layout/engine.js +1092 -142
- package/dist/src/layout/flex.js +4 -4
- package/dist/src/layout/size.js +3 -2
- package/dist/src/layout/text.d.ts +3 -2
- package/dist/src/layout/text.js +96 -17
- package/dist/src/layout/unicode.d.ts +20 -0
- package/dist/src/layout/unicode.js +121 -0
- package/dist/src/render/animation-clock.d.ts +57 -0
- package/dist/src/render/animation-clock.js +221 -0
- package/dist/src/render/ansi-text.d.ts +26 -0
- package/dist/src/render/ansi-text.js +131 -0
- package/dist/src/render/ansi.d.ts +18 -0
- package/dist/src/render/ansi.js +64 -19
- package/dist/src/render/border.js +166 -17
- package/dist/src/render/buffer.d.ts +1 -0
- package/dist/src/render/buffer.js +5 -2
- package/dist/src/render/clock.d.ts +35 -0
- package/dist/src/render/clock.js +67 -0
- package/dist/src/render/color-depth.d.ts +8 -0
- package/dist/src/render/color-depth.js +59 -0
- package/dist/src/render/context.d.ts +1 -0
- package/dist/src/render/context.js +17 -21
- package/dist/src/render/cursor-emit.d.ts +18 -0
- package/dist/src/render/cursor-emit.js +50 -0
- package/dist/src/render/diff.d.ts +12 -0
- package/dist/src/render/diff.js +120 -0
- package/dist/src/render/generation.d.ts +9 -0
- package/dist/src/render/generation.js +14 -0
- package/dist/src/render/graphics-layer.d.ts +27 -0
- package/dist/src/render/graphics-layer.js +86 -0
- package/dist/src/render/image.d.ts +27 -0
- package/dist/src/render/image.js +113 -0
- package/dist/src/render/incremental-paint.d.ts +7 -3
- package/dist/src/render/incremental-paint.js +52 -79
- package/dist/src/render/inline.d.ts +59 -0
- package/dist/src/render/inline.js +219 -0
- package/dist/src/render/kitty-graphics.d.ts +24 -0
- package/dist/src/render/kitty-graphics.js +58 -0
- package/dist/src/render/paint-text.js +68 -22
- package/dist/src/render/paint.d.ts +8 -1
- package/dist/src/render/paint.js +358 -31
- package/dist/src/render/png.d.ts +13 -0
- package/dist/src/render/png.js +145 -0
- package/dist/src/render/scrollbar.d.ts +8 -2
- package/dist/src/render/scrollbar.js +71 -14
- package/dist/src/render/snapshot.js +3 -1
- package/dist/src/renderer/default.d.ts +7 -0
- package/dist/src/renderer/default.js +11 -0
- package/dist/src/renderer/index.d.ts +8 -2
- package/dist/src/renderer/index.js +4 -2
- package/dist/src/renderer/node.d.ts +109 -0
- package/dist/src/renderer/node.js +165 -1
- package/dist/src/terminal/capabilities.d.ts +33 -0
- package/dist/src/terminal/capabilities.js +66 -0
- package/dist/src/terminal/clipboard.d.ts +9 -0
- package/dist/src/terminal/clipboard.js +39 -0
- package/dist/src/terminal/io.d.ts +82 -0
- package/dist/src/terminal/io.js +155 -0
- package/dist/src/terminal/screen.d.ts +3 -10
- package/dist/src/terminal/screen.js +5 -28
- package/dist/src/terminal/stdin-router.d.ts +8 -5
- package/dist/src/terminal/stdin-router.js +22 -11
- package/dist/src/utils/node-map.d.ts +24 -0
- package/dist/src/utils/node-map.js +75 -0
- package/dist/src/vite/config.d.ts +62 -0
- package/dist/src/vite/config.js +191 -0
- package/docs/compatibility.md +67 -0
- package/docs/debug/devtools.md +40 -0
- package/docs/debug/svt.md +50 -0
- package/docs/distribution.md +106 -0
- package/docs/elements.md +120 -0
- package/docs/getting-started.md +177 -0
- package/docs/guide/css.md +187 -0
- package/docs/guide/input.md +143 -0
- package/docs/guide/layout.md +171 -0
- package/docs/guide/theming.md +94 -0
- package/docs/how-it-works.md +115 -0
- package/docs/inline-mode.md +77 -0
- package/docs/layout.md +112 -0
- package/docs/motion.md +91 -0
- package/docs/reference/README.md +65 -0
- package/docs/reference/css/properties/border-corner.md +82 -0
- package/docs/reference/css/properties/border-style.md +168 -0
- package/docs/reference.md +227 -0
- package/docs/selectors.md +80 -0
- package/docs/terminal-css.md +149 -0
- package/docs/terminals.md +83 -0
- package/package.json +28 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.23.0 — 2026-07-05
|
|
4
|
+
|
|
5
|
+
Positioning: `relative` offsets apply, and `sticky` arrives.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`position: relative`** — `top/right/bottom/left` now shift the box
|
|
10
|
+
and its descendants visually while flow position and size behave as if
|
|
11
|
+
unshifted, per spec (previously parsed and dropped).
|
|
12
|
+
- **`position: sticky`** (top edge) — inside a scroll container the
|
|
13
|
+
element pins to the container top + `top` once scrolled past, painting
|
|
14
|
+
above in-flow content; descendants move with it. Deviations
|
|
15
|
+
(documented): top-only, no push-out at the containing-block end, and
|
|
16
|
+
hit-testing targets the flow position.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **Opaque backgrounds now cover what's beneath** — an element's
|
|
21
|
+
background fill previously kept stale glyphs from earlier paints, so
|
|
22
|
+
overlapping paints (sticky, absolute) showed old content through the
|
|
23
|
+
background. Fills now clear covered cells.
|
|
24
|
+
|
|
25
|
+
## 0.22.0 — 2026-07-05
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **`Clock` seam for deterministic animation tests** — the animation
|
|
30
|
+
engine's time source *and* its frame scheduler now go through a
|
|
31
|
+
`Clock` interface. `TestClock` (exported) lets tests set time and
|
|
32
|
+
advance it, firing the frame timer at each tick — so the animation and
|
|
33
|
+
transition frame lifecycle is exact, not `setInterval`/`Date.now`
|
|
34
|
+
dependent. `run()` uses the real `systemClock` by default.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- **Docs: `<img>` rendering** — `reference.md` still listed `img` as
|
|
39
|
+
"not rendered", and `elements.md`'s intro contradicted its own Images
|
|
40
|
+
section. Both now describe the half-block + kitty-graphics rendering
|
|
41
|
+
shipped in 0.15.0 / 0.19.0.
|
|
42
|
+
|
|
43
|
+
## 0.21.0 — 2026-07-05
|
|
44
|
+
|
|
45
|
+
DevTools polish.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **Collapsible tree** — ← / → (or Enter) fold and unfold subtrees in
|
|
50
|
+
`svelterm devtools`; nodes with children show a ▸/▾ marker.
|
|
51
|
+
- **Fuller style panel** — the selected node's panel now lists every
|
|
52
|
+
non-default resolved value, instead of a fixed subset of keys.
|
|
53
|
+
- **Clearer connect error** — `svt` and `devtools` both name the exact
|
|
54
|
+
call to enable debugging (`run(App, { debug: true })`) when they can't
|
|
55
|
+
reach a server.
|
|
56
|
+
|
|
57
|
+
## 0.20.0 — 2026-07-05
|
|
58
|
+
|
|
59
|
+
DevTools: a terminal inspector, itself a svelterm app.
|
|
60
|
+
|
|
61
|
+
### Added
|
|
62
|
+
|
|
63
|
+
- **`svelterm devtools`** — connects to a `run(App, { debug: true })`
|
|
64
|
+
app's debug server and shows its live node tree (left) with each
|
|
65
|
+
selected node's computed style and layout box (right); ↑/↓ to select,
|
|
66
|
+
r to refresh. Built with svelterm and the DOM/CSS debug domains — it
|
|
67
|
+
dogfoods the renderer it inspects. See `docs/debug/devtools.md`.
|
|
68
|
+
- The DevTools component is precompiled into the package at build time,
|
|
69
|
+
so it runs without a build step in your project.
|
|
70
|
+
|
|
71
|
+
## 0.19.0 — 2026-07-05
|
|
72
|
+
|
|
73
|
+
Kitty graphics: crisp `<img>` pixels where the terminal supports them.
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- **Kitty graphics protocol** — on kitty, Ghostty, and WezTerm (detected
|
|
78
|
+
via XTVERSION), `<img>` transmits real RGBA pixels scaled to its cell
|
|
79
|
+
box instead of half-blocks. Pixel data transmits once per (element,
|
|
80
|
+
src); each frame re-places over the box and deletes placements for
|
|
81
|
+
images that moved, scrolled away, or unmounted; teardown and suspend
|
|
82
|
+
clear them. Half-blocks stay the buffer fallback everywhere else.
|
|
83
|
+
|
|
84
|
+
## 0.18.0 — 2026-07-04
|
|
85
|
+
|
|
86
|
+
Scroll-region diffing, and a border-clip fix found along the way.
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
|
|
90
|
+
- **DECSTBM scroll diffing** — when a repaint is a clean vertical
|
|
91
|
+
translation of the previous frame (a full-viewport scroll), the diff
|
|
92
|
+
emits a scroll-region command + index/reverse-index and paints only
|
|
93
|
+
the newly revealed rows, instead of rewriting the screen. ~13× less
|
|
94
|
+
output on an 80×40 one-line scroll (`scripts/bench-scroll-bytes.mjs`).
|
|
95
|
+
Falls back to the normal cell diff for any non-translation change.
|
|
96
|
+
|
|
97
|
+
### Fixed
|
|
98
|
+
|
|
99
|
+
- **Scrolled content painted over borders** — a bordered
|
|
100
|
+
`overflow: auto`/`scroll` box clipped its children to the box
|
|
101
|
+
*including* the border cells, so scrolled content overwrote the top
|
|
102
|
+
and bottom border rows. The clip now insets by the border. (Regression
|
|
103
|
+
from 0.13.0's virtual scrolling.)
|
|
104
|
+
|
|
105
|
+
## 0.17.0 — 2026-07-04
|
|
106
|
+
|
|
107
|
+
Debug tooling: a minimal DevTools for terminal apps.
|
|
108
|
+
|
|
109
|
+
### Added
|
|
110
|
+
|
|
111
|
+
- **DOM and CSS debug domains** — over the existing (opt-in) debug
|
|
112
|
+
WebSocket server: `DOM.getDocument` serialises the live node tree,
|
|
113
|
+
`DOM.querySelector` finds nodes by selector, `DOM.getBoxModel` reports
|
|
114
|
+
layout, `DOM.setAttribute`/`removeAttribute` mutate and repaint;
|
|
115
|
+
`CSS.getComputedStyle` returns the resolved style svelterm painted.
|
|
116
|
+
- **`svt` CLI** (`svelterm inspect`) — a client for the protocol:
|
|
117
|
+
`svt tree | query <sel> | style <id> | box <id> | console | raw`,
|
|
118
|
+
JSON on stdout for `jq`. Point it at a `run(App, { debug: true })`
|
|
119
|
+
app.
|
|
120
|
+
|
|
121
|
+
## 0.16.0 — 2026-07-04
|
|
122
|
+
|
|
123
|
+
### Fixed
|
|
124
|
+
|
|
125
|
+
- **`svelterm build` with symlinked component libraries** — a library
|
|
126
|
+
installed via `file:`/`link:` (e.g. a local `@svelterm/ui`) resolves
|
|
127
|
+
its imports from its real path, where the app's `node_modules` isn't
|
|
128
|
+
visible, so `@svelterm/core` and `svelte` failed to resolve. The
|
|
129
|
+
bundler now pins those packages to the project's own installation.
|
|
130
|
+
|
|
131
|
+
## 0.15.0 — 2026-07-04
|
|
132
|
+
|
|
133
|
+
Images: `<img>` on the cell grid.
|
|
134
|
+
|
|
135
|
+
### Added
|
|
136
|
+
|
|
137
|
+
- **`<img>`** — renders as half-blocks (two pixels per cell) from file
|
|
138
|
+
paths or `data:image/png;base64` URIs. PNG decoding (8-bit
|
|
139
|
+
RGB/RGBA/greyscale/palette) is built in with no dependencies, via
|
|
140
|
+
`node:zlib`. Intrinsic size is 1 column per pixel and 1 row per two;
|
|
141
|
+
CSS `width`/`height` scale nearest-neighbour. Loading is async — the
|
|
142
|
+
layout reflows when pixels arrive; transparent pixels show the
|
|
143
|
+
terminal background. (Kitty graphics passthrough is deliberately not
|
|
144
|
+
included yet — half-blocks work everywhere.)
|
|
145
|
+
|
|
146
|
+
## 0.14.0 — 2026-07-04
|
|
147
|
+
|
|
148
|
+
Inline-mode maturity: the mouse works in the live area.
|
|
149
|
+
|
|
150
|
+
### Added
|
|
151
|
+
|
|
152
|
+
- **Inline-mode mouse** — the zone's screen origin comes from a CPR
|
|
153
|
+
(cursor position report) query, snapshotted as the query bytes go out,
|
|
154
|
+
shifted as frames archive, and clamped when growth scrolls the zone.
|
|
155
|
+
Mouse coordinates map through it; clicks on shell history are ignored.
|
|
156
|
+
Origins re-query after resize and suspend/resume.
|
|
157
|
+
- **Playground example** — `inline mode` example with a `svelterm:inline`
|
|
158
|
+
marker that the site preview and the `run/*.mjs` bundles honour.
|
|
159
|
+
|
|
160
|
+
### Fixed
|
|
161
|
+
|
|
162
|
+
- An explicit `mode` now wins over the `fullscreen` flag —
|
|
163
|
+
`mode: 'fullscreen', fullscreen: false` is full-viewport rendering
|
|
164
|
+
without the alternate screen again (embedded previews), instead of
|
|
165
|
+
being forced inline.
|
|
166
|
+
|
|
167
|
+
## 0.13.0 — 2026-07-04
|
|
168
|
+
|
|
169
|
+
Virtual scrolling: long lists repaint at the speed of what's visible.
|
|
170
|
+
|
|
171
|
+
### Changed
|
|
172
|
+
|
|
173
|
+
- **Paint culling** — subtrees fully outside the active clip are skipped
|
|
174
|
+
in the paint walk (cell writes were already clipped, so output is
|
|
175
|
+
identical). A 10,000-row `overflow: scroll` list drops from ~228 ms to
|
|
176
|
+
~1.4 ms per scroll repaint on the benchmark machine
|
|
177
|
+
(`scripts/bench-scroll.mjs`); first paint from ~254 ms to ~5 ms.
|
|
178
|
+
- **Scrollbar extent caching** — the content-size walk behind scrollbar
|
|
179
|
+
overlays is memoized per layout, instead of re-walking every child on
|
|
180
|
+
every frame of the fade.
|
|
181
|
+
|
|
182
|
+
### Fixed
|
|
183
|
+
|
|
184
|
+
- A focused input culled offscreen no longer reports a stale cursor
|
|
185
|
+
position — cursor positions carry the paint generation that wrote
|
|
186
|
+
them, and the terminal cursor hides when its owner leaves the
|
|
187
|
+
viewport.
|
|
188
|
+
|
|
189
|
+
## 0.12.0 — 2026-07-04
|
|
190
|
+
|
|
191
|
+
Terminal matrix evidence: proof the emitted bytes work, per terminal
|
|
192
|
+
class.
|
|
193
|
+
|
|
194
|
+
### Added
|
|
195
|
+
|
|
196
|
+
- **Round-trip test suite** — svelterm's emitted ANSI (full frames,
|
|
197
|
+
incremental diffs, the inline live zone) replays through a terminal
|
|
198
|
+
model in CI and must reproduce the exact cell grid, at every colour
|
|
199
|
+
depth (truecolor / 256 / 16 / mono) and with wide glyphs.
|
|
200
|
+
- **Support matrix** in `docs/terminals.md` — verified vs expected vs
|
|
201
|
+
unknown, per terminal, with the capability columns that matter
|
|
202
|
+
(truecolor, DEC 2026, kitty keys, OSC 52).
|
|
203
|
+
|
|
204
|
+
## 0.11.0 — 2026-07-04
|
|
205
|
+
|
|
206
|
+
Unicode correctness: non-Latin text stops breaking layout.
|
|
207
|
+
|
|
208
|
+
### Fixed
|
|
209
|
+
|
|
210
|
+
- **Cell widths** — text measurement previously assumed one JavaScript
|
|
211
|
+
character = one terminal cell, so CJK, fullwidth forms, and emoji
|
|
212
|
+
misaligned borders, wrapping, and diffs. Layout, paint, truncation,
|
|
213
|
+
and the inline renderer now work in grapheme clusters with East Asian
|
|
214
|
+
Width cell widths; wide glyphs own a continuation cell that diff
|
|
215
|
+
emission skips.
|
|
216
|
+
- **Input editing** — cursor movement, backspace, and delete operate on
|
|
217
|
+
grapheme boundaries (arrow keys no longer split surrogate pairs or ZWJ
|
|
218
|
+
emoji); the terminal cursor position accounts for wide glyphs.
|
|
219
|
+
|
|
220
|
+
## 0.10.0 — 2026-07-04
|
|
221
|
+
|
|
222
|
+
Colour blending: real alpha compositing on the cell grid.
|
|
223
|
+
|
|
224
|
+
### Added
|
|
225
|
+
|
|
226
|
+
- **Alpha colours** — `rgba()`, `hsl(... / a)`, `#rrggbbaa` keep their
|
|
227
|
+
alpha and composite over whatever the cell already holds at paint
|
|
228
|
+
time. Blending over ANSI names uses nominal xterm values; over the
|
|
229
|
+
terminal's default background it assumes black.
|
|
230
|
+
- **Numeric `opacity`** — folds into the element's colours as a blend
|
|
231
|
+
factor (previously any `opacity < 1` just set the dim attribute; the
|
|
232
|
+
non-standard `opacity: dim` still does).
|
|
233
|
+
|
|
234
|
+
## 0.9.0 — 2026-07-04
|
|
235
|
+
|
|
236
|
+
Text & content: wrapping control, path-friendly truncation, and raw
|
|
237
|
+
ANSI passthrough.
|
|
238
|
+
|
|
239
|
+
### Added
|
|
240
|
+
|
|
241
|
+
- **`word-break: break-all`** — wrap at any character (URLs, hashes,
|
|
242
|
+
paths) instead of only at spaces; inherits as in CSS and applies in
|
|
243
|
+
both layout and paint.
|
|
244
|
+
- **`text-overflow: ellipsis-middle`** — the parsed-but-unwired middle
|
|
245
|
+
truncation now paints: `/Users/tom/…/index.ts` style, keeping both
|
|
246
|
+
ends of long paths.
|
|
247
|
+
- **`<svt-ansi>`** — raw ANSI passthrough element: pre-styled output
|
|
248
|
+
(git diff, ls --color, build logs) renders with its own SGR colours
|
|
249
|
+
(16/256/truecolor + attributes); non-SGR sequences are stripped,
|
|
250
|
+
content is `pre`-formatted.
|
|
251
|
+
|
|
252
|
+
## 0.8.0 — 2026-07-04
|
|
253
|
+
|
|
254
|
+
Input completeness: modern key reporting, honest job control, and
|
|
255
|
+
browser-style modals.
|
|
256
|
+
|
|
257
|
+
### Added
|
|
258
|
+
|
|
259
|
+
- **Kitty keyboard protocol** — CSI u key reports parse with correct
|
|
260
|
+
modifiers (`Ctrl+Enter`, `Shift+Space`, …); the protocol is pushed at
|
|
261
|
+
startup and popped on exit and suspend. Terminals without it ignore
|
|
262
|
+
the push and keep the legacy encoding.
|
|
263
|
+
- **Suspend/resume** — `Ctrl+Z` restores the terminal for the shell
|
|
264
|
+
without unmounting; `fg` (SIGCONT) re-enters raw mode, alt screen,
|
|
265
|
+
mouse and keyboard modes, and repaints with component state intact.
|
|
266
|
+
Previously Ctrl+Z tore the app down.
|
|
267
|
+
- **`exitOn` option** — opt into `Ctrl+D` EOF-style exit
|
|
268
|
+
(`run(App, { exitOn: ['ctrl+c', 'ctrl+d'] })`).
|
|
269
|
+
- **Modal `<dialog open>`** — captures keys: Tab/Shift+Tab trap inside
|
|
270
|
+
the dialog, focus pulls in from outside, Escape removes `open` and
|
|
271
|
+
dispatches `close`.
|
|
272
|
+
|
|
273
|
+
### Fixed
|
|
274
|
+
|
|
275
|
+
- Legacy CSI modifier parsing was off by one — `Shift+Arrow` reported
|
|
276
|
+
as Alt, `Ctrl+Arrow` as Shift+Alt.
|
|
277
|
+
|
|
278
|
+
## 0.7.0 — 2026-07-04
|
|
279
|
+
|
|
280
|
+
Inline rendering: svelterm apps that live in the main buffer like a
|
|
281
|
+
CLI tool, not a fullscreen TUI.
|
|
282
|
+
|
|
283
|
+
### Added
|
|
284
|
+
|
|
285
|
+
- **`mode: 'inline'`** — render at the shell cursor: the live area sizes
|
|
286
|
+
to content, updates via cell diffs with relative-only cursor movement
|
|
287
|
+
(LF to grow, erase-below to shrink), and leaves its output in place on
|
|
288
|
+
exit. `fullscreen: false` now routes here too. Mouse reporting is off
|
|
289
|
+
in inline mode (screen-absolute coordinates can't map to an unknown
|
|
290
|
+
origin); keyboard, focus, and the input cursor work as usual.
|
|
291
|
+
- **`FrameLog`** — append-only frame log for streaming sessions:
|
|
292
|
+
`append(Component, props)` / `update` / `archive` / `remove`.
|
|
293
|
+
Archived frames' rows scroll into the terminal's real history
|
|
294
|
+
untouched and their components unmount, so a long session's memory
|
|
295
|
+
tracks the live area, not the transcript. See `docs/inline-mode.md`.
|
|
296
|
+
- **`demo/inline`** — five streaming turns, each archived into
|
|
297
|
+
scrollback (`DEMO=inline npm run demo`).
|
|
298
|
+
|
|
299
|
+
## 0.6.0 — 2026-07-04
|
|
300
|
+
|
|
301
|
+
Terminal integration: selection, clipboard, and a cursor that reads as
|
|
302
|
+
an insertion point.
|
|
303
|
+
|
|
304
|
+
### Added
|
|
305
|
+
|
|
306
|
+
- **Text selection** — drag selects a row-major cell range (painted
|
|
307
|
+
inverted), double-click selects the word, triple-click the line.
|
|
308
|
+
Releasing copies the selection; the next click clears it. Works over
|
|
309
|
+
the diff pipeline without repainting the tree.
|
|
310
|
+
- **Clipboard** — selections copy via OSC 52 (in-band, ssh-safe) plus
|
|
311
|
+
the platform tool (`pbcopy`, `wl-copy`/`xclip`, `clip`) when present;
|
|
312
|
+
`copyToClipboard` is exported for apps.
|
|
313
|
+
- **Cursor shape** — a focused `<input>`/`<textarea>` shows a bar cursor
|
|
314
|
+
(DECSCUSR 6); the terminal's configured shape is restored otherwise
|
|
315
|
+
and on exit.
|
|
316
|
+
|
|
317
|
+
## 0.5.0 — 2026-07-04
|
|
318
|
+
|
|
319
|
+
Terminal robustness: the same app now degrades gracefully from a
|
|
320
|
+
truecolor GPU terminal down to `TERM=xterm` — and respects `NO_COLOR`.
|
|
321
|
+
|
|
322
|
+
### Added
|
|
323
|
+
|
|
324
|
+
- **Capability detection** — colour depth from
|
|
325
|
+
`NO_COLOR`/`COLORTERM`/`TERM`, plus an XTVERSION query identifying
|
|
326
|
+
known-truecolor terminals; DEC 2026 synchronized-output support probed
|
|
327
|
+
via DECRQM. Detection runs in the background with timeouts; the first
|
|
328
|
+
frame paints with modern defaults and re-paints on a downgrade.
|
|
329
|
+
- **Colour degradation** — hex/RGB colours quantize at emit time: xterm
|
|
330
|
+
256 cube/grey-ramp on 256-colour terminals, nearest base colour on
|
|
331
|
+
16-colour terminals, no colour under `NO_COLOR`. ANSI names always
|
|
332
|
+
pass through. Override with `run(App, { colorDepth })`.
|
|
333
|
+
- **Gated synchronized output** — frames wrap in DEC 2026 only when the
|
|
334
|
+
terminal reports the mode (previously sent unconditionally).
|
|
335
|
+
- **`docs/terminals.md`** — what svelterm emits and queries, per depth.
|
|
336
|
+
|
|
337
|
+
## 0.4.0 — 2026-07-04
|
|
338
|
+
|
|
339
|
+
The developer-experience release: `npx @svelterm/core init` to a running,
|
|
340
|
+
hot-reloading, shippable app in one minute.
|
|
341
|
+
|
|
342
|
+
### Added
|
|
343
|
+
|
|
344
|
+
- **`svelterm init <dir>`** — scaffold a working project: counter
|
|
345
|
+
component, vite config, dev/app/build scripts, fork-setup README.
|
|
346
|
+
- **`svelterm build [entry]`** — bundle the component graph, Svelte
|
|
347
|
+
runtime and svelterm into one self-contained `.mjs` (rolldown, node
|
|
348
|
+
platform) that runs with plain `node`. Global CSS via `--css` or
|
|
349
|
+
`src/main.css` convention; component CSS travels in the bundle through
|
|
350
|
+
the new `registerComponentCss` registry that `run()` falls back to.
|
|
351
|
+
- **Terminal-environment `.svelte` compilation** — `terminalServer()`
|
|
352
|
+
compiles components for the terminal environment itself, so
|
|
353
|
+
terminal-only projects need no `vite-plugin-svelte` (the registry
|
|
354
|
+
plugin is not environment-aware and emitted empty component stubs for
|
|
355
|
+
custom environments, rendering a blank screen).
|
|
356
|
+
- **Console forwarding in dev** — `console.log` from the app streams to
|
|
357
|
+
the vite terminal prefixed `[svelterm]`; previously any console call
|
|
358
|
+
crashed `svelterm dev`.
|
|
359
|
+
|
|
360
|
+
### Changed
|
|
361
|
+
|
|
362
|
+
- The `svelterm` bin now dispatches `init` / `dev` / `build`
|
|
363
|
+
subcommands (previously `dev` only).
|
|
364
|
+
- The terminal environment marks `svelte` and `@svelterm/core` as
|
|
365
|
+
`noExternal` so a natively-imported second copy can't split module
|
|
366
|
+
state.
|
|
367
|
+
|
|
368
|
+
## 0.3.0 — 2026-07-04
|
|
369
|
+
|
|
370
|
+
Motion completeness: easing everywhere, and keyframes that understand
|
|
371
|
+
your theme.
|
|
372
|
+
|
|
373
|
+
### Added
|
|
374
|
+
|
|
375
|
+
- **Easing functions** — `animation-timing-function` and
|
|
376
|
+
`transition-timing-function` (longhands and inside the shorthands)
|
|
377
|
+
support `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`,
|
|
378
|
+
`cubic-bezier()`, `steps(n[, start|end])`, `step-start` and `step-end`.
|
|
379
|
+
Easing applies per keyframe segment; non-interpolable values switch when
|
|
380
|
+
eased progress crosses the midpoint, as in CSS.
|
|
381
|
+
- **Keyframe `var()` / `light-dark()`** — keyframe declarations resolve
|
|
382
|
+
custom properties and colour-scheme pairs against the animated element
|
|
383
|
+
when the animation starts.
|
|
384
|
+
|
|
385
|
+
### Changed
|
|
386
|
+
|
|
387
|
+
- Timing functions default to `ease` per spec (previously everything
|
|
388
|
+
interpolated linearly). Declare `linear` explicitly to keep the old
|
|
389
|
+
behaviour.
|
|
390
|
+
|
|
391
|
+
## 0.2.0 — 2026-07-04
|
|
392
|
+
|
|
393
|
+
The browser-compatibility release: any HTML/CSS feature with a sensible
|
|
394
|
+
cell-grid meaning now works as a browser author expects. Full support matrix
|
|
395
|
+
in [`docs/reference.md`](docs/reference.md); manual in [`docs/`](docs/).
|
|
396
|
+
|
|
397
|
+
**Requires** a Svelte fork with the custom renderer API. Until
|
|
398
|
+
[sveltejs/svelte#18505](https://github.com/sveltejs/svelte/pull/18505) lands,
|
|
399
|
+
use [`tomyan/svelte#svelte-custom-renderer`](https://github.com/tomyan/svelte/tree/svelte-custom-renderer)
|
|
400
|
+
(upstream plus the `svelte/renderer` mount export svelterm needs on Node).
|
|
401
|
+
|
|
402
|
+
### Added
|
|
403
|
+
|
|
404
|
+
- **CSS grid** — column and row templates with `fr`/`repeat()`/`minmax()`,
|
|
405
|
+
`grid-column`/`grid-row` placement and spans, `grid-template-areas` with
|
|
406
|
+
named `grid-area`
|
|
407
|
+
- **CSS tables** — `display: table*` including `inline-table`, sections and
|
|
408
|
+
captions, `colspan`/`rowspan`, `vertical-align`, `border-collapse` with
|
|
409
|
+
shared box-drawing grid lines, anonymous table boxes
|
|
410
|
+
- **Animations & transitions** — `@keyframes` wired into the render loop
|
|
411
|
+
with RGB colour interpolation between stops, cell-stepped length
|
|
412
|
+
animation, discrete stepping for other properties; `transition` on style
|
|
413
|
+
changes
|
|
414
|
+
- **Selectors** — attribute operators (`^=`, `$=`, `*=`, `~=`, `|=`),
|
|
415
|
+
`:is()`/`:where()`, the `:nth-child()` family, structural pseudo-classes
|
|
416
|
+
(`:empty`, `:first/last/only-of-type`, `:only-child`),
|
|
417
|
+
`:checked`/`:disabled`/`:enabled`, `::before`/`::after` with `content`
|
|
418
|
+
- **Form controls** — checkboxes and radios, cycling `<select>`,
|
|
419
|
+
`<progress>`/`<meter>` block-glyph bars, `<details>`/`<summary>`,
|
|
420
|
+
labels activate their controls on click
|
|
421
|
+
- **CSS values** — Color Level 4 syntax, `light-dark()`, inline `style`
|
|
422
|
+
attributes, `box-sizing`, `text-transform`, the `ch` unit as a `cell`
|
|
423
|
+
alias
|
|
424
|
+
- **Scrolling** — viewport scrolling with overlay scrollbars, horizontal
|
|
425
|
+
scroll, scroll clamping on resize
|
|
426
|
+
- **Borders** — block-character border styles with half-cell corner
|
|
427
|
+
treatment
|
|
428
|
+
- **IO abstraction** — `ProcessIO` (with `/dev/tty` fallback when stdin is
|
|
429
|
+
piped) and `InProcessIO` for embedding; browser-compatible input parsing
|
|
430
|
+
- **Dev mode** — `svelterm dev` CLI with Vite environments, HMR, and a
|
|
431
|
+
two-process WebSocket bridge
|
|
432
|
+
- **Docs** — chaptered manual under `docs/` and a full feature support
|
|
433
|
+
matrix with MDN links in `docs/reference.md`
|
|
434
|
+
|
|
435
|
+
### Changed
|
|
436
|
+
|
|
437
|
+
- Tracks the upstream unified `mount({ renderer, target, props })` API from
|
|
438
|
+
the `svelte-custom-renderer` branch
|
|
439
|
+
- Exact hex/computed colours are no longer remapped to nearest ANSI names
|
|
440
|
+
- Flex `align-items: stretch` no longer overrides an explicit cross-axis
|
|
441
|
+
size
|
|
442
|
+
|
|
443
|
+
### Fixed
|
|
444
|
+
|
|
445
|
+
- Incremental repaint artifacts (borders, list markers), flex `min-height:
|
|
446
|
+
auto` shrinking per spec, nested `@media` inside selector blocks, inline
|
|
447
|
+
whitespace and list bullets, scroll position clamping after relayout
|
|
448
|
+
|
|
449
|
+
## 0.1.0
|
|
450
|
+
|
|
451
|
+
Initial release — name reservation and early preview.
|
|
452
|
+
|
|
453
|
+
**Requires** the unmerged [`svelte-custom-renderer`](https://github.com/paoloricciuti/svelte/tree/svelte-custom-renderer) branch of Svelte 5.
|
|
454
|
+
|
|
455
|
+
### Features
|
|
456
|
+
|
|
457
|
+
- **CSS engine** — selectors, specificity, cascade, inheritance, scoped styles, `var()`, `calc()`, `@media`, `@keyframes`, `:focus`, `:hover`
|
|
458
|
+
- **Flexbox layout** — `flex-direction`, `justify-content`, `align-items`, `flex-grow`, `flex-shrink`, `flex-basis`, `gap`, `flex-wrap`, `order`
|
|
459
|
+
- **Terminal rendering** — ANSI colors (16, 256, truecolor), box-drawing borders (`single`, `double`, `rounded`, `heavy`), text styles, differential output
|
|
460
|
+
- **Incremental updates** — mutations classified as paint-only, style-resolve, layout-subtree, or layout-bubble to avoid full recomputation
|
|
461
|
+
- **Input handling** — keyboard events, mouse (click, scroll, motion), focus management with Tab/Shift+Tab, bracketed paste
|
|
462
|
+
- **Text input** — `<input>` and `<textarea>` with readline-like editing
|
|
463
|
+
- **Color scheme detection** — automatic `prefers-color-scheme` via OSC 11 terminal query
|
|
464
|
+
- **Debug protocol** — WebSocket-based CDP-inspired server with Console domain
|
|
465
|
+
- **Dual-target components** — same `.svelte` component renders in terminal and browser via `@media (display-mode: terminal/screen)`
|
package/README.md
CHANGED
|
@@ -4,6 +4,14 @@ Svelte 5 components rendered to the terminal with real CSS.
|
|
|
4
4
|
|
|
5
5
|
Write standard Svelte components with `<style>` blocks. They render in the terminal with ANSI escape sequences — flexbox layout, scoped styles, CSS variables, pseudo-classes, all on a cell grid.
|
|
6
6
|
|
|
7
|
+
**Try it:** live playground and docs at [svelterm.dev](https://svelterm.dev), or pipe a demo straight into a real terminal:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
curl -fsSL https://svelterm.dev/run/counter.mjs | node --input-type=module -
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
svelterm is largely LLM-written — designed and directed by a human, with most of the code produced in pair-programming sessions with Claude, test-driven and reviewed as it landed. If that's not your thing, there are plenty of artisanal, hand-typed frameworks out there.
|
|
14
|
+
|
|
7
15
|
> **Early release.** Svelterm requires an unmerged Svelte branch (`svelte-custom-renderer` by [@paoloricciuti](https://github.com/paoloricciuti)) that adds the custom renderer API. It is not usable with mainline Svelte yet.
|
|
8
16
|
|
|
9
17
|
## Example
|
|
@@ -88,21 +96,39 @@ Standard CSS works as expected. These are the terminal-specific additions:
|
|
|
88
96
|
|
|
89
97
|
## Features
|
|
90
98
|
|
|
91
|
-
- **CSS engine** — selectors, specificity, cascade, inheritance, scoped styles, `var()`, `calc()`, `@media`, `@keyframes`
|
|
99
|
+
- **CSS engine** — selectors (attribute operators, structural/state pseudo-classes, `::before`/`::after`), specificity, cascade, inheritance, scoped styles, `var()`, `calc()`, `@media`, `@container`, `@supports`, `@keyframes`
|
|
92
100
|
- **Flexbox layout** — `flex-direction`, `justify-content`, `align-items`, `flex-grow`, `flex-shrink`, `gap`, `flex-wrap`
|
|
101
|
+
- **CSS grid** — column and row templates with `fr`/`repeat()`/`minmax()`, `grid-column`/`grid-row` placement and spans, `grid-template-areas` with named `grid-area`
|
|
102
|
+
- **CSS tables** — `display: table*` including `inline-table`, sections and captions, `colspan`/`rowspan`, column sizing, `vertical-align`, `border-collapse` with shared box-drawing grid lines, anonymous boxes
|
|
103
|
+
- **Animations & transitions** — `@keyframes` with RGB colour interpolation and cell-stepped length animation, `transition` on style changes, easing functions
|
|
93
104
|
- **Terminal rendering** — ANSI colors (16, 256, truecolor), borders, text styles, differential output
|
|
94
105
|
- **Input** — keyboard events, mouse click and scroll, focus management with Tab/Shift+Tab, `:focus` and `:hover` pseudo-classes
|
|
95
|
-
- **
|
|
106
|
+
- **Form controls** — `<input>`/`<textarea>` editing, checkboxes and radios, cycling `<select>`, `<progress>`/`<meter>` bars, `<details>`/`<summary>`
|
|
96
107
|
- **Incremental updates** — mutation tracking classifies changes as paint-only, style-resolve, or layout to avoid full recomputation
|
|
97
108
|
- **Color scheme** — automatic `prefers-color-scheme` detection via terminal queries
|
|
98
109
|
|
|
110
|
+
### Browser compatibility
|
|
111
|
+
|
|
112
|
+
Any HTML/CSS feature with a sensible cell-grid meaning works as a browser
|
|
113
|
+
author expects; pixel-derived features are dropped silently and targeted
|
|
114
|
+
per mode with `@media (display-mode: terminal | browser)`. The manual
|
|
115
|
+
lives in [`docs/`](docs/) — [getting started](docs/getting-started.md),
|
|
116
|
+
[terminal CSS](docs/terminal-css.md), [layout](docs/layout.md),
|
|
117
|
+
[selectors](docs/selectors.md), [elements & input](docs/elements.md),
|
|
118
|
+
[motion](docs/motion.md), [compatibility](docs/compatibility.md),
|
|
119
|
+
[terminal support](docs/terminals.md),
|
|
120
|
+
[inline mode](docs/inline-mode.md) — with
|
|
121
|
+
the one-page support matrix in [`docs/reference.md`](docs/reference.md)
|
|
122
|
+
and the design rationale in
|
|
123
|
+
[`DESIGN-browser-compat.md`](DESIGN-browser-compat.md).
|
|
124
|
+
|
|
99
125
|
## Prerequisites
|
|
100
126
|
|
|
101
|
-
Svelterm requires the experimental custom renderer API
|
|
127
|
+
Svelterm requires the experimental custom renderer API from the [`svelte-custom-renderer`](https://github.com/sveltejs/svelte/pull/18042) branch by [@paoloricciuti](https://github.com/paoloricciuti). Until [sveltejs/svelte#18505](https://github.com/sveltejs/svelte/pull/18505) lands (it exposes `mount`/`unmount` from `svelte/renderer`, which svelterm needs on Node), clone the branch from the svelterm fork, which tracks upstream plus that fix:
|
|
102
128
|
|
|
103
129
|
```bash
|
|
104
130
|
# Clone the branch
|
|
105
|
-
git clone -b svelte-custom-renderer https://github.com/
|
|
131
|
+
git clone -b svelte-custom-renderer https://github.com/tomyan/svelte.git svelte-fork
|
|
106
132
|
cd svelte-fork
|
|
107
133
|
pnpm install
|
|
108
134
|
pnpm -C packages/svelte build
|
|
@@ -120,34 +146,21 @@ Then reference it in your project's `package.json`:
|
|
|
120
146
|
|
|
121
147
|
## Setup
|
|
122
148
|
|
|
123
|
-
|
|
149
|
+
Scaffold a project with the CLI (the Svelte fork above must be a sibling
|
|
150
|
+
directory, or adjust the `svelte` path in the generated `package.json`):
|
|
124
151
|
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
plugins: [
|
|
132
|
-
svelte({
|
|
133
|
-
compilerOptions: {
|
|
134
|
-
experimental: {
|
|
135
|
-
customRenderer: '@svelterm/core',
|
|
136
|
-
},
|
|
137
|
-
css: 'external',
|
|
138
|
-
},
|
|
139
|
-
}),
|
|
140
|
-
],
|
|
141
|
-
build: {
|
|
142
|
-
target: 'node22',
|
|
143
|
-
rollupOptions: {
|
|
144
|
-
external: ['svelte', 'svelte/renderer', 'svelte/internal',
|
|
145
|
-
'svelte/internal/client', 'ws', 'http', 'crypto'],
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
})
|
|
152
|
+
```bash
|
|
153
|
+
npx @svelterm/core init my-app
|
|
154
|
+
cd my-app && npm install
|
|
155
|
+
npm run dev # vite dev server (terminal 1)
|
|
156
|
+
npm run app # the app, hot-reloading, in this terminal (terminal 2)
|
|
157
|
+
npm run build # → dist/app.mjs — self-contained, runs with plain node
|
|
149
158
|
```
|
|
150
159
|
|
|
160
|
+
`console.log` output from the app streams to the vite terminal, like a
|
|
161
|
+
browser console. See [docs/getting-started.md](docs/getting-started.md)
|
|
162
|
+
for manual setup and dual-target configuration.
|
|
163
|
+
|
|
151
164
|
## API
|
|
152
165
|
|
|
153
166
|
### `run(component, options?)`
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* svelterm build — bundle a terminal app into one self-contained .mjs
|
|
3
|
+
* that any Node runtime can execute directly:
|
|
4
|
+
*
|
|
5
|
+
* svelterm build # src/App.svelte → dist/app.mjs
|
|
6
|
+
* svelterm build src/App.svelte -o dist/app.mjs
|
|
7
|
+
*
|
|
8
|
+
* Components compile with the project's Svelte (the custom-renderer
|
|
9
|
+
* fork) targeting @svelterm/core; each carries its extracted CSS via
|
|
10
|
+
* registerComponentCss. Requires rolldown (a dependency of vite 8 —
|
|
11
|
+
* `npm i -D rolldown` if resolution fails).
|
|
12
|
+
*/
|
|
13
|
+
export declare function runBuild(argv: string[]): Promise<void>;
|