Skip to content

UXMarkdown

UXMarkdown turns inline markdown into a UXAttributedString.

#use <UXKit> // or #import "UXMarkdown.xc"
UXAttributedString* s =
UXMarkdown.parse((u8*)"plain **bold** and *italic* and `code` here");
s.stringValue(); // "plain bold and italic and code here" — markers gone
s.runCount(); // 7 — the spans, coalesced

It covers help text, notes and formatted labels drawn through the attributed-string path.

writtenattribute
**bold**bold
*italic*italic
`code`a distinct colour pen

Each marker is a toggle, not a matched pair. The parser flips a flag and continues, which has two consequences.

Nesting works with no special handling, because the flags are independent:

UXMarkdown.parse((u8*)"**bold *and italic* **");
// "bold and italic " — three runs: bold, bold+italic, bold

An unclosed marker is not an error. It applies to the rest of the string, so "**oops" is all bold. This is forgiving for help text, but a stray asterisk changes everything after it.

** is checked before *, so a double marker is bold rather than two italics.

UXMarkdown.parse((u8*)"a \\*literal\\* star");
// "a *literal* star" — one run, no styling

A backslash takes the next character literally. Use it to write an asterisk or a backtick that stands for itself.

The ` marker sets the pen rather than a monospace family, because UXCharAttr has bold, italic, pen and size, and no family.

Code spans are distinguished, not monospaced. Adding a family to the character attributes would change the run-coalescing rule and every backend’s text drawing, for a feature help text rarely needs.

If you need monospace, draw the runs yourself and choose a family per run; drawTextFont takes one.

No headings, no lists, no links, no block quotes, no paragraphs. The scope is inline markup only.

Block markdown would sit on top of this. It needs a line model and a notion of vertical space, and an attributed string has neither. UXMarkdown handles the part that fits in a label.

parse

static UXAttributedString* parse(u8* md)

Markdown in, attributed string out. It never fails: no input is malformed, though some input styles differently from what you meant.

The output text is never longer than the input, because markers are only removed. Attributes are applied per character, so the runs coalesce correctly with no extra work.

markdown: 'plain bold and italic and code here'
7 run(s): [0..5] [6..9 B] [10..14] [15..20 I] [21..25] [26..29 C] [30..34]
escaped: 'a *literal* star' runs=1
nested: 'bold and italic ' runs=3

Three styled spans give seven runs, because each one splits the plain text around it. The escaped line is a single run because nothing is styled.

The program is website/site/examples/uxkit/toolbox.xc. The doc-examples gate compiles it, and the listing above is its output.

  • A plain class (not an Object subclass). It has one static method, so there is nothing to instantiate.