Skip to content

TextSpace

Documents & Officev0.5.1-alpha.1 MIT 6

A local-first word processor with paginated paper, built in C#

TextSpace is an independent, local-first word processor built in C#, Uno Platform, SkiaSharp and HarfBuzz. Its ribbon, paginated editing surface, navigation panes, review tools and file workflows are reusable .NET controls—not an embedded web editor. Documents are processed locally with rolling recovery snapshots, and interchange covers native .textspace, bounded DOCX, PDF/PNG, HTML and plain text.

10reusable, packable libraries
17supported field types
9ribbon tabs plus contextual tabs
0accounts, uploads or AI services required
TextSpacewieslawsoltes.github.io/TextSpace/
TextSpace running in a browser
Highlights

What makes TextSpace special

Familiar if you know Word-style word processors — but original, local‑first and written end‑to‑end in C#.

Paginated paper

Mixed-size sections, columns, per-section numbering, first/even/default headers and footers, paragraph keeps and widow control.

A familiar ribbon

A custom ribbon with Home, Insert, Design, Layout, References, Mailings, Review, View and Help, plus contextual table and picture tabs.

HarfBuzz typography

HarfBuzz metrics with aligned tab stops and leaders, styles, paragraph spacing and discretionary or nonbreaking characters.

Live fields and contents

Seventeen field types with F9 updates, locks, sequences and REF/PAGEREF, plus a linked, rebuildable table of contents.

Merged and nested tables

Rectangular merges, split-to-grid, nested tables, header-row repetition, vertical alignment and row splitting.

Navigation and review

Heading outline, page previews, search/replace, bookmarks, safe links, comments with replies and guarded change rejection.

Real interchange

Native .textspace, bounded DOCX import/export, PDF and PNG rendering, HTML and plain text, and CSV mail merge.

Recovery Center

Rolling IndexedDB/native snapshots, previewed repair and checksum-verified protected originals—without clearing your data.

0reusable libraries
0lines of C# & XAML
0features catalogued
0.NET projects
0CI workflows
0docs
Feature tour

31 capabilities, 7 areas

Editing

  • Rich runs with paragraph splitting and joining
  • Grapheme-safe selections and transactional editing
  • Bounded undo/redo and native platform text input
  • Templates, import/export and rolling local history in the File backstage

Typography

  • Font metadata, emphasis, colors and paragraph styles
  • Left, center, right, decimal and bar tabs with six leader styles
  • Discretionary and nonbreaking characters via Insert → Special Characters
  • Rich-run-aware wrapping without artificial break opportunities

Layout and sections

  • Next, odd, even-page, continuous and next-column section starts
  • Per-section paper size, orientation, margins, columns and numbering
  • First/even/default plain-text headers and footers with placeholders
  • Widow/orphan control, keep with next, keep lines together, page break before
  • Balanced paragraph-only column bands on shared pages

Fields and contents

  • 17 allowlisted field types including PAGE, NUMPAGES, SEQ, REF and PAGEREF
  • F9 updates, Manage Fields, locking and unlinking
  • Numeric switches for Arabic, Roman and alphabetic display
  • Generated table of contents with linked entries and dot leaders

Tables and pictures

  • Rectangular cell merges and split-to-grid
  • Nested tables and in-cell or in-flow pictures
  • First-header-row repetition, row splitting and minimum heights
  • Top/middle/bottom vertical alignment in cells

Navigation and review

  • Heading outline and page previews
  • Search and replace
  • Bookmarks with atomic internal-link rename
  • Safe HTTP/HTTPS/mailto links and internal #bookmark links
  • Comments, replies and resolution with guarded local change rejection

Recovery

  • Rolling IndexedDB (browser) or native snapshots
  • Actionable Recovery Center at startup instead of a reload-only error
  • Preview tab-stop repair before protecting the original
  • SHA-256-addressed protected originals that are never automatically evicted
  • Recovery → Open and Repair for native files
