Skip to main content

MarkdownWidget

Struct MarkdownWidget 

Source
pub struct MarkdownWidget<'a> {
    pub inner_area: Option<Rect>,
    /* private fields */
}
Available on crate feature markdown-preview only.
Expand description

A scrollable, interactive markdown widget.

This widget renders markdown content with:

  • Scroll support (keyboard and mouse)
  • Click-to-highlight line selection
  • Clickable headings to collapse/expand sections
  • Clickable frontmatter to collapse/expand
  • Expandable content blocks (“Show more”/“Show less”)
  • Text selection and copy support (drag to select)
  • Double-click detection
  • Statusline showing mode and scroll position

The widget handles ALL event processing internally and returns MarkdownEvent variants so the parent application can react appropriately.

§Mouse Capture Requirement

For click events to work (line highlighting, TOC navigation, text selection), you must enable mouse capture in your terminal setup:

use crossterm::{
    event::{EnableMouseCapture, DisableMouseCapture},
    execute,
    terminal::{EnterAlternateScreen, LeaveAlternateScreen},
};

// On startup:
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;

// On cleanup:
execute!(stdout, LeaveAlternateScreen, DisableMouseCapture)?;

Without EnableMouseCapture, scroll wheel events may still work (terminal-dependent), but click events will not be received by the application.

Fields§

§inner_area: Option<Rect>

Inner area calculated during render (for mouse event handling).

Implementations§

Source§

impl<'a> MarkdownWidget<'a>

Construct MarkdownWidget from a unified MarkdownState.

Source

