Kode
A fast, embeddable code editor for Leptos applications. Kode provides a syntax-highlighted code editor component, a WYSIWYG Markdown editor, and a toolkit of building blocks for editor experiences that feel native to the web.
Status:
0.2.0-alpha.1. APIs may change before 1.0.
Features
- Code editor with syntax highlighting for SQL, YAML, Markdown, Rust, Python,
JavaScript/TypeScript, HTML, CSS, JSON, Bash, and plain text (powered by
tree-sitter via
arborium). - WYSIWYG Markdown editor that round-trips to source.
- Diagnostics API — plug in linters/validators that render squiggly underlines.
- Completions API — autocomplete with keyword triggers, typing triggers, and custom item renderers.
- Theming via CSS variables; three built-in themes (
tokyo_night,one_dark,github_light) and full custom theme support. - Placeholder text, IME composition, multi-cursor selection, undo/redo, find-and-replace primitives, virtualized rendering for large files.
- Imperative handle for programmatic control (insert text, read selection, set markers).
Workspace layout
| Crate | Purpose |
|---|---|
kode-core |
Text buffer, selection, editing primitives (no UI, no wasm deps). |
kode-leptos |
Leptos components: CodeEditor, MarkdownEditorComponent, TreeWysiwygEditor, toolbar, completion popup. |
kode-markdown |
Markdown parser and formatting utilities. |
kode-doc |
Structured document model (used by the WYSIWYG tree editor). |
kode-demo |
Trunk-built SPA showing the full API in action. |
Installation
# In your Cargo.toml
[]
= "0.1"
= { = "0.8", = ["csr"] }
For active local development, use a path dependency:
= { = "../kode/kode-leptos" }
Quick start
use *;
use ;
use Arc;
CodeEditor props
| Prop | Type | Default | Description |
|---|---|---|---|
language |
Signal<Language> |
Language::Plain |
Syntax highlighting language. Reactive — changes re-highlight immediately. |
content |
Signal<String> |
"" |
Editor text. When the signal changes, the editor replaces its buffer. |
theme |
Signal<Theme> |
Theme::default() |
Color theme. Set via CSS variables on the editor root. |
on_change |
Option<Arc<dyn Fn(String) + Send + Sync>> |
None |
Called after every text edit with the full new text. |
on_ready |
Option<Arc<dyn Fn(EditorHandle) + Send + Sync>> |
None |
Called once with an imperative handle (see below). |
diagnostic_providers |
Signal<Vec<DiagnosticProvider>> |
vec![] |
Debounced providers that return markers. See Diagnostics. |
diagnostic_debounce_ms |
Option<i32> |
300 |
Debounce delay for diagnostic providers. |
completion_providers |
Signal<Vec<CompletionProviderConfig>> |
vec![] |
Autocomplete providers. See Completions. |
placeholder |
Signal<String> |
"" |
Ghost text shown at line 1 col 1 when the buffer is empty. Hidden on first keystroke. |
Supported languages
Plain // no highlighting
Sql
Yaml
Markdown // recognizes fenced code blocks
Python
Rust
Html
Css
Json
Bash
Imperative handle
Receive an EditorHandle via on_ready to interact with the editor outside the
props flow:
use ;
let = ;
view!
Available methods:
handle.insert_at_cursor; // replace selection / insert at cursor
handle.selected_text; // Option<String>
handle.cursor; // Position { line, col }
handle.selection; // Selection { anchor, head }
handle.set_markers;
handle.clear_markers;
Theming
Pick a built-in theme:
tokyo_night
one_dark
github_light
Or customize by starting from a builtin and overriding fields. The theme drives a
set of --kode-* CSS custom properties applied to the editor root. You can
override any of them in your own CSS:
}
Key variables: --kode-bg, --kode-fg, --kode-fg-dim, --kode-cursor,
--kode-selection, --kode-current-line, --kode-gutter-fg,
--kode-gutter-border, --kode-accent, --kode-marker-error,
--kode-marker-warning, --kode-marker-info.
Diagnostics
Register one or more providers. Each provider receives the current buffer and returns markers; results are merged and rendered as wavy underlines.
use ;
let providers = stored;
view!
Write a custom provider by constructing a DiagnosticProvider from a closure that
takes the text and returns Vec<Marker>.
With the optional schema feature:
= { = "...", = ["schema"] }
use json_schema_provider;
let schema = json!;
let providers = stored;
Completions
use ;
let sql_keywords = CompletionProviderConfig ;
let providers = stored;
view!
activate_on_typing: true— popup opens as the user types identifiers.trigger_characters: vec!['.', ':']— popup opens when any listed character is typed (good for member access).render: Some(renderer)— customize popup item rendering.
Keyboard: ↑/↓ navigate, Enter/Tab accept, Esc dismiss.
WYSIWYG Markdown editor
use ;
let content = new;
let mode = new;
view!
Toggle mode between EditorMode::Wysiwyg and EditorMode::Source to switch
between the rendered and markdown-source views.
Running the demo
The demo/ crate is a Trunk-built SPA that exercises every feature.
# Install Trunk if you don't have it
# Build and serve (listens on 0.0.0.0:8090)
Open http://localhost:8090/ and try the language selector, theme switcher, completions, and imperative-handle controls.
Development
# Native check (all crates)
# WASM check (what the editor actually targets)
# Lints
# Unit tests
Prerequisites:
- Rust
stable(seerust-toolchain.toml). wasm32-unknown-unknowntarget:rustup target add wasm32-unknown-unknown.- Trunk for the demo:
cargo install trunk.
Project layout for contributors
kode/
├── kode-core/ # editing primitives (no-UI)
├── kode-leptos/ # Leptos components + CSS + highlighting
│ ├── src/editor.rs # CodeEditor component
│ ├── src/wysiwyg/ # WYSIWYG markdown tree editor
│ └── src/completion.rs
├── kode-markdown/ # markdown parser
├── kode-doc/ # document tree model
└── demo/ # Trunk SPA demo
License
MIT — see LICENSE.