Integrated playground

Run TextSpace right here

The live browser build is the full C#/Skia word processor—write, paginate and export without an account or upload. Switch viewports, go fullscreen and tick off the guided tour as you explore.

https://wieslawsoltes.github.io/TextSpace/
TextSpace screenshot

Try TextSpace live

The live browser build is the full C#/Skia word processor—write, paginate and export without an account or upload.

Real C# · Uno WebAssembly · runs locally in your browser
Booting .NET WebAssembly runtime…
Reusable packages

10 libraries you can embed

TextSpace is assembled from independently reusable libraries, each published on NuGet.org. Hover the graph to trace dependencies; click a node to jump to its package, and open a card for install and usage.

Core 728 lines Documents 725 lines Editing 1,089 lines Layout 1,149 lines Skia 349 lines OpenXml 1,023 lines Storage 221 lines Controls 680 lines Editor 481 lines Workbench 1,667 lines App 609 lines
Arrows point from a project to what it references. Bars show relative size. ModelI/OEngineRenderingServiceControlsEditorWorkbench
Model 0.5.1-alpha.1

TextSpace.Core

Rich document model, typography, blocks, tables, anchors and text indexing

No UI depsnet10.0
728 lines20 files0 refsUsage
I/O 0.5.1-alpha.1

TextSpace.Documents

Native serialization/validation, repair plans, templates, HTML and CSV merge

No UI depsnet10.0
refs → Core
725 lines10 files1 refsUsage
Engine 0.5.1-alpha.1

TextSpace.Editing

Atomic editing, selections, formatting, structure and history

No UI depsnet10.0
refs → Documents
1,089 lines12 files1 refsUsage
Engine 0.5.1-alpha.1

TextSpace.Layout

Renderer-independent pagination, caret queries, section regions and hit testing

No UI depsnet10.0
refs → Core
1,149 lines13 files1 refsUsage
Rendering 0.5.1-alpha.1

TextSpace.Skia

HarfBuzz metrics, font registration, page rendering and PDF/PNG export

SkiaSharp + HarfBuzznet10.0
refs → Layout
nuget → SkiaSharp, SkiaSharp.HarfBuzz
349 lines4 files1 refsUsage
I/O 0.5.1-alpha.1

TextSpace.OpenXml

Bounded, dependency-light DOCX import/export

No UI depsnet10.0
refs → Documents
1,023 lines12 files1 refsUsage
Service 0.5.1-alpha.1

TextSpace.Storage

Recovery contracts, atomic files, protected archives and verified transport

No UI depsnet10.0
221 lines5 files0 refsUsage
Controls 0.5.1-alpha.1

TextSpace.Controls

Custom ribbon, galleries, menus, icons, palettes, dialogs and panes

Unonet10.0-browserwasmnet10.0-desktop
refs → Core
680 lines19 files1 refsUsage
Editor 0.5.1-alpha.1

TextSpace.Editor

Embeddable paginated editor, native input bridge, rulers and previews

Uno + Skianet10.0-browserwasmnet10.0-desktop
refs → Controls, Editing, Skia
481 lines7 files3 refsUsage
Workbench 0.5.1-alpha.1

TextSpace.Workbench

Composable office shell, commands, backstage, recovery, navigation and review

Uno + Skianet10.0-browserwasmnet10.0-desktop
refs → Editor, OpenXml, Storage
1,667 lines15 files3 refsUsage
Install from NuGet

10 packages on NuGet.org

TextSpace ships as ten MIT-licensed packages, all versioned together. Seven target plain net10.0 and have no UI dependency: TextSpace.Core, Storage, Documents, Layout, Editing and OpenXml are pure .NET, and TextSpace.Skia adds only SkiaSharp and HarfBuzz. The three Uno Platform packages (Controls, Editor, Workbench) target net10.0-desktop and net10.0-browserwasm. Symbols are published to nuget.org as .snupkg with SourceLink, so you can step into the library source while debugging.

