Switch over to WebAssembly, Rust and Yew #35
@ -158,6 +158,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_footnote_ix(&mut self, name: CowStr<'a>) -> usize {
|
||||||
|
let next = self.footnotes.len() + 1;
|
||||||
|
*self.footnotes.entry(name).or_insert(next)
|
||||||
|
}
|
||||||
|
|
||||||
fn output<N: Into<RenderNode>>(&mut self, node: N) {
|
fn output<N: Into<RenderNode>>(&mut self, node: N) {
|
||||||
if let Some(top) = self.stack.last_mut() {
|
if let Some(top) = self.stack.last_mut() {
|
||||||
top.add_child(node)
|
top.add_child(node)
|
||||||
@ -342,7 +347,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(&mut self, tag: Tag) {
|
fn start(&mut self, tag: Tag<'a>) {
|
||||||
match tag {
|
match tag {
|
||||||
Tag::Paragraph => self.enter(RenderElement::new(TagName::P)),
|
Tag::Paragraph => self.enter(RenderElement::new(TagName::P)),
|
||||||
|
|
||||||
@ -491,7 +496,23 @@ where
|
|||||||
p.map(|p| self.enter(p));
|
p.map(|p| self.enter(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
Tag::FootnoteDefinition(name) => {
|
||||||
|
let mut div = RenderElement::new(TagName::Div);
|
||||||
|
div.add_attribute(AttributeName::Class, "footnote");
|
||||||
|
div.add_attribute(AttributeName::Id, name.to_string());
|
||||||
|
|
||||||
|
let index = self.get_footnote_ix(name);
|
||||||
|
let mut left = RenderElement::new(TagName::Div);
|
||||||
|
left.add_attribute(AttributeName::Class, "footnote-index");
|
||||||
|
left.add_child(RenderText::new(index.to_string()));
|
||||||
|
div.add_child(left);
|
||||||
|
|
||||||
|
let mut right = RenderElement::new(TagName::Div);
|
||||||
|
right.add_attribute(AttributeName::Class, "footnote-def");
|
||||||
|
|
||||||
|
self.enter(div);
|
||||||
|
self.enter(right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,8 +608,12 @@ where
|
|||||||
Tag::Strong => self.leave(TagName::Strong),
|
Tag::Strong => self.leave(TagName::Strong),
|
||||||
Tag::Strikethrough => self.leave(TagName::S),
|
Tag::Strikethrough => self.leave(TagName::S),
|
||||||
Tag::Link(_, _, _) => self.leave(TagName::A),
|
Tag::Link(_, _, _) => self.leave(TagName::A),
|
||||||
|
Tag::Image(_, _, _) => {}
|
||||||
|
|
||||||
_ => {}
|
Tag::FootnoteDefinition(_) => {
|
||||||
|
self.leave(TagName::Div); // <div .right>
|
||||||
|
self.leave(TagName::Div); // <div .footnote>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,9 +636,12 @@ where
|
|||||||
Event::SoftBreak | Event::HardBreak | Event::Rule => output.push(' '),
|
Event::SoftBreak | Event::HardBreak | Event::Rule => output.push(' '),
|
||||||
|
|
||||||
Event::FootnoteReference(name) => {
|
Event::FootnoteReference(name) => {
|
||||||
let next = self.footnotes.len() + 1;
|
let ix = {
|
||||||
let footnote = *self.footnotes.entry(name).or_insert(next);
|
let next = self.footnotes.len() + 1;
|
||||||
output.push_str(&format!("[{footnote}]"));
|
*self.footnotes.entry(name).or_insert(next)
|
||||||
|
};
|
||||||
|
|
||||||
|
output.push_str(&format!("[{ix}]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::TaskListMarker(true) => output.push_str("[x]"),
|
Event::TaskListMarker(true) => output.push_str("[x]"),
|
||||||
@ -624,7 +652,7 @@ where
|
|||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, event: Event) {
|
fn event(&mut self, event: Event<'a>) {
|
||||||
match event {
|
match event {
|
||||||
Event::Start(tag) => self.start(tag),
|
Event::Start(tag) => self.start(tag),
|
||||||
Event::End(tag) => self.end(tag),
|
Event::End(tag) => self.end(tag),
|
||||||
@ -659,7 +687,34 @@ where
|
|||||||
self.output(RenderElement::new(TagName::Br));
|
self.output(RenderElement::new(TagName::Br));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
Event::Rule => {
|
||||||
|
self.output(RenderElement::new(TagName::Hr));
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::FootnoteReference(name) => {
|
||||||
|
let mut sup = RenderElement::new(TagName::Sup);
|
||||||
|
let mut anchor = RenderElement::new(TagName::A);
|
||||||
|
anchor.add_attribute(AttributeName::Href, format!("#{name}"));
|
||||||
|
|
||||||
|
let ix = self.get_footnote_ix(name);
|
||||||
|
anchor.add_child(RenderText::new(ix.to_string()));
|
||||||
|
|
||||||
|
sup.add_child(anchor);
|
||||||
|
self.output(sup);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::TaskListMarker(checked) => {
|
||||||
|
let mut input = RenderElement::new(TagName::Input);
|
||||||
|
input.add_attribute(AttributeName::Type, "checkbox");
|
||||||
|
input.add_attribute(AttributeName::Disabled, "");
|
||||||
|
input.add_attribute(AttributeName::Class, "mr-2");
|
||||||
|
|
||||||
|
if checked {
|
||||||
|
input.add_attribute(AttributeName::Checked, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.output(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,9 @@ pub enum TagName {
|
|||||||
H4,
|
H4,
|
||||||
H5,
|
H5,
|
||||||
H6,
|
H6,
|
||||||
|
Hr,
|
||||||
Img,
|
Img,
|
||||||
|
Input,
|
||||||
Li,
|
Li,
|
||||||
Ol,
|
Ol,
|
||||||
P,
|
P,
|
||||||
@ -146,6 +148,7 @@ pub enum TagName {
|
|||||||
S,
|
S,
|
||||||
Span,
|
Span,
|
||||||
Strong,
|
Strong,
|
||||||
|
Sup,
|
||||||
TBody,
|
TBody,
|
||||||
THead,
|
THead,
|
||||||
Table,
|
Table,
|
||||||
@ -173,7 +176,9 @@ impl TagName {
|
|||||||
TagName::H4 => "h4",
|
TagName::H4 => "h4",
|
||||||
TagName::H5 => "h5",
|
TagName::H5 => "h5",
|
||||||
TagName::H6 => "h6",
|
TagName::H6 => "h6",
|
||||||
|
TagName::Hr => "hr",
|
||||||
TagName::Img => "img",
|
TagName::Img => "img",
|
||||||
|
TagName::Input => "input",
|
||||||
TagName::Li => "li",
|
TagName::Li => "li",
|
||||||
TagName::Ol => "ol",
|
TagName::Ol => "ol",
|
||||||
TagName::P => "p",
|
TagName::P => "p",
|
||||||
@ -181,6 +186,7 @@ impl TagName {
|
|||||||
TagName::S => "s",
|
TagName::S => "s",
|
||||||
TagName::Span => "span",
|
TagName::Span => "span",
|
||||||
TagName::Strong => "strong",
|
TagName::Strong => "strong",
|
||||||
|
TagName::Sup => "sup",
|
||||||
TagName::TBody => "tbody",
|
TagName::TBody => "tbody",
|
||||||
TagName::THead => "thead",
|
TagName::THead => "thead",
|
||||||
TagName::Table => "table",
|
TagName::Table => "table",
|
||||||
@ -201,8 +207,10 @@ pub struct RenderAttribute {
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum AttributeName {
|
pub enum AttributeName {
|
||||||
Alt,
|
Alt,
|
||||||
|
Checked,
|
||||||
Class,
|
Class,
|
||||||
Decoding,
|
Decoding,
|
||||||
|
Disabled,
|
||||||
Href,
|
Href,
|
||||||
Id,
|
Id,
|
||||||
Loading,
|
Loading,
|
||||||
@ -210,14 +218,17 @@ pub enum AttributeName {
|
|||||||
Start,
|
Start,
|
||||||
Style,
|
Style,
|
||||||
Title,
|
Title,
|
||||||
|
Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttributeName {
|
impl AttributeName {
|
||||||
pub fn as_str(&self) -> &'static str {
|
pub fn as_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
AttributeName::Alt => "alt",
|
AttributeName::Alt => "alt",
|
||||||
|
AttributeName::Checked => "checked",
|
||||||
AttributeName::Class => "class",
|
AttributeName::Class => "class",
|
||||||
AttributeName::Decoding => "decoding",
|
AttributeName::Decoding => "decoding",
|
||||||
|
AttributeName::Disabled => "disabled",
|
||||||
AttributeName::Href => "href",
|
AttributeName::Href => "href",
|
||||||
AttributeName::Id => "id",
|
AttributeName::Id => "id",
|
||||||
AttributeName::Loading => "loading",
|
AttributeName::Loading => "loading",
|
||||||
@ -225,6 +236,7 @@ impl AttributeName {
|
|||||||
AttributeName::Start => "start",
|
AttributeName::Start => "start",
|
||||||
AttributeName::Style => "style",
|
AttributeName::Style => "style",
|
||||||
AttributeName::Title => "title",
|
AttributeName::Title => "title",
|
||||||
|
AttributeName::Type => "type",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,32 @@ fn main() {
|
|||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
wasm_logger::init(wasm_logger::Config::default());
|
wasm_logger::init(wasm_logger::Config::default());
|
||||||
|
|
||||||
|
log::info!(
|
||||||
|
"blakerain.com {}, {} {} build",
|
||||||
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
"debug"
|
||||||
|
} else {
|
||||||
|
"release"
|
||||||
|
},
|
||||||
|
if cfg!(feature = "hydration") {
|
||||||
|
"hydration"
|
||||||
|
} else {
|
||||||
|
"standard"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let app = yew::Renderer::<App>::new();
|
||||||
|
|
||||||
#[cfg(feature = "hydration")]
|
#[cfg(feature = "hydration")]
|
||||||
{
|
{
|
||||||
log::info!("Hydration build; hydrating application");
|
log::info!("Hydrating application");
|
||||||
yew::Renderer::<App>::new().hydrate();
|
app.hydrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "hydration"))]
|
#[cfg(not(feature = "hydration"))]
|
||||||
{
|
{
|
||||||
log::info!("Standard build; rendering application");
|
log::info!("Rendering application");
|
||||||
yew::Renderer::<App>::new().render();
|
app.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,28 @@
|
|||||||
@apply hover:text-blue-600 dark:hover:text-blue-300;
|
@apply hover:text-blue-600 dark:hover:text-blue-300;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footnote {
|
||||||
|
@apply mb-8 flex flex-row gap-1 text-base text-gray-500 dark:text-gray-400;
|
||||||
|
|
||||||
|
&:has(+ .footnote) {
|
||||||
|
@apply mb-0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footnote-index {
|
||||||
|
@apply leading-relaxed mr-2;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: ".";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
&:last-child {
|
||||||
|
@apply mb-0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dl,
|
dl,
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
|
Loading…
Reference in New Issue
Block a user