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:
parent
9022fb4ce9
commit
42eaa326ab
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
60
crates/treehouse/src/vfs/content_cache.rs
Normal file
60
crates/treehouse/src/vfs/content_cache.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue