Use Ructe (#327)

All the template are now compiled at compile-time with the `ructe` crate.

I preferred to use it instead of askama because it allows more complex Rust expressions, where askama only supports a small subset of expressions and doesn't allow them everywhere (for instance, `{{ macro!() | filter }}` would result in a parsing error).

The diff is quite huge, but there is normally no changes in functionality.

Fixes #161 and unblocks #110 and #273
This commit is contained in:
Baptiste Gelez
2018-12-06 18:54:16 +01:00
committed by GitHub
parent 5f059c3e98
commit 70af57c6e1
121 changed files with 3132 additions and 3260 deletions
+28 -26
View File
@@ -3,9 +3,9 @@ use rocket::{
request::LenientForm,
response::Redirect
};
use rocket_contrib::Template;
use serde_json;
use rocket_i18n::I18n;
use validator::Validate;
use template_utils::Ructe;
use plume_common::{utils, activity_pub::{broadcast, ApRequest, ActivityStream}};
use plume_models::{
@@ -15,24 +15,24 @@ use plume_models::{
mentions::Mention,
posts::Post,
safe_string::SafeString,
tags::Tag,
users::User
};
use Worker;
#[derive(FromForm, Debug, Validate, Serialize)]
struct NewCommentForm {
#[derive(Default, FromForm, Debug, Validate, Serialize)]
pub struct NewCommentForm {
pub responding_to: Option<i32>,
#[validate(length(min = "1", message = "Your comment can't be empty"))]
pub content: String,
pub warning: String,
}
#[post("/~/<blog_name>/<slug>/comment", data = "<data>")]
fn create(blog_name: String, slug: String, data: LenientForm<NewCommentForm>, user: User, conn: DbConn, worker: Worker)
-> Result<Redirect, Option<Template>> {
#[post("/~/<blog_name>/<slug>/comment", data = "<form>")]
pub fn create(blog_name: String, slug: String, form: LenientForm<NewCommentForm>, user: User, conn: DbConn, worker: Worker, intl: I18n)
-> Result<Redirect, Option<Ructe>> {
let blog = Blog::find_by_fqn(&*conn, &blog_name).ok_or(None)?;
let post = Post::find_by_slug(&*conn, &slug, blog.id).ok_or(None)?;
let form = data.get();
form.validate()
.map(|_| {
let (html, mentions, _hashtags) = utils::md_to_html(form.content.as_ref());
@@ -62,28 +62,30 @@ fn create(blog_name: String, slug: String, data: LenientForm<NewCommentForm>, us
.map_err(|errors| {
// TODO: de-duplicate this code
let comments = Comment::list_by_post(&*conn, post.id);
let comms = comments.clone();
Some(Template::render("posts/details", json!({
"author": post.get_authors(&*conn)[0].to_json(&*conn),
"post": post,
"blog": blog,
"comments": &comments.into_iter().map(|c| c.to_json(&*conn, &comms)).collect::<Vec<serde_json::Value>>(),
"n_likes": post.get_likes(&*conn).len(),
"has_liked": user.has_liked(&*conn, &post),
"n_reshares": post.get_reshares(&*conn).len(),
"has_reshared": user.has_reshared(&*conn, &post),
"account": user.to_json(&*conn),
"date": &post.creation_date.timestamp(),
"previous": form.responding_to.and_then(|r| Comment::get(&*conn, r)).map(|r| r.to_json(&*conn, &[])),
"user_fqn": user.get_fqn(&*conn),
"comment_form": form,
"comment_errors": errors,
})))
let previous = form.responding_to.map(|r| Comment::get(&*conn, r)
.expect("posts::details_reponse: Error retrieving previous comment"));
Some(render!(posts::details(
&(&*conn, &intl.catalog, Some(user.clone())),
post.clone(),
blog,
&*form,
errors,
Tag::for_post(&*conn, post.id),
comments.into_iter().filter(|c| c.in_response_to_id.is_none()).collect::<Vec<Comment>>(),
previous,
post.get_likes(&*conn).len(),
post.get_reshares(&*conn).len(),
user.has_liked(&*conn, &post),
user.has_reshared(&*conn, &post),
user.is_following(&*conn, post.get_authors(&*conn)[0].id),
post.get_authors(&*conn)[0].clone()
)))
})
}
#[get("/~/<_blog>/<_slug>/comment/<id>")]
fn activity_pub(_blog: String, _slug: String, id: i32, _ap: ApRequest, conn: DbConn) -> Option<ActivityStream<Note>> {
pub fn activity_pub(_blog: String, _slug: String, id: i32, _ap: ApRequest, conn: DbConn) -> Option<ActivityStream<Note>> {
Comment::get(&*conn, id).map(|c| ActivityStream::new(c.to_activity(&*conn)))
}