10packages
0.5.1-alpha.1pre-release · Sep 29, 2026
7plain .NET — no UI framework
Newjust published
bashStart with the foundation package
dotnet add package TextSpace.Core --prerelease
xmlEvery package — keep only what you need
<PackageReference Include="TextSpace.Core" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Storage" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Documents" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Layout" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Editing" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.OpenXml" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Skia" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Controls" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Editor" Version="0.5.1-alpha.1" />
<PackageReference Include="TextSpace.Workbench" Version="0.5.1-alpha.1" />
xmlCentral package management
<!-- Directory.Packages.props -->
<ItemGroup>
  <PackageVersion Include="TextSpace.Core" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Storage" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Documents" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Layout" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Editing" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.OpenXml" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Skia" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Controls" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Editor" Version="0.5.1-alpha.1" />
  <PackageVersion Include="TextSpace.Workbench" Version="0.5.1-alpha.1" />
</ItemGroup>

Published with NuGet Trusted Publishing from GitHub Actions, with symbols (.snupkg) and SourceLink. Release v0.5.1-alpha.1 ↗

Dependencies (from project references): Core ← Documents ← Editing, Documents ← OpenXml, Core ← Layout ← Skia, Core ← Controls; Controls + Editing + Skia ← Editor; Editor + OpenXml + Storage ← Workbench. Storage stands alone. TextSpace.App (not packaged) supplies the browser and native desktop hosts.

TextSpace.Core

ModelNo UI depsnet10.0v0.5.1-alpha.1

The document model every other package builds on: blocks (paragraphs, tables, pictures, page/section/column breaks), immutable character and paragraph formatting, page and section settings, comments, tracked edits, fields and bookmarks. Use it alone to build or inspect documents in code. No dependencies and no UI.

bashInstall
dotnet add package TextSpace.Core --prerelease
Depends onno other TextSpace packageUsed byDocumentsLayoutControls

Key types

  • DocumentModel – root object: Blocks, Page, Comments, Fields, Bookmarks, PlainText, WordCount
  • Paragraph, TextRun, TableBlock.Create(rows, columns), ImageBlock, SectionBreakBlock – content blocks
  • TextStyle, ParagraphFormat, PageSettings – immutable records using typographic points
  • DocumentStyles.BuiltIn / DocumentStyles.Find(name) – Normal, Heading 1–3, Title, Quote, Caption…
  • TextIndex – UTF-16 coordinate index with paragraph lookup and grapheme snapping (At, Snap, Next)

Basic usage

csharpUsage
using TextSpace.Core;

var heading = DocumentStyles.Find("Heading 1");
var document = new DocumentModel { Title = "Quarterly report", Page = new PageSettings().Landscape() };
document.Blocks.Clear();
document.Blocks.Add(new Paragraph("Summary", heading.Character, heading.Paragraph));

var body = new Paragraph("Revenue grew ");
body.Runs.Add(new TextRun("12%", new TextStyle { Bold = true, Color = "#107C10" }));
document.Blocks.Add(body);
document.Blocks.Add(TableBlock.Create(rows: 3, columns: 2));

var index = new TextIndex(document);          // UTF-16 text coordinates, grapheme-safe
var address = index.At(10);                   // paragraph containing offset 10
Console.WriteLine($"{document.WordCount} words; offset 10 is in \"{address.Paragraph.Text}\"");

TextSpace.Storage

ServiceNo UI depsnet10.0v0.5.1-alpha.1

Local persistence primitives for document apps: an atomic latest-snapshot store with bounded rolling history, a content-addressed archive of protected originals that is never evicted automatically, and a checksum-verified envelope for moving original text across interop boundaries. It has no dependency on the document model and no UI.

bashInstall
dotnet add package TextSpace.Storage --prerelease
Depends onno other TextSpace packageUsed byWorkbench

