Replace Dracula-era hardcoded ANSI colors with named constants from the
Catppuccin Macchiato palette. All semantic roles now use 24-bit RGB values:
Headers: Mauve (H1), Blue (H2), Lavender (H3), Teal (H4), Subtext1 (H5+)
Bold: Sky (#91d7e3)
Italic: Sapphire (#7dc4e4)
Inline code: Peach (#f5a97f)
Links: Green (#a6da95) underlined
HR/labels: Overlay1 (#8087a2)
Also switches syntect code highlighting theme from base16-ocean.dark to
base16-mocha.dark for better palette consistency.
When streaming markdown headers containing inline tags (backticks, bold,
italic), the closing delimiter triggered early emission via
emit_formatted_inline(). Since format_header() appends a newline, any
text after the closing tag ended up on a separate line.
Added an in_header guard to handle_delimiter() so headers wait for the
actual newline to emit as a complete line. Added 4 char-by-char streaming
tests covering the bug pattern.
When a code block ended without a trailing newline after the closing
\`\`\`, two bugs occurred in flush_incomplete():
1. The closing \`\`\` was included as part of the code block content
(displayed with syntax highlighting)
2. The same \`\`\` was then emitted again as literal text because
current_line was not cleared after being pushed to block_buffer
The fix:
- Check if current_line is the closing fence before adding to block_buffer
- Always clear current_line after processing in the CodeBlock case
Added two tests:
- test_code_fence_after_blank_line: code fence with trailing newline
- test_code_fence_no_trailing_newline: code fence without trailing newline
The format_header() function was not calling format_inline_content()
to process inline formatting like **bold**, *italic*, and `code`
within headers. This caused raw markdown markers to appear in output.
Added 4 tests to verify the fix:
- test_bold_inside_header
- test_italic_inside_header
- test_code_inside_header
- test_mixed_formatting_inside_header
The code fence (```) was not being properly detected during streaming,
causing it to be rendered as inline code instead of a code block.
Root cause: When buffering a code fence after seeing ```, the code
was returning early for ALL characters including newlines. This meant
handle_newline() was never called and block_state was never set to
BlockState::CodeBlock.
Fixes:
- Don't return early for newlines when buffering code fence, allow them
to fall through to handle_newline()
- Support indented code fences (up to 3 spaces per CommonMark spec) by
using trim_start() when checking for ``` at line start
Bug 1: Inline code after list bullets not detected
- After emitting a list bullet, at_line_start was not set to false
- This caused the next backtick to be treated as a potential code fence
- Fixed by setting at_line_start = false after emitting bullet
Bug 2: Code block closing on indented backticks
- Code blocks containing indented ``` (4+ spaces) were closing prematurely
- The .trim() check was too permissive
- Fixed by only allowing closing fence with <= 3 spaces indent (CommonMark spec)
Added tests for both edge cases.