| Crates.io | quill-wr |
| lib.rs | quill-wr |
| version | 0.2.0 |
| created_at | 2025-11-09 07:50:38.056689+00 |
| updated_at | 2025-11-09 10:03:21.245753+00 |
| description | A thin Rust→WASM wrapper around the popular Quill.js rich text editor. |
| homepage | https://github.com/ALAWIII/quill-wr |
| repository | https://github.com/ALAWIII/quill-wr |
| max_upload_size | |
| id | 1923784 |
| size | 76,863 |
A thin Rust→WASM wrapper around the popular Quill rich text editor. This crate allows you to initialize and interact with a Quill editor instance directly from Rust via wasm-bindgen.
This project aims to provide Rust bindings for Quill.js — a modern, rich text editor built for the web. You can control the editor (get/set contents, listen to events, apply formats, etc.) all from Rust, compiled to WebAssembly.
⚠️ Project status: Experimental and incomplete
get_text, set_text, get_content, set_content, on, off) work correctlyget_semantic_html() are broken or unimplementedget_semantic_html ,align ,size)You can find the official Quill documentation here: 👉 https://quilljs.com/docs/quickstart
The following example demonstrates how to initialize a Quill editor, set/get text and content, format text, and attach event listeners.
use super::*;
use serde_json::Value;
use serde_wasm_bindgen::to_value;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn test_quill() {
let toolbar = ToolbarConfig::Selector("#toolbar-container".into());
let modules = ModulesConfigBuilder::new().toolbar(toolbar).build();
let options = QuillOptions::builder()
.theme("snow")
.placeholder("Type here...")
.modules(modules)
.build();
let editor = QuillEditor::new_with_options("#editor", options);
editor.set_text("hello", None);
let txt = editor.get_text(None, None);
let contnt = editor.get_content(None, None);
let length = editor.get_length();
gloo::console::log!(txt);
gloo::console::log!(contnt.to_json().expect("Failed to convert to json"));
gloo::console::log!(length);
gloo::console::log!(
editor
.set_content(&contnt, None)
.to_json()
.expect("Failed to convert to json")
);
editor.set_text("eat pizza", None);
let fore = [
Inline::Bold,
Inline::Underline,
Inline::Code,
Inline::Strike,
Inline::Sup,
Inline::Custom("background".into(), Value::String("red".into())), // works
Inline::Size(50.0), // not working yet
];
editor.insert_embed(50, Embeds::Video("video_2025-09-13_18-52-54.mp4".into()), None);
let formats = inlines_to_map(&fore);
gloo::console::log!(to_value(&formats).expect("msg"));
let inserted = editor.insert_text(10, "delicious", &fore, None);
gloo::console::log!(inserted.to_json().unwrap());
editor.delete_text(0, 20, None);
editor.update_content(contnt, None);
editor.format(Inline::Color("red".into()), Some(Source::Api));
editor.blur();
editor.disable();
editor.enable(true);
editor.focus(Some(false));
// Listen for changes
let id = editor.on("text-change", |args| {
web_sys::console::log_1(&"Text changed!".into());
});
editor.off(id);
}
To set up a full toolbar, refer to tests/test.html in the repository.
Here’s a minimal HTML snippet you can use:
<div id="toolbar-container">
<span class="ql-formats">
<select class="ql-font"></select>
<select class="ql-size"></select>
</span>
<span class="ql-formats">
<button class="ql-bold"></button>
<button class="ql-italic"></button>
<button class="ql-underline"></button>
<button class="ql-strike"></button>
</span>
<span class="ql-formats">
<select class="ql-color"></select>
<select class="ql-background"></select>
</span>
<span class="ql-formats">
<button class="ql-script" value="sub"></button>
<button class="ql-script" value="super"></button>
</span>
<span class="ql-formats">
<button class="ql-header" value="1"></button>
<button class="ql-header" value="2"></button>
<button class="ql-blockquote"></button>
<button class="ql-code-block"></button>
</span>
<span class="ql-formats">
<button class="ql-list" value="ordered"></button>
<button class="ql-list" value="bullet"></button>
<button class="ql-indent" value="-1"></button>
<button class="ql-indent" value="+1"></button>
</span>
<span class="ql-formats">
<button class="ql-direction" value="rtl"></button>
<select class="ql-align"></select>
</span>
<span class="ql-formats">
<button class="ql-link"></button>
<button class="ql-image"></button>
<button class="ql-video"></button>
</span>
<span class="ql-formats">
<button class="ql-clean"></button>
</span>
</div>
you get this :
