You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(termserver): virtual-canvas ANSI-art rendering (new default)
Add AnsiCanvasRenderer: resolves an ANSI-art byte stream against an
off-screen character grid (cursor moves, erase, SGR, save/restore) and
serialises the used rows back to SGR-only lines with no positioning.
Ported from the browser AnsiTerminal in public_html/js/ansisys.js.
TERM_ANSI_ART_MODE gains 'canvas' and it is now the default: art bodies
are canvas-rendered and shown inline in the normal reader, which scrolls,
repaints and resizes them like any other message -- no cursor-control
code reaches the terminal, only colour. 'viewer' (old default), 'inline'
and 'raw' remain. The full-screen positioned view is still on the 'A' key
in every mode.
- AnsiArtViewer::readerRenderMode() replaces readerSkipsWrap(); returns
strict | canvas | raw and drives both the sanitize policy and the
$buildView line-production branch in the Echomail/Netmail viewers.
- Height capped at 1000 rows; lines clipped to the reader width and
re-rendered on resize.
Unit tests for the renderer and the mode helpers, daemon include lists,
.env.example and the three terminal-server docs updated.
Copy file name to clipboardExpand all lines: docs/TerminalServer.md
+7-1Lines changed: 7 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -101,7 +101,13 @@ Pipe-code rendering for plain bulletins and other ANSI/pipe text shared with the
101
101
- Press `T` in the echomail viewer to download the current message as a plain-text `.txt` file via ZMODEM. The filename is derived from the message subject. Uses the built-in ZMODEM implementation by default; no additional software required.
102
102
- Press `E` in the echomail viewer to forward the current message to the logged-in user's email address. Requires outbound email to be configured on the BBS; an error is shown inline if it is not.
103
103
- Press `F` in the echomail viewer to forward the current message. A dialog prompts the user to choose **Echomail** (forward to another subscribed echoarea — opens compose pre-filled with a `Fwd:` subject, attribution header, and quoted body) or **Netmail** (forward as a netmail to an FTN address — uses the standard netmail compose flow). The source echoarea appears in the attribution header in both cases.
104
-
- Press `A` in the echomail or netmail viewer to open the **ANSI art view** — a full-screen render of the message body with cursor positioning intact. `A` only appears (in the Ctrl-K help overlay) when the body is ANSI art. Message bodies are stripped of cursor-positioning sequences before the normal reader shows them (security hardening in 1.10.5), so art that draws itself with absolute cursor moves reflows into unreadable text there; the art view restores in-screen drawing while still blocking window-title/clipboard writes and answerback queries. The `TERM_ANSI_ART_MODE` setting selects the behaviour: `viewer` (default) is the press-`A` flow just described; `inline` makes the full-screen art view open automatically whenever an ANSI-art message is opened, with any key returning to the normal reader; `raw` lets the cursor-positioning and erase codes pass straight through to the normal reader for art messages (which are then not word-wrapped), so the art draws itself in place as you scroll. `raw` is the sysop opting in to in-screen display spoofing within the reader; the window-title/clipboard and answerback protections still apply in all three modes.
104
+
-**ANSI-art messages** (echomail or netmail whose body positions the cursor to place its pieces) are rendered onto a virtual character canvas and shown inline in the normal reader — the reader scrolls, repaints and resizes the art like any other message, and no cursor-control code reaches your terminal. Message bodies are stripped of cursor-positioning sequences before the plain reader would otherwise see them (security hardening in 1.10.5), which is why the canvas exists: it resolves the cursor moves against an off-screen grid first. Press `A` (shown in the Ctrl-K help overlay only when the body is art) for a full-screen render with real cursor positioning for maximum fidelity.
105
+
- The `TERM_ANSI_ART_MODE` setting selects how art is handled:
106
+
-`canvas` (default) — virtual-canvas render inline; `A` for the full-screen view.
107
+
-`viewer` — inline reader shows the escape-filtered, reflowed body; `A` for the full-screen view.
108
+
-`inline` — the full-screen view opens automatically whenever an art message is opened; any key returns to the reader.
109
+
-`raw` — cursor-positioning and erase codes pass straight through to the normal reader for art messages (which are then not word-wrapped), so the art draws itself in place as you scroll. This is the sysop opting in to in-screen display spoofing within the reader.
110
+
The window-title/clipboard (OSC) and answerback/device-status protections apply in every mode.
105
111
- Press `G` in the echomail viewer to **add an ignore rule** for the current message's sender. A sub-menu offers three options: **By sender name** (hides all future messages from that name), **By FTN address** (hides messages from that name at that address — only shown if the message carries an FTN address), and **Subject keyword** (hides future messages from that sender whose subject contains the given keyword). Options 1 and 2 show a confirmation dialog pre-filled from the message header; option 3 prompts for a keyword string. The rule is saved via `POST /api/messages/echomail/ignore-rules`. `G` is available in the Ctrl-K help overlay only (not the status bar).
106
112
- Press `G` from the **echoarea list** to open the **Ignore Rules** management screen. Rules are fetched from `GET /api/user/echomail-ignore-rules` and displayed in a paginated selectable list. Each row shows the sender name and, where set, the FTN address and subject keyword. Select a rule and press Enter or `D` to delete it after confirmation via `DELETE /api/user/echomail-ignore-rules/{id}`. `G` appears in the Ctrl-K help overlay on the echoarea list.
107
113
- The **echoarea list** (the screen showing your subscribed areas) uses the same navigable list interface as message lists. Arrow Up/Down moves the highlight cursor; Arrow Left/Right (or `n`/`p`) changes pages; Enter selects the highlighted area; typing a number jumps the cursor to that row. A status bar at the bottom shows available actions. Press `/` to filter the list by tag or description, `C` to clear the filter, and (when Interests is enabled) `I` to open the interests browser. The list redraws immediately on terminal resize.
|`viewer` (default) | Body sanitized `POLICY_STRIP` and reflowed; press `A` for `AnsiArtViewer::show()`. |
342
-
|`inline`| Same as `viewer`, plus `AnsiArtViewer::show()` auto-launches once per message open. |
343
-
|`raw`| For art bodies: `AnsiArtViewer::readerBodyPolicy()` returns `POLICY_POSITIONING` so the handler sanitizes permissively, and `AnsiArtViewer::readerSkipsWrap()` returns true so `$buildView` splits the body on newlines instead of calling `wrapTextLines()`. The cursor codes reach the terminal from inside the normal scroll viewer. |
344
-
345
-
The two `reader*` helpers take the `$isArt` flag and both no-op unless the mode
346
-
is `raw` and the body is art, so every non-art message and every other mode keeps
347
-
the strict path.
320
+
### ANSI art
321
+
322
+
Two pieces cooperate. `TerminalTextSanitizer::sanitize($raw, POLICY_POSITIONING)`
323
+
keeps a whitelist of cursor-movement and erase sequences on top of SGR while
324
+
still removing OSC, DCS/APC/PM, private-mode sequences,
325
+
device-status/answerback queries and C0/C1 bytes — the input-injection and
326
+
clipboard/title vectors stay closed regardless of mode.
Copy file name to clipboardExpand all lines: docs/UPGRADING_1.10.6.md
+23-15Lines changed: 23 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,21 +32,29 @@ changes are made.
32
32
their absolute cursor positioning. Escape sequences are now treated as
33
33
zero-width and are never split; wrapping only breaks on character boundaries.
34
34
35
-
-**ANSI-art message viewer:** echomail and netmail whose body is ANSI art (it
36
-
positions the cursor to place its pieces) can now be viewed as art. The inline
37
-
reader still shows the escape-filtered, reflowed body; pressing `A` opens a
38
-
dedicated full-screen view that renders the art with cursor positioning
39
-
intact. That view still strips window-title/clipboard writes (OSC),
40
-
answerback/device-status queries and other input-injection sequences — only
41
-
in-screen drawing is restored. The `TERM_ANSI_ART_MODE` setting controls this:
42
-
`viewer` (default) is the press-`A` behaviour above; `inline` opens the
43
-
full-screen art view automatically whenever an art message is opened, and any
44
-
key drops through to the normal reader; `raw` passes cursor-positioning and
45
-
erase sequences straight through to the normal reader for art messages (and
46
-
does not word-wrap them), so the art renders in place during normal scrolling.
47
-
`raw` reintroduces in-screen display spoofing inside the message reader — the
48
-
sysop opts into that tradeoff; the OSC/DCS/answerback vectors stay closed in
49
-
every mode.
35
+
-**ANSI-art messages render on a virtual canvas:** echomail and netmail whose
36
+
body is ANSI art (it positions the cursor to place its pieces) are now drawn
37
+
onto an off-screen character grid and the resulting coloured lines are shown
38
+
inline in the normal reader. The 1.10.5 security fix strips absolute cursor
39
+
positioning from message bodies, which left ANSI art reflowing into unreadable
40
+
text; the canvas resolves every cursor move against the grid first, so the art
41
+
keeps its layout and the reader still scrolls, repaints and resizes it like
42
+
any other message. No cursor-control code reaches the terminal — only colour.
43
+
Pressing `A` in the reader opens a full-screen view that renders the art with
44
+
real cursor positioning for maximum fidelity; that view (like the inline
45
+
canvas) still strips window-title/clipboard writes (OSC),
46
+
answerback/device-status queries and other input-injection sequences.
47
+
48
+
The `TERM_ANSI_ART_MODE` setting selects the behaviour:
49
+
50
+
| Value | Behaviour |
51
+
|-------|-----------|
52
+
|`canvas` (default) | Art rendered on the virtual canvas inline; `A` for the full-screen view. |
53
+
|`viewer`| Inline reader shows the escape-filtered, reflowed body; `A` for the full-screen view. |
54
+
|`inline`| The full-screen view opens automatically when an art message is opened; any key returns to the reader. |
55
+
|`raw`| Cursor-positioning and erase codes pass straight through to the normal reader for art messages (not word-wrapped). Reintroduces in-screen display spoofing within the reader — the sysop opts in. |
56
+
57
+
The OSC/DCS/answerback protections apply in every mode.
0 commit comments