diff --git a/Cargo.lock b/Cargo.lock
index 7afd9d3..a329de2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -9,6 +9,12 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "anyhow"
+version = "1.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
+
[[package]]
name = "atty"
version = "0.2.14"
@@ -310,6 +316,20 @@ dependencies = [
"tokio-util",
]
+[[package]]
+name = "handlebars"
+version = "3.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8ae96a0e0dacf151557ccba95a7a80889f8e74a784484377739628fcdb3996"
+dependencies = [
+ "log 0.4.8",
+ "pest",
+ "pest_derive",
+ "quick-error",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "headers"
version = "0.3.2"
@@ -488,6 +508,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
[[package]]
name = "matches"
version = "0.1.8"
@@ -615,6 +641,49 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+dependencies = [
+ "maplit",
+ "pest",
+ "sha-1",
+]
+
[[package]]
name = "pfacts"
version = "0.1.0"
@@ -718,10 +787,13 @@ dependencies = [
name = "printerfacts"
version = "0.1.0"
dependencies = [
+ "anyhow",
+ "handlebars",
"log 0.4.8",
"pfacts",
"pretty_env_logger",
"rand 0.7.3",
+ "serde",
"tokio",
"warp",
]
@@ -974,6 +1046,9 @@ name = "serde"
version = "1.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
+dependencies = [
+ "serde_derive",
+]
[[package]]
name = "serde_derive"
@@ -1194,6 +1269,12 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+
[[package]]
name = "unicase"
version = "1.4.2"
diff --git a/Cargo.toml b/Cargo.toml
index d4535d4..222f01a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,9 +7,12 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+anyhow = "1"
+handlebars = "3.2.1"
log = "0"
pfacts = "0.1.0"
pretty_env_logger = "0"
rand = "0"
+serde = { version = "1", features = ["derive"] }
tokio = { version = "0.2", features = ["macros"] }
warp = "0.2"
diff --git a/default.nix b/default.nix
index c83abf5..846ba81 100644
--- a/default.nix
+++ b/default.nix
@@ -14,6 +14,7 @@ in pkgs.dockerTools.buildLayeredImage {
config = {
Cmd = [ "${printerfacts}/bin/printerfacts" ];
+ Env = [ "RUST_LOG=info" ];
WorkingDir = "/";
};
}
diff --git a/nix/sources.json b/nix/sources.json
index e8b854e..14385e5 100644
--- a/nix/sources.json
+++ b/nix/sources.json
@@ -17,6 +17,18 @@
"url": "https://github.com/justinwoo/easy-dhall-nix/archive/27edaa0c769b9c876f11c50c9ab542061d07def5.tar.gz",
"url_template": "https://github.com///archive/.tar.gz"
},
+ "gruvbox-css": {
+ "branch": "master",
+ "description": "My minimal Gruvbox CSS file I've been keeping multiple places",
+ "homepage": null,
+ "owner": "Xe",
+ "repo": "gruvbox-css",
+ "rev": "6e1841c94190a1e06e63a2596767e66c35671320",
+ "sha256": "0s7whnin63558i70wp3by3rydsdx0qdzh5553km1s29w81npmgj6",
+ "type": "tarball",
+ "url": "https://github.com/Xe/gruvbox-css/archive/6e1841c94190a1e06e63a2596767e66c35671320.tar.gz",
+ "url_template": "https://github.com///archive/.tar.gz"
+ },
"naersk": {
"branch": "master",
"description": "Build rust crates in Nix. No configuration, no code generation, no IFD. Sandbox friendly.",
diff --git a/printerfacts.nix b/printerfacts.nix
index 6d0b5ee..830d384 100644
--- a/printerfacts.nix
+++ b/printerfacts.nix
@@ -5,9 +5,22 @@ let
(path: type: type != "directory" || builtins.baseNameOf path != "target")
dir;
naersk = pkgs.callPackage sources.naersk { };
+ gruvbox-css = pkgs.callPackage sources.gruvbox-css { };
src = srcNoTarget ./.;
pfacts = naersk.buildPackage {
inherit src;
remapPathPrefix = true;
};
-in pfacts
+in pkgs.stdenv.mkDerivation {
+ inherit (pfacts) name;
+ inherit src;
+ phases = "installPhase";
+
+ installPhase = ''
+ mkdir -p $out/static
+
+ cp -rf $src/templates $out/templates
+ cp -rf ${pfacts}/bin $out/bin
+ cp -rf ${gruvbox-css}/gruvbox.css $out/static/gruvbox.css
+ '';
+}
diff --git a/src/main.rs b/src/main.rs
index 60e43fa..e835bab 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,25 +1,96 @@
-use std::convert::Infallible;
+use handlebars::Handlebars;
use pfacts::Facts;
use rand::prelude::*;
+use serde::Serialize;
+use std::{convert::Infallible, sync::Arc};
use warp::Filter;
async fn give_fact(facts: Facts) -> Result {
Ok(facts.choose(&mut thread_rng()).unwrap().clone())
}
+#[derive(Serialize)]
+struct TemplateContext {
+ title: &'static str,
+ fact: Option,
+ // This key tells handlebars which template is the parent.
+ parent: &'static str,
+}
+
+struct WithTemplate {
+ name: &'static str,
+ value: T,
+}
+
+fn render(template: WithTemplate, hbs: Arc) -> impl warp::Reply
+where
+ T: Serialize,
+{
+ let render = hbs
+ .render(template.name, &template.value)
+ .unwrap_or_else(|err| err.to_string());
+ warp::reply::html(render)
+}
+
#[tokio::main]
-async fn main() {
+async fn main() -> anyhow::Result<()> {
pretty_env_logger::init();
let facts = pfacts::make();
+ let mut hb = Handlebars::new();
- let mw = warp::any().map(move || facts.clone());
+ hb.register_template_file("layout", "./templates/layout.hbs")?;
+ hb.register_template_file("footer", "./templates/footer.hbs")?;
+ hb.register_template_file("index", "./templates/index.hbs")?;
+ hb.register_template_file("error/404", "./templates/error/404.hbs")?;
- let fact_handler = warp::any()
- .and(mw)
+ let fact = {
+ let facts = facts.clone();
+ warp::any().map(move || facts.clone())
+ };
+ let hb = Arc::new(hb);
+ let handlebars = move |with_template| render(with_template, hb.clone());
+
+ let files = warp::path("static").and(warp::fs::dir("./static"));
+
+ let fact_handler = warp::get()
+ .and(warp::path("fact"))
+ .and(fact)
.and_then(give_fact);
+ let index_handler = warp::get()
+ .and(warp::path::end())
+ .map(move || WithTemplate {
+ name: "index",
+ value: TemplateContext {
+ title: "Printer Facts",
+ fact: {
+ let ref facts = facts.clone();
+ Some(facts.choose(&mut thread_rng()).unwrap().clone())
+ },
+ parent: "layout",
+ },
+ })
+ .map(handlebars.clone());
+
+ let not_found_handler = warp::any()
+ .map(move || WithTemplate {
+ name: "error/404",
+ value: TemplateContext {
+ title: "Not Found",
+ fact: None,
+ parent: "layout",
+ },
+ })
+ .map(handlebars.clone());
+
log::info!("listening on port 5000");
- warp::serve(fact_handler)
- .run(([0, 0, 0, 0], 5000))
- .await;
+ warp::serve(
+ fact_handler
+ .or(index_handler)
+ .or(files)
+ .or(not_found_handler),
+ )
+ .run(([0, 0, 0, 0], 5000))
+ .await;
+ Ok(())
}
diff --git a/static/.gitignore b/static/.gitignore
new file mode 100644
index 0000000..bc5370d
--- /dev/null
+++ b/static/.gitignore
@@ -0,0 +1 @@
+gruvbox.css
diff --git a/templates/error/404.hbs b/templates/error/404.hbs
new file mode 100644
index 0000000..542c039
--- /dev/null
+++ b/templates/error/404.hbs
@@ -0,0 +1,6 @@
+{{#*inline "page"}}
+This page does not exist!
+
+Go home
+{{/inline}}
+{{~> (parent)~}}
diff --git a/templates/footer.hbs b/templates/footer.hbs
new file mode 100644
index 0000000..1c49f2a
--- /dev/null
+++ b/templates/footer.hbs
@@ -0,0 +1,3 @@
+
diff --git a/templates/index.hbs b/templates/index.hbs
new file mode 100644
index 0000000..2c8cd7c
--- /dev/null
+++ b/templates/index.hbs
@@ -0,0 +1,10 @@
+{{#*inline "page"}}
+
+
+
+ {{ fact }}
+
+
+
+{{/inline}}
+{{~> (parent)~}}
diff --git a/templates/layout.hbs b/templates/layout.hbs
new file mode 100644
index 0000000..46c19d7
--- /dev/null
+++ b/templates/layout.hbs
@@ -0,0 +1,17 @@
+
+
+
+ {{ title }}
+
+
+
+
+
+ {{ title }}
+
+ {{~> page}}
+
+ {{> footer }}
+
+
+