use serde_json::Value;
use crate::assets::quill::{QUILL_CSS_SRI, QUILL_CSS_URL, QUILL_JS_SRI, QUILL_JS_URL};
use crate::component::RichTextEditorProps;
use crate::plugin::{Asset, JsonUiPlugin};
pub struct RichTextEditorPlugin;
impl JsonUiPlugin for RichTextEditorPlugin {
fn component_type(&self) -> &str {
"RichTextEditor"
}
fn props_schema(&self) -> Value {
serde_json::to_value(schemars::schema_for!(RichTextEditorProps)).unwrap_or_else(|_| {
serde_json::json!({
"type": "object",
"description": "RichTextEditor props (schema derivation failed at runtime)",
})
})
}
fn render(&self, _props: &Value, _data: &Value) -> String {
String::from(
"<div class=\"p-4 bg-red-50 text-red-600 rounded\">\
RichTextEditorPlugin.render unreachable: Component::RichTextEditor \
is dispatched directly by render_component. \
Did a regression route a generic Plugin variant here?\
</div>",
)
}
fn css_assets(&self) -> Vec<Asset> {
vec![Asset::new(QUILL_CSS_URL)
.integrity(QUILL_CSS_SRI)
.crossorigin("anonymous")]
}
fn js_assets(&self) -> Vec<Asset> {
vec![Asset::new(QUILL_JS_URL)
.integrity(QUILL_JS_SRI)
.crossorigin("anonymous")]
}
fn init_script(&self) -> Option<String> {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn component_type_is_rich_text_editor() {
let p = RichTextEditorPlugin;
assert_eq!(p.component_type(), "RichTextEditor");
}
#[test]
fn css_assets_have_sha384_sri_and_anonymous_crossorigin() {
let p = RichTextEditorPlugin;
let css = p.css_assets();
assert_eq!(css.len(), 1, "exactly one CSS asset");
assert_eq!(css[0].url, QUILL_CSS_URL);
let integrity = css[0].integrity.as_deref().expect("integrity required");
assert!(
integrity.starts_with("sha384-"),
"integrity must use sha384"
);
assert_eq!(css[0].crossorigin.as_deref(), Some("anonymous"));
}
#[test]
fn js_assets_have_sha384_sri_and_anonymous_crossorigin() {
let p = RichTextEditorPlugin;
let js = p.js_assets();
assert_eq!(js.len(), 1, "exactly one JS asset");
assert_eq!(js[0].url, QUILL_JS_URL);
let integrity = js[0].integrity.as_deref().expect("integrity required");
assert!(
integrity.starts_with("sha384-"),
"integrity must use sha384"
);
assert_eq!(js[0].crossorigin.as_deref(), Some("anonymous"));
}
#[test]
fn init_script_is_none() {
let p = RichTextEditorPlugin;
assert!(p.init_script().is_none());
}
#[test]
fn props_schema_describes_rich_text_editor() {
let p = RichTextEditorPlugin;
let schema = p.props_schema();
let s = serde_json::to_string(&schema).expect("schema must serialize");
assert!(
s.contains("name"),
"schema must reference the name field: {s}"
);
assert!(
s.contains("formats"),
"schema must reference the formats field: {s}"
);
}
}