Hebrew, Arabic and other right-to-left documents render the way they read: each block of the document takes the direction of its own text, so a page can mix right-to-left and left-to-right paragraphs, and code always stays left to right.
Each paragraph, heading, list, quote, alert, table and details block takes the direction of the
first letter of its text that has one, as HTML's dir="auto" does (rules P2 and P3 of the
Unicode Bidirectional Algorithm):
2026,
---) takes the direction of the block around it, or the viewer's own FlowDirection at the
top level.A list, a quote, an alert or a table takes one direction as a whole, from its first block that has
one, so its markers, bar or columns stay on one side. A paragraph inside it whose own text reads the
other way keeps its own direction and is aligned toward the marker or the start of the cell, as a
browser lays out dir="auto" blocks inside a list.
Unlike a browser, the text of code spans, math, autolinks, raw HTML tags and images is skipped
while looking for the first letter: it is technical text that rarely says which way the prose
around it reads, so a Hebrew paragraph that opens with `npm install` stays right to left.
Code blocks, math blocks, Mermaid diagrams and front matter are always left to right, wherever they
are. Inline code inside right-to-left text keeps its own order too: foo() shows as foo(), not
()foo. The viewer wraps it in a Unicode left-to-right isolate (U+2066…U+2069), the way HTML isolates
an element that has its own direction, so the sentence around it keeps its order: in
הריצו `foo()` 3 פעמים, the 3 stays after the code in reading order. Copying leaves the isolate
characters out.
dir attributeWith the HTML subset, dir="rtl" and dir="ltr" set a direction
whatever the text says:
<p> and <h1>…<h6>, the direction of that paragraph or heading.<div>, the direction of the blocks inside it that have no letter with a direction. Markdown
blocks inside it that do have one still take the direction of their own text, as on GitHub, which
renders every markdown block with dir="auto".Other values (dir="auto") are ignored, since detection already does what they ask. A block with a
dir attribute is skipped when the block around it looks for its first letter, as HTML skips the
elements that have their own dir.
<p dir="rtl">This English paragraph starts on the right.</p>
<mv:MarkdownViewer DetectTextDirection="False" />
Without detection, the whole document takes the viewer's own FlowDirection (inherited from its
parent, left to right by default), so an application that only shows right-to-left documents can
set FlowDirection="RightToLeft" on the viewer instead. Code blocks stay left to right and the
dir attribute still applies. Changing DetectTextDirection re-renders the document.
A custom pipeline renderer exposes the same switch as AvaloniaRenderer.DetectTextDirection.
A column alignment in a pipe table (:---, ---:) stays where it says: a left-aligned column is
aligned left even in a right-to-left table, as on GitHub. A column without an alignment starts on
the side the table starts on.
The viewer draws text with the fonts the application gives Avalonia. On the desktop, the system's
fonts usually cover Hebrew and Arabic. In the browser (WebAssembly), Avalonia has only the fonts the
application embeds, so letters the embedded font lacks show as boxes: embed a font for each script
the documents use and register it as a fallback. The demo's DemoFonts.WithRightToLeftFonts() does
this with Noto Sans Hebrew and Noto Sans Arabic, cut down to those scripts:
AppBuilder.Configure<App>()
.WithInterFont()
.ConfigureFonts(fontManager => fontManager.AddFontCollection(
new EmbeddedFontCollection(new Uri("fonts:Noto"), new Uri("avares://MyApp/Assets/Fonts"))))
.With(new FontManagerOptions
{
FontFallbacks =
[
new FontFallback { FontFamily = new FontFamily("fonts:Noto#Noto Sans Hebrew") },
new FontFallback { FontFamily = new FontFamily("fonts:Noto#Noto Sans Arabic") },
],
});