Key types

  • IRecoveryStore / FileRecoveryStore – WriteLatestAsync, ReadLatestAsync, ListVersionsAsync, ReadVersionAsync
  • IRecoveryArchiveStore / FileRecoveryArchiveStore – ProtectAsync, ListProtectedAsync, ReadProtectedAsync
  • RecoveryArchiveTransport – Encode / Decode with SHA-256 and byte-count verification
  • RecoveryArchiveLimits – entry, per-original and total byte budgets

Basic usage

csharpUsage
using TextSpace.Storage;

var root = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MyApp");

using var recovery = new FileRecoveryStore(Path.Combine(root, "Recovery"));
await recovery.WriteLatestAsync("Draft", json);          // atomic replace + rolling history
string? latest = await recovery.ReadLatestAsync();
foreach (var version in await recovery.ListVersionsAsync())
    Console.WriteLine($"{version.Title} {version.SavedAt:u} ({version.Bytes} bytes)");

var originals = new FileRecoveryArchiveStore(Path.Combine(root, "ProtectedOriginals"));
RecoveryArchive archive = await originals.ProtectAsync(originalText); // SHA-256 addressed
string envelope = RecoveryArchiveTransport.Encode(originalText);
string verified = RecoveryArchiveTransport.Decode(envelope, expectedId: archive.Id);

TextSpace.Documents

I/ONo UI depsnet10.0v0.5.1-alpha.1

Everything that turns a DocumentModel into files and back without a renderer: native .textspace JSON with strict size/structure validation, explicit tab-stop repair plans, sample templates, field evaluation, sanitized HTML export, CSV mail merge and offline writing checks. Depends on TextSpace.Core; no UI.

bashInstall
dotnet add package TextSpace.Documents --prerelease
Depends onCoreUsed byEditingOpenXml

Key types

  • DocumentJson – Save, Load (validating), Clone, FromText, Validate
  • DocumentRecovery.PrepareTabRepair – non-destructive RecoveryRepairPlan for invalid saved files
  • HtmlExporter.Export – escaped HTML with a restrictive content-security policy
  • MailMerge – ParseCsv and Merge for «Field» placeholders
  • FieldEngine.Evaluate, FieldInstruction.Parse – DATE, PAGE, SEQ, REF/PAGEREF and other supported fields
  • WritingAnalysis – Statistics and repetition/spacing/long-sentence Check

Basic usage

csharpUsage
using TextSpace.Documents;

var template = DocumentJson.FromText("Dear «Name»,\nYour order ships on «Date».", "Letter");
string json = DocumentJson.Save(template);        // native .textspace JSON
var reloaded = DocumentJson.Load(json);           // bounded + validated

var recipients = MailMerge.ParseCsv("Name,Date\nAda,Monday\nGrace,Friday");
foreach (var record in recipients.Records)
{
    var letter = MailMerge.Merge(reloaded, record);
    File.WriteAllText($"letter-{record["Name"]}.html", HtmlExporter.Export(letter));
}

var stats = WritingAnalysis.Statistics(reloaded);
Console.WriteLine($"{stats.Words} words, ~{stats.ReadingMinutes} min");
foreach (var issue in WritingAnalysis.Check(reloaded)) Console.WriteLine(issue.Message);

TextSpace.Layout

EngineNo UI depsnet10.0v0.5.1-alpha.1

Deterministic, point-based layout: line breaking with tab stops, pagination with keeps and widow control, sections and columns, repeating table headers and row splitting, plus caret geometry and hit testing. It measures text through the ITextMetrics interface, so it runs headless (tests, servers) or with the real shaper from TextSpace.Skia. Depends on TextSpace.Core; no UI.

bashInstall
dotnet add package TextSpace.Layout --prerelease
Depends onCoreUsed bySkia

