Archived
127 lines
4.4 KiB
Rust
127 lines
4.4 KiB
Rust
//! el-platform — Universal rendering backends for el-ui.
|
|
//!
|
|
//! The same component code produces native output for every target platform.
|
|
//! No bridge. No virtual DOM. Direct platform calls.
|
|
//!
|
|
//! The target is chosen in `el.toml`:
|
|
//!
|
|
//! ```toml
|
|
//! [platform]
|
|
//! target = "web" # web | server | ios | android | macos | linux | windows
|
|
//! ssr = true
|
|
//! ```
|
|
//!
|
|
//! All platforms implement the `PlatformBackend` trait. A future agent fills in
|
|
//! the native API calls for iOS/Android/macOS/Linux/Windows — the architecture
|
|
//! is correct and complete now.
|
|
|
|
pub mod backends;
|
|
pub mod config;
|
|
pub mod node;
|
|
|
|
pub use backends::{
|
|
android::AndroidBackend,
|
|
ios::IosBackend,
|
|
linux::LinuxBackend,
|
|
macos::MacosBackend,
|
|
server::ServerBackend,
|
|
web::WebBackend,
|
|
windows::WindowsBackend,
|
|
};
|
|
pub use config::{PlatformConfig, PlatformTarget};
|
|
pub use node::{Attribute, EventHandler, PlatformNode, PlatformNodeKind};
|
|
|
|
use thiserror::Error;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum PlatformError {
|
|
#[error("render error: {0}")]
|
|
Render(String),
|
|
#[error("mount error: {0}")]
|
|
Mount(String),
|
|
#[error("unsupported operation on target {target}: {op}")]
|
|
Unsupported { target: String, op: String },
|
|
#[error("event binding error: {0}")]
|
|
EventBinding(String),
|
|
}
|
|
|
|
pub type PlatformResult<T> = Result<T, PlatformError>;
|
|
|
|
/// The core trait every platform backend must implement.
|
|
///
|
|
/// All rendering paths go through this interface. Component code is identical
|
|
/// across targets — only the backend chosen by `el.toml` differs.
|
|
pub trait PlatformBackend: Send + Sync {
|
|
/// The platform name (e.g. "web", "server", "ios").
|
|
fn name(&self) -> &'static str;
|
|
|
|
/// Create a new element node on this platform.
|
|
fn create_element(&self, tag: &str) -> PlatformResult<PlatformNode>;
|
|
|
|
/// Create a text node on this platform.
|
|
fn create_text(&self, content: &str) -> PlatformResult<PlatformNode>;
|
|
|
|
/// Set an attribute on a node.
|
|
fn set_attribute(&self, node: &mut PlatformNode, name: &str, value: &str)
|
|
-> PlatformResult<()>;
|
|
|
|
/// Remove an attribute from a node.
|
|
fn remove_attribute(&self, node: &mut PlatformNode, name: &str) -> PlatformResult<()>;
|
|
|
|
/// Append a child node to a parent.
|
|
fn append_child(&self, parent: &mut PlatformNode, child: PlatformNode)
|
|
-> PlatformResult<()>;
|
|
|
|
/// Remove a child node from a parent.
|
|
fn remove_child(&self, parent: &mut PlatformNode, child_index: usize) -> PlatformResult<()>;
|
|
|
|
/// Replace a child node at the given index.
|
|
fn replace_child(
|
|
&self,
|
|
parent: &mut PlatformNode,
|
|
index: usize,
|
|
new_child: PlatformNode,
|
|
) -> PlatformResult<()>;
|
|
|
|
/// Bind an event handler to a node.
|
|
fn bind_event(
|
|
&self,
|
|
node: &mut PlatformNode,
|
|
event: &str,
|
|
handler: EventHandler,
|
|
) -> PlatformResult<()>;
|
|
|
|
/// Render a node tree to its platform representation.
|
|
/// For `server`, this returns an HTML string.
|
|
/// For `web`, this patches the live DOM.
|
|
/// For native targets, this calls the appropriate native APIs.
|
|
fn render_to_string(&self, node: &PlatformNode) -> PlatformResult<String>;
|
|
|
|
/// Mount a node tree into the platform's root container.
|
|
/// `container_id` is a platform-specific identifier (CSS selector for web,
|
|
/// view controller ID for iOS, activity ID for Android, etc.).
|
|
fn mount(&self, root: PlatformNode, container_id: &str) -> PlatformResult<()>;
|
|
|
|
/// Patch an existing mounted tree with a new tree.
|
|
/// The backend performs the minimal update needed.
|
|
fn patch(&self, old: &PlatformNode, new: &PlatformNode) -> PlatformResult<()>;
|
|
|
|
/// Whether this backend supports SSR (rendering to HTML string on the server).
|
|
fn supports_ssr(&self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
/// Select the backend for a given platform target.
|
|
pub fn backend_for(target: &PlatformTarget) -> Box<dyn PlatformBackend> {
|
|
match target {
|
|
PlatformTarget::Web => Box::new(WebBackend::new()),
|
|
PlatformTarget::Server => Box::new(ServerBackend::new()),
|
|
PlatformTarget::Ios => Box::new(IosBackend::new()),
|
|
PlatformTarget::Android => Box::new(AndroidBackend::new()),
|
|
PlatformTarget::Macos => Box::new(MacosBackend::new()),
|
|
PlatformTarget::Linux => Box::new(LinuxBackend::new()),
|
|
PlatformTarget::Windows => Box::new(WindowsBackend::new()),
|
|
}
|
|
}
|