blog: get rid of Vec allocation in render for good
just spawn the cache whitelist task onto the js ev loop and don't care about it; the write only need to succeed once and that normally happens at the very first time.
This commit is contained in:
parent
e0d8c94986
commit
5c2615a6cb
33
src/blog.rs
33
src/blog.rs
|
@ -9,10 +9,10 @@ use crate::utils::*;
|
|||
use js_sys::{JsString, RegExp};
|
||||
use pulldown_cmark::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::future::Future;
|
||||
use std::vec::Vec;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen::closure::Closure;
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
|
||||
// A list of the UUIDs of all published blog posts
|
||||
// This should be SORTED with the newest posts at lower indices (closer to 0)
|
||||
|
@ -215,16 +215,25 @@ impl PostContentCache {
|
|||
Some(cache)
|
||||
}
|
||||
|
||||
async fn transform_tag<'a>(tag: &mut Tag<'a>) {
|
||||
fn transform_tag<'a>(tag: &mut Tag<'a>) {
|
||||
match tag {
|
||||
Tag::Image(_, url, _) => {
|
||||
// Convert all external image to our cached URL
|
||||
// to protect users and speed up page loading
|
||||
let url_encoded: String = js_sys::encode_uri_component(url).into();
|
||||
// Also write this URL to whitelist
|
||||
// (just throw the task onto the JS ev loop,
|
||||
// because to make this function async we MUST need to
|
||||
// allocate Vec later in the render function)
|
||||
// we don't care about if this write succeeds or not,
|
||||
// because even if it breaks we still can recover by a simple refresh
|
||||
let _ = store::put_str(&Self::url_to_cache_whitelist_key(url), "Y").await;
|
||||
// and once it's written, it's permanent, so we expect the write
|
||||
// to succeed as soon as the article is submitted
|
||||
let url_cache_key = Self::url_to_cache_whitelist_key(url);
|
||||
spawn_local(async move {
|
||||
let _ = store::put_str(&url_cache_key, "Y").await;
|
||||
()
|
||||
});
|
||||
// Now we can overwrite the tag URL
|
||||
*url = format!("{}{}", IMG_CACHE_PREFIX, url_encoded).into();
|
||||
},
|
||||
|
@ -233,18 +242,16 @@ impl PostContentCache {
|
|||
}
|
||||
|
||||
fn transform_tags<'ev>(
|
||||
parser: impl 'ev + Iterator<Item = Event<'ev>>
|
||||
) -> impl 'ev + Iterator<Item = impl Future<Output = Event<'ev>>> {
|
||||
parser: impl Iterator<Item = Event<'ev>>
|
||||
) -> impl Iterator<Item = Event<'ev>> {
|
||||
parser.map(|mut ev| {
|
||||
async {
|
||||
match ev {
|
||||
Event::Start(ref mut tag) | Event::End(ref mut tag) => {
|
||||
Self::transform_tag(tag).await;
|
||||
Self::transform_tag(tag);
|
||||
ev
|
||||
},
|
||||
_ => ev
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -329,17 +336,11 @@ impl PostContentCache {
|
|||
let parser = Parser::new_ext(&post.content, Options::all());
|
||||
// Apply code highlighting via Highlight.js
|
||||
let parser = Self::transform_code_block_highlight(parser);
|
||||
// Apply async tag transform (resulting in an iterator of Futures)
|
||||
// Apply tag transform
|
||||
let parser = Self::transform_tags(parser);
|
||||
|
||||
// Await on every Future in the queue to convert them back as Events
|
||||
let mut events: Vec<Event> = vec![];
|
||||
for ev in parser {
|
||||
events.push(ev.await);
|
||||
}
|
||||
|
||||
let mut html_output = String::new();
|
||||
html::push_html(&mut html_output, events.into_iter());
|
||||
html::push_html(&mut html_output, parser);
|
||||
html_output = Self::transform_html(html_output);
|
||||
PostContentCache {
|
||||
uuid: post.uuid.clone(),
|
||||
|
|
Loading…
Reference in New Issue