Key types

  • PageLayoutEngine – Layout(document) with a bounded ParagraphLayoutCache
  • DocumentLayout – Pages, Caret, HitTest, VerticalMove, VisiblePages, Notices
  • LayoutPage, LayoutLine, LayoutCell, LayoutRegion – positioned output for renderers
  • ITextMetrics / MonospaceTextMetrics – measurement contract and a deterministic stand-in

Basic usage

csharpUsage
using TextSpace.Documents;
using TextSpace.Layout;

var document = DocumentJson.FromText(string.Join('\n', Enumerable.Repeat("Lorem ipsum dolor sit amet.", 200)));

// Any ITextMetrics works; MonospaceTextMetrics is a deterministic stand-in (TextSpace.Skia provides real shaping).
var engine = new PageLayoutEngine(new MonospaceTextMetrics());
DocumentLayout layout = engine.Layout(document);
Console.WriteLine($"{layout.Pages.Count} pages, {layout.Pages[0].Lines.Count} lines on page 1");

CaretGeometry caret = layout.Caret(position: 120);
double x = layout.PageLeft(caret.PageIndex) + caret.X, y = layout.PageTop(caret.PageIndex) + caret.Y;
int hit = layout.HitTest(x, y + caret.Height / 2);   // back to a text position
int below = layout.VerticalMove(hit, deltaY: caret.Height);

(TextSpace.Documents is used here only for DocumentJson.FromText.)

TextSpace.Editing

EngineNo UI depsnet10.0v0.5.1-alpha.1

A UI-independent editing session: every command is an atomic, undoable transaction over the model, with grapheme-safe selections, typing style, paragraph styles, lists, tables (including merge/split), sections, fields, bookmarks, comments and tracked changes. Use it to script edits or to drive your own editor view. Depends on TextSpace.Documents (and Core); no UI.

bashInstall
dotnet add package TextSpace.Editing --prerelease
Depends onDocumentsUsed byEditor

Key types

  • EditorSession – Document, Selection, SetSelection, InsertText, Replace, Undo/Redo, IsDirty
  • Formatting – ToggleBold, SetFont, SetFontSize, ApplyStyle, FormatParagraph, ToggleList
  • Structure – InsertTable, InsertPicture, InsertSectionBreak, MergeTableCells, InsertField, SetBookmark
  • EditorSession.Changed / EditorChangedEventArgs – document, selection and view notifications
  • SessionTextProjection – revision-bound presentation text for input synchronization

Basic usage

csharpUsage
using TextSpace.Documents;
using TextSpace.Editing;

var session = new EditorSession(DocumentJson.FromText("Introduction\nDetails", "Example"));
session.Changed += (_, e) => Console.WriteLine($"{e.Kind}: {e.Label}");

session.SetSelection(0, 12);            // "Introduction"
session.ApplyStyle("Heading 1");
session.SetSelection(13, 20);           // "Details"
session.ToggleBold();
session.SetBookmark("Details");
session.SetSelection(session.Index.Length, session.Index.Length);
session.InsertText(" follow.");
session.InsertTable(rows: 2, columns: 3);

Console.WriteLine($"{session.Find("details").Count} match(es); dirty: {session.IsDirty}");
session.Undo();                         // each command is one transaction
string json = DocumentJson.Save(session.Document);

TextSpace.OpenXml

I/ONo UI depsnet10.0v0.5.1-alpha.1

Bounded DOCX import and export written directly against the OOXML package (no Open XML SDK at runtime): paragraphs and runs, styles, lists, tab stops, tables with real gridSpan/vMerge, pictures, comments, bookmarks, fields, sections, headers and footers. Imports cap package sizes, prohibit DTDs and never fetch external relationships; unsupported content is reported as warnings. Depends on TextSpace.Documents; no UI.

bashInstall
dotnet add package TextSpace.OpenXml --prerelease
Depends onDocumentsUsed byWorkbench

Key types

  • DocxReader.Read(bytes) – returns a DocxImportResult
  • DocxImportResult – the imported Document plus Warnings for anything dropped
  • DocxWriter.Write(document) – .docx bytes

