Skip to content

Decode and draw server output with MarkupString - #31

Draft
HarryCordewener wants to merge 3 commits into
masterfrom
claude/project-thread-g3zsec
Draft

HarryCordewener wants to merge 3 commits into
masterfrom
claude/project-thread-g3zsec

Conversation

@HarryCordewener

@HarryCordewener HarryCordewener commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Requested by Grave · project thread

Replaces AnsiParser, MxpParserState and the segment types (StyledSegment, TextStyle, AnsiColor, SegmentStyle, AnsiPalette) with MarkupString.

Waiting on NuGet. This references MarkupString 2.27.0, which is tagged but not on NuGet yet. 2.26.0 lacks two things the old parser did (MXP T= image directories, and a short 38;2;… reading its leftover number as a background colour); SharpMUSH/MarkupString#81 (merged) fixes both and ships in 2.27.0. CI here cannot restore until 2.27.0 is published. The results below were run against a local pack of the v2.27.0 tag.

How it works now

  • OutputDecoder (Core): one MarkupString Decoder per session, with WithVt().WithMxp().WithPueblo(). MXP and Pueblo are turned on by the same telnet events as before, and the decoder is reset when the connection drops. It answers nothing itself (ClientAnswers.None): TNC still answers MXP <SUPPORT>/<VERSION>, and there is no path for VT replies yet.
  • ScrollbackLine holds a MarkupText. OutputView draws SpanRenderer.Render(...) spans, cached per line.
  • OutputDisplay: browser output with URL, command and menu interactions; no sound, no panes; prompt links become command links. Colours come from OutputPalette, an AnsiColors subclass that keeps the client's sixteen colours, with --pho/--outbg as the inverse defaults.
  • Highlight triggers wrap the line in TriggerHighlightMarkup, drawn by a style contributor that runs after the ANSI one, so it replaces the server's colour as before.
  • TriggerEngine.Apply takes the decoded lines, not the raw string (it no longer decodes itself). Rules still match the raw line.
  • MxpTags now claims the tags the decoder and view act on (open tags, A, SEND, IMAGE with t/w/h, custom elements). It still does not claim sound, frames or send.prompt.

Capabilities before, and where each is checked now

Before Now Test
SGR 0, 1, 4, 7, 22, 24, 27, 39, 49 Same OutputRenderingTests.AttributesAreDrawn / AttributesTurnOff / InverseSwaps…
30–37, 90–97, 40–47, 100–107 in the client palette Same palette StandardColoursAreTheClientsOwn, PaletteColoursUseTheClientPalette
38/48;5;n, 38/48;2;r;g;b Same, plus colon forms PaletteColours…, Truecolor…
Truncated 38;2;40 colours nothing Same (needs 2.27.0) TruncatedTruecolorColoursNothing
Inverse swaps against --outbg/--pho Same InverseSwapsColoursAgainstTheOutputDefaults
Bold is not brightened Same BoldIsNotBrightened
Background gets padding:0 2px Same OutputViewTests.BackgroundGetsPadding
Other CSI stripped Stripped OtherControlSequencesAreNotShown
Tags and & literal without MXP/Pueblo Same MarkupIsLiteralWithoutMxpOrPueblo, SessionMxpTests
MXP SEND href/hint on secure lines, shorthand SEND, ignored on open lines Same SendOnSecureLine…, ShorthandSend…, SendOnOpenLine…
Line modes 1, 2, 6 Same, plus the rest of the modes LockSecurePersists…, SecureLineModeEndsWithTheLine, LockedLine…
Colour inside a link keeps the link Same ColourInsideALinkKeepsTheLink, OutputViewLinkTests.CommandLinkKeepsItsColour
MXP/Pueblo entities, numeric, unknown kept, entities in attributes, > inside quotes Same EntitiesAreDecoded, PuebloEntities…, LoneAndUnknown…, EntityInsideAnAttribute…, GreaterThanInsideAQuotedAttribute…
Pueblo a xch_cmd/xch_hint Same PuebloAnchorWithXchCmd…, PuebloCommandLinkIsAButton
MXP IMAGE fname/url/T, Pueblo img src/alt, image inside SEND, data:image Same (T needs 2.27.0), plus width/height MxpImage…, PuebloImg…, ImageInsideASend…, OutputViewLinkTests.MxpImageIsNamedAfterItsFile
Only http(s) and data:image images load; refused ones show nothing Same (ImageSource.Resolve at draw time) NonWebImageSourcesAreRefused, RefusedImageSourceShowsNothing
Images toggle shows the name instead Same ImagesOffRendersTheTextInstead
Highlight trigger recolours the whole line Same TriggerEngineTests, TriggerHighlightReplacesTheServersColour
Dim local echo (palette 8) Same SessionTests.SendAppendsLocalEcho
MXP/Pueblo state dropped on disconnect Same MarkupStateIsDroppedWhenTheConnectionGoesDown, ResetForgetsProtocolsAndStyle

