1. Docs
  2. Developers
  3. Editor systems

Markdown and text shortcuts

The two markdown systems, what each supports, and the typing replacement engine.

Mnemo contains two separate markdown systems with different jobs. Knowing which one you are in saves a lot of confusion.

SystemJobParserLocation
Note converterImport and export notes as .md, markdown clipboard fallbackCustom line parser for blocks, Markdig for inline runs onlyMnemo.Infrastructure/Services/Notes/Markdown/
Markdown rendererDisplay AI chat output and learning path contentMarkdig with advanced extensions, plus a custom pre-passMnemo.UI/Services/MarkdownRenderer.cs, Mnemo.Infrastructure/Services/MarkdownProcessor.cs

The note editor itself does not run on markdown at all; its document model is blocks and spans. Markdown only appears at the boundaries.

The note converter

NoteBlockMarkdownConverter maps markdown lines to block types with hand-written rules, not Markdig: headings # to ####, bullets (-, *, +), 1. numbered items, - [ ] checklists, > quotes, fenced code (including ```sketch for sketch blocks), --- dividers, $$...$$ equation blocks, ![alt](path) images, and [[page:id]] page embeds. One list item becomes one block; nested lists are not represented. Tables are not supported in notes at all.

Inline content inside each block goes through InlineMarkdownParser, which uses Markdig for emphasis, strikethrough, inline code, and links, and a custom rule that turns \3/7 into a FractionSpan. The reverse direction, InlineMarkdownSerializer, writes **bold**, *italic*, ~~strike~~, `code`, [text](url), $latex$ for equation spans, and \n/d for fractions.

One known gap: the inline parser has a code path for Markdig’s MathInline, but the pipeline never registers the math extension, so $...$ in imported markdown stays literal text. Inline equations survive Mnemo-to-Mnemo round trips because the serializer writes them and the in-app clipboard uses JSON, but third-party markdown with inline math does not import as math.

A second, partially duplicated implementation exists in Mnemo.UI/Components/BlockEditor/BlockMarkdownSerializer.cs for clipboard fallback. If you change markdown behavior, check both.

The chat renderer

MarkdownRenderer builds Avalonia controls from markdown for AI-generated content. Before Markdig runs, MarkdownProcessor extracts constructs Markdig does not know: $$...$$ and $...$ math (rendered through the LaTeX engine), ==highlight==, ^sup^, ~sub~. This path supports tables via Markdig’s advanced extensions, which is why chat can show tables but notes cannot.

Live typing shortcuts

Two editor-side mechanisms convert text while typing; neither touches stored content.

Block conversion. MarkdownShortcutDetector (block editor) watches line prefixes and converts the current block when you type #, -, >, 1., [], ---, or a code fence.

Text shortcuts. TextShortcutService (Mnemo.Infrastructure/Services/TextShortcuts/) replaces ASCII sequences with Unicode as you type: arrows (->, <->), typography (..., (c), (tm), -- with a trailing space so --- still makes a divider), and explicit commands like \pi, \sum, \leq, \approx, \EUR. Replacement cascades up to 32 iterations, so building < plus an existing arrow can upgrade it to <->’s symbol. The catalog is DefaultTextShortcutCatalog.cs; FractionShortcutResolver handles \3/7 fraction display. The service is invoked by RichTextEditor on text input.

Where the code lives

ConcernPath
Note block conversionMnemo.Infrastructure/Services/Notes/Markdown/NoteBlockMarkdownConverter.cs
Inline parse and serializesame folder, InlineMarkdownParser.cs, InlineMarkdownSerializer.cs
Clipboard fallback copyMnemo.UI/Components/BlockEditor/BlockMarkdownSerializer.cs
Chat renderingMnemo.UI/Services/MarkdownRenderer.cs, Mnemo.Infrastructure/Services/MarkdownProcessor.cs
Text shortcutsMnemo.Infrastructure/Services/TextShortcuts/, models in Mnemo.Core/Models/TextShortcuts/