diff --git a/CHANGELOG.md b/CHANGELOG.md
index 45d9210..0328943 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,17 @@ follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
+## 2.18.1 — 2026-10-13
+
+### Changed
+
+- **`Repeat` writes the text once instead of concatenating copies.** It builds the string in a few
+ block copies and the runs directly, so `MarkupText.Space.Repeat(1000000)` takes about 1 ms and 2 MB
+ instead of 18 ms and 18 MB. Padding, fills and blank lines in layouts go through it too. The
+ result is unchanged.
+
+## 2.18.0 — 2026-10-10
+
### Added
- **More theme colours.** `ThemeRole` gains `Subtle` (text quieter than muted), `Link`, `Highlight` (a
@@ -18,17 +29,22 @@ follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- **A page can theme the sixteen ANSI colours.** HTML writes a standard colour as
`var(--ms-ansi-N, #hex)`, so a page that sets `--ms-ansi-0` to `--ms-ansi-15` gives `ansi()` colours
its own scheme, and `--ms-ansi-bg-N` for backgrounds. A page that sets none shows the same colours as before.
-- **Text for a client without Unicode.** `AsciiFold` replaces each character an ASCII-only or
- Latin-1 client cannot show with the nearest one it can (`·` to `*`, `—` to `-`, `é` to `e`, `?` for
- the rest), keeping markup and, for the built-in stand-ins, each character's width. A game's own
- stand-ins come first. `LayoutContext.Fold` folds the text inside every block before it is
- measured, through the new `Block.MapText`, so tables stay aligned whatever the stand-ins' widths.
### Changed
- **A base16 palette's tertiary colour is `base09` (orange),** not `base0C`, which info already used,
so bullets and info text are no longer the same colour.
+## 2.17.0 — 2026-10-09
+
+### Added
+
+- **Text for a client without Unicode.** `AsciiFold` replaces each character an ASCII-only or
+ Latin-1 client cannot show with the nearest one it can (`·` to `*`, `—` to `-`, `é` to `e`, `?` for
+ the rest), keeping markup and, for the built-in stand-ins, each character's width. A game's own
+ stand-ins come first. `LayoutContext.Fold` folds the text inside every block before it is
+ measured, through the new `Block.MapText`, so tables stay aligned whatever the stand-ins' widths.
+
## 2.16.0 — 2026-10-09
### Added
diff --git a/MarkupString.Ansi/MarkupString.Ansi.csproj b/MarkupString.Ansi/MarkupString.Ansi.csproj
index 6e40348..cbc0318 100644
--- a/MarkupString.Ansi/MarkupString.Ansi.csproj
+++ b/MarkupString.Ansi/MarkupString.Ansi.csproj
@@ -12,7 +12,7 @@
each time one goes out; drop it for a release that removes public API on purpose, and put
it back straight after. -->
true
- 2.15.5
+ 2.18.0
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.
diff --git a/MarkupString.Html/MarkupString.Html.csproj b/MarkupString.Html/MarkupString.Html.csproj
index 4f3b848..ecf9152 100644
--- a/MarkupString.Html/MarkupString.Html.csproj
+++ b/MarkupString.Html/MarkupString.Html.csproj
@@ -12,7 +12,7 @@
each time one goes out; drop it for a release that removes public API on purpose, and put
it back straight after. -->
true
- 2.15.5
+ 2.18.0
Raw HTML tag markup for MarkupString — an anchor, a pre, a span — rendered as itself in the HTML, Pueblo and MXP formats and folded into terminal styling elsewhere, with checked construction and tag policies for untrusted input.
diff --git a/MarkupString.Mxp/MarkupString.Mxp.csproj b/MarkupString.Mxp/MarkupString.Mxp.csproj
index fb94028..079ec3e 100644
--- a/MarkupString.Mxp/MarkupString.Mxp.csproj
+++ b/MarkupString.Mxp/MarkupString.Mxp.csproj
@@ -12,7 +12,7 @@
each time one goes out; drop it for a release that removes public API on purpose, and put
it back straight after. -->
true
- 2.15.5
+ 2.18.0
MXP for MarkupString: writes the shared vocabulary — sounds, music, pictures, panes, gauges, status, variables, link expiry, relocation, login prompts — as MXP tags, holding each to what the client said it supports.
diff --git a/MarkupString.Pueblo/MarkupString.Pueblo.csproj b/MarkupString.Pueblo/MarkupString.Pueblo.csproj
index 4876f45..e26be55 100644
--- a/MarkupString.Pueblo/MarkupString.Pueblo.csproj
+++ b/MarkupString.Pueblo/MarkupString.Pueblo.csproj
@@ -12,7 +12,7 @@
each time one goes out; drop it for a release that removes public API on purpose, and put
it back straight after. -->
true
- 2.15.5
+ 2.18.0
Pueblo for MarkupString: writes the shared vocabulary — sounds, pictures, panes, clearing the screen, prefetching — in the Pueblo client's own HTML extensions.
diff --git a/MarkupString.Tests/MarkupTextOperationsTests.cs b/MarkupString.Tests/MarkupTextOperationsTests.cs
index 885dbdd..4c7b688 100644
--- a/MarkupString.Tests/MarkupTextOperationsTests.cs
+++ b/MarkupString.Tests/MarkupTextOperationsTests.cs
@@ -360,6 +360,47 @@ public async Task Repeat_ThreeTimes_RepeatsCorrectly()
public async Task Repeat_ZeroTimes_ReturnsEmpty()
=> await Assert.That(MarkupText.Plain("ab").Repeat(0).Length).IsEqualTo(0);
+ public static IEnumerable> RepeatUnits()
+ {
+ yield return () => MarkupText.Space;
+ yield return () => MarkupText.Plain("abc");
+ yield return () => MarkupText.Wrap(Red, "-");
+ yield return () => MarkupText.Wrap(Red, "ab");
+ yield return () => MarkupText.Concat([MarkupText.Wrap(Red, "a"), MarkupText.Plain("bc"), MarkupText.Wrap(Red, "d")]);
+ yield return () => MarkupText.Concat(MarkupText.Plain("x"), MarkupText.Wrap(Red, "y"));
+ yield return MarkupText.Bell;
+ yield return () => MarkupText.Concat(MarkupText.Plain("Hey"), MarkupText.Bell());
+ }
+
+ /// Repeat builds what concatenating the copies one by one builds, runs and all.
+ [Test]
+ [MethodDataSource(nameof(RepeatUnits))]
+ public async Task Repeat_MatchesConcatenatedCopies(MarkupText unit)
+ {
+ foreach (var count in new[] { 2, 3, 7, 64, 1001 })
+ {
+ var expected = MarkupText.Concat(Enumerable.Repeat(unit, count).ToArray().AsSpan());
+ var result = unit.Repeat(count);
+
+ await Assert.That(result.Text).IsEqualTo(expected.Text);
+ await Assert.That(result.Runs.SequenceEqual(expected.Runs)).IsTrue();
+ }
+ }
+
+ [Test]
+ public async Task Repeat_PlainText_AllocatesOnlyTheString()
+ {
+ const int count = 100_000;
+ GC.KeepAlive(MarkupText.Space.Repeat(count));
+
+ var before = GC.GetAllocatedBytesForCurrentThread();
+ GC.KeepAlive(MarkupText.Space.Repeat(count));
+ var allocated = GC.GetAllocatedBytesForCurrentThread() - before;
+
+ // Two bytes a character for the string, plus the MarkupText itself.
+ await Assert.That(allocated).IsBetween(2L * count, 2L * count + 512);
+ }
+
// Remove, Replace, Insert
[Test]
diff --git a/MarkupString/MarkupString.csproj b/MarkupString/MarkupString.csproj
index 14e0ee3..4ef89ee 100644
--- a/MarkupString/MarkupString.csproj
+++ b/MarkupString/MarkupString.csproj
@@ -12,7 +12,7 @@
each time one goes out; drop it for a release that removes public API on purpose, and put
it back straight after. -->
true
- 2.15.5
+ 2.18.0
Immutable styled text: a string plus layered markup runs, rendered to ANSI, HTML, Pueblo, MXP, BBCode or plain text through a registry of emitters, and round-tripped through JSON.
diff --git a/MarkupString/MarkupText.Operations.cs b/MarkupString/MarkupText.Operations.cs
index a2d8bb0..8e95659 100644
--- a/MarkupString/MarkupText.Operations.cs
+++ b/MarkupString/MarkupText.Operations.cs
@@ -297,9 +297,28 @@ public MarkupText Repeat(int count)
{
if (count <= 0 || Length == 0) return Empty;
if (count == 1) return this;
- var parts = new MarkupText[count];
- Array.Fill(parts, this);
- return Concat(parts.AsSpan());
+ var text = Length == 1
+ ? new string(Text[0], count)
+ : string.Create(checked(Length * count), Text, static (span, unit) =>
+ {
+ // Each copy doubles what is written, so n copies take log n block copies.
+ unit.AsSpan().CopyTo(span);
+ for (var filled = unit.Length; filled < span.Length; filled *= 2)
+ span[..Math.Min(filled, span.Length - filled)].CopyTo(span[filled..]);
+ });
+ if (Runs.IsDefaultOrEmpty) return new MarkupText(text, ImmutableArray.Empty);
+ // One style over the whole text: the copies would coalesce into one run anyway. A point
+ // marks a single carrier, so its copies stay apart.
+ if (Runs is [{ Start: 0 } whole] && whole.Length == Length && !whole.Markups.Any(m => m is IPointMarkup))
+ return new MarkupText(text, [new Run(0, text.Length, whole.Markups)]);
+
+ var runs = ImmutableArray.CreateBuilder(Runs.Length * count);
+ for (var copy = 0; copy < count; copy++)
+ {
+ var offset = copy * Length;
+ foreach (var run in Runs) runs.Add(run with { Start = run.Start + offset });
+ }
+ return new MarkupText(text, runs.MoveToImmutable());
}
/// Removes code units from .
diff --git a/MarkupString/PublicAPI.Shipped.txt b/MarkupString/PublicAPI.Shipped.txt
index 08b97e7..7572a5a 100644
--- a/MarkupString/PublicAPI.Shipped.txt
+++ b/MarkupString/PublicAPI.Shipped.txt
@@ -1,4 +1,10 @@
#nullable enable
+MarkupString.AsciiFold
+MarkupString.AsciiFold.AsciiFold(System.Collections.Generic.IEnumerable>? translations = null, bool latin1 = false) -> void
+MarkupString.AsciiFold.Fold(MarkupString.MarkupText! text) -> MarkupString.MarkupText!
+MarkupString.AsciiFold.Fold(string! text) -> string!
+MarkupString.AsciiFold.Latin1.get -> bool
+MarkupString.AsciiFold.Translations.get -> System.Collections.Generic.IReadOnlyDictionary!
MarkupString.BellMarkup
MarkupString.BellMarkup.Carrier.get -> string!
MarkupString.BufferWriterExtensions
@@ -526,6 +532,8 @@ MarkupString.Layout.LayoutContext.AsciiOnly.init -> void
MarkupString.Layout.LayoutContext.Border(MarkupString.Layout.BorderStyle? style) -> MarkupString.Layout.BorderStyle!
MarkupString.Layout.LayoutContext.Draw(MarkupString.Layout.Block! block, int width, System.Collections.Generic.IList! lines) -> void
MarkupString.Layout.LayoutContext.Equals(MarkupString.Layout.LayoutContext? other) -> bool
+MarkupString.Layout.LayoutContext.Fold.get -> MarkupString.AsciiFold?
+MarkupString.Layout.LayoutContext.Fold.init -> void
MarkupString.Layout.LayoutContext.Glyph(MarkupString.MarkupText! piece, string! fallback) -> MarkupString.MarkupText!
MarkupString.Layout.LayoutContext.Guide(MarkupString.Layout.TreeGuide? guide) -> MarkupString.Layout.TreeGuide!
MarkupString.Layout.LayoutContext.LayoutContext() -> void
@@ -1060,6 +1068,7 @@ MarkupString.ThemePalette.BackgroundColor.get -> MarkupString.RgbColor
MarkupString.ThemePalette.Check() -> System.Collections.Generic.IReadOnlyList!
MarkupString.ThemePalette.Colors.get -> System.Collections.Immutable.ImmutableDictionary!
MarkupString.ThemePalette.Colors.init -> void
+MarkupString.ThemePalette.Completed() -> MarkupString.ThemePalette!
MarkupString.ThemePalette.Contrast.get -> double
MarkupString.ThemePalette.Contrast.init -> void
MarkupString.ThemePalette.Equals(MarkupString.ThemePalette? other) -> bool
@@ -1081,16 +1090,27 @@ MarkupString.ThemePalette.With(MarkupString.ThemeRole role, MarkupString.ThemeCo
MarkupString.ThemePalette.this[MarkupString.ThemeRole role].get -> MarkupString.ThemeColor?
MarkupString.ThemeRole
MarkupString.ThemeRole.Background = 0 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Blue = 19 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Cyan = 18 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Error = 9 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Foreground = 2 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Green = 17 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Highlight = 13 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Info = 10 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Link = 12 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Muted = 6 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Orange = 15 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Pink = 21 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Primary = 3 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Purple = 20 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Red = 14 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Secondary = 4 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Subtle = 11 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Success = 7 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Surface = 1 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Tertiary = 5 -> MarkupString.ThemeRole
MarkupString.ThemeRole.Warning = 8 -> MarkupString.ThemeRole
+MarkupString.ThemeRole.Yellow = 16 -> MarkupString.ThemeRole
MarkupString.TrimType
MarkupString.TrimType.TrimBoth = 2 -> MarkupString.TrimType
MarkupString.TrimType.TrimEnd = 1 -> MarkupString.TrimType
@@ -1143,6 +1163,7 @@ override MarkupString.Layout.Aligned.$() -> MarkupString.Layout.Aligned!
override MarkupString.Layout.Aligned.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Aligned.Equals(object? obj) -> bool
override MarkupString.Layout.Aligned.GetHashCode() -> int
+override MarkupString.Layout.Aligned.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Aligned.ToString() -> string!
override MarkupString.Layout.Block.Equals(object? obj) -> bool
override MarkupString.Layout.Block.GetHashCode() -> int
@@ -1157,11 +1178,13 @@ override MarkupString.Layout.Bullets.$() -> MarkupString.Layout.Bullets!
override MarkupString.Layout.Bullets.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Bullets.Equals(object? obj) -> bool
override MarkupString.Layout.Bullets.GetHashCode() -> int
+override MarkupString.Layout.Bullets.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Bullets.ToString() -> string!
override MarkupString.Layout.Colored.$() -> MarkupString.Layout.Colored!
override MarkupString.Layout.Colored.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Colored.Equals(object? obj) -> bool
override MarkupString.Layout.Colored.GetHashCode() -> int
+override MarkupString.Layout.Colored.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Colored.ToString() -> string!
override MarkupString.Layout.ColumnFormat.Equals(object? obj) -> bool
override MarkupString.Layout.ColumnFormat.GetHashCode() -> int
@@ -1177,6 +1200,7 @@ override MarkupString.Layout.Fields.Draw(MarkupString.Layout.LayoutContext! cont
override MarkupString.Layout.Fields.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Fields.Equals(object? obj) -> bool
override MarkupString.Layout.Fields.GetHashCode() -> int
+override MarkupString.Layout.Fields.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Fields.Measure(MarkupString.Layout.LayoutContext! context, int width) -> MarkupString.Layout.BlockMeasure
override MarkupString.Layout.Fields.ToString() -> string!
override MarkupString.Layout.Figure.$() -> MarkupString.Layout.Figure!
@@ -1184,30 +1208,35 @@ override MarkupString.Layout.Figure.Draw(MarkupString.Layout.LayoutContext! cont
override MarkupString.Layout.Figure.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Figure.Equals(object? obj) -> bool
override MarkupString.Layout.Figure.GetHashCode() -> int
+override MarkupString.Layout.Figure.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Figure.ToString() -> string!
override MarkupString.Layout.Flex.$() -> MarkupString.Layout.Flex!
override MarkupString.Layout.Flex.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Flex.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Flex.Equals(object? obj) -> bool
override MarkupString.Layout.Flex.GetHashCode() -> int
+override MarkupString.Layout.Flex.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Flex.ToString() -> string!
override MarkupString.Layout.Frame.$() -> MarkupString.Layout.Frame!
override MarkupString.Layout.Frame.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Frame.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Frame.Equals(object? obj) -> bool
override MarkupString.Layout.Frame.GetHashCode() -> int
+override MarkupString.Layout.Frame.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Frame.ToString() -> string!
override MarkupString.Layout.Gauge.$() -> MarkupString.Layout.Gauge!
override MarkupString.Layout.Gauge.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Gauge.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Gauge.Equals(object? obj) -> bool
override MarkupString.Layout.Gauge.GetHashCode() -> int
+override MarkupString.Layout.Gauge.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Gauge.ToString() -> string!
override MarkupString.Layout.Grid.$() -> MarkupString.Layout.Grid!
override MarkupString.Layout.Grid.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Grid.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Grid.Equals(object? obj) -> bool
override MarkupString.Layout.Grid.GetHashCode() -> int
+override MarkupString.Layout.Grid.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Grid.ToString() -> string!
override MarkupString.Layout.Indent.GetHashCode() -> int
override MarkupString.Layout.LayoutCell.Equals(object? obj) -> bool
@@ -1238,27 +1267,32 @@ override MarkupString.Layout.Rule.Draw(MarkupString.Layout.LayoutContext! contex
override MarkupString.Layout.Rule.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Rule.Equals(object? obj) -> bool
override MarkupString.Layout.Rule.GetHashCode() -> int
+override MarkupString.Layout.Rule.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Rule.ToString() -> string!
override MarkupString.Layout.Shaded.$() -> MarkupString.Layout.Shaded!
override MarkupString.Layout.Shaded.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Shaded.Equals(object? obj) -> bool
override MarkupString.Layout.Shaded.GetHashCode() -> int
+override MarkupString.Layout.Shaded.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Shaded.ToString() -> string!
override MarkupString.Layout.Sized.$() -> MarkupString.Layout.Sized!
override MarkupString.Layout.Sized.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Sized.Equals(object? obj) -> bool
override MarkupString.Layout.Sized.GetHashCode() -> int
+override MarkupString.Layout.Sized.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Sized.ToString() -> string!
override MarkupString.Layout.Stack.$() -> MarkupString.Layout.Stack!
override MarkupString.Layout.Stack.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Stack.Equals(object? obj) -> bool
override MarkupString.Layout.Stack.GetHashCode() -> int
+override MarkupString.Layout.Stack.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Stack.ToString() -> string!
override MarkupString.Layout.Table.$() -> MarkupString.Layout.Table!
override MarkupString.Layout.Table.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Table.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Table.Equals(object? obj) -> bool
override MarkupString.Layout.Table.GetHashCode() -> int
+override MarkupString.Layout.Table.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Table.ToString() -> string!
override MarkupString.Layout.TableColumn.Equals(object? obj) -> bool
override MarkupString.Layout.TableColumn.GetHashCode() -> int
@@ -1268,6 +1302,7 @@ override MarkupString.Layout.TextBlock.Draw(MarkupString.Layout.LayoutContext! c
override MarkupString.Layout.TextBlock.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.TextBlock.Equals(object? obj) -> bool
override MarkupString.Layout.TextBlock.GetHashCode() -> int
+override MarkupString.Layout.TextBlock.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.TextBlock.Measure(MarkupString.Layout.LayoutContext! context, int width) -> MarkupString.Layout.BlockMeasure
override MarkupString.Layout.TextBlock.ToString() -> string!
override MarkupString.Layout.TextLine.GetHashCode() -> int
@@ -1275,12 +1310,14 @@ override MarkupString.Layout.Themed.$() -> MarkupString.Layout.Themed!
override MarkupString.Layout.Themed.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Themed.Equals(object? obj) -> bool
override MarkupString.Layout.Themed.GetHashCode() -> int
+override MarkupString.Layout.Themed.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Themed.ToString() -> string!
override MarkupString.Layout.Tree.$() -> MarkupString.Layout.Tree!
override MarkupString.Layout.Tree.Draw(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Tree.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
override MarkupString.Layout.Tree.Equals(object? obj) -> bool
override MarkupString.Layout.Tree.GetHashCode() -> int
+override MarkupString.Layout.Tree.MapText(System.Func! map) -> MarkupString.Layout.Block!
override MarkupString.Layout.Tree.ToString() -> string!
override MarkupString.Layout.TreeGuide.Equals(object? obj) -> bool
override MarkupString.Layout.TreeGuide.GetHashCode() -> int
@@ -1353,6 +1390,7 @@ override sealed MarkupString.Layout.Table.Equals(MarkupString.Layout.Block? othe
override sealed MarkupString.Layout.TextBlock.Equals(MarkupString.Layout.Block? other) -> bool
override sealed MarkupString.Layout.Themed.Equals(MarkupString.Layout.Block? other) -> bool
override sealed MarkupString.Layout.Tree.Equals(MarkupString.Layout.Block? other) -> bool
+static MarkupString.AsciiFold.Default.get -> MarkupString.AsciiFold!
static MarkupString.BufferWriterExtensions.Write(this System.Buffers.IBufferWriter! writer, System.ReadOnlySpan text) -> void
static MarkupString.ColorGradient.Blend(MarkupString.RgbColor from, MarkupString.RgbColor to, double t, MarkupString.GradientSpace space) -> MarkupString.RgbColor
static MarkupString.ColorGradient.operator !=(MarkupString.ColorGradient? left, MarkupString.ColorGradient? right) -> bool
@@ -1618,6 +1656,7 @@ static readonly MarkupString.PreformattedMarkup.Instance -> MarkupString.Preform
virtual MarkupString.Layout.Block.DrawLinear(MarkupString.Layout.LayoutContext! context, int width, System.Collections.Generic.IList! lines) -> void
virtual MarkupString.Layout.Block.EqualityContract.get -> System.Type!
virtual MarkupString.Layout.Block.Equals(MarkupString.Layout.Block? other) -> bool
+virtual MarkupString.Layout.Block.MapText(System.Func! map) -> MarkupString.Layout.Block!
virtual MarkupString.Layout.Block.Measure(MarkupString.Layout.LayoutContext! context, int width) -> MarkupString.Layout.BlockMeasure
virtual MarkupString.Layout.Block.PrintMembers(System.Text.StringBuilder! builder) -> bool
virtual MarkupString.Layout.LayoutCell.EqualityContract.get -> System.Type!
diff --git a/MarkupString/PublicAPI.Unshipped.txt b/MarkupString/PublicAPI.Unshipped.txt
index d05ae06..7dc5c58 100644
--- a/MarkupString/PublicAPI.Unshipped.txt
+++ b/MarkupString/PublicAPI.Unshipped.txt
@@ -1,40 +1 @@
#nullable enable
-MarkupString.AsciiFold
-MarkupString.AsciiFold.AsciiFold(System.Collections.Generic.IEnumerable>? translations = null, bool latin1 = false) -> void
-MarkupString.AsciiFold.Fold(MarkupString.MarkupText! text) -> MarkupString.MarkupText!
-MarkupString.AsciiFold.Fold(string! text) -> string!
-MarkupString.AsciiFold.Latin1.get -> bool
-MarkupString.AsciiFold.Translations.get -> System.Collections.Generic.IReadOnlyDictionary!
-MarkupString.Layout.LayoutContext.Fold.get -> MarkupString.AsciiFold?
-MarkupString.Layout.LayoutContext.Fold.init -> void
-override MarkupString.Layout.Aligned.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Bullets.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Colored.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Fields.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Figure.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Flex.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Frame.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Gauge.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Grid.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Rule.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Shaded.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Sized.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Stack.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Table.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.TextBlock.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Themed.MapText(System.Func! map) -> MarkupString.Layout.Block!
-override MarkupString.Layout.Tree.MapText(System.Func! map) -> MarkupString.Layout.Block!
-static MarkupString.AsciiFold.Default.get -> MarkupString.AsciiFold!
-virtual MarkupString.Layout.Block.MapText(System.Func! map) -> MarkupString.Layout.Block!
-MarkupString.ThemePalette.Completed() -> MarkupString.ThemePalette!
-MarkupString.ThemeRole.Blue = 19 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Cyan = 18 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Green = 17 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Highlight = 13 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Link = 12 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Orange = 15 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Pink = 21 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Purple = 20 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Red = 14 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Subtle = 11 -> MarkupString.ThemeRole
-MarkupString.ThemeRole.Yellow = 16 -> MarkupString.ThemeRole