Basic usage

csharpUsage
using TextSpace.OpenXml;

DocxImportResult result = new DocxReader().Read(File.ReadAllBytes("input.docx"));
foreach (var warning in result.Warnings)
    Console.WriteLine($"Not imported: {warning}");

var document = result.Document;              // TextSpace.Core.DocumentModel
document.Title = "Round-tripped";
File.WriteAllBytes("output.docx", new DocxWriter().Write(document));

TextSpace.Skia

RenderingSkiaSharp + HarfBuzznet10.0v0.5.1-alpha.1

The rendering backend: HarfBuzz-shaped text metrics with glyph caches, explicit font registration, and page painting (selection, caret, formatting marks, comments, tracked changes) onto any SKCanvas, plus PDF and PNG export. Use it headless for server-side PDF/PNG generation. Depends on TextSpace.Layout, SkiaSharp and SkiaSharp.HarfBuzz; no UI framework.

bashInstall
dotnet add package TextSpace.Skia --prerelease
Depends onLayoutUsed byEditor

Key types

  • DocumentRenderer – Layout, DrawPage, ExportPdf, ExportPng, Metrics
  • SkiaTextMetrics – Register(family, bold, italic, data), HarfBuzz Measure/CaretPositions, shaped-run cache
  • RenderOptions – selection, caret, formatting marks, comments, changes and boundaries

Basic usage

csharpUsage
using SkiaSharp;
using TextSpace.Documents;
using TextSpace.Skia;

var document = SampleDocument.Report();
using var renderer = new DocumentRenderer();

// Register faces before layout; the built-in styles use "Aptos".
var regular = File.ReadAllBytes("fonts/Carlito-Regular.ttf");
renderer.Metrics.Register("Aptos", bold: false, italic: false, regular);

var layout = renderer.Layout(document);
File.WriteAllBytes("report.pdf", renderer.ExportPdf(document, layout));
File.WriteAllBytes("page1.png", renderer.ExportPng(document, layout, pageIndex: 0, scale: 2));

// Or draw a page onto any SKCanvas (units are points).
using var surface = SKSurface.Create(new SKImageInfo(612, 792));
renderer.DrawPage(surface.Canvas, document, layout, pageIndex: 0, new RenderOptions { ShowFormatting = true });

TextSpace.Controls

ControlsUnonet10.0-browserwasmnet10.0-desktopv0.5.1-alpha.1

Custom Uno Platform office chrome drawn with the Skia renderer: a tabbed RibbonBar with lazy groups, ribbon/office buttons with bindable appearance properties, vector icons, style gallery, table picker, color palette, menus, dialogs, task panes, zoom slider and scroll bars. Useful for any Uno app that wants an Office-style command surface. Depends on TextSpace.Core (for style definitions) and Uno Platform (Skia renderer).

bashInstall
dotnet add package TextSpace.Controls --prerelease
Depends onCoreUsed byEditor

Key types

  • RibbonBar – AddTab, InsertGroup (extend a tab without replacing its factory), SelectTab, AddFileTab
  • RibbonGroup, RibbonButton, OfficeButton (IsSelected, IsPrimary, RestBackground dependency properties)
  • OfficeIcon, StyleGallery, TablePicker, ColorPalette (AsFlyout)
  • OfficeMenu, OfficeDialog, OfficeTaskPane, OfficeZoomSlider, OfficeScrollBar
  • OfficeTheme – palette constants, Font, and Text/Rows/Columns layout helpers

Basic usage

csharpUsage
using TextSpace.Controls;

var status = OfficeTheme.Text("Ready", 12, OfficeTheme.Muted);
var ribbon = new RibbonBar();
ribbon.AddTab("Home", () =>
{
    var clipboard = new RibbonGroup("Clipboard");
    clipboard.Body.Children.Add(new RibbonButton("paste", "Paste", () => status.Text = "Pasted", large: true, showLabel: true));
    clipboard.Body.Children.Add(new RibbonButton("copy", "Copy", () => status.Text = "Copied"));
    return [clipboard];
});

