aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Dirkjan Ochtman <dirkjan@ochtman.nl>2021-12-01 06:43:36 -0800
committerLibravatar GitHub <noreply@github.com>2021-12-01 15:43:36 +0100
commite3d690ba102f3624ff65f5476dc68dfe98f2e221 (patch)
tree873c6957e727befe1103633a3b5559451e66f743
parent671bc7f32fd150f04793d8d5dbe806e9d4cfe669 (diff)
downloadaskama-e3d690ba102f3624ff65f5476dc68dfe98f2e221.tar.gz
askama-e3d690ba102f3624ff65f5476dc68dfe98f2e221.tar.bz2
askama-e3d690ba102f3624ff65f5476dc68dfe98f2e221.zip
Move askama_mendes integration into Askama repo (#561)
-rw-r--r--.github/workflows/rust.yml13
-rw-r--r--Cargo.toml1
-rw-r--r--askama_mendes/Cargo.toml23
-rw-r--r--askama_mendes/README.md9
-rw-r--r--askama_mendes/src/lib.rs39
-rw-r--r--askama_mendes/templates/hello.txt1
-rw-r--r--askama_mendes/tests/basic.rs96
-rw-r--r--askama_shared/src/generator.rs4
8 files changed, 184 insertions, 2 deletions
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index b62ae5d..26ca174 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -113,6 +113,19 @@ jobs:
- run: cargo test --package askama_tide --all-targets
- run: cargo clippy --package askama_tide --all-targets -- -D warnings
+ Mendes:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v1
+ - uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: stable
+ override: true
+ components: clippy
+ - run: cargo test --package askama_mendes --all-targets
+ - run: cargo clippy --package askama_mendes --all-targets -- -D warnings
+
Lint:
runs-on: ubuntu-latest
steps:
diff --git a/Cargo.toml b/Cargo.toml
index fd273c7..0907742 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,6 +6,7 @@ members = [
"askama_gotham",
"askama_derive",
"askama_escape",
+ "askama_mendes",
"askama_rocket",
"askama_shared",
"askama_tide",
diff --git a/askama_mendes/Cargo.toml b/askama_mendes/Cargo.toml
new file mode 100644
index 0000000..34eeb11
--- /dev/null
+++ b/askama_mendes/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+name = "askama_mendes"
+version = "0.1.0"
+description = "Mendes integration for Askama templates"
+documentation = "https://docs.rs/askama"
+keywords = ["markup", "template", "jinja2", "html"]
+categories = ["template-engine"]
+homepage = "https://github.com/djc/askama"
+repository = "https://github.com/djc/askama"
+license = "MIT OR Apache-2.0"
+workspace = ".."
+readme = "README.md"
+edition = "2018"
+
+[dependencies]
+askama = { version = "0.11.0-beta.1", path = "../askama", default-features = false, features = ["with-mendes", "mime", "mime_guess"] }
+mendes = "0.0.59"
+mime_guess = "2.0.3"
+
+[dev-dependencies]
+async-trait = "0.1.51"
+hyper = "0.14.15"
+tokio = { version = "1.12", features = ["macros", "rt-multi-thread"] }
diff --git a/askama_mendes/README.md b/askama_mendes/README.md
new file mode 100644
index 0000000..f91ffbd
--- /dev/null
+++ b/askama_mendes/README.md
@@ -0,0 +1,9 @@
+# askama_mendes: Askama integration with Mendes
+
+[![Documentation](https://docs.rs/askama_mendes/badge.svg)](https://docs.rs/askama_mendes/)
+[![Latest version](https://img.shields.io/crates/v/askama_mendes.svg)](https://crates.io/crates/askama_mendes)
+[![Build Status](https://github.com/djc/askama/workflows/CI/badge.svg)](https://github.com/djc/askama/actions?query=workflow%3ACI)
+[![Chat](https://badges.gitter.im/gitterHQ/gitter.svg)](https://gitter.im/djc/askama)
+
+Integration of the [Askama](https://github.com/djc/askama) templating engine in
+code building on the [Mendes](https://github.com/djc/mendes) framework.
diff --git a/askama_mendes/src/lib.rs b/askama_mendes/src/lib.rs
new file mode 100644
index 0000000..8f32269
--- /dev/null
+++ b/askama_mendes/src/lib.rs
@@ -0,0 +1,39 @@
+#![deny(elided_lifetimes_in_paths)]
+
+use std::convert::TryFrom;
+
+use mendes::application::{Application, Responder};
+use mendes::http::header::{HeaderValue, CONTENT_LENGTH, CONTENT_TYPE};
+use mendes::http::request::Parts;
+use mendes::http::Response;
+use mime_guess::MimeGuess;
+
+pub use askama::*;
+
+pub fn into_response<A, T>(
+ app: &A,
+ req: &Parts,
+ t: &T,
+ ext: Option<&str>,
+) -> Response<A::ResponseBody>
+where
+ A: Application,
+ T: Template,
+ A::ResponseBody: From<String>,
+ A::Error: From<askama::Error>,
+{
+ let content = match t.render() {
+ Ok(content) => content,
+ Err(e) => return <A::Error as From<_>>::from(e).into_response(app, req),
+ };
+
+ let mut builder = Response::builder();
+ builder = builder.header(CONTENT_LENGTH, content.len());
+ if let Some(ext) = ext {
+ if let Some(ty) = MimeGuess::from_ext(ext).first() {
+ builder = builder.header(CONTENT_TYPE, HeaderValue::try_from(ty.as_ref()).unwrap());
+ }
+ }
+
+ builder.body(content.into()).unwrap()
+}
diff --git a/askama_mendes/templates/hello.txt b/askama_mendes/templates/hello.txt
new file mode 100644
index 0000000..8149be7
--- /dev/null
+++ b/askama_mendes/templates/hello.txt
@@ -0,0 +1 @@
+Hello, {{ name }}!
diff --git a/askama_mendes/tests/basic.rs b/askama_mendes/tests/basic.rs
new file mode 100644
index 0000000..2a07c13
--- /dev/null
+++ b/askama_mendes/tests/basic.rs
@@ -0,0 +1,96 @@
+use std::sync::Arc;
+
+use async_trait::async_trait;
+use hyper::body::to_bytes;
+use hyper::{Body, Request};
+use mendes::application::Responder;
+use mendes::http::request::Parts;
+use mendes::http::{Response, StatusCode};
+use mendes::{handler, route, Application, Context};
+
+use askama::Template;
+
+#[tokio::test]
+async fn test() {
+ let req = Request::builder().body(()).unwrap();
+ let rsp = App::handle(Context::new(Arc::new(App), req)).await;
+ let (rsp, body) = rsp.into_parts();
+ assert_eq!(
+ rsp.headers
+ .get("content-type")
+ .and_then(|hv| hv.to_str().ok()),
+ Some("text/plain")
+ );
+ assert_eq!(to_bytes(body).await.unwrap(), &b"Hello, world!"[..]);
+}
+
+#[handler(GET)]
+async fn hello(_: &App) -> Result<HelloTemplate<'static>, Error> {
+ Ok(HelloTemplate { name: "world" })
+}
+
+#[derive(Template)]
+#[template(path = "hello.txt")]
+struct HelloTemplate<'a> {
+ name: &'a str,
+}
+
+struct App;
+
+#[async_trait]
+impl Application for App {
+ type RequestBody = ();
+ type ResponseBody = Body;
+ type Error = Error;
+
+ async fn handle(mut cx: Context<Self>) -> Response<Body> {
+ route!(match cx.path() {
+ _ => hello,
+ })
+ }
+}
+
+#[derive(Debug)]
+enum Error {
+ Askama(askama::Error),
+ Mendes(mendes::Error),
+}
+
+impl From<askama::Error> for Error {
+ fn from(e: askama::Error) -> Error {
+ Error::Askama(e)
+ }
+}
+
+impl From<mendes::Error> for Error {
+ fn from(e: mendes::Error) -> Error {
+ Error::Mendes(e)
+ }
+}
+
+impl std::fmt::Display for Error {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Error::Askama(e) => write!(f, "{}", e),
+ Error::Mendes(e) => write!(f, "{}", e),
+ }
+ }
+}
+
+impl Responder<App> for Error {
+ fn into_response(self, _: &App, _: &Parts) -> Response<Body> {
+ Response::builder()
+ .status(StatusCode::from(&self))
+ .body(self.to_string().into())
+ .unwrap()
+ }
+}
+
+impl From<&Error> for StatusCode {
+ fn from(e: &Error) -> StatusCode {
+ match e {
+ Error::Mendes(e) => StatusCode::from(e),
+ Error::Askama(_) => StatusCode::INTERNAL_SERVER_ERROR,
+ }
+ }
+}
diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs
index cb395d4..368db9f 100644
--- a/askama_shared/src/generator.rs
+++ b/askama_shared/src/generator.rs
@@ -298,7 +298,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
.push(syn::parse_str("A::ResponseBody: From<String>").unwrap());
where_clause
.predicates
- .push(syn::parse_str("A::Error: From<::mendes::askama::Error>").unwrap());
+ .push(syn::parse_str("A::Error: From<::askama_mendes::Error>").unwrap());
buf.writeln(
format!(
@@ -317,7 +317,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> {
)?;
buf.writeln(&format!(
- "::mendes::askama::into_response(app, req, &self, {:?})",
+ "::askama_mendes::into_response(app, req, &self, {:?})",
self.input.extension()
))?;
buf.writeln("}")?;