MarkupString 1.1.0

dotnet add package MarkupString --version 1.1.0
                    
NuGet\Install-Package MarkupString -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MarkupString" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MarkupString" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="MarkupString" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MarkupString --version 1.1.0
                    
#r "nuget: MarkupString, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MarkupString@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MarkupString&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=MarkupString&version=1.1.0
                    
Install as a Cake Tool

MarkupString

Immutable styled text for terminals and the web: a plain string plus layered markup runs over it. One value renders to ANSI, HTML, Pueblo, MXP, BBCode or plain text, and round-trips through JSON without losing a layer it does not understand.

Slicing, padding, wrapping and the rest of the string operations work in display cells (wide CJK, combining marks and emoji sequences count correctly), and they carry the markup with them.

dotnet add package MarkupString

Rendering needs emitters, which live in the format packages — add MarkupString.Ansi and MarkupString.Html for the built-in six.

Usage

using MarkupString;
using MarkupString.Ansi;
using MarkupString.Html;

MarkupRegistry.Default = MarkupRegistry.Empty.WithAnsi().WithHtml();

var text = MarkupText.Concat(
  MarkupText.Plain("Hello, "),
  MarkupText.Wrap(AnsiCodeParser.Parse("hr"), "world"));

text.Render(MarkupFormat.Ansi);   // Hello, \e[1;31mworld\e[0m
text.Render(MarkupFormat.Html);   // Hello, <span style="color: #ff5555">world</span>
text.Render(MarkupFormat.Plain);  // Hello, world

var json = MarkupTextSerializer.Serialize(text);
var back = MarkupTextSerializer.Deserialize(json);

Formats

Plain, Ansi, Html, Pueblo, Mxp, BBCode. MarkupFormat.Custom(name, encoding) declares one of your own; a registry keyed by it renders through your emitters like any built-in.

Extension points

  • IMarkup — a markup layer. Value equality makes identically marked spans coalesce.
  • IMarkupEmitter / IMarkupSetEmitter — how a layer, or a whole run's stack of layers, is written in one format.
  • IFormatFramer — a prologue and epilogue around a rendered document.
  • IMarkupCodec — the JSON shape of a layer. A layer with no codec at read time survives as UnknownMarkup and is written back verbatim, so an old reader does not destroy new markup.

Build a MarkupRegistry from MarkupRegistry.Empty with With(...), pass it per call, or install it once as MarkupRegistry.Default (set-once: a second, different registry throws).

Composing with another kind package

A registry holds one IMarkupSetEmitter per format, and the last registration wins — so a kind package that registers a set emitter for, say, Html takes that format over from whatever registered it before, for every layer, not only its own. WithAnsi().WithHtml() works because MarkupString.Html deliberately hands the styling half back: it implements IAnsiStyleSource on its own markup, and the ANSI package's set emitters fold that into their output. If your kind wants ANSI styling applied to it, do the same — implement IAnsiStyleSource and let the ANSI set emitters run — rather than registering a competing set emitter, which would silently drop every other kind's contribution to that format.

Per-layer IMarkupEmitters are keyed by (markup type, format), so unrelated kinds never collide there; only the set emitter and the framer are one-per-format.

AOT and trimming

IsAotCompatible; no reflection, no dynamic code, no source generators. Registration is explicit, so nothing needs a trimmer root beyond what you reference.

Licence

Apache-2.0. Source, guides and issues: SharpMUSH/MarkupString.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on MarkupString:

Package Downloads
MarkupString.Html

Raw HTML tag markup for MarkupString — an MXP <send>, an anchor, a span — rendered as itself in the HTML, Pueblo and MXP formats, folded into terminal styling elsewhere, with the stylesheet for the ms-* classes the emitters write.

MarkupString.Ansi

Terminal styling for MarkupString: colours (16, 256 and truecolor), text attributes and links, an ansi() code parser, and emitters that fold a run's layers into one SGR sequence, HTML span, Pueblo/MXP tag or BBCode tag.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 48 9/7/2026
1.0.0 42 9/7/2026