tawasuyu

tawasuyu/brahman

Rust 459TOML 177Markdown 49JSON 176207 Definiciones

⎇ fce630c8d0a50843b6d447531efb106a627fd1c7 crates/modules/pluma/pluma-reader-web/src/lib.rs Rust · 88 líneas · 2.9 KB Historia Quién tocó qué crudo

feat(gioser): sol detrás, título central, drawers MD + pluma agnóstico fce630c8d · sergio ·

1//! Pluma reader — visor de markdown elegante para WASM/web.
2//!
3//! Toma un `<div>` que actúa como contenedor y le inyecta el HTML
4//! producido por `pluma-md`. El styling (fonts, colores, animaciones)
5//! lo provee el CSS del host: este crate no inyecta estilos, sólo
6//! marcado y `data-pluma-theme="…"` para que el CSS reaccione.
7//!
8//! Patrón de uso:
9//!
10//! ```ignore
11//! let container = document.get_element_by_id("drawer-aire-content")?
12//!     .dyn_into::<HtmlElement>()?;
13//! let reader = Reader::new(container);
14//! reader.show_loading();
15//! wasm_bindgen_futures::spawn_local(async move {
16//!     let _ = reader.open_url("./md/aire.md", "aire").await;
17//! });
18//! ```
19
20use wasm_bindgen::prelude::*;
21use wasm_bindgen::JsCast;
22use wasm_bindgen_futures::JsFuture;
23use web_sys::{HtmlElement, Response};
24
25pub struct Reader {
26    container: HtmlElement,
27}
28
29impl Reader {
30    pub fn new(container: HtmlElement) -> Self {
31        Self { container }
32    }
33
34    pub fn container(&self) -> &HtmlElement {
35        &self.container
36    }
37
38    /// Inyecta un mensaje de carga mientras se resuelve `open_url`.
39    pub fn show_loading(&self) {
40        self.container.set_inner_html(
41            r#"<div class="pluma-loading" aria-live="polite">…</div>"#,
42        );
43    }
44
45    /// Inyecta un mensaje de error visible.
46    pub fn show_error(&self, msg: &str) {
47        let safe: String = msg.replace('<', "&lt;").replace('>', "&gt;");
48        self.container.set_inner_html(&format!(
49            r#"<div class="pluma-error">{}</div>"#,
50            safe
51        ));
52    }
53
54    /// Renderea un string markdown directamente, sin fetch.
55    pub fn render_md(&self, md: &str, theme: &str) {
56        let html = pluma_md::to_themed_html(md, theme);
57        self.container.set_inner_html(&html);
58    }
59
60    /// Inyecta HTML pre-renderizado (sin parsear). Útil si el caller ya
61    /// hizo el parse en otro lado.
62    pub fn render_html(&self, html: &str) {
63        self.container.set_inner_html(html);
64    }
65
66    /// Limpia el contenedor.
67    pub fn clear(&self) {
68        self.container.set_inner_html("");
69    }
70
71    /// Fetcha la URL, parsea el markdown y lo renderea con el tema dado.
72    /// El loader muestra un placeholder mientras la promesa está pendiente.
73    pub async fn open_url(&self, url: &str, theme: &str) -> Result<(), JsValue> {
74        let window = web_sys::window().ok_or_else(|| JsValue::from_str("no window"))?;
75        self.show_loading();
76        let resp_value = JsFuture::from(window.fetch_with_str(url)).await?;
77        let resp: Response = resp_value.dyn_into()?;
78        if !resp.ok() {
79            let err = format!("HTTP {} para {}", resp.status(), url);
80            self.show_error(&err);
81            return Err(JsValue::from_str(&err));
82        }
83        let text_value = JsFuture::from(resp.text()?).await?;
84        let md = text_value.as_string().unwrap_or_default();
85        self.render_md(&md, theme);
86        Ok(())
87    }
88}