lib.rs
4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
mod data;
use log::Level;
use mogwai::prelude::*;
use std::panic;
use wasm_bindgen::prelude::*;
#[derive(Clone)]
enum AppLogic {
Update,
Toggle,
}
fn md_to_html(source: &str) -> String {
use pulldown_cmark::{Parser, Options, html};
let parser = Parser::new_ext(source, Options::all());
let mut html_output = String::new();
html::push_html(&mut html_output, parser);
html_output
}
async fn editor_logic( mut rx_logic: broadcast::Receiver<AppLogic>
, tx_view: broadcast::Sender<String>
, mut rx_dom: broadcast::Receiver<Dom> ) {
let dom = rx_dom.next().await.unwrap();
let mut show_edit = false;
fn get_md(dom: &Dom) -> String {
match dom.inner_read() {
Either::Left(dom_js) => dom_js . to_owned()
. dyn_into::<Node>().unwrap()
. first_child().unwrap()
. dyn_into::<HtmlElement>().unwrap()
. inner_text(),
_ => String::from(""),
}
}
fn update(dom: &Dom) {
if let Either::Left(dom_js) = dom.inner_read() {
dom_js . to_owned()
. dyn_into::<Node>().unwrap()
. child_nodes().get(1).unwrap()
. child_nodes().get(1).unwrap()
. dyn_into::<HtmlElement>().unwrap()
. set_inner_html(md_to_html(get_md(dom).as_str()).as_str())
};
}
update(&dom);
while let Some(msg) = rx_logic.next().await {
match msg {
AppLogic::Update => update(&dom),
AppLogic::Toggle => {
show_edit = ! show_edit;
match show_edit {
true => tx_view . broadcast(String::from("block"))
. await.unwrap(),
false => tx_view . broadcast(String::from("none"))
. await.unwrap(),
};
},
}
}
}
fn editor_view( tx_logic: broadcast::Sender<AppLogic>
, rx_view: broadcast::Receiver<String>
, tx_dom: broadcast::Sender<Dom>
) -> ViewBuilder<Dom> {
let ns = "http://www.w3.org/2000/svg";
builder! {
<div class="input"
style:width="33%"
on:input=tx_logic.sink().contra_map(|_| AppLogic::Update)
capture:view=tx_dom.sink()>
<div contenteditable="true"
style:cursor="text"
style:display=("none", rx_view)>
<pre>{data::MD_EXAMPLE}</pre>
</div>
<div>
<button on:click=tx_logic . sink()
. contra_map(|_| AppLogic::Toggle)>
<svg version="1.1" id="Capa_1" xmlns=ns
x="0px" y="0px" viewBox="0 0 220.001 220.001"
style:width="1.5em" style:height="1.5em">
<g xmlns=ns>
<polygon xmlns=ns points="0,220 59.34,213.86 6.143,160.661"></polygon>
<path xmlns=ns d="M132.018,34.787l53.197,53.197L69.568,203.631L16.37,
150.434L132.018,34.787z M212.696,60.502c9.738-9.738,9.742-25.527,
0-35.268l-17.93-17.93c-9.738-9.74-25.529-9.738-35.268,0l-17.346,
17.347l53.199,53.196L212.696,60.502z"></path>
</g>
</svg>
</button>
<div></div>
</div>
</div>
}
}
#[wasm_bindgen(start)]
pub fn main() -> Result<(), JsValue> {
panic::set_hook(Box::new(console_error_panic_hook::hook));
console_log::init_with_level(Level::Trace).unwrap();
let (tx_dom, rx_dom) = broadcast::bounded(1);
let (tx_logic, rx_logic) = broadcast::bounded(1);
let (tx_view, rx_view) = broadcast::bounded(1);
let comp = Component::from( editor_view(tx_logic, rx_view, tx_dom) )
. with_logic( editor_logic(rx_logic, tx_view, rx_dom) );
let page = Component::from(builder! {{comp}});
page.build()?.run()
}