Distinguish attachments, which are non-markdown files that should be served/copied directly, not processed into a template.

This commit is contained in:
2025-05-04 00:30:43 -05:00
parent 91ea5fbfce
commit 9e44884dde
3 changed files with 57 additions and 14 deletions

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env -S guix shell -D -f guix.scm rust-analyzer -- sh
#!/usr/bin/env -S guix shell pkg-config rust-analyzer -- sh
##!/usr/bin/env -S guix shell -D -f guix.scm rust-analyzer -- sh
##!/usr/bin/env -S guix shell -D -f guix.scm -- sh
#export LIBCLANG_PATH=$GUIX_ENVIRONMENT/lib/libclang.so
export CC=gcc

View File

@@ -1,6 +1,7 @@
static DEFAULT_INDEX_FILENAME: &'static str = "README.md";
static DEFAULT_TEMPLATES_PATH: &'static str = "templates";
static DEFAULT_TOML_FILENAME: &'static str = "Historian.toml";
static MD_EXTENSION: &'static str = ".md";
extern crate pulldown_cmark;
extern crate tera;
@@ -63,10 +64,14 @@ impl Historian {
Err(_) => None,
Ok(metadata) => {
let mut children = vec![];
let mut attachments = vec![];
if metadata.is_dir() {
for entry in fs::read_dir(&file_path).unwrap() {
let child = entry.unwrap().file_name().into_string().unwrap();
if !(child.starts_with(".") || child == self.index_filename || child == DEFAULT_TOML_FILENAME) {
let entry_file = entry.unwrap();
let child = entry_file.file_name().into_string().unwrap();
if entry_file.metadata().unwrap().is_file() && !child.ends_with(MD_EXTENSION) {
attachments.push(child);
} else if !(child.starts_with(".") || child == self.index_filename || child == DEFAULT_TOML_FILENAME) {
children.push(child);
}
}
@@ -99,12 +104,31 @@ impl Historian {
parent: parent_page,
path: file_path,
is_directory: metadata.is_dir(),
children
children,
attachments
})
}
}
}
pub fn resolve_to_attachment(&self, name: &str) -> Option<PathBuf> {
if name.ends_with(MD_EXTENSION) {
return None;
}
let file_path = self.source_root.clone().join(Path::new(name));
match fs::metadata(&file_path) {
Err(_) => None,
Ok(metadata) => {
if metadata.is_dir() {
None
} else {
Some(file_path)
}
}
}
}
// Creates a struct for a new page.
// The page is not saved until an edit is submitted.
pub fn start_page(&self, name: &str) -> Page {
@@ -128,7 +152,8 @@ impl Historian {
parent: None,
path: file_path,
is_directory,
children: vec![]
children: vec![],
attachments: vec![]
}
}
@@ -264,7 +289,8 @@ pub struct Page {
pub url: String,
pub is_directory: bool,
pub parent: Option<Box<Page>>,
pub children: Vec<String>
pub children: Vec<String>,
pub attachments: Vec<String>
}
#[derive(Serialize)]
@@ -462,33 +488,47 @@ pub fn export_wiki(historian: &Historian, renderer: &PageRenderer, output_path:
for resource_name in renderer.resource_names() {
let mut resource_output_path: PathBuf = output_path.into();
resource_output_path.push(&resource_name);
println!("export resource {} to {:?}", resource_name, resource_output_path);
fs::copy(renderer.resolve_to_resource(&resource_name).unwrap(), resource_output_path).unwrap();
export_resource(renderer.resolve_to_resource(&resource_name).unwrap(), output_path);
}
export_wiki_page(historian, renderer, "", output_path);
}
fn export_resource(resource_path: PathBuf, output_path: &str) {
let mut resource_output_path: PathBuf = output_path.into();
let resource_name = resource_path.file_name().unwrap().to_str().unwrap();
resource_output_path.push(&resource_name);
println!("export resource {} to {:?}", resource_name, resource_output_path);
fs::copy(resource_path, resource_output_path).unwrap();
}
fn export_wiki_page(historian: &Historian, renderer: &PageRenderer, name: &str, output_path: &str) {
if let Some(page) = historian.resolve_to_page(name) {
let page_path: PathBuf = page.full_name.to_owned().replace(".md", ".html").into();
let mut page_output_path: PathBuf = output_path.into();
page_output_path.push(&page_path);
if page.is_directory {
let page_html_output_path = if page.is_directory {
println!("create directory {:?}", page_output_path);
fs::create_dir_all(&page_output_path);
page_output_path.push("index.html");
}
page_output_path.join("index.html")
} else {
page_output_path.clone()
};
println!("export: {} to {:?}", page.full_name, page_output_path);
println!("export: {} to {:?}", page.full_name, page_html_output_path);
let page_html = renderer.render_page_template("page.html", historian, &page, toml! {
dynamic = false
}.as_table().unwrap()).replace(".md", ".html");
let mut page_html_file = fs::File::create(page_output_path).unwrap();
let mut page_html_file = fs::File::create(page_html_output_path).unwrap();
page_html_file.write_all(page_html.as_bytes());
for attachment in page.attachments {
let attachment_path = page_path.join(attachment);
export_resource(attachment_path, page_output_path.to_str().unwrap());
}
for child in page.children {
let child_path = page_path.join(child);
export_wiki_page(historian, renderer, child_path.to_str().unwrap(), output_path);

View File

@@ -35,6 +35,8 @@ async fn page<'r>(
let path_str = path.to_str().unwrap();
if let Some(resource_path) = renderer.resolve_to_resource(path_str) {
Some(PageResponder::File(NamedFile::open(resource_path).await.unwrap()))
} else if let Some(attachment_path) = historian.resolve_to_attachment(path_str) {
Some(PageResponder::File(NamedFile::open(attachment_path).await.unwrap()))
} else {
historian.resolve_to_page(path_str).map(|page| {
if let Some(query) = origin.query() {