Embed default templates into the binary
This commit is contained in:
parent
b443116e56
commit
6488f3ddb7
5 changed files with 100 additions and 12 deletions
|
|
@ -170,7 +170,7 @@ tag: update
|
|||
echo "Last tag {{ last_tag }} and manifest ({{ manifest_version }}) already match"
|
||||
if [ "{{ last_tag }}" != "{{ tagged_latest }}" ]; then
|
||||
echo "Last tag {{ last_tag }} and 'latest' tag ({{ tagged_latest }}) diverge"
|
||||
git tag latest "v{{ manifest_version }}"
|
||||
git tag --force latest "v{{ manifest_version }}"
|
||||
{{ just_cmd }} version-assess
|
||||
fi
|
||||
exit
|
||||
|
|
@ -180,7 +180,7 @@ tag: update
|
|||
fi
|
||||
|
||||
git tag "v{{ manifest_version }}" HEAD
|
||||
git tag latest "v{{ manifest_version }}"
|
||||
git tag --force latest "v{{ manifest_version }}"
|
||||
{{ just_cmd }} version-assess
|
||||
|
||||
# Verify and push
|
||||
|
|
|
|||
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -259,7 +259,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "en"
|
||||
version = "0.1.0-alpha"
|
||||
version = "0.2.0-alpha"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"serde",
|
||||
|
|
@ -1476,18 +1476,18 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
|||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.41"
|
||||
version = "0.8.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96e13bc581734df6250836c59a5f44f3c57db9f9acb9dc8e3eaabdaf6170254d"
|
||||
checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.41"
|
||||
version = "0.8.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3545ea9e86d12ab9bba9fcd99b54c1556fd3199007def5a03c375623d05fac1c"
|
||||
checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "en"
|
||||
version = "0.1.0-alpha"
|
||||
version = "0.2.0-alpha"
|
||||
description = "A non-linear writing instrument."
|
||||
license = "AGPL-3.0-only"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::{collections::HashMap, fs, io::ErrorKind, path::PathBuf};
|
||||
|
||||
use axum::{
|
||||
body::Body,
|
||||
http::{Response, StatusCode, header},
|
||||
|
|
@ -101,6 +103,77 @@ impl std::fmt::Display for RenderingError {
|
|||
}
|
||||
}
|
||||
|
||||
static DEFAULTS: &[(&str, &str)] = &[
|
||||
("base.html", include_str!("../../../templates/base.html")),
|
||||
("index.html", include_str!("../../../templates/index.html")),
|
||||
("about.html", include_str!("../../../templates/about.html")),
|
||||
("data.html", include_str!("../../../templates/data.html")),
|
||||
("empty.html", include_str!("../../../templates/empty.html")),
|
||||
("error.html", include_str!("../../../templates/error.html")),
|
||||
("node.html", include_str!("../../../templates/node.html")),
|
||||
("tree.html", include_str!("../../../templates/tree.html")),
|
||||
];
|
||||
|
||||
fn read_template(name: &str, path: PathBuf) -> Result<String, std::io::Error> {
|
||||
let defaults: HashMap<&str, &str> = DEFAULTS.iter().copied().collect();
|
||||
|
||||
match fs::read_to_string(path) {
|
||||
Ok(content) => Ok(content),
|
||||
Err(error) if error.kind() == ErrorKind::NotFound => {
|
||||
match defaults.get(name) {
|
||||
Some(default) => Ok(default.to_string()),
|
||||
None => Err(error),
|
||||
}
|
||||
},
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_templates() -> Result<tera::Tera, tera::Error> {
|
||||
let mut tera = tera::Tera::default();
|
||||
|
||||
let root = PathBuf::from("templates");
|
||||
let default_names: Vec<&str> = DEFAULTS.iter().map(|(n, _)| *n).collect();
|
||||
|
||||
match fs::read_dir(&root) {
|
||||
Ok(dir) => {
|
||||
for file_opt in dir {
|
||||
let file = file_opt?;
|
||||
let path = file.path();
|
||||
if path.is_file() {
|
||||
if let Some(name) = path.clone().file_name() {
|
||||
let Some(name_str) = name.to_str() else {
|
||||
return Err(tera::Error::msg(format!(
|
||||
"Template filename {} is not valid unicode",
|
||||
name.display()
|
||||
)))
|
||||
};
|
||||
if !default_names.contains(&name_str) {
|
||||
tera.add_raw_template(
|
||||
name_str,
|
||||
&read_template(name_str, path)?,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(error) => {
|
||||
if error.kind() != ErrorKind::NotFound {
|
||||
return Err(tera::Error::msg(error.to_string()))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
for tuple in DEFAULTS {
|
||||
let path = root.join(tuple.0);
|
||||
let name = tuple.0;
|
||||
tera.add_raw_template(name, &read_template(name, path)?)?;
|
||||
}
|
||||
|
||||
Ok(tera)
|
||||
}
|
||||
|
||||
/// Renders a template into a String and error code.
|
||||
///
|
||||
/// The template name **must not** contain the extension (e.g. `.html`).
|
||||
|
|
@ -110,7 +183,7 @@ pub(in crate::router::handlers) fn render(
|
|||
error_message: Option<String>,
|
||||
) -> Result<Rendered, RenderingError> {
|
||||
let instant = now();
|
||||
let tera = match tera::Tera::new("./templates/**/*") {
|
||||
let tera = match load_templates() {
|
||||
Ok(engine) => engine,
|
||||
Err(error) => {
|
||||
return Err(RenderingError::new(
|
||||
|
|
@ -330,7 +403,7 @@ mod tests {
|
|||
fn render_bad_context() {
|
||||
let (body, status) =
|
||||
match render("node", &tera::Context::default(), None) {
|
||||
Ok(rendered) => panic!("Got Ok, expected Error"),
|
||||
Ok(_) => panic!("Got Ok, expected Error"),
|
||||
Err(error) => (error.template.html, error.template.code),
|
||||
};
|
||||
assert!(body.matches("Template render failed.").count() > 0);
|
||||
|
|
@ -344,4 +417,18 @@ mod tests {
|
|||
let html = emergency_wrap(&error, "");
|
||||
assert!(html.matches(payload).count() == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_templates_exist_and_match() {
|
||||
let templates_dir =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("templates");
|
||||
|
||||
for (map_name, map_contents) in DEFAULTS {
|
||||
let path = templates_dir.join(map_name);
|
||||
assert!(path.exists());
|
||||
assert!(path.is_file());
|
||||
let contents = fs::read_to_string(&path).unwrap();
|
||||
assert_eq!(&contents, map_contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -856,7 +856,7 @@ text = """
|
|||
- [ ] Most linked
|
||||
- [ ] Rendering
|
||||
- [ ] Sorting of tree, index list and drop-down navigation
|
||||
- [ ] Alphabetic
|
||||
- [x] Alphabetic
|
||||
- [ ] By most linked to
|
||||
- [ ] By most linked
|
||||
- [ ] Tree
|
||||
|
|
@ -866,7 +866,8 @@ text = """
|
|||
- [ ] Custom assets (favicon, CSS)
|
||||
- [x] Drop all hardcoded assets endpoints
|
||||
- [ ] Custom header include
|
||||
- [ ] Custom templates
|
||||
- [x] Custom templates
|
||||
- [ ] user-supplied loading order (e.g. through filenames)
|
||||
- [ ] Themes
|
||||
- [x] Anchors and connections
|
||||
- [x] Render detached anchors differently
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue