add content cache to generated pages

just so that we don't waste work regenerating them over and over again -w-
This commit is contained in:
liquidex 2024-11-23 21:21:28 +01:00
parent 9022fb4ce9
commit 42eaa326ab
4 changed files with 127 additions and 14 deletions

View file

@ -20,7 +20,10 @@ use crate::{
parse::parse_tree_with_diagnostics, parse::parse_tree_with_diagnostics,
state::{report_diagnostics, Source}, state::{report_diagnostics, Source},
tree::SemaRoots, tree::SemaRoots,
vfs::{self, Cd, Dir, DirEntry, DynDir, MemDir, Overlay, ToDynDir, VPath, VPathBuf}, vfs::{
self, Cd, ContentCache, Dir, DirEntry, DynDir, EditPath, ImageSize, MemDir, Overlay,
ToDynDir, VPath, VPathBuf,
},
}; };
use crate::state::{FileId, Treehouse}; use crate::state::{FileId, Treehouse};
@ -415,14 +418,10 @@ impl Dir for TreehouseDir {
} else { } else {
path path
}; };
let mut path = path.to_owned();
if path.extension() == Some("html") {
path.set_extension("");
}
self.sources self.sources
.parsed_trees .parsed_trees
.get(&path) .get(path)
.map(|parsed_tree| { .map(|parsed_tree| {
generate_tree_or_error(&self.sources, &self.dirs, &self.handlebars, parsed_tree) generate_tree_or_error(&self.sources, &self.dirs, &self.handlebars, parsed_tree)
.into() .into()
@ -456,12 +455,67 @@ impl fmt::Debug for TreehouseDir {
} }
} }
struct HtmlCanonicalize<T> {
inner: T,
}
impl<T> HtmlCanonicalize<T> {
pub fn new(inner: T) -> Self {
Self { inner }
}
}
impl<T> Dir for HtmlCanonicalize<T>
where
T: Dir,
{
fn dir(&self, path: &VPath) -> Vec<DirEntry> {
self.inner.dir(path)
}
fn content(&self, path: &VPath) -> Option<Vec<u8>> {
let mut path = path.to_owned();
if path.extension() == Some("html") {
path.set_extension("");
}
self.inner.content(&path)
}
fn content_version(&self, path: &VPath) -> Option<String> {
self.inner.content_version(path)
}
fn image_size(&self, path: &VPath) -> Option<ImageSize> {
self.inner.image_size(path)
}
fn anchor(&self, path: &VPath) -> Option<VPathBuf> {
self.inner.anchor(path)
}
fn edit_path(&self, path: &VPath) -> Option<EditPath> {
self.inner.edit_path(path)
}
}
impl<T> fmt::Debug for HtmlCanonicalize<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "HtmlCanonicalize({:?})", self.inner)
}
}
pub fn target(dirs: Arc<Dirs>, sources: Arc<Sources>) -> DynDir { pub fn target(dirs: Arc<Dirs>, sources: Arc<Sources>) -> DynDir {
let mut root = MemDir::new(); let mut root = MemDir::new();
root.add(VPath::new("static"), dirs.static_.clone()); root.add(VPath::new("static"), dirs.static_.clone());
let dir_index = DirIndex::new(sources.parsed_trees.keys().map(|x| &**x)); let dir_index = DirIndex::new(sources.parsed_trees.keys().map(|x| &**x));
let tree_view = TreehouseDir::new(dirs, sources, dir_index); let tree_view = TreehouseDir::new(dirs, sources, dir_index);
let tree_view = ContentCache::new(tree_view);
let tree_view = HtmlCanonicalize::new(tree_view);
Overlay::new(tree_view.to_dyn(), root.to_dyn()).to_dyn() Overlay::new(tree_view.to_dyn(), root.to_dyn()).to_dyn()
} }

View file

