Skip to main content

Crate markdown_editor

Crate markdown_editor 

Source
Expand description

A block-based WYSIWYG Markdown editor for GPUI, built on gpui-kit’s public editor host API (gpui_kit::base::text::editor_host).

The design began as a spike in longbridge/gpui-kit#3049 and #3566; see docs/design.md. Call init once, after gpui_kit::init.

  • BlockEditorModel: the headless model. It has stable BlockIds, validated BlockPositions, normalized inline mark runs, invertible steps grouped into transactions, undo coalescing, commands on nested blocks (EditorCommand), and a Markdown serializer.
  • BlockEditorState: the entity that owns a model, focus, IME and key bindings, and emits BlockEditorEvents.
  • BlockEditor: the view. It renders through gpui-kit’s own text renderer (a direct model-to-node projection) and culls off-screen blocks.
ⓘ
let scroll = ScrollHandle::new();
let editor = cx.new(|cx| {
    let mut state = BlockEditorState::new(window, cx).with_source("# Hello");
    // Optional: keep the caret in view inside your scroll container.
    state.set_scroll_handle(scroll.clone());
    state
});
cx.subscribe(&editor, |_, editor, event: &BlockEditorEvent, cx| {
    if let BlockEditorEvent::Changed { .. } = event {
        let markdown = editor.read(cx).source();
    }
});
// in render:
div().id("doc").overflow_y_scroll().track_scroll(&scroll)
    .child(BlockEditor::new(&editor))

Keys: Enter, Backspace/Delete, arrows/Home/End (+Shift), Cmd/Ctrl+A, B, I, E, Z, Shift+Z, C, X, V, and Shift+V (plain paste); Tab/Shift+Tab indent list items; Cmd/Ctrl+Alt+0 makes the block (or each selected block) a paragraph. Input rules: # ..###### , - , * , + , 1. . The scroll handle is optional: without it, blocks outside the visible area are still culled, but moving the caret never scrolls (a no-op).

Modules§

component
Themed, content-sized Markdown editor. Base retains all editing behavior.

Structs§

BlockEditor
A block-based WYSIWYG Markdown editor (spike). Hold an Entity<BlockEditorState> and pass it here in render. Instance styling applies to the native input root; it installs no padding or height defaults.
BlockEditorModel
Headless editor facade (spike name). Phase 3 wraps this in the BlockEditorState entity.
BlockEditorState
BlockEditorStyle
Presentation seam for super::BlockEditor. Private fields, with_* setters and readers (ARCHITECTURE.md invariant 12). Unset colours are transparent and are filled from the theme tokens by Self::resolved, mirroring InputEditorStyle::resolved.
BlockId
Opaque, process-unique block identity (design D1).
BlockPosition
A caret location. Plain value type: its fields are the definition.
BlockRef
Borrowed read projection of one block.
CapturedRange
An opaque range tied to one editor, revision and navigation epoch. Successful replacement advances the capture to cover just the inserted text. Any other edit, load, undo/redo or navigation invalidates it, even if text is unchanged.
DocumentRef
Borrowed read projection of the document, like the dock’s PaneRef.
InputRule
One input rule. Construct the built-in rules with the associated functions, or take them all with InputRule::markdown_defaults.
MarkChange
A change to apply over a range. Builder with private fields.
MarkSet
Read-only view of the marks at a position. TextMark stays internal.
PasteRequest
An intercepted semantic paste tied to the editor’s current document and selection. Resolve once; no synthetic key events or OS clipboard access is needed when delivering an explicit ClipboardItem.
SourceSnapshot
Immutable canonical source derived once per document revision. Cloning this value shares the text; it is not another writable document owner.
Transaction
A committed group of steps. Opaque.

Enums§

Affinity
Caret side at a soft wrap or mark boundary. Not part of ordering.
BlockEditorEvent
Events emitted by BlockEditorState.
BlockKind
Public, payload-light projection of a block’s kind, for matching in toolbar code. Payloads (code language, table alignments, definition targets) stay in the crate-internal BlockKindData.
BlockSelection
CapturedRangeError
ClipboardPolicy
Whether paste uses editor defaults or is first offered to the host.
ColumnAlign
The alignment of a table column.
CommandError
EditOrigin
Why an edit happened; drives undo coalescing.
EditorCommand
ImagePolicy
Whether image atoms may load resources while the editor presents them. Placeholder keeps the atomic document, source and selection but never resolves URLs, decodes data, reads paths or creates image elements.
MarkKind
A kind of inline mark, keyed on exactly TextMark’s attributes (D12).
MarkState
Whether a mark covers a whole range, none of it, or part of it.
PositionError
SelectionError
SubmitPolicy
Which Enter action requests submission. Newline is the document-editor default.
TableEdit
Which table edit to make at the caret’s cell, or across the rows and columns of a cell selection (D20).
TableLine
A table row or column, as a grip names it.

Functions§

init
Registers the editor’s key bindings. Call once at startup, after gpui_kit::init.