Skip to content

Markdown Rendering

Experimental

The document pager (run_markdown, render_markdown, MarkdownViewport) is experimental. The API may still change. The Markdown component used as a field value is separate and is not covered by this warning.

xnano.markdown loads Markdown from a string, bytes, or file path and either paints one frame or opens an interactive pager — scrollable viewport, status line, and keyboard / wheel navigation.

This is separate from the Markdown component, which is a field value for embedding markdown inside a grid. The module here is a document runner and viewport.

Interactive pager

run_markdown opens a live session when a TTY is available. The document is taller than the screen when needed; you scroll the window rather than painting everything at once.

run_markdown
from xnano.markdown import run_markdown

run_markdown("README.md") # (1)!
# or: run_markdown("# Title\n\nBody text.")
  1. Path, literal markdown string, or bytes. Paths set a base directory for relative images.

CLI / entrypoint:

xnano README.md
# same as: python -m xnano README.md

With no path, xnano runs the feature demo instead.

Input Action
arrows, j / k Line scroll
PageUp / PageDown, space Page scroll
Home / g, End / G Start / end of document
mouse wheel Scroll
i / click / hover Expand image preview (when images are present)
q / esc Quit (esc first clears a pinned image expand)

A status line at the bottom shows scroll position and short hints.

One frame

render_markdown paints once and returns a Frame. No event loop.

render_markdown
from xnano.markdown import render_markdown

frame = render_markdown("# Hello\n\nA single frame.")
print(frame.text)

Interactive

This code block runs in the browser via Pyodide.

Try editing the code!
  • Change the heading text.
  • Add a second paragraph to the string.

Editor (session: default)Run
from xnano.markdown import render_markdown

frame = render_markdown("# Hello\n\nA single frame from Markdown.")
print(frame.text)
OutputClear

Loading helpers

from pathlib import Path

from xnano.markdown import is_markdown_path, load_markdown_source

is_markdown_path("notes.md")  # True if the file exists with a .md-like suffix

text, base = load_markdown_source(Path("docs/guide.md"))
# base is the parent directory for relative assets

Supported suffixes include .md, .markdown, .mdown, .mkd, and .mkdn.

Viewport and images

MarkdownViewport is the windowed body used by the pager: block-aware layout (text + images), scroll offset, and hover/pin expand for local images.

Inline images paint as compact half-block thumbnails (never upscaled past native cell resolution). Expand with hover, click, or i for a larger preview without decoding full-size images on every frame.

The Markdown component is still the right choice when markdown is one slot inside a larger app grid. Use xnano.markdown when the document is the session.

Next

API

xnano.markdown · run_markdown · render_markdown · Markdown component