var zoom = new OfficeZoomSlider { Value = 1 };
zoom.ValueChanged += value => status.Text = $"{value:P0}";
window.Content = OfficeTheme.Rows((ribbon, 0), (status, -1), (zoom, 0)); // 0 = auto, -1 = star

TextSpace.Editor

EditorUno + Skianet10.0-browserwasmnet10.0-desktopv0.5.1-alpha.1

The embeddable paginated editor: DocumentSurface renders an EditorSession with Skia, bridges native text input, handles mouse/keyboard selection, zoom and scrolling, and shows a horizontal ruler with indent handles. DocumentPreview draws page thumbnails. Depends on TextSpace.Controls, TextSpace.Editing, TextSpace.Skia and Uno Platform (Skia renderer).

bashInstall
dotnet add package TextSpace.Editor --prerelease

Key types

  • DocumentSurface – DocumentSurface(session), Session, Renderer, Layout, Relayout, SetZoom, FitPageWidth, FocusEditor
  • DocumentSurface events – Error, ViewChanged, CommandRequested, ContextRequested
  • PageRuler – ruler with IndentChanged
  • DocumentPreview – page thumbnail for navigation panes

Basic usage

csharpUsage
using TextSpace.Documents;
using TextSpace.Editing;
using TextSpace.Editor;

var session = new EditorSession(DocumentJson.FromText("Hello from TextSpace", "Hello"));
var surface = new DocumentSurface(session) { ShowRuler = true };
surface.Renderer.Metrics.Register("Aptos", false, false, fontBytes); // register faces, then relayout
surface.Relayout();
surface.Error += message => System.Diagnostics.Debug.WriteLine(message);

window.Content = surface;
window.Closed += (_, _) => surface.Dispose();
surface.FocusEditor();

TextSpace.Workbench

WorkbenchUno + Skianet10.0-browserwasmnet10.0-desktopv0.5.1-alpha.1

The complete Word-style shell: ribbon tabs (Home, Insert, Design, Layout, References, Mailings, Review, View, Help plus contextual table/picture tabs), File backstage, navigation/review panes, dialogs, recovery tools and status bar around a DocumentSurface. All platform services go through IWorkspaceHost (files, clipboard, printing, URI launching and IRecoveryStore AutoSave); wrap it in RecoveryWorkspaceHost with an IRecoveryArchiveStore to enable the Recovery tab. Dispose owned workbenches when their host closes. Depends on TextSpace.Editor, TextSpace.OpenXml, TextSpace.Storage and Uno Platform.

bashInstall
dotnet add package TextSpace.Workbench --prerelease

Key types

  • WordWorkbench – WordWorkbench(session, host), Session, Surface, Ribbon, ExecuteCommandAsync(id), StateChanged
  • IWorkspaceHost – host contract; OpenedFile result
  • RecoveryWorkspaceHost – adds protected originals to any host
  • WordWorkbench.EnableRecoveryTools / ShowRecoveryNotice – recovery UI

Basic usage

csharpUsage
using TextSpace.Controls;
using TextSpace.Documents;
using TextSpace.Editing;
using TextSpace.Storage;
using TextSpace.Workbench;

// MyWorkspaceHost implements IWorkspaceHost (file pickers, clipboard, printing, URIs, AutoSave).
IWorkspaceHost host = new RecoveryWorkspaceHost(new MyWorkspaceHost(),
    new FileRecoveryArchiveStore(Path.Combine(appData, "ProtectedOriginals")));

var workbench = new WordWorkbench(new EditorSession(SampleDocument.Create()), host);
workbench.EnableRecoveryTools();
workbench.Ribbon.InsertGroup("Home", 0, () => new RibbonGroup("My tools"));
workbench.Surface.Renderer.Metrics.Register("Aptos", false, false, fontBytes);
workbench.Surface.Relayout();

