Simple markdown parser for agent chat rendering.
Parses a subset of markdown into styled line segments suitable for terminal rendering. This is intentionally not a full CommonMark parser; it handles the patterns that LLM output commonly uses.
Supported syntax
**bold**and__bold__*italic*and_italic_`inline code`- Fenced code blocks (
`` with optional language tag) -# Headers(levels 1-3) -- list itemsandlist items-> blockquotes- Horizontal rules (---,**,_) ## Output format Returns a list of{line_segments, line_type}tuples where eachline_segmentsis a list of{text, style}pairs andline_type` indicates the block context.
Summary
Types
Extracted code block with language and content.
Line type indicating block context.
A parsed line with its segments and type.
A styled text segment.
Style attributes for a text segment.
Functions
Extracts fenced code blocks from markdown text.
Parses markdown text into styled line segments.
Parses inline markdown formatting within a single line.
Types
Extracted code block with language and content.
@type line_type() :: :text | :code | {:code_header, String.t()} | :header | :blockquote | :list_item | :rule | :empty
Line type indicating block context.
A parsed line with its segments and type.
A styled text segment.
@type style() :: :plain | :bold | :italic | :bold_italic | :code | :code_block | {:code_content, String.t()} | :header1 | :header2 | :header3 | :blockquote | :list_bullet | :rule
Style attributes for a text segment.
Functions
@spec extract_code_blocks(String.t()) :: [code_block()]
Extracts fenced code blocks from markdown text.
Returns a list of %{language: String.t(), content: String.t()} maps,
one per fenced code block. The content excludes the fence markers.
@spec parse(String.t()) :: [parsed_line()]
Parses markdown text into styled line segments.
Returns a list of {segments, line_type} tuples, one per output line.
Parses inline markdown formatting within a single line.
Returns a list of {text, style} segments.