A Dioxus web component that wraps the CodeMirror 6 editor, for use in Dioxus web applications.
Demo: https://azriel.im/dioxus_codemirror.
Note
🚧 This crate is new and not yet stable; its API may change between releases.
No JavaScript build step is required: the component drives CodeMirror through a
single long-lived document::eval channel. CodeMirror itself is vendored as
a Dioxus folder asset, so there is no runtime CDN dependency.
Details
- Pure Rust build / no
nodedependency. - Set / receive text via
Signal<String>. - Syntax highlighting per-language (YAML, Markdown, JavaScript, CSS, HTML).
- Light / dark / auto theme (auto follows
prefers-color-scheme). - In-page LSP bridge -- synchronous, or async / worker-backed.
Add the following to Cargo.toml:
[dependencies]
dioxus_codemirror = "0.1.0"All bundled languages (YAML, Markdown, JavaScript, CSS, HTML) are available out
of the box. The lang-* Cargo features are currently no-ops; see
Choosing languages.
In code:
use dioxus::prelude::*;
use dioxus_codemirror::{CodeMirror, Language};
#[component]
fn App() -> Element {
let value = use_signal(|| "fn main() {}".to_string());
rsx! {
// Editing the editor updates `value`; setting `value` updates the editor.
CodeMirror { value }
pre { "{value}" }
// Optional line-number gutter and syntax highlighting.
CodeMirror { value, line_numbers: true, language: Language::Yaml }
}
}The editor is always editable. Props:
value: Signal<String>-- two-way bound document text (required).line_numbers: bool-- show a line-number gutter (defaultfalse).language: Language-- syntax highlighting (default plain text). All languages are bundled; see Choosing languages.- editor feature toggles (e.g.
allow_multiple_selections: bool) -- optional CodeMirror features, off by default; see Editor features. theme: Theme-- color theme,Theme::Auto(default, follows the OSprefers-color-scheme),Theme::Light, orTheme::Dark.lsp: LspBridge-- connect an in-page language server, synchronous or async (optional); see LSP.
Optional CodeMirror behaviours are individual props, each named after the CodeMirror extension it enables (API parity). All are off by default; set the ones you want:
use dioxus_codemirror::CodeMirror;
rsx! {
CodeMirror {
value,
allow_multiple_selections: true, // Alt-click, Ctrl/Cmd-d / Ctrl/Cmd-F2 cursors
highlight_selection_matches: true, // highlight other occurrences
bracket_matching: true,
close_brackets: true,
line_wrapping: true,
}
}| Prop | CodeMirror extension |
|---|---|
allow_multiple_selections |
Allows multiple selections in the editor. Also binds Ctrl/Cmd-d to select the next match and Ctrl/Cmd-F2 to select all matches. |
bracket_matching |
Highlight the bracket matching the one next to the cursor. |
close_brackets |
Auto-insert closing brackets and quotes. |
highlight_active_line |
Highlight the line the primary cursor is on. |
highlight_selection_matches |
Highlight every occurrence of the selected text, the selection included. |
highlight_whitespace |
Render whitespace characters visibly. |
indent_on_input |
Re-indent lines as you type. |
indent_with_tab |
Bind Tab/Shift-Tab to indent, so Tab inserts indentation rather than moving focus out of the editor. |
language |
Syntax highlighting language, e.g. Language::Yaml. Defaults to plain text (None). |
line_numbers |
Show a line-number gutter. |
line_wrapping |
Wrap long lines instead of scrolling horizontally. |
read_only |
Make the document read-only, |
rectangular_selection |
Allow rectangular (block) selection via Alt-drag. |
tab_size |
Width of a tab in spaces. |
theme |
Color theme, e.g. Theme::Dark. Defaults to Theme::Auto. |
Every supported language -- Language::Yaml, Markdown, Javascript, Css,
Html -- is bundled and ready to use; no feature selection is required.
The lang-yaml, lang-markdown, lang-javascript, lang-css, lang-html, and
lang-all Cargo features still exist but are currently no-ops: the whole
language superset is shipped regardless. This is because Dioxus cannot yet serve
a build-script-generated, per-feature asset folder -- see
DioxusLabs/dioxus#4426. Once that lands, the features will once again trim the
shipped JS to only the languages you enable, so it is worth setting them now to
match the languages you actually use.
To add a language not listed above, see DEVELOPMENT.md.
CodeMirror takes an optional LspBridge, which connects the editor's
@codemirror/lsp-client to an in-page language server. There are two transport
flavours, chosen by which constructor you call:
-
Synchronous --
LspBridge::lsp_bridge_from_serverdrives anLspServer, the extension point a real in-page language server implements. It is request/response: each message from the editor is handed to the server, and the messages it returns are forwarded straight back. -
Async / worker-capable --
LspBridge::lsp_bridge_from_server_asyncdrives anLspServerAsync, for a server running in a Web Worker (or off the main thread), or one that emits diagnostics after a processing step. Instead of returning replies, the server pushes messages onto anLspPusherwhenever they are ready -- which is what makes server-initiated, unprompted messages (e.g.textDocument/publishDiagnostics) work.
The example ships mock servers for both flavours. Replace either mock with your
WASM language server to get genuine language features. See
DEVELOPMENT.md for the wire protocol and architecture.
See DEVELOPMENT.md for the architecture, the message
protocol, the vendored CodeMirror assets, and how to add a language.
To run the bundled example:
dx serve --platform web -p exampleLicensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.