-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
112 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,44 @@ | ||
use std::{cell::RefCell, rc::Rc}; | ||
use web_sys::{Document, HtmlElement}; | ||
use crate::{Composable, IntoComposable}; | ||
use std::borrow::Cow; | ||
|
||
use crate::{Composable, Composition, IntoComposable}; | ||
|
||
thread_local! { | ||
static HTML_CONTEXT: RefCell<Option<HtmlContext>> = RefCell::default(); | ||
pub trait Platform: Sized { | ||
fn html(&mut self, html: &mut Builder) -> impl IntoComposable; | ||
} | ||
|
||
struct Inner { | ||
document: Document, | ||
body: HtmlElement, | ||
#[derive(Default, PartialEq, Eq)] | ||
pub struct Builder { | ||
pub attrs: Vec<(Cow<'static, str>, Cow<'static, str>)>, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct HtmlContext { | ||
inner: Rc<RefCell<Inner>>, | ||
#[derive(PartialEq, Eq)] | ||
pub struct Html<P> { | ||
platform: P, | ||
builder: Builder, | ||
} | ||
|
||
impl HtmlContext { | ||
pub fn new() -> Self { | ||
let window = web_sys::window().unwrap(); | ||
let document = window.document().unwrap(); | ||
let body = document.body().unwrap(); | ||
impl<P> Html<P> { | ||
pub fn new(platform: P) -> Self { | ||
Self { | ||
inner: Rc::new(RefCell::new(Inner { document, body })), | ||
platform, | ||
builder: Builder::default(), | ||
} | ||
} | ||
|
||
pub fn current() -> Self { | ||
HTML_CONTEXT | ||
.try_with(|cx| cx.borrow().as_ref().unwrap().clone()) | ||
.unwrap() | ||
} | ||
|
||
pub fn enter(self) { | ||
HTML_CONTEXT | ||
.try_with(|cx| *cx.borrow_mut() = Some(self)) | ||
.unwrap() | ||
pub fn attr( | ||
mut self, | ||
name: impl Into<Cow<'static, str>>, | ||
value: impl Into<Cow<'static, str>>, | ||
) -> Self { | ||
self.builder.attrs.push((name.into(), value.into())); | ||
self | ||
} | ||
} | ||
|
||
#[derive(PartialEq, Eq)] | ||
pub struct Html {} | ||
|
||
impl Composable for Html { | ||
fn compose(&mut self) -> impl IntoComposable { | ||
let cx = HtmlContext::current(); | ||
let inner = cx.inner.borrow_mut(); | ||
let element = inner.document.create_element("div").unwrap(); | ||
inner.body.append_child(&element).unwrap(); | ||
} | ||
} | ||
|
||
pub fn run<C>(content: fn() -> C) | ||
impl<P> Composable for Html<P> | ||
where | ||
C: IntoComposable + 'static, | ||
P: Platform + PartialEq + 'static, | ||
{ | ||
let cx = HtmlContext::new(); | ||
cx.enter(); | ||
|
||
let mut composition = Composition::new(content); | ||
composition.build() | ||
fn compose(&mut self) -> impl IntoComposable { | ||
self.platform.html(&mut self.builder) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
use std::{cell::RefCell, rc::Rc}; | ||
use web_sys::{Document, HtmlElement}; | ||
|
||
use crate::{ | ||
html::{Builder, Html, Platform}, | ||
Composition, IntoComposable, | ||
}; | ||
|
||
thread_local! { | ||
static HTML_CONTEXT: RefCell<Option<WebContext>> = RefCell::default(); | ||
} | ||
|
||
struct Inner { | ||
document: Document, | ||
body: HtmlElement, | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct WebContext { | ||
inner: Rc<RefCell<Inner>>, | ||
} | ||
|
||
impl WebContext { | ||
pub fn new() -> Self { | ||
let window = web_sys::window().unwrap(); | ||
let document = window.document().unwrap(); | ||
let body = document.body().unwrap(); | ||
Self { | ||
inner: Rc::new(RefCell::new(Inner { document, body })), | ||
} | ||
} | ||
|
||
pub fn current() -> Self { | ||
HTML_CONTEXT | ||
.try_with(|cx| cx.borrow().as_ref().unwrap().clone()) | ||
.unwrap() | ||
} | ||
|
||
pub fn enter(self) { | ||
HTML_CONTEXT | ||
.try_with(|cx| *cx.borrow_mut() = Some(self)) | ||
.unwrap() | ||
} | ||
} | ||
|
||
pub fn html() -> Html<WebHtml> { | ||
Html::new(WebHtml {}) | ||
} | ||
|
||
#[derive(PartialEq, Eq)] | ||
pub struct WebHtml {} | ||
|
||
impl Platform for WebHtml { | ||
fn html(&mut self, html: &mut Builder) -> impl IntoComposable { | ||
let cx = WebContext::current(); | ||
let inner = cx.inner.borrow_mut(); | ||
let element = inner.document.create_element("div").unwrap(); | ||
|
||
for (name, value) in &html.attrs { | ||
element.set_attribute(&name, &value).unwrap(); | ||
} | ||
|
||
inner.body.append_child(&element).unwrap(); | ||
} | ||
} | ||
|
||
pub fn run<C>(content: fn() -> C) | ||
where | ||
C: IntoComposable + 'static, | ||
{ | ||
let cx = WebContext::new(); | ||
cx.enter(); | ||
|
||
let mut composition = Composition::new(content); | ||
composition.build() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
use concoct::{html::Html, IntoComposable}; | ||
use concoct::{web::html, IntoComposable}; | ||
|
||
fn app() -> impl IntoComposable { | ||
Html {} | ||
html().attr("class", "main") | ||
} | ||
|
||
fn main() { | ||
concoct::html::run(app) | ||
concoct::web::run(app) | ||
} |