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) {
|
||||
if let Some(top) = self.stack.last_mut() {
|
||||
top.add_child(node)
|
||||
@ -342,7 +347,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn start(&mut self, tag: Tag) {
|
||||
fn start(&mut self, tag: Tag<'a>) {
|
||||
match tag {
|
||||
Tag::Paragraph => self.enter(RenderElement::new(TagName::P)),
|
||||
|
||||
@ -491,7 +496,23 @@ where
|
||||
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::Strikethrough => self.leave(TagName::S),
|
||||
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::FootnoteReference(name) => {
|
||||
let ix = {
|
||||
let next = self.footnotes.len() + 1;
|
||||
let footnote = *self.footnotes.entry(name).or_insert(next);
|
||||
output.push_str(&format!("[{footnote}]"));
|
||||
*self.footnotes.entry(name).or_insert(next)
|
||||
};
|
||||
|
||||
output.push_str(&format!("[{ix}]"));
|
||||
}
|
||||
|
||||
Event::TaskListMarker(true) => output.push_str("[x]"),
|
||||
@ -624,7 +652,7 @@ where
|
||||
output
|
||||
}
|
||||
|
||||
fn event(&mut self, event: Event) {
|
||||
fn event(&mut self, event: Event<'a>) {
|
||||
match event {
|
||||
Event::Start(tag) => self.start(tag),
|
||||
Event::End(tag) => self.end(tag),
|
||||
@ -659,7 +687,34 @@ where
|
||||
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,
|
||||
H5,
|
||||
H6,
|
||||
Hr,
|
||||
Img,
|
||||
Input,
|
||||
Li,
|
||||
Ol,
|
||||
P,
|
||||
@ -146,6 +148,7 @@ pub enum TagName {
|
||||
S,
|
||||
Span,
|
||||
Strong,
|
||||
Sup,
|
||||
TBody,
|
||||
THead,
|
||||
Table,
|
||||
@ -173,7 +176,9 @@ impl TagName {
|
||||
TagName::H4 => "h4",
|
||||
TagName::H5 => "h5",
|
||||
TagName::H6 => "h6",
|
||||
TagName::Hr => "hr",
|
||||
TagName::Img => "img",
|
||||
TagName::Input => "input",
|
||||
TagName::Li => "li",
|
||||
TagName::Ol => "ol",
|
||||
TagName::P => "p",
|
||||
@ -181,6 +186,7 @@ impl TagName {
|
||||
TagName::S => "s",
|
||||
TagName::Span => "span",
|
||||
TagName::Strong => "strong",
|
||||
TagName::Sup => "sup",
|
||||
TagName::TBody => "tbody",
|
||||
TagName::THead => "thead",
|
||||
TagName::Table => "table",
|
||||
@ -201,8 +207,10 @@ pub struct RenderAttribute {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum AttributeName {
|
||||
Alt,
|
||||
Checked,
|
||||
Class,
|
||||
Decoding,
|
||||
Disabled,
|
||||
Href,
|
||||
Id,
|
||||
Loading,
|
||||
@ -210,14 +218,17 @@ pub enum AttributeName {
|
||||
Start,
|
||||
Style,
|
||||
Title,
|
||||
Type,
|
||||
}
|
||||
|
||||
impl AttributeName {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
AttributeName::Alt => "alt",
|
||||
AttributeName::Checked => "checked",
|
||||
AttributeName::Class => "class",
|
||||
AttributeName::Decoding => "decoding",
|
||||
AttributeName::Disabled => "disabled",
|
||||
AttributeName::Href => "href",
|
||||
AttributeName::Id => "id",
|
||||
AttributeName::Loading => "loading",
|
||||
@ -225,6 +236,7 @@ impl AttributeName {
|
||||
AttributeName::Start => "start",
|
||||
AttributeName::Style => "style",
|
||||
AttributeName::Title => "title",
|
||||
AttributeName::Type => "type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,32 @@ fn main() {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
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")]
|
||||
{
|
||||
log::info!("Hydration build; hydrating application");
|
||||
yew::Renderer::<App>::new().hydrate();
|
||||
log::info!("Hydrating application");
|
||||
app.hydrate();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "hydration"))]
|
||||
{
|
||||
log::info!("Standard build; rendering application");
|
||||
yew::Renderer::<App>::new().render();
|
||||
log::info!("Rendering application");
|
||||
app.render();
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,28 @@
|
||||
@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,
|
||||
ul,
|
||||
ol {
|
||||
|
Loading…
Reference in New Issue
Block a user