pub fn from_state(state: &'a MarkdownState) -> MarkdownWidget<'a>

Create a new MarkdownWidget from a unified MarkdownState.

This constructor clones the state into the widget, allowing the widget to own its state internally without holding references to the original state.

§Arguments
  • content - The markdown content to render
  • state - The unified markdown state containing all component states
§Returns

A new MarkdownWidget instance that owns its state.

§Example
use ratatui_toolkit::markdown_widget::state::MarkdownState;
use ratatui_toolkit::MarkdownWidget;

let mut state = MarkdownState::default();
state.source.set_content("# Hello World");

let widget = MarkdownWidget::from_state(&state);
Source§

impl<'a> MarkdownWidget<'a>

Constructor for has_pane option.

Source

pub fn with_has_pane(self, has_pane: bool) -> MarkdownWidget<'a>

Set whether to wrap the widget in a Pane.

When has_pane is true (default), the widget is wrapped in a styled Pane with title, border, and padding. Set to false for raw markdown rendering.

§Arguments
  • has_pane - Whether to wrap in a Pane (default: true)
§Returns

The modified MarkdownWidget instance.

Source§

impl<'a> MarkdownWidget<'a>

Constructor for MarkdownWidget.

Source

pub fn new( content: String, scroll: ScrollState, source: SourceState, cache: CacheState, display: DisplaySettings, collapse: CollapseState, expandable: ExpandableState, git_stats_state: GitStatsState, vim: VimState, selection: SelectionState, double_click: DoubleClickState, ) -> MarkdownWidget<'a>

Create a new MarkdownWidget with the given content and state managers.

This constructor takes owned state values, allowing the widget to own its state internally.

§Arguments
  • content - The markdown content to render
  • scroll - Scroll state (position, viewport, current line)
  • source - Content source state
  • cache - Render cache state
  • display - Display settings (line numbers, themes)
  • collapse - Section collapse state
  • expandable - Expandable content state
  • git_stats_state - Git stats state
  • vim - Vim keybinding state
  • selection - Selection state for text selection/copy
  • double_click - Double-click state for detection
§Returns

A new MarkdownWidget instance.

Source§

impl<'a> MarkdownWidget<'a>

Constructor for pane configuration.

Source

pub fn with_pane(self, pane: Pane<'a>) -> MarkdownWidget<'a>

Configure the Pane that wraps the widget.

When has_pane is true (default), the widget is wrapped in this Pane. Use this to customize the pane’s title, icon, padding, border style, etc.

§Arguments
  • pane - The Pane configuration to use
§Returns

The modified MarkdownWidget instance.

Source§

impl<'a> MarkdownWidget<'a>

Constructor for pane color.

Source

pub fn with_pane_color(self, color: impl Into<Color>) -> MarkdownWidget<'a>

Set the border color for the Pane that wraps the widget.

Only used when has_pane is true (default).

§Arguments
  • color - The color to use for the pane’s border
§Returns

The modified MarkdownWidget instance.

Source§

impl<'a> MarkdownWidget<'a>

Constructor for pane title.

Source

pub fn with_pane_title(self, title: impl Into<String>) -> MarkdownWidget<'a>

Set the title for the Pane that wraps the widget.

This is typically the filename being displayed. Only used when has_pane is true (default).

§Arguments
  • title - The title to display in the pane’s title bar
§Returns

The modified MarkdownWidget instance.

Source§

impl<'a> MarkdownWidget<'a>

Set the custom scrollbar configuration.

Source

pub fn scrollbar_config(self, config: ScrollbarConfig) -> MarkdownWidget<'a>

Set the custom scrollbar configuration.

§Arguments
  • config - The scrollbar configuration to use
§Returns

Self for method chaining.

§Example
use ratatui::style::{Color, Style};
use ratatui_toolkit::markdown_widget::extensions::scrollbar::ScrollbarConfig;

let config = ScrollbarConfig {
    thumb_style: Style::default().fg(Color::Cyan),
    ..Default::default()
};

let widget = MarkdownWidget::from_state(&content, &mut state)
    .show_custom_scrollbar(true)
    .scrollbar_config(config);
Source§

impl<'a> MarkdownWidget<'a>

Set whether selection mode is active.

Source

pub fn selection_active(self, active: bool) -> MarkdownWidget<'a>

Set whether selection mode is active.

This affects the mode displayed in the statusline (Normal vs Drag).

§Arguments
  • active - Whether selection is active
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Enable or disable the scrollbar.

Source

pub fn show_scrollbar(self, show: bool) -> MarkdownWidget<'a>

Enable or disable the scrollbar.

§Arguments
  • show - Whether to show the scrollbar
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Enable or disable the statusline.

Source

pub fn show_statusline(self, show: bool) -> MarkdownWidget<'a>

Set whether to show the statusline.

§Arguments
  • show - Whether to show the statusline
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Enable or disable the TOC (Table of Contents).

Source

pub fn show_toc(self, show: bool) -> MarkdownWidget<'a>

Enable or disable the TOC (Table of Contents).

When enabled, shows heading navigation in the top-right corner. Compact mode shows lines, expanded mode (on hover) shows text.

§Arguments
  • show - Whether to show the TOC
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Set the TOC configuration.

Source

pub fn toc_config(self, config: TocConfig) -> MarkdownWidget<'a>

Set the TOC configuration.

§Arguments
  • config - The TOC configuration
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Set the TOC hovered state.

Source

pub fn toc_hovered(self, hovered: bool) -> MarkdownWidget<'a>

Set the TOC hovered state.

When hovered, the TOC expands to show heading text.

§Arguments
  • hovered - Whether the TOC is hovered
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Set the hovered TOC entry index.

Source

pub fn toc_hovered_entry(self, index: Option<usize>) -> MarkdownWidget<'a>

Set the hovered TOC entry index.

§Arguments
  • index - The index of the hovered entry, or None
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Set the TOC scroll offset.

Source

pub fn toc_scroll_offset(self, offset: usize) -> MarkdownWidget<'a>

Set the TOC scroll offset.

§Arguments
  • offset - The scroll offset for the TOC list
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Theme application constructor for MarkdownWidget.

Source

pub fn with_theme(self, theme: &AppTheme) -> MarkdownWidget<'a>

Applies an application theme to the widget.

When a theme is applied, the widget will use theme colors for:

  • Statusline (mode colors, background, text)
  • TOC (text, active, hover, background, border colors)
  • Selection highlighting

If no theme is set, the widget falls back to default hardcoded colors.

§Arguments
  • theme - The application theme to use for styling
§Returns

Self for method chaining.

§Example
use ratatui_toolkit::{MarkdownWidget, theme::AppTheme};

let theme = AppTheme::default();
// let widget = MarkdownWidget::new(content, scroll, selection, double_click)
//     .with_theme(&theme);
Source§

impl<'a> MarkdownWidget<'a>

TOC state constructor for MarkdownWidget.

Source

pub fn with_toc_state(self, toc_state: TocState) -> MarkdownWidget<'a>

Set the TOC state for the widget.

When a TOC state is provided, the widget can use it for TOC rendering and navigation.

§Arguments
  • toc_state - The TOC state containing entries and hover information
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Source

pub fn calculate_scrollbar_area(&self, area: Rect) -> Option<Rect>

Calculate the scrollbar area based on the content area.

Returns Some(Rect) if the scrollbar should be shown, None otherwise.

§Arguments
  • area - The main widget area
Source§

impl<'a> MarkdownWidget<'a>

Calculate the TOC area.

Source

pub fn calculate_toc_area(&self, total_area: Rect) -> Option<Rect>

Calculate the TOC area based on current widget configuration.

Uses dynamic dimensions based on content:

  • Expanded mode: width fits all headers, height fits all entries
  • Compact mode: fixed width, height based on entry count and line spacing
§Arguments
  • total_area - The total area available for the widget
§Returns

Some(Rect) with the TOC area if TOC is enabled, None otherwise.

Source§

impl MarkdownWidget<'_>

Source

pub fn handle_key(&mut self, key: KeyEvent) -> MarkdownEvent

Handle a keyboard event for navigation and actions.

This is a convenience method that delegates to handle_key_event. The widget manages all state internally.

§Arguments
  • key - The keyboard event to handle
§Returns

A MarkdownEvent indicating what action was taken.

Source

pub fn handle_mouse(&mut self, event: MouseEvent, area: Rect) -> MarkdownEvent

Handle a mouse event for all interactions.

This is a convenience method that delegates to the internal handler. The widget manages all state internally.

§Arguments
  • event - The mouse event to handle
  • area - The area the widget occupies (for bounds checking)
§Returns

A MarkdownEvent indicating what action was taken.

Source

pub fn update_git_stats(&mut self)

Update git stats for the current content.

This method loads git stats for the file if the source is a file path.

Source§

impl<'a> MarkdownWidget<'a>

Git stats setter for MarkdownWidget.

Source

pub fn git_stats(self, stats: GitStats) -> MarkdownWidget<'a>

Set the git statistics to display in the statusline.

§Arguments
  • stats - The git statistics (additions, modified, deletions)
§Returns

Self for method chaining.

Source

pub fn maybe_git_stats(self, stats: Option<GitStats>) -> MarkdownWidget<'a>

Set the git statistics from an optional value.

This is useful when the git stats may or may not be available, such as when fetching from a scroll manager.

§Arguments
  • stats - Optional git statistics
§Returns

Self for method chaining.

Source

pub fn git_stats_tuple( self, additions: usize, modified: usize, deletions: usize, ) -> MarkdownWidget<'a>

Set the git statistics from a tuple (additions, modified, deletions).

§Arguments
  • additions - Lines added
  • modified - Files/lines modified
  • deletions - Lines deleted
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Handle keyboard events for the markdown widget.

Source

pub fn handle_key_event(&mut self, key: KeyEvent) -> MarkdownEvent

Handle a keyboard event for navigation and actions.

This method handles:

  • j / Down: Move focused line down (scrolls when near edge)
  • k / Up: Move focused line up (scrolls when near edge)
  • PageDown: Scroll down by viewport height
  • PageUp: Scroll up by viewport height
  • Home / gg: Go to top
  • End / G: Go to bottom
  • /: Enter filter mode
  • Esc: Exit selection mode or filter mode
  • y: Copy selection to clipboard (when selection active)
  • Ctrl+Shift+C: Copy selection to clipboard

Returns a MarkdownEvent indicating what action was taken.

Source§

impl<'a> MarkdownWidget<'a>

Source

pub fn get_line_info_at_position( &self, y: usize, width: usize, ) -> Option<(usize, String, String)>

Get line information at a given screen position.

Returns (line_number, line_kind, content) if found.

Source

pub fn set_rendered_lines(&mut self, lines: Vec<Line<'static>>)

Set the rendered lines for selection text extraction.

Call this after rendering to update the cached lines.

Source

pub fn is_selection_active(&self) -> bool

Check if selection mode is active.

Source

pub fn selection(&self) -> &SelectionState

Get the current selection state (for rendering).

Source

pub fn get_current_line_info( &self, width: usize, ) -> Option<(usize, String, String)>

Get line information at the current highlighted line.

Returns (line_number, line_kind, content) if found.

Source§

impl<'a> MarkdownWidget<'a>

Handle TOC click events for scroll-to-heading navigation.

Source

pub fn handle_toc_click(&mut self, event: &MouseEvent, area: Rect) -> bool

Handle a click on the TOC to scroll to the selected heading.

§Arguments
  • event - The mouse event
  • area - The total widget area
§Returns

true if the click was handled (was on a TOC entry), false otherwise.

§Example
// In your event loop:
if let Event::Mouse(mouse_event) = event {
    if matches!(mouse_event.kind, MouseEventKind::Down(MouseButton::Left)) {
        if widget.handle_toc_click(&mouse_event, area) {
            // Click was handled - you may want to redraw
        }
    }
}
Source

pub fn handle_toc_click_in_area( &mut self, event: &MouseEvent, toc_area: Rect, ) -> bool

Handle a click on the TOC in a specific area (for when area is pre-calculated).

§Arguments
  • event - The mouse event
  • toc_area - The pre-calculated TOC area
§Returns

true if the click was handled (was on a TOC entry), false otherwise.

Source§

impl<'a> MarkdownWidget<'a>

Handle TOC hover events for interactive expansion and entry highlight.

Source

pub fn handle_toc_hover(&mut self, event: &MouseEvent, area: Rect) -> bool

Handle mouse move events to detect TOC hover.

Call this method with MouseEventKind::Moved events to track whether the mouse is hovering over the TOC area and which entry is being hovered.

§Arguments
  • event - The mouse event (should be a Moved event)
  • area - The total widget area
§Returns

true if the hover state changed (entered/exited hover or hovered entry changed), false otherwise.

§Example
// In your event loop:
if let Event::Mouse(mouse_event) = event {
    if matches!(mouse_event.kind, MouseEventKind::Moved) {
        if widget.handle_toc_hover(&mouse_event, area) {
            // Hover state changed - you may want to redraw
        }
    }
}
Source

pub fn is_toc_hovered(&self) -> bool

Check if the TOC is currently being hovered.

§Returns

true if the mouse is over the TOC, false otherwise.

Source

pub fn get_toc_hovered_entry(&self) -> Option<usize>

Get the currently hovered TOC entry index.

§Returns

The index of the hovered entry, or None if no entry is hovered.

Source

pub fn set_toc_hovered(&mut self, hovered: bool)

Set the TOC hover state directly.

Useful for manually controlling hover state in tests or special scenarios.

§Arguments
  • hovered - Whether the TOC should be considered hovered.
Source

pub fn get_toc_scroll_offset(&self) -> usize

Get the current TOC scroll offset.

§Returns

The current scroll offset for the TOC list.

Source

pub fn set_toc_scroll_offset(&mut self, offset: usize)

Set the TOC scroll offset directly.

§Arguments
  • offset - The scroll offset for the TOC list.
Source

pub fn update_toc_hovered_entry(&mut self, x: u16, y: u16, toc_area: Rect)

Update the hovered entry based on current mouse position and scroll offset.

Call this after scrolling the TOC to recalculate which entry is under the cursor.

§Arguments
  • x - Mouse X coordinate
  • y - Mouse Y coordinate
  • toc_area - The TOC area rect
Source§

impl<'a> MarkdownWidget<'a>

Set resizing state method for MarkdownWidget.

Source

pub fn is_resizing(self, resizing: bool) -> MarkdownWidget<'a>

Set whether the widget is currently being resized (for smoother drag performance).

§Arguments
  • resizing - Whether the widget is being resized
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Methods for retrieving the last double-click info and copied text.

Source

pub fn take_last_double_click(&mut self) -> Option<(usize, String, String)>

Get the last double-click info and clear it.

Call this after processing events to check if a double-click occurred.

§Returns

Some((line_number, line_kind, content)) if a double-click occurred, None otherwise.

Source

pub fn take_last_copied(&mut self) -> Option<String>

Get the last copied text and clear it.

Call this after processing events to check if text was copied to clipboard. Use this to show a toast notification when text is copied.

§Returns

Some(text) if text was copied, None otherwise.

Source§

impl<'a> MarkdownWidget<'a>

Set mode method for MarkdownWidget.

Source

pub fn mode(self, mode: MarkdownWidgetMode) -> MarkdownWidget<'a>

Set the current mode for the statusline.

§Arguments
  • mode - The mode to display (Normal or Drag)
§Returns

Self for method chaining.

Source§

impl<'a> MarkdownWidget<'a>

Source

pub fn rendered_lines(&self) -> &Vec<Line<'static>>

Source§

impl<'a> MarkdownWidget<'a>

Source

pub fn get_state_sync(&mut self) -> WidgetStateSync

Get the state that needs to be synced back to MarkdownState.

This method captures the TOC and selection state from the widget so it can be synced back after the widget is dropped.

§Returns

A WidgetStateSync struct containing the state values to sync.

§Example
let sync_state = {
    let mut widget = MarkdownWidget::from_state(&content, &mut state).show_toc(true);
    widget.handle_toc_hover(&mouse, render_area);
    widget.handle_toc_click(&mouse, render_area);
    widget.handle_mouse_event(&mouse, render_area);
    widget.get_state_sync()
};
sync_state.apply_to(&mut state);
Source

pub fn sync_state_back(self, state: &mut MarkdownState)

Sync widget state back to MarkdownState by consuming self.

This method consumes the widget and syncs TOC and selection state back to the MarkdownState, ensuring state persistence between frames.

Call this after handling mouse events to preserve hover and selection state.

§Arguments
  • state - The MarkdownState to sync state back to
§Example
let mut widget = MarkdownWidget::from_state(&content, &mut state).show_toc(true);
widget.handle_toc_hover(&mouse, render_area);
widget.handle_toc_click(&mouse, render_area);
widget.handle_mouse_event(&mouse, render_area);
widget.sync_state_back(&mut state);

Trait Implementations§

Source§

impl<'a> Widget for &mut MarkdownWidget<'a>

Source§

fn render(self, area: Rect, buf: &mut Buffer)

Draws the current state of the widget in the given buffer. That is the only method required to implement a custom widget.
Source§

impl<'a> Widget for MarkdownWidget<'a>

Source§

fn render(self, area: Rect, buf: &mut Buffer)

Draws the current state of the widget in the given buffer. That is the only method required to implement a custom widget.

Auto Trait Implementations§

§

impl<'a> Freeze for MarkdownWidget<'a>

§

impl<'a> RefUnwindSafe for MarkdownWidget<'a>

§

impl<'a> Send for MarkdownWidget<'a>

§

impl<'a> !Sync for MarkdownWidget<'a>

§

impl<'a> Unpin for MarkdownWidget<'a>

§

impl<'a> UnsafeUnpin for MarkdownWidget<'a>

§

impl<'a> UnwindSafe for MarkdownWidget<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more