[WIP] A (somewhat barebones) atproto app for creating custom sites without hosting!
1use ignore::WalkBuilder;
2use jacquard::types::blob::Blob;
3use miette::Diagnostic;
4use mime_guess::mime;
5use std::{collections::HashMap, path::PathBuf};
6use thiserror::Error;
7
8pub type Sitemap = HashMap<String, SitemapNode>;
9
10#[derive(Debug)]
11pub struct SitemapNode {
12 pub mime_type: String,
13 pub blob: BlobRef,
14}
15
16#[derive(Debug)]
17pub enum BlobRef {
18 Local(PathBuf),
19 Remote(Blob<'static>),
20}
21
22#[derive(Debug, Error, Diagnostic)]
23pub enum SitemapErr {
24 #[error("IO error: {}", .0)]
25 IoErr(#[from] std::io::Error),
26 #[error("Error finding files: {}", .0)]
27 IgnoreErr(#[from] ignore::Error),
28 #[error("Error normalising file paths: {}", .0)]
29 StripPrefixErr(#[from] std::path::StripPrefixError),
30 #[error("Found non UTF-8 path")]
31 NotUTF8Path,
32}
33
34pub fn local_sitemap(
35 dir: PathBuf,
36 include_dotfiles: bool,
37 use_gitignore: bool,
38) -> miette::Result<Sitemap, SitemapErr> {
39 let prefix = dir.canonicalize()?;
40
41 let mut res = HashMap::new();
42 for file in WalkBuilder::new(dir)
43 .hidden(!include_dotfiles)
44 .git_ignore(use_gitignore)
45 .git_exclude(use_gitignore)
46 .git_global(use_gitignore)
47 .follow_links(true)
48 .build()
49 {
50 let file = file?;
51
52 let metadata = file.metadata()?;
53
54 if !metadata.is_file() {
55 continue;
56 };
57
58 // find the path of the files relative to the source directory
59 // source dir `./dist`:
60 // ./dist/index.html => index.html
61 // ./dist/assets/cat.jpg => cat.jpg
62 // etc
63 let key = file.path().canonicalize()?;
64 let key = key.strip_prefix(&prefix)?;
65 let key = String::from(key.to_str().ok_or(SitemapErr::NotUTF8Path)?);
66
67 let mime = mime_guess::from_path(&key);
68 let mime = mime.first().unwrap_or(mime::APPLICATION_OCTET_STREAM);
69 let mime = mime.essence_str();
70
71 res.insert(
72 key,
73 SitemapNode {
74 mime_type: String::from(mime),
75 blob: BlobRef::Local(file.path().to_owned()),
76 },
77 );
78 }
79 Ok(res)
80}