{
+pub async fn file(
+ Path(path): Path,
+ State(state): State,
+) -> Response {
let instant = now();
- let content = match std::fs::read(file_path) {
+ let target = format!("static/public/{path}");
+ let content = match std::fs::read(&target) {
Ok(s) => s,
Err(e) => {
- panic!("Failed to read {file_path} contents: {e}")
+ let mut error_message = String::from(
+ "The requested file does not exist, the server does not have \
+ permission to access it or a filesystem error ocurred.",
+ );
+ if log::env_level() >= DEBUG {
+ error_message = format!(
+ "
{error_message}
\
+
Targeted path: {target}
\
+
Error message:
{e}
"
+ );
+ }
+ log!(ERROR, "{error_message}");
+ return super::error::by_code(
+ Some(404),
+ Some(&error_message),
+ &state.graph,
+ );
},
};
@@ -26,19 +46,20 @@ pub async fn file(file_path: &str, content_type: &str) -> Response {
*response.status_mut() = StatusCode::OK;
let header = header::CONTENT_TYPE;
- if let Ok(header_value) = HeaderValue::from_str(content_type) {
+ let content_type = Mime::guess(&path);
+
+ if let Ok(header_value) =
+ HeaderValue::from_str(&String::from(content_type.clone()))
+ {
response.headers_mut().append(header, header_value);
} else {
log!(
WARN,
- "Failed to create content type header value from {content_type}"
+ "Failed to create content type header value from {content_type:?}"
);
}
- tlog!(
- &instant,
- "Assembled response for {content_type} {file_path}"
- );
+ tlog!(&instant, "Assembled response for {content_type:?} {path}");
response
}
@@ -147,30 +168,4 @@ mod tests {
== "application/json"
);
}
-
- #[tokio::test]
- async fn file_valid_header() {
- let payload = "y1mgMhjeIMFsRNZ1tskP52DfWuvhvbRP";
- let response = file("./static/graph.toml", payload).await;
- assert_eq!(
- response.headers().get(header::CONTENT_TYPE).unwrap(),
- payload
- );
- }
-
- #[tokio::test]
- async fn file_invalid_header() {
- let response = file("./static/graph.toml", "\n").await;
- println!("{response:#?}");
- assert!(response.headers().get(header::CONTENT_TYPE).is_none());
- }
-
- #[tokio::test]
- #[should_panic(
- expected = "Failed to read IvnhZhdHb1xDnUw4hYDDNIERoaOojkiu \
- contents: No such file or directory (os error 2)"
- )]
- async fn file_invalid_path() {
- drop(file("IvnhZhdHb1xDnUw4hYDDNIERoaOojkiu", "text/plain").await);
- }
}
diff --git a/src/router/handlers/mime.rs b/src/router/handlers/mime.rs
new file mode 100644
index 0000000..4b82089
--- /dev/null
+++ b/src/router/handlers/mime.rs
@@ -0,0 +1,94 @@
+#[derive(Debug, Clone)]
+pub enum Mime {
+ Txt,
+ Csv,
+ Css,
+ Ttf,
+ Otf,
+ Woff,
+ Woff2,
+ Svg,
+ Ico,
+ Jpeg,
+ Png,
+ Apng,
+ Gif,
+ Webp,
+ Avif,
+ Toml,
+ Xml,
+ Json,
+ Js,
+ Pdf,
+ Epub,
+ Unknown,
+}
+
+impl From<&str> for Mime {
+ fn from(extension: &str) -> Mime {
+ match extension {
+ "txt" => Mime::Txt,
+ "csv" => Mime::Csv,
+ "css" => Mime::Css,
+ "ttf" => Mime::Ttf,
+ "otf" => Mime::Otf,
+ "woff" => Mime::Woff,
+ "woff2" => Mime::Woff2,
+ "svg" => Mime::Svg,
+ "ico" => Mime::Ico,
+ "jpeg" => Mime::Jpeg,
+ "png" => Mime::Png,
+ "apng" => Mime::Apng,
+ "gif" => Mime::Gif,
+ "webp" => Mime::Webp,
+ "avif" => Mime::Avif,
+ "toml" => Mime::Toml,
+ "xml" => Mime::Xml,
+ "json" => Mime::Json,
+ "js" => Mime::Js,
+ "pdf" => Mime::Pdf,
+ "epub" => Mime::Epub,
+ _ => Mime::Unknown,
+ }
+ }
+}
+
+impl From for String {
+ fn from(mime: Mime) -> String {
+ let s = match mime {
+ Mime::Txt => "text/plain",
+ Mime::Csv => "text/csv",
+ Mime::Css => "text/css",
+ Mime::Ttf => "font/ttf",
+ Mime::Otf => "font/otf",
+ Mime::Woff => "font/woff",
+ Mime::Woff2 => "font/woff2",
+ Mime::Svg => "image/svg+xml",
+ Mime::Ico => "image/x-icon",
+ Mime::Jpeg => "image/jpeg",
+ Mime::Png => "image/png",
+ Mime::Apng => "image/apng",
+ Mime::Gif => "image/gif",
+ Mime::Webp => "image/webp",
+ Mime::Avif => "image/avif",
+ Mime::Toml => "application/toml",
+ Mime::Xml => "application/xml",
+ Mime::Json => "application/json",
+ Mime::Js => "text/javascript",
+ Mime::Pdf => "application/pdf",
+ Mime::Epub => "application/epub+zip",
+ Mime::Unknown => "application/octet-stream",
+ };
+ String::from(s)
+ }
+}
+
+impl Mime {
+ pub fn guess(path: &str) -> Mime {
+ if let Some(pair) = path.rsplit_once('.') {
+ Mime::from(pair.1)
+ } else {
+ Mime::Unknown
+ }
+ }
+}
diff --git a/static/fonts/mono b/static/fonts/mono
deleted file mode 120000
index 274627c..0000000
--- a/static/fonts/mono
+++ /dev/null
@@ -1 +0,0 @@
-mononoki/mononoki-latin-400-normal.woff2
\ No newline at end of file
diff --git a/static/fonts/prose b/static/fonts/prose
deleted file mode 120000
index cd79e75..0000000
--- a/static/fonts/prose
+++ /dev/null
@@ -1 +0,0 @@
-reforma/Reforma1969-Blanca.woff2
\ No newline at end of file
diff --git a/static/fonts/prose-bold b/static/fonts/prose-bold
deleted file mode 120000
index 233b22c..0000000
--- a/static/fonts/prose-bold
+++ /dev/null
@@ -1 +0,0 @@
-reforma/Reforma1969-Gris.woff2
\ No newline at end of file
diff --git a/static/fonts/prose-bold-italic b/static/fonts/prose-bold-italic
deleted file mode 120000
index 383f1a9..0000000
--- a/static/fonts/prose-bold-italic
+++ /dev/null
@@ -1 +0,0 @@
-reforma/Reforma1969-GrisItalica.woff2
\ No newline at end of file
diff --git a/static/fonts/prose-italic b/static/fonts/prose-italic
deleted file mode 120000
index 59e30c7..0000000
--- a/static/fonts/prose-italic
+++ /dev/null
@@ -1 +0,0 @@
-reforma/Reforma1969-BlancaItalica.woff2
\ No newline at end of file
diff --git a/static/fonts/rawengulk/RawengulkLight.otf b/static/fonts/rawengulk/RawengulkLight.otf
deleted file mode 100644
index a187371..0000000
Binary files a/static/fonts/rawengulk/RawengulkLight.otf and /dev/null differ
diff --git a/static/fonts/sans b/static/fonts/sans
deleted file mode 120000
index a3df751..0000000
--- a/static/fonts/sans
+++ /dev/null
@@ -1 +0,0 @@
-maven/maven-pro-latin-400-normal.woff2
\ No newline at end of file
diff --git a/static/fonts/serifed b/static/fonts/serifed
deleted file mode 120000
index 4f488ec..0000000
--- a/static/fonts/serifed
+++ /dev/null
@@ -1 +0,0 @@
-cormorant/cormorant-infant-latin-300-normal.woff2
\ No newline at end of file
diff --git a/static/fonts/serifed-italic b/static/fonts/serifed-italic
deleted file mode 120000
index 719d1f3..0000000
--- a/static/fonts/serifed-italic
+++ /dev/null
@@ -1 +0,0 @@
-cormorant/cormorant-infant-latin-300-italic.woff2
\ No newline at end of file
diff --git a/static/fonts/title b/static/fonts/title
deleted file mode 120000
index 498110b..0000000
--- a/static/fonts/title
+++ /dev/null
@@ -1 +0,0 @@
-rawengulk/RawengulkLight.otf
\ No newline at end of file
diff --git a/static/graph.toml b/static/graph.toml
index 631d6c4..54b060d 100644
--- a/static/graph.toml
+++ b/static/graph.toml
@@ -589,7 +589,7 @@ text = """
- [ ] Branch deeper
- Customization
- [ ] Custom assets (favicon, CSS)
- - [ ] Drop all hardcoded assets endpoints
+ - [x] Drop all hardcoded assets endpoints
- [ ] Custom header include
- [ ] Custom templates
- [ ] Themes
diff --git a/static/favicon.svg b/static/public/assets/favicon.svg
similarity index 100%
rename from static/favicon.svg
rename to static/public/assets/favicon.svg
diff --git a/static/fonts/cormorant/LICENSE b/static/public/assets/fonts/cormorant/LICENSE
similarity index 100%
rename from static/fonts/cormorant/LICENSE
rename to static/public/assets/fonts/cormorant/LICENSE
diff --git a/static/fonts/cormorant/cormorant-infant-latin-300-italic.woff2 b/static/public/assets/fonts/cormorant/cormorant-infant-latin-300-italic.woff2
similarity index 100%
rename from static/fonts/cormorant/cormorant-infant-latin-300-italic.woff2
rename to static/public/assets/fonts/cormorant/cormorant-infant-latin-300-italic.woff2
diff --git a/static/fonts/cormorant/cormorant-infant-latin-300-normal.woff2 b/static/public/assets/fonts/cormorant/cormorant-infant-latin-300-normal.woff2
similarity index 100%
rename from static/fonts/cormorant/cormorant-infant-latin-300-normal.woff2
rename to static/public/assets/fonts/cormorant/cormorant-infant-latin-300-normal.woff2
diff --git a/static/public/assets/fonts/fonts.css b/static/public/assets/fonts/fonts.css
new file mode 100644
index 0000000..65bfaea
--- /dev/null
+++ b/static/public/assets/fonts/fonts.css
@@ -0,0 +1,65 @@
+@font-face {
+ src: url("maven/maven-pro-latin-400-normal.woff2") format("woff2");
+ font-family: "sans";
+ size-adjust: 110%;
+ display: swap;
+}
+
+@font-face {
+ src:
+ url("cormorant/cormorant-infant-latin-300-normal.woff2")
+ format("woff2");
+ font-family: "serifed";
+ display: swap;
+}
+
+@font-face {
+ src:
+ url("cormorant/cormorant-infant-latin-300-italic.woff2")
+ format("woff2");
+ font-family: "serifed";
+ font-style: italic;
+ display: swap;
+}
+
+@font-face {
+ src: url("mononoki/mononoki-latin-400-normal.woff2") format("woff2");
+ font-family: "mono";
+ display: swap;
+}
+
+@font-face {
+ src: url("rawengulk/RawengulkLight.woff2") format("woff2");
+ font-family: "title";
+ display: swap;
+}
+
+@font-face {
+ src: url("reforma/Reforma1969-Blanca.woff2") format("woff2");
+ font-family: "prose";
+ size-adjust: 120%;
+ display: swap;
+}
+
+@font-face {
+ src: url("reforma/Reforma1969-Gris.woff2") format("woff2");
+ font-family: "prose";
+ font-weight: bold;
+ display: swap;
+}
+
+@font-face {
+ src: url("reforma/Reforma1969-BlancaItalica.woff2") format("woff2");
+ src: url("prose-italic");
+ font-family: "prose";
+ font-style: italic;
+ display: swap;
+}
+
+@font-face {
+ src: url("reforma/Reforma1969-GrisItalica.woff2") format("woff2");
+ font-family: "prose";
+ font-weight: bold;
+ font-style: italic;
+ display: swap;
+}
diff --git a/static/fonts/maven/LICENSE b/static/public/assets/fonts/maven/LICENSE
similarity index 100%
rename from static/fonts/maven/LICENSE
rename to static/public/assets/fonts/maven/LICENSE
diff --git a/static/fonts/maven/maven-pro-latin-400-normal.woff2 b/static/public/assets/fonts/maven/maven-pro-latin-400-normal.woff2
similarity index 100%
rename from static/fonts/maven/maven-pro-latin-400-normal.woff2
rename to static/public/assets/fonts/maven/maven-pro-latin-400-normal.woff2
diff --git a/static/fonts/mononoki/LICENSE b/static/public/assets/fonts/mononoki/LICENSE
similarity index 100%
rename from static/fonts/mononoki/LICENSE
rename to static/public/assets/fonts/mononoki/LICENSE
diff --git a/static/fonts/mononoki/README.md b/static/public/assets/fonts/mononoki/README.md
similarity index 100%
rename from static/fonts/mononoki/README.md
rename to static/public/assets/fonts/mononoki/README.md
diff --git a/static/fonts/mononoki/mononoki-latin-400-normal.woff2 b/static/public/assets/fonts/mononoki/mononoki-latin-400-normal.woff2
similarity index 100%
rename from static/fonts/mononoki/mononoki-latin-400-normal.woff2
rename to static/public/assets/fonts/mononoki/mononoki-latin-400-normal.woff2
diff --git a/static/public/assets/fonts/rawengulk/RawengulkLight.woff2 b/static/public/assets/fonts/rawengulk/RawengulkLight.woff2
new file mode 100644
index 0000000..d866f46
Binary files /dev/null and b/static/public/assets/fonts/rawengulk/RawengulkLight.woff2 differ
diff --git a/static/fonts/rawengulk/SIL Open Font License.txt b/static/public/assets/fonts/rawengulk/SIL Open Font License.txt
similarity index 100%
rename from static/fonts/rawengulk/SIL Open Font License.txt
rename to static/public/assets/fonts/rawengulk/SIL Open Font License.txt
diff --git a/static/fonts/reforma/LICENSE.txt b/static/public/assets/fonts/reforma/LICENSE.txt
similarity index 100%
rename from static/fonts/reforma/LICENSE.txt
rename to static/public/assets/fonts/reforma/LICENSE.txt
diff --git a/static/fonts/reforma/README.txt b/static/public/assets/fonts/reforma/README.txt
similarity index 100%
rename from static/fonts/reforma/README.txt
rename to static/public/assets/fonts/reforma/README.txt
diff --git a/static/fonts/reforma/Reforma1969-Blanca.woff2 b/static/public/assets/fonts/reforma/Reforma1969-Blanca.woff2
similarity index 100%
rename from static/fonts/reforma/Reforma1969-Blanca.woff2
rename to static/public/assets/fonts/reforma/Reforma1969-Blanca.woff2
diff --git a/static/fonts/reforma/Reforma1969-BlancaItalica.woff2 b/static/public/assets/fonts/reforma/Reforma1969-BlancaItalica.woff2
similarity index 100%
rename from static/fonts/reforma/Reforma1969-BlancaItalica.woff2
rename to static/public/assets/fonts/reforma/Reforma1969-BlancaItalica.woff2
diff --git a/static/fonts/reforma/Reforma1969-Gris.woff2 b/static/public/assets/fonts/reforma/Reforma1969-Gris.woff2
similarity index 100%
rename from static/fonts/reforma/Reforma1969-Gris.woff2
rename to static/public/assets/fonts/reforma/Reforma1969-Gris.woff2
diff --git a/static/fonts/reforma/Reforma1969-GrisItalica.woff2 b/static/public/assets/fonts/reforma/Reforma1969-GrisItalica.woff2
similarity index 100%
rename from static/fonts/reforma/Reforma1969-GrisItalica.woff2
rename to static/public/assets/fonts/reforma/Reforma1969-GrisItalica.woff2
diff --git a/static/style.css b/static/public/assets/style.css
similarity index 88%
rename from static/style.css
rename to static/public/assets/style.css
index e7060f4..84d767e 100644
--- a/static/style.css
+++ b/static/public/assets/style.css
@@ -2,64 +2,6 @@
--base-font-size: 1em;
}
-@font-face {
- src: url("fonts/sans");
- font-family: "sans";
- display: swap;
- size-adjust: 110%;
-}
-
-@font-face {
- src: url("fonts/serifed");
- font-family: "serifed";
- display: swap;
-}
-
-@font-face {
- src: url("fonts/serifed-italic");
- font-family: "serifed";
- display: swap;
- font-style: italic;
-}
-
-@font-face {
- src: url("fonts/mono");
- font-family: "mono";
- display: swap;
-}
-
-@font-face {
- src: url("fonts/title");
- font-family: "title";
- display: swap;
-}
-
-@font-face {
- src: url("fonts/prose");
- font-family: "prose";
- display: swap;
- size-adjust: 120%;
-}
-
-@font-face {
- src: url("fonts/prose-bold");
- font-family: "prose";
- font-weight: bold;
-}
-
-@font-face {
- src: url("fonts/prose-italic");
- font-family: "prose";
- font-style: italic;
-}
-
-@font-face {
- src: url("fonts/prose-bold-italic");
- font-family: "prose";
- font-weight: bold;
- font-style: italic;
-}
-
html {
height: 100%;
}
@@ -366,9 +308,9 @@ em#index-node-count {
}
table {
- margin: auto;
- border-collapse: collapse;
- border: 0.5px dotted #666;
+ margin: auto;
+ border-collapse: collapse;
+ border: 0.5px dotted #666;
}
td, th {
diff --git a/templates/base.html b/templates/base.html
index 190a0bd..6e5dfc8 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -12,8 +12,9 @@
{% endif %}
-
-
+
+
+
{% block head %}
{% endblock head %}