window.Content = workbench;
window.Closed += (_, _) => workbench.Dispose();
Architecture

From engine to workbench

Layers build bottom‑up: each one depends only on those beneath it.

L1Document model

UI-independent rich document model with persistent paragraph IDs and typographic-point geometry.

TextSpace.Core
L2Engines and interchange

Serialization, transactional editing, deterministic pagination, bounded DOCX and recovery storage without UI dependencies.

TextSpace.DocumentsTextSpace.EditingTextSpace.LayoutTextSpace.OpenXmlTextSpace.Storage
L3Rendering

SkiaSharp and HarfBuzz implement text metrics and paint the same geometry on screen and in PDF/PNG.

TextSpace.Skia
L4Uno surfaces

Custom ribbon and office controls plus the embeddable paginated editor with native text input.

TextSpace.ControlsTextSpace.Editor
L5Workbench

Assembles commands, backstage, recovery, navigation and review behind the IWorkspaceHost abstraction.

TextSpace.Workbench
Use it in code

Embed, script, extend

csharpEdit, bookmark and export DOCX/PDF
using TextSpace.Documents;
using TextSpace.Editing;
using TextSpace.OpenXml;
using TextSpace.Skia;

var document = DocumentJson.FromText("Introduction\nDetails", "Example");
var editor = new EditorSession(document);
editor.SetSelection(13, 20);
editor.SetBookmark("Details");
File.WriteAllBytes("Example.docx", new DocxWriter().Write(document));

using var renderer = new DocumentRenderer();
// Register required faces before layout for predictable typography.
var layout = renderer.Layout(document);
File.WriteAllBytes("Example.pdf", renderer.ExportPdf(document, layout));
shPublish the browser app
dotnet workload install wasm-tools
dotnet publish src/TextSpace.App -f net10.0-browserwasm -c Release \
  -p:WasmShellWebAppBasePath=/TextSpace/ -o artifacts/publish
python3 scripts/collect-site.py artifacts/publish site
python3 scripts/serve-site.py site --port 4173

File formats

.textspaceread/write
.docximport/export
PDFexport
PNG page imageexport
HTMLexport
Plain textimport/export
CSV (mail merge data)import

Keyboard essentials

Update fieldsF9
Insert a literal tab (incl. table cells)Ctrl Tab
Next / previous table cellTab / Shift Tab
Append a row from the last cellTab
Follow a rendered hyperlinkCtrl-click / Cmd-click
Build & CI

Continuously verified

Each push runs through GitHub Actions. The public browser build is deployed only from successful pipelines.

Toolchain

.NET SDK10.0.401
Uno SDK6.7.30
Target frameworksnet10.0-browserwasm · net10.0-desktop · net10.0

Third‑party NuGet packages

HarfBuzzSharp.NativeAssets.Linux8.3.1.2
SkiaSharp3.119.2
SkiaSharp.HarfBuzz3.119.2
SkiaSharp.NativeAssets.Linux.NoDependencies3.119.2
bashClone & run the browser build locally
git clone https://github.com/wieslawsoltes/TextSpace.git
cd TextSpace
dotnet workload install wasm-tools
dotnet run --project src/TextSpace.App -f net10.0-browserwasm
Honest boundaries

What it doesn’t claim

The project documents its limits as carefully as its features.

  • Not Microsoft Word: no identical pagination, pixel-identical appearance or lossless DOCX round-tripping
  • Footnotes/endnotes, equations, floating drawings and rich independent header/footer stories are unfinished
  • No collaboration, macros or add-ins; the offline Editor checks style, not full spelling or grammar
  • AutoSave is device-local and abrupt termination can lose debounced edits—keep independent backups
  • Browser tests use Chromium; Safari, Firefox, mobile, IME and screen-reader parity need more validation