@ -52,6 +52,7 @@ use std::{
mod anchored; mod anchored;
pub mod asynch; pub mod asynch;
mod cd; mod cd;
mod content_cache;
mod content_version_cache; mod content_version_cache;
mod edit; mod edit;
mod empty; mod empty;
@ -64,6 +65,7 @@ mod physical;
pub use anchored::*; pub use anchored::*;
pub use cd::*; pub use cd::*;
pub use content_cache::*;
pub use content_version_cache::*; pub use content_version_cache::*;
pub use edit::*; pub use edit::*;
pub use empty::*; pub use empty::*;

View file

@ -0,0 +1,60 @@
use std::fmt::{self, Debug};
use dashmap::DashMap;
use super::{Dir, DirEntry, EditPath, ImageSize, VPath, VPathBuf};
pub struct ContentCache<T> {
inner: T,
cache: DashMap<VPathBuf, Option<Vec<u8>>>,
}
impl<T> ContentCache<T> {
pub fn new(inner: T) -> Self {
Self {
inner,
cache: DashMap::new(),
}
}
}
impl<T> Dir for ContentCache<T>
where
T: Dir,
{
fn dir(&self, path: &VPath) -> Vec<DirEntry> {
self.inner.dir(path)
}
fn content(&self, path: &VPath) -> Option<Vec<u8>> {
self.cache
.entry(path.to_owned())
.or_insert_with(|| self.inner.content(path))
.clone()
}
fn content_version(&self, path: &VPath) -> Option<String> {
self.inner.content_version(path)
}
fn image_size(&self, path: &VPath) -> Option<ImageSize> {
self.inner.image_size(path)
}
fn anchor(&self, path: &VPath) -> Option<VPathBuf> {
self.inner.anchor(path)
}
fn edit_path(&self, path: &VPath) -> Option<EditPath> {
self.inner.edit_path(path)
}
}
impl<T> fmt::Debug for ContentCache<T>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ContentCache({:?})", self.inner)
}
}

View file

@ -104,9 +104,7 @@ class LinkedBranch extends Branch {
async loadTreePromise(_initiator) { async loadTreePromise(_initiator) {
try { try {
let response = await fetch( let response = await fetch(`${TREEHOUSE_SITE}/${this.linkedTree}`);
`${TREEHOUSE_SITE}/${this.linkedTree}.html`
);
if (response.status == 404) { if (response.status == 404) {
throw `Hmm, seems like the tree "${this.linkedTree}" does not exist.`; throw `Hmm, seems like the tree "${this.linkedTree}" does not exist.`;
} }
@ -127,7 +125,9 @@ class LinkedBranch extends Branch {
// No need to await for the import because we don't use the resulting module. // No need to await for the import because we don't use the resulting module.
// Just fire and forger 💀 // Just fire and forger 💀
// and let them run in parallel. // and let them run in parallel.
let url = URL.createObjectURL(new Blob([script.textContent], { type: "text/javascript" })) let url = URL.createObjectURL(
new Blob([script.textContent], { type: "text/javascript" }),
);
import(url); import(url);
} }
} catch (error) { } catch (error) {
@ -257,10 +257,7 @@ async function expandLinkedBranch() {
let currentlyHighlightedBranch = getCurrentlyHighlightedBranch(); let currentlyHighlightedBranch = getCurrentlyHighlightedBranch();
if (currentlyHighlightedBranch.length > 0) { if (currentlyHighlightedBranch.length > 0) {
let linkedBranch = document.getElementById(currentlyHighlightedBranch); let linkedBranch = document.getElementById(currentlyHighlightedBranch);
if ( if (linkedBranch.children.length > 0 && linkedBranch.children[0].tagName == "DETAILS") {
linkedBranch.children.length > 0 &&
linkedBranch.children[0].tagName == "DETAILS"
) {
expandDetailsRecursively(linkedBranch.children[0]); expandDetailsRecursively(linkedBranch.children[0]);
} }
} }