Skip to main content

ps_blitz/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! Blitz is a modular, embeddable web engine with a native Rust API.
4//!
5//! It powers the [`dioxus-native`] UI framework.
6//!
7//! This crate exists to collect the most important functionality for users together in one place.
8//! It does not bring any unique functionality, but rather, it re-exports the relevant crates as modules.
9//! The exported crate corresponding to each module is also available in a stand-alone manner, i.e. [`blitz-dom`] as [`blitz::dom`](crate::dom).
10//!
11//! [`dioxus-native`]: https://docs.rs/dioxus-native
12//! [`blitz-dom`]: https://docs.rs/blitz-dom
13
14use std::sync::Arc;
15
16use anyrender_vello::VelloWindowRenderer as WindowRenderer;
17use blitz_dom::DocumentConfig;
18use blitz_html::HtmlDocument;
19use blitz_shell::{
20    BlitzApplication, BlitzShellProxy, Config, EventLoop, WindowConfig, create_default_event_loop,
21};
22use blitz_traits::net::NetProvider;
23
24#[doc(inline)]
25/// Re-export of [`blitz_dom`].
26pub use blitz_dom as dom;
27#[doc(inline)]
28/// Re-export of [`blitz_html`]. HTML parsing on top of blitz-dom
29pub use blitz_html as html;
30#[cfg(feature = "net")]
31#[doc(inline)]
32/// Re-export of [`blitz_net`].
33pub use blitz_net as net;
34#[doc(inline)]
35/// Re-export of [`blitz_paint`].
36pub use blitz_paint as paint;
37#[doc(inline)]
38/// Re-export of [`blitz_shell`].
39pub use blitz_shell as shell;
40#[doc(inline)]
41/// Re-export of [`blitz_traits`](https://docs.rs/blitz-traits). Base types and traits for interoperability between modules
42pub use blitz_traits as traits;
43
44#[cfg(feature = "net")]
45#[cfg(not(target_arch = "wasm32"))]
46pub fn launch_url(url: &str) {
47    // Assert that url is valid
48    #[cfg(feature = "tracing")]
49    tracing::info!("Launching {url}");
50    let url = url.to_owned();
51    let url = url::Url::parse(&url).expect("Invalid url");
52
53    // Turn on the runtime and enter it
54    let rt = tokio::runtime::Builder::new_multi_thread()
55        .enable_all()
56        .build()
57        .unwrap();
58    let _guard = rt.enter();
59
60    let event_loop = create_default_event_loop();
61    let (proxy, reciever) = BlitzShellProxy::new(event_loop.create_proxy());
62    let net_provider = create_net_provider(proxy.clone());
63    let application = BlitzApplication::new(proxy, reciever);
64
65    let resource_policy = Arc::new(blitz_traits::net::ResourcePolicy::default());
66    let navigation = resource_policy.browser(url.clone());
67    let (url, bytes) = rt
68        .block_on(
69            net_provider
70                .fetch_async(blitz_traits::net::Request::get(url).initiator(navigation.clone())),
71        )
72        .unwrap();
73    let document_url = url::Url::parse(&url).expect("provider returned a URL");
74    let net_provider = net_provider.for_scope(resource_policy.document(document_url, &navigation));
75    let html = std::str::from_utf8(bytes.as_ref()).unwrap();
76
77    launch_internal(
78        html,
79        Config {
80            stylesheets: Vec::new(),
81            base_url: Some(url),
82        },
83        event_loop,
84        application,
85        net_provider,
86    )
87}
88
89pub fn launch_static_html(html: &str) {
90    launch_static_html_cfg(html, Config::default())
91}
92
93pub fn launch_static_html_cfg(html: &str, cfg: Config) {
94    // Turn on the runtime and enter it
95    #[cfg(feature = "net")]
96    #[cfg(not(target_arch = "wasm32"))]
97    let rt = tokio::runtime::Builder::new_multi_thread()
98        .enable_all()
99        .build()
100        .unwrap();
101    #[cfg(feature = "net")]
102    #[cfg(not(target_arch = "wasm32"))]
103    let _guard = rt.enter();
104
105    let event_loop = create_default_event_loop();
106    let (proxy, reciever) = BlitzShellProxy::new(event_loop.create_proxy());
107    let net_provider = create_net_provider(proxy.clone());
108    let application = BlitzApplication::new(proxy, reciever);
109
110    launch_internal(html, cfg, event_loop, application, net_provider)
111}
112
113fn launch_internal(
114    html: &str,
115    cfg: Config,
116    event_loop: EventLoop,
117    mut application: BlitzApplication<WindowRenderer>,
118    net_provider: Arc<dyn NetProvider>,
119) {
120    let doc = HtmlDocument::from_html(
121        html,
122        DocumentConfig {
123            base_url: cfg.base_url,
124            ua_stylesheets: Some(cfg.stylesheets),
125            net_provider: Some(net_provider),
126            ..Default::default()
127        },
128    );
129    let renderer = WindowRenderer::new();
130    let window = WindowConfig::new(Box::new(doc) as _, renderer);
131
132    // Create application
133
134    application.add_window(window);
135
136    // Run event loop
137    event_loop.run_app(application).unwrap()
138}
139
140#[cfg(feature = "net")]
141type EnabledNetProvider = blitz_net::Provider;
142#[cfg(not(feature = "net"))]
143type EnabledNetProvider = blitz_traits::net::DummyNetProvider;
144
145fn create_net_provider(proxy: BlitzShellProxy) -> Arc<EnabledNetProvider> {
146    #[cfg(feature = "net")]
147    let net_provider = Arc::new(blitz_net::Provider::new(Some(Arc::new(proxy))));
148    #[cfg(not(feature = "net"))]
149    let net_provider = {
150        use blitz_traits::net::DummyNetProvider;
151
152        // This isn't used without the net feature, so ignore it here to not
153        // get unnused warnings.
154        let _ = event_loop;
155        Arc::new(DummyNetProvider::default())
156    };
157
158    net_provider
159}