Skip to main content

Markdown and links

Label, description and note text is more than a flat string: it can carry a clickable link, and - when you opt in - a small, safe subset of markdown. Both adapt to the terminal, degrading to clean plain text where a terminal (or your color switch) cannot show the real thing, so the same form reads well everywhere.

A bordered note rendering bold, emphasis, inline code, a bullet list and a linkA bordered note rendering bold, emphasis, inline code, a bullet list and a link

A [text](url) link is recognized in field labels, descriptions, notes and the summary report - no opt-in needed. On a capable terminal it renders as a clickable OSC 8 hyperlink showing just its text; elsewhere it degrades to text (url) so the address is never lost.

$p->text('item', 'Item')
->description('Full list in the [orchard index](https://example.com/orchard).');

Only an addressable target is linked - the URL must carry a scheme (https://, mailto:, tel: and the like) - so incidental bracket-and-paren prose such as [note](see step 3) stays literal. Links honor the color switch: with color off (the NO_COLOR convention, TERM=dumb, or ->color(FALSE)) every link degrades to text (url).

The summary resolves links too: $answers->toSummary() follows the terminal's color capability - the same NO_COLOR / TERM=dumb signal the interactive TUI uses - emitting a hyperlink on a capable terminal and text (url) otherwise.

Markdown

Turn on ->markdown() and field descriptions and note bodies render a small subset of markdown, each construct mapped to one of the theme's style atoms:

$answers = (new Tui($form))->markdown()->run();
MarkupRenders as
**bold**bold
*emphasis*italic
`code`the theme's code color
[text](url)a hyperlink (as above)
- item / * itema bullet list
$p->note('intro', 'Fresh produce order')
->description("Pick what is **ripe** today:\n- crisp apples\n- sweet pears\nSee the [seasonal guide](https://example.com/seasonal-guide).")
->border();

$p->number('quantity', 'Quantity')->min(1)->max(99)
->description('Baskets hold up to **99**; order more in a *second* basket.');

The subset is deliberately small and inline - no headings, tables or nested blocks - so a description stays a description. Because each construct maps to a theme atom, a custom theme restyles bold, emphasis, code, links and bullets by overriding strong(), emphasis(), code(), link() and bullet().

Markdown honors both the color and the Unicode switches. With color off the markers drop and the text renders plain (bold **ripe** becomes ripe, a link becomes text (url)); with ASCII glyphs the bullet falls back from to -. Headless collection never renders descriptions or notes at all, so it is unaffected. Links stay recognized whether or not markdown is on - ->markdown() only adds the rest of the subset.

The same markdown note in all four display modes - the color-off column drops the styling and degrades the link to text (url), the ASCII row falls back to a - bullet:

ANSINo ANSI
UnicodeMarkdown note: Unicode + ANSIMarkdown note: Unicode + ANSIMarkdown note: Unicode + No ANSIMarkdown note: Unicode + No ANSI
ASCIIMarkdown note: ASCII + ANSIMarkdown note: ASCII + ANSIMarkdown note: ASCII + No ANSIMarkdown note: ASCII + No ANSI

A runnable example is playground/11-display-modes-markdown.php.