New: faint, italic, blink (ms-blink, off under reduced motion), conceal, strikethrough, overline; OSC 8, MXP <A> and Pueblo <a href> web links (target=_blank, noopener noreferrer, unsafe schemes stay text); MXP open tags (B, I, U, S, H, COLOR, FONT, BR), custom <!ELEMENT>s, and SEND href="a|b" menus (the text sends the first command, a ▾ toggle lists them all).

Behaviour that changes

These follow the terminal and protocol specs, and the decoder does them on purpose:

  • \r and \e[K overwrite in place: x\ry shows y, a\e[2Kb shows b (was ab).
  • An out-of-range truecolour component (38;2;300;0;128) leaves the colour unchanged instead of clamping.
  • Pueblo tags are read only after the server leaves MUD text (</xch_mudtext> or <img xch_mode=html>), which PennMUSH-style servers send after PUEBLOCLIENT. Before that, tags are text.
  • A command link without its own colour now uses .sc-link's accent colour. Before, an inline phosphor colour always covered it.

Tests

Run with the .NET 10.0.114 SDK against a local pack of MarkupString v2.27.0 (3cf3199):

  • SharpClient.Tests: 301 passed, 0 failed
  • SharpClient.UI.Tests: 92 passed, 0 failed
  • SharpClient.Data.Tests: 19 passed, 0 failed
  • SharpClient.Core, .UI, .Web, .Data build in Release with warnings as errors.

Not run: the MAUI Android head (no Android SDK here; CI's android-build job covers it), and the app itself in a browser. The view is covered only by bUnit, so the menu popup's placement still needs a look by eye.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Rqqt7TnKiMidjBirFcUqtL

Replace AnsiParser, MxpParserState and the segment types with MarkupString
2.26.1: a decoder per session (VT, MXP, Pueblo) turns each line into
MarkupText, and OutputView draws SpanRenderer's spans. The client palette
becomes an AnsiColors theme, and a Highlight trigger is a markup layer
drawn by its own style contributor.

Kept: every colour, link, image, entity and MXP line-mode behaviour the old
parser had, the image source rules, and MXP <SUPPORT> answers that claim
only what is drawn. Added: faint, italic, blink, conceal, strikethrough,
overline, colon SGR, OSC 8 and MXP/Pueblo web links, MXP open tags, custom
elements and SEND menus, and carriage-return overwrite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rqqt7TnKiMidjBirFcUqtL
@coderabbitai

coderabbitai Bot commented Nov 7, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@HarryCordewener HarryCordewener self-assigned this Nov 7, 2026
…d short-colour fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rqqt7TnKiMidjBirFcUqtL

Copy link
Copy Markdown
Member Author

Unit tests fails at restore with NU1102: the MarkupString version this PR references is not on nuget.org yet (nearest there is 2.25.0). That run was on 3621e5b (2.26.1). The head now references 2.27.0, which carries the merged SharpMUSH/MarkupString#81. CI stays red until v2.27.0 is tagged and published; no code change here can fix it, and re-running